Support for digest signing and X931 in rsa_pkey_meth.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 9 Apr 2006 19:17:25 +0000 (19:17 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 9 Apr 2006 19:17:25 +0000 (19:17 +0000)
crypto/evp/evp.h
crypto/evp/evp_err.c
crypto/evp/pmeth_lib.c
crypto/rsa/rsa.h
crypto/rsa/rsa_err.c
crypto/rsa/rsa_pmeth.c
crypto/rsa/rsa_sign.c

index 07bcb50ad0f8edb2d0e436d7de908bb3e9bf18c5..e09c55377cd2d07ad9b9a000bf7df8fcd26c45cb 100644 (file)
@@ -914,6 +914,10 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
 #define EVP_PKEY_OP_ENCRYPT            8
 #define EVP_PKEY_OP_DECRYPT            9
 
 #define EVP_PKEY_OP_ENCRYPT            8
 #define EVP_PKEY_OP_DECRYPT            9
 
+#define EVP_PKEY_CTRL_MD_NID           1
+
+#define EVP_PKEY_ALG_CTRL              0x1000
+
 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
@@ -1024,6 +1028,7 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_EXPECTING_A_EC_KEY                        142
 #define EVP_R_INITIALIZATION_ERROR                      134
 #define EVP_R_INPUT_NOT_INITIALIZED                     111
 #define EVP_R_EXPECTING_A_EC_KEY                        142
 #define EVP_R_INITIALIZATION_ERROR                      134
 #define EVP_R_INPUT_NOT_INITIALIZED                     111
+#define EVP_R_INVALID_DIGEST                            152
 #define EVP_R_INVALID_KEY_LENGTH                        130
 #define EVP_R_INVALID_OPERATION                                 148
 #define EVP_R_IV_TOO_LARGE                              102
 #define EVP_R_INVALID_KEY_LENGTH                        130
 #define EVP_R_INVALID_OPERATION                                 148
 #define EVP_R_IV_TOO_LARGE                              102
index 702331a4a9f71b94ba322cdfa46d49284dcc6783..0f14fa8a7d86b47378f7687a04a0badb0324004a 100644 (file)
@@ -143,6 +143,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY)    ,"expecting a ec key"},
 {ERR_REASON(EVP_R_INITIALIZATION_ERROR)  ,"initialization error"},
 {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) ,"input not initialized"},
 {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY)    ,"expecting a ec key"},
 {ERR_REASON(EVP_R_INITIALIZATION_ERROR)  ,"initialization error"},
 {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) ,"input not initialized"},
+{ERR_REASON(EVP_R_INVALID_DIGEST)        ,"invalid digest"},
 {ERR_REASON(EVP_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(EVP_R_INVALID_OPERATION)     ,"invalid operation"},
 {ERR_REASON(EVP_R_IV_TOO_LARGE)          ,"iv too large"},
 {ERR_REASON(EVP_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(EVP_R_INVALID_OPERATION)     ,"invalid operation"},
 {ERR_REASON(EVP_R_IV_TOO_LARGE)          ,"iv too large"},
index 7c363956968e3f6b66330b6bb6da19a5d33c6d62..a705901c7068b7d1ed9e0f3764b928ff9422dfda 100644 (file)
@@ -179,5 +179,16 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
                EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
                return -2;
                }
                EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
                return -2;
                }
+       if (!strcmp(name, "digest"))
+               {
+               const EVP_MD *md;
+               if (!value || !(md = EVP_get_digestbyname(value)))
+                       {
+                       EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_DIGEST);
+                       return 0;
+                       }
+               return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_MD_NID,
+                                       EVP_MD_type(md), NULL);
+               }
        return ctx->pmeth->ctrl_str(ctx, name, value);
        }
        return ctx->pmeth->ctrl_str(ctx, name, value);
        }
index 09db1c88dedd784b322503884d972758d2bf0219..a7a06b4acbc78001dfe1a642b6a8f46aa853ad97 100644 (file)
@@ -196,7 +196,7 @@ struct rsa_st
        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, \
                                pad, NULL)
 
        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, \
                                pad, NULL)
 
