1 /* $OpenBSD: hash.c,v 1.21 2006/06/10 20:10:02 hshoexer 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/param.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 SHA256_CTX sha256ctx; 50 SHA384_CTX sha384ctx; 51 SHA512_CTX sha512ctx; 52 } Ctx, Ctx2; 53 54 /* Temporary hash digest. */ 55 static unsigned char digest[HASH_MAX]; 56 57 /* Encapsulation of hash functions. */ 58 59 static struct hash hashes[] = { 60 { 61 HASH_MD5, 5, MD5_SIZE, (void *)&Ctx.md5ctx, digest, 62 sizeof(MD5_CTX), (void *)&Ctx2.md5ctx, 63 (void (*)(void *))MD5Init, 64 (void (*)(void *, unsigned char *, unsigned int))MD5Update, 65 (void (*)(unsigned char *, void *))MD5Final, 66 hmac_init, 67 hmac_final 68 }, { 69 HASH_SHA1, 6, SHA1_SIZE, (void *)&Ctx.sha1ctx, digest, 70 sizeof(SHA1_CTX), (void *)&Ctx2.sha1ctx, 71 (void (*)(void *))SHA1Init, 72 (void (*)(void *, unsigned char *, unsigned int))SHA1Update, 73 (void (*)(unsigned char *, void *))SHA1Final, 74 hmac_init, 75 hmac_final 76 }, { 77 HASH_SHA2_256, 7, SHA2_256_SIZE, (void *)&Ctx.sha256ctx, digest, 78 sizeof(SHA256_CTX), (void *)&Ctx2.sha256ctx, 79 (void (*)(void *))SHA256_Init, 80 (void (*)(void *, unsigned char *, unsigned int))SHA256_Update, 81 (void (*)(u_int8_t *, void *))SHA256_Final, 82 hmac_init, 83 hmac_final 84 }, { 85 HASH_SHA2_384, 8, SHA2_384_SIZE, (void *)&Ctx.sha384ctx, digest, 86 sizeof(SHA384_CTX), (void *)&Ctx2.sha384ctx, 87 (void (*)(void *))SHA384_Init, 88 (void (*)(void *, unsigned char *, unsigned int))SHA384_Update, 89 (void (*)(u_int8_t *, void *))SHA384_Final, 90 hmac_init, 91 hmac_final 92 }, { 93 HASH_SHA2_512, 9, SHA2_512_SIZE, (void *)&Ctx.sha512ctx, digest, 94 sizeof(SHA512_CTX), (void *)&Ctx2.sha512ctx, 95 (void (*)(void *))SHA512_Init, 96 (void (*)(void *, unsigned char *, unsigned int))SHA512_Update, 97 (void (*)(u_int8_t *, void *))SHA512_Final, 98 hmac_init, 99 hmac_final 100 } 101 }; 102 103 struct hash * 104 hash_get(enum hashes hashtype) 105 { 106 size_t i; 107 108 LOG_DBG((LOG_CRYPTO, 60, "hash_get: requested algorithm %d", 109 hashtype)); 110 111 for (i = 0; i < sizeof hashes / sizeof hashes[0]; i++) 112 if (hashtype == hashes[i].type) 113 return &hashes[i]; 114 115 return 0; 116 } 117 118 /* 119 * Initial a hash for HMAC usage this requires a special init function. 120 * ctx, ctx2 hold the contexts, if you want to use the hash object for 121 * something else in the meantime, be sure to store the contexts somewhere. 122 */ 123 124 void 125 hmac_init(struct hash *hash, unsigned char *okey, unsigned int len) 126 { 127 unsigned int i, blocklen = HMAC_BLOCKLEN; 128 unsigned char key[HMAC_BLOCKLEN]; 129 130 bzero(key, blocklen); 131 if (len > blocklen) { 132 /* Truncate key down to blocklen */ 133 hash->Init(hash->ctx); 134 hash->Update(hash->ctx, okey, len); 135 hash->Final(key, hash->ctx); 136 } else { 137 memcpy(key, okey, len); 138 } 139 140 /* HMAC I and O pad computation */ 141 for (i = 0; i < blocklen; i++) 142 key[i] ^= HMAC_IPAD_VAL; 143 144 hash->Init(hash->ctx); 145 hash->Update(hash->ctx, key, blocklen); 146 147 for (i = 0; i < blocklen; i++) 148 key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 149 150 hash->Init(hash->ctx2); 151 hash->Update(hash->ctx2, key, blocklen); 152 153 bzero(key, blocklen); 154 } 155 156 /* 157 * HMAC Final function 158 */ 159 160 void 161 hmac_final(unsigned char *dgst, struct hash *hash) 162 { 163 hash->Final(dgst, hash->ctx); 164 hash->Update(hash->ctx2, dgst, hash->hashsize); 165 hash->Final(dgst, hash->ctx2); 166 } 167