And so it begins...
[oweals/openssl.git] / fips-1.0 / rsa / fips_rsa_sign.c
1 /* fips_rsa_sign.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 2007.
4  */
5 /* ====================================================================
6  * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <string.h>
60 #include <openssl/evp.h>
61 #include <openssl/rsa.h>
62 #include <openssl/err.h>
63
64 /* FIPS versions of RSA_sign() and RSA_verify().
65  * These will only have to deal with SHA* signatures and by including
66  * pregenerated encodings all ASN1 dependencies can be avoided
67  */
68
69 static const unsigned char sha1_bin[] = {
70   0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
71   0x00, 0x04, 0x14
72 };
73
74 static const unsigned char sha224_bin[] = {
75   0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
76   0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
77 };
78
79 static const unsigned char sha256_bin[] = {
80   0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
81   0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
82 };
83
84 static const unsigned char sha384_bin[] = {
85   0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
86   0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
87 };
88
89 static const unsigned char sha512_bin[] = {
90   0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
91   0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
92 };
93
94
95 static const unsigned char *fips_digestinfo_encoding(int nid, unsigned int *len)
96         {
97         switch (nid)
98                 {
99
100                 case NID_sha1:
101                 *len = sizeof(sha1_bin);
102                 return sha1_bin;
103
104                 case NID_sha224:
105                 *len = sizeof(sha224_bin);
106                 return sha224_bin;
107
108                 case NID_sha256:
109                 *len = sizeof(sha256_bin);
110                 return sha256_bin;
111
112                 case NID_sha384:
113                 *len = sizeof(sha384_bin);
114                 return sha384_bin;
115
116                 case NID_sha512:
117                 *len = sizeof(sha512_bin);
118                 return sha512_bin;
119
120                 default:
121                 return NULL;
122
123                 }
124         }
125
126 int FIPS_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
127              unsigned char *sigret, unsigned int *siglen, RSA *rsa)
128         {
129         int i,j,ret=1;
130         unsigned int dlen;
131         const unsigned char *der;
132         /* Largest DigestInfo: 19 (max encoding) + max MD */
133         unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE];
134         if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign)
135                 {
136                 return rsa->meth->rsa_sign(type, m, m_len,
137                         sigret, siglen, rsa);
138                 }
139
140         if(m_len > EVP_MAX_MD_SIZE)
141                 {
142                 RSAerr(RSA_F_RSA_SIGN,RSA_R_INVALID_MESSAGE_LENGTH);
143                 return 0;
144                 }
145
146         der = fips_digestinfo_encoding(type, &dlen);
147         
148         if (!der)
149                 {
150                 RSAerr(RSA_F_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE);
151                 return(0);
152                 }
153         memcpy(tmpdinfo, der, dlen);
154         memcpy(tmpdinfo + dlen, m, m_len);
155
156         i = dlen + m_len;
157
158         j=RSA_size(rsa);
159         if (i > (j-RSA_PKCS1_PADDING_SIZE))
160                 {
161                 RSAerr(RSA_F_RSA_SIGN,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
162                 return(0);
163                 }
164         j=RSA_private_encrypt(i,tmpdinfo,sigret,rsa,RSA_PKCS1_PADDING);
165         if (j <= 0)
166                 ret=0;
167         else
168                 *siglen=j;
169
170         OPENSSL_cleanse(tmpdinfo,i);
171         return(ret);
172         }
173
174 int FIPS_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
175              unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
176         {
177         int i,ret=0;
178         unsigned int dlen;
179         unsigned char *s;
180         const unsigned char *der;
181
182         if (siglen != (unsigned int)RSA_size(rsa))
183                 {
184                 RSAerr(RSA_F_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH);
185                 return(0);
186                 }
187
188         if((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
189                 {
190                 return rsa->meth->rsa_verify(dtype, m, m_len,
191                         sigbuf, siglen, rsa);
192                 }
193
194         s= OPENSSL_malloc((unsigned int)siglen);
195         if (s == NULL)
196                 {
197                 RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE);
198                 goto err;
199                 }
200
201         i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING);
202
203         if (i <= 0) goto err;
204
205         der = fips_digestinfo_encoding(dtype, &dlen);
206         
207         if (!der)
208                 {
209                 RSAerr(RSA_F_RSA_SIGN,RSA_R_UNKNOWN_ALGORITHM_TYPE);
210                 return(0);
211                 }
212
213         /* Compare, DigestInfo length, DigestInfo header and finally
214          * digest value itself
215          */
216         if ((i != (int)(dlen + m_len)) || memcmp(der, s, dlen)
217                 || memcmp(s + dlen, m, m_len))
218                 {
219                 RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
220                 goto err;
221                 }
222         else
223                 ret = 1;
224 err:
225         if (s != NULL)
226                 {
227                 OPENSSL_cleanse(s, siglen);
228                 OPENSSL_free(s);
229                 }
230         return(ret);
231         }