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