1 /* $OpenBSD: hash.c,v 1.24 2015/10/15 06:35:54 mmcc Exp $ */ 2 /* $EOM: hash.c,v 1.10 1999/04/17 23:20:34 niklas Exp $ */ 3 4 /* 5 * Copyright (c) 1998 Niels Provos. All rights reserved. 6 * Copyright (c) 1999 Niklas Hallqvist. 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 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * This code was written under funding by Ericsson Radio Systems. 31 */ 32 33 #include <sys/types.h> 34 #include <string.h> 35 #include <md5.h> 36 #include <sha1.h> 37 #include <sha2.h> 38 39 #include "hash.h" 40 #include "log.h" 41 42 void hmac_init(struct hash *, unsigned char *, unsigned int); 43 void hmac_final(unsigned char *, struct hash *); 44 45 /* Temporary hash contexts. */ 46 static union { 47 MD5_CTX md5ctx; 48 SHA1_CTX sha1ctx; 49 SHA2_CTX sha2ctx; 50 } Ctx, Ctx2; 51 52 /* Temporary hash digest. */ 53 static unsigned char digest[HASH_MAX]; 54 55 /* Encapsulation of hash functions. */ 56 57 static struct hash hashes[] = { 58 { 59 HASH_MD5, 5, MD5_SIZE, (void *)&Ctx.md5ctx, digest, 60 sizeof(MD5_CTX), (void *)&Ctx2.md5ctx, 61 (void (*)(void *))MD5Init, 62 (void (*)(void *, unsigned char *, unsigned int))MD5Update, 63 (void (*)(unsigned char *, void *))MD5Final, 64 hmac_init, 65 hmac_final 66 }, { 67 HASH_SHA1, 6, SHA1_SIZE, (void *)&Ctx.sha1ctx, digest, 68 sizeof(SHA1_CTX), (void *)&Ctx2.sha1ctx, 69 (void (*)(void *))SHA1Init, 70 (void (*)(void *, unsigned char *, unsigned int))SHA1Update, 71 (void (*)(unsigned char *, void *))SHA1Final, 72 hmac_init, 73 hmac_final 74 }, { 75 HASH_SHA2_256, 7, SHA2_256_SIZE, (void *)&Ctx.sha2ctx, digest, 76 sizeof(SHA2_CTX), (void *)&Ctx2.sha2ctx, 77 (void (*)(void *))SHA256Init, 78 (void (*)(void *, unsigned char *, unsigned int))SHA256Update, 79 (void (*)(u_int8_t *, void *))SHA256Final, 80 hmac_init, 81 hmac_final 82 }, { 83 HASH_SHA2_384, 8, SHA2_384_SIZE, (void *)&Ctx.sha2ctx, digest, 84 sizeof(SHA2_CTX), (void *)&Ctx2.sha2ctx, 85 (void (*)(void *))SHA384Init, 86 (void (*)(void *, unsigned char *, unsigned int))SHA384Update, 87 (void (*)(u_int8_t *, void *))SHA384Final, 88 hmac_init, 89 hmac_final 90 }, { 91 HASH_SHA2_512, 9, SHA2_512_SIZE, (void *)&Ctx.sha2ctx, digest, 92 sizeof(SHA2_CTX), (void *)&Ctx2.sha2ctx, 93 (void (*)(void *))SHA512Init, 94 (void (*)(void *, unsigned char *, unsigned int))SHA512Update, 95 (void (*)(u_int8_t *, void *))SHA512Final, 96 hmac_init, 97 hmac_final 98 } 99 }; 100 101 struct hash * 102 hash_get(enum hashes hashtype) 103 { 104 size_t i; 105 106 LOG_DBG((LOG_CRYPTO, 60, "hash_get: requested algorithm %d", 107 hashtype)); 108 109 for (i = 0; i < sizeof hashes / sizeof hashes[0]; i++) 110 if (hashtype == hashes[i].type) 111 return &hashes[i]; 112 113 return 0; 114 } 115 116 /* 117 * Initial a hash for HMAC usage this requires a special init function. 118 * ctx, ctx2 hold the contexts, if you want to use the hash object for 119 * something else in the meantime, be sure to store the contexts somewhere. 120 */ 121 122 void 123 hmac_init(struct hash *hash, unsigned char *okey, unsigned int len) 124 { 125 unsigned int i, blocklen = HMAC_BLOCKLEN; 126 unsigned char key[HMAC_BLOCKLEN]; 127 128 bzero(key, blocklen); 129 if (len > blocklen) { 130 /* Truncate key down to blocklen */ 131 hash->Init(hash->ctx); 132 hash->Update(hash->ctx, okey, len); 133 hash->Final(key, hash->ctx); 134 } else { 135 memcpy(key, okey, len); 136 } 137 138 /* HMAC I and O pad computation */ 139 for (i = 0; i < blocklen; i++) 140 key[i] ^= HMAC_IPAD_VAL; 141 142 hash->Init(hash->ctx); 143 hash->Update(hash->ctx, key, blocklen); 144 145 for (i = 0; i < blocklen; i++) 146 key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 147 148 hash->Init(hash->ctx2); 149 hash->Update(hash->ctx2, key, blocklen); 150 151 explicit_bzero(key, blocklen); 152 } 153 154 /* 155 * HMAC Final function 156 */ 157 158 void 159 hmac_final(unsigned char *dgst, struct hash *hash) 160 { 161 hash->Final(dgst, hash->ctx); 162 hash->Update(hash->ctx2, dgst, hash->hashsize); 163 hash->Final(dgst, hash->ctx2); 164 } 165