summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2024-03-25 13:09:13 +0000
committerjsing <>2024-03-25 13:09:13 +0000
commite00adf12955fdea439af1b8b891281599923a63d (patch)
treee2d4382cd172c23377b42dd44c5db5506114726a
parenteae74a9d914ce6cfd4b0079fc18c48ba7760093b (diff)
downloadopenbsd-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.c88
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}
123LCRYPTO_ALIAS(HKDF_expand); 135LCRYPTO_ALIAS(HKDF_expand);