1 /* $OpenBSD: hash.c,v 1.7 2001/06/29 20:38:15 angelos 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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Ericsson Radio Systems. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * This code was written under funding by Ericsson Radio Systems. 36 */ 37 38 #include <sys/param.h> 39 #include <string.h> 40 #include <md5.h> 41 #include <sha1.h> 42 43 #include "sysdep.h" 44 45 #include "hash.h" 46 #include "log.h" 47 48 void hmac_init (struct hash *, unsigned char *, int); 49 void hmac_final (unsigned char *, struct hash *); 50 51 /* Temporary hash contexts. */ 52 static union { 53 MD5_CTX md5ctx; 54 SHA1_CTX sha1ctx; 55 } Ctx, Ctx2; 56 57 /* Temporary hash digest. */ 58 static unsigned char digest[HASH_MAX]; 59 60 /* Encapsulation of hash functions. */ 61 62 static struct hash hashes[] = { 63 { HASH_MD5, 5, MD5_SIZE, (void *)&Ctx.md5ctx, digest, 64 sizeof (MD5_CTX), (void *)&Ctx2.md5ctx, 65 (void (*) (void *))MD5Init, 66 (void (*) (void *, unsigned char *, unsigned int))MD5Update, 67 (void (*) (unsigned char *, void *))MD5Final, 68 hmac_init, hmac_final }, 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, hmac_final }, 75 }; 76 77 struct hash * 78 hash_get (enum hashes hashtype) 79 { 80 int i; 81 82 LOG_DBG ((LOG_CRYPTO, 60, "hash_get: requested algorithm %d", hashtype)); 83 84 for (i = 0; i < sizeof hashes / sizeof hashes[0]; i++) 85 if (hashtype == hashes[i].type) 86 return &hashes[i]; 87 88 return 0; 89 } 90 91 /* 92 * Initial a hash for HMAC usage this requires a special init function. 93 * ctx, ctx2 hold the contexts, if you want to use the hash object for 94 * something else in the meantime, be sure to store the contexts somewhere. 95 */ 96 97 void 98 hmac_init (struct hash *hash, unsigned char *okey, int len) 99 { 100 int i, blocklen = HMAC_BLOCKLEN; 101 unsigned char key[HMAC_BLOCKLEN]; 102 103 if (len > blocklen) 104 { 105 /* Truncate key down to blocklen */ 106 hash->Init (hash->ctx); 107 hash->Update (hash->ctx, okey, len); 108 hash->Final (key, hash->ctx); 109 } 110 else 111 { 112 memset (key, 0, blocklen); 113 memcpy (key, okey, len); 114 } 115 116 /* HMAC I and O pad computation */ 117 for (i = 0; i < blocklen; i++) 118 key[i] ^= HMAC_IPAD_VAL; 119 120 hash->Init (hash->ctx); 121 hash->Update (hash->ctx, key, blocklen); 122 123 for (i = 0; i < blocklen; i++) 124 key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 125 126 hash->Init (hash->ctx2); 127 hash->Update (hash->ctx2, key, blocklen); 128 129 memset (key, 0, blocklen); 130 } 131 132 /* 133 * HMAC Final function 134 */ 135 136 void 137 hmac_final (unsigned char *digest, struct hash *hash) 138 { 139 hash->Final (digest, hash->ctx); 140 hash->Update (hash->ctx2, digest, hash->hashsize); 141 hash->Final (digest, hash->ctx2); 142 } 143