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