1193645Ssimon/* fips_hmactest.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/hmac.h> 66193645Ssimon#include <openssl/err.h> 67193645Ssimon#include <openssl/bn.h> 68193645Ssimon 69193645Ssimon#include <openssl/x509v3.h> 70193645Ssimon 71193645Ssimon#ifndef OPENSSL_FIPS 72193645Ssimon 73193645Ssimonint main(int argc, char *argv[]) 74193645Ssimon{ 75193645Ssimon printf("No FIPS HMAC support\n"); 76296465Sdelphij return (0); 77193645Ssimon} 78193645Ssimon 79193645Ssimon#else 80193645Ssimon 81296465Sdelphij# include <openssl/fips.h> 82296465Sdelphij# include "fips_utl.h" 83193645Ssimon 84193645Ssimonstatic int hmac_test(const EVP_MD *md, FILE *out, FILE *in); 85193645Ssimonstatic int print_hmac(const EVP_MD *md, FILE *out, 86296465Sdelphij unsigned char *Key, int Klen, 87296465Sdelphij unsigned char *Msg, int Msglen, int Tlen); 88193645Ssimon 89193645Ssimonint main(int argc, char **argv) 90296465Sdelphij{ 91296465Sdelphij FILE *in = NULL, *out = NULL; 92193645Ssimon 93296465Sdelphij int ret = 1; 94193645Ssimon 95296465Sdelphij if (!FIPS_mode_set(1)) { 96296465Sdelphij do_print_errors(); 97296465Sdelphij goto end; 98296465Sdelphij } 99193645Ssimon 100296465Sdelphij if (argc == 1) 101296465Sdelphij in = stdin; 102296465Sdelphij else 103296465Sdelphij in = fopen(argv[1], "r"); 104193645Ssimon 105296465Sdelphij if (argc < 2) 106296465Sdelphij out = stdout; 107296465Sdelphij else 108296465Sdelphij out = fopen(argv[2], "w"); 109193645Ssimon 110296465Sdelphij if (!in) { 111296465Sdelphij fprintf(stderr, "FATAL input initialization error\n"); 112296465Sdelphij goto end; 113296465Sdelphij } 114193645Ssimon 115296465Sdelphij if (!out) { 116296465Sdelphij fprintf(stderr, "FATAL output initialization error\n"); 117296465Sdelphij goto end; 118296465Sdelphij } 119193645Ssimon 120296465Sdelphij if (!hmac_test(EVP_sha1(), out, in)) { 121296465Sdelphij fprintf(stderr, "FATAL hmac file processing error\n"); 122296465Sdelphij goto end; 123296465Sdelphij } else 124296465Sdelphij ret = 0; 125193645Ssimon 126296465Sdelphij end: 127193645Ssimon 128296465Sdelphij if (ret) 129296465Sdelphij do_print_errors(); 130193645Ssimon 131296465Sdelphij if (in && (in != stdin)) 132296465Sdelphij fclose(in); 133296465Sdelphij if (out && (out != stdout)) 134296465Sdelphij fclose(out); 135193645Ssimon 136296465Sdelphij return ret; 137193645Ssimon 138296465Sdelphij} 139193645Ssimon 140296465Sdelphij# define HMAC_TEST_MAXLINELEN 1024 141193645Ssimon 142193645Ssimonint hmac_test(const EVP_MD *md, FILE *out, FILE *in) 143296465Sdelphij{ 144296465Sdelphij char *linebuf, *olinebuf, *p, *q; 145296465Sdelphij char *keyword, *value; 146296465Sdelphij unsigned char *Key = NULL, *Msg = NULL; 147296465Sdelphij int Count, Klen, Tlen; 148296465Sdelphij long Keylen, Msglen; 149296465Sdelphij int ret = 0; 150296465Sdelphij int lnum = 0; 151193645Ssimon 152296465Sdelphij olinebuf = OPENSSL_malloc(HMAC_TEST_MAXLINELEN); 153296465Sdelphij linebuf = OPENSSL_malloc(HMAC_TEST_MAXLINELEN); 154193645Ssimon 155296465Sdelphij if (!linebuf || !olinebuf) 156296465Sdelphij goto error; 157193645Ssimon 158296465Sdelphij Count = -1; 159296465Sdelphij Klen = -1; 160296465Sdelphij Tlen = -1; 161193645Ssimon 162296465Sdelphij while (fgets(olinebuf, HMAC_TEST_MAXLINELEN, in)) { 163296465Sdelphij lnum++; 164296465Sdelphij strcpy(linebuf, olinebuf); 165296465Sdelphij keyword = linebuf; 166296465Sdelphij /* Skip leading space */ 167296465Sdelphij while (isspace((unsigned char)*keyword)) 168296465Sdelphij keyword++; 169193645Ssimon 170296465Sdelphij /* Look for = sign */ 171296465Sdelphij p = strchr(linebuf, '='); 172193645Ssimon 173296465Sdelphij /* If no = or starts with [ (for [L=20] line) just copy */ 174296465Sdelphij if (!p) { 175296465Sdelphij if (fputs(olinebuf, out) < 0) 176296465Sdelphij goto error; 177296465Sdelphij continue; 178296465Sdelphij } 179193645Ssimon 180296465Sdelphij q = p - 1; 181193645Ssimon 182296465Sdelphij /* Remove trailing space */ 183296465Sdelphij while (isspace((unsigned char)*q)) 184296465Sdelphij *q-- = 0; 185193645Ssimon 186296465Sdelphij *p = 0; 187296465Sdelphij value = p + 1; 188193645Ssimon 189296465Sdelphij /* Remove leading space from value */ 190296465Sdelphij while (isspace((unsigned char)*value)) 191296465Sdelphij value++; 192193645Ssimon 193296465Sdelphij /* Remove trailing space from value */ 194296465Sdelphij p = value + strlen(value) - 1; 195193645Ssimon 196296465Sdelphij while (*p == '\n' || isspace((unsigned char)*p)) 197296465Sdelphij *p-- = 0; 198193645Ssimon 199296465Sdelphij if (!strcmp(keyword, "[L") && *p == ']') { 200296465Sdelphij switch (atoi(value)) { 201296465Sdelphij case 20: 202296465Sdelphij md = EVP_sha1(); 203296465Sdelphij break; 204296465Sdelphij case 28: 205296465Sdelphij md = EVP_sha224(); 206296465Sdelphij break; 207296465Sdelphij case 32: 208296465Sdelphij md = EVP_sha256(); 209296465Sdelphij break; 210296465Sdelphij case 48: 211296465Sdelphij md = EVP_sha384(); 212296465Sdelphij break; 213296465Sdelphij case 64: 214296465Sdelphij md = EVP_sha512(); 215296465Sdelphij break; 216296465Sdelphij default: 217296465Sdelphij goto parse_error; 218296465Sdelphij } 219296465Sdelphij } else if (!strcmp(keyword, "Count")) { 220296465Sdelphij if (Count != -1) 221296465Sdelphij goto parse_error; 222296465Sdelphij Count = atoi(value); 223296465Sdelphij if (Count < 0) 224296465Sdelphij goto parse_error; 225296465Sdelphij } else if (!strcmp(keyword, "Klen")) { 226296465Sdelphij if (Klen != -1) 227296465Sdelphij goto parse_error; 228296465Sdelphij Klen = atoi(value); 229296465Sdelphij if (Klen < 0) 230296465Sdelphij goto parse_error; 231296465Sdelphij } else if (!strcmp(keyword, "Tlen")) { 232296465Sdelphij if (Tlen != -1) 233296465Sdelphij goto parse_error; 234296465Sdelphij Tlen = atoi(value); 235296465Sdelphij if (Tlen < 0) 236296465Sdelphij goto parse_error; 237296465Sdelphij } else if (!strcmp(keyword, "Msg")) { 238296465Sdelphij if (Msg) 239296465Sdelphij goto parse_error; 240296465Sdelphij Msg = hex2bin_m(value, &Msglen); 241296465Sdelphij if (!Msg) 242296465Sdelphij goto parse_error; 243296465Sdelphij } else if (!strcmp(keyword, "Key")) { 244296465Sdelphij if (Key) 245296465Sdelphij goto parse_error; 246296465Sdelphij Key = hex2bin_m(value, &Keylen); 247296465Sdelphij if (!Key) 248296465Sdelphij goto parse_error; 249296465Sdelphij } else if (!strcmp(keyword, "Mac")) 250296465Sdelphij continue; 251296465Sdelphij else 252296465Sdelphij goto parse_error; 253193645Ssimon 254296465Sdelphij fputs(olinebuf, out); 255193645Ssimon 256296465Sdelphij if (Key && Msg && (Tlen > 0) && (Klen > 0)) { 257296465Sdelphij if (!print_hmac(md, out, Key, Klen, Msg, Msglen, Tlen)) 258296465Sdelphij goto error; 259296465Sdelphij OPENSSL_free(Key); 260296465Sdelphij Key = NULL; 261296465Sdelphij OPENSSL_free(Msg); 262296465Sdelphij Msg = NULL; 263296465Sdelphij Klen = -1; 264296465Sdelphij Tlen = -1; 265296465Sdelphij Count = -1; 266296465Sdelphij } 267193645Ssimon 268296465Sdelphij } 269193645Ssimon 270296465Sdelphij ret = 1; 271193645Ssimon 272296465Sdelphij error: 273193645Ssimon 274296465Sdelphij if (olinebuf) 275296465Sdelphij OPENSSL_free(olinebuf); 276296465Sdelphij if (linebuf) 277296465Sdelphij OPENSSL_free(linebuf); 278296465Sdelphij if (Key) 279296465Sdelphij OPENSSL_free(Key); 280296465Sdelphij if (Msg) 281296465Sdelphij OPENSSL_free(Msg); 282193645Ssimon 283296465Sdelphij return ret; 284193645Ssimon 285296465Sdelphij parse_error: 286193645Ssimon 287296465Sdelphij fprintf(stderr, "FATAL parse error processing line %d\n", lnum); 288193645Ssimon 289296465Sdelphij goto error; 290193645Ssimon 291296465Sdelphij} 292193645Ssimon 293193645Ssimonstatic int print_hmac(const EVP_MD *emd, FILE *out, 294296465Sdelphij unsigned char *Key, int Klen, 295296465Sdelphij unsigned char *Msg, int Msglen, int Tlen) 296296465Sdelphij{ 297296465Sdelphij int i, mdlen; 298296465Sdelphij unsigned char md[EVP_MAX_MD_SIZE]; 299296465Sdelphij if (!HMAC(emd, Key, Klen, Msg, Msglen, md, (unsigned int *)&mdlen)) { 300296465Sdelphij fputs("Error calculating HMAC\n", stderr); 301296465Sdelphij return 0; 302296465Sdelphij } 303296465Sdelphij if (Tlen > mdlen) { 304296465Sdelphij fputs("Parameter error, Tlen > HMAC length\n", stderr); 305296465Sdelphij return 0; 306296465Sdelphij } 307296465Sdelphij fputs("Mac = ", out); 308296465Sdelphij for (i = 0; i < Tlen; i++) 309296465Sdelphij fprintf(out, "%02x", md[i]); 310296465Sdelphij fputs("\n", out); 311296465Sdelphij return 1; 312296465Sdelphij} 313193645Ssimon 314193645Ssimon#endif 315