diff options
author | jsing <> | 2024-03-25 13:09:13 +0000 |
---|---|---|
committer | jsing <> | 2024-03-25 13:09:13 +0000 |
commit | e00adf12955fdea439af1b8b891281599923a63d (patch) | |
tree | e2d4382cd172c23377b42dd44c5db5506114726a | |
parent | eae74a9d914ce6cfd4b0079fc18c48ba7760093b (diff) | |
download | openbsd-e00adf12955fdea439af1b8b891281599923a63d.tar.gz openbsd-e00adf12955fdea439af1b8b891281599923a63d.tar.bz2 openbsd-e00adf12955fdea439af1b8b891281599923a63d.zip |
Rewrite HKDF_expand().
Simplify overflow checking and length tracking, use a CBB to handle output
and use HMAC_CTX_new() rather than having a HMAC_CTX on the stack.
ok tb@
-rw-r--r-- | src/lib/libcrypto/hkdf/hkdf.c | 88 |
1 files changed, 50 insertions, 38 deletions
diff --git a/src/lib/libcrypto/hkdf/hkdf.c b/src/lib/libcrypto/hkdf/hkdf.c index 4f9c9e566a..6104ef0cc7 100644 --- a/src/lib/libcrypto/hkdf/hkdf.c +++ b/src/lib/libcrypto/hkdf/hkdf.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* $OpenBSD: hkdf.c,v 1.10 2023/07/07 13:54:46 beck Exp $ */ | 1 | /* $OpenBSD: hkdf.c,v 1.11 2024/03/25 13:09:13 jsing Exp $ */ |
2 | /* Copyright (c) 2014, Google Inc. | 2 | /* |
3 | * Copyright (c) 2014, Google Inc. | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -21,6 +22,7 @@ | |||
21 | #include <openssl/err.h> | 22 | #include <openssl/err.h> |
22 | #include <openssl/hmac.h> | 23 | #include <openssl/hmac.h> |
23 | 24 | ||
25 | #include "bytestring.h" | ||
24 | #include "evp_local.h" | 26 | #include "evp_local.h" |
25 | #include "hmac_local.h" | 27 | #include "hmac_local.h" |
26 | 28 | ||
@@ -73,51 +75,61 @@ HKDF_expand(uint8_t *out_key, size_t out_len, | |||
73 | const uint8_t *info, size_t info_len) | 75 | const uint8_t *info, size_t info_len) |
74 | { | 76 | { |
75 | const size_t digest_len = EVP_MD_size(digest); | 77 | const size_t digest_len = EVP_MD_size(digest); |
76 | uint8_t previous[EVP_MAX_MD_SIZE]; | 78 | uint8_t out_hmac[EVP_MAX_MD_SIZE]; |
77 | size_t n, done = 0; | 79 | size_t n, remaining; |
78 | unsigned int i; | 80 | uint8_t ctr; |
81 | HMAC_CTX *hmac = NULL; | ||
82 | CBB cbb; | ||
79 | int ret = 0; | 83 | int ret = 0; |
80 | HMAC_CTX hmac; | ||
81 | 84 | ||
82 | /* Expand key material to desired length. */ | 85 | if (!CBB_init_fixed(&cbb, out_key, out_len)) |
83 | n = (out_len + digest_len - 1) / digest_len; | 86 | goto err; |
84 | if (out_len + digest_len < out_len || n > 255) { | ||
85 | CRYPTOerror(EVP_R_TOO_LARGE); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | HMAC_CTX_init(&hmac); | ||
90 | if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) | ||
91 | goto out; | ||
92 | |||
93 | for (i = 0; i < n; i++) { | ||
94 | uint8_t ctr = i + 1; | ||
95 | size_t todo; | ||
96 | 87 | ||
97 | if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) || | 88 | if ((hmac = HMAC_CTX_new()) == NULL) |
98 | !HMAC_Update(&hmac, previous, digest_len))) | 89 | goto err; |
99 | goto out; | 90 | if (!HMAC_Init_ex(hmac, prk, prk_len, digest, NULL)) |
91 | goto err; | ||
100 | 92 | ||
101 | if (!HMAC_Update(&hmac, info, info_len) || | 93 | remaining = out_len; |
102 | !HMAC_Update(&hmac, &ctr, 1) || | 94 | ctr = 0; |
103 | !HMAC_Final(&hmac, previous, NULL)) | ||
104 | goto out; | ||
105 | 95 | ||
106 | todo = digest_len; | 96 | /* Expand key material to desired length. */ |
107 | if (todo > out_len - done) | 97 | while (remaining > 0) { |
108 | todo = out_len - done; | 98 | if (++ctr == 0) { |
109 | 99 | CRYPTOerror(EVP_R_TOO_LARGE); | |
110 | memcpy(out_key + done, previous, todo); | 100 | goto err; |
111 | done += todo; | 101 | } |
102 | |||
103 | if (!HMAC_Update(hmac, info, info_len)) | ||
104 | goto err; | ||
105 | if (!HMAC_Update(hmac, &ctr, 1)) | ||
106 | goto err; | ||
107 | if (!HMAC_Final(hmac, out_hmac, NULL)) | ||
108 | goto err; | ||
109 | |||
110 | if ((n = remaining) > digest_len) | ||
111 | n = digest_len; | ||
112 | |||
113 | if (!CBB_add_bytes(&cbb, out_hmac, n)) | ||
114 | goto err; | ||
115 | |||
116 | remaining -= n; | ||
117 | |||
118 | if (remaining > 0) { | ||
119 | if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL)) | ||
120 | goto err; | ||
121 | if (!HMAC_Update(hmac, out_hmac, digest_len)) | ||
122 | goto err; | ||
123 | } | ||
112 | } | 124 | } |
113 | 125 | ||
114 | ret = 1; | 126 | ret = 1; |
115 | 127 | ||
116 | out: | 128 | err: |
117 | HMAC_CTX_cleanup(&hmac); | 129 | CBB_cleanup(&cbb); |
118 | explicit_bzero(previous, sizeof(previous)); | 130 | HMAC_CTX_free(hmac); |
119 | if (ret != 1) | 131 | explicit_bzero(out_hmac, sizeof(out_hmac)); |
120 | CRYPTOerror(ERR_R_CRYPTO_LIB); | 132 | |
121 | return ret; | 133 | return ret; |
122 | } | 134 | } |
123 | LCRYPTO_ALIAS(HKDF_expand); | 135 | LCRYPTO_ALIAS(HKDF_expand); |