-#define EVP_PKEY_CTRL_RSA_PADDING      1
+#define EVP_PKEY_CTRL_RSA_PADDING      (EVP_PKEY_ALG_CTRL + 1)
 
 #define RSA_PKCS1_PADDING      1
 #define RSA_SSLV23_PADDING     2
 
 #define RSA_PKCS1_PADDING      1
 #define RSA_SSLV23_PADDING     2
@@ -349,7 +349,9 @@ void ERR_load_RSA_strings(void);
 /* Error codes for the RSA functions. */
 
 /* Function codes. */
 /* Error codes for the RSA functions. */
 
 /* Function codes. */
+#define RSA_F_CHECK_PADDING_NID                                 140
 #define RSA_F_MEMORY_LOCK                               100
 #define RSA_F_MEMORY_LOCK                               100
+#define RSA_F_PKEY_RSA_VERIFYRECOVER                    141
 #define RSA_F_RSA_BUILTIN_KEYGEN                        129
 #define RSA_F_RSA_CHECK_KEY                             123
 #define RSA_F_RSA_EAY_PRIVATE_DECRYPT                   101
 #define RSA_F_RSA_BUILTIN_KEYGEN                        129
 #define RSA_F_RSA_CHECK_KEY                             123
 #define RSA_F_RSA_EAY_PRIVATE_DECRYPT                   101
@@ -409,10 +411,13 @@ void ERR_load_RSA_strings(void);
 #define RSA_R_DMQ1_NOT_CONGRUENT_TO_D                   125
 #define RSA_R_D_E_NOT_CONGRUENT_TO_1                    123
 #define RSA_R_FIRST_OCTET_INVALID                       133
 #define RSA_R_DMQ1_NOT_CONGRUENT_TO_D                   125
 #define RSA_R_D_E_NOT_CONGRUENT_TO_1                    123
 #define RSA_R_FIRST_OCTET_INVALID                       133
+#define RSA_R_INVALID_DIGEST                            105
 #define RSA_R_INVALID_HEADER                            137
 #define RSA_R_INVALID_MESSAGE_LENGTH                    131
 #define RSA_R_INVALID_PADDING                           138
 #define RSA_R_INVALID_HEADER                            137
 #define RSA_R_INVALID_MESSAGE_LENGTH                    131
 #define RSA_R_INVALID_PADDING                           138
+#define RSA_R_INVALID_PADDING_MODE                      141
 #define RSA_R_INVALID_TRAILER                           139
 #define RSA_R_INVALID_TRAILER                           139
+#define RSA_R_INVALID_X931_DIGEST                       142
 #define RSA_R_IQMP_NOT_INVERSE_OF_Q                     126
 #define RSA_R_KEY_SIZE_TOO_SMALL                        120
 #define RSA_R_LAST_OCTET_INVALID                        134
 #define RSA_R_IQMP_NOT_INVERSE_OF_Q                     126
 #define RSA_R_KEY_SIZE_TOO_SMALL                        120
 #define RSA_R_LAST_OCTET_INVALID                        134
index fc43065317b4e0f110fb689ac9b6494c8e8076b2..f403d0cedf134bb15e0325f133592247609d021e 100644 (file)
@@ -70,7 +70,9 @@
 
 static ERR_STRING_DATA RSA_str_functs[]=
        {
 
 static ERR_STRING_DATA RSA_str_functs[]=
        {
+{ERR_FUNC(RSA_F_CHECK_PADDING_NID),    "CHECK_PADDING_NID"},
 {ERR_FUNC(RSA_F_MEMORY_LOCK),  "MEMORY_LOCK"},
 {ERR_FUNC(RSA_F_MEMORY_LOCK),  "MEMORY_LOCK"},
+{ERR_FUNC(RSA_F_PKEY_RSA_VERIFYRECOVER),       "PKEY_RSA_VERIFYRECOVER"},
 {ERR_FUNC(RSA_F_RSA_BUILTIN_KEYGEN),   "RSA_BUILTIN_KEYGEN"},
 {ERR_FUNC(RSA_F_RSA_CHECK_KEY),        "RSA_check_key"},
 {ERR_FUNC(RSA_F_RSA_EAY_PRIVATE_DECRYPT),      "RSA_EAY_PRIVATE_DECRYPT"},
 {ERR_FUNC(RSA_F_RSA_BUILTIN_KEYGEN),   "RSA_BUILTIN_KEYGEN"},
 {ERR_FUNC(RSA_F_RSA_CHECK_KEY),        "RSA_check_key"},
 {ERR_FUNC(RSA_F_RSA_EAY_PRIVATE_DECRYPT),      "RSA_EAY_PRIVATE_DECRYPT"},
@@ -100,7 +102,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23),     "RSA_padding_check_SSLv23"},
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931),       "RSA_padding_check_X931"},
 {ERR_FUNC(RSA_F_RSA_PRINT),    "RSA_print"},
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23),     "RSA_padding_check_SSLv23"},
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931),       "RSA_padding_check_X931"},
 {ERR_FUNC(RSA_F_RSA_PRINT),    "RSA_print"},
