Flag to disable automatic copying of contexts.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 13 Nov 2013 14:33:57 +0000 (14:33 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 13 Nov 2013 23:48:35 +0000 (23:48 +0000)
Some functions such as EVP_VerifyFinal only finalise a copy of the passed
context in case an application wants to digest more data. Doing this when
it is not needed is inefficient and many applications don't require it.

For compatibility the default is to still finalise a copy unless the
flag EVP_MD_CTX_FLAG_FINALISE is set in which case the passed
context is finalised an *no* further data can be digested after
finalisation.

crypto/evp/evp.h
crypto/evp/m_sigver.c
crypto/evp/p_sign.c
crypto/evp/p_verify.c

index fcc75e77aaef9b05a54f7a744ff2f22fb85ce8f4..2b130c483d5e7cc57709703e92f123eadf8d79a0 100644 (file)
@@ -300,6 +300,12 @@ struct env_md_ctx_st
 #define EVP_MD_CTX_FLAG_PAD_PSS                0x20    /* PSS mode */
 
 #define EVP_MD_CTX_FLAG_NO_INIT                0x0100 /* Don't initialize md_data */
+/* Some functions such as EVP_DigestSign only finalise copies of internal
+ * contexts so additional data can be included after the finalisation call.
+ * This is inefficient if this functionality is not required: it is disabled
+ * if the following flag is set.
+ */
+#define EVP_MD_CTX_FLAG_FINALISE       0x0200
 
 struct evp_cipher_st
        {
index 664ed0c2122cc716ed7cc8f17d373e1e86bd3722..9f83d3e25f4b03b065901fd7b8988adbaae161eb 100644 (file)
@@ -140,14 +140,18 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
        EVP_PKEY_CTX *pctx = ctx->pctx;
        if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)
                {
-               EVP_PKEY_CTX *dctx;
                if (!sigret)
                        return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
-               dctx = EVP_PKEY_CTX_dup(ctx->pctx);
-               if (!dctx)
-                       return 0;
-               r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
-               EVP_PKEY_CTX_free(dctx);
+               if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
+                       r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
+               else
+                       {
+                       EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx);
+                       if (!dctx)
+                               return 0;
+                       r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
+                       EVP_PKEY_CTX_free(dctx);
+                       }
                return r;
                }
        if (pctx->pmeth->signctx)
@@ -156,18 +160,29 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
                sctx = 0;
        if (sigret)
                {
-               EVP_MD_CTX tmp_ctx;
                unsigned char md[EVP_MAX_MD_SIZE];
                unsigned int mdlen;
-               EVP_MD_CTX_init(&tmp_ctx);
-               if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
-                       return 0;
-               if (sctx)
-                       r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
-                                       sigret, siglen, &tmp_ctx);
+               if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
+                       {
+                       if (sctx)
+                               r = ctx->pctx->pmeth->signctx(ctx->pctx,
+                                               sigret, siglen, ctx);
+                       else
+                               r = EVP_DigestFinal_ex(ctx, md, &mdlen);
+                       }
                else
-                       r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
-               EVP_MD_CTX_cleanup(&tmp_ctx);
+                       {
+                       EVP_MD_CTX tmp_ctx;
+                       EVP_MD_CTX_init(&tmp_ctx);
+                       if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
+                               return 0;
+                       if (sctx)
+                               r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
+                                               sigret, siglen, &tmp_ctx);
+                       else
+                               r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+                       EVP_MD_CTX_cleanup(&tmp_ctx);
+                       }
                if (sctx || !r)
                        return r;
                if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
@@ -192,7 +207,6 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
 
 int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t siglen)
        {
-       EVP_MD_CTX tmp_ctx;
        unsigned char md[EVP_MAX_MD_SIZE];
        int r;
        unsigned int mdlen;
@@ -202,17 +216,31 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t siglen)
                vctx = 1;
        else
                vctx = 0;
-       EVP_MD_CTX_init(&tmp_ctx);
-       if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
-               return -1;      
-       if (vctx)
+       if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
                {
-               r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx,
-                                       sig, siglen, &tmp_ctx);
+               if (vctx)
+                       {
+                       r = ctx->pctx->pmeth->verifyctx(ctx->pctx,
+                                               sig, siglen, ctx);
+                       }
+               else
+                       r = EVP_DigestFinal_ex(ctx, md, &mdlen);
                }
        else
-               r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
-       EVP_MD_CTX_cleanup(&tmp_ctx);
+               {
+               EVP_MD_CTX tmp_ctx;
+               EVP_MD_CTX_init(&tmp_ctx);
+               if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
+                       return -1;
+               if (vctx)
+                       {
+                       r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx,
+                                               sig, siglen, &tmp_ctx);
+                       }
+               else
+                       r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
+               EVP_MD_CTX_cleanup(&tmp_ctx);
+               }
        if (vctx || !r)
                return r;
        return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen);
index 8afb664306e908e896249f6a70bcbd6cdfe6c4e5..1889117d39ccce2aa822738da1496d1b71a98edd 100644 (file)
@@ -81,16 +81,26 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
        unsigned char m[EVP_MAX_MD_SIZE];
        unsigned int m_len;
        int i = 0,ok = 0,v;
-       EVP_MD_CTX tmp_ctx;
        EVP_PKEY_CTX *pkctx = NULL;
 
        *siglen=0;
-       EVP_MD_CTX_init(&tmp_ctx);
-       if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
-               goto err;  
-       if (!EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len))
-               goto err;
-       EVP_MD_CTX_cleanup(&tmp_ctx);
+       if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
+               {
+               if (!EVP_DigestFinal_ex(ctx, m, &m_len))
+                       goto err;
+               }
+       else
+               {
+               int rv;
+               EVP_MD_CTX tmp_ctx;
+               EVP_MD_CTX_init(&tmp_ctx);
+               rv = EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+               if (rv)
+                       rv = EVP_DigestFinal_ex(&tmp_ctx, m, &m_len);
+               EVP_MD_CTX_cleanup(&tmp_ctx);
+               if (!rv)
+                       return 0;
+               }
 
        if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
                {
@@ -133,7 +143,7 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
                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));
+       return ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
+               pkey->pkey.ptr);
        }
 
index c66d63ccf8597ebf1721551dfa1fb082c93d304e..a3df5dfc3d11b6d51784265a2a289b591bd339ab 100644 (file)
@@ -68,15 +68,25 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
        unsigned char m[EVP_MAX_MD_SIZE];
        unsigned int m_len;
        int i = 0,ok = 0,v;
-       EVP_MD_CTX tmp_ctx;
        EVP_PKEY_CTX *pkctx = NULL;
 
-       EVP_MD_CTX_init(&tmp_ctx);
-       if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
-               goto err;    
-       if (!EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len))
-               goto err;
-       EVP_MD_CTX_cleanup(&tmp_ctx);
+       if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
+               {
+               if (!EVP_DigestFinal_ex(ctx, m, &m_len))
+                       goto err;
+               }
+       else
+               {
+               int rv;
+               EVP_MD_CTX tmp_ctx;
+               EVP_MD_CTX_init(&tmp_ctx);
+               rv = EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+               if (rv)
+                       rv = EVP_DigestFinal_ex(&tmp_ctx, m, &m_len);
+               EVP_MD_CTX_cleanup(&tmp_ctx);
+               if (!rv)
+                       return 0;
+               }
 
        if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
                {