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