xref: /freebsd/crypto/openssl/crypto/rsa/rsa_sign.c (revision 80815a778ec9d0fc06b0e000c4608da4b4f3a711)
197b2ed56SKris Kennaway /* crypto/rsa/rsa_sign.c */
297b2ed56SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
397b2ed56SKris Kennaway  * All rights reserved.
497b2ed56SKris Kennaway  *
597b2ed56SKris Kennaway  * This package is an SSL implementation written
697b2ed56SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
797b2ed56SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
897b2ed56SKris Kennaway  *
997b2ed56SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1097b2ed56SKris Kennaway  * the following conditions are aheared to.  The following conditions
1197b2ed56SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1297b2ed56SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1397b2ed56SKris Kennaway  * included with this distribution is covered by the same copyright terms
1497b2ed56SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1597b2ed56SKris Kennaway  *
1697b2ed56SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1797b2ed56SKris Kennaway  * the code are not to be removed.
1897b2ed56SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
1997b2ed56SKris Kennaway  * as the author of the parts of the library used.
2097b2ed56SKris Kennaway  * This can be in the form of a textual message at program startup or
2197b2ed56SKris Kennaway  * in documentation (online or textual) provided with the package.
2297b2ed56SKris Kennaway  *
2397b2ed56SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2497b2ed56SKris Kennaway  * modification, are permitted provided that the following conditions
2597b2ed56SKris Kennaway  * are met:
2697b2ed56SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2797b2ed56SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
2897b2ed56SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
2997b2ed56SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3097b2ed56SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3197b2ed56SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3297b2ed56SKris Kennaway  *    must display the following acknowledgement:
3397b2ed56SKris Kennaway  *    "This product includes cryptographic software written by
3497b2ed56SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3597b2ed56SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3697b2ed56SKris Kennaway  *    being used are not cryptographic related :-).
3797b2ed56SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
3897b2ed56SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
3997b2ed56SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4097b2ed56SKris Kennaway  *
4197b2ed56SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4297b2ed56SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4397b2ed56SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4497b2ed56SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4597b2ed56SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4697b2ed56SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4797b2ed56SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4897b2ed56SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4997b2ed56SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5097b2ed56SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5197b2ed56SKris Kennaway  * SUCH DAMAGE.
5297b2ed56SKris Kennaway  *
5397b2ed56SKris Kennaway  * The licence and distribution terms for any publically available version or
5497b2ed56SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5597b2ed56SKris Kennaway  * copied and put under another distribution licence
5697b2ed56SKris Kennaway  * [including the GNU Public Licence.]
5797b2ed56SKris Kennaway  */
5897b2ed56SKris Kennaway 
5997b2ed56SKris Kennaway #include <stdio.h>
6097b2ed56SKris Kennaway #include "cryptlib.h"
6197b2ed56SKris Kennaway #include <openssl/bn.h>
6297b2ed56SKris Kennaway #include <openssl/rsa.h>
6397b2ed56SKris Kennaway #include <openssl/objects.h>
6497b2ed56SKris Kennaway #include <openssl/x509.h>
651f13597dSJung-uk Kim #include "rsa_locl.h"
6697b2ed56SKris Kennaway 
67f579bf8eSKris Kennaway /* Size of an SSL signature: MD5+SHA1 */
68f579bf8eSKris Kennaway #define SSL_SIG_LENGTH  36
69f579bf8eSKris Kennaway 
705c87c606SMark Murray int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
7197b2ed56SKris Kennaway              unsigned char *sigret, unsigned int *siglen, RSA *rsa)
7297b2ed56SKris Kennaway {
7397b2ed56SKris Kennaway     X509_SIG sig;
7497b2ed56SKris Kennaway     ASN1_TYPE parameter;
7597b2ed56SKris Kennaway     int i, j, ret = 1;
765c87c606SMark Murray     unsigned char *p, *tmps = NULL;
775c87c606SMark Murray     const unsigned char *s = NULL;
7897b2ed56SKris Kennaway     X509_ALGOR algor;
7997b2ed56SKris Kennaway     ASN1_OCTET_STRING digest;
801f13597dSJung-uk Kim #ifdef OPENSSL_FIPS
811f13597dSJung-uk Kim     if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
826f9291ceSJung-uk Kim         && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
831f13597dSJung-uk Kim         RSAerr(RSA_F_RSA_SIGN, RSA_R_NON_FIPS_RSA_METHOD);
841f13597dSJung-uk Kim         return 0;
851f13597dSJung-uk Kim     }
861f13597dSJung-uk Kim #endif
876f9291ceSJung-uk Kim     if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
886f9291ceSJung-uk Kim         return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
8950ef0093SJacques Vidrine     }
90f579bf8eSKris Kennaway     /* Special case: SSL signature, just check the length */
91f579bf8eSKris Kennaway     if (type == NID_md5_sha1) {
92f579bf8eSKris Kennaway         if (m_len != SSL_SIG_LENGTH) {
93f579bf8eSKris Kennaway             RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH);
94f579bf8eSKris Kennaway             return (0);
95f579bf8eSKris Kennaway         }
96f579bf8eSKris Kennaway         i = SSL_SIG_LENGTH;
97f579bf8eSKris Kennaway         s = m;
98f579bf8eSKris Kennaway     } else {
9997b2ed56SKris Kennaway         sig.algor = &algor;
10097b2ed56SKris Kennaway         sig.algor->algorithm = OBJ_nid2obj(type);
1016f9291ceSJung-uk Kim         if (sig.algor->algorithm == NULL) {
10297b2ed56SKris Kennaway             RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
10397b2ed56SKris Kennaway             return (0);
10497b2ed56SKris Kennaway         }
1056f9291ceSJung-uk Kim         if (sig.algor->algorithm->length == 0) {
1066f9291ceSJung-uk Kim             RSAerr(RSA_F_RSA_SIGN,
1076f9291ceSJung-uk Kim                    RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
10897b2ed56SKris Kennaway             return (0);
10997b2ed56SKris Kennaway         }
11097b2ed56SKris Kennaway         parameter.type = V_ASN1_NULL;
11197b2ed56SKris Kennaway         parameter.value.ptr = NULL;
11297b2ed56SKris Kennaway         sig.algor->parameter = &parameter;
11397b2ed56SKris Kennaway 
11497b2ed56SKris Kennaway         sig.digest = &digest;
1155c87c606SMark Murray         sig.digest->data = (unsigned char *)m; /* TMP UGLY CAST */
11697b2ed56SKris Kennaway         sig.digest->length = m_len;
11797b2ed56SKris Kennaway 
11897b2ed56SKris Kennaway         i = i2d_X509_SIG(&sig, NULL);
119f579bf8eSKris Kennaway     }
12097b2ed56SKris Kennaway     j = RSA_size(rsa);
1216f9291ceSJung-uk Kim     if (i > (j - RSA_PKCS1_PADDING_SIZE)) {
12297b2ed56SKris Kennaway         RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
12397b2ed56SKris Kennaway         return (0);
12497b2ed56SKris Kennaway     }
125f579bf8eSKris Kennaway     if (type != NID_md5_sha1) {
1265c87c606SMark Murray         tmps = (unsigned char *)OPENSSL_malloc((unsigned int)j + 1);
1276f9291ceSJung-uk Kim         if (tmps == NULL) {
12897b2ed56SKris Kennaway             RSAerr(RSA_F_RSA_SIGN, ERR_R_MALLOC_FAILURE);
12997b2ed56SKris Kennaway             return (0);
13097b2ed56SKris Kennaway         }
1315c87c606SMark Murray         p = tmps;
13297b2ed56SKris Kennaway         i2d_X509_SIG(&sig, &p);
1335c87c606SMark Murray         s = tmps;
134f579bf8eSKris Kennaway     }
13597b2ed56SKris Kennaway     i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING);
13697b2ed56SKris Kennaway     if (i <= 0)
13797b2ed56SKris Kennaway         ret = 0;
13897b2ed56SKris Kennaway     else
13997b2ed56SKris Kennaway         *siglen = i;
14097b2ed56SKris Kennaway 
141f579bf8eSKris Kennaway     if (type != NID_md5_sha1) {
1425c87c606SMark Murray         OPENSSL_cleanse(tmps, (unsigned int)j + 1);
1435c87c606SMark Murray         OPENSSL_free(tmps);
144f579bf8eSKris Kennaway     }
14597b2ed56SKris Kennaway     return (ret);
14697b2ed56SKris Kennaway }
14797b2ed56SKris Kennaway 
148fa5fddf1SJung-uk Kim /*
149fa5fddf1SJung-uk Kim  * Check DigestInfo structure does not contain extraneous data by reencoding
150fa5fddf1SJung-uk Kim  * using DER and checking encoding against original.
151fa5fddf1SJung-uk Kim  */
1526f9291ceSJung-uk Kim static int rsa_check_digestinfo(X509_SIG *sig, const unsigned char *dinfo,
1536f9291ceSJung-uk Kim                                 int dinfolen)
154fa5fddf1SJung-uk Kim {
155fa5fddf1SJung-uk Kim     unsigned char *der = NULL;
156fa5fddf1SJung-uk Kim     int derlen;
157fa5fddf1SJung-uk Kim     int ret = 0;
158fa5fddf1SJung-uk Kim     derlen = i2d_X509_SIG(sig, &der);
159fa5fddf1SJung-uk Kim     if (derlen <= 0)
160fa5fddf1SJung-uk Kim         return 0;
161fa5fddf1SJung-uk Kim     if (derlen == dinfolen && !memcmp(dinfo, der, derlen))
162fa5fddf1SJung-uk Kim         ret = 1;
163fa5fddf1SJung-uk Kim     OPENSSL_cleanse(der, derlen);
164fa5fddf1SJung-uk Kim     OPENSSL_free(der);
165fa5fddf1SJung-uk Kim     return ret;
166fa5fddf1SJung-uk Kim }
167fa5fddf1SJung-uk Kim 
1681f13597dSJung-uk Kim int int_rsa_verify(int dtype, const unsigned char *m,
1691f13597dSJung-uk Kim                    unsigned int m_len,
1701f13597dSJung-uk Kim                    unsigned char *rm, size_t *prm_len,
1716f9291ceSJung-uk Kim                    const unsigned char *sigbuf, size_t siglen, RSA *rsa)
17297b2ed56SKris Kennaway {
17397b2ed56SKris Kennaway     int i, ret = 0, sigtype;
1743b4e3dcbSSimon L. B. Nielsen     unsigned char *s;
17597b2ed56SKris Kennaway     X509_SIG *sig = NULL;
17697b2ed56SKris Kennaway 
1771f13597dSJung-uk Kim #ifdef OPENSSL_FIPS
1781f13597dSJung-uk Kim     if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
1796f9291ceSJung-uk Kim         && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
1801f13597dSJung-uk Kim         RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_NON_FIPS_RSA_METHOD);
1811f13597dSJung-uk Kim         return 0;
1821f13597dSJung-uk Kim     }
1831f13597dSJung-uk Kim #endif
1841f13597dSJung-uk Kim 
1856f9291ceSJung-uk Kim     if (siglen != (unsigned int)RSA_size(rsa)) {
1861f13597dSJung-uk Kim         RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
18797b2ed56SKris Kennaway         return (0);
18897b2ed56SKris Kennaway     }
18997b2ed56SKris Kennaway 
1906f9291ceSJung-uk Kim     if ((dtype == NID_md5_sha1) && rm) {
1911f13597dSJung-uk Kim         i = RSA_public_decrypt((int)siglen,
1921f13597dSJung-uk Kim                                sigbuf, rm, rsa, RSA_PKCS1_PADDING);
1931f13597dSJung-uk Kim         if (i <= 0)
1941f13597dSJung-uk Kim             return 0;
1951f13597dSJung-uk Kim         *prm_len = i;
1961f13597dSJung-uk Kim         return 1;
19750ef0093SJacques Vidrine     }
198f579bf8eSKris Kennaway 
199ddd58736SKris Kennaway     s = (unsigned char *)OPENSSL_malloc((unsigned int)siglen);
2006f9291ceSJung-uk Kim     if (s == NULL) {
2011f13597dSJung-uk Kim         RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
20297b2ed56SKris Kennaway         goto err;
20397b2ed56SKris Kennaway     }
2041f13597dSJung-uk Kim     if ((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH)) {
2051f13597dSJung-uk Kim         RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
2063b4e3dcbSSimon L. B. Nielsen         goto err;
207f579bf8eSKris Kennaway     }
20897b2ed56SKris Kennaway     i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);
20997b2ed56SKris Kennaway 
2106f9291ceSJung-uk Kim     if (i <= 0)
2116f9291ceSJung-uk Kim         goto err;
2126f9291ceSJung-uk Kim     /*
2136f9291ceSJung-uk Kim      * Oddball MDC2 case: signature can be OCTET STRING. check for correct
2146f9291ceSJung-uk Kim      * tag and length octets.
2151f13597dSJung-uk Kim      */
2166f9291ceSJung-uk Kim     if (dtype == NID_mdc2 && i == 18 && s[0] == 0x04 && s[1] == 0x10) {
2176f9291ceSJung-uk Kim         if (rm) {
2181f13597dSJung-uk Kim             memcpy(rm, s + 2, 16);
2191f13597dSJung-uk Kim             *prm_len = 16;
2201f13597dSJung-uk Kim             ret = 1;
221*80815a77SJung-uk Kim         } else if (memcmp(m, s + 2, 16)) {
2221f13597dSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
223*80815a77SJung-uk Kim         } else {
2241f13597dSJung-uk Kim             ret = 1;
2251f13597dSJung-uk Kim         }
226*80815a77SJung-uk Kim     } else if (dtype == NID_md5_sha1) {
227f579bf8eSKris Kennaway         /* Special case: SSL signature */
228f579bf8eSKris Kennaway         if ((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH))
2291f13597dSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
2306f9291ceSJung-uk Kim         else
2316f9291ceSJung-uk Kim             ret = 1;
232f579bf8eSKris Kennaway     } else {
2333b4e3dcbSSimon L. B. Nielsen         const unsigned char *p = s;
23497b2ed56SKris Kennaway         sig = d2i_X509_SIG(NULL, &p, (long)i);
23597b2ed56SKris Kennaway 
2366f9291ceSJung-uk Kim         if (sig == NULL)
2376f9291ceSJung-uk Kim             goto err;
238c800238eSSimon L. B. Nielsen 
239c800238eSSimon L. B. Nielsen         /* Excess data can be used to create forgeries */
2406f9291ceSJung-uk Kim         if (p != s + i || !rsa_check_digestinfo(sig, s, i)) {
2411f13597dSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
242c800238eSSimon L. B. Nielsen             goto err;
243c800238eSSimon L. B. Nielsen         }
244c800238eSSimon L. B. Nielsen 
2456f9291ceSJung-uk Kim         /*
2466f9291ceSJung-uk Kim          * Parameters to the signature algorithm can also be used to create
2476f9291ceSJung-uk Kim          * forgeries
2486f9291ceSJung-uk Kim          */
249c800238eSSimon L. B. Nielsen         if (sig->algor->parameter
2506f9291ceSJung-uk Kim             && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) {
2511f13597dSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
252c800238eSSimon L. B. Nielsen             goto err;
253c800238eSSimon L. B. Nielsen         }
254c800238eSSimon L. B. Nielsen 
25597b2ed56SKris Kennaway         sigtype = OBJ_obj2nid(sig->algor->algorithm);
25697b2ed56SKris Kennaway 
25797b2ed56SKris Kennaway #ifdef RSA_DEBUG
258f579bf8eSKris Kennaway         /* put a backward compatibility flag in EAY */
25997b2ed56SKris Kennaway         fprintf(stderr, "in(%s) expect(%s)\n", OBJ_nid2ln(sigtype),
26097b2ed56SKris Kennaway                 OBJ_nid2ln(dtype));
26197b2ed56SKris Kennaway #endif
2626f9291ceSJung-uk Kim         if (sigtype != dtype) {
2636f9291ceSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH);
26497b2ed56SKris Kennaway             goto err;
26597b2ed56SKris Kennaway         }
2666f9291ceSJung-uk Kim         if (rm) {
2671f13597dSJung-uk Kim             const EVP_MD *md;
2681f13597dSJung-uk Kim             md = EVP_get_digestbynid(dtype);
2691f13597dSJung-uk Kim             if (md && (EVP_MD_size(md) != sig->digest->length))
2706f9291ceSJung-uk Kim                 RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
2716f9291ceSJung-uk Kim             else {
2726f9291ceSJung-uk Kim                 memcpy(rm, sig->digest->data, sig->digest->length);
2731f13597dSJung-uk Kim                 *prm_len = sig->digest->length;
2741f13597dSJung-uk Kim                 ret = 1;
2751f13597dSJung-uk Kim             }
2766f9291ceSJung-uk Kim         } else if (((unsigned int)sig->digest->length != m_len) ||
2776f9291ceSJung-uk Kim                    (memcmp(m, sig->digest->data, m_len) != 0)) {
2781f13597dSJung-uk Kim             RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
2796f9291ceSJung-uk Kim         } else
28097b2ed56SKris Kennaway             ret = 1;
281f579bf8eSKris Kennaway     }
28297b2ed56SKris Kennaway  err:
2836f9291ceSJung-uk Kim     if (sig != NULL)
2846f9291ceSJung-uk Kim         X509_SIG_free(sig);
2856f9291ceSJung-uk Kim     if (s != NULL) {
2865c87c606SMark Murray         OPENSSL_cleanse(s, (unsigned int)siglen);
287ddd58736SKris Kennaway         OPENSSL_free(s);
2883b4e3dcbSSimon L. B. Nielsen     }
28997b2ed56SKris Kennaway     return (ret);
29097b2ed56SKris Kennaway }
29197b2ed56SKris Kennaway 
2921f13597dSJung-uk Kim int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
2936f9291ceSJung-uk Kim                const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
2941f13597dSJung-uk Kim {
2951f13597dSJung-uk Kim 
2966f9291ceSJung-uk Kim     if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
2976f9291ceSJung-uk Kim         return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa);
2981f13597dSJung-uk Kim     }
2991f13597dSJung-uk Kim 
3001f13597dSJung-uk Kim     return int_rsa_verify(dtype, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
3011f13597dSJung-uk Kim }
302