bool validateHelper ( RSA* key, Slice message, Slice signature) { int const keySize = RSA_size(key); if (!checkModulusLength (keySize)) return false; Buffer buf; auto ret = RSA_public_decrypt( keySize, signature.data(), buf.alloc (keySize), key, RSA_NO_PADDING); if (ret == -1) return false; sha256_hasher h; h (message.data(), message.size()); auto digest = static_cast<sha256_hasher::result_type>(h); return RSA_verify_PKCS1_PSS(key, digest.data(), EVP_sha256(), buf.data(), -1) == 1; }
//Hardcoding this test code for PSS-SHA1 void RsaPssVerification(unsigned int uKeySize, const unsigned char* pMsg, const unsigned char* pSign, unsigned int E, const unsigned char* pN, const unsigned char* pD) { RSA* pRsaKey = NULL; const unsigned char* pDigest = NULL; size_t uDigestLen = 20; unsigned char EM[512]; unsigned char signature[512]; unsigned int uLen = 0; int status = 0; // Generate an RSA key pair pRsaKey = GetRsaKey(E, pN, pD); if (pRsaKey) { //Use the already hashed input message and compute the PSS padded data with max salt size pDigest = pMsg; printbin("HASH", pDigest, 20); status = RSA_padding_add_PKCS1_PSS(pRsaKey, EM, pDigest, EVP_sha1(), -2); printbin("EM", EM, uKeySize); if (status == 1) { //Now do Rsa Signature (RSA private encrypt) status = RSA_private_encrypt(uKeySize, EM, signature, pRsaKey, RSA_NO_PADDING); printbin("Sign", signature, uKeySize); if (status != -1) { //Now its time to verify the signature using RSA public decryption //We could directly use signature, but we are here to verify the signature generated by HW KM1 uLen = hex2bin(signature, pSign); //assert(uLen == uKeySize) printbin("Sign", signature, uLen); status = RSA_public_decrypt(uKeySize, signature, EM, pRsaKey, RSA_NO_PADDING); printbin("EM", EM, uKeySize); if (status != -1) { //Verify the data against the message with expecting max salt length from ssignature status = RSA_verify_PKCS1_PSS(pRsaKey, pDigest, EVP_sha1(), EM, -2); if (status == 1) { printf("GREAT: Signature verification successful\n"); } else { printf("RSA_verify_PKCS1_PSS failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); } } else { printf("RSA_public_decrypt failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); } } else { printf("RSA_private_encrypt failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); } } else { printf("RSA_padding_add_PKCS1_PSS failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); } } if (pRsaKey) { RSA_free(pRsaKey); } }
static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { RSA_PKEY_CTX *rctx = (RSA_PKEY_CTX*)ctx->data; RSA *rsa = ctx->pkey->pkey.rsa; size_t rslen; if (rctx->md) { if (rctx->pad_mode == RSA_PKCS1_PADDING) return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa); if (rctx->pad_mode == RSA_X931_PADDING) { if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0) return 0; } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) { int ret; if (!setup_tbuf(rctx, ctx)) return -1; ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa, RSA_NO_PADDING); if (ret <= 0) return 0; ret = RSA_verify_PKCS1_PSS(rsa, tbs, rctx->md, rctx->tbuf, rctx->saltlen); if (ret <= 0) return 0; return 1; } else return -1; } else { if (!setup_tbuf(rctx, ctx)) return -1; rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa, rctx->pad_mode); if (rslen == 0) return 0; } if ((rslen != tbslen) || TINYCLR_SSL_MEMCMP(tbs, rctx->tbuf, rslen)) return 0; return 1; }
void rsa_key::verify_PKCS1_PSS(const void* digest, size_t digest_len, const void* buf, size_t /*buf_len*/, hash::message_digest_algorithm algorithm, int salt_len) const { assert(digest_len >= algorithm.result_size()); if (digest_len < algorithm.result_size()) { throw std::invalid_argument("digest_len"); } //TODO: Use buf_len throw_error_if_not(RSA_verify_PKCS1_PSS(ptr().get(), static_cast<const unsigned char*>(digest), algorithm.raw(), static_cast<const unsigned char*>(buf), salt_len) != 0); }
/* * verify HMAC signature on JWT */ static apr_byte_t apr_jws_verify_rsa(apr_pool_t *pool, apr_jwt_t *jwt, apr_jwk_t *jwk, apr_jwt_error_t *err) { apr_byte_t rc = FALSE; /* get the OpenSSL digest function */ const EVP_MD *digest = NULL; if ((digest = apr_jws_crypto_alg_to_evp(pool, jwt->header.alg, err)) == NULL) return FALSE; EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); RSA * pubkey = RSA_new(); BIGNUM * modulus = BN_new(); BIGNUM * exponent = BN_new(); BN_bin2bn(jwk->key.rsa->modulus, jwk->key.rsa->modulus_len, modulus); BN_bin2bn(jwk->key.rsa->exponent, jwk->key.rsa->exponent_len, exponent); pubkey->n = modulus; pubkey->e = exponent; EVP_PKEY* pRsaKey = EVP_PKEY_new(); if (!EVP_PKEY_assign_RSA(pRsaKey, pubkey)) { pRsaKey = NULL; apr_jwt_error_openssl(err, "EVP_PKEY_assign_RSA"); goto end; } if (apr_jws_signature_starts_with(pool, jwt->header.alg, "PS") == TRUE) { int status = 0; unsigned char *pDecrypted = apr_pcalloc(pool, jwt->signature.length); status = RSA_public_decrypt(jwt->signature.length, jwt->signature.bytes, pDecrypted, pubkey, RSA_NO_PADDING); if (status == -1) { apr_jwt_error_openssl(err, "RSA_public_decrypt"); goto end; } unsigned char *pDigest = apr_pcalloc(pool, RSA_size(pubkey)); unsigned int uDigestLen = RSA_size(pubkey); if (!EVP_DigestInit(&ctx, digest)) { apr_jwt_error_openssl(err, "EVP_DigestInit"); goto end; } if (!EVP_DigestUpdate(&ctx, jwt->message, strlen(jwt->message))) { apr_jwt_error_openssl(err, "EVP_DigestUpdate"); goto end; } if (!EVP_DigestFinal(&ctx, pDigest, &uDigestLen)) { apr_jwt_error_openssl(err, "wrong key? EVP_DigestFinal"); goto end; } /* verify the data */ status = RSA_verify_PKCS1_PSS(pubkey, pDigest, digest, pDecrypted, -2 /* salt length recovered from signature*/); if (status != 1) { apr_jwt_error_openssl(err, "RSA_verify_PKCS1_PSS"); goto end; } rc = TRUE; } else if (apr_jws_signature_starts_with(pool, jwt->header.alg, "RS") == TRUE) { if (!EVP_VerifyInit_ex(&ctx, digest, NULL)) { apr_jwt_error_openssl(err, "EVP_VerifyInit_ex"); goto end; } if (!EVP_VerifyUpdate(&ctx, jwt->message, strlen(jwt->message))) { apr_jwt_error_openssl(err, "EVP_VerifyUpdate"); goto end; } if (!EVP_VerifyFinal(&ctx, (const unsigned char *) jwt->signature.bytes, jwt->signature.length, pRsaKey)) { apr_jwt_error_openssl(err, "wrong key? EVP_VerifyFinal"); goto end; } rc = TRUE; } end: if (pRsaKey) { EVP_PKEY_free(pRsaKey); } else if (pubkey) { RSA_free(pubkey); } EVP_MD_CTX_cleanup(&ctx); return rc; }
static bool _cjose_jws_verify_sig_ps(cjose_jws_t *jws, const cjose_jwk_t *jwk, cjose_err *err) { bool retval = false; uint8_t *em = NULL; size_t em_len = 0; // ensure jwk is RSA if (jwk->kty != CJOSE_JWK_KTY_RSA) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto _cjose_jws_verify_sig_ps_cleanup; } // make sure we have an alg header json_t *alg_obj = json_object_get(jws->hdr, CJOSE_HDR_ALG); if (NULL == alg_obj) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } const char *alg = json_string_value(alg_obj); // build digest using SHA-256/384/512 digest algorithm const EVP_MD *digest_alg = NULL; if (strcmp(alg, CJOSE_HDR_ALG_PS256) == 0) digest_alg = EVP_sha256(); else if (strcmp(alg, CJOSE_HDR_ALG_PS384) == 0) digest_alg = EVP_sha384(); else if (strcmp(alg, CJOSE_HDR_ALG_PS512) == 0) digest_alg = EVP_sha512(); if (NULL == digest_alg) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // allocate buffer for encoded message em_len = RSA_size((RSA *)jwk->keydata); em = (uint8_t *)cjose_get_alloc()(em_len); if (NULL == em) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // decrypt signature if (RSA_public_decrypt(jws->sig_len, jws->sig, em, (RSA *)jwk->keydata, RSA_NO_PADDING) != em_len) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // verify decrypted signature data against PSS encoded digest if (RSA_verify_PKCS1_PSS((RSA *)jwk->keydata, jws->dig, digest_alg, em, -1) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ps_cleanup; } // if we got this far - success retval = true; _cjose_jws_verify_sig_ps_cleanup: cjose_get_dealloc()(em); return retval; }
bool OSSLRSA::verifyFinal(const ByteString& signature) { // Save necessary state before calling super class verifyFinal OSSLRSAPublicKey* pk = (OSSLRSAPublicKey*) currentPublicKey; AsymMech::Type mechanism = currentMechanism; if (!AsymmetricAlgorithm::verifyFinal(signature)) { return false; } ByteString firstHash, secondHash; bool bFirstResult = pCurrentHash->hashFinal(firstHash); bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true; delete pCurrentHash; pCurrentHash = NULL; if (pSecondHash != NULL) { delete pSecondHash; pSecondHash = NULL; } if (!bFirstResult || !bSecondResult) { return false; } ByteString digest = firstHash + secondHash; // Determine the signature NID type int type = 0; bool isPSS = false; const EVP_MD* hash = NULL; switch (mechanism) { case AsymMech::RSA_MD5_PKCS: type = NID_md5; break; case AsymMech::RSA_SHA1_PKCS: type = NID_sha1; break; case AsymMech::RSA_SHA224_PKCS: type = NID_sha224; break; case AsymMech::RSA_SHA256_PKCS: type = NID_sha256; break; case AsymMech::RSA_SHA384_PKCS: type = NID_sha384; break; case AsymMech::RSA_SHA512_PKCS: type = NID_sha512; break; case AsymMech::RSA_SHA1_PKCS_PSS: isPSS = true; hash = EVP_sha1(); break; case AsymMech::RSA_SHA224_PKCS_PSS: isPSS = true; hash = EVP_sha224(); break; case AsymMech::RSA_SHA256_PKCS_PSS: isPSS = true; hash = EVP_sha256(); break; case AsymMech::RSA_SHA384_PKCS_PSS: isPSS = true; hash = EVP_sha384(); break; case AsymMech::RSA_SHA512_PKCS_PSS: isPSS = true; hash = EVP_sha512(); break; case AsymMech::RSA_SSL: type = NID_md5_sha1; break; default: break; } // Perform the verify operation bool rv; if (isPSS) { ByteString plain; plain.resize(pk->getN().size()); int result = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &plain[0], pk->getOSSLKey(), RSA_NO_PADDING); if (result < 0) { rv = false; ERROR_MSG("RSA public decrypt failed (0x%08X)", ERR_get_error()); } else { plain.resize(result); result = RSA_verify_PKCS1_PSS(pk->getOSSLKey(), &digest[0], hash, &plain[0], sLen); if (result == 1) { rv = true; } else { rv = false; ERROR_MSG("RSA PSS verify failed (0x%08X)", ERR_get_error()); } } } else { rv = (RSA_verify(type, &digest[0], digest.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1); if (!rv) ERROR_MSG("RSA verify failed (0x%08X)", ERR_get_error()); } return rv; }
static int fips_rsa_verify(int dtype, const unsigned char *x, unsigned int y, unsigned char *sigbuf, unsigned int siglen, EVP_MD_SVCTX * sv) { int i, ret = 0; unsigned int dlen, diglen; int pad_mode = sv->mctx->flags & EVP_MD_CTX_FLAG_PAD_MASK; int rsa_pad_mode = 0; unsigned char *s; const unsigned char *der; unsigned char dig[EVP_MAX_MD_SIZE]; RSA *rsa = sv->key; if (siglen != (unsigned int)RSA_size(sv->key)) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH); return (0); } EVP_DigestFinal_ex(sv->mctx, dig, &diglen); if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) { return rsa->meth->rsa_verify(dtype, dig, diglen, sigbuf, siglen, rsa); } s = OPENSSL_malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_FIPS_RSA_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931) rsa_pad_mode = RSA_X931_PADDING; else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1) rsa_pad_mode = RSA_PKCS1_PADDING; else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS) rsa_pad_mode = RSA_NO_PADDING; /* NB: call underlying method directly to avoid FIPS blocking */ i = rsa->meth->rsa_pub_dec((int)siglen, sigbuf, s, rsa, rsa_pad_mode); if (i <= 0) goto err; if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931) { int hash_id; if (i != (int)(diglen + 1)) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } hash_id = RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx)); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE); goto err; } if (s[diglen] != (unsigned char)hash_id) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } if (memcmp(s, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1) { der = fips_digestinfo_encoding(dtype, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE); return (0); } /* * Compare, DigestInfo length, DigestInfo header and finally digest * value itself */ /* If length mismatch try alternate encoding */ if (i != (int)(dlen + diglen)) der = fips_digestinfo_nn_encoding(dtype, &dlen); if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen) || memcmp(s + dlen, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS) { int saltlen; saltlen = M_EVP_MD_CTX_FLAG_PSS_SALT(sv->mctx); if (saltlen == EVP_MD_CTX_FLAG_PSS_MDLEN) saltlen = -1; else if (saltlen == EVP_MD_CTX_FLAG_PSS_MREC) saltlen = -2; ret = RSA_verify_PKCS1_PSS(rsa, dig, M_EVP_MD_CTX_md(sv->mctx), s, saltlen); if (ret < 0) ret = 0; } err: if (s != NULL) { OPENSSL_cleanse(s, siglen); OPENSSL_free(s); } return (ret); }