diff options
author | inoguchi <> | 2017-03-03 10:39:07 +0000 |
---|---|---|
committer | inoguchi <> | 2017-03-03 10:39:07 +0000 |
commit | 97d56837a149cc0208c55b487d71956d327193fd (patch) | |
tree | f55b9886b7ecc1012718eec4a621d7ac8d098382 | |
parent | 71095999206308b62fa7ab18602ceb3fa91f6a9c (diff) | |
download | openbsd-97d56837a149cc0208c55b487d71956d327193fd.tar.gz openbsd-97d56837a149cc0208c55b487d71956d327193fd.tar.bz2 openbsd-97d56837a149cc0208c55b487d71956d327193fd.zip |
Ensure MD and key initialized before processing HMAC
Ensure both MD and key have been initialized before processing HMAC.
Releasing HMAC_CTX in error path of HMAC().
In regress test, added test 4,5,6 and cleaned up the code.
ok jsing@
-rw-r--r-- | src/lib/libcrypto/hmac/hmac.c | 22 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/hmac/hmactest.c | 237 |
2 files changed, 224 insertions, 35 deletions
diff --git a/src/lib/libcrypto/hmac/hmac.c b/src/lib/libcrypto/hmac/hmac.c index 8fd980b052..84917662ca 100644 --- a/src/lib/libcrypto/hmac/hmac.c +++ b/src/lib/libcrypto/hmac/hmac.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hmac.c,v 1.23 2017/01/29 17:49:23 beck Exp $ */ | 1 | /* $OpenBSD: hmac.c,v 1.24 2017/03/03 10:39:07 inoguchi Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -70,11 +70,17 @@ HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, | |||
70 | int i, j, reset = 0; | 70 | int i, j, reset = 0; |
71 | unsigned char pad[HMAC_MAX_MD_CBLOCK]; | 71 | unsigned char pad[HMAC_MAX_MD_CBLOCK]; |
72 | 72 | ||
73 | /* If we are changing MD then we must have a key */ | ||
74 | if (md != NULL && md != ctx->md && (key == NULL || len < 0)) | ||
75 | return 0; | ||
76 | |||
73 | if (md != NULL) { | 77 | if (md != NULL) { |
74 | reset = 1; | 78 | reset = 1; |
75 | ctx->md = md; | 79 | ctx->md = md; |
76 | } else | 80 | } else if (ctx->md != NULL) |
77 | md = ctx->md; | 81 | md = ctx->md; |
82 | else | ||
83 | return 0; | ||
78 | 84 | ||
79 | if (key != NULL) { | 85 | if (key != NULL) { |
80 | reset = 1; | 86 | reset = 1; |
@@ -92,7 +98,7 @@ HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, | |||
92 | &ctx->key_length)) | 98 | &ctx->key_length)) |
93 | goto err; | 99 | goto err; |
94 | } else { | 100 | } else { |
95 | if ((size_t)len > sizeof(ctx->key)) { | 101 | if (len < 0 || (size_t)len > sizeof(ctx->key)) { |
96 | EVPerror(EVP_R_BAD_KEY_LENGTH); | 102 | EVPerror(EVP_R_BAD_KEY_LENGTH); |
97 | goto err; | 103 | goto err; |
98 | } | 104 | } |
@@ -137,6 +143,9 @@ HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) | |||
137 | int | 143 | int |
138 | HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) | 144 | HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) |
139 | { | 145 | { |
146 | if (ctx->md == NULL) | ||
147 | return 0; | ||
148 | |||
140 | return EVP_DigestUpdate(&ctx->md_ctx, data, len); | 149 | return EVP_DigestUpdate(&ctx->md_ctx, data, len); |
141 | } | 150 | } |
142 | 151 | ||
@@ -146,6 +155,9 @@ HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) | |||
146 | unsigned int i; | 155 | unsigned int i; |
147 | unsigned char buf[EVP_MAX_MD_SIZE]; | 156 | unsigned char buf[EVP_MAX_MD_SIZE]; |
148 | 157 | ||
158 | if (ctx->md == NULL) | ||
159 | goto err; | ||
160 | |||
149 | if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i)) | 161 | if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i)) |
150 | goto err; | 162 | goto err; |
151 | if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx)) | 163 | if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx)) |
@@ -165,6 +177,7 @@ HMAC_CTX_init(HMAC_CTX *ctx) | |||
165 | EVP_MD_CTX_init(&ctx->i_ctx); | 177 | EVP_MD_CTX_init(&ctx->i_ctx); |
166 | EVP_MD_CTX_init(&ctx->o_ctx); | 178 | EVP_MD_CTX_init(&ctx->o_ctx); |
167 | EVP_MD_CTX_init(&ctx->md_ctx); | 179 | EVP_MD_CTX_init(&ctx->md_ctx); |
180 | ctx->md = NULL; | ||
168 | } | 181 | } |
169 | 182 | ||
170 | int | 183 | int |
@@ -190,7 +203,7 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx) | |||
190 | EVP_MD_CTX_cleanup(&ctx->i_ctx); | 203 | EVP_MD_CTX_cleanup(&ctx->i_ctx); |
191 | EVP_MD_CTX_cleanup(&ctx->o_ctx); | 204 | EVP_MD_CTX_cleanup(&ctx->o_ctx); |
192 | EVP_MD_CTX_cleanup(&ctx->md_ctx); | 205 | EVP_MD_CTX_cleanup(&ctx->md_ctx); |
193 | memset(ctx, 0, sizeof *ctx); | 206 | explicit_bzero(ctx, sizeof(*ctx)); |
194 | } | 207 | } |
195 | 208 | ||
196 | unsigned char * | 209 | unsigned char * |
@@ -212,6 +225,7 @@ HMAC(const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, | |||
212 | HMAC_CTX_cleanup(&c); | 225 | HMAC_CTX_cleanup(&c); |
213 | return md; | 226 | return md; |
214 | err: | 227 | err: |
228 | HMAC_CTX_cleanup(&c); | ||
215 | return NULL; | 229 | return NULL; |
216 | } | 230 | } |
217 | 231 | ||
diff --git a/src/regress/lib/libcrypto/hmac/hmactest.c b/src/regress/lib/libcrypto/hmac/hmactest.c index 7daaacd34f..d5a00c8aac 100644 --- a/src/regress/lib/libcrypto/hmac/hmactest.c +++ b/src/regress/lib/libcrypto/hmac/hmactest.c | |||
@@ -66,32 +66,33 @@ | |||
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | #ifndef OPENSSL_NO_MD5 | 68 | #ifndef OPENSSL_NO_MD5 |
69 | static struct test_st | 69 | static struct test_st { |
70 | { | ||
71 | unsigned char key[16]; | 70 | unsigned char key[16]; |
72 | int key_len; | 71 | int key_len; |
73 | unsigned char data[64]; | 72 | unsigned char data[64]; |
74 | int data_len; | 73 | int data_len; |
75 | unsigned char *digest; | 74 | unsigned char *digest; |
76 | } test[4]={ | 75 | } test[8] = { |
77 | { "", | 76 | { "", |
78 | 0, | 77 | 0, |
79 | "More text test vectors to stuff up EBCDIC machines :-)", | 78 | "More text test vectors to stuff up EBCDIC machines :-)", |
80 | 54, | 79 | 54, |
81 | (unsigned char *)"e9139d1e6ee064ef8cf514fc7dc83e86", | 80 | (unsigned char *)"e9139d1e6ee064ef8cf514fc7dc83e86", |
82 | },{ {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, | 81 | }, |
82 | { {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, | ||
83 | 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,}, | 83 | 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,}, |
84 | 16, | 84 | 16, |
85 | "Hi There", | 85 | "Hi There", |
86 | 8, | 86 | 8, |
87 | (unsigned char *)"9294727a3638bb1c13f48ef8158bfc9d", | 87 | (unsigned char *)"9294727a3638bb1c13f48ef8158bfc9d", |
88 | },{ "Jefe", | 88 | }, |
89 | { "Jefe", | ||
89 | 4, | 90 | 4, |
90 | "what do ya want for nothing?", | 91 | "what do ya want for nothing?", |
91 | 28, | 92 | 28, |
92 | (unsigned char *)"750c783e6ab0b503eaa86e310a5db738", | 93 | (unsigned char *)"750c783e6ab0b503eaa86e310a5db738", |
93 | },{ | 94 | }, |
94 | {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, | 95 | { {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, |
95 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,}, | 96 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,}, |
96 | 16, | 97 | 16, |
97 | {0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, | 98 | {0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, |
@@ -104,51 +105,225 @@ static struct test_st | |||
104 | 50, | 105 | 50, |
105 | (unsigned char *)"56be34521d144c88dbb8c733f0e8b3f6", | 106 | (unsigned char *)"56be34521d144c88dbb8c733f0e8b3f6", |
106 | }, | 107 | }, |
107 | }; | 108 | { "", |
109 | 0, | ||
110 | "My test data", | ||
111 | 12, | ||
112 | (unsigned char *)"61afdecb95429ef494d61fdee15990cabf0826fc" | ||
113 | }, | ||
114 | { "", | ||
115 | 0, | ||
116 | "My test data", | ||
117 | 12, | ||
118 | (unsigned char *)"2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776" | ||
119 | }, | ||
120 | { "123456", | ||
121 | 6, | ||
122 | "My test data", | ||
123 | 12, | ||
124 | (unsigned char *)"bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd" | ||
125 | }, | ||
126 | { "12345", | ||
127 | 5, | ||
128 | "My test data again", | ||
129 | 12, | ||
130 | (unsigned char *)"7dbe8c764c068e3bcd6e6b0fbcd5e6fc197b15bb" | ||
131 | } | ||
132 | }; | ||
108 | #endif | 133 | #endif |
109 | 134 | ||
110 | static char *pt(unsigned char *md); | 135 | static char *pt(unsigned char *md, unsigned int len); |
111 | int main(int argc, char *argv[]) | 136 | |
112 | { | 137 | int |
138 | main(int argc, char *argv[]) | ||
139 | { | ||
113 | #ifndef OPENSSL_NO_MD5 | 140 | #ifndef OPENSSL_NO_MD5 |
114 | int i; | 141 | int i; |
115 | char *p; | 142 | char *p; |
116 | #endif | 143 | #endif |
117 | int err=0; | 144 | int err = 0; |
145 | HMAC_CTX ctx, ctx2; | ||
146 | unsigned char buf[EVP_MAX_MD_SIZE]; | ||
147 | unsigned int len; | ||
118 | 148 | ||
119 | #ifdef OPENSSL_NO_MD5 | 149 | #ifdef OPENSSL_NO_MD5 |
120 | printf("test skipped: MD5 disabled\n"); | 150 | printf("test skipped: MD5 disabled\n"); |
121 | #else | 151 | #else |
122 | 152 | ||
123 | for (i=0; i<4; i++) | 153 | for (i = 0; i < 4; i++) { |
124 | { | 154 | p = pt(HMAC(EVP_md5(), |
125 | p=pt(HMAC(EVP_md5(), | ||
126 | test[i].key, test[i].key_len, | 155 | test[i].key, test[i].key_len, |
127 | test[i].data, test[i].data_len, | 156 | test[i].data, test[i].data_len, NULL, NULL), |
128 | NULL,NULL)); | 157 | MD5_DIGEST_LENGTH); |
129 | 158 | ||
130 | if (strcmp(p,(char *)test[i].digest) != 0) | 159 | if (strcmp(p, (char *)test[i].digest) != 0) { |
131 | { | 160 | printf("error calculating HMAC on %d entry'\n", i); |
132 | printf("error calculating HMAC on %d entry'\n",i); | 161 | printf("got %s instead of %s\n", p, test[i].digest); |
133 | printf("got %s instead of %s\n",p,test[i].digest); | ||
134 | err++; | 162 | err++; |
135 | } | 163 | } else |
136 | else | 164 | printf("test %d ok\n", i); |
137 | printf("test %d ok\n",i); | 165 | } |
138 | } | ||
139 | #endif /* OPENSSL_NO_MD5 */ | 166 | #endif /* OPENSSL_NO_MD5 */ |
167 | |||
168 | /* test4 */ | ||
169 | HMAC_CTX_init(&ctx); | ||
170 | if (HMAC_Init_ex(&ctx, NULL, 0, NULL, NULL)) { | ||
171 | printf("Should fail to initialise HMAC with empty MD and key (test 4)\n"); | ||
172 | err++; | ||
173 | goto test5; | ||
174 | } | ||
175 | if (HMAC_Update(&ctx, test[4].data, test[4].data_len)) { | ||
176 | printf("Should fail HMAC_Update with ctx not set up (test 4)\n"); | ||
177 | err++; | ||
178 | goto test5; | ||
179 | } | ||
180 | if (HMAC_Init_ex(&ctx, NULL, 0, EVP_sha1(), NULL)) { | ||
181 | printf("Should fail to initialise HMAC with empty key (test 4)\n"); | ||
182 | err++; | ||
183 | goto test5; | ||
184 | } | ||
185 | if (HMAC_Update(&ctx, test[4].data, test[4].data_len)) { | ||
186 | printf("Should fail HMAC_Update with ctx not set up (test 4)\n"); | ||
187 | err++; | ||
188 | goto test5; | ||
189 | } | ||
190 | printf("test 4 ok\n"); | ||
191 | test5: | ||
192 | HMAC_CTX_cleanup(&ctx); | ||
193 | HMAC_CTX_init(&ctx); | ||
194 | if (HMAC_Init_ex(&ctx, test[4].key, test[4].key_len, NULL, NULL)) { | ||
195 | printf("Should fail to initialise HMAC with empty MD (test 5)\n"); | ||
196 | err++; | ||
197 | goto test6; | ||
198 | } | ||
199 | if (HMAC_Update(&ctx, test[4].data, test[4].data_len)) { | ||
200 | printf("Should fail HMAC_Update with ctx not set up (test 5)\n"); | ||
201 | err++; | ||
202 | goto test6; | ||
203 | } | ||
204 | if (HMAC_Init_ex(&ctx, test[4].key, -1, EVP_sha1(), NULL)) { | ||
205 | printf("Should fail to initialise HMAC with invalid key len(test 5)\n"); | ||
206 | err++; | ||
207 | goto test6; | ||
208 | } | ||
209 | if (!HMAC_Init_ex(&ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL)) { | ||
210 | printf("Failed to initialise HMAC (test 5)\n"); | ||
211 | err++; | ||
212 | goto test6; | ||
213 | } | ||
214 | if (!HMAC_Update(&ctx, test[4].data, test[4].data_len)) { | ||
215 | printf("Error updating HMAC with data (test 5)\n"); | ||
216 | err++; | ||
217 | goto test6; | ||
218 | } | ||
219 | if (!HMAC_Final(&ctx, buf, &len)) { | ||
220 | printf("Error finalising data (test 5)\n"); | ||
221 | err++; | ||
222 | goto test6; | ||
223 | } | ||
224 | p = pt(buf, len); | ||
225 | if (strcmp(p, (char *)test[4].digest) != 0) { | ||
226 | printf("Error calculating interim HMAC on test 5\n"); | ||
227 | printf("got %s instead of %s\n", p, test[4].digest); | ||
228 | err++; | ||
229 | goto test6; | ||
230 | } | ||
231 | if (HMAC_Init_ex(&ctx, NULL, 0, EVP_sha256(), NULL)) { | ||
232 | printf("Should disallow changing MD without a new key (test 5)\n"); | ||
233 | err++; | ||
234 | goto test6; | ||
235 | } | ||
236 | if (!HMAC_Init_ex(&ctx, test[4].key, test[4].key_len, EVP_sha256(), NULL)) { | ||
237 | printf("Failed to reinitialise HMAC (test 5)\n"); | ||
238 | err++; | ||
239 | goto test6; | ||
240 | } | ||
241 | if (!HMAC_Update(&ctx, test[5].data, test[5].data_len)) { | ||
242 | printf("Error updating HMAC with data (sha256) (test 5)\n"); | ||
243 | err++; | ||
244 | goto test6; | ||
245 | } | ||
246 | if (!HMAC_Final(&ctx, buf, &len)) { | ||
247 | printf("Error finalising data (sha256) (test 5)\n"); | ||
248 | err++; | ||
249 | goto test6; | ||
250 | } | ||
251 | p = pt(buf, len); | ||
252 | if (strcmp(p, (char *)test[5].digest) != 0) { | ||
253 | printf("Error calculating 2nd interim HMAC on test 5\n"); | ||
254 | printf("got %s instead of %s\n", p, test[5].digest); | ||
255 | err++; | ||
256 | goto test6; | ||
257 | } | ||
258 | if (!HMAC_Init_ex(&ctx, test[6].key, test[6].key_len, NULL, NULL)) { | ||
259 | printf("Failed to reinitialise HMAC with key (test 5)\n"); | ||
260 | err++; | ||
261 | goto test6; | ||
262 | } | ||
263 | if (!HMAC_Update(&ctx, test[6].data, test[6].data_len)) { | ||
264 | printf("Error updating HMAC with data (new key) (test 5)\n"); | ||
265 | err++; | ||
266 | goto test6; | ||
267 | } | ||
268 | if (!HMAC_Final(&ctx, buf, &len)) { | ||
269 | printf("Error finalising data (new key) (test 5)\n"); | ||
270 | err++; | ||
271 | goto test6; | ||
272 | } | ||
273 | p = pt(buf, len); | ||
274 | if (strcmp(p, (char *)test[6].digest) != 0) { | ||
275 | printf("error calculating HMAC on test 5\n"); | ||
276 | printf("got %s instead of %s\n", p, test[6].digest); | ||
277 | err++; | ||
278 | } else { | ||
279 | printf("test 5 ok\n"); | ||
280 | } | ||
281 | test6: | ||
282 | HMAC_CTX_cleanup(&ctx); | ||
283 | HMAC_CTX_init(&ctx); | ||
284 | if (!HMAC_Init_ex(&ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL)) { | ||
285 | printf("Failed to initialise HMAC (test 6)\n"); | ||
286 | err++; | ||
287 | goto end; | ||
288 | } | ||
289 | if (!HMAC_Update(&ctx, test[7].data, test[7].data_len)) { | ||
290 | printf("Error updating HMAC with data (test 6)\n"); | ||
291 | err++; | ||
292 | goto end; | ||
293 | } | ||
294 | if (!HMAC_CTX_copy(&ctx2, &ctx)) { | ||
295 | printf("Failed to copy HMAC_CTX (test 6)\n"); | ||
296 | err++; | ||
297 | goto end; | ||
298 | } | ||
299 | if (!HMAC_Final(&ctx2, buf, &len)) { | ||
300 | printf("Error finalising data (test 6)\n"); | ||
301 | err++; | ||
302 | goto end; | ||
303 | } | ||
304 | p = pt(buf, len); | ||
305 | if (strcmp(p, (char *)test[7].digest) != 0) { | ||
306 | printf("Error calculating HMAC on test 6\n"); | ||
307 | printf("got %s instead of %s\n", p, test[7].digest); | ||
308 | err++; | ||
309 | } else { | ||
310 | printf("test 6 ok\n"); | ||
311 | } | ||
312 | end: | ||
313 | HMAC_CTX_cleanup(&ctx); | ||
140 | exit(err); | 314 | exit(err); |
141 | return(0); | 315 | return(0); |
142 | } | 316 | } |
143 | 317 | ||
144 | #ifndef OPENSSL_NO_MD5 | 318 | #ifndef OPENSSL_NO_MD5 |
145 | static char *pt(unsigned char *md) | 319 | static char * |
146 | { | 320 | pt(unsigned char *md, unsigned int len) |
321 | { | ||
147 | int i; | 322 | int i; |
148 | static char buf[80]; | 323 | static char buf[80]; |
149 | 324 | ||
150 | for (i=0; i<MD5_DIGEST_LENGTH; i++) | 325 | for (i = 0; i < len; i++) |
151 | snprintf(buf + i*2, sizeof(buf) - i*2, "%02x",md[i]); | 326 | snprintf(buf + i * 2, sizeof(buf) - i * 2, "%02x", md[i]); |
152 | return(buf); | 327 | return(buf); |
153 | } | 328 | } |
154 | #endif | 329 | #endif |