xref: /openbsd/sbin/isakmpd/hash.c (revision a7bc745a)
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 *
hash_get(enum hashes hashtype)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
hmac_init(struct hash * hash,unsigned char * okey,unsigned int len)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
hmac_final(unsigned char * dgst,struct hash * hash)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