]>
Commit | Line | Data |
---|---|---|
d2e9e320 | 1 | /* |
2d28a42f | 2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
58964a49 | 3 | * |
d2e9e320 RS |
4 | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
58964a49 | 8 | */ |
6dff52e8 | 9 | |
58964a49 RE |
10 | #include <stdio.h> |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
b39fc560 | 13 | #include "internal/cryptlib.h" |
25a66ee3 | 14 | #include <openssl/hmac.h> |
98186eb4 | 15 | #include <openssl/opensslconf.h> |
3f43aecc | 16 | #include "hmac_lcl.h" |
58964a49 | 17 | |
6343829a | 18 | int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, |
0f113f3e MC |
19 | const EVP_MD *md, ENGINE *impl) |
20 | { | |
2d28a42f | 21 | int rv = 0; |
0f113f3e | 22 | int i, j, reset = 0; |
e0810e35 | 23 | unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; |
0f113f3e | 24 | |
4b464e7b MC |
25 | /* If we are changing MD then we must have a key */ |
26 | if (md != NULL && md != ctx->md && (key == NULL || len < 0)) | |
27 | return 0; | |
28 | ||
0f113f3e MC |
29 | if (md != NULL) { |
30 | reset = 1; | |
31 | ctx->md = md; | |
61986d32 | 32 | } else if (ctx->md) { |
0f113f3e | 33 | md = ctx->md; |
e2095c65 MC |
34 | } else { |
35 | return 0; | |
36 | } | |
37 | ||
0f113f3e MC |
38 | if (key != NULL) { |
39 | reset = 1; | |
fa0c23de | 40 | j = EVP_MD_block_size(md); |
8f9ee7a3 | 41 | if (!ossl_assert(j <= (int)sizeof(ctx->key))) |
2d28a42f | 42 | return 0; |
0f113f3e | 43 | if (j < len) { |
2d28a42f SL |
44 | if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl) |
45 | || !EVP_DigestUpdate(ctx->md_ctx, key, len) | |
46 | || !EVP_DigestFinal_ex(ctx->md_ctx, ctx->key, | |
47 | &ctx->key_length)) | |
48 | return 0; | |
0f113f3e | 49 | } else { |
61986d32 | 50 | if (len < 0 || len > (int)sizeof(ctx->key)) |
c62e94d8 | 51 | return 0; |
0f113f3e MC |
52 | memcpy(ctx->key, key, len); |
53 | ctx->key_length = len; | |
54 | } | |
e0810e35 | 55 | if (ctx->key_length != HMAC_MAX_MD_CBLOCK_SIZE) |
0f113f3e | 56 | memset(&ctx->key[ctx->key_length], 0, |
e0810e35 | 57 | HMAC_MAX_MD_CBLOCK_SIZE - ctx->key_length); |
0f113f3e MC |
58 | } |
59 | ||
60 | if (reset) { | |
e0810e35 | 61 | for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) |
0f113f3e | 62 | pad[i] = 0x36 ^ ctx->key[i]; |
2d28a42f SL |
63 | if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl) |
64 | || !EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md))) | |
0f113f3e MC |
65 | goto err; |
66 | ||
e0810e35 | 67 | for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) |
0f113f3e | 68 | pad[i] = 0x5c ^ ctx->key[i]; |
2d28a42f SL |
69 | if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl) |
70 | || !EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md))) | |
0f113f3e MC |
71 | goto err; |
72 | } | |
fa0c23de | 73 | if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx)) |
0f113f3e | 74 | goto err; |
2d28a42f | 75 | rv = 1; |
0f113f3e | 76 | err: |
2d28a42f SL |
77 | if (reset) |
78 | OPENSSL_cleanse(pad, sizeof(pad)); | |
79 | return rv; | |
0f113f3e | 80 | } |
58964a49 | 81 | |
98186eb4 | 82 | #if OPENSSL_API_COMPAT < 0x10100000L |
6343829a | 83 | int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) |
0f113f3e MC |
84 | { |
85 | if (key && md) | |
a87a0a6e | 86 | HMAC_CTX_reset(ctx); |
0f113f3e MC |
87 | return HMAC_Init_ex(ctx, key, len, md, NULL); |
88 | } | |
00a5a74b | 89 | #endif |
ff3fa48f | 90 | |
87d52468 | 91 | int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) |
0f113f3e | 92 | { |
4b464e7b | 93 | if (!ctx->md) |
e2095c65 | 94 | return 0; |
fa0c23de | 95 | return EVP_DigestUpdate(ctx->md_ctx, data, len); |
0f113f3e | 96 | } |
58964a49 | 97 | |
87d52468 | 98 | int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) |
0f113f3e MC |
99 | { |
100 | unsigned int i; | |
101 | unsigned char buf[EVP_MAX_MD_SIZE]; | |
102 | ||
4b464e7b | 103 | if (!ctx->md) |
e2095c65 MC |
104 | goto err; |
105 | ||
fa0c23de | 106 | if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i)) |
0f113f3e | 107 | goto err; |
fa0c23de | 108 | if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx)) |
0f113f3e | 109 | goto err; |
fa0c23de | 110 | if (!EVP_DigestUpdate(ctx->md_ctx, buf, i)) |
0f113f3e | 111 | goto err; |
fa0c23de | 112 | if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len)) |
0f113f3e MC |
113 | goto err; |
114 | return 1; | |
115 | err: | |
116 | return 0; | |
117 | } | |
dbad1690 | 118 | |
2194351f | 119 | size_t HMAC_size(const HMAC_CTX *ctx) |
3f43aecc | 120 | { |
708e06c5 | 121 | int size = EVP_MD_size((ctx)->md); |
d0ee717c MC |
122 | |
123 | return (size < 0) ? 0 : size; | |
3f43aecc RL |
124 | } |
125 | ||
126 | HMAC_CTX *HMAC_CTX_new(void) | |
127 | { | |
43ecb9c3 RS |
128 | HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); |
129 | ||
130 | if (ctx != NULL) { | |
dc0099e1 | 131 | if (!HMAC_CTX_reset(ctx)) { |
3f43aecc | 132 | HMAC_CTX_free(ctx); |
43ecb9c3 | 133 | return NULL; |
3f43aecc | 134 | } |
43ecb9c3 | 135 | } |
3f43aecc RL |
136 | return ctx; |
137 | } | |
138 | ||
32fd54a9 RL |
139 | static void hmac_ctx_cleanup(HMAC_CTX *ctx) |
140 | { | |
bfb0641f RL |
141 | EVP_MD_CTX_reset(ctx->i_ctx); |
142 | EVP_MD_CTX_reset(ctx->o_ctx); | |
143 | EVP_MD_CTX_reset(ctx->md_ctx); | |
32fd54a9 RL |
144 | ctx->md = NULL; |
145 | ctx->key_length = 0; | |
85cbc182 | 146 | OPENSSL_cleanse(ctx->key, sizeof(ctx->key)); |
32fd54a9 RL |
147 | } |
148 | ||
3f43aecc RL |
149 | void HMAC_CTX_free(HMAC_CTX *ctx) |
150 | { | |
151 | if (ctx != NULL) { | |
32fd54a9 | 152 | hmac_ctx_cleanup(ctx); |
bfb0641f RL |
153 | EVP_MD_CTX_free(ctx->i_ctx); |
154 | EVP_MD_CTX_free(ctx->o_ctx); | |
155 | EVP_MD_CTX_free(ctx->md_ctx); | |
3f43aecc RL |
156 | OPENSSL_free(ctx); |
157 | } | |
158 | } | |
159 | ||
b98530d6 | 160 | static int hmac_ctx_alloc_mds(HMAC_CTX *ctx) |
0f113f3e | 161 | { |
fa0c23de | 162 | if (ctx->i_ctx == NULL) |
bfb0641f | 163 | ctx->i_ctx = EVP_MD_CTX_new(); |
fa0c23de | 164 | if (ctx->i_ctx == NULL) |
b98530d6 | 165 | return 0; |
fa0c23de | 166 | if (ctx->o_ctx == NULL) |
bfb0641f | 167 | ctx->o_ctx = EVP_MD_CTX_new(); |
fa0c23de | 168 | if (ctx->o_ctx == NULL) |
b98530d6 | 169 | return 0; |
fa0c23de | 170 | if (ctx->md_ctx == NULL) |
bfb0641f | 171 | ctx->md_ctx = EVP_MD_CTX_new(); |
fa0c23de | 172 | if (ctx->md_ctx == NULL) |
b98530d6 | 173 | return 0; |
fa0c23de | 174 | return 1; |
b98530d6 GN |
175 | } |
176 | ||
177 | int HMAC_CTX_reset(HMAC_CTX *ctx) | |
178 | { | |
32fd54a9 | 179 | hmac_ctx_cleanup(ctx); |
b98530d6 GN |
180 | if (!hmac_ctx_alloc_mds(ctx)) { |
181 | hmac_ctx_cleanup(ctx); | |
182 | return 0; | |
183 | } | |
184 | return 1; | |
0f113f3e | 185 | } |
58964a49 | 186 | |
87d52468 | 187 | int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) |
0f113f3e | 188 | { |
b98530d6 | 189 | if (!hmac_ctx_alloc_mds(dctx)) |
fa0c23de RL |
190 | goto err; |
191 | if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx)) | |
0f113f3e | 192 | goto err; |
fa0c23de | 193 | if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx)) |
0f113f3e | 194 | goto err; |
fa0c23de | 195 | if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx)) |
0f113f3e | 196 | goto err; |
e0810e35 | 197 | memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK_SIZE); |
4b464e7b | 198 | dctx->key_length = sctx->key_length; |
0f113f3e MC |
199 | dctx->md = sctx->md; |
200 | return 1; | |
201 | err: | |
32fd54a9 | 202 | hmac_ctx_cleanup(dctx); |
0f113f3e MC |
203 | return 0; |
204 | } | |
74633553 | 205 | |
6343829a | 206 | unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, |
0f113f3e MC |
207 | const unsigned char *d, size_t n, unsigned char *md, |
208 | unsigned int *md_len) | |
209 | { | |
3f43aecc | 210 | HMAC_CTX *c = NULL; |
0f113f3e | 211 | static unsigned char m[EVP_MAX_MD_SIZE]; |
b1413d9b | 212 | static const unsigned char dummy_key[1] = {'\0'}; |
0f113f3e MC |
213 | |
214 | if (md == NULL) | |
215 | md = m; | |
3f43aecc RL |
216 | if ((c = HMAC_CTX_new()) == NULL) |
217 | goto err; | |
b1413d9b EK |
218 | |
219 | /* For HMAC_Init_ex, NULL key signals reuse. */ | |
220 | if (key == NULL && key_len == 0) { | |
221 | key = dummy_key; | |
222 | } | |
223 | ||
3f43aecc | 224 | if (!HMAC_Init_ex(c, key, key_len, evp_md, NULL)) |
0f113f3e | 225 | goto err; |
3f43aecc | 226 | if (!HMAC_Update(c, d, n)) |
0f113f3e | 227 | goto err; |
3f43aecc | 228 | if (!HMAC_Final(c, md, md_len)) |
0f113f3e | 229 | goto err; |
3f43aecc | 230 | HMAC_CTX_free(c); |
0f113f3e MC |
231 | return md; |
232 | err: | |
3f43aecc | 233 | HMAC_CTX_free(c); |
0f113f3e MC |
234 | return NULL; |
235 | } | |
58964a49 | 236 | |
e92f9f45 | 237 | void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) |
0f113f3e | 238 | { |
fa0c23de RL |
239 | EVP_MD_CTX_set_flags(ctx->i_ctx, flags); |
240 | EVP_MD_CTX_set_flags(ctx->o_ctx, flags); | |
241 | EVP_MD_CTX_set_flags(ctx->md_ctx, flags); | |
0f113f3e | 242 | } |
a6211814 MC |
243 | |
244 | const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) | |
245 | { | |
246 | return ctx->md; | |
247 | } |