xref: /openbmc/google-misc/ncsid/subprojects/libcr51sign/src/libcr51sign_support.c (revision 027c042e5847fd0e8bc9ab68b62d7a4f0d5efa47)
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  */
16adb8ffe4SWilly Tu 
175acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign_support.h>
18*027c042eSDan Zhang #include <openssl/bio.h>
19*027c042eSDan Zhang #include <openssl/bn.h>
20deb5501aSWilliam A. Kennington III #include <openssl/err.h>
215acaca2fSWilliam A. Kennington III #include <openssl/evp.h>
225acaca2fSWilliam A. Kennington III #include <openssl/pem.h>
235acaca2fSWilliam A. Kennington III #include <openssl/rsa.h>
24*027c042eSDan Zhang #include <openssl/sha.h>
25*027c042eSDan Zhang #include <stdint.h>
265acaca2fSWilliam A. Kennington III #include <stdio.h>
27dca92e47SWilly Tu #include <string.h>
285acaca2fSWilliam A. Kennington III 
295acaca2fSWilliam A. Kennington III #ifdef __cplusplus
305acaca2fSWilliam A. Kennington III extern "C"
315acaca2fSWilliam A. Kennington III {
325acaca2fSWilliam A. Kennington III #endif
335acaca2fSWilliam A. Kennington III 
34deb5501aSWilliam A. Kennington III #ifndef USER_PRINT
35deb5501aSWilliam A. Kennington III #define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
36deb5501aSWilliam A. Kennington III #endif
37deb5501aSWilliam A. Kennington III 
385acaca2fSWilliam A. Kennington III // @func hash_init get ready to compute a hash
395acaca2fSWilliam A. Kennington III //
405acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct
415acaca2fSWilliam A. Kennington III // @param[in] hash_type - type of hash function to use
425acaca2fSWilliam A. Kennington III //
435acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success
445acaca2fSWilliam A. Kennington III 
455acaca2fSWilliam A. Kennington III int hash_init(const void* ctx, enum hash_type type)
465acaca2fSWilliam A. Kennington III {
475acaca2fSWilliam A. Kennington III     struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
485acaca2fSWilliam A. Kennington III     struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
495acaca2fSWilliam A. Kennington III     hash_context->hash_type = type;
50*027c042eSDan Zhang     if (type == HASH_SHA2_256)
51*027c042eSDan Zhang     { // SHA256_Init returns 1
525acaca2fSWilliam A. Kennington III         SHA256_Init(&hash_context->sha256_ctx);
53*027c042eSDan Zhang     }
545acaca2fSWilliam A. Kennington III     else if (type == HASH_SHA2_512)
55*027c042eSDan Zhang     {
565acaca2fSWilliam A. Kennington III         SHA512_Init(&hash_context->sha512_ctx);
57*027c042eSDan Zhang     }
585acaca2fSWilliam A. Kennington III     else
59*027c042eSDan Zhang     {
605acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
61*027c042eSDan Zhang     }
625acaca2fSWilliam A. Kennington III 
635acaca2fSWilliam A. Kennington III     return LIBCR51SIGN_SUCCESS;
645acaca2fSWilliam A. Kennington III }
655acaca2fSWilliam A. Kennington III 
665acaca2fSWilliam A. Kennington III // @func hash_update add data to the hash
675acaca2fSWilliam A. Kennington III //
685acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct
695acaca2fSWilliam A. Kennington III // @param[in] buf - data to add to hash
705acaca2fSWilliam A. Kennington III // @param[in] count - number of bytes of data to add
715acaca2fSWilliam A. Kennington III //
725acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success
735acaca2fSWilliam A. Kennington III 
745acaca2fSWilliam A. Kennington III int hash_update(void* ctx, const uint8_t* data, size_t size)
755acaca2fSWilliam A. Kennington III {
765acaca2fSWilliam A. Kennington III     if (size == 0)
775acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
785acaca2fSWilliam A. Kennington III     struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
795acaca2fSWilliam A. Kennington III     struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
805acaca2fSWilliam A. Kennington III 
81*027c042eSDan Zhang     if (hash_context->hash_type == HASH_SHA2_256)
82*027c042eSDan Zhang     { // SHA256_Update returns 1
835acaca2fSWilliam A. Kennington III         SHA256_Update(&hash_context->sha256_ctx, data, size);
84*027c042eSDan Zhang     }
855acaca2fSWilliam A. Kennington III     else if (hash_context->hash_type == HASH_SHA2_512)
86*027c042eSDan Zhang     {
875acaca2fSWilliam A. Kennington III         SHA512_Update(&hash_context->sha512_ctx, data, size);
88*027c042eSDan Zhang     }
895acaca2fSWilliam A. Kennington III     else
90*027c042eSDan Zhang     {
915acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
92*027c042eSDan Zhang     }
935acaca2fSWilliam A. Kennington III 
945acaca2fSWilliam A. Kennington III     return LIBCR51SIGN_SUCCESS;
955acaca2fSWilliam A. Kennington III }
965acaca2fSWilliam A. Kennington III 
975acaca2fSWilliam A. Kennington III // @func hash_final finish hash calculation
985acaca2fSWilliam A. Kennington III //
995acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct
1005acaca2fSWilliam A. Kennington III // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
1015acaca2fSWilliam A. Kennington III //
1025acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success
1035acaca2fSWilliam A. Kennington III 
1045acaca2fSWilliam A. Kennington III int hash_final(void* ctx, uint8_t* hash)
1055acaca2fSWilliam A. Kennington III {
1065acaca2fSWilliam A. Kennington III     int rv;
1075acaca2fSWilliam A. Kennington III     struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
1085acaca2fSWilliam A. Kennington III     struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
1095acaca2fSWilliam A. Kennington III 
1105acaca2fSWilliam A. Kennington III     if (hash_context->hash_type == HASH_SHA2_256)
111*027c042eSDan Zhang     {
1125acaca2fSWilliam A. Kennington III         rv = SHA256_Final(hash, &hash_context->sha256_ctx);
113*027c042eSDan Zhang     }
1145acaca2fSWilliam A. Kennington III     else if (hash_context->hash_type == HASH_SHA2_512)
115*027c042eSDan Zhang     {
1165acaca2fSWilliam A. Kennington III         rv = SHA512_Final(hash, &hash_context->sha512_ctx);
117*027c042eSDan Zhang     }
1185acaca2fSWilliam A. Kennington III     else
119*027c042eSDan Zhang     {
1205acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
121*027c042eSDan Zhang     }
1225acaca2fSWilliam A. Kennington III 
1235acaca2fSWilliam A. Kennington III     if (rv)
124*027c042eSDan Zhang     {
1255acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
126*027c042eSDan Zhang     }
127*027c042eSDan Zhang 
1285acaca2fSWilliam A. Kennington III     return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
1295acaca2fSWilliam A. Kennington III }
1305acaca2fSWilliam A. Kennington III 
1315acaca2fSWilliam A. Kennington III // @func verify check that the signature is valid for given hashed data
1325acaca2fSWilliam A. Kennington III //
1335acaca2fSWilliam A. Kennington III // @param[in] ctx - context struct
1345acaca2fSWilliam A. Kennington III // @param[in] scheme - type of signature, hash, etc.
1355acaca2fSWilliam A. Kennington III // @param[in] sig - signature blob
1365acaca2fSWilliam A. Kennington III // @param[in] sig_len - length of signature in bytes
1375acaca2fSWilliam A. Kennington III // @param[in] data - pre-hashed data to verify
1385acaca2fSWilliam A. Kennington III // @param[in] data_len - length of hashed data in bytes
1395acaca2fSWilliam A. Kennington III //
1405acaca2fSWilliam A. Kennington III // verify_signature expects RSA public key file path in ctx->key_ring
1415acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success
1425acaca2fSWilliam A. Kennington III 
1435acaca2fSWilliam A. Kennington III int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
1446084957fSPatrick Williams                      const uint8_t* sig, size_t sig_len, const uint8_t* data,
1456084957fSPatrick Williams                      size_t data_len)
1465acaca2fSWilliam A. Kennington III {
1475acaca2fSWilliam A. Kennington III     // By default returns error.
1485acaca2fSWilliam A. Kennington III     int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
1495acaca2fSWilliam A. Kennington III 
150af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
151deb5501aSWilliam A. Kennington III     for (size_t i = 0; i < sig_len; i++)
1525acaca2fSWilliam A. Kennington III     {
153deb5501aSWilliam A. Kennington III         CPRINTS(ctx, "%x", sig[i]);
1545acaca2fSWilliam A. Kennington III     }
155af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "\n");
1565acaca2fSWilliam A. Kennington III 
1575acaca2fSWilliam A. Kennington III     struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
1585acaca2fSWilliam A. Kennington III     FILE* fp = fopen(lctx->keyring, "r");
1595acaca2fSWilliam A. Kennington III     RSA *rsa = NULL, *pub_rsa = NULL;
1605acaca2fSWilliam A. Kennington III     EVP_PKEY* pkey = NULL;
1615acaca2fSWilliam A. Kennington III     BIO* bio = BIO_new(BIO_s_mem());
1625acaca2fSWilliam A. Kennington III     if (!fp)
1635acaca2fSWilliam A. Kennington III     {
164af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "fopen failed\n");
1655acaca2fSWilliam A. Kennington III         goto clean_up;
1665acaca2fSWilliam A. Kennington III     }
1675acaca2fSWilliam A. Kennington III 
1685acaca2fSWilliam A. Kennington III     pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
1695acaca2fSWilliam A. Kennington III     if (!pkey)
1705acaca2fSWilliam A. Kennington III     {
171af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "Read public key failed\n");
1725acaca2fSWilliam A. Kennington III         goto clean_up;
1735acaca2fSWilliam A. Kennington III     }
1745acaca2fSWilliam A. Kennington III 
1755acaca2fSWilliam A. Kennington III     rsa = EVP_PKEY_get1_RSA(pkey);
1765acaca2fSWilliam A. Kennington III     if (!rsa)
1775acaca2fSWilliam A. Kennington III     {
1785acaca2fSWilliam A. Kennington III         goto clean_up;
1795acaca2fSWilliam A. Kennington III     }
1805acaca2fSWilliam A. Kennington III     pub_rsa = RSAPublicKey_dup(rsa);
1815acaca2fSWilliam A. Kennington III     if (!RSA_print(bio, pub_rsa, 2))
1825acaca2fSWilliam A. Kennington III     {
183af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "RSA print failed\n");
1845acaca2fSWilliam A. Kennington III     }
1855acaca2fSWilliam A. Kennington III     if (!pub_rsa)
1865acaca2fSWilliam A. Kennington III     {
187af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "no pub RSA\n");
1885acaca2fSWilliam A. Kennington III         goto clean_up;
1895acaca2fSWilliam A. Kennington III     }
190af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "public RSA\n");
191dca92e47SWilly Tu     char buffer[1024] = {};
1925acaca2fSWilliam A. Kennington III     while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
1935acaca2fSWilliam A. Kennington III     {
194deb5501aSWilliam A. Kennington III         CPRINTS(ctx, " %s", buffer);
1955acaca2fSWilliam A. Kennington III     }
1965acaca2fSWilliam A. Kennington III     enum hash_type hash_type;
1975acaca2fSWilliam A. Kennington III     rv = get_hash_type_from_signature(sig_scheme, &hash_type);
1985acaca2fSWilliam A. Kennington III     if (rv != LIBCR51SIGN_SUCCESS)
1995acaca2fSWilliam A. Kennington III     {
200af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "Invalid hash_type!\n");
2015acaca2fSWilliam A. Kennington III         goto clean_up;
2025acaca2fSWilliam A. Kennington III     }
2035acaca2fSWilliam A. Kennington III     int hash_nid = -1;
2045acaca2fSWilliam A. Kennington III     if (hash_type == HASH_SHA2_256)
2055acaca2fSWilliam A. Kennington III     {
2065acaca2fSWilliam A. Kennington III         hash_nid = NID_sha256;
2075acaca2fSWilliam A. Kennington III     }
2085acaca2fSWilliam A. Kennington III     else if (hash_type == HASH_SHA2_512)
2095acaca2fSWilliam A. Kennington III     {
2105acaca2fSWilliam A. Kennington III         hash_nid = NID_sha512;
2115acaca2fSWilliam A. Kennington III     }
2125acaca2fSWilliam A. Kennington III     else
2135acaca2fSWilliam A. Kennington III     {
2145acaca2fSWilliam A. Kennington III         rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
2155acaca2fSWilliam A. Kennington III         goto clean_up;
2165acaca2fSWilliam A. Kennington III     }
2175acaca2fSWilliam A. Kennington III 
2185acaca2fSWilliam A. Kennington III     int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
2195acaca2fSWilliam A. Kennington III     // OpenSSL RSA_verify returns 1 on success and 0 on failure
2205acaca2fSWilliam A. Kennington III     if (!ret)
2215acaca2fSWilliam A. Kennington III     {
222af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
2235acaca2fSWilliam A. Kennington III                 ERR_error_string(ERR_get_error(), NULL));
2245acaca2fSWilliam A. Kennington III         rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2255acaca2fSWilliam A. Kennington III         goto clean_up;
2265acaca2fSWilliam A. Kennington III     }
2275acaca2fSWilliam A. Kennington III     rv = LIBCR51SIGN_SUCCESS;
228af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "sig: ");
229deb5501aSWilliam A. Kennington III     for (size_t i = 0; i < sig_len; i++)
2305acaca2fSWilliam A. Kennington III     {
231deb5501aSWilliam A. Kennington III         CPRINTS(ctx, "%x", sig[i]);
2325acaca2fSWilliam A. Kennington III     }
233af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "\n");
2345acaca2fSWilliam A. Kennington III 
235af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "data: ");
236deb5501aSWilliam A. Kennington III     for (size_t i = 0; i < data_len; i++)
2375acaca2fSWilliam A. Kennington III     {
238deb5501aSWilliam A. Kennington III         CPRINTS(ctx, "%x", data[i]);
2395acaca2fSWilliam A. Kennington III     }
240af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "\n");
241af46bea6SWilliam A. Kennington III 
2425acaca2fSWilliam A. Kennington III     const unsigned rsa_size = RSA_size(pub_rsa);
243af46bea6SWilliam A. Kennington III     CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
2445acaca2fSWilliam A. Kennington III 
2455acaca2fSWilliam A. Kennington III clean_up:
2465acaca2fSWilliam A. Kennington III     if (fp)
2475acaca2fSWilliam A. Kennington III     {
2485acaca2fSWilliam A. Kennington III         fclose(fp);
2495acaca2fSWilliam A. Kennington III     }
2505acaca2fSWilliam A. Kennington III     EVP_PKEY_free(pkey);
2515acaca2fSWilliam A. Kennington III     RSA_free(rsa);
2525acaca2fSWilliam A. Kennington III     RSA_free(pub_rsa);
2535acaca2fSWilliam A. Kennington III     BIO_free(bio);
2545acaca2fSWilliam A. Kennington III     return rv;
2555acaca2fSWilliam A. Kennington III }
2565acaca2fSWilliam A. Kennington III 
257*027c042eSDan Zhang // @func Verify RSA signature with modulus and exponent
258*027c042eSDan Zhang // @param[in]  ctx - context struct
259*027c042eSDan Zhang // @param[in]  sig_scheme - signature scheme
260*027c042eSDan Zhang // @param[in]  modulus - modulus of the RSA key, MSB (big-endian)
261*027c042eSDan Zhang // @param[in]  modulus_len - length of modulus in bytes
262*027c042eSDan Zhang // @param[in]  exponent - exponent of the RSA key
263*027c042eSDan Zhang // @param[in]  sig - signature blob
264*027c042eSDan Zhang // @param[in]  sig_len - length of signature in bytes
265*027c042eSDan Zhang // @param[in]  digest - digest to verify
266*027c042eSDan Zhang // @param[in]  digest_len - digest size
267*027c042eSDan Zhang //
268*027c042eSDan Zhang // @return true: if the signature is verified
269*027c042eSDan Zhang //         false: otherwise
270*027c042eSDan Zhang __attribute__((nonnull)) bool verify_rsa_signature_with_modulus_and_exponent(
271*027c042eSDan Zhang     const void* ctx, enum signature_scheme sig_scheme, const uint8_t* modulus,
272*027c042eSDan Zhang     int modulus_len, uint32_t exponent, const uint8_t* sig, int sig_len,
273*027c042eSDan Zhang     const uint8_t* digest, int digest_len)
274*027c042eSDan Zhang {
275*027c042eSDan Zhang     RSA* rsa = NULL;
276*027c042eSDan Zhang     BIGNUM* n = NULL;
277*027c042eSDan Zhang     BIGNUM* e = NULL;
278*027c042eSDan Zhang     int ret = 0;
279*027c042eSDan Zhang     int hash_nid = NID_undef;
280*027c042eSDan Zhang     int expected_modulus_bits = 0;
281*027c042eSDan Zhang     int expected_digest_len = 0;
282*027c042eSDan Zhang 
283*027c042eSDan Zhang     CPRINTS(ctx, "%s: sig_scheme = %d\n", __FUNCTION__, sig_scheme);
284*027c042eSDan Zhang     // Determine hash NID and expected modulus size based on signature_scheme
285*027c042eSDan Zhang     switch (sig_scheme)
286*027c042eSDan Zhang     {
287*027c042eSDan Zhang         case SIGNATURE_RSA2048_PKCS15:
288*027c042eSDan Zhang             expected_modulus_bits = 2048;
289*027c042eSDan Zhang             hash_nid = NID_sha256;
290*027c042eSDan Zhang             expected_digest_len = SHA256_DIGEST_LENGTH;
291*027c042eSDan Zhang             break;
292*027c042eSDan Zhang         case SIGNATURE_RSA3072_PKCS15:
293*027c042eSDan Zhang             expected_modulus_bits = 3072;
294*027c042eSDan Zhang             hash_nid = NID_sha256;
295*027c042eSDan Zhang             expected_digest_len = SHA256_DIGEST_LENGTH;
296*027c042eSDan Zhang             break;
297*027c042eSDan Zhang         case SIGNATURE_RSA4096_PKCS15:
298*027c042eSDan Zhang             expected_modulus_bits = 4096;
299*027c042eSDan Zhang             hash_nid = NID_sha256;
300*027c042eSDan Zhang             expected_digest_len = SHA256_DIGEST_LENGTH;
301*027c042eSDan Zhang             break;
302*027c042eSDan Zhang         case SIGNATURE_RSA4096_PKCS15_SHA512:
303*027c042eSDan Zhang             expected_modulus_bits = 4096;
304*027c042eSDan Zhang             hash_nid = NID_sha512;
305*027c042eSDan Zhang             expected_digest_len = SHA512_DIGEST_LENGTH;
306*027c042eSDan Zhang             break;
307*027c042eSDan Zhang         default:
308*027c042eSDan Zhang             CPRINTS(ctx, "%s: Unsupported signature scheme.\n", __FUNCTION__);
309*027c042eSDan Zhang             return false;
310*027c042eSDan Zhang     }
311*027c042eSDan Zhang 
312*027c042eSDan Zhang     // Input validation: Check digest length
313*027c042eSDan Zhang     if (digest_len != expected_digest_len)
314*027c042eSDan Zhang     {
315*027c042eSDan Zhang         CPRINTS(
316*027c042eSDan Zhang             ctx,
317*027c042eSDan Zhang             "%s: Mismatch in expected digest length (%d) and actual (%d).\n",
318*027c042eSDan Zhang             __FUNCTION__, expected_digest_len, digest_len);
319*027c042eSDan Zhang         return false;
320*027c042eSDan Zhang     }
321*027c042eSDan Zhang 
322*027c042eSDan Zhang     // 1. Create a new RSA object
323*027c042eSDan Zhang     rsa = RSA_new();
324*027c042eSDan Zhang     if (rsa == NULL)
325*027c042eSDan Zhang     {
326*027c042eSDan Zhang         CPRINTS(ctx, "%s:Error creating RSA object: %s\n", __FUNCTION__,
327*027c042eSDan Zhang                 ERR_error_string(ERR_get_error(), NULL));
328*027c042eSDan Zhang         goto err;
329*027c042eSDan Zhang     }
330*027c042eSDan Zhang 
331*027c042eSDan Zhang     // 2. Convert raw modulus and exponent to BIGNUMs
332*027c042eSDan Zhang     n = BN_bin2bn(modulus, modulus_len, NULL);
333*027c042eSDan Zhang     if (n == NULL)
334*027c042eSDan Zhang     {
335*027c042eSDan Zhang         CPRINTS(ctx, "%s:Error converting modulus to BIGNUM: %s\n",
336*027c042eSDan Zhang                 __FUNCTION__, ERR_error_string(ERR_get_error(), NULL));
337*027c042eSDan Zhang         goto err;
338*027c042eSDan Zhang     }
339*027c042eSDan Zhang 
340*027c042eSDan Zhang     e = BN_new();
341*027c042eSDan Zhang     if (e == NULL)
342*027c042eSDan Zhang     {
343*027c042eSDan Zhang         CPRINTS(ctx, "%s: Error creating BIGNUM for exponent: %s\n",
344*027c042eSDan Zhang                 __FUNCTION__, ERR_error_string(ERR_get_error(), NULL));
345*027c042eSDan Zhang         goto err;
346*027c042eSDan Zhang     }
347*027c042eSDan Zhang     if (!BN_set_word(e, exponent))
348*027c042eSDan Zhang     {
349*027c042eSDan Zhang         CPRINTS(ctx, "%s: Error setting exponent word: %s\n", __FUNCTION__,
350*027c042eSDan Zhang                 ERR_error_string(ERR_get_error(), NULL));
351*027c042eSDan Zhang         goto err;
352*027c042eSDan Zhang     }
353*027c042eSDan Zhang 
354*027c042eSDan Zhang     // Set the public key components. RSA_set0_key takes ownership of n and e.
355*027c042eSDan Zhang     if (!RSA_set0_key(rsa, n, e, NULL))
356*027c042eSDan Zhang     { // For public key, d is NULL
357*027c042eSDan Zhang         CPRINTS(ctx, "%s: Error setting RSA key components: %s\n", __FUNCTION__,
358*027c042eSDan Zhang                 ERR_error_string(ERR_get_error(), NULL));
359*027c042eSDan Zhang         goto err;
360*027c042eSDan Zhang     }
361*027c042eSDan Zhang     n = NULL; // Clear pointers to prevent double-free
362*027c042eSDan Zhang     e = NULL;
363*027c042eSDan Zhang 
364*027c042eSDan Zhang     if (RSA_bits(rsa) != expected_modulus_bits)
365*027c042eSDan Zhang     {
366*027c042eSDan Zhang         CPRINTS(
367*027c042eSDan Zhang             ctx,
368*027c042eSDan Zhang             "%s: Error: RSA key size (%d bits) does not match expected size for "
369*027c042eSDan Zhang             "scheme (%d bits).\n",
370*027c042eSDan Zhang             __FUNCTION__, RSA_bits(rsa), expected_modulus_bits);
371*027c042eSDan Zhang         goto err;
372*027c042eSDan Zhang     }
373*027c042eSDan Zhang 
374*027c042eSDan Zhang     // Input validation: Signature length must match modulus length
375*027c042eSDan Zhang     if (sig_len != RSA_size(rsa))
376*027c042eSDan Zhang     {
377*027c042eSDan Zhang         CPRINTS(
378*027c042eSDan Zhang             ctx,
379*027c042eSDan Zhang             "%s: Error: Signature length (%d) does not match RSA key size (%d).\n",
380*027c042eSDan Zhang             __FUNCTION__, sig_len, RSA_size(rsa));
381*027c042eSDan Zhang         goto err;
382*027c042eSDan Zhang     }
383*027c042eSDan Zhang 
384*027c042eSDan Zhang     // 3. Verify the signature
385*027c042eSDan Zhang     // RSA_verify handles the decryption, PKCS#1 v1.5 padding check, and hash
386*027c042eSDan Zhang     // comparison internally.
387*027c042eSDan Zhang     CPRINTS(ctx, "%s: RSA_verify\n", __FUNCTION__);
388*027c042eSDan Zhang     CPRINTS(ctx, "%s: hash_nid %d\n", __FUNCTION__, hash_nid);
389*027c042eSDan Zhang     CPRINTS(ctx, "%s: digest_len  %d, digest: \n", __FUNCTION__, digest_len);
390*027c042eSDan Zhang     for (int i = 0; i < digest_len; i++)
391*027c042eSDan Zhang     {
392*027c042eSDan Zhang         CPRINTS(ctx, "%x", digest[i]);
393*027c042eSDan Zhang     }
394*027c042eSDan Zhang     CPRINTS(ctx, "\n");
395*027c042eSDan Zhang 
396*027c042eSDan Zhang     CPRINTS(ctx, "%s: sig_len %d, sig: \n", __FUNCTION__, sig_len);
397*027c042eSDan Zhang     for (int i = 0; i < sig_len; i++)
398*027c042eSDan Zhang     {
399*027c042eSDan Zhang         CPRINTS(ctx, "%x", sig[i]);
400*027c042eSDan Zhang     }
401*027c042eSDan Zhang     CPRINTS(ctx, "\n");
402*027c042eSDan Zhang 
403*027c042eSDan Zhang     ret = RSA_verify(hash_nid, digest, digest_len, sig, sig_len, rsa);
404*027c042eSDan Zhang 
405*027c042eSDan Zhang     if (ret == 1)
406*027c042eSDan Zhang     {
407*027c042eSDan Zhang         CPRINTS(ctx, "%s: Signature verification successful!\n", __FUNCTION__);
408*027c042eSDan Zhang     }
409*027c042eSDan Zhang     else
410*027c042eSDan Zhang     {
411*027c042eSDan Zhang         CPRINTS(ctx, "%s: Signature verification failed: %s\n", __FUNCTION__,
412*027c042eSDan Zhang                 ERR_error_string(ERR_get_error(), NULL));
413*027c042eSDan Zhang     }
414*027c042eSDan Zhang 
415*027c042eSDan Zhang err:
416*027c042eSDan Zhang     RSA_free(rsa); // Frees n and e if RSA_set0_key successfully took ownership
417*027c042eSDan Zhang     BN_free(n);    // Only if RSA_set0_key failed or was not called
418*027c042eSDan Zhang     BN_free(e);    // Only if RSA_set0_key failed or was not called
419*027c042eSDan Zhang     return (ret == 1);
420*027c042eSDan Zhang     (void)ctx;     // make compiler happy when CPRINTS is null statemenet
421*027c042eSDan Zhang }
422*027c042eSDan Zhang 
4235acaca2fSWilliam A. Kennington III #ifdef __cplusplus
4245acaca2fSWilliam A. Kennington III } //  extern "C"
4255acaca2fSWilliam A. Kennington III #endif
426