Run util/openssl-format-source -v -c .
[openssl.git] / fips / hmac / fips_hmactest.c
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
73 int 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
84 static int hmac_test(const EVP_MD *md, FILE *out, FILE *in);
85 static int print_hmac(const EVP_MD *md, FILE *out,
86                       unsigned char *Key, int Klen,
87                       unsigned char *Msg, int Msglen, int Tlen);
88
89 int 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
142 int 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
293 static 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