Workaround for some CMS signature formats.
[openssl.git] / fips / sha / fips_shatest.c
1 /* fips_shatest.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2005.
4  */
5 /* ====================================================================
6  * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #define OPENSSL_FIPSAPI
60
61 #include <stdio.h>
62 #include <ctype.h>
63 #include <string.h>
64 #include <openssl/bio.h>
65 #include <openssl/evp.h>
66 #include <openssl/err.h>
67 #include <openssl/bn.h>
68
69 #ifndef OPENSSL_FIPS
70
71 int main(int argc, char *argv[])
72 {
73     printf("No FIPS SHAXXX support\n");
74     return(0);
75 }
76
77 #else
78
79 #include <openssl/fips.h>
80
81 #include "fips_utl.h"
82
83 static int dgst_test(FILE *out, FILE *in);
84 static int print_dgst(const EVP_MD *md, FILE *out,
85                 unsigned char *Msg, int Msglen);
86 static int print_monte(const EVP_MD *md, FILE *out,
87                 unsigned char *Seed, int SeedLen);
88
89 #ifdef FIPS_ALGVS
90 int fips_shatest_main(int argc, char **argv)
91 #else
92 int main(int argc, char **argv)
93 #endif
94         {
95         FILE *in = NULL, *out = NULL;
96
97         int ret = 1;
98         fips_algtest_init();
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                 {
112                 fprintf(stderr, "FATAL input initialization error\n");
113                 goto end;
114                 }
115
116         if (!out)
117                 {
118                 fprintf(stderr, "FATAL output initialization error\n");
119                 goto end;
120                 }
121
122         if (!dgst_test(out, in))
123                 {
124                 fprintf(stderr, "FATAL digest file processing error\n");
125                 goto end;
126                 }
127         else
128                 ret = 0;
129
130         end:
131
132         if (in && (in != stdin))
133                 fclose(in);
134         if (out && (out != stdout))
135                 fclose(out);
136
137         return ret;
138
139         }
140
141 #define SHA_TEST_MAX_BITS       102400
142 #define SHA_TEST_MAXLINELEN     (((SHA_TEST_MAX_BITS >> 3) * 2) + 100)
143
144 int dgst_test(FILE *out, FILE *in)
145         {
146         const EVP_MD *md = NULL;
147         char *linebuf, *olinebuf, *p, *q;
148         char *keyword, *value;
149         unsigned char *Msg = NULL, *Seed = NULL;
150         long MsgLen = -1, Len = -1, SeedLen = -1;
151         int ret = 0;
152         int lnum = 0;
153
154         olinebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN);
155         linebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN);
156
157         if (!linebuf || !olinebuf)
158                 goto error;
159
160
161         while (fgets(olinebuf, SHA_TEST_MAXLINELEN, in))
162                 {
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                         {
176                         fputs(olinebuf, out);
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                 while (*p == '\n' || isspace((unsigned char)*p))
196                         *p-- = 0;
197
198                 if (!strcmp(keyword,"[L") && *p==']')
199                         {
200                         switch (atoi(value))
201                                 {
202                                 case 20: md=EVP_sha1();   break;
203                                 case 28: md=EVP_sha224(); break;
204                                 case 32: md=EVP_sha256(); break;
205                                 case 48: md=EVP_sha384(); break;
206                                 case 64: md=EVP_sha512(); break;
207                                 default: goto parse_error;
208                                 }
209                         }
210                 else if (!strcmp(keyword, "Len"))
211                         {
212                         if (Len != -1)
213                                 goto parse_error;
214                         Len = atoi(value);
215                         if (Len < 0)
216                                 goto parse_error;
217                         /* Only handle multiples of 8 bits */
218                         if (Len & 0x7)
219                                 goto parse_error;
220                         if (Len > SHA_TEST_MAX_BITS)
221                                 goto parse_error;
222                         MsgLen = Len >> 3;
223                         }
224
225                 else if (!strcmp(keyword, "Msg"))
226                         {
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                         }
236                 else if (!strcmp(keyword, "Seed"))
237                         {
238                         if (strlen(value) & 1)
239                                 *(--value) = '0';
240                         if (Seed)
241                                 goto parse_error;
242                         Seed = hex2bin_m(value, &SeedLen);
243                         if (!Seed)
244                                 goto parse_error;
245                         }
246                 else if (!strcmp(keyword, "MD"))
247                         continue;
248                 else
249                         goto parse_error;
250
251                 fputs(olinebuf, out);
252
253                 if (md && Msg && (MsgLen >= 0))
254                         {
255                         if (!print_dgst(md, out, Msg, MsgLen))
256                                 goto error;
257                         OPENSSL_free(Msg);
258                         Msg = NULL;
259                         MsgLen = -1;
260                         Len = -1;
261                         }
262                 else if (md && Seed && (SeedLen > 0))
263                         {
264                         if (!print_monte(md, out, Seed, SeedLen))
265                                 goto error;
266                         OPENSSL_free(Seed);
267                         Seed = NULL;
268                         SeedLen = -1;
269                         }
270         
271
272                 }
273
274
275         ret = 1;
276
277
278         error:
279
280         if (olinebuf)
281                 OPENSSL_free(olinebuf);
282         if (linebuf)
283                 OPENSSL_free(linebuf);
284         if (Msg)
285                 OPENSSL_free(Msg);
286         if (Seed)
287                 OPENSSL_free(Seed);
288
289         return ret;
290
291         parse_error:
292
293         fprintf(stderr, "FATAL parse error processing line %d\n", lnum);
294
295         goto error;
296
297         }
298
299 static int print_dgst(const EVP_MD *emd, FILE *out,
300                 unsigned char *Msg, int Msglen)
301         {
302         int i, mdlen;
303         unsigned char md[EVP_MAX_MD_SIZE];
304         if (!FIPS_digest(Msg, Msglen, md, (unsigned int *)&mdlen, emd))
305                 {
306                 fputs("Error calculating HASH\n", stderr);
307                 return 0;
308                 }
309         fputs("MD = ", out);
310         for (i = 0; i < mdlen; i++)
311                 fprintf(out, "%02x", md[i]);
312         fputs(RESP_EOL, out);
313         return 1;
314         }
315
316 static int print_monte(const EVP_MD *md, FILE *out,
317                 unsigned char *Seed, int SeedLen)
318         {
319         unsigned int i, j, k;
320         int ret = 0;
321         EVP_MD_CTX ctx;
322         unsigned char *m1, *m2, *m3, *p;
323         unsigned int mlen, m1len, m2len, m3len;
324
325         FIPS_md_ctx_init(&ctx);
326
327         if (SeedLen > EVP_MAX_MD_SIZE)
328                 mlen = SeedLen;
329         else
330                 mlen = EVP_MAX_MD_SIZE;
331
332         m1 = OPENSSL_malloc(mlen);
333         m2 = OPENSSL_malloc(mlen);
334         m3 = OPENSSL_malloc(mlen);
335
336         if (!m1 || !m2 || !m3)
337                 goto mc_error;
338
339         m1len = m2len = m3len = SeedLen;
340         memcpy(m1, Seed, SeedLen);
341         memcpy(m2, Seed, SeedLen);
342         memcpy(m3, Seed, SeedLen);
343
344         fputs(RESP_EOL, out);
345
346         for (j = 0; j < 100; j++)
347                 {
348                 for (i = 0; i < 1000; i++)
349                         {
350                         FIPS_digestinit(&ctx, md);
351                         FIPS_digestupdate(&ctx, m1, m1len);
352                         FIPS_digestupdate(&ctx, m2, m2len);
353                         FIPS_digestupdate(&ctx, m3, m3len);
354                         p = m1;
355                         m1 = m2;
356                         m1len = m2len;
357                         m2 = m3;
358                         m2len = m3len;
359                         m3 = p;
360                         FIPS_digestfinal(&ctx, m3, &m3len);
361                         }
362                 fprintf(out, "COUNT = %d" RESP_EOL, j);
363                 fputs("MD = ", out);
364                 for (k = 0; k < m3len; k++)
365                         fprintf(out, "%02x", m3[k]);
366                 fputs(RESP_EOL RESP_EOL, out);
367                 memcpy(m1, m3, m3len);
368                 memcpy(m2, m3, m3len);
369                 m1len = m2len = m3len;
370                 }
371
372         ret = 1;
373
374         mc_error:
375         if (m1)
376                 OPENSSL_free(m1);
377         if (m2)
378                 OPENSSL_free(m2);
379         if (m3)
380                 OPENSSL_free(m3);
381
382         FIPS_md_ctx_cleanup(&ctx);
383
384         return ret;
385         }
386
387 #endif