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 /src | |
| 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@
Diffstat (limited to 'src')
| -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); |
