1193645Ssimon/* fips_shatest.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 2005. 5193645Ssimon */ 6193645Ssimon/* ==================================================================== 7193645Ssimon * Copyright (c) 2005 The OpenSSL Project. All rights reserved. 8193645Ssimon * 9193645Ssimon * Redistribution and use in source and binary forms, with or without 10193645Ssimon * modification, are permitted provided that the following conditions 11193645Ssimon * are met: 12193645Ssimon * 13193645Ssimon * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15193645Ssimon * 16193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17193645Ssimon * notice, this list of conditions and the following disclaimer in 18193645Ssimon * the documentation and/or other materials provided with the 19193645Ssimon * distribution. 20193645Ssimon * 21193645Ssimon * 3. All advertising materials mentioning features or use of this 22193645Ssimon * software must display the following acknowledgment: 23193645Ssimon * "This product includes software developed by the OpenSSL Project 24193645Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25193645Ssimon * 26193645Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27193645Ssimon * endorse or promote products derived from this software without 28193645Ssimon * prior written permission. For written permission, please contact 29193645Ssimon * licensing@OpenSSL.org. 30193645Ssimon * 31193645Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32193645Ssimon * nor may "OpenSSL" appear in their names without prior written 33193645Ssimon * permission of the OpenSSL Project. 34193645Ssimon * 35193645Ssimon * 6. Redistributions of any form whatsoever must retain the following 36193645Ssimon * acknowledgment: 37193645Ssimon * "This product includes software developed by the OpenSSL Project 38193645Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39193645Ssimon * 40193645Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41193645Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43193645Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44193645Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45193645Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46193645Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47193645Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49193645Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50193645Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51193645Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52193645Ssimon * ==================================================================== 53193645Ssimon * 54193645Ssimon * This product includes cryptographic software written by Eric Young 55193645Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 56193645Ssimon * Hudson (tjh@cryptsoft.com). 57193645Ssimon * 58193645Ssimon */ 59193645Ssimon 60193645Ssimon#include <stdio.h> 61193645Ssimon#include <ctype.h> 62193645Ssimon#include <string.h> 63193645Ssimon#include <openssl/bio.h> 64193645Ssimon#include <openssl/evp.h> 65193645Ssimon#include <openssl/err.h> 66193645Ssimon#include <openssl/bn.h> 67193645Ssimon#include <openssl/x509v3.h> 68193645Ssimon 69193645Ssimon#ifndef OPENSSL_FIPS 70193645Ssimon 71193645Ssimonint main(int argc, char *argv[]) 72193645Ssimon{ 73193645Ssimon printf("No FIPS SHAXXX support\n"); 74296465Sdelphij return (0); 75193645Ssimon} 76193645Ssimon 77193645Ssimon#else 78193645Ssimon 79296465Sdelphij# include "fips_utl.h" 80193645Ssimon 81193645Ssimonstatic int dgst_test(FILE *out, FILE *in); 82193645Ssimonstatic int print_dgst(const EVP_MD *md, FILE *out, 83296465Sdelphij unsigned char *Msg, int Msglen); 84193645Ssimonstatic int print_monte(const EVP_MD *md, FILE *out, 85296465Sdelphij unsigned char *Seed, int SeedLen); 86193645Ssimon 87193645Ssimonint main(int argc, char **argv) 88296465Sdelphij{ 89296465Sdelphij FILE *in = NULL, *out = NULL; 90193645Ssimon 91296465Sdelphij int ret = 1; 92193645Ssimon 93296465Sdelphij if (!FIPS_mode_set(1)) { 94296465Sdelphij do_print_errors(); 95296465Sdelphij goto end; 96296465Sdelphij } 97193645Ssimon 98296465Sdelphij if (argc == 1) 99296465Sdelphij in = stdin; 100296465Sdelphij else 101296465Sdelphij in = fopen(argv[1], "r"); 102193645Ssimon 103296465Sdelphij if (argc < 2) 104296465Sdelphij out = stdout; 105296465Sdelphij else 106296465Sdelphij out = fopen(argv[2], "w"); 107193645Ssimon 108296465Sdelphij if (!in) { 109296465Sdelphij fprintf(stderr, "FATAL input initialization error\n"); 110296465Sdelphij goto end; 111296465Sdelphij } 112193645Ssimon 113296465Sdelphij if (!out) { 114296465Sdelphij fprintf(stderr, "FATAL output initialization error\n"); 115296465Sdelphij goto end; 116296465Sdelphij } 117193645Ssimon 118296465Sdelphij if (!dgst_test(out, in)) { 119296465Sdelphij fprintf(stderr, "FATAL digest file processing error\n"); 120296465Sdelphij goto end; 121296465Sdelphij } else 122296465Sdelphij ret = 0; 123193645Ssimon 124296465Sdelphij end: 125193645Ssimon 126296465Sdelphij if (ret) 127296465Sdelphij do_print_errors(); 128193645Ssimon 129296465Sdelphij if (in && (in != stdin)) 130296465Sdelphij fclose(in); 131296465Sdelphij if (out && (out != stdout)) 132296465Sdelphij fclose(out); 133193645Ssimon 134296465Sdelphij return ret; 135193645Ssimon 136296465Sdelphij} 137193645Ssimon 138296465Sdelphij# define SHA_TEST_MAX_BITS 102400 139296465Sdelphij# define SHA_TEST_MAXLINELEN (((SHA_TEST_MAX_BITS >> 3) * 2) + 100) 140193645Ssimon 141193645Ssimonint dgst_test(FILE *out, FILE *in) 142296465Sdelphij{ 143296465Sdelphij const EVP_MD *md = NULL; 144296465Sdelphij char *linebuf, *olinebuf, *p, *q; 145296465Sdelphij char *keyword, *value; 146296465Sdelphij unsigned char *Msg = NULL, *Seed = NULL; 147296465Sdelphij long MsgLen = -1, Len = -1, SeedLen = -1; 148296465Sdelphij int ret = 0; 149296465Sdelphij int lnum = 0; 150193645Ssimon 151296465Sdelphij olinebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN); 152296465Sdelphij linebuf = OPENSSL_malloc(SHA_TEST_MAXLINELEN); 153193645Ssimon 154296465Sdelphij if (!linebuf || !olinebuf) 155296465Sdelphij goto error; 156193645Ssimon 157296465Sdelphij while (fgets(olinebuf, SHA_TEST_MAXLINELEN, in)) { 158296465Sdelphij lnum++; 159296465Sdelphij strcpy(linebuf, olinebuf); 160296465Sdelphij keyword = linebuf; 161296465Sdelphij /* Skip leading space */ 162296465Sdelphij while (isspace((unsigned char)*keyword)) 163296465Sdelphij keyword++; 164193645Ssimon 165296465Sdelphij /* Look for = sign */ 166296465Sdelphij p = strchr(linebuf, '='); 167193645Ssimon 168296465Sdelphij /* If no = or starts with [ (for [L=20] line) just copy */ 169296465Sdelphij if (!p) { 170296465Sdelphij fputs(olinebuf, out); 171296465Sdelphij continue; 172296465Sdelphij } 173193645Ssimon 174296465Sdelphij q = p - 1; 175193645Ssimon 176296465Sdelphij /* Remove trailing space */ 177296465Sdelphij while (isspace((unsigned char)*q)) 178296465Sdelphij *q-- = 0; 179193645Ssimon 180296465Sdelphij *p = 0; 181296465Sdelphij value = p + 1; 182193645Ssimon 183296465Sdelphij /* Remove leading space from value */ 184296465Sdelphij while (isspace((unsigned char)*value)) 185296465Sdelphij value++; 186193645Ssimon 187296465Sdelphij /* Remove trailing space from value */ 188296465Sdelphij p = value + strlen(value) - 1; 189296465Sdelphij while (*p == '\n' || isspace((unsigned char)*p)) 190296465Sdelphij *p-- = 0; 191193645Ssimon 192296465Sdelphij if (!strcmp(keyword, "[L") && *p == ']') { 193296465Sdelphij switch (atoi(value)) { 194296465Sdelphij case 20: 195296465Sdelphij md = EVP_sha1(); 196296465Sdelphij break; 197296465Sdelphij case 28: 198296465Sdelphij md = EVP_sha224(); 199296465Sdelphij break; 200296465Sdelphij case 32: 201296465Sdelphij md = EVP_sha256(); 202296465Sdelphij break; 203296465Sdelphij case 48: 204296465Sdelphij md = EVP_sha384(); 205296465Sdelphij break; 206296465Sdelphij case 64: 207296465Sdelphij md = EVP_sha512(); 208296465Sdelphij break; 209296465Sdelphij default: 210296465Sdelphij goto parse_error; 211296465Sdelphij } 212296465Sdelphij } else if (!strcmp(keyword, "Len")) { 213296465Sdelphij if (Len != -1) 214296465Sdelphij goto parse_error; 215296465Sdelphij Len = atoi(value); 216296465Sdelphij if (Len < 0) 217296465Sdelphij goto parse_error; 218296465Sdelphij /* Only handle multiples of 8 bits */ 219296465Sdelphij if (Len & 0x7) 220296465Sdelphij goto parse_error; 221296465Sdelphij if (Len > SHA_TEST_MAX_BITS) 222296465Sdelphij goto parse_error; 223296465Sdelphij MsgLen = Len >> 3; 224296465Sdelphij } 225193645Ssimon 226296465Sdelphij else if (!strcmp(keyword, "Msg")) { 227296465Sdelphij long tmplen; 228296465Sdelphij if (strlen(value) & 1) 229296465Sdelphij *(--value) = '0'; 230296465Sdelphij if (Msg) 231296465Sdelphij goto parse_error; 232296465Sdelphij Msg = hex2bin_m(value, &tmplen); 233296465Sdelphij if (!Msg) 234296465Sdelphij goto parse_error; 235296465Sdelphij } else if (!strcmp(keyword, "Seed")) { 236296465Sdelphij if (strlen(value) & 1) 237296465Sdelphij *(--value) = '0'; 238296465Sdelphij if (Seed) 239296465Sdelphij goto parse_error; 240296465Sdelphij Seed = hex2bin_m(value, &SeedLen); 241296465Sdelphij if (!Seed) 242296465Sdelphij goto parse_error; 243296465Sdelphij } else if (!strcmp(keyword, "MD")) 244296465Sdelphij continue; 245296465Sdelphij else 246296465Sdelphij goto parse_error; 247193645Ssimon 248296465Sdelphij fputs(olinebuf, out); 249193645Ssimon 250296465Sdelphij if (md && Msg && (MsgLen >= 0)) { 251296465Sdelphij if (!print_dgst(md, out, Msg, MsgLen)) 252296465Sdelphij goto error; 253296465Sdelphij OPENSSL_free(Msg); 254296465Sdelphij Msg = NULL; 255296465Sdelphij MsgLen = -1; 256296465Sdelphij Len = -1; 257296465Sdelphij } else if (md && Seed && (SeedLen > 0)) { 258296465Sdelphij if (!print_monte(md, out, Seed, SeedLen)) 259296465Sdelphij goto error; 260296465Sdelphij OPENSSL_free(Seed); 261296465Sdelphij Seed = NULL; 262296465Sdelphij SeedLen = -1; 263296465Sdelphij } 264193645Ssimon 265296465Sdelphij } 266193645Ssimon 267296465Sdelphij ret = 1; 268193645Ssimon 269296465Sdelphij error: 270193645Ssimon 271296465Sdelphij if (olinebuf) 272296465Sdelphij OPENSSL_free(olinebuf); 273296465Sdelphij if (linebuf) 274296465Sdelphij OPENSSL_free(linebuf); 275296465Sdelphij if (Msg) 276296465Sdelphij OPENSSL_free(Msg); 277296465Sdelphij if (Seed) 278296465Sdelphij OPENSSL_free(Seed); 279193645Ssimon 280296465Sdelphij return ret; 281193645Ssimon 282296465Sdelphij parse_error: 283193645Ssimon 284296465Sdelphij fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 285193645Ssimon 286296465Sdelphij goto error; 287193645Ssimon 288296465Sdelphij} 289193645Ssimon 290193645Ssimonstatic int print_dgst(const EVP_MD *emd, FILE *out, 291296465Sdelphij unsigned char *Msg, int Msglen) 292296465Sdelphij{ 293296465Sdelphij int i, mdlen; 294296465Sdelphij unsigned char md[EVP_MAX_MD_SIZE]; 295296465Sdelphij if (!EVP_Digest(Msg, Msglen, md, (unsigned int *)&mdlen, emd, NULL)) { 296296465Sdelphij fputs("Error calculating HASH\n", stderr); 297296465Sdelphij return 0; 298296465Sdelphij } 299296465Sdelphij fputs("MD = ", out); 300296465Sdelphij for (i = 0; i < mdlen; i++) 301296465Sdelphij fprintf(out, "%02x", md[i]); 302296465Sdelphij fputs("\n", out); 303296465Sdelphij return 1; 304296465Sdelphij} 305193645Ssimon 306193645Ssimonstatic int print_monte(const EVP_MD *md, FILE *out, 307296465Sdelphij unsigned char *Seed, int SeedLen) 308296465Sdelphij{ 309296465Sdelphij unsigned int i, j, k; 310296465Sdelphij int ret = 0; 311296465Sdelphij EVP_MD_CTX ctx; 312296465Sdelphij unsigned char *m1, *m2, *m3, *p; 313296465Sdelphij unsigned int mlen, m1len, m2len, m3len; 314193645Ssimon 315296465Sdelphij EVP_MD_CTX_init(&ctx); 316193645Ssimon 317296465Sdelphij if (SeedLen > EVP_MAX_MD_SIZE) 318296465Sdelphij mlen = SeedLen; 319296465Sdelphij else 320296465Sdelphij mlen = EVP_MAX_MD_SIZE; 321193645Ssimon 322296465Sdelphij m1 = OPENSSL_malloc(mlen); 323296465Sdelphij m2 = OPENSSL_malloc(mlen); 324296465Sdelphij m3 = OPENSSL_malloc(mlen); 325193645Ssimon 326296465Sdelphij if (!m1 || !m2 || !m3) 327296465Sdelphij goto mc_error; 328193645Ssimon 329296465Sdelphij m1len = m2len = m3len = SeedLen; 330296465Sdelphij memcpy(m1, Seed, SeedLen); 331296465Sdelphij memcpy(m2, Seed, SeedLen); 332296465Sdelphij memcpy(m3, Seed, SeedLen); 333193645Ssimon 334296465Sdelphij fputs("\n", out); 335193645Ssimon 336296465Sdelphij for (j = 0; j < 100; j++) { 337296465Sdelphij for (i = 0; i < 1000; i++) { 338296465Sdelphij EVP_DigestInit_ex(&ctx, md, NULL); 339296465Sdelphij EVP_DigestUpdate(&ctx, m1, m1len); 340296465Sdelphij EVP_DigestUpdate(&ctx, m2, m2len); 341296465Sdelphij EVP_DigestUpdate(&ctx, m3, m3len); 342296465Sdelphij p = m1; 343296465Sdelphij m1 = m2; 344296465Sdelphij m1len = m2len; 345296465Sdelphij m2 = m3; 346296465Sdelphij m2len = m3len; 347296465Sdelphij m3 = p; 348296465Sdelphij EVP_DigestFinal_ex(&ctx, m3, &m3len); 349296465Sdelphij } 350296465Sdelphij fprintf(out, "COUNT = %d\n", j); 351296465Sdelphij fputs("MD = ", out); 352296465Sdelphij for (k = 0; k < m3len; k++) 353296465Sdelphij fprintf(out, "%02x", m3[k]); 354296465Sdelphij fputs("\n\n", out); 355296465Sdelphij memcpy(m1, m3, m3len); 356296465Sdelphij memcpy(m2, m3, m3len); 357296465Sdelphij m1len = m2len = m3len; 358296465Sdelphij } 359193645Ssimon 360296465Sdelphij ret = 1; 361193645Ssimon 362296465Sdelphij mc_error: 363296465Sdelphij if (m1) 364296465Sdelphij OPENSSL_free(m1); 365296465Sdelphij if (m2) 366296465Sdelphij OPENSSL_free(m2); 367296465Sdelphij if (m3) 368296465Sdelphij OPENSSL_free(m3); 369193645Ssimon 370296465Sdelphij EVP_MD_CTX_cleanup(&ctx); 371193645Ssimon 372296465Sdelphij return ret; 373296465Sdelphij} 374193645Ssimon 375193645Ssimon#endif 376