1 /* $OpenBSD: hkdf_evp.c,v 1.18 2022/05/05 19:48:06 tb Exp $ */ 2 /* ==================================================================== 3 * Copyright (c) 2016-2018 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 */ 49 50 #include <stdlib.h> 51 #include <string.h> 52 53 #include <openssl/err.h> 54 #include <openssl/evp.h> 55 #include <openssl/hmac.h> 56 #include <openssl/hkdf.h> 57 #include <openssl/kdf.h> 58 59 #include "evp_locl.h" 60 61 #define HKDF_MAXBUF 1024 62 63 typedef struct { 64 int mode; 65 const EVP_MD *md; 66 unsigned char *salt; 67 size_t salt_len; 68 unsigned char *key; 69 size_t key_len; 70 unsigned char info[HKDF_MAXBUF]; 71 size_t info_len; 72 } HKDF_PKEY_CTX; 73 74 static int 75 pkey_hkdf_init(EVP_PKEY_CTX *ctx) 76 { 77 HKDF_PKEY_CTX *kctx; 78 79 if ((kctx = calloc(1, sizeof(*kctx))) == NULL) { 80 KDFerror(ERR_R_MALLOC_FAILURE); 81 return 0; 82 } 83 84 ctx->data = kctx; 85 86 return 1; 87 } 88 89 static void 90 pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx) 91 { 92 HKDF_PKEY_CTX *kctx = ctx->data; 93 94 freezero(kctx->salt, kctx->salt_len); 95 freezero(kctx->key, kctx->key_len); 96 freezero(kctx, sizeof(*kctx)); 97 } 98 99 static int 100 pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 101 { 102 HKDF_PKEY_CTX *kctx = ctx->data; 103 104 switch (type) { 105 case EVP_PKEY_CTRL_HKDF_MD: 106 if (p2 == NULL) 107 return 0; 108 109 kctx->md = p2; 110 return 1; 111 112 case EVP_PKEY_CTRL_HKDF_MODE: 113 kctx->mode = p1; 114 return 1; 115 116 case EVP_PKEY_CTRL_HKDF_SALT: 117 if (p1 == 0 || p2 == NULL) 118 return 1; 119 120 if (p1 < 0) 121 return 0; 122 123 freezero(kctx->salt, kctx->salt_len); 124 if ((kctx->salt = malloc(p1)) == NULL) 125 return 0; 126 memcpy(kctx->salt, p2, p1); 127 128 kctx->salt_len = p1; 129 return 1; 130 131 case EVP_PKEY_CTRL_HKDF_KEY: 132 if (p1 <= 0) 133 return 0; 134 135 freezero(kctx->key, kctx->key_len); 136 if ((kctx->key = malloc(p1)) == NULL) 137 return 0; 138 memcpy(kctx->key, p2, p1); 139 140 kctx->key_len = p1; 141 return 1; 142 143 case EVP_PKEY_CTRL_HKDF_INFO: 144 if (p1 == 0 || p2 == NULL) 145 return 1; 146 147 if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len)) 148 return 0; 149 150 memcpy(kctx->info + kctx->info_len, p2, p1); 151 kctx->info_len += p1; 152 return 1; 153 154 default: 155 return -2; 156 } 157 } 158 159 static int 160 pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, 161 const char *value) 162 { 163 if (strcmp(type, "mode") == 0) { 164 int mode; 165 166 if (strcmp(value, "EXTRACT_AND_EXPAND") == 0) 167 mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND; 168 else if (strcmp(value, "EXTRACT_ONLY") == 0) 169 mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY; 170 else if (strcmp(value, "EXPAND_ONLY") == 0) 171 mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY; 172 else 173 return 0; 174 175 return EVP_PKEY_CTX_hkdf_mode(ctx, mode); 176 } 177 178 if (strcmp(type, "md") == 0) 179 return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE, 180 EVP_PKEY_CTRL_HKDF_MD, value); 181 182 if (strcmp(type, "salt") == 0) 183 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, 184 value); 185 186 if (strcmp(type, "hexsalt") == 0) 187 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, 188 value); 189 190 if (strcmp(type, "key") == 0) 191 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value); 192 193 if (strcmp(type, "hexkey") == 0) 194 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value); 195 196 if (strcmp(type, "info") == 0) 197 return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, 198 value); 199 200 if (strcmp(type, "hexinfo") == 0) 201 return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, 202 value); 203 204 KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE); 205 return -2; 206 } 207 208 static int 209 pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx) 210 { 211 HKDF_PKEY_CTX *kctx = ctx->data; 212 213 freezero(kctx->key, kctx->key_len); 214 freezero(kctx->salt, kctx->salt_len); 215 explicit_bzero(kctx, sizeof(*kctx)); 216 217 return 1; 218 } 219 220 static int 221 pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 222 size_t *keylen) 223 { 224 HKDF_PKEY_CTX *kctx = ctx->data; 225 226 if (kctx->md == NULL) { 227 KDFerror(KDF_R_MISSING_MESSAGE_DIGEST); 228 return 0; 229 } 230 if (kctx->key == NULL) { 231 KDFerror(KDF_R_MISSING_KEY); 232 return 0; 233 } 234 235 switch (kctx->mode) { 236 case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND: 237 return HKDF(key, *keylen, kctx->md, kctx->key, kctx->key_len, 238 kctx->salt, kctx->salt_len, kctx->info, kctx->info_len); 239 240 case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY: 241 if (key == NULL) { 242 *keylen = EVP_MD_size(kctx->md); 243 return 1; 244 } 245 return HKDF_extract(key, keylen, kctx->md, kctx->key, 246 kctx->key_len, kctx->salt, kctx->salt_len); 247 248 case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY: 249 return HKDF_expand(key, *keylen, kctx->md, kctx->key, 250 kctx->key_len, kctx->info, kctx->info_len); 251 252 default: 253 return 0; 254 } 255 } 256 257 const EVP_PKEY_METHOD hkdf_pkey_meth = { 258 .pkey_id = EVP_PKEY_HKDF, 259 .flags = 0, 260 261 .init = pkey_hkdf_init, 262 .copy = NULL, 263 .cleanup = pkey_hkdf_cleanup, 264 265 .derive_init = pkey_hkdf_derive_init, 266 .derive = pkey_hkdf_derive, 267 .ctrl = pkey_hkdf_ctrl, 268 .ctrl_str = pkey_hkdf_ctrl_str, 269 }; 270