]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/fips/rsa/fips_rsavtest.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / fips / rsa / fips_rsavtest.c
1 /* fips_rsavtest.c */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4  * 2005.
5  */
6 /* ====================================================================
7  * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59
60 #include <stdio.h>
61 #include <ctype.h>
62 #include <string.h>
63 #include <openssl/bio.h>
64 #include <openssl/evp.h>
65 #include <openssl/hmac.h>
66 #include <openssl/err.h>
67 #include <openssl/x509v3.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
82 # include "fips_utl.h"
83
84 int rsa_test(FILE *out, FILE *in, int saltlen);
85 static int rsa_printver(FILE *out,
86                         BIGNUM *n, BIGNUM *e,
87                         const EVP_MD *dgst,
88                         unsigned char *Msg, long Msglen,
89                         unsigned char *S, long Slen, int Saltlen);
90
91 int main(int argc, char **argv)
92 {
93     FILE *in = NULL, *out = NULL;
94
95     int ret = 1;
96     int Saltlen = -1;
97
98     if (!FIPS_mode_set(1)) {
99         do_print_errors();
100         goto end;
101     }
102
103     if ((argc > 2) && !strcmp("-saltlen", argv[1])) {
104         Saltlen = atoi(argv[2]);
105         if (Saltlen < 0) {
106             fprintf(stderr, "FATAL: Invalid salt length\n");
107             goto end;
108         }
109         argc -= 2;
110         argv += 2;
111     } else if ((argc > 1) && !strcmp("-x931", argv[1])) {
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         fprintf(stderr, "FATAL input initialization error\n");
129         goto end;
130     }
131
132     if (!out) {
133         fprintf(stderr, "FATAL output initialization error\n");
134         goto end;
135     }
136
137     if (!rsa_test(out, in, Saltlen)) {
138         fprintf(stderr, "FATAL RSAVTEST file processing error\n");
139         goto end;
140     } else
141         ret = 0;
142
143  end:
144
145     if (ret)
146         do_print_errors();
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_test(FILE *out, FILE *in, int Saltlen)
160 {
161     char *linebuf, *olinebuf, *p, *q;
162     char *keyword, *value;
163     const EVP_MD *dgst = NULL;
164     BIGNUM *n = NULL, *e = NULL;
165     unsigned char *Msg = NULL, *S = NULL;
166     long Msglen, Slen;
167     int ret = 0;
168     int lnum = 0;
169
170     olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
171     linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
172
173     if (!linebuf || !olinebuf)
174         goto error;
175
176     while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) {
177         lnum++;
178         strcpy(linebuf, olinebuf);
179         keyword = linebuf;
180         /* Skip leading space */
181         while (isspace((unsigned char)*keyword))
182             keyword++;
183
184         /* Look for = sign */
185         p = strchr(linebuf, '=');
186
187         /*
188          * If no = or starts with [ (for [foo = bar] line) just copy
189          */
190         if (!p || *keyword == '[') {
191             if (fputs(olinebuf, out) < 0)
192                 goto error;
193             continue;
194         }
195
196         q = p - 1;
197
198         /* Remove trailing space */
199         while (isspace((unsigned char)*q))
200             *q-- = 0;
201
202         *p = 0;
203         value = p + 1;
204
205         /* Remove leading space from value */
206         while (isspace((unsigned char)*value))
207             value++;
208
209         /* Remove trailing space from value */
210         p = value + strlen(value) - 1;
211
212         while (*p == '\n' || isspace((unsigned char)*p))
213             *p-- = 0;
214
215         if (!strcmp(keyword, "n")) {
216             if (!do_hex2bn(&n, value))
217                 goto parse_error;
218         } else if (!strcmp(keyword, "e")) {
219             if (!do_hex2bn(&e, value))
220                 goto parse_error;
221         } else if (!strcmp(keyword, "SHAAlg")) {
222             if (!strcmp(value, "SHA1"))
223                 dgst = EVP_sha1();
224             else if (!strcmp(value, "SHA224"))
225                 dgst = EVP_sha224();
226             else if (!strcmp(value, "SHA256"))
227                 dgst = EVP_sha256();
228             else if (!strcmp(value, "SHA384"))
229                 dgst = EVP_sha384();
230             else if (!strcmp(value, "SHA512"))
231                 dgst = EVP_sha512();
232             else {
233                 fprintf(stderr,
234                         "FATAL: unsupported algorithm \"%s\"\n", value);
235                 goto parse_error;
236             }
237         } else if (!strcmp(keyword, "Msg")) {
238             if (Msg)
239                 goto parse_error;
240             if (strlen(value) & 1)
241                 *(--value) = '0';
242             Msg = hex2bin_m(value, &Msglen);
243             if (!Msg)
244                 goto parse_error;
245         } else if (!strcmp(keyword, "S")) {
246             if (S)
247                 goto parse_error;
248             if (strlen(value) & 1)
249                 *(--value) = '0';
250             S = hex2bin_m(value, &Slen);
251             if (!S)
252                 goto parse_error;
253         } else if (!strcmp(keyword, "Result"))
254             continue;
255         else
256             goto parse_error;
257
258         fputs(olinebuf, out);
259
260         if (n && e && Msg && S && dgst) {
261             if (!rsa_printver(out, n, e, dgst, Msg, Msglen, S, Slen, Saltlen))
262                 goto error;
263             OPENSSL_free(Msg);
264             Msg = NULL;
265             OPENSSL_free(S);
266             S = NULL;
267         }
268
269     }
270
271     ret = 1;
272
273  error:
274
275     if (olinebuf)
276         OPENSSL_free(olinebuf);
277     if (linebuf)
278         OPENSSL_free(linebuf);
279     if (n)
280         BN_free(n);
281     if (e)
282         BN_free(e);
283
284     return ret;
285
286  parse_error:
287
288     fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
289
290     goto error;
291
292 }
293
294 static int rsa_printver(FILE *out,
295                         BIGNUM *n, BIGNUM *e,
296                         const EVP_MD *dgst,
297                         unsigned char *Msg, long Msglen,
298                         unsigned char *S, long Slen, int Saltlen)
299 {
300     int ret = 0, r;
301     /* Setup RSA and EVP_PKEY structures */
302     RSA *rsa_pubkey = NULL;
303     EVP_PKEY pk;
304     EVP_MD_CTX ctx;
305     unsigned char *buf = NULL;
306     rsa_pubkey = FIPS_rsa_new();
307     if (!rsa_pubkey)
308         goto error;
309     rsa_pubkey->n = BN_dup(n);
310     rsa_pubkey->e = BN_dup(e);
311     if (!rsa_pubkey->n || !rsa_pubkey->e)
312         goto error;
313     pk.type = EVP_PKEY_RSA;
314     pk.pkey.rsa = rsa_pubkey;
315
316     EVP_MD_CTX_init(&ctx);
317
318     if (Saltlen >= 0) {
319         M_EVP_MD_CTX_set_flags(&ctx,
320                                EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
321     } else if (Saltlen == -2)
322         M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
323     if (!EVP_VerifyInit_ex(&ctx, dgst, NULL))
324         goto error;
325     if (!EVP_VerifyUpdate(&ctx, Msg, Msglen))
326         goto error;
327
328     r = EVP_VerifyFinal(&ctx, S, Slen, &pk);
329
330     EVP_MD_CTX_cleanup(&ctx);
331
332     if (r < 0)
333         goto error;
334     ERR_clear_error();
335
336     if (r == 0)
337         fputs("Result = F\n", out);
338     else
339         fputs("Result = P\n", out);
340
341     ret = 1;
342
343  error:
344     if (rsa_pubkey)
345         FIPS_rsa_free(rsa_pubkey);
346     if (buf)
347         OPENSSL_free(buf);
348
349     return ret;
350 }
351 #endif