//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); } }
bool signHelper ( RSA* key, Slice message, Buffer& modulus, Buffer& signature) { int const keySize = RSA_size(key); if (!checkModulusLength (keySize)) return false; sha256_hasher h; h (message.data(), message.size()); auto digest = static_cast<sha256_hasher::result_type>(h); Buffer buf; // Pad the result (-1 -> use hash length as salt length) if (!RSA_padding_add_PKCS1_PSS(key, buf.alloc(keySize), digest.data(), EVP_sha256(), -1)) return false; // Sign - we've manually padded the input already. auto ret = RSA_private_encrypt(keySize, buf.data(), signature.alloc (buf.size()), key, RSA_NO_PADDING); if (ret == -1) return false; BN_bn2bin (key->n, modulus.alloc(BN_num_bytes (key->n))); return true; }
static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { int ret; RSA_PKEY_CTX *rctx = (RSA_PKEY_CTX*)ctx->data; RSA *rsa = ctx->pkey->pkey.rsa; if (rctx->md) { if (tbslen != (size_t)EVP_MD_size(rctx->md)) { RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH); return -1; } if (rctx->pad_mode == RSA_X931_PADDING) { if (!setup_tbuf(rctx, ctx)) return -1; TINYCLR_SSL_MEMCPY(rctx->tbuf, tbs, tbslen); rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md)); ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf, sig, rsa, RSA_X931_PADDING); } else if (rctx->pad_mode == RSA_PKCS1_PADDING) { unsigned int sltmp; ret = RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &sltmp, rsa); if (ret <= 0) return ret; ret = sltmp; } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) { if (!setup_tbuf(rctx, ctx)) return -1; if (!RSA_padding_add_PKCS1_PSS(rsa, rctx->tbuf, tbs, rctx->md, rctx->saltlen)) return -1; ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf, sig, rsa, RSA_NO_PADDING); } else return -1; } else ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa, rctx->pad_mode); if (ret < 0) return ret; *siglen = ret; return 1; }
void rsa_key::padding_add_PKCS1_PSS(void* out, size_t out_len, const void* buf, size_t buf_len, hash::message_digest_algorithm algorithm, int salt_len) const { assert(out_len >= algorithm.result_size()); assert(buf_len >= algorithm.result_size()); if (out_len < algorithm.result_size()) { throw std::invalid_argument("out_len"); } if (buf_len < algorithm.result_size()) { throw std::invalid_argument("buf_len"); } throw_error_if_not(RSA_padding_add_PKCS1_PSS(ptr().get(), static_cast<unsigned char*>(out), static_cast<const unsigned char*>(buf), algorithm.raw(), salt_len) != 0); }
static bool _cjose_jws_build_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 private RSA if (jwk->kty != CJOSE_JWK_KTY_RSA) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto _cjose_jws_build_sig_ps_cleanup; } RSA *rsa = (RSA *)jwk->keydata; BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; _cjose_jwk_rsa_get(rsa, &rsa_n, &rsa_e, &rsa_d); if (!rsa || !rsa_e || !rsa_n || !rsa_d) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } // 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_build_sig_ps_cleanup; } // apply EMSA-PSS encoding (RFC-3447, 8.1.1, step 1) // (RSA_padding_add_PKCS1_PSS includes PKCS1_MGF1, -1 => saltlen = hashlen) em_len = RSA_size((RSA *)jwk->keydata); em = (uint8_t *)cjose_get_alloc()(em_len); if (NULL == em) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jws_build_sig_ps_cleanup; } if (RSA_padding_add_PKCS1_PSS((RSA *)jwk->keydata, em, jws->dig, digest_alg, -1) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_build_sig_ps_cleanup; } // sign the digest (RFC-3447, 8.1.1, step 2) jws->sig_len = em_len; jws->sig = (uint8_t *)cjose_get_alloc()(jws->sig_len); if (NULL == jws->sig) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jws_build_sig_ps_cleanup; } if (RSA_private_encrypt(em_len, em, jws->sig, (RSA *)jwk->keydata, RSA_NO_PADDING) != jws->sig_len) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_build_sig_ps_cleanup; } // base64url encode signed digest if (!cjose_base64url_encode((const uint8_t *)jws->sig, jws->sig_len, &jws->sig_b64u, &jws->sig_b64u_len, err)) { goto _cjose_jws_build_sig_ps_cleanup; } // if we got this far - success retval = true; _cjose_jws_build_sig_ps_cleanup: cjose_get_dealloc()(em); return retval; }
bool OSSLRSA::signFinal(ByteString& signature) { // Save necessary state before calling super class signFinal OSSLRSAPrivateKey* pk = (OSSLRSAPrivateKey*) currentPrivateKey; AsymMech::Type mechanism = currentMechanism; if (!AsymmetricAlgorithm::signFinal(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; // Resize the data block for the signature to the modulus size of the key signature.resize(pk->getN().size()); // 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 signature operation unsigned int sigLen = signature.size(); RSA* rsa = pk->getOSSLKey(); if (!RSA_blinding_on(rsa, NULL)) { ERROR_MSG("Failed to turn blinding on for OpenSSL RSA key"); return false; } bool rv; if (isPSS) { ByteString em; em.resize(pk->getN().size()); rv = (RSA_padding_add_PKCS1_PSS(pk->getOSSLKey(), &em[0], &digest[0], hash, sLen) == 1); if (!rv) { ERROR_MSG("RSA PSS padding failed (0x%08X)", ERR_get_error()); } else { int result = RSA_private_encrypt(em.size(), &em[0], &signature[0], pk->getOSSLKey(), RSA_NO_PADDING); if (result >= 0) { sigLen = result; rv = true; } else { rv = false; ERROR_MSG("RSA private encrypt failed (0x%08X)", ERR_get_error()); } } } else { rv = (RSA_sign(type, &digest[0], digest.size(), &signature[0], &sigLen, pk->getOSSLKey()) == 1); } RSA_blinding_off(rsa); signature.resize(sigLen); return rv; }
static int fips_rsa_sign(int type, const unsigned char *x, unsigned int y, unsigned char *sigret, unsigned int *siglen, EVP_MD_SVCTX * sv) { int i = 0, j, ret = 0; unsigned int dlen; const unsigned char *der; unsigned int m_len; int pad_mode = sv->mctx->flags & EVP_MD_CTX_FLAG_PAD_MASK; int rsa_pad_mode = 0; RSA *rsa = sv->key; /* Largest DigestInfo: 19 (max encoding) + max MD */ unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE]; unsigned char md[EVP_MAX_MD_SIZE + 1]; EVP_DigestFinal_ex(sv->mctx, md, &m_len); if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) { ret = rsa->meth->rsa_sign(type, md, m_len, sigret, siglen, rsa); goto done; } if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931) { int hash_id; memcpy(tmpdinfo, md, m_len); hash_id = RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx)); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } tmpdinfo[m_len] = (unsigned char)hash_id; i = m_len + 1; rsa_pad_mode = RSA_X931_PADDING; } else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PKCS1) { der = fips_digestinfo_encoding(type, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } memcpy(tmpdinfo, der, dlen); memcpy(tmpdinfo + dlen, md, m_len); i = dlen + m_len; rsa_pad_mode = RSA_PKCS1_PADDING; } else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS) { unsigned char *sbuf; int saltlen; i = RSA_size(rsa); sbuf = OPENSSL_malloc(RSA_size(rsa)); 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; if (!sbuf) { RSAerr(RSA_F_FIPS_RSA_SIGN, ERR_R_MALLOC_FAILURE); goto psserr; } if (!RSA_padding_add_PKCS1_PSS(rsa, sbuf, md, M_EVP_MD_CTX_md(sv->mctx), saltlen)) goto psserr; j = rsa->meth->rsa_priv_enc(i, sbuf, sigret, rsa, RSA_NO_PADDING); if (j > 0) { ret = 1; *siglen = j; } psserr: OPENSSL_cleanse(md, m_len); OPENSSL_cleanse(sbuf, i); OPENSSL_free(sbuf); return ret; } j = RSA_size(rsa); if (i > (j - RSA_PKCS1_PADDING_SIZE)) { RSAerr(RSA_F_FIPS_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); goto done; } /* NB: call underlying method directly to avoid FIPS blocking */ j = rsa->meth->rsa_priv_enc(i, tmpdinfo, sigret, rsa, rsa_pad_mode); if (j > 0) { ret = 1; *siglen = j; } done: OPENSSL_cleanse(tmpdinfo, i); OPENSSL_cleanse(md, m_len); return ret; }