int FIPS_rsa_sign_digest(RSA *rsa, const unsigned char *md, int md_len, const EVP_MD *mhash, int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, unsigned char *sigret, unsigned int *siglen) { int i=0,j,ret=0; unsigned int dlen; const unsigned char *der; int md_type; /* Largest DigestInfo: 19 (max encoding) + max MD */ unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE]; if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_RSA_SIGN_DIGEST, FIPS_R_SELFTEST_FAILED); return 0; } if (!mhash && rsa_pad_mode == RSA_PKCS1_PADDING) md_type = saltlen; else md_type = M_EVP_MD_type(mhash); if (rsa_pad_mode == RSA_X931_PADDING) { int hash_id; memcpy(tmpdinfo, md, md_len); hash_id = RSA_X931_hash_id(md_type); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } tmpdinfo[md_len] = (unsigned char)hash_id; i = md_len + 1; } else if (rsa_pad_mode == RSA_PKCS1_PADDING) { der = fips_digestinfo_encoding(md_type, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); return 0; } memcpy(tmpdinfo, der, dlen); memcpy(tmpdinfo + dlen, md, md_len); i = dlen + md_len; } else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) { unsigned char *sbuf; i = RSA_size(rsa); sbuf = OPENSSL_malloc(RSA_size(rsa)); if (!sbuf) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,ERR_R_MALLOC_FAILURE); goto psserr; } if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, sbuf, md, mhash, mgf1Hash, 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(sbuf, i); OPENSSL_free(sbuf); return ret; } j=RSA_size(rsa); if (i > (j-RSA_PKCS1_PADDING_SIZE)) { RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,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); return ret; }
int FIPS_rsa_verify_digest(RSA *rsa, const unsigned char *dig, int diglen, const EVP_MD *mhash, int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, const unsigned char *sigbuf, unsigned int siglen) { int i,ret=0; unsigned int dlen; unsigned char *s; const unsigned char *der; int md_type; int rsa_dec_pad_mode; if (FIPS_selftest_failed()) { FIPSerr(FIPS_F_FIPS_RSA_VERIFY_DIGEST, FIPS_R_SELFTEST_FAILED); return 0; } if (siglen != (unsigned int)RSA_size(rsa)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_WRONG_SIGNATURE_LENGTH); return(0); } if (!mhash && rsa_pad_mode == RSA_PKCS1_PADDING) md_type = saltlen; else md_type = M_EVP_MD_type(mhash); s= OPENSSL_malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,ERR_R_MALLOC_FAILURE); goto err; } if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) rsa_dec_pad_mode = RSA_NO_PADDING; else rsa_dec_pad_mode = rsa_pad_mode; /* NB: call underlying method directly to avoid FIPS blocking */ i=rsa->meth->rsa_pub_dec((int)siglen,sigbuf,s, rsa, rsa_dec_pad_mode); if (i <= 0) goto err; if (rsa_pad_mode == RSA_X931_PADDING) { int hash_id; if (i != (int)(diglen + 1)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } hash_id = RSA_X931_hash_id(md_type); if (hash_id == -1) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); goto err; } if (s[diglen] != (unsigned char)hash_id) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } if (memcmp(s, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (rsa_pad_mode == RSA_PKCS1_PADDING) { der = fips_digestinfo_encoding(md_type, &dlen); if (!der) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,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(md_type, &dlen); if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen) || memcmp(s + dlen, dig, diglen)) { RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); goto err; } ret = 1; } else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) { ret = RSA_verify_PKCS1_PSS_mgf1(rsa, dig, mhash, mgf1Hash, s, saltlen); if (ret < 0) ret = 0; } err: if (s != NULL) { OPENSSL_cleanse(s, siglen); OPENSSL_free(s); } return(ret); }
int fips_pkey_signature_test(int id, EVP_PKEY *pkey, const unsigned char *tbs, size_t tbslen, const unsigned char *kat, size_t katlen, const EVP_MD *digest, int pad_mode, const char *fail_str) { int subid; void *ex = NULL; int ret = 0; unsigned char *sig = NULL; unsigned int siglen; static const unsigned char str1[]="12345678901234567890"; DSA_SIG *dsig = NULL; ECDSA_SIG *esig = NULL; EVP_MD_CTX mctx; FIPS_md_ctx_init(&mctx); if (tbs == NULL) tbs = str1; if (tbslen == 0) tbslen = strlen((char *)tbs); if (digest == NULL) digest = EVP_sha256(); subid = M_EVP_MD_type(digest); if (!fips_post_started(id, subid, pkey)) return 1; if (!pkey || pkey->type == EVP_PKEY_RSA) { size_t sigsize; if (!pkey) sigsize = EVP_MAX_MD_SIZE; else sigsize = RSA_size(pkey->pkey.rsa); sig = OPENSSL_malloc(sigsize); if (!sig) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE); goto error; } } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (!fips_post_corrupt(id, subid, pkey)) { if (!FIPS_digestupdate(&mctx, tbs, 1)) goto error; } if (pkey == NULL) { if (!FIPS_digestfinal(&mctx, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_RSA) { if (!FIPS_rsa_sign_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_DSA) { dsig = FIPS_dsa_sign_ctx(pkey->pkey.dsa, &mctx); if (!dsig) goto error; } else if (pkey->type == EVP_PKEY_EC) { esig = FIPS_ecdsa_sign_ctx(pkey->pkey.ec, &mctx); if (!esig) goto error; } if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) goto error; #if 0 { /* Debug code to print out self test KAT discrepancies */ unsigned int i; fprintf(stderr, "%s=", fail_str); for (i = 0; i < siglen; i++) fprintf(stderr, "%02X", sig[i]); fprintf(stderr, "\n"); goto error; } #endif /* If just digest test we've finished */ if (pkey == NULL) { ret = 1; /* Well actually sucess as we've set ret to 1 */ goto error; } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (pkey->type == EVP_PKEY_RSA) { ret = FIPS_rsa_verify_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, siglen); } else if (pkey->type == EVP_PKEY_DSA) { ret = FIPS_dsa_verify_ctx(pkey->pkey.dsa, &mctx, dsig); } else if (pkey->type == EVP_PKEY_EC) { ret = FIPS_ecdsa_verify_ctx(pkey->pkey.ec, &mctx, esig); } error: if (dsig != NULL) FIPS_dsa_sig_free(dsig); if (esig != NULL) FIPS_ecdsa_sig_free(esig); if (sig) OPENSSL_free(sig); FIPS_md_ctx_cleanup(&mctx); if (ret != 1) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE); if (fail_str) FIPS_add_error_data(2, "Type=", fail_str); fips_post_failed(id, subid, ex); return 0; } return fips_post_success(id, subid, pkey); }