And so it begins...
[oweals/openssl.git] / fips-1.0 / rsa / fips_rsavtest.c
1 /* fips_rsavtest.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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 #include <stdio.h>
60 #include <ctype.h>
61 #include <string.h>
62 #include <openssl/bio.h>
63 #include <openssl/evp.h>
64 #include <openssl/hmac.h>
65 #include <openssl/err.h>
66 #include <openssl/x509v3.h>
67
68 #ifndef OPENSSL_FIPS
69
70 int main(int argc, char *argv[])
71 {
72     printf("No FIPS RSA support\n");
73     return(0);
74 }
75
76 #else
77
78 #include "fips_utl.h"
79
80 int rsa_test(FILE *out, FILE *in, int saltlen);
81 static int rsa_printver(FILE *out,
82                 BIGNUM *n, BIGNUM *e,
83                 const EVP_MD *dgst,
84                 unsigned char *Msg, long Msglen,
85                 unsigned char *S, long Slen, int Saltlen);
86
87 int main(int argc, char **argv)
88         {
89         FILE *in = NULL, *out = NULL;
90
91         int ret = 1;
92         int Saltlen = -1;
93
94         if(!FIPS_mode_set(1))
95                 {
96                 do_print_errors();
97                 goto end;
98                 }
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_test(out, in, Saltlen))
141                 {
142                 fprintf(stderr, "FATAL RSAVTEST file processing error\n");
143                 goto end;
144                 }
145         else
146                 ret = 0;
147
148         end:
149
150         if (ret)
151                 do_print_errors();
152
153         if (in && (in != stdin))
154                 fclose(in);
155         if (out && (out != stdout))
156                 fclose(out);
157
158         return ret;
159
160         }
161
162 #define RSA_TEST_MAXLINELEN     10240
163
164 int rsa_test(FILE *out, FILE *in, int Saltlen)
165         {
166         char *linebuf, *olinebuf, *p, *q;
167         char *keyword, *value;
168         const EVP_MD *dgst = NULL;
169         BIGNUM *n = NULL, *e = NULL;
170         unsigned char *Msg = NULL, *S = NULL;
171         long Msglen, Slen;
172         int ret = 0;
173         int lnum = 0;
174
175         olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
176         linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
177
178         if (!linebuf || !olinebuf)
179                 goto error;
180
181         while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in))
182                 {
183                 lnum++;
184                 strcpy(linebuf, olinebuf);
185                 keyword = linebuf;
186                 /* Skip leading space */
187                 while (isspace((unsigned char)*keyword))
188                         keyword++;
189
190                 /* Look for = sign */
191                 p = strchr(linebuf, '=');
192
193                 /* If no = or starts with [ (for [foo = bar] line) just copy */
194                 if (!p || *keyword=='[')
195                         {
196                         if (!fputs(olinebuf, out))
197                                 goto error;
198                         continue;
199                         }
200
201                 q = p - 1;
202
203                 /* Remove trailing space */
204                 while (isspace((unsigned char)*q))
205                         *q-- = 0;
206
207                 *p = 0;
208                 value = p + 1;
209
210                 /* Remove leading space from value */
211                 while (isspace((unsigned char)*value))
212                         value++;
213
214                 /* Remove trailing space from value */
215                 p = value + strlen(value) - 1;
216
217                 while (*p == '\n' || isspace((unsigned char)*p))
218                         *p-- = 0;
219
220                 if (!strcmp(keyword, "n"))
221                         {
222                         if (!do_hex2bn(&n,value))
223                                 goto parse_error;
224                         }
225                 else if (!strcmp(keyword, "e"))
226                         {
227                         if (!do_hex2bn(&e,value))
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                 else if (!strcmp(keyword, "S"))
261                         {
262                         if (S)
263                                 goto parse_error;
264                         if (strlen(value) & 1)
265                                 *(--value) = '0';
266                         S = hex2bin_m(value, &Slen);
267                         if (!S)
268                                 goto parse_error;
269                         }
270                 else if (!strcmp(keyword, "Result"))
271                         continue;
272                 else
273                         goto parse_error;
274
275                 fputs(olinebuf, out);
276
277                 if (n && e && Msg && S && dgst)
278                         {
279                         if (!rsa_printver(out, n, e, dgst,
280                                         Msg, Msglen, S, Slen, Saltlen))
281                                 goto error;
282                         OPENSSL_free(Msg);
283                         Msg = NULL;
284                         OPENSSL_free(S);
285                         S = NULL;
286                         }
287
288                 }
289
290
291         ret = 1;
292
293
294         error:
295
296         if (olinebuf)
297                 OPENSSL_free(olinebuf);
298         if (linebuf)
299                 OPENSSL_free(linebuf);
300         if (n)
301                 BN_free(n);
302         if (e)
303                 BN_free(e);
304
305         return ret;
306
307         parse_error:
308
309         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
310
311         goto error;
312
313         }
314
315 static int rsa_printver(FILE *out,
316                 BIGNUM *n, BIGNUM *e,
317                 const EVP_MD *dgst,
318                 unsigned char *Msg, long Msglen,
319                 unsigned char *S, long Slen, int Saltlen)
320         {
321         int ret = 0, r;
322         /* Setup RSA and EVP_PKEY structures */
323         RSA *rsa_pubkey = NULL;
324         EVP_PKEY pk;
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         pk.type = EVP_PKEY_RSA;
335         pk.pkey.rsa = rsa_pubkey;
336
337         EVP_MD_CTX_init(&ctx);
338
339         if (Saltlen != -1)
340                 {
341                 int pad;
342                 unsigned char mdtmp[EVP_MAX_MD_SIZE];
343                 buf = OPENSSL_malloc(RSA_size(rsa_pubkey));
344                 if (Saltlen == -2)
345                         pad = RSA_X931_PADDING;
346                 else
347                         pad = RSA_NO_PADDING;
348                 if (!buf)
349                         goto error;
350                 r = RSA_public_decrypt(Slen, S, buf, rsa_pubkey, pad);
351
352                 if (r > 0)
353                         {
354                         EVP_DigestInit_ex(&ctx, dgst, NULL);
355                         if (!EVP_DigestUpdate(&ctx, Msg, Msglen))
356                                 goto error;
357                         if (!EVP_DigestFinal_ex(&ctx, mdtmp, NULL))
358                                 goto error;
359                         if (pad == RSA_X931_PADDING)
360                                 {
361                                 int mdlen = M_EVP_MD_size(dgst);
362                                 if (r != mdlen + 1)
363                                         r = 0;
364                                 else if (buf[mdlen] !=
365                                     RSA_X931_hash_id(M_EVP_MD_type(dgst)))
366                                         r = 0;
367                                 else if (memcmp(buf, mdtmp, mdlen))
368                                         r = 0;
369                                 else
370                                         r = 1;
371                                 }
372                         else
373                                 r = RSA_verify_PKCS1_PSS(rsa_pubkey,
374                                                         mdtmp, dgst,
375                                                         buf, Saltlen);
376                         }
377                 if (r < 0)
378                         r = 0;
379                 }
380         else
381                 {
382
383                 if (!EVP_VerifyInit_ex(&ctx, dgst, NULL))
384                         goto error;
385                 if (!EVP_VerifyUpdate(&ctx, Msg, Msglen))
386                         goto error;
387
388                 r = EVP_VerifyFinal(&ctx, S, Slen, &pk);
389
390                 }
391
392         EVP_MD_CTX_cleanup(&ctx);
393
394         if (r < 0)
395                 goto error;
396         ERR_clear_error();
397
398         if (r == 0)
399                 fputs("Result = F\n", out);
400         else
401                 fputs("Result = P\n", out);
402
403         ret = 1;
404
405         error:
406         if (rsa_pubkey)
407                 FIPS_rsa_free(rsa_pubkey);
408         if (buf)
409                 OPENSSL_free(buf);
410
411         return ret;
412         }
413 #endif