1 /* $OpenBSD: hash.c,v 1.25 2024/11/21 10:07:30 yasuoka 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, MD5_BLOCK_LENGTH, (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, SHA1_BLOCK_LENGTH, (void *)&Ctx.sha1ctx,
68 digest, 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, SHA256_BLOCK_LENGTH,
76 (void *)&Ctx.sha2ctx, digest, 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, SHA384_BLOCK_LENGTH,
84 (void *)&Ctx.sha2ctx, digest, 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, SHA512_BLOCK_LENGTH,
92 (void *)&Ctx.sha2ctx, digest, 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;
126 unsigned char key[128];
127
128 bzero(key, sizeof(key));
129 if (len > hash->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 < hash->blocklen; i++)
140 key[i] ^= HMAC_IPAD_VAL;
141
142 hash->Init(hash->ctx);
143 hash->Update(hash->ctx, key, hash->blocklen);
144
145 for (i = 0; i < hash->blocklen; i++)
146 key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
147
148 hash->Init(hash->ctx2);
149 hash->Update(hash->ctx2, key, hash->blocklen);
150
151 explicit_bzero(key, sizeof(key));
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