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