fips_shatest.c revision 296465
1/* fips_shatest.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/err.h>
66#include <openssl/bn.h>
67#include <openssl/x509v3.h>
68
69#ifndef OPENSSL_FIPS
70
71int main(int argc, char *argv[])
72{
73    printf("No FIPS SHAXXX support\n");
74    return (0);
75}
76
77#else
78
79# include "fips_utl.h"
80
81static int dgst_test(FILE *out, FILE *in);
82static int print_dgst(const EVP_MD *md, FILE *out,
83                      unsigned char *Msg, int Msglen);
84static int print_monte(const EVP_MD *md, FILE *out,
85                       unsigned char *Seed, int SeedLen);
86
87int main(int argc, char **argv)
88{
89    FILE *in = NULL, *out = NULL;
90
91    int ret = 1;
92
93    if (!FIPS_mode_set(1)) {
94        do_print_errors();
95        goto end;
96    }
97
98    if (argc == 1)
99        in = stdin;
100    else
101        in = fopen(argv[1], "r");
102
103    if (argc < 2)
104        out = stdout;
105    else
106        out = fopen(argv[2], "w");
107
108    if (!in) {
109        fprintf(stderr, "FATAL input initialization error\n");
110        goto end;
111    }
112
113    if (!out) {
114        fprintf(stderr, "FATAL output initialization error\n");
115        goto end;
116    }
117
118    if (!dgst_test(out, in)) {
119        fprintf(stderr, "FATAL digest file processing error\n");
120        goto end;
121    } else
122        ret = 0;
123
124 end:
125
126    if (ret)
127        do_print_errors();
128
129    if (in && (in != stdin))
130        fclose(in);
131    if (out && (out != stdout))
132        fclose(out);
133
134    return ret;
135
136}
137
138# define SHA_TEST_MAX_BITS       102400
139# define SHA_TEST_MAXLINELEN     (((SHA_TEST_MAX_BITS >> 3) * 2) + 100)
140
141int dgst_test(FILE *out, FILE *in)
142{
143    const EVP_MD *md = NULL;
144    char *linebuf, *olinebuf, *p, *q;
145    char *keyword, *value;
146    unsigned char *Msg = NULL, *Seed = NULL;
147    long MsgLen = -1, Len = -1, SeedLen = -1;
148    int ret = 0;
149    int lnum = 0;
150
151    olinebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN);
152    linebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN);
153
154    if (!linebuf || !olinebuf)
155        goto error;
156
157    while (fgets(olinebuf, SHA_TEST_MAXLINELEN, in)) {
158        lnum++;
159        strcpy(linebuf, olinebuf);
160        keyword = linebuf;
161        /* Skip leading space */
162        while (isspace((unsigned char)*keyword))
163            keyword++;
164
165        /* Look for = sign */
166        p = strchr(linebuf, '=');
167
168        /* If no = or starts with [ (for [L=20] line) just copy */
169        if (!p) {
170            fputs(olinebuf, out);
171            continue;
172        }
173
174        q = p - 1;
175
176        /* Remove trailing space */
177        while (isspace((unsigned char)*q))
178            *q-- = 0;
179
180        *p = 0;
181        value = p + 1;
182
183        /* Remove leading space from value */
184        while (isspace((unsigned char)*value))
185            value++;
186
187        /* Remove trailing space from value */
188        p = value + strlen(value) - 1;
189        while (*p == '\n' || isspace((unsigned char)*p))
190            *p-- = 0;
191
192        if (!strcmp(keyword, "[L") && *p == ']') {
193            switch (atoi(value)) {
194            case 20:
195                md = EVP_sha1();
196                break;
197            case 28:
198                md = EVP_sha224();
199                break;
200            case 32:
201                md = EVP_sha256();
202                break;
203            case 48:
204                md = EVP_sha384();
205                break;
206            case 64:
207                md = EVP_sha512();
208                break;
209            default:
210                goto parse_error;
211            }
212        } else if (!strcmp(keyword, "Len")) {
213            if (Len != -1)
214                goto parse_error;
215            Len = atoi(value);
216            if (Len < 0)
217                goto parse_error;
218            /* Only handle multiples of 8 bits */
219            if (Len & 0x7)
220                goto parse_error;
221            if (Len > SHA_TEST_MAX_BITS)
222                goto parse_error;
223            MsgLen = Len >> 3;
224        }
225
226        else if (!strcmp(keyword, "Msg")) {
227            long tmplen;
228            if (strlen(value) & 1)
229                *(--value) = '0';
230            if (Msg)
231                goto parse_error;
232            Msg = hex2bin_m(value, &tmplen);
233            if (!Msg)
234                goto parse_error;
235        } else if (!strcmp(keyword, "Seed")) {
236            if (strlen(value) & 1)
237                *(--value) = '0';
238            if (Seed)
239                goto parse_error;
240            Seed = hex2bin_m(value, &SeedLen);
241            if (!Seed)
242                goto parse_error;
243        } else if (!strcmp(keyword, "MD"))
244            continue;
245        else
246            goto parse_error;
247
248        fputs(olinebuf, out);
249
250        if (md && Msg && (MsgLen >= 0)) {
251            if (!print_dgst(md, out, Msg, MsgLen))
252                goto error;
253            OPENSSL_free(Msg);
254            Msg = NULL;
255            MsgLen = -1;
256            Len = -1;
257        } else if (md && Seed && (SeedLen > 0)) {
258            if (!print_monte(md, out, Seed, SeedLen))
259                goto error;
260            OPENSSL_free(Seed);
261            Seed = NULL;
262            SeedLen = -1;
263        }
264
265    }
266
267    ret = 1;
268
269 error:
270
271    if (olinebuf)
272        OPENSSL_free(olinebuf);
273    if (linebuf)
274        OPENSSL_free(linebuf);
275    if (Msg)
276        OPENSSL_free(Msg);
277    if (Seed)
278        OPENSSL_free(Seed);
279
280    return ret;
281
282 parse_error:
283
284    fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
285
286    goto error;
287
288}
289
290static int print_dgst(const EVP_MD *emd, FILE *out,
291                      unsigned char *Msg, int Msglen)
292{
293    int i, mdlen;
294    unsigned char md[EVP_MAX_MD_SIZE];
295    if (!EVP_Digest(Msg, Msglen, md, (unsigned int *)&mdlen, emd, NULL)) {
296        fputs("Error calculating HASH\n", stderr);
297        return 0;
298    }
299    fputs("MD = ", out);
300    for (i = 0; i < mdlen; i++)
301        fprintf(out, "%02x", md[i]);
302    fputs("\n", out);
303    return 1;
304}
305
306static int print_monte(const EVP_MD *md, FILE *out,
307                       unsigned char *Seed, int SeedLen)
308{
309    unsigned int i, j, k;
310    int ret = 0;
311    EVP_MD_CTX ctx;
312    unsigned char *m1, *m2, *m3, *p;
313    unsigned int mlen, m1len, m2len, m3len;
314
315    EVP_MD_CTX_init(&ctx);
316
317    if (SeedLen > EVP_MAX_MD_SIZE)
318        mlen = SeedLen;
319    else
320        mlen = EVP_MAX_MD_SIZE;
321
322    m1 = OPENSSL_malloc(mlen);
323    m2 = OPENSSL_malloc(mlen);
324    m3 = OPENSSL_malloc(mlen);
325
326    if (!m1 || !m2 || !m3)
327        goto mc_error;
328
329    m1len = m2len = m3len = SeedLen;
330    memcpy(m1, Seed, SeedLen);
331    memcpy(m2, Seed, SeedLen);
332    memcpy(m3, Seed, SeedLen);
333
334    fputs("\n", out);
335
336    for (j = 0; j < 100; j++) {
337        for (i = 0; i < 1000; i++) {
338            EVP_DigestInit_ex(&ctx, md, NULL);
339            EVP_DigestUpdate(&ctx, m1, m1len);
340            EVP_DigestUpdate(&ctx, m2, m2len);
341            EVP_DigestUpdate(&ctx, m3, m3len);
342            p = m1;
343            m1 = m2;
344            m1len = m2len;
345            m2 = m3;
346            m2len = m3len;
347            m3 = p;
348            EVP_DigestFinal_ex(&ctx, m3, &m3len);
349        }
350        fprintf(out, "COUNT = %d\n", j);
351        fputs("MD = ", out);
352        for (k = 0; k < m3len; k++)
353            fprintf(out, "%02x", m3[k]);
354        fputs("\n\n", out);
355        memcpy(m1, m3, m3len);
356        memcpy(m2, m3, m3len);
357        m1len = m2len = m3len;
358    }
359
360    ret = 1;
361
362 mc_error:
363    if (m1)
364        OPENSSL_free(m1);
365    if (m2)
366        OPENSSL_free(m2);
367    if (m3)
368        OPENSSL_free(m3);
369
370    EVP_MD_CTX_cleanup(&ctx);
371
372    return ret;
373}
374
375#endif
376