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