Have all algorithm test programs call fips_algtest_init() at startup:
[openssl.git] / fips / rsa / fips_rsastest.c
1 /* fips_rsastest.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 #include "fips_utl.h"
83
84 static int rsa_stest(FILE *out, FILE *in, int Saltlen);
85 static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
86                 unsigned char *Msg, long Msglen, int Saltlen);
87
88 int main(int argc, char **argv)
89         {
90         FILE *in = NULL, *out = NULL;
91
92         int ret = 1, Saltlen = -1;
93
94         fips_algtest_init();
95
96         if ((argc > 2) && !strcmp("-saltlen", argv[1]))
97                 {
98                 Saltlen = atoi(argv[2]);
99                 if (Saltlen < 0)
100                         {
101                         fprintf(stderr, "FATAL: Invalid salt length\n");
102                         goto end;
103                         }
104                 argc -= 2;
105                 argv += 2;
106                 }
107         else if ((argc > 1) && !strcmp("-x931", argv[1]))
108                 {
109                 Saltlen = -2;
110                 argc--;
111                 argv++;
112                 }
113
114         if (argc == 1)
115                 in = stdin;
116         else
117                 in = fopen(argv[1], "r");
118
119         if (argc < 2)
120                 out = stdout;
121         else
122                 out = fopen(argv[2], "w");
123
124         if (!in)
125                 {
126                 fprintf(stderr, "FATAL input initialization error\n");
127                 goto end;
128                 }
129
130         if (!out)
131                 {
132                 fprintf(stderr, "FATAL output initialization error\n");
133                 goto end;
134                 }
135
136         if (!rsa_stest(out, in, Saltlen))
137                 {
138                 fprintf(stderr, "FATAL RSASTEST file processing error\n");
139                 goto end;
140                 }
141         else
142                 ret = 0;
143
144         end:
145
146         if (in && (in != stdin))
147                 fclose(in);
148         if (out && (out != stdout))
149                 fclose(out);
150
151         return ret;
152
153         }
154
155 #define RSA_TEST_MAXLINELEN     10240
156
157 int rsa_stest(FILE *out, FILE *in, int Saltlen)
158         {
159         char *linebuf, *olinebuf, *p, *q;
160         char *keyword, *value;
161         RSA *rsa = NULL;
162         const EVP_MD *dgst = NULL;
163         unsigned char *Msg = NULL;
164         long Msglen = -1;
165         int keylen = -1, current_keylen = -1;
166         int ret = 0;
167         int lnum = 0;
168
169         olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
170         linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
171
172         if (!linebuf || !olinebuf)
173                 goto error;
174
175         while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in))
176                 {
177                 lnum++;
178                 strcpy(linebuf, olinebuf);
179                 keyword = linebuf;
180                 /* Skip leading space */
181                 while (isspace((unsigned char)*keyword))
182                         keyword++;
183
184                 /* Look for = sign */
185                 p = strchr(linebuf, '=');
186
187                 /* If no = just copy */
188                 if (!p)
189                         {
190                         if (fputs(olinebuf, out) < 0)
191                                 goto error;
192                         continue;
193                         }
194
195                 q = p - 1;
196
197                 /* Remove trailing space */
198                 while (isspace((unsigned char)*q))
199                         *q-- = 0;
200
201                 *p = 0;
202                 value = p + 1;
203
204                 /* Remove leading space from value */
205                 while (isspace((unsigned char)*value))
206                         value++;
207
208                 /* Remove trailing space from value */
209                 p = value + strlen(value) - 1;
210
211                 while (*p == '\n' || isspace((unsigned char)*p))
212                         *p-- = 0;
213
214                 /* Look for [mod = XXX] for key length */
215
216                 if (!strcmp(keyword, "[mod"))
217                         {
218                         p = value + strlen(value) - 1;
219                         if (*p != ']')
220                                 goto parse_error;
221                         *p = 0;
222                         keylen = atoi(value);
223                         if (keylen < 0)
224                                 goto parse_error;
225                         }
226                 else if (!strcmp(keyword, "SHAAlg"))
227                         {
228                         if (!strcmp(value, "SHA1"))
229                                 dgst = EVP_sha1();
230                         else if (!strcmp(value, "SHA224"))
231                                 dgst = EVP_sha224();
232                         else if (!strcmp(value, "SHA256"))
233                                 dgst = EVP_sha256();
234                         else if (!strcmp(value, "SHA384"))
235                                 dgst = EVP_sha384();
236                         else if (!strcmp(value, "SHA512"))
237                                 dgst = EVP_sha512();
238                         else
239                                 {
240                                 fprintf(stderr,
241                                         "FATAL: unsupported algorithm \"%s\"\n",
242                                                                 value);
243                                 goto parse_error;
244                                 }
245                         }
246                 else if (!strcmp(keyword, "Msg"))
247                         {
248                         if (Msg)
249                                 goto parse_error;
250                         if (strlen(value) & 1)
251                                 *(--value) = '0';
252                         Msg = hex2bin_m(value, &Msglen);
253                         if (!Msg)
254                                 goto parse_error;
255                         }
256
257                 fputs(olinebuf, out);
258
259                 /* If key length has changed, generate and output public
260                  * key components of new RSA private key.
261                  */
262
263                 if (keylen != current_keylen)
264                         {
265                         BIGNUM *bn_e;
266                         if (rsa)
267                                 FIPS_rsa_free(rsa);
268                         rsa = FIPS_rsa_new();
269                         if (!rsa)
270                                 goto error;
271                         bn_e = BN_new();
272                         if (!bn_e || !BN_set_word(bn_e, 0x1001))
273                                 goto error;
274                         if (!RSA_X931_generate_key_ex(rsa, keylen, bn_e, NULL))
275                                 goto error;
276                         BN_free(bn_e);
277                         fputs("n = ", out);
278                         do_bn_print(out, rsa->n);
279                         fputs("\ne = ", out);
280                         do_bn_print(out, rsa->e);
281                         fputs("\n", out);
282                         current_keylen = keylen;
283                         }
284
285                 if (Msg && dgst)
286                         {
287                         if (!rsa_printsig(out, rsa, dgst, Msg, Msglen,
288                                                                 Saltlen))
289                                 goto error;
290                         OPENSSL_free(Msg);
291                         Msg = NULL;
292                         }
293
294                 }
295
296         ret = 1;
297
298         error:
299
300         if (olinebuf)
301                 OPENSSL_free(olinebuf);
302         if (linebuf)
303                 OPENSSL_free(linebuf);
304         if (rsa)
305                 FIPS_rsa_free(rsa);
306
307         return ret;
308
309         parse_error:
310
311         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
312
313         goto error;
314
315         }
316
317 static int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
318                 unsigned char *Msg, long Msglen, int Saltlen)
319         {
320         int ret = 0;
321         unsigned char *sigbuf = NULL;
322         int i, siglen, pad_mode;
323         /* EVP_PKEY structure */
324         EVP_MD_CTX ctx;
325
326         siglen = RSA_size(rsa);
327         sigbuf = OPENSSL_malloc(siglen);
328         if (!sigbuf)
329                 goto error;
330
331         FIPS_md_ctx_init(&ctx);
332
333         if (Saltlen >= 0)
334                 pad_mode = RSA_PKCS1_PSS_PADDING;
335         else if (Saltlen == -2)
336                 pad_mode = RSA_X931_PADDING;
337         else
338                 pad_mode = RSA_PKCS1_PADDING;
339
340         if (!FIPS_digestinit(&ctx, dgst))
341                 goto error;
342         if (!FIPS_digestupdate(&ctx, Msg, Msglen))
343                 goto error;
344         if (!FIPS_rsa_sign_ctx(rsa, &ctx, pad_mode, Saltlen, NULL,
345                                 sigbuf, (unsigned int *)&siglen))
346                 goto error;
347
348         FIPS_md_ctx_cleanup(&ctx);
349
350         fputs("S = ", out);
351
352         for (i = 0; i < siglen; i++)
353                 fprintf(out, "%02X", sigbuf[i]);
354
355         fputs("\n", out);
356
357         ret = 1;
358
359         error:
360
361         return ret;
362         }
363 #endif