]>
Commit | Line | Data |
---|---|---|
2b4b28dc DSH |
1 | /* fips_rsa_sign.c */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) 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 | ||
7c8ced94 | 59 | #define OPENSSL_FIPSAPI |
2b4b28dc DSH |
60 | |
61 | #include <string.h> | |
62 | #include <openssl/evp.h> | |
63 | #include <openssl/rsa.h> | |
64 | #include <openssl/err.h> | |
65 | #include <openssl/sha.h> | |
7cc684f4 | 66 | #include <openssl/fips.h> |
2b4b28dc DSH |
67 | |
68 | #ifdef OPENSSL_FIPS | |
69 | ||
70 | /* FIPS versions of RSA_sign() and RSA_verify(). | |
71 | * These will only have to deal with SHA* signatures and by including | |
72 | * pregenerated encodings all ASN1 dependencies can be avoided | |
73 | */ | |
74 | ||
75 | /* Standard encodings including NULL parameter */ | |
76 | ||
77 | static const unsigned char sha1_bin[] = { | |
78 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, | |
79 | 0x00, 0x04, 0x14 | |
80 | }; | |
81 | ||
82 | static const unsigned char sha224_bin[] = { | |
83 | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
84 | 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c | |
85 | }; | |
86 | ||
87 | static const unsigned char sha256_bin[] = { | |
88 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
89 | 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 | |
90 | }; | |
91 | ||
92 | static const unsigned char sha384_bin[] = { | |
93 | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
94 | 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 | |
95 | }; | |
96 | ||
97 | static const unsigned char sha512_bin[] = { | |
98 | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
99 | 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 | |
100 | }; | |
101 | ||
102 | /* Alternate encodings with absent parameters. We don't generate signature | |
103 | * using this format but do tolerate received signatures of this form. | |
104 | */ | |
105 | ||
106 | static unsigned char sha1_nn_bin[] = { | |
107 | 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, | |
108 | 0x14 | |
109 | }; | |
110 | ||
111 | static unsigned char sha224_nn_bin[] = { | |
112 | 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
113 | 0x04, 0x02, 0x04, 0x04, 0x1c | |
114 | }; | |
115 | ||
116 | static unsigned char sha256_nn_bin[] = { | |
117 | 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
118 | 0x04, 0x02, 0x01, 0x04, 0x20 | |
119 | }; | |
120 | ||
121 | static unsigned char sha384_nn_bin[] = { | |
122 | 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
123 | 0x04, 0x02, 0x02, 0x04, 0x30 | |
124 | }; | |
125 | ||
126 | static unsigned char sha512_nn_bin[] = { | |
127 | 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, | |
128 | 0x04, 0x02, 0x03, 0x04, 0x40 | |
129 | }; | |
130 | ||
131 | ||
132 | static const unsigned char *fips_digestinfo_encoding(int nid, unsigned int *len) | |
133 | { | |
134 | switch (nid) | |
135 | { | |
136 | ||
137 | case NID_sha1: | |
138 | *len = sizeof(sha1_bin); | |
139 | return sha1_bin; | |
140 | ||
141 | case NID_sha224: | |
142 | *len = sizeof(sha224_bin); | |
143 | return sha224_bin; | |
144 | ||
145 | case NID_sha256: | |
146 | *len = sizeof(sha256_bin); | |
147 | return sha256_bin; | |
148 | ||
149 | case NID_sha384: | |
150 | *len = sizeof(sha384_bin); | |
151 | return sha384_bin; | |
152 | ||
153 | case NID_sha512: | |
154 | *len = sizeof(sha512_bin); | |
155 | return sha512_bin; | |
156 | ||
157 | default: | |
158 | return NULL; | |
159 | ||
160 | } | |
161 | } | |
162 | ||
163 | static const unsigned char *fips_digestinfo_nn_encoding(int nid, unsigned int *len) | |
164 | { | |
165 | switch (nid) | |
166 | { | |
167 | ||
168 | case NID_sha1: | |
169 | *len = sizeof(sha1_nn_bin); | |
170 | return sha1_nn_bin; | |
171 | ||
172 | case NID_sha224: | |
173 | *len = sizeof(sha224_nn_bin); | |
174 | return sha224_nn_bin; | |
175 | ||
176 | case NID_sha256: | |
177 | *len = sizeof(sha256_nn_bin); | |
178 | return sha256_nn_bin; | |
179 | ||
180 | case NID_sha384: | |
181 | *len = sizeof(sha384_nn_bin); | |
182 | return sha384_nn_bin; | |
183 | ||
184 | case NID_sha512: | |
185 | *len = sizeof(sha512_nn_bin); | |
186 | return sha512_nn_bin; | |
187 | ||
188 | default: | |
189 | return NULL; | |
190 | ||
191 | } | |
192 | } | |
193 | ||
2b4b28dc DSH |
194 | int FIPS_rsa_sign_ctx(RSA *rsa, EVP_MD_CTX *ctx, |
195 | int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, | |
196 | unsigned char *sigret, unsigned int *siglen) | |
197 | { | |
a5b196a2 DSH |
198 | unsigned int md_len, rv; |
199 | unsigned char md[EVP_MAX_MD_SIZE]; | |
200 | EVP_DigestFinal_ex(ctx, md, &md_len); | |
201 | rv = FIPS_rsa_sign_digest(rsa, md, md_len, | |
202 | M_EVP_MD_CTX_md(ctx), | |
203 | rsa_pad_mode, saltlen, | |
204 | mgf1Hash, sigret, siglen); | |
205 | OPENSSL_cleanse(md, md_len); | |
206 | return rv; | |
207 | } | |
208 | ||
209 | ||
210 | int FIPS_rsa_sign_digest(RSA *rsa, const unsigned char *md, int md_len, | |
211 | const EVP_MD *mhash, int rsa_pad_mode, int saltlen, | |
212 | const EVP_MD *mgf1Hash, | |
213 | unsigned char *sigret, unsigned int *siglen) | |
214 | { | |
2b4b28dc DSH |
215 | int i=0,j,ret=0; |
216 | unsigned int dlen; | |
217 | const unsigned char *der; | |
2b4b28dc DSH |
218 | int md_type; |
219 | /* Largest DigestInfo: 19 (max encoding) + max MD */ | |
220 | unsigned char tmpdinfo[19 + EVP_MAX_MD_SIZE]; | |
2b4b28dc | 221 | |
2b4b28dc DSH |
222 | md_type = M_EVP_MD_type(mhash); |
223 | ||
224 | if (rsa_pad_mode == RSA_X931_PADDING) | |
225 | { | |
226 | int hash_id; | |
a5b196a2 | 227 | memcpy(tmpdinfo, md, md_len); |
2b4b28dc DSH |
228 | hash_id = RSA_X931_hash_id(md_type); |
229 | if (hash_id == -1) | |
230 | { | |
2440d8b1 | 231 | RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); |
2b4b28dc DSH |
232 | return 0; |
233 | } | |
a5b196a2 DSH |
234 | tmpdinfo[md_len] = (unsigned char)hash_id; |
235 | i = md_len + 1; | |
2b4b28dc DSH |
236 | } |
237 | else if (rsa_pad_mode == RSA_PKCS1_PADDING) | |
238 | { | |
239 | ||
240 | der = fips_digestinfo_encoding(md_type, &dlen); | |
241 | ||
242 | if (!der) | |
243 | { | |
2440d8b1 | 244 | RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); |
2b4b28dc DSH |
245 | return 0; |
246 | } | |
247 | memcpy(tmpdinfo, der, dlen); | |
a5b196a2 | 248 | memcpy(tmpdinfo + dlen, md, md_len); |
2b4b28dc | 249 | |
a5b196a2 | 250 | i = dlen + md_len; |
2b4b28dc DSH |
251 | |
252 | } | |
253 | else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) | |
254 | { | |
255 | unsigned char *sbuf; | |
256 | i = RSA_size(rsa); | |
257 | sbuf = OPENSSL_malloc(RSA_size(rsa)); | |
258 | if (!sbuf) | |
259 | { | |
2440d8b1 | 260 | RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,ERR_R_MALLOC_FAILURE); |
2b4b28dc DSH |
261 | goto psserr; |
262 | } | |
263 | if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, sbuf, md, mhash, | |
264 | mgf1Hash, saltlen)) | |
265 | goto psserr; | |
266 | j=rsa->meth->rsa_priv_enc(i,sbuf,sigret,rsa,RSA_NO_PADDING); | |
267 | if (j > 0) | |
268 | { | |
269 | ret=1; | |
270 | *siglen=j; | |
271 | } | |
272 | psserr: | |
2b4b28dc DSH |
273 | OPENSSL_cleanse(sbuf, i); |
274 | OPENSSL_free(sbuf); | |
275 | return ret; | |
276 | } | |
277 | ||
278 | j=RSA_size(rsa); | |
279 | if (i > (j-RSA_PKCS1_PADDING_SIZE)) | |
280 | { | |
2440d8b1 | 281 | RSAerr(RSA_F_FIPS_RSA_SIGN_DIGEST,RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); |
2b4b28dc DSH |
282 | goto done; |
283 | } | |
284 | /* NB: call underlying method directly to avoid FIPS blocking */ | |
285 | j=rsa->meth->rsa_priv_enc(i,tmpdinfo,sigret,rsa,rsa_pad_mode); | |
286 | if (j > 0) | |
287 | { | |
288 | ret=1; | |
289 | *siglen=j; | |
290 | } | |
291 | ||
292 | done: | |
293 | OPENSSL_cleanse(tmpdinfo,i); | |
2b4b28dc DSH |
294 | return ret; |
295 | } | |
296 | ||
297 | int FIPS_rsa_verify_ctx(RSA *rsa, EVP_MD_CTX *ctx, | |
298 | int rsa_pad_mode, int saltlen, const EVP_MD *mgf1Hash, | |
299 | unsigned char *sigbuf, unsigned int siglen) | |
300 | { | |
a5b196a2 DSH |
301 | unsigned int md_len, rv; |
302 | unsigned char md[EVP_MAX_MD_SIZE]; | |
303 | EVP_DigestFinal_ex(ctx, md, &md_len); | |
304 | rv = FIPS_rsa_verify_digest(rsa, md, md_len, M_EVP_MD_CTX_md(ctx), | |
305 | rsa_pad_mode, saltlen, mgf1Hash, | |
306 | sigbuf, siglen); | |
307 | OPENSSL_cleanse(md, md_len); | |
308 | return rv; | |
309 | } | |
310 | ||
311 | int FIPS_rsa_verify_digest(RSA *rsa, const unsigned char *dig, int diglen, | |
312 | const EVP_MD *mhash, int rsa_pad_mode, int saltlen, | |
313 | const EVP_MD *mgf1Hash, | |
314 | unsigned char *sigbuf, unsigned int siglen) | |
315 | { | |
2b4b28dc | 316 | int i,ret=0; |
a5b196a2 | 317 | unsigned int dlen; |
2b4b28dc DSH |
318 | unsigned char *s; |
319 | const unsigned char *der; | |
2b4b28dc DSH |
320 | int md_type; |
321 | int rsa_dec_pad_mode; | |
322 | ||
323 | if (siglen != (unsigned int)RSA_size(rsa)) | |
324 | { | |
2440d8b1 | 325 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_WRONG_SIGNATURE_LENGTH); |
2b4b28dc DSH |
326 | return(0); |
327 | } | |
328 | ||
2b4b28dc DSH |
329 | md_type = M_EVP_MD_type(mhash); |
330 | ||
2b4b28dc DSH |
331 | s= OPENSSL_malloc((unsigned int)siglen); |
332 | if (s == NULL) | |
333 | { | |
2440d8b1 | 334 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,ERR_R_MALLOC_FAILURE); |
2b4b28dc DSH |
335 | goto err; |
336 | } | |
337 | ||
338 | if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) | |
339 | rsa_dec_pad_mode = RSA_NO_PADDING; | |
340 | else | |
341 | rsa_dec_pad_mode = rsa_pad_mode; | |
342 | ||
343 | /* NB: call underlying method directly to avoid FIPS blocking */ | |
344 | i=rsa->meth->rsa_pub_dec((int)siglen,sigbuf,s, rsa, rsa_dec_pad_mode); | |
345 | ||
346 | if (i <= 0) goto err; | |
347 | ||
348 | if (rsa_pad_mode == RSA_X931_PADDING) | |
349 | { | |
350 | int hash_id; | |
351 | if (i != (int)(diglen + 1)) | |
352 | { | |
2440d8b1 | 353 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); |
2b4b28dc DSH |
354 | goto err; |
355 | } | |
356 | hash_id = RSA_X931_hash_id(md_type); | |
357 | if (hash_id == -1) | |
358 | { | |
2440d8b1 | 359 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); |
2b4b28dc DSH |
360 | goto err; |
361 | } | |
362 | if (s[diglen] != (unsigned char)hash_id) | |
363 | { | |
2440d8b1 | 364 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); |
2b4b28dc DSH |
365 | goto err; |
366 | } | |
367 | if (memcmp(s, dig, diglen)) | |
368 | { | |
2440d8b1 | 369 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); |
2b4b28dc DSH |
370 | goto err; |
371 | } | |
372 | ret = 1; | |
373 | } | |
374 | else if (rsa_pad_mode == RSA_PKCS1_PADDING) | |
375 | { | |
376 | ||
377 | der = fips_digestinfo_encoding(md_type, &dlen); | |
378 | ||
379 | if (!der) | |
380 | { | |
2440d8b1 | 381 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_UNKNOWN_ALGORITHM_TYPE); |
2b4b28dc DSH |
382 | return(0); |
383 | } | |
384 | ||
385 | /* Compare, DigestInfo length, DigestInfo header and finally | |
386 | * digest value itself | |
387 | */ | |
388 | ||
389 | /* If length mismatch try alternate encoding */ | |
390 | if (i != (int)(dlen + diglen)) | |
391 | der = fips_digestinfo_nn_encoding(md_type, &dlen); | |
392 | ||
393 | if ((i != (int)(dlen + diglen)) || memcmp(der, s, dlen) | |
394 | || memcmp(s + dlen, dig, diglen)) | |
395 | { | |
2440d8b1 | 396 | RSAerr(RSA_F_FIPS_RSA_VERIFY_DIGEST,RSA_R_BAD_SIGNATURE); |
2b4b28dc DSH |
397 | goto err; |
398 | } | |
399 | ret = 1; | |
400 | ||
401 | } | |
402 | else if (rsa_pad_mode == RSA_PKCS1_PSS_PADDING) | |
403 | { | |
404 | ret = RSA_verify_PKCS1_PSS_mgf1(rsa, dig, mhash, mgf1Hash, | |
405 | s, saltlen); | |
406 | if (ret < 0) | |
407 | ret = 0; | |
408 | } | |
409 | err: | |
410 | if (s != NULL) | |
411 | { | |
412 | OPENSSL_cleanse(s, siglen); | |
413 | OPENSSL_free(s); | |
414 | } | |
415 | return(ret); | |
416 | } | |
417 | ||
418 | #endif |