Update RSA selftest code to use a 2048 bit RSA and only a single KAT
[openssl.git] / fips / rsa / fips_rsavtest.c
1 /* fips_rsavtest.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2005.
4  */
5 /* ====================================================================
6  * Copyright (c) 2005 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 #define OPENSSL_FIPSAPI
60
61 #include <stdio.h>
62 #include <ctype.h>
63 #include <string.h>
64 #include <openssl/bio.h>
65 #include <openssl/evp.h>
66 #include <openssl/hmac.h>
67 #include <openssl/err.h>
68 #include <openssl/bn.h>
69
70 #ifndef OPENSSL_FIPS
71
72 int main(int argc, char *argv[])
73 {
74     printf("No FIPS RSA support\n");
75     return(0);
76 }
77
78 #else
79
80 #include <openssl/rsa.h>
81 #include <openssl/fips.h>
82
83 #include "fips_utl.h"
84
85 int rsa_test(FILE *out, FILE *in, int saltlen);
86 static int rsa_printver(FILE *out,
87                 BIGNUM *n, BIGNUM *e,
88                 const EVP_MD *dgst,
89                 unsigned char *Msg, long Msglen,
90                 unsigned char *S, long Slen, int Saltlen);
91
92 int main(int argc, char **argv)
93         {
94         FILE *in = NULL, *out = NULL;
95
96         int ret = 1;
97         int Saltlen = -1;
98
99         fips_algtest_init();
100
101         if ((argc > 2) && !strcmp("-saltlen", argv[1]))
102                 {
103                 Saltlen = atoi(argv[2]);
104                 if (Saltlen < 0)
105                         {
106                         fprintf(stderr, "FATAL: Invalid salt length\n");
107                         goto end;
108                         }
109                 argc -= 2;
110                 argv += 2;
111                 }
112         else if ((argc > 1) && !strcmp("-x931", argv[1]))
113                 {
114                 Saltlen = -2;
115                 argc--;
116                 argv++;
117                 }
118
119         if (argc == 1)
120                 in = stdin;
121         else
122                 in = fopen(argv[1], "r");
123
124         if (argc < 2)
125                 out = stdout;
126         else
127                 out = fopen(argv[2], "w");
128
129         if (!in)
130                 {
131                 fprintf(stderr, "FATAL input initialization error\n");
132                 goto end;
133                 }
134
135         if (!out)
136                 {
137                 fprintf(stderr, "FATAL output initialization error\n");
138                 goto end;
139                 }
140
141         if (!rsa_test(out, in, Saltlen))
142                 {
143                 fprintf(stderr, "FATAL RSAVTEST file processing error\n");
144                 goto end;
145                 }
146         else
147                 ret = 0;
148
149         end:
150
151         if (in && (in != stdin))
152                 fclose(in);
153         if (out && (out != stdout))
154                 fclose(out);
155
156         return ret;
157
158         }
159
160 #define RSA_TEST_MAXLINELEN     10240
161
162 int rsa_test(FILE *out, FILE *in, int Saltlen)
163         {
164         char *linebuf, *olinebuf, *p, *q;
165         char *keyword, *value;
166         const EVP_MD *dgst = NULL;
167         BIGNUM *n = NULL, *e = NULL;
168         unsigned char *Msg = NULL, *S = NULL;
169         long Msglen, Slen;
170         int ret = 0;
171         int lnum = 0;
172
173         olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
174         linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
175
176         if (!linebuf || !olinebuf)
177                 goto error;
178
179         while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in))
180                 {
181                 lnum++;
182                 strcpy(linebuf, olinebuf);
183                 keyword = linebuf;
184                 /* Skip leading space */
185                 while (isspace((unsigned char)*keyword))
186                         keyword++;
187
188                 /* Look for = sign */
189                 p = strchr(linebuf, '=');
190
191                 /* If no = or starts with [ (for [foo = bar] line) just copy */
192                 if (!p || *keyword=='[')
193                         {
194                         if (fputs(olinebuf, out) < 0)
195                                 goto error;
196                         continue;
197                         }
198
199                 q = p - 1;
200
201                 /* Remove trailing space */
202                 while (isspace((unsigned char)*q))
203                         *q-- = 0;
204
205                 *p = 0;
206                 value = p + 1;
207
208                 /* Remove leading space from value */
209                 while (isspace((unsigned char)*value))
210                         value++;
211
212                 /* Remove trailing space from value */
213                 p = value + strlen(value) - 1;
214
215                 while (*p == '\n' || isspace((unsigned char)*p))
216                         *p-- = 0;
217
218                 if (!strcmp(keyword, "n"))
219                         {
220                         if (!do_hex2bn(&n,value))
221                                 goto parse_error;
222                         }
223                 else if (!strcmp(keyword, "e"))
224                         {
225                         if (!do_hex2bn(&e,value))
226                                 goto parse_error;
227                         }
228                 else if (!strcmp(keyword, "SHAAlg"))
229                         {
230                         if (!strcmp(value, "SHA1"))
231                                 dgst = EVP_sha1();
232                         else if (!strcmp(value, "SHA224"))
233                                 dgst = EVP_sha224();
234                         else if (!strcmp(value, "SHA256"))
235                                 dgst = EVP_sha256();
236                         else if (!strcmp(value, "SHA384"))
237                                 dgst = EVP_sha384();
238                         else if (!strcmp(value, "SHA512"))
239                                 dgst = EVP_sha512();
240                         else
241                                 {
242                                 fprintf(stderr,
243                                         "FATAL: unsupported algorithm \"%s\"\n",
244                                                                 value);
245                                 goto parse_error;
246                                 }
247                         }
248                 else if (!strcmp(keyword, "Msg"))
249                         {
250                         if (Msg)
251                                 goto parse_error;
252                         if (strlen(value) & 1)
253                                 *(--value) = '0';
254                         Msg = hex2bin_m(value, &Msglen);
255                         if (!Msg)
256                                 goto parse_error;
257                         }
258                 else if (!strcmp(keyword, "S"))
259                         {
260                         if (S)
261                                 goto parse_error;
262                         if (strlen(value) & 1)
263                                 *(--value) = '0';
264                         S = hex2bin_m(value, &Slen);
265                         if (!S)
266                                 goto parse_error;
267                         }
268                 else if (!strcmp(keyword, "Result"))
269                         continue;
270                 else
271                         goto parse_error;
272
273                 fputs(olinebuf, out);
274
275                 if (n && e && Msg && S && dgst)
276                         {
277                         if (!rsa_printver(out, n, e, dgst,
278                                         Msg, Msglen, S, Slen, Saltlen))
279                                 goto error;
280                         OPENSSL_free(Msg);
281                         Msg = NULL;
282                         OPENSSL_free(S);
283                         S = NULL;
284                         }
285
286                 }
287
288
289         ret = 1;
290
291
292         error:
293
294         if (olinebuf)
295                 OPENSSL_free(olinebuf);
296         if (linebuf)
297                 OPENSSL_free(linebuf);
298         if (n)
299                 BN_free(n);
300         if (e)
301                 BN_free(e);
302
303         return ret;
304
305         parse_error:
306
307         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
308
309         goto error;
310
311         }
312
313 static int rsa_printver(FILE *out,
314                 BIGNUM *n, BIGNUM *e,
315                 const EVP_MD *dgst,
316                 unsigned char *Msg, long Msglen,
317                 unsigned char *S, long Slen, int Saltlen)
318         {
319         int ret = 0, r, pad_mode;
320         /* Setup RSA and EVP_PKEY structures */
321         RSA *rsa_pubkey = NULL;
322         EVP_MD_CTX ctx;
323         unsigned char *buf = NULL;
324         rsa_pubkey = FIPS_rsa_new();
325         if (!rsa_pubkey)
326                 goto error;
327         rsa_pubkey->n = BN_dup(n);
328         rsa_pubkey->e = BN_dup(e);
329         if (!rsa_pubkey->n || !rsa_pubkey->e)
330                 goto error;
331
332         FIPS_md_ctx_init(&ctx);
333
334         if (Saltlen >= 0)
335                 pad_mode = RSA_PKCS1_PSS_PADDING;
336         else if (Saltlen == -2)
337                 pad_mode = RSA_X931_PADDING;
338         else
339                 pad_mode = RSA_PKCS1_PADDING;
340
341         if (!FIPS_digestinit(&ctx, dgst))
342                 goto error;
343         if (!FIPS_digestupdate(&ctx, Msg, Msglen))
344                 goto error;
345
346         no_err = 1;
347         r = FIPS_rsa_verify_ctx(rsa_pubkey, &ctx,
348                                 pad_mode, Saltlen, NULL, S, Slen);
349         no_err = 0;
350
351
352         FIPS_md_ctx_cleanup(&ctx);
353
354         if (r < 0)
355                 goto error;
356
357         if (r == 0)
358                 fputs("Result = F\n", out);
359         else
360                 fputs("Result = P\n", out);
361
362         ret = 1;
363
364         error:
365         if (rsa_pubkey)
366                 FIPS_rsa_free(rsa_pubkey);
367         if (buf)
368                 OPENSSL_free(buf);
369
370         return ret;
371         }
372 #endif