Changes between 0.9.8e and 0.9.8f-fips [xx XXX xxxx]
+ *) New flag EVP_MD_FLAG_SVCTX which passes EVP_MD_CTX and key to underlying
+ sign/verify method. This permits the method to perform finalization
+ and signing itself and have access to the EVP_MD_CTX structure in case
+ additional parameters are needed. Modify fips_{dsa,rsa}_{sign,verify}
+ to use EVP_MD_FLAG_SVCTX and support PSS and X9.31 RSA modes.
+ Modify RSA algorithm test programs to use new parameters.
+ [Steve Henson]
+
*) Add small standalone ASN1 encoder/decoder to handle DSA signature format.
Modify test, algorithm test and selftest routines to use EVP for DSA.
Move FIPS implementation of EVP_sha*() and EVP_dss1() under fips-1.0.
unsigned int m_length,const unsigned char *sigbuf,
unsigned int siglen, void *key);
+typedef struct
+ {
+ EVP_MD_CTX *mctx;
+ void *key;
+ } EVP_MD_SVCTX;
+
#define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single
* block */
#define EVP_MD_FLAG_FIPS 0x0400 /* Note if suitable for use in FIPS mode */
+#define EVP_MD_FLAG_SVCTX 0x0800 /* pass EVP_MD_SVCTX to sign/verify */
+
#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0}
#ifndef OPENSSL_NO_DSA
#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008 /* Allow use of non FIPS digest
* in FIPS mode */
+#define EVP_MD_CTX_FLAG_PAD_MASK 0xF0 /* RSA mode to use */
+#define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00 /* PKCS#1 v1.5 mode */
+#define EVP_MD_CTX_FLAG_PAD_X931 0x10 /* X9.31 mode */
+#define EVP_MD_CTX_FLAG_PAD_PSS 0x20 /* PSS mode */
+#define M_EVP_MD_CTX_FLAG_PSS_SALT(ctx) \
+ ((ctx->flags>>16) &0xFFFF) /* seed length */
+#define EVP_MD_CTX_FLAG_PSS_MDLEN 0xFFFF /* salt len same as digest */
+#define EVP_MD_CTX_FLAG_PSS_MREC 0xFFFE /* salt max or auto recovered */
+
struct evp_cipher_st
{
int nid;
#define M_EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs))
#define M_EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs))
#define M_EVP_MD_type(e) ((e)->type)
+#define M_EVP_MD_CTX_type(e) M_EVP_MD_type(M_EVP_MD_CTX_md(e))
+#define M_EVP_MD_CTX_md(e) ((e)->digest)
int EVP_MD_type(const EVP_MD *md);
MS_STATIC EVP_MD_CTX tmp_ctx;
*siglen=0;
- EVP_MD_CTX_init(&tmp_ctx);
- EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
- EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
- EVP_MD_CTX_cleanup(&tmp_ctx);
for (i=0; i<4; i++)
{
v=ctx->digest->required_pkey_type[i];
EVPerr(EVP_F_EVP_SIGNFINAL,EVP_R_NO_SIGN_FUNCTION_CONFIGURED);
return(0);
}
- return(ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
- pkey->pkey.ptr));
+ EVP_MD_CTX_init(&tmp_ctx);
+ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+ EVP_MD_SVCTX sctmp;
+ sctmp.mctx = &tmp_ctx;
+ sctmp.key = pkey->pkey.ptr;
+ i = ctx->digest->sign(ctx->digest->type,
+ NULL, -1, sigret, siglen, &sctmp);
+ }
+ else
+ {
+ EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
+ i = ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
+ pkey->pkey.ptr);
+ }
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+ return i;
}
EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_WRONG_PUBLIC_KEY_TYPE);
return(-1);
}
- EVP_MD_CTX_init(&tmp_ctx);
- EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
- EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
- EVP_MD_CTX_cleanup(&tmp_ctx);
- if (ctx->digest->verify == NULL)
+ if (ctx->digest->verify == NULL)
{
EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_NO_VERIFY_FUNCTION_CONFIGURED);
return(0);
}
- return(ctx->digest->verify(ctx->digest->type,m,m_len,
- sigbuf,siglen,pkey->pkey.ptr));
+ EVP_MD_CTX_init(&tmp_ctx);
+ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+ EVP_MD_SVCTX sctmp;
+ sctmp.mctx = &tmp_ctx;
+ sctmp.key = pkey->pkey.ptr;
+ i = ctx->digest->verify(ctx->digest->type,
+ NULL, -1, sigbuf, siglen, &sctmp);
+ }
+ else
+ {
+ EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
+ i = ctx->digest->verify(ctx->digest->type,m,m_len,
+ sigbuf,siglen,pkey->pkey.ptr);
+ }
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+ return i;
}
return 1;
}
-static int fips_dsa_sign(int type, const unsigned char *dgst, int dlen,
- unsigned char *sig, unsigned int *siglen, DSA *dsa)
+static int fips_dsa_sign(int type, const unsigned char *x, int y,
+ unsigned char *sig, unsigned int *siglen, EVP_MD_SVCTX *sv)
{
+ DSA *dsa = sv->key;
+ unsigned char dig[EVP_MAX_MD_SIZE];
+ unsigned int dlen;
DSA_SIG *s;
- s=dsa->meth->dsa_do_sign(dgst,dlen,dsa);
+ EVP_DigestFinal_ex(sv->mctx, dig, &dlen);
+ s=dsa->meth->dsa_do_sign(dig,dlen,dsa);
+ OPENSSL_cleanse(dig, dlen);
if (s == NULL)
{
*siglen=0;
return 1;
}
-static int fips_dsa_verify(int type, const unsigned char *dgst, int dgst_len,
- const unsigned char *sigbuf, int siglen, DSA *dsa)
+static int fips_dsa_verify(int type, const unsigned char *x, int y,
+ const unsigned char *sigbuf, unsigned int siglen, EVP_MD_SVCTX *sv)
{
+ DSA *dsa = sv->key;
DSA_SIG *s;
int ret=-1;
+ unsigned char dig[EVP_MAX_MD_SIZE];
+ unsigned int dlen;
s = DSA_SIG_new();
if (s == NULL)
return ret;
if (!FIPS_dsa_sig_decode(s,sigbuf,siglen))
goto err;
- ret=dsa->meth->dsa_do_verify(dgst,dgst_len,s,dsa);
+ EVP_DigestFinal_ex(sv->mctx, dig, &dlen);
+ ret=dsa->meth->dsa_do_verify(dig,dlen,s,dsa);
+ OPENSSL_cleanse(dig, dlen);
err:
DSA_SIG_free(s);
return ret;
NID_dsa,
NID_dsaWithSHA1,
SHA_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init,
update,
final,
}
}
-static int fips_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
- unsigned char *sigret, unsigned int *siglen, RSA *rsa)
+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,j,ret=1;
+ int i,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;
+ 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)
{
- return rsa->meth->rsa_sign(type, m, m_len,
+ ret = rsa->meth->rsa_sign(type, md, m_len,
sigret, siglen, rsa);
+ goto done;
}
- if(m_len > EVP_MAX_MD_SIZE)
+ if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931)
{
- RSAerr(RSA_F_RSA_SIGN,RSA_R_INVALID_MESSAGE_LENGTH);
- return 0;
+ memcpy(tmpdinfo, md, m_len);
+ tmpdinfo[m_len] = RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx));
+ 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)
+ der = fips_digestinfo_encoding(type, &dlen);
+
+ if (!der)
+ {
+ RSAerr(RSA_F_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)
{
- RSAerr(RSA_F_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE);
- return(0);
+ 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_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;
}
- memcpy(tmpdinfo, der, dlen);
- memcpy(tmpdinfo + dlen, m, m_len);
-
- i = dlen + m_len;
j=RSA_size(rsa);
if (i > (j-RSA_PKCS1_PADDING_SIZE))
{
RSAerr(RSA_F_RSA_SIGN,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
- return(0);
+ goto done;
}
/* NB: call underlying method directly to avoid FIPS blocking */
- j=rsa->meth->rsa_priv_enc(i,tmpdinfo,sigret,rsa,RSA_PKCS1_PADDING);
- if (j <= 0)
- ret=0;
- else
+ 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);
+ OPENSSL_cleanse(md,m_len);
+ return ret;
}
static int fips_rsa_verify(int dtype,
- const unsigned char *m, unsigned int m_len,
- unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
+ const unsigned char *x, unsigned int y,
+ unsigned char *sigbuf, unsigned int siglen, EVP_MD_SVCTX *sv)
{
int i,ret=0;
- unsigned int dlen;
+ unsigned int dlen, diglen;
+ int pad_mode = sv->mctx->flags & EVP_MD_CTX_FLAG_PAD_MASK;
+ int rsa_pad_mode;
unsigned char *s;
const unsigned char *der;
+ unsigned char dig[EVP_MAX_MD_SIZE];
+ RSA *rsa = sv->key;
- if (siglen != (unsigned int)RSA_size(rsa))
+ if (siglen != (unsigned int)RSA_size(sv->key))
{
RSAerr(RSA_F_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, m, m_len,
+ return rsa->meth->rsa_verify(dtype, dig, diglen,
sigbuf, siglen, rsa);
}
+
s= OPENSSL_malloc((unsigned int)siglen);
if (s == NULL)
{
RSAerr(RSA_F_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_PKCS1_PADDING);
+ i=rsa->meth->rsa_pub_dec((int)siglen,sigbuf,s, rsa, rsa_pad_mode);
if (i <= 0) goto err;
- der = fips_digestinfo_encoding(dtype, &dlen);
-
- if (!der)
+ if (pad_mode == EVP_MD_CTX_FLAG_PAD_X931)
{
- RSAerr(RSA_F_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE);
- return(0);
+ if (i != diglen + 1)
+ {
+ RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
+ goto err;
+ }
+ if (s[diglen] != RSA_X931_hash_id(M_EVP_MD_CTX_type(sv->mctx)))
+ {
+ RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
+ goto err;
+ }
+ if (memcmp(s, dig, diglen))
+ {
+ RSAerr(RSA_F_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_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return(0);
+ }
+
+ /* Compare, DigestInfo length, DigestInfo header and finally
+ * digest value itself
+ */
+ if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen)
+ || memcmp(s + dlen, dig, diglen))
+ {
+ RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
+ goto err;
+ }
+ else
+ ret = 1;
- /* Compare, DigestInfo length, DigestInfo header and finally
- * digest value itself
- */
- if ((i != (int)(dlen + m_len)) || memcmp(der, s, dlen)
- || memcmp(s + dlen, m, m_len))
+ }
+ else if (pad_mode == EVP_MD_CTX_FLAG_PAD_PSS)
{
- RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
- goto err;
+ 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;
}
- else
- ret = 1;
err:
if (s != NULL)
{
NID_sha1,
NID_sha1WithRSAEncryption,
SHA_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init,
update,
final,
NID_sha224,
NID_sha224WithRSAEncryption,
SHA224_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init224,
update256,
final256,
NID_sha256,
NID_sha256WithRSAEncryption,
SHA256_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init256,
update256,
final256,
NID_sha384,
NID_sha384WithRSAEncryption,
SHA384_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init384,
update512,
final512,
NID_sha512,
NID_sha512WithRSAEncryption,
SHA512_DIGEST_LENGTH,
- EVP_MD_FLAG_FIPS,
+ EVP_MD_FLAG_FIPS|EVP_MD_FLAG_SVCTX,
init512,
update512,
final512,
EVP_MD_CTX_init(&ctx);
- if (Saltlen != -1)
+ if (Saltlen >= 0)
{
- unsigned int mdlen;
- unsigned char mdtmp[EVP_MAX_MD_SIZE + 1];
-
- if (!EVP_DigestInit_ex(&ctx, dgst, NULL))
- goto error;
- if (!EVP_DigestUpdate(&ctx, Msg, Msglen))
- goto error;
- if (!EVP_DigestFinal(&ctx, mdtmp, &mdlen))
- goto error;
-
- if (Saltlen == -2)
- {
- mdtmp[mdlen] = RSA_X931_hash_id(M_EVP_MD_type(dgst));
- siglen = RSA_private_encrypt(mdlen + 1, mdtmp,
- sigbuf, rsa, RSA_X931_PADDING);
- if (siglen <= 0)
- goto error;
- }
- else
- {
- if (!RSA_padding_add_PKCS1_PSS(rsa, sigbuf, mdtmp,
- dgst, Saltlen))
- goto error;
- siglen = RSA_private_encrypt(siglen, sigbuf, sigbuf,
- rsa, RSA_NO_PADDING);
- if (siglen <= 0)
- goto error;
- }
- }
- else
- {
- if (!EVP_SignInit_ex(&ctx, dgst, NULL))
- goto error;
- if (!EVP_SignUpdate(&ctx, Msg, Msglen))
- goto error;
- if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk))
- goto error;
+ M_EVP_MD_CTX_set_flags(&ctx,
+ EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
}
+ else if (Saltlen == -2)
+ M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
+ if (!EVP_SignInit_ex(&ctx, dgst, NULL))
+ goto error;
+ if (!EVP_SignUpdate(&ctx, Msg, Msglen))
+ goto error;
+ if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk))
+ goto error;
EVP_MD_CTX_cleanup(&ctx);
EVP_MD_CTX_init(&ctx);
- if (Saltlen != -1)
+ if (Saltlen >= 0)
{
- int pad;
- unsigned char mdtmp[EVP_MAX_MD_SIZE];
- buf = OPENSSL_malloc(RSA_size(rsa_pubkey));
- if (Saltlen == -2)
- pad = RSA_X931_PADDING;
- else
- pad = RSA_NO_PADDING;
- if (!buf)
- goto error;
- r = RSA_public_decrypt(Slen, S, buf, rsa_pubkey, pad);
-
- if (r > 0)
- {
- EVP_DigestInit_ex(&ctx, dgst, NULL);
- if (!EVP_DigestUpdate(&ctx, Msg, Msglen))
- goto error;
- if (!EVP_DigestFinal_ex(&ctx, mdtmp, NULL))
- goto error;
- if (pad == RSA_X931_PADDING)
- {
- int mdlen = M_EVP_MD_size(dgst);
- if (r != mdlen + 1)
- r = 0;
- else if (buf[mdlen] !=
- RSA_X931_hash_id(M_EVP_MD_type(dgst)))
- r = 0;
- else if (memcmp(buf, mdtmp, mdlen))
- r = 0;
- else
- r = 1;
- }
- else
- r = RSA_verify_PKCS1_PSS(rsa_pubkey,
- mdtmp, dgst,
- buf, Saltlen);
- }
- if (r < 0)
- r = 0;
+ M_EVP_MD_CTX_set_flags(&ctx,
+ EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
}
- else
- {
-
- if (!EVP_VerifyInit_ex(&ctx, dgst, NULL))
- goto error;
- if (!EVP_VerifyUpdate(&ctx, Msg, Msglen))
- goto error;
+ else if (Saltlen == -2)
+ M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
+ if (!EVP_VerifyInit_ex(&ctx, dgst, NULL))
+ goto error;
+ if (!EVP_VerifyUpdate(&ctx, Msg, Msglen))
+ goto error;
- r = EVP_VerifyFinal(&ctx, S, Slen, &pk);
+ r = EVP_VerifyFinal(&ctx, S, Slen, &pk);
- }
EVP_MD_CTX_cleanup(&ctx);