X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frsa%2Frsa_sign.c;h=031246055b045d4ae0c18ee298ca8687d28b433c;hp=1d47a3139c1c6390bcf0e836ba447fc9c20d962c;hb=6d23cf97443bfedf755341b4f2d0d7fce254e020;hpb=3b30121bd989bc79b8cb4a5440f55acf7442b3d2 diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 1d47a3139c..031246055b 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -62,12 +62,13 @@ #include #include #include +#include "rsa_locl.h" /* Size of an SSL signature: MD5+SHA1 */ #define SSL_SIG_LENGTH 36 int RSA_sign(int type, const unsigned char *m, unsigned int m_len, - unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + unsigned char *sigret, unsigned int *siglen, RSA *rsa) { X509_SIG sig; ASN1_TYPE parameter; @@ -76,7 +77,7 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len, const unsigned char *s = NULL; X509_ALGOR algor; ASN1_OCTET_STRING digest; - if(rsa->flags & RSA_FLAG_SIGN_VER) + if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) { return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); @@ -142,49 +143,108 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len, return(ret); } -int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len, - unsigned char *sigbuf, unsigned int siglen, const RSA *rsa) +/* + * Check DigestInfo structure does not contain extraneous data by reencoding + * using DER and checking encoding against original. + */ +static int rsa_check_digestinfo(X509_SIG *sig, const unsigned char *dinfo, int dinfolen) + { + unsigned char *der = NULL; + int derlen; + int ret = 0; + derlen = i2d_X509_SIG(sig, &der); + if (derlen <= 0) + return 0; + if (derlen == dinfolen && !memcmp(dinfo, der, derlen)) + ret = 1; + OPENSSL_cleanse(der, derlen); + OPENSSL_free(der); + return ret; + } + +int int_rsa_verify(int dtype, const unsigned char *m, + unsigned int m_len, + unsigned char *rm, size_t *prm_len, + const unsigned char *sigbuf, size_t siglen, + RSA *rsa) { int i,ret=0,sigtype; - unsigned char *p,*s; + unsigned char *s; X509_SIG *sig=NULL; if (siglen != (unsigned int)RSA_size(rsa)) { - RSAerr(RSA_F_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH); + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH); return(0); } - if(rsa->flags & RSA_FLAG_SIGN_VER) + 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); if (s == NULL) { - RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE); + RSAerr(RSA_F_INT_RSA_VERIFY,ERR_R_MALLOC_FAILURE); goto err; } if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) { - RSAerr(RSA_F_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH); - return(0); + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH); + goto err; } i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING); if (i <= 0) goto err; + /* Oddball MDC2 case: signature can be OCTET STRING. + * check for correct tag and length octets. + */ + if (dtype == NID_mdc2 && i == 18 && s[0] == 0x04 && s[1] == 0x10) + { + if (rm) + { + memcpy(rm, s + 2, 16); + *prm_len = 16; + ret = 1; + } + else if(memcmp(m, s + 2, 16)) + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + else + ret = 1; + } /* Special case: SSL signature */ if(dtype == NID_md5_sha1) { if((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH)) - RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE); else ret = 1; } else { - p=s; + const unsigned char *p=s; sig=d2i_X509_SIG(NULL,&p,(long)i); if (sig == NULL) goto err; + + /* Excess data can be used to create forgeries */ + if(p != s+i || !rsa_check_digestinfo(sig, s, i)) + { + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + goto err; + } + + /* Parameters to the signature algorithm can also be used to + create forgeries */ + if(sig->algor->parameter + && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) + { + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE); + goto err; + } + sigtype=OBJ_obj2nid(sig->algor->algorithm); @@ -201,29 +261,60 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len, (sigtype == NID_md2WithRSAEncryption))) { /* ok, we will let it through */ -#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) +#if !defined(OPENSSL_NO_STDIO) fprintf(stderr,"signature has problems, re-make with post SSLeay045\n"); #endif } else { - RSAerr(RSA_F_RSA_VERIFY, + RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH); goto err; } } - if ( ((unsigned int)sig->digest->length != m_len) || + if (rm) + { + const EVP_MD *md; + md = EVP_get_digestbynid(dtype); + if (md && (EVP_MD_size(md) != sig->digest->length)) + RSAerr(RSA_F_INT_RSA_VERIFY, + RSA_R_INVALID_DIGEST_LENGTH); + else + { + 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); + RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE); } else ret=1; } err: if (sig != NULL) X509_SIG_free(sig); - OPENSSL_cleanse(s,(unsigned int)siglen); - OPENSSL_free(s); + if (s != NULL) + { + OPENSSL_cleanse(s,(unsigned int)siglen); + OPENSSL_free(s); + } return(ret); } +int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len, + const 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); + }