fips_hmactest.c revision 296465
1/* fips_hmactest.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/bn.h>
68
69#include <openssl/x509v3.h>
70
71#ifndef OPENSSL_FIPS
72
73int main(int argc, char *argv[])
74{
75    printf("No FIPS HMAC support\n");
76    return (0);
77}
78
79#else
80
81# include <openssl/fips.h>
82# include "fips_utl.h"
83
84static int hmac_test(const EVP_MD *md, FILE *out, FILE *in);
85static int print_hmac(const EVP_MD *md, FILE *out,
86                      unsigned char *Key, int Klen,
87                      unsigned char *Msg, int Msglen, int Tlen);
88
89int main(int argc, char **argv)
90{
91    FILE *in = NULL, *out = NULL;
92
93    int ret = 1;
94
95    if (!FIPS_mode_set(1)) {
96        do_print_errors();
97        goto end;
98    }
99
100    if (argc == 1)
101        in = stdin;
102    else
103        in = fopen(argv[1], "r");
104
105    if (argc < 2)
106        out = stdout;
107    else
108        out = fopen(argv[2], "w");
109
110    if (!in) {
111        fprintf(stderr, "FATAL input initialization error\n");
112        goto end;
113    }
114
115    if (!out) {
116        fprintf(stderr, "FATAL output initialization error\n");
117        goto end;
118    }
119
120    if (!hmac_test(EVP_sha1(), out, in)) {
121        fprintf(stderr, "FATAL hmac file processing error\n");
122        goto end;
123    } else
124        ret = 0;
125
126 end:
127
128    if (ret)
129        do_print_errors();
130
131    if (in && (in != stdin))
132        fclose(in);
133    if (out && (out != stdout))
134        fclose(out);
135
136    return ret;
137
138}
139
140# define HMAC_TEST_MAXLINELEN    1024
141
142int hmac_test(const EVP_MD *md, FILE *out, FILE *in)
143{
144    char *linebuf, *olinebuf, *p, *q;
145    char *keyword, *value;
146    unsigned char *Key = NULL, *Msg = NULL;
147    int Count, Klen, Tlen;
148    long Keylen, Msglen;
149    int ret = 0;
150    int lnum = 0;
151
152    olinebuf = OPENSSL_malloc(HMAC_TEST_MAXLINELEN);
153    linebuf = OPENSSL_malloc(HMAC_TEST_MAXLINELEN);
154
155    if (!linebuf || !olinebuf)
156        goto error;
157
158    Count = -1;
159    Klen = -1;
160    Tlen = -1;
161
162    while (fgets(olinebuf, HMAC_TEST_MAXLINELEN, in)) {
163        lnum++;
164        strcpy(linebuf, olinebuf);
165        keyword = linebuf;
166        /* Skip leading space */
167        while (isspace((unsigned char)*keyword))
168            keyword++;
169
170        /* Look for = sign */
171        p = strchr(linebuf, '=');
172
173        /* If no = or starts with [ (for [L=20] line) just copy */
174        if (!p) {
175            if (fputs(olinebuf, out) < 0)
176                goto error;
177            continue;
178        }
179
180        q = p - 1;
181
182        /* Remove trailing space */
183        while (isspace((unsigned char)*q))
184            *q-- = 0;
185
186        *p = 0;
187        value = p + 1;
188
189        /* Remove leading space from value */
190        while (isspace((unsigned char)*value))
191            value++;
192
193        /* Remove trailing space from value */
194        p = value + strlen(value) - 1;
195
196        while (*p == '\n' || isspace((unsigned char)*p))
197            *p-- = 0;
198
199        if (!strcmp(keyword, "[L") && *p == ']') {
200            switch (atoi(value)) {
201            case 20:
202                md = EVP_sha1();
203                break;
204            case 28:
205                md = EVP_sha224();
206                break;
207            case 32:
208                md = EVP_sha256();
209                break;
210            case 48:
211                md = EVP_sha384();
212                break;
213            case 64:
214                md = EVP_sha512();
215                break;
216            default:
217                goto parse_error;
218            }
219        } else if (!strcmp(keyword, "Count")) {
220            if (Count != -1)
221                goto parse_error;
222            Count = atoi(value);
223            if (Count < 0)
224                goto parse_error;
225        } else if (!strcmp(keyword, "Klen")) {
226            if (Klen != -1)
227                goto parse_error;
228            Klen = atoi(value);
229            if (Klen < 0)
230                goto parse_error;
231        } else if (!strcmp(keyword, "Tlen")) {
232            if (Tlen != -1)
233                goto parse_error;
234            Tlen = atoi(value);
235            if (Tlen < 0)
236                goto parse_error;
237        } else if (!strcmp(keyword, "Msg")) {
238            if (Msg)
239                goto parse_error;
240            Msg = hex2bin_m(value, &Msglen);
241            if (!Msg)
242                goto parse_error;
243        } else if (!strcmp(keyword, "Key")) {
244            if (Key)
245                goto parse_error;
246            Key = hex2bin_m(value, &Keylen);
247            if (!Key)
248                goto parse_error;
249        } else if (!strcmp(keyword, "Mac"))
250            continue;
251        else
252            goto parse_error;
253
254        fputs(olinebuf, out);
255
256        if (Key && Msg && (Tlen > 0) && (Klen > 0)) {
257            if (!print_hmac(md, out, Key, Klen, Msg, Msglen, Tlen))
258                goto error;
259            OPENSSL_free(Key);
260            Key = NULL;
261            OPENSSL_free(Msg);
262            Msg = NULL;
263            Klen = -1;
264            Tlen = -1;
265            Count = -1;
266        }
267
268    }
269
270    ret = 1;
271
272 error:
273
274    if (olinebuf)
275        OPENSSL_free(olinebuf);
276    if (linebuf)
277        OPENSSL_free(linebuf);
278    if (Key)
279        OPENSSL_free(Key);
280    if (Msg)
281        OPENSSL_free(Msg);
282
283    return ret;
284
285 parse_error:
286
287    fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
288
289    goto error;
290
291}
292
293static int print_hmac(const EVP_MD *emd, FILE *out,
294                      unsigned char *Key, int Klen,
295                      unsigned char *Msg, int Msglen, int Tlen)
296{
297    int i, mdlen;
298    unsigned char md[EVP_MAX_MD_SIZE];
299    if (!HMAC(emd, Key, Klen, Msg, Msglen, md, (unsigned int *)&mdlen)) {
300        fputs("Error calculating HMAC\n", stderr);
301        return 0;
302    }
303    if (Tlen > mdlen) {
304        fputs("Parameter error, Tlen > HMAC length\n", stderr);
305        return 0;
306    }
307    fputs("Mac = ", out);
308    for (i = 0; i < Tlen; i++)
309        fprintf(out, "%02x", md[i]);
310    fputs("\n", out);
311    return 1;
312}
313
314#endif
315