-{ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"},
+{ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_PRINT_FP"},
 {ERR_FUNC(RSA_F_RSA_PRIV_DECODE),      "RSA_PRIV_DECODE"},
 {ERR_FUNC(RSA_F_RSA_PRIV_ENCODE),      "RSA_PRIV_ENCODE"},
 {ERR_FUNC(RSA_F_RSA_PUB_DECODE),       "RSA_PUB_DECODE"},
 {ERR_FUNC(RSA_F_RSA_PRIV_DECODE),      "RSA_PRIV_DECODE"},
 {ERR_FUNC(RSA_F_RSA_PRIV_ENCODE),      "RSA_PRIV_ENCODE"},
 {ERR_FUNC(RSA_F_RSA_PUB_DECODE),       "RSA_PUB_DECODE"},
@@ -133,10 +135,13 @@ static ERR_STRING_DATA RSA_str_reasons[]=
 {ERR_REASON(RSA_R_DMQ1_NOT_CONGRUENT_TO_D),"dmq1 not congruent to d"},
 {ERR_REASON(RSA_R_D_E_NOT_CONGRUENT_TO_1),"d e not congruent to 1"},
 {ERR_REASON(RSA_R_FIRST_OCTET_INVALID)   ,"first octet invalid"},
 {ERR_REASON(RSA_R_DMQ1_NOT_CONGRUENT_TO_D),"dmq1 not congruent to d"},
 {ERR_REASON(RSA_R_D_E_NOT_CONGRUENT_TO_1),"d e not congruent to 1"},
 {ERR_REASON(RSA_R_FIRST_OCTET_INVALID)   ,"first octet invalid"},
+{ERR_REASON(RSA_R_INVALID_DIGEST)        ,"invalid digest"},
 {ERR_REASON(RSA_R_INVALID_HEADER)        ,"invalid header"},
 {ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"},
 {ERR_REASON(RSA_R_INVALID_PADDING)       ,"invalid padding"},
 {ERR_REASON(RSA_R_INVALID_HEADER)        ,"invalid header"},
 {ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"},
 {ERR_REASON(RSA_R_INVALID_PADDING)       ,"invalid padding"},
+{ERR_REASON(RSA_R_INVALID_PADDING_MODE)  ,"invalid padding mode"},
 {ERR_REASON(RSA_R_INVALID_TRAILER)       ,"invalid trailer"},
 {ERR_REASON(RSA_R_INVALID_TRAILER)       ,"invalid trailer"},
+{ERR_REASON(RSA_R_INVALID_X931_DIGEST)   ,"invalid x931 digest"},
 {ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"},
 {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL)    ,"key size too small"},
 {ERR_REASON(RSA_R_LAST_OCTET_INVALID)    ,"last octet invalid"},
 {ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"},
 {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL)    ,"key size too small"},
 {ERR_REASON(RSA_R_LAST_OCTET_INVALID)    ,"last octet invalid"},
index 3552fce8d9015f674ccad56d1cfcd3505ce347d0..a93adb75b9253c737cef7d46a165d99a6b19ea35 100644 (file)
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
 #include <openssl/rsa.h>
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
 #include <openssl/rsa.h>
+#include <openssl/evp.h>
 #include "evp_locl.h"
 
 #include "evp_locl.h"
 
+extern int int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
+               unsigned char *rm, unsigned int *prm_len,
+               unsigned char *sigbuf, unsigned int siglen,
+               RSA *rsa);
+
 /* RSA pkey context structure */
 
 typedef struct
 /* RSA pkey context structure */
 
 typedef struct
@@ -71,6 +77,10 @@ typedef struct
        BIGNUM *pub_exp;
        /* RSA padding mode */
        int pad_mode;
        BIGNUM *pub_exp;
        /* RSA padding mode */
        int pad_mode;
+       /* nid for message digest */
+       int md_nid;
+       /* Temp buffer */
+       unsigned char *tbuf;
        } RSA_PKEY_CTX;
 
 static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
        } RSA_PKEY_CTX;
 
 static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
@@ -82,7 +92,21 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
        rctx->nbits = 1024;
        rctx->pub_exp = NULL;
        rctx->pad_mode = RSA_PKCS1_PADDING;
        rctx->nbits = 1024;
        rctx->pub_exp = NULL;
        rctx->pad_mode = RSA_PKCS1_PADDING;
+       rctx->md_nid = NID_undef;
+       rctx->tbuf = NULL;
+
        ctx->data = rctx;
        ctx->data = rctx;
+       
+       return 1;
+       }
+
+static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
+       {
+       if (ctx->tbuf)
+               return 1;
+       ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
+       if (!ctx->tbuf)
+               return 0;
        return 1;
        }
 
        return 1;
        }
 
