1/* $OpenBSD: tls1_prf.c,v 1.40 2024/07/10 06:53:27 tb Exp $ */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2016. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2015 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdlib.h> 61#include <stdio.h> 62#include <string.h> 63 64#include <openssl/err.h> 65#include <openssl/evp.h> 66#include <openssl/kdf.h> 67 68#include "evp_local.h" 69 70#define TLS1_PRF_MAXBUF 1024 71 72struct tls1_prf_ctx { 73 const EVP_MD *md; 74 unsigned char *secret; 75 size_t secret_len; 76 unsigned char seed[TLS1_PRF_MAXBUF]; 77 size_t seed_len; 78}; 79 80static int 81pkey_tls1_prf_init(EVP_PKEY_CTX *ctx) 82{ 83 struct tls1_prf_ctx *kctx; 84 85 if ((kctx = calloc(1, sizeof(*kctx))) == NULL) { 86 KDFerror(ERR_R_MALLOC_FAILURE); 87 return 0; 88 } 89 ctx->data = kctx; 90 91 return 1; 92} 93 94static void 95pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx) 96{ 97 struct tls1_prf_ctx *kctx = ctx->data; 98 99 freezero(kctx->secret, kctx->secret_len); 100 freezero(kctx, sizeof(*kctx)); 101} 102 103static int 104pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 105{ 106 struct tls1_prf_ctx *kctx = ctx->data; 107 108 switch (type) { 109 case EVP_PKEY_CTRL_TLS_MD: 110 kctx->md = p2; 111 return 1; 112 113 case EVP_PKEY_CTRL_TLS_SECRET: 114 if (p1 < 0) 115 return 0; 116 117 freezero(kctx->secret, kctx->secret_len); 118 kctx->secret = NULL; 119 kctx->secret_len = 0; 120 121 explicit_bzero(kctx->seed, kctx->seed_len); 122 kctx->seed_len = 0; 123 124 if (p1 == 0 || p2 == NULL) 125 return 0; 126 127 if ((kctx->secret = calloc(1, p1)) == NULL) 128 return 0; 129 memcpy(kctx->secret, p2, p1); 130 kctx->secret_len = p1; 131 132 return 1; 133 134 case EVP_PKEY_CTRL_TLS_SEED: 135 if (p1 == 0 || p2 == NULL) 136 return 1; 137 if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seed_len)) 138 return 0; 139 memcpy(kctx->seed + kctx->seed_len, p2, p1); 140 kctx->seed_len += p1; 141 return 1; 142 143 default: 144 return -2; 145 } 146} 147 148static int 149pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 150{ 151 if (value == NULL) { 152 KDFerror(KDF_R_VALUE_MISSING); 153 return 0; 154 } 155 if (strcmp(type, "md") == 0) { 156 struct tls1_prf_ctx *kctx = ctx->data; 157 158 const EVP_MD *md = EVP_get_digestbyname(value); 159 if (md == NULL) { 160 KDFerror(KDF_R_INVALID_DIGEST); 161 return 0; 162 } 163 kctx->md = md; 164 return 1; 165 } 166 if (strcmp(type, "secret") == 0) 167 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); 168 if (strcmp(type, "hexsecret") == 0) 169 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value); 170 if (strcmp(type, "seed") == 0) 171 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); 172 if (strcmp(type, "hexseed") == 0) 173 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value); 174 175 KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE); 176 return -2; 177} 178 179static int 180tls1_prf_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, 181 const unsigned char *seed, size_t seed_len, unsigned char *out, size_t out_len) 182{ 183 int chunk; 184 EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL; 185 EVP_PKEY *mac_key = NULL; 186 unsigned char A1[EVP_MAX_MD_SIZE]; 187 size_t A1_len; 188 int ret = 0; 189 190 if ((chunk = EVP_MD_size(md)) < 0) 191 goto err; 192 193 if ((ctx = EVP_MD_CTX_new()) == NULL) 194 goto err; 195 if ((ctx_tmp = EVP_MD_CTX_new()) == NULL) 196 goto err; 197 if ((ctx_init = EVP_MD_CTX_new()) == NULL) 198 goto err; 199 200 EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 201 202 if ((mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, 203 secret, secret_len)) == NULL) 204 goto err; 205 206 if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key)) 207 goto err; 208 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) 209 goto err; 210 if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len)) 211 goto err; 212 if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) 213 goto err; 214 215 for (;;) { 216 /* Reinit mac contexts */ 217 if (!EVP_MD_CTX_copy_ex(ctx, ctx_init)) 218 goto err; 219 if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) 220 goto err; 221 if (out_len > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx)) 222 goto err; 223 if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len)) 224 goto err; 225 226 if (out_len > (size_t)chunk) { 227 size_t mac_len; 228 if (!EVP_DigestSignFinal(ctx, out, &mac_len)) 229 goto err; 230 out += mac_len; 231 out_len -= mac_len; 232 if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len)) 233 goto err; 234 } else { 235 if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) 236 goto err; 237 memcpy(out, A1, out_len); 238 break; 239 } 240 } 241 242 ret = 1; 243 244 err: 245 EVP_PKEY_free(mac_key); 246 EVP_MD_CTX_free(ctx); 247 EVP_MD_CTX_free(ctx_tmp); 248 EVP_MD_CTX_free(ctx_init); 249 explicit_bzero(A1, sizeof(A1)); 250 251 return ret; 252} 253 254static int 255tls1_prf_alg(const EVP_MD *md, const unsigned char *secret, size_t secret_len, 256 const unsigned char *seed, size_t seed_len, unsigned char *out, size_t out_len) 257{ 258 unsigned char *tmp = NULL; 259 size_t half_len; 260 size_t i; 261 int ret = 0; 262 263 if (EVP_MD_type(md) != NID_md5_sha1) 264 return tls1_prf_P_hash(md, secret, secret_len, seed, seed_len, 265 out, out_len); 266 267 half_len = secret_len - secret_len / 2; 268 if (!tls1_prf_P_hash(EVP_md5(), secret, half_len, seed, seed_len, 269 out, out_len)) 270 goto err; 271 272 if ((tmp = calloc(1, out_len)) == NULL) { 273 KDFerror(ERR_R_MALLOC_FAILURE); 274 goto err; 275 } 276 secret += secret_len - half_len; 277 if (!tls1_prf_P_hash(EVP_sha1(), secret, half_len, seed, seed_len, 278 tmp, out_len)) 279 goto err; 280 for (i = 0; i < out_len; i++) 281 out[i] ^= tmp[i]; 282 283 ret = 1; 284 285 err: 286 freezero(tmp, out_len); 287 288 return ret; 289} 290 291static int 292pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len) 293{ 294 struct tls1_prf_ctx *kctx = ctx->data; 295 296 if (kctx->md == NULL) { 297 KDFerror(KDF_R_MISSING_MESSAGE_DIGEST); 298 return 0; 299 } 300 if (kctx->secret == NULL) { 301 KDFerror(KDF_R_MISSING_SECRET); 302 return 0; 303 } 304 if (kctx->seed_len == 0) { 305 KDFerror(KDF_R_MISSING_SEED); 306 return 0; 307 } 308 309 return tls1_prf_alg(kctx->md, kctx->secret, kctx->secret_len, 310 kctx->seed, kctx->seed_len, key, *key_len); 311} 312 313const EVP_PKEY_METHOD tls1_prf_pkey_meth = { 314 .pkey_id = EVP_PKEY_TLS1_PRF, 315 .flags = 0, 316 317 .init = pkey_tls1_prf_init, 318 .copy = NULL, 319 .cleanup = pkey_tls1_prf_cleanup, 320 321 .paramgen = NULL, 322 323 .keygen = NULL, 324 325 .sign_init = NULL, 326 .sign = NULL, 327 328 .verify_init = NULL, 329 .verify = NULL, 330 331 .verify_recover = NULL, 332 333 .signctx_init = NULL, 334 .signctx = NULL, 335 336 .encrypt = NULL, 337 338 .decrypt = NULL, 339 340 .derive_init = NULL, 341 .derive = pkey_tls1_prf_derive, 342 343 .ctrl = pkey_tls1_prf_ctrl, 344 .ctrl_str = pkey_tls1_prf_ctrl_str, 345}; 346