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