@@ -102,7 +126,31 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
-       ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
+
+       if (rctx->md_nid != NID_undef)
+               {
+
+               if (rctx->pad_mode == RSA_X931_PADDING)
+                       {
+                       if (!setup_tbuf(rctx, ctx))
+                               return -1;
+                       memcpy(rctx->tbuf, tbs, tbslen);
+                       rctx->tbuf[tbslen] = RSA_X931_hash_id(rctx->md_nid);
+                       ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
+                                               sig, ctx->pkey->pkey.rsa,
+                                               RSA_X931_PADDING);
+                       }
+               else if (rctx->pad_mode == RSA_PKCS1_PADDING)
+                       {
+                       unsigned int sltmp;
+                       ret = RSA_sign(rctx->md_nid, tbs, tbslen, sig, &sltmp,
+                                                       ctx->pkey->pkey.rsa);
+                       }
+               else
+                       return -1;
+               }
+       else
+               ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
@@ -117,7 +165,38 @@ static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
        {
        int ret;
        RSA_PKEY_CTX *rctx = ctx->data;
-       ret = RSA_public_decrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
+
+       if (rctx->md_nid != NID_undef)
+               {
+               if (rctx->pad_mode == RSA_X931_PADDING)
+                       {
+                       if (!setup_tbuf(rctx, ctx))
+                               return -1;
+                       ret = RSA_private_encrypt(tbslen, tbs,
+                                               rctx->tbuf, ctx->pkey->pkey.rsa,
+                                               RSA_X931_PADDING);
+                       if (ret < 1)
+                               return 0;
+                       if (rctx->tbuf[ret] != RSA_X931_hash_id(rctx->md_nid))
+                               {
+                               RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
+                                               RSA_R_ALGORITHM_MISMATCH);
+                               return 0;
+                               }
+                       ret--;
+                       memcpy(sig, rctx->tbuf, ret);
+                       }
+               else if (rctx->pad_mode == RSA_PKCS1_PADDING)
+                       {
+                       unsigned int sltmp;
+                       ret = int_rsa_verify(rctx->md_nid, NULL, 0, sig, &sltmp,
+                                       tbs, tbslen, ctx->pkey->pkey.rsa);
+                       }
+               else
+                       return -1;
+               }
+       else
+               ret = RSA_public_decrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
                                                        rctx->pad_mode);
        if (ret < 0)
                return ret;
@@ -151,23 +230,55 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
        return 1;
        }
 
        return 1;
        }
 
