Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/libecc/src/hash/hmac.c
34879 views
1
/*
2
* Copyright (C) 2021 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
7
*
8
* This software is licensed under a dual BSD and GPL v2 license.
9
* See LICENSE file at the root folder of the project.
10
*/
11
#include <libecc/lib_ecc_config.h>
12
#ifdef WITH_HMAC
13
14
#include <libecc/hash/hmac.h>
15
16
int hmac_init(hmac_context *ctx, const u8 *hmackey, u32 hmackey_len,
17
hash_alg_type hash_type)
18
{
19
u8 ipad[MAX_BLOCK_SIZE];
20
u8 opad[MAX_BLOCK_SIZE];
21
u8 local_hmac_key[MAX_BLOCK_SIZE];
22
unsigned int i, local_hmac_key_len;
23
int ret;
24
const hash_mapping *h;
25
26
MUST_HAVE((ctx != NULL) && (hmackey != NULL), ret, err);
27
28
ret = local_memset(local_hmac_key, 0, sizeof(local_hmac_key)); EG(ret, err);
29
/* Set ipad and opad to appropriate values */
30
ret = local_memset(ipad, 0x36, sizeof(ipad)); EG(ret, err);
31
ret = local_memset(opad, 0x5c, sizeof(opad)); EG(ret, err);
32
33
/* Get the hash mapping of the current asked hash function */
34
ret = get_hash_by_type(hash_type, &(ctx->hash)); EG(ret, err);
35
MUST_HAVE((ctx->hash != NULL), ret, err);
36
37
/* Make things more readable */
38
h = ctx->hash;
39
40
if(hmackey_len <= ctx->hash->block_size){
41
/* The key size is less than the hash function block size */
42
ret = local_memcpy(local_hmac_key, hmackey, hmackey_len); EG(ret, err);
43
local_hmac_key_len = hmackey_len;
44
}
45
else{
46
/* The key size is greater than the hash function block size.
47
* We hash it to shorten it.
48
*/
49
hash_context tmp_ctx;
50
/* Check our callback */
51
ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
52
ret = h->hfunc_init(&tmp_ctx); EG(ret, err);
53
ret = h->hfunc_update(&tmp_ctx, hmackey, hmackey_len); EG(ret, err);
54
ret = h->hfunc_finalize(&tmp_ctx, local_hmac_key); EG(ret, err);
55
local_hmac_key_len = h->digest_size;
56
}
57
58
/* Initialize our input and output hash contexts */
59
/* Check our callback */
60
ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
61
ret = h->hfunc_init(&(ctx->in_ctx)); EG(ret, err);
62
/* Check our callback */
63
ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
64
ret = h->hfunc_init(&(ctx->out_ctx)); EG(ret, err);
65
66
/* Update our input context with K^ipad */
67
for(i = 0; i < local_hmac_key_len; i++){
68
ipad[i] ^= local_hmac_key[i];
69
}
70
ret = h->hfunc_update(&(ctx->in_ctx), ipad, h->block_size); EG(ret, err);
71
/* Update our output context with K^opad */
72
for(i = 0; i < local_hmac_key_len; i++){
73
opad[i] ^= local_hmac_key[i];
74
}
75
ret = h->hfunc_update(&(ctx->out_ctx), opad, h->block_size); EG(ret, err);
76
77
/* Initialize our magic */
78
ctx->magic = HMAC_MAGIC;
79
80
err:
81
return ret;
82
}
83
84
int hmac_update(hmac_context *ctx, const u8 *input, u32 ilen)
85
{
86
int ret;
87
const hash_mapping *h;
88
89
HMAC_CHECK_INITIALIZED(ctx, ret, err);
90
MUST_HAVE((input != NULL) || (ilen == 0), ret, err);
91
92
/* Make things more readable */
93
h = ctx->hash;
94
/* Check our callback */
95
ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
96
ret = h->hfunc_update(&(ctx->in_ctx), input, ilen); EG(ret, err);
97
98
err:
99
return ret;
100
}
101
102
int hmac_finalize(hmac_context *ctx, u8 *output, u8 *outlen)
103
{
104
int ret;
105
u8 in_hash[MAX_DIGEST_SIZE];
106
const hash_mapping *h;
107
108
HMAC_CHECK_INITIALIZED(ctx, ret, err);
109
MUST_HAVE((output != NULL) && (outlen != NULL), ret, err);
110
111
/* Make things more readable */
112
h = ctx->hash;
113
114
MUST_HAVE(((*outlen) >= h->digest_size), ret, err);
115
116
/* Check our callback */
117
ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
118
ret = h->hfunc_finalize(&(ctx->in_ctx), in_hash); EG(ret, err);
119
ret = h->hfunc_update(&(ctx->out_ctx), in_hash, h->digest_size); EG(ret, err);
120
ret = h->hfunc_finalize(&(ctx->out_ctx), output); EG(ret, err);
121
(*outlen) = h->digest_size;
122
123
err:
124
if(ctx != NULL){
125
/* Clear the hash contexts that could contain sensitive data */
126
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(hmac_context)));
127
/* Uninitialize the context */
128
ctx->magic = WORD(0);
129
}
130
if(ret && (outlen != NULL)){
131
(*outlen) = 0;
132
}
133
return ret;
134
}
135
136
int hmac(const u8 *hmackey, u32 hmackey_len, hash_alg_type hash_type,
137
const u8 *input, u32 ilen, u8 *output, u8 *outlen)
138
{
139
int ret;
140
hmac_context ctx;
141
142
ret = hmac_init(&ctx, hmackey, hmackey_len, hash_type); EG(ret, err);
143
ret = hmac_update(&ctx, input, ilen); EG(ret, err);
144
ret = hmac_finalize(&ctx, output, outlen);
145
146
err:
147
/* Clean our context as it can contain sensitive data */
148
IGNORE_RET_VAL(local_memset(&ctx, 0, sizeof(hmac_context)));
149
150
return ret;
151
}
152
153
/* Scattered version */
154
int hmac_scattered(const u8 *hmackey, u32 hmackey_len, hash_alg_type hash_type,
155
const u8 **inputs, const u32 *ilens, u8 *output, u8 *outlen)
156
{
157
int ret, pos = 0;
158
hmac_context ctx;
159
160
MUST_HAVE((inputs != NULL) && (ilens != NULL) && (output != NULL), ret, err);
161
162
ret = hmac_init(&ctx, hmackey, hmackey_len, hash_type); EG(ret, err);
163
164
while (inputs[pos] != NULL) {
165
ret = hmac_update(&ctx, inputs[pos], ilens[pos]); EG(ret, err);
166
pos += 1;
167
}
168
169
ret = hmac_finalize(&ctx, output, outlen);
170
171
err:
172
/* Clean our context as it can contain sensitive data */
173
IGNORE_RET_VAL(local_memset(&ctx, 0, sizeof(hmac_context)));
174
175
return ret;
176
}
177
178
179
#else /* WITH_HMAC */
180
181
/*
182
* Dummy definition to avoid the empty translation unit ISO C warning
183
*/
184
typedef int dummy;
185
#endif /* WITH_HMAC */
186
187