diff options
-rw-r--r-- | src/lib/libcrypto/kdf/tls1_prf.c | 462 |
1 files changed, 236 insertions, 226 deletions
diff --git a/src/lib/libcrypto/kdf/tls1_prf.c b/src/lib/libcrypto/kdf/tls1_prf.c index c065572431..cc3f27f3c9 100644 --- a/src/lib/libcrypto/kdf/tls1_prf.c +++ b/src/lib/libcrypto/kdf/tls1_prf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls1_prf.c,v 1.14 2024/07/09 16:45:33 tb Exp $ */ | 1 | /* $OpenBSD: tls1_prf.c,v 1.15 2024/07/09 16:46:33 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project | 3 | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project |
4 | * 2016. | 4 | * 2016. |
@@ -68,9 +68,9 @@ | |||
68 | #include "evp_local.h" | 68 | #include "evp_local.h" |
69 | 69 | ||
70 | static int tls1_prf_alg(const EVP_MD *md, | 70 | static int tls1_prf_alg(const EVP_MD *md, |
71 | const unsigned char *sec, size_t slen, | 71 | const unsigned char *sec, size_t slen, |
72 | const unsigned char *seed, size_t seed_len, | 72 | const unsigned char *seed, size_t seed_len, |
73 | unsigned char *out, size_t olen); | 73 | unsigned char *out, size_t olen); |
74 | 74 | ||
75 | #define TLS1_PRF_MAXBUF 1024 | 75 | #define TLS1_PRF_MAXBUF 1024 |
76 | 76 | ||
@@ -78,267 +78,277 @@ static int tls1_prf_alg(const EVP_MD *md, | |||
78 | 78 | ||
79 | typedef struct { | 79 | typedef struct { |
80 | /* Digest to use for PRF */ | 80 | /* Digest to use for PRF */ |
81 | const EVP_MD *md; | 81 | const EVP_MD *md; |
82 | /* Secret value to use for PRF */ | 82 | /* Secret value to use for PRF */ |
83 | unsigned char *sec; | 83 | unsigned char *sec; |
84 | size_t seclen; | 84 | size_t seclen; |
85 | /* Buffer of concatenated seed data */ | 85 | /* Buffer of concatenated seed data */ |
86 | unsigned char seed[TLS1_PRF_MAXBUF]; | 86 | unsigned char seed[TLS1_PRF_MAXBUF]; |
87 | size_t seedlen; | 87 | size_t seedlen; |
88 | } TLS1_PRF_PKEY_CTX; | 88 | } TLS1_PRF_PKEY_CTX; |
89 | 89 | ||
90 | static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx) | 90 | static int |
91 | pkey_tls1_prf_init(EVP_PKEY_CTX *ctx) | ||
91 | { | 92 | { |
92 | TLS1_PRF_PKEY_CTX *kctx; | 93 | TLS1_PRF_PKEY_CTX *kctx; |
93 | 94 | ||
94 | if ((kctx = calloc(1, sizeof(*kctx))) == NULL) { | 95 | if ((kctx = calloc(1, sizeof(*kctx))) == NULL) { |
95 | KDFerror(ERR_R_MALLOC_FAILURE); | 96 | KDFerror(ERR_R_MALLOC_FAILURE); |
96 | return 0; | 97 | return 0; |
97 | } | 98 | } |
98 | ctx->data = kctx; | 99 | ctx->data = kctx; |
99 | 100 | ||
100 | return 1; | 101 | return 1; |
101 | } | 102 | } |
102 | 103 | ||
103 | static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx) | 104 | static void |
105 | pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx) | ||
104 | { | 106 | { |
105 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; | 107 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; |
106 | freezero(kctx->sec, kctx->seclen); | 108 | freezero(kctx->sec, kctx->seclen); |
107 | explicit_bzero(kctx->seed, kctx->seedlen); | 109 | explicit_bzero(kctx->seed, kctx->seedlen); |
108 | free(kctx); | 110 | free(kctx); |
109 | } | 111 | } |
110 | 112 | ||
111 | static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | 113 | static int |
114 | pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | ||
112 | { | 115 | { |
113 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; | 116 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; |
114 | switch (type) { | 117 | switch (type) { |
115 | case EVP_PKEY_CTRL_TLS_MD: | 118 | case EVP_PKEY_CTRL_TLS_MD: |
116 | kctx->md = p2; | 119 | kctx->md = p2; |
117 | return 1; | 120 | return 1; |
118 | 121 | ||
119 | case EVP_PKEY_CTRL_TLS_SECRET: | 122 | case EVP_PKEY_CTRL_TLS_SECRET: |
120 | if (p1 < 0) | 123 | if (p1 < 0) |
121 | return 0; | 124 | return 0; |
122 | if (kctx->sec != NULL) | 125 | if (kctx->sec != NULL) |
123 | freezero(kctx->sec, kctx->seclen); | 126 | freezero(kctx->sec, kctx->seclen); |
124 | 127 | ||
125 | explicit_bzero(kctx->seed, kctx->seedlen); | 128 | explicit_bzero(kctx->seed, kctx->seedlen); |
126 | kctx->seedlen = 0; | 129 | kctx->seedlen = 0; |
127 | 130 | ||
128 | kctx->sec = NULL; | 131 | kctx->sec = NULL; |
129 | kctx->seclen = 0; | 132 | kctx->seclen = 0; |
130 | 133 | ||
131 | if (p1 == 0 || p2 == NULL) | 134 | if (p1 == 0 || p2 == NULL) |
132 | return 0; | 135 | return 0; |
133 | 136 | ||
134 | if ((kctx->sec = calloc(1, p1)) == NULL) | 137 | if ((kctx->sec = calloc(1, p1)) == NULL) |
135 | return 0; | 138 | return 0; |
136 | memcpy(kctx->sec, p2, p1); | 139 | memcpy(kctx->sec, p2, p1); |
137 | kctx->seclen = p1; | 140 | kctx->seclen = p1; |
138 | 141 | ||
139 | return 1; | 142 | return 1; |
140 | 143 | ||
141 | case EVP_PKEY_CTRL_TLS_SEED: | 144 | case EVP_PKEY_CTRL_TLS_SEED: |
142 | if (p1 == 0 || p2 == NULL) | 145 | if (p1 == 0 || p2 == NULL) |
143 | return 1; | 146 | return 1; |
144 | if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen)) | 147 | if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen)) |
145 | return 0; | 148 | return 0; |
146 | memcpy(kctx->seed + kctx->seedlen, p2, p1); | 149 | memcpy(kctx->seed + kctx->seedlen, p2, p1); |
147 | kctx->seedlen += p1; | 150 | kctx->seedlen += p1; |
148 | return 1; | 151 | return 1; |
149 | 152 | ||
150 | default: | 153 | default: |
151 | return -2; | 154 | return -2; |
152 | 155 | } | |
153 | } | ||
154 | } | 156 | } |
155 | 157 | ||
156 | static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, | 158 | static int |
157 | const char *type, const char *value) | 159 | pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, |
160 | const char *type, const char *value) | ||
158 | { | 161 | { |
159 | if (value == NULL) { | 162 | if (value == NULL) { |
160 | KDFerror(KDF_R_VALUE_MISSING); | 163 | KDFerror(KDF_R_VALUE_MISSING); |
161 | return 0; | 164 | return 0; |
162 | } | 165 | } |
163 | if (strcmp(type, "md") == 0) { | 166 | if (strcmp(type, "md") == 0) { |
164 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; | 167 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; |
165 | 168 | ||
166 | const EVP_MD *md = EVP_get_digestbyname(value); | 169 | const EVP_MD *md = EVP_get_digestbyname(value); |
167 | if (md == NULL) { | 170 | if (md == NULL) { |
168 | KDFerror(KDF_R_INVALID_DIGEST); | 171 | KDFerror(KDF_R_INVALID_DIGEST); |
169 | return 0; | 172 | return 0; |
170 | } | 173 | } |
171 | kctx->md = md; | 174 | kctx->md = md; |
172 | return 1; | 175 | return 1; |
173 | } | 176 | } |
174 | if (strcmp(type, "secret") == 0) | 177 | if (strcmp(type, "secret") == 0) |
175 | return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); | 178 | return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, |
176 | if (strcmp(type, "hexsecret") == 0) | 179 | value); |
177 | return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); | 180 | if (strcmp(type, "hexsecret") == 0) |
178 | if (strcmp(type, "seed") == 0) | 181 | return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, |
179 | return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); | 182 | value); |
180 | if (strcmp(type, "hexseed") == 0) | 183 | if (strcmp(type, "seed") == 0) |
181 | return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); | 184 | return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, |
182 | 185 | value); | |
183 | KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE); | 186 | if (strcmp(type, "hexseed") == 0) |
184 | return -2; | 187 | return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, |
188 | value); | ||
189 | |||
190 | KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE); | ||
191 | return -2; | ||
185 | } | 192 | } |
186 | 193 | ||
187 | static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, | 194 | static int |
188 | size_t *keylen) | 195 | pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, |
196 | size_t *keylen) | ||
189 | { | 197 | { |
190 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; | 198 | TLS1_PRF_PKEY_CTX *kctx = ctx->data; |
191 | if (kctx->md == NULL) { | 199 | if (kctx->md == NULL) { |
192 | KDFerror(KDF_R_MISSING_MESSAGE_DIGEST); | 200 | KDFerror(KDF_R_MISSING_MESSAGE_DIGEST); |
193 | return 0; | 201 | return 0; |
194 | } | 202 | } |
195 | if (kctx->sec == NULL) { | 203 | if (kctx->sec == NULL) { |
196 | KDFerror(KDF_R_MISSING_SECRET); | 204 | KDFerror(KDF_R_MISSING_SECRET); |
197 | return 0; | 205 | return 0; |
198 | } | 206 | } |
199 | if (kctx->seedlen == 0) { | 207 | if (kctx->seedlen == 0) { |
200 | KDFerror(KDF_R_MISSING_SEED); | 208 | KDFerror(KDF_R_MISSING_SEED); |
201 | return 0; | 209 | return 0; |
202 | } | 210 | } |
203 | return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen, | 211 | return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen, |
204 | kctx->seed, kctx->seedlen, | 212 | kctx->seed, kctx->seedlen, |
205 | key, *keylen); | 213 | key, *keylen); |
206 | } | 214 | } |
207 | 215 | ||
208 | const EVP_PKEY_METHOD tls1_prf_pkey_meth = { | 216 | const EVP_PKEY_METHOD tls1_prf_pkey_meth = { |
209 | .pkey_id = EVP_PKEY_TLS1_PRF, | 217 | .pkey_id = EVP_PKEY_TLS1_PRF, |
210 | .flags = 0, | 218 | .flags = 0, |
211 | 219 | ||
212 | .init = pkey_tls1_prf_init, | 220 | .init = pkey_tls1_prf_init, |
213 | .copy = NULL, | 221 | .copy = NULL, |
214 | .cleanup = pkey_tls1_prf_cleanup, | 222 | .cleanup = pkey_tls1_prf_cleanup, |
215 | 223 | ||
216 | .paramgen = NULL, | 224 | .paramgen = NULL, |
217 | 225 | ||
218 | .keygen = NULL, | 226 | .keygen = NULL, |
219 | 227 | ||
220 | .sign_init = NULL, | 228 | .sign_init = NULL, |
221 | .sign = NULL, | 229 | .sign = NULL, |
222 | 230 | ||
223 | .verify_init = NULL, | 231 | .verify_init = NULL, |
224 | .verify = NULL, | 232 | .verify = NULL, |
225 | 233 | ||
226 | .verify_recover = NULL, | 234 | .verify_recover = NULL, |
227 | 235 | ||
228 | .signctx_init = NULL, | 236 | .signctx_init = NULL, |
229 | .signctx = NULL, | 237 | .signctx = NULL, |
230 | 238 | ||
231 | .encrypt = NULL, | 239 | .encrypt = NULL, |
232 | 240 | ||
233 | .decrypt = NULL, | 241 | .decrypt = NULL, |
234 | 242 | ||
235 | .derive_init = NULL, | 243 | .derive_init = NULL, |
236 | .derive = pkey_tls1_prf_derive, | 244 | .derive = pkey_tls1_prf_derive, |
237 | 245 | ||
238 | .ctrl = pkey_tls1_prf_ctrl, | 246 | .ctrl = pkey_tls1_prf_ctrl, |
239 | .ctrl_str = pkey_tls1_prf_ctrl_str, | 247 | .ctrl_str = pkey_tls1_prf_ctrl_str, |
240 | }; | 248 | }; |
241 | 249 | ||
242 | static int tls1_prf_P_hash(const EVP_MD *md, | 250 | static int |
243 | const unsigned char *sec, size_t sec_len, | 251 | tls1_prf_P_hash(const EVP_MD *md, |
244 | const unsigned char *seed, size_t seed_len, | 252 | const unsigned char *sec, size_t sec_len, |
245 | unsigned char *out, size_t olen) | 253 | const unsigned char *seed, size_t seed_len, |
254 | unsigned char *out, size_t olen) | ||
246 | { | 255 | { |
247 | int chunk; | 256 | int chunk; |
248 | EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL; | 257 | EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL; |
249 | EVP_PKEY *mac_key = NULL; | 258 | EVP_PKEY *mac_key = NULL; |
250 | unsigned char A1[EVP_MAX_MD_SIZE]; | 259 | unsigned char A1[EVP_MAX_MD_SIZE]; |
251 | size_t A1_len; | 260 | size_t A1_len; |
252 | int ret = 0; | 261 | int ret = 0; |
253 | 262 | ||
254 | if ((chunk = EVP_MD_size(md)) < 0) | 263 | if ((chunk = EVP_MD_size(md)) < 0) |
255 | goto err; | 264 | goto err; |
256 | 265 | ||
257 | ctx = EVP_MD_CTX_new(); | 266 | ctx = EVP_MD_CTX_new(); |
258 | ctx_tmp = EVP_MD_CTX_new(); | 267 | ctx_tmp = EVP_MD_CTX_new(); |
259 | ctx_init = EVP_MD_CTX_new(); | 268 | ctx_init = EVP_MD_CTX_new(); |
260 | if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL) | 269 | if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL) |
261 | goto err; | 270 | goto err; |
262 | EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); | 271 | EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); |
263 | mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, sec, sec_len); | 272 | mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, sec, |
264 | if (mac_key == NULL) | 273 | sec_len); |
265 | goto err; | 274 | if (mac_key == NULL) |
266 | if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key)) | 275 | goto err; |
267 | goto err; | 276 | if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key)) |
268 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) | 277 | goto err; |
269 | goto err; | 278 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) |
270 | if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len)) | 279 | goto err; |
271 | goto err; | 280 | if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len)) |
272 | if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) | 281 | goto err; |
273 | goto err; | 282 | if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) |
274 | 283 | goto err; | |
275 | for (;;) { | 284 | |
276 | /* Reinit mac contexts */ | 285 | for (;;) { |
277 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) | 286 | /* Reinit mac contexts */ |
278 | goto err; | 287 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) |
279 | if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) | 288 | goto err; |
280 | goto err; | 289 | if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) |
281 | if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx)) | 290 | goto err; |
282 | goto err; | 291 | if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx)) |
283 | if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len)) | 292 | goto err; |
284 | goto err; | 293 | if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len)) |
285 | 294 | goto err; | |
286 | if (olen > (size_t)chunk) { | 295 | |
287 | size_t mac_len; | 296 | if (olen > (size_t)chunk) { |
288 | if (!EVP_DigestSignFinal(ctx, out, &mac_len)) | 297 | size_t mac_len; |
289 | goto err; | 298 | if (!EVP_DigestSignFinal(ctx, out, &mac_len)) |
290 | out += mac_len; | 299 | goto err; |
291 | olen -= mac_len; | 300 | out += mac_len; |
292 | /* calc the next A1 value */ | 301 | olen -= mac_len; |
293 | if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len)) | 302 | /* calc the next A1 value */ |
294 | goto err; | 303 | if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len)) |
295 | } else { /* last one */ | 304 | goto err; |
296 | 305 | } else { /* last one */ | |
297 | if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) | 306 | if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) |
298 | goto err; | 307 | goto err; |
299 | memcpy(out, A1, olen); | 308 | memcpy(out, A1, olen); |
300 | break; | 309 | break; |
301 | } | 310 | } |
302 | } | 311 | } |
303 | ret = 1; | 312 | ret = 1; |
304 | err: | 313 | err: |
305 | EVP_PKEY_free(mac_key); | 314 | EVP_PKEY_free(mac_key); |
306 | EVP_MD_CTX_free(ctx); | 315 | EVP_MD_CTX_free(ctx); |
307 | EVP_MD_CTX_free(ctx_tmp); | 316 | EVP_MD_CTX_free(ctx_tmp); |
308 | EVP_MD_CTX_free(ctx_init); | 317 | EVP_MD_CTX_free(ctx_init); |
309 | explicit_bzero(A1, sizeof(A1)); | 318 | explicit_bzero(A1, sizeof(A1)); |
310 | return ret; | 319 | return ret; |
311 | } | 320 | } |
312 | 321 | ||
313 | static int tls1_prf_alg(const EVP_MD *md, | 322 | static int |
314 | const unsigned char *sec, size_t slen, | 323 | tls1_prf_alg(const EVP_MD *md, |
315 | const unsigned char *seed, size_t seed_len, | 324 | const unsigned char *sec, size_t slen, |
316 | unsigned char *out, size_t olen) | 325 | const unsigned char *seed, size_t seed_len, |
326 | unsigned char *out, size_t olen) | ||
317 | { | 327 | { |
318 | 328 | ||
319 | if (EVP_MD_type(md) == NID_md5_sha1) { | 329 | if (EVP_MD_type(md) == NID_md5_sha1) { |
320 | size_t i; | 330 | size_t i; |
321 | unsigned char *tmp; | 331 | unsigned char *tmp; |
322 | if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1), | 332 | if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1), |
323 | seed, seed_len, out, olen)) | 333 | seed, seed_len, out, olen)) |
324 | return 0; | 334 | return 0; |
325 | 335 | ||
326 | if ((tmp = calloc(1, olen)) == NULL) { | 336 | if ((tmp = calloc(1, olen)) == NULL) { |
327 | KDFerror(ERR_R_MALLOC_FAILURE); | 337 | KDFerror(ERR_R_MALLOC_FAILURE); |
328 | return 0; | 338 | return 0; |
329 | } | 339 | } |
330 | if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1), | 340 | if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, |
331 | seed, seed_len, tmp, olen)) { | 341 | slen/2 + (slen & 1), seed, seed_len, tmp, olen)) { |
332 | freezero(tmp, olen); | 342 | freezero(tmp, olen); |
333 | return 0; | 343 | return 0; |
334 | } | 344 | } |
335 | for (i = 0; i < olen; i++) | 345 | for (i = 0; i < olen; i++) |
336 | out[i] ^= tmp[i]; | 346 | out[i] ^= tmp[i]; |
337 | freezero(tmp, olen); | 347 | freezero(tmp, olen); |
338 | return 1; | 348 | return 1; |
339 | } | 349 | } |
340 | if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen)) | 350 | if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen)) |
341 | return 0; | 351 | return 0; |
342 | 352 | ||
343 | return 1; | 353 | return 1; |
344 | } | 354 | } |