fips_rsastest.c revision 296465
1226890Sdim/* fips_rsastest.c */
2193326Sed/*
3193326Sed * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4193326Sed * 2005.
5193326Sed */
6193326Sed/* ====================================================================
7193326Sed * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
8193326Sed *
9193326Sed * Redistribution and use in source and binary forms, with or without
10193326Sed * modification, are permitted provided that the following conditions
11226890Sdim * are met:
12193326Sed *
13193326Sed * 1. Redistributions of source code must retain the above copyright
14193326Sed *    notice, this list of conditions and the following disclaimer.
15212904Sdim *
16212904Sdim * 2. Redistributions in binary form must reproduce the above copyright
17193326Sed *    notice, this list of conditions and the following disclaimer in
18223017Sdim *    the documentation and/or other materials provided with the
19193326Sed *    distribution.
20193326Sed *
21212904Sdim * 3. All advertising materials mentioning features or use of this
22193326Sed *    software must display the following acknowledgment:
23193326Sed *    "This product includes software developed by the OpenSSL Project
24193326Sed *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25193326Sed *
26193326Sed * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27193326Sed *    endorse or promote products derived from this software without
28193326Sed *    prior written permission. For written permission, please contact
29193326Sed *    licensing@OpenSSL.org.
30193326Sed *
31193326Sed * 5. Products derived from this software may not be called "OpenSSL"
32193326Sed *    nor may "OpenSSL" appear in their names without prior written
33193326Sed *    permission of the OpenSSL Project.
34198092Srdivacky *
35193326Sed * 6. Redistributions of any form whatsoever must retain the following
36193326Sed *    acknowledgment:
37193326Sed *    "This product includes software developed by the OpenSSL Project
38193326Sed *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39193326Sed *
40193326Sed * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41193326Sed * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42193326Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43193326Sed * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44198092Srdivacky * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45235633Sdim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46208600Srdivacky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47198092Srdivacky * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48235633Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49208600Srdivacky * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50208600Srdivacky * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51208600Srdivacky * OF THE POSSIBILITY OF SUCH DAMAGE.
52208600Srdivacky * ====================================================================
53193326Sed *
54193326Sed * This product includes cryptographic software written by Eric Young
55198092Srdivacky * (eay@cryptsoft.com).  This product includes software written by Tim
56208600Srdivacky * Hudson (tjh@cryptsoft.com).
57208600Srdivacky *
58208600Srdivacky */
59193326Sed
60198092Srdivacky#include <stdio.h>
61226890Sdim#include <ctype.h>
62193326Sed#include <string.h>
63226890Sdim#include <openssl/bio.h>
64208600Srdivacky#include <openssl/evp.h>
65226890Sdim#include <openssl/hmac.h>
66226890Sdim#include <openssl/err.h>
67193326Sed#include <openssl/bn.h>
68193326Sed#include <openssl/x509v3.h>
69193326Sed
70210299Sed#ifndef OPENSSL_FIPS
71224145Sdim
72224145Sdimint main(int argc, char *argv[])
73224145Sdim{
74224145Sdim    printf("No FIPS RSA support\n");
75193326Sed    return (0);
76208600Srdivacky}
77235633Sdim
78208600Srdivacky#else
79218893Sdim
80226890Sdim# include <openssl/rsa.h>
81235633Sdim# include "fips_utl.h"
82235633Sdim
83208600Srdivackystatic int rsa_stest(FILE *out, FILE *in, int Saltlen);
84208600Srdivackystatic int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
85193326Sed                        unsigned char *Msg, long Msglen, int Saltlen);
86193326Sed
87193326Sedint main(int argc, char **argv)
88193326Sed{
89193326Sed    FILE *in = NULL, *out = NULL;
90193326Sed
91208600Srdivacky    int ret = 1, Saltlen = -1;
92198092Srdivacky
93193326Sed    if (!FIPS_mode_set(1)) {
94193326Sed        do_print_errors();
95224145Sdim        goto end;
96224145Sdim    }
97198092Srdivacky
98193326Sed    if ((argc > 2) && !strcmp("-saltlen", argv[1])) {
99193326Sed        Saltlen = atoi(argv[2]);
100208600Srdivacky        if (Saltlen < 0) {
101193326Sed            fprintf(stderr, "FATAL: Invalid salt length\n");
102198092Srdivacky            goto end;
103208600Srdivacky        }
104208600Srdivacky        argc -= 2;
105208600Srdivacky        argv += 2;
106208600Srdivacky    } else if ((argc > 1) && !strcmp("-x931", argv[1])) {
107208600Srdivacky        Saltlen = -2;
108208600Srdivacky        argc--;
109208600Srdivacky        argv++;
110208600Srdivacky    }
111208600Srdivacky
112208600Srdivacky    if (argc == 1)
113208600Srdivacky        in = stdin;
114208600Srdivacky    else
115208600Srdivacky        in = fopen(argv[1], "r");
116208600Srdivacky
117208600Srdivacky    if (argc < 2)
118208600Srdivacky        out = stdout;
119208600Srdivacky    else
120224145Sdim        out = fopen(argv[2], "w");
121224145Sdim
122193326Sed    if (!in) {
123193326Sed        fprintf(stderr, "FATAL input initialization error\n");
124224145Sdim        goto end;
125193326Sed    }
126245431Sdim
127193326Sed    if (!out) {
128208600Srdivacky        fprintf(stderr, "FATAL output initialization error\n");
129208600Srdivacky        goto end;
130224145Sdim    }
131224145Sdim
132224145Sdim    if (!rsa_stest(out, in, Saltlen)) {
133224145Sdim        fprintf(stderr, "FATAL RSASTEST file processing error\n");
134224145Sdim        goto end;
135224145Sdim    } else
136224145Sdim        ret = 0;
137224145Sdim
138235633Sdim end:
139224145Sdim
140224145Sdim    if (ret)
141224145Sdim        do_print_errors();
142224145Sdim
143224145Sdim    if (in && (in != stdin))
144224145Sdim        fclose(in);
145224145Sdim    if (out && (out != stdout))
146224145Sdim        fclose(out);
147224145Sdim
148224145Sdim    return ret;
149224145Sdim
150224145Sdim}
151224145Sdim
152235633Sdim# define RSA_TEST_MAXLINELEN     10240
153235633Sdim
154224145Sdimint rsa_stest(FILE *out, FILE *in, int Saltlen)
155224145Sdim{
156224145Sdim    char *linebuf, *olinebuf, *p, *q;
157224145Sdim    char *keyword, *value;
158224145Sdim    RSA *rsa = NULL;
159224145Sdim    const EVP_MD *dgst = NULL;
160224145Sdim    unsigned char *Msg = NULL;
161224145Sdim    long Msglen = -1;
162224145Sdim    int keylen = -1, current_keylen = -1;
163224145Sdim    int ret = 0;
164224145Sdim    int lnum = 0;
165224145Sdim
166224145Sdim    olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
167245431Sdim    linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
168245431Sdim
169245431Sdim    if (!linebuf || !olinebuf)
170224145Sdim        goto error;
171245431Sdim
172245431Sdim    while (fgets(olinebuf, RSA_TEST_MAXLINELEN, in)) {
173245431Sdim        lnum++;
174224145Sdim        strcpy(linebuf, olinebuf);
175245431Sdim        keyword = linebuf;
176245431Sdim        /* Skip leading space */
177224145Sdim        while (isspace((unsigned char)*keyword))
178245431Sdim            keyword++;
179245431Sdim
180224145Sdim        /* Look for = sign */
181245431Sdim        p = strchr(linebuf, '=');
182245431Sdim
183245431Sdim        /* If no = just copy */
184224145Sdim        if (!p) {
185245431Sdim            if (fputs(olinebuf, out) < 0)
186245431Sdim                goto error;
187245431Sdim            continue;
188245431Sdim        }
189245431Sdim
190245431Sdim        q = p - 1;
191245431Sdim
192245431Sdim        /* Remove trailing space */
193245431Sdim        while (isspace((unsigned char)*q))
194245431Sdim            *q-- = 0;
195245431Sdim
196245431Sdim        *p = 0;
197245431Sdim        value = p + 1;
198245431Sdim
199245431Sdim        /* Remove leading space from value */
200245431Sdim        while (isspace((unsigned char)*value))
201245431Sdim            value++;
202245431Sdim
203245431Sdim        /* Remove trailing space from value */
204245431Sdim        p = value + strlen(value) - 1;
205245431Sdim
206245431Sdim        while (*p == '\n' || isspace((unsigned char)*p))
207245431Sdim            *p-- = 0;
208210299Sed
209245431Sdim        /* Look for [mod = XXX] for key length */
210245431Sdim
211208600Srdivacky        if (!strcmp(keyword, "[mod")) {
212245431Sdim            p = value + strlen(value) - 1;
213245431Sdim            if (*p != ']')
214208600Srdivacky                goto parse_error;
215208600Srdivacky            *p = 0;
216208600Srdivacky            keylen = atoi(value);
217193326Sed            if (keylen < 0)
218224145Sdim                goto parse_error;
219193326Sed        } else if (!strcmp(keyword, "SHAAlg")) {
220198092Srdivacky            if (!strcmp(value, "SHA1"))
221221345Sdim                dgst = EVP_sha1();
222221345Sdim            else if (!strcmp(value, "SHA224"))
223224145Sdim                dgst = EVP_sha224();
224221345Sdim            else if (!strcmp(value, "SHA256"))
225221345Sdim                dgst = EVP_sha256();
226224145Sdim            else if (!strcmp(value, "SHA384"))
227193326Sed                dgst = EVP_sha384();
228193326Sed            else if (!strcmp(value, "SHA512"))
229210299Sed                dgst = EVP_sha512();
230210299Sed            else {
231210299Sed                fprintf(stderr,
232224145Sdim                        "FATAL: unsupported algorithm \"%s\"\n", value);
233210299Sed                goto parse_error;
234210299Sed            }
235210299Sed        } else if (!strcmp(keyword, "Msg")) {
236210299Sed            if (Msg)
237210299Sed                goto parse_error;
238210299Sed            if (strlen(value) & 1)
239210299Sed                *(--value) = '0';
240210299Sed            Msg = hex2bin_m(value, &Msglen);
241210299Sed            if (!Msg)
242210299Sed                goto parse_error;
243210299Sed        }
244210299Sed
245193326Sed        fputs(olinebuf, out);
246224145Sdim
247224145Sdim        /*
248224145Sdim         * If key length has changed, generate and output public key
249224145Sdim         * components of new RSA private key.
250224145Sdim         */
251224145Sdim
252224145Sdim        if (keylen != current_keylen) {
253224145Sdim            BIGNUM *bn_e;
254224145Sdim            if (rsa)
255224145Sdim                FIPS_rsa_free(rsa);
256224145Sdim            rsa = FIPS_rsa_new();
257224145Sdim            if (!rsa)
258224145Sdim                goto error;
259224145Sdim            bn_e = BN_new();
260224145Sdim            if (!bn_e || !BN_set_word(bn_e, 0x1001))
261224145Sdim                goto error;
262224145Sdim            if (!RSA_X931_generate_key_ex(rsa, keylen, bn_e, NULL))
263224145Sdim                goto error;
264224145Sdim            BN_free(bn_e);
265224145Sdim            fputs("n = ", out);
266224145Sdim            do_bn_print(out, rsa->n);
267224145Sdim            fputs("\ne = ", out);
268224145Sdim            do_bn_print(out, rsa->e);
269224145Sdim            fputs("\n", out);
270224145Sdim            current_keylen = keylen;
271224145Sdim        }
272235633Sdim
273224145Sdim        if (Msg && dgst) {
274224145Sdim            if (!rsa_printsig(out, rsa, dgst, Msg, Msglen, Saltlen))
275224145Sdim                goto error;
276224145Sdim            OPENSSL_free(Msg);
277224145Sdim            Msg = NULL;
278224145Sdim        }
279224145Sdim
280224145Sdim    }
281224145Sdim
282224145Sdim    ret = 1;
283193326Sed
284193326Sed error:
285193326Sed
286193326Sed    if (olinebuf)
287224145Sdim        OPENSSL_free(olinebuf);
288224145Sdim    if (linebuf)
289224145Sdim        OPENSSL_free(linebuf);
290224145Sdim    if (rsa)
291224145Sdim        FIPS_rsa_free(rsa);
292224145Sdim
293224145Sdim    return ret;
294224145Sdim
295210299Sed parse_error:
296210299Sed
297193326Sed    fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
298208600Srdivacky
299208600Srdivacky    goto error;
300208600Srdivacky
301208600Srdivacky}
302208600Srdivacky
303208600Srdivackystatic int rsa_printsig(FILE *out, RSA *rsa, const EVP_MD *dgst,
304218893Sdim                        unsigned char *Msg, long Msglen, int Saltlen)
305218893Sdim{
306218893Sdim    int ret = 0;
307218893Sdim    unsigned char *sigbuf = NULL;
308218893Sdim    int i, siglen;
309218893Sdim    /* EVP_PKEY structure */
310218893Sdim    EVP_PKEY pk;
311218893Sdim    EVP_MD_CTX ctx;
312218893Sdim    pk.type = EVP_PKEY_RSA;
313218893Sdim    pk.pkey.rsa = rsa;
314218893Sdim
315208600Srdivacky    siglen = RSA_size(rsa);
316208600Srdivacky    sigbuf = OPENSSL_malloc(siglen);
317208600Srdivacky    if (!sigbuf)
318208600Srdivacky        goto error;
319210299Sed
320210299Sed    EVP_MD_CTX_init(&ctx);
321210299Sed
322210299Sed    if (Saltlen >= 0) {
323210299Sed        M_EVP_MD_CTX_set_flags(&ctx,
324210299Sed                               EVP_MD_CTX_FLAG_PAD_PSS | (Saltlen << 16));
325210299Sed    } else if (Saltlen == -2)
326210299Sed        M_EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_PAD_X931);
327210299Sed    if (!EVP_SignInit_ex(&ctx, dgst, NULL))
328208600Srdivacky        goto error;
329193326Sed    if (!EVP_SignUpdate(&ctx, Msg, Msglen))
330193326Sed        goto error;
331193326Sed    if (!EVP_SignFinal(&ctx, sigbuf, (unsigned int *)&siglen, &pk))
332193326Sed        goto error;
333208600Srdivacky
334208600Srdivacky    EVP_MD_CTX_cleanup(&ctx);
335245431Sdim
336245431Sdim    fputs("S = ", out);
337245431Sdim
338245431Sdim    for (i = 0; i < siglen; i++)
339245431Sdim        fprintf(out, "%02X", sigbuf[i]);
340245431Sdim
341245431Sdim    fputs("\n", out);
342245431Sdim
343245431Sdim    ret = 1;
344245431Sdim
345245431Sdim error:
346245431Sdim
347245431Sdim    return ret;
348245431Sdim}
349245431Sdim#endif
350245431Sdim