xref: /openbmc/google-misc/dhcp-done/subprojects/libcr51sign/src/libcr51sign_support.c (revision af46bea650b072b978619acfbfd7cc1b3aead30b)
15acaca2fSWilliam A. Kennington III /*
25acaca2fSWilliam A. Kennington III  * Copyright 2021 Google LLC
35acaca2fSWilliam A. Kennington III  *
45acaca2fSWilliam A. Kennington III  * Licensed under the Apache License, Version 2.0 (the "License");
55acaca2fSWilliam A. Kennington III  * you may not use this file except in compliance with the License.
65acaca2fSWilliam A. Kennington III  * You may obtain a copy of the License at
75acaca2fSWilliam A. Kennington III  *
85acaca2fSWilliam A. Kennington III  *      http://www.apache.org/licenses/LICENSE-2.0
95acaca2fSWilliam A. Kennington III  *
105acaca2fSWilliam A. Kennington III  * Unless required by applicable law or agreed to in writing, software
115acaca2fSWilliam A. Kennington III  * distributed under the License is distributed on an "AS IS" BASIS,
125acaca2fSWilliam A. Kennington III  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135acaca2fSWilliam A. Kennington III  * See the License for the specific language governing permissions and
145acaca2fSWilliam A. Kennington III  * limitations under the License.
155acaca2fSWilliam A. Kennington III  */
165acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign_support.h>
17deb5501aSWilliam A. Kennington III #include <openssl/err.h>
185acaca2fSWilliam A. Kennington III #include <openssl/evp.h>
195acaca2fSWilliam A. Kennington III #include <openssl/pem.h>
205acaca2fSWilliam A. Kennington III #include <openssl/rsa.h>
215acaca2fSWilliam A. Kennington III #include <stdio.h>
225acaca2fSWilliam A. Kennington III #include <string.h>
235acaca2fSWilliam A. Kennington III 
245acaca2fSWilliam A. Kennington III #ifdef __cplusplus
255acaca2fSWilliam A. Kennington III extern "C"
265acaca2fSWilliam A. Kennington III {
275acaca2fSWilliam A. Kennington III #endif
285acaca2fSWilliam A. Kennington III 
29deb5501aSWilliam A. Kennington III #ifndef USER_PRINT
30deb5501aSWilliam A. Kennington III #define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
31deb5501aSWilliam A. Kennington III #endif
32deb5501aSWilliam A. Kennington III 
335acaca2fSWilliam A. Kennington III     // @func hash_init get ready to compute a hash
345acaca2fSWilliam A. Kennington III     //
355acaca2fSWilliam A. Kennington III     // @param[in] ctx - context struct
365acaca2fSWilliam A. Kennington III     // @param[in] hash_type - type of hash function to use
375acaca2fSWilliam A. Kennington III     //
385acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
395acaca2fSWilliam A. Kennington III 
405acaca2fSWilliam A. Kennington III     int hash_init(const void* ctx, enum hash_type type)
415acaca2fSWilliam A. Kennington III     {
425acaca2fSWilliam A. Kennington III         struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
435acaca2fSWilliam A. Kennington III         struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
445acaca2fSWilliam A. Kennington III         hash_context->hash_type = type;
455acaca2fSWilliam A. Kennington III         if (type == HASH_SHA2_256) // SHA256_Init returns 1
465acaca2fSWilliam A. Kennington III             SHA256_Init(&hash_context->sha256_ctx);
475acaca2fSWilliam A. Kennington III         else if (type == HASH_SHA2_512)
485acaca2fSWilliam A. Kennington III             SHA512_Init(&hash_context->sha512_ctx);
495acaca2fSWilliam A. Kennington III         else
505acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
515acaca2fSWilliam A. Kennington III 
525acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
535acaca2fSWilliam A. Kennington III     }
545acaca2fSWilliam A. Kennington III 
555acaca2fSWilliam A. Kennington III     // @func hash_update add data to the hash
565acaca2fSWilliam A. Kennington III     //
575acaca2fSWilliam A. Kennington III     // @param[in] ctx - context struct
585acaca2fSWilliam A. Kennington III     // @param[in] buf - data to add to hash
595acaca2fSWilliam A. Kennington III     // @param[in] count - number of bytes of data to add
605acaca2fSWilliam A. Kennington III     //
615acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
625acaca2fSWilliam A. Kennington III 
635acaca2fSWilliam A. Kennington III     int hash_update(void* ctx, const uint8_t* data, size_t size)
645acaca2fSWilliam A. Kennington III     {
655acaca2fSWilliam A. Kennington III         if (size == 0)
665acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_SUCCESS;
675acaca2fSWilliam A. Kennington III         struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
685acaca2fSWilliam A. Kennington III         struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
695acaca2fSWilliam A. Kennington III 
705acaca2fSWilliam A. Kennington III         if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
715acaca2fSWilliam A. Kennington III             SHA256_Update(&hash_context->sha256_ctx, data, size);
725acaca2fSWilliam A. Kennington III         else if (hash_context->hash_type == HASH_SHA2_512)
735acaca2fSWilliam A. Kennington III             SHA512_Update(&hash_context->sha512_ctx, data, size);
745acaca2fSWilliam A. Kennington III         else
755acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
765acaca2fSWilliam A. Kennington III 
775acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
785acaca2fSWilliam A. Kennington III     }
795acaca2fSWilliam A. Kennington III 
805acaca2fSWilliam A. Kennington III     // @func hash_final finish hash calculation
815acaca2fSWilliam A. Kennington III     //
825acaca2fSWilliam A. Kennington III     // @param[in] ctx - context struct
835acaca2fSWilliam A. Kennington III     // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
845acaca2fSWilliam A. Kennington III     //
855acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
865acaca2fSWilliam A. Kennington III 
875acaca2fSWilliam A. Kennington III     int hash_final(void* ctx, uint8_t* hash)
885acaca2fSWilliam A. Kennington III     {
895acaca2fSWilliam A. Kennington III         int rv;
905acaca2fSWilliam A. Kennington III         struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
915acaca2fSWilliam A. Kennington III         struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
925acaca2fSWilliam A. Kennington III 
935acaca2fSWilliam A. Kennington III         if (hash_context->hash_type == HASH_SHA2_256)
945acaca2fSWilliam A. Kennington III             rv = SHA256_Final(hash, &hash_context->sha256_ctx);
955acaca2fSWilliam A. Kennington III         else if (hash_context->hash_type == HASH_SHA2_512)
965acaca2fSWilliam A. Kennington III             rv = SHA512_Final(hash, &hash_context->sha512_ctx);
975acaca2fSWilliam A. Kennington III         else
985acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
995acaca2fSWilliam A. Kennington III 
1005acaca2fSWilliam A. Kennington III         if (rv)
1015acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_SUCCESS;
1025acaca2fSWilliam A. Kennington III         else
1035acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
1045acaca2fSWilliam A. Kennington III     }
1055acaca2fSWilliam A. Kennington III 
1065acaca2fSWilliam A. Kennington III     // @func verify check that the signature is valid for given hashed data
1075acaca2fSWilliam A. Kennington III     //
1085acaca2fSWilliam A. Kennington III     // @param[in] ctx - context struct
1095acaca2fSWilliam A. Kennington III     // @param[in] scheme - type of signature, hash, etc.
1105acaca2fSWilliam A. Kennington III     // @param[in] sig - signature blob
1115acaca2fSWilliam A. Kennington III     // @param[in] sig_len - length of signature in bytes
1125acaca2fSWilliam A. Kennington III     // @param[in] data - pre-hashed data to verify
1135acaca2fSWilliam A. Kennington III     // @param[in] data_len - length of hashed data in bytes
1145acaca2fSWilliam A. Kennington III     //
1155acaca2fSWilliam A. Kennington III     // verify_signature expects RSA public key file path in ctx->key_ring
1165acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
1175acaca2fSWilliam A. Kennington III 
1185acaca2fSWilliam A. Kennington III     int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
1195acaca2fSWilliam A. Kennington III                          const uint8_t* sig, size_t sig_len,
1205acaca2fSWilliam A. Kennington III                          const uint8_t* data, size_t data_len)
1215acaca2fSWilliam A. Kennington III     {
1225acaca2fSWilliam A. Kennington III         // By default returns error.
1235acaca2fSWilliam A. Kennington III         int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
1245acaca2fSWilliam A. Kennington III 
125*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
126deb5501aSWilliam A. Kennington III         for (size_t i = 0; i < sig_len; i++)
1275acaca2fSWilliam A. Kennington III         {
128deb5501aSWilliam A. Kennington III             CPRINTS(ctx, "%x", sig[i]);
1295acaca2fSWilliam A. Kennington III         }
130*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "\n");
1315acaca2fSWilliam A. Kennington III 
1325acaca2fSWilliam A. Kennington III         struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
1335acaca2fSWilliam A. Kennington III         FILE* fp = fopen(lctx->keyring, "r");
1345acaca2fSWilliam A. Kennington III         RSA *rsa = NULL, *pub_rsa = NULL;
1355acaca2fSWilliam A. Kennington III         EVP_PKEY* pkey = NULL;
1365acaca2fSWilliam A. Kennington III         BIO* bio = BIO_new(BIO_s_mem());
1375acaca2fSWilliam A. Kennington III         if (!fp)
1385acaca2fSWilliam A. Kennington III         {
139*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "fopen failed\n");
1405acaca2fSWilliam A. Kennington III             goto clean_up;
1415acaca2fSWilliam A. Kennington III         }
1425acaca2fSWilliam A. Kennington III 
1435acaca2fSWilliam A. Kennington III         pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
1445acaca2fSWilliam A. Kennington III         if (!pkey)
1455acaca2fSWilliam A. Kennington III         {
146*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "Read public key failed\n");
1475acaca2fSWilliam A. Kennington III             goto clean_up;
1485acaca2fSWilliam A. Kennington III         }
1495acaca2fSWilliam A. Kennington III 
1505acaca2fSWilliam A. Kennington III         rsa = EVP_PKEY_get1_RSA(pkey);
1515acaca2fSWilliam A. Kennington III         if (!rsa)
1525acaca2fSWilliam A. Kennington III         {
1535acaca2fSWilliam A. Kennington III             goto clean_up;
1545acaca2fSWilliam A. Kennington III         }
1555acaca2fSWilliam A. Kennington III         pub_rsa = RSAPublicKey_dup(rsa);
1565acaca2fSWilliam A. Kennington III         if (!RSA_print(bio, pub_rsa, 2))
1575acaca2fSWilliam A. Kennington III         {
158*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "RSA print failed\n");
1595acaca2fSWilliam A. Kennington III         }
1605acaca2fSWilliam A. Kennington III         if (!pub_rsa)
1615acaca2fSWilliam A. Kennington III         {
162*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "no pub RSA\n");
1635acaca2fSWilliam A. Kennington III             goto clean_up;
1645acaca2fSWilliam A. Kennington III         }
165*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "public RSA\n");
1665acaca2fSWilliam A. Kennington III         char buffer[1024];
1675acaca2fSWilliam A. Kennington III         while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
1685acaca2fSWilliam A. Kennington III         {
169deb5501aSWilliam A. Kennington III             CPRINTS(ctx, " %s", buffer);
1705acaca2fSWilliam A. Kennington III         }
1715acaca2fSWilliam A. Kennington III         enum hash_type hash_type;
1725acaca2fSWilliam A. Kennington III         rv = get_hash_type_from_signature(sig_scheme, &hash_type);
1735acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
1745acaca2fSWilliam A. Kennington III         {
175*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "Invalid hash_type!\n");
1765acaca2fSWilliam A. Kennington III             goto clean_up;
1775acaca2fSWilliam A. Kennington III         }
1785acaca2fSWilliam A. Kennington III         int hash_nid = -1;
1795acaca2fSWilliam A. Kennington III         if (hash_type == HASH_SHA2_256)
1805acaca2fSWilliam A. Kennington III         {
1815acaca2fSWilliam A. Kennington III             hash_nid = NID_sha256;
1825acaca2fSWilliam A. Kennington III         }
1835acaca2fSWilliam A. Kennington III         else if (hash_type == HASH_SHA2_512)
1845acaca2fSWilliam A. Kennington III         {
1855acaca2fSWilliam A. Kennington III             hash_nid = NID_sha512;
1865acaca2fSWilliam A. Kennington III         }
1875acaca2fSWilliam A. Kennington III         else
1885acaca2fSWilliam A. Kennington III         {
1895acaca2fSWilliam A. Kennington III             rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1905acaca2fSWilliam A. Kennington III             goto clean_up;
1915acaca2fSWilliam A. Kennington III         }
1925acaca2fSWilliam A. Kennington III 
1935acaca2fSWilliam A. Kennington III         int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
1945acaca2fSWilliam A. Kennington III         // OpenSSL RSA_verify returns 1 on success and 0 on failure
1955acaca2fSWilliam A. Kennington III         if (!ret)
1965acaca2fSWilliam A. Kennington III         {
197*af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
1985acaca2fSWilliam A. Kennington III                     ERR_error_string(ERR_get_error(), NULL));
1995acaca2fSWilliam A. Kennington III             rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2005acaca2fSWilliam A. Kennington III             goto clean_up;
2015acaca2fSWilliam A. Kennington III         }
2025acaca2fSWilliam A. Kennington III         rv = LIBCR51SIGN_SUCCESS;
203*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "sig: ");
204deb5501aSWilliam A. Kennington III         for (size_t i = 0; i < sig_len; i++)
2055acaca2fSWilliam A. Kennington III         {
206deb5501aSWilliam A. Kennington III             CPRINTS(ctx, "%x", sig[i]);
2075acaca2fSWilliam A. Kennington III         }
208*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "\n");
2095acaca2fSWilliam A. Kennington III 
210*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "data: ");
211deb5501aSWilliam A. Kennington III         for (size_t i = 0; i < data_len; i++)
2125acaca2fSWilliam A. Kennington III         {
213deb5501aSWilliam A. Kennington III             CPRINTS(ctx, "%x", data[i]);
2145acaca2fSWilliam A. Kennington III         }
215*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "\n");
216*af46bea6SWilliam A. Kennington III 
2175acaca2fSWilliam A. Kennington III         const unsigned rsa_size = RSA_size(pub_rsa);
218*af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
2195acaca2fSWilliam A. Kennington III 
2205acaca2fSWilliam A. Kennington III     clean_up:
2215acaca2fSWilliam A. Kennington III         if (fp)
2225acaca2fSWilliam A. Kennington III         {
2235acaca2fSWilliam A. Kennington III             fclose(fp);
2245acaca2fSWilliam A. Kennington III         }
2255acaca2fSWilliam A. Kennington III         EVP_PKEY_free(pkey);
2265acaca2fSWilliam A. Kennington III         RSA_free(rsa);
2275acaca2fSWilliam A. Kennington III         RSA_free(pub_rsa);
2285acaca2fSWilliam A. Kennington III         BIO_free(bio);
2295acaca2fSWilliam A. Kennington III         return rv;
2305acaca2fSWilliam A. Kennington III     }
2315acaca2fSWilliam A. Kennington III 
2325acaca2fSWilliam A. Kennington III #ifdef __cplusplus
2335acaca2fSWilliam A. Kennington III } //  extern "C"
2345acaca2fSWilliam A. Kennington III #endif
235