+static int check_padding_nid(int nid, int padding)
+       {
+       if (nid == NID_undef)
+               return 1;
+       if (padding == RSA_NO_PADDING)
+               {
+               RSAerr(RSA_F_CHECK_PADDING_NID, RSA_R_INVALID_PADDING_MODE);
+               return 0;
+               }
+
+       if (padding == RSA_X931_PADDING)
+               {
+               if (RSA_X931_hash_id(nid) == -1)
+                       {
+                       RSAerr(RSA_F_CHECK_PADDING_NID,
+                                               RSA_R_INVALID_X931_DIGEST);
+                       return 0;
+                       }
+               return 1;
+               }
+
+       return 1;
+       }
+                       
+
 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
        {
        RSA_PKEY_CTX *rctx = ctx->data;
        switch (type)
                {
 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
        {
        RSA_PKEY_CTX *rctx = ctx->data;
        switch (type)
                {
-
                case EVP_PKEY_CTRL_RSA_PADDING:
                /* TODO: add PSS support */
                if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_X931_PADDING))
                        {
                        if (ctx->operation == EVP_PKEY_OP_KEYGEN)
                                return -2;
                case EVP_PKEY_CTRL_RSA_PADDING:
                /* TODO: add PSS support */
                if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_X931_PADDING))
                        {
                        if (ctx->operation == EVP_PKEY_OP_KEYGEN)
                                return -2;
+                       if (!check_padding_nid(rctx->md_nid, p1))
+                               return 0;
                        rctx->pad_mode = p1;
                        return 1;
                        }
                return -2;
 
                        rctx->pad_mode = p1;
                        return 1;
                        }
                return -2;
 
+               case EVP_PKEY_CTRL_MD_NID:
+               if (!check_padding_nid(p1, rctx->pad_mode))
+                       return 0;
+               rctx->md_nid = p1;
+               return 1;
+
                default:
                return -2;
 
                default:
                return -2;
 
index 230ec6d7ea2a981ead6a4a8fa45d1f38128298e5..91f03406d01dc9a67ed6ecbb682cedff9f310318 100644 (file)
@@ -142,8 +142,10 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
        return(ret);
        }
 
        return(ret);
        }
 
-int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
-            unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
+int int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
+               unsigned char *rm, unsigned int *prm_len,
+               unsigned char *sigbuf, unsigned int siglen,
+               RSA *rsa)
        {
        int i,ret=0,sigtype;
        unsigned char *s;
        {
        int i,ret=0,sigtype;
        unsigned char *s;
@@ -155,10 +157,14 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
                return(0);
                }
 
                return(0);
                }
 
-       if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
+       if((dtype == NID_md5_sha1) && rm)
                {
                {
-               return rsa->meth->rsa_verify(dtype, m, m_len,
-                       sigbuf, siglen, rsa);
+               i = RSA_public_decrypt((int)siglen,
+                                       sigbuf,rm,rsa,RSA_PKCS1_PADDING);
+               if (i <= 0)
+                       return 0;
+               *prm_len = i;
+               return 1;
                }
 
        s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen);
                }
 
        s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen);
@@ -212,7 +218,13 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
                                goto err;
                                }
                        }
                                goto err;
                                }
                        }
-               if (    ((unsigned int)sig->digest->length != m_len) ||
+               if (rm)
+                       {
+                       memcpy(rm, sig->digest->data, sig->digest->length);
+                       *prm_len = sig->digest->length;
+                       ret = 1;
+                       }
+               else if (((unsigned int)sig->digest->length != m_len) ||
                        (memcmp(m,sig->digest->data,m_len) != 0))
                        {
                        RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
                        (memcmp(m,sig->digest->data,m_len) != 0))
                        {
                        RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
@@ -230,3 +242,16 @@ err:
        return(ret);
        }
 
        return(ret);
        }
 
+int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
+               unsigned char *sigbuf, unsigned int siglen,
+               RSA *rsa)
+       {
+
+       if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
+               {
+               return rsa->meth->rsa_verify(dtype, m, m_len,
+                       sigbuf, siglen, rsa);
+               }
+
+       return int_rsa_verify(dtype, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
+       }