1 /* 2 * Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* 11 * DES low level APIs are deprecated for public use, but still ok for internal 12 * use. We access the DES_set_odd_parity(3) function here. 13 */ 14 #include "internal/deprecated.h" 15 16 #include <stdlib.h> 17 #include <stdarg.h> 18 #include <string.h> 19 20 #include <openssl/core_names.h> 21 #include <openssl/des.h> 22 #include <openssl/evp.h> 23 #include <openssl/kdf.h> 24 #include <openssl/proverr.h> 25 26 #include "internal/cryptlib.h" 27 #include "crypto/evp.h" 28 #include "internal/numbers.h" 29 #include "prov/implementations.h" 30 #include "prov/provider_ctx.h" 31 #include "prov/provider_util.h" 32 #include "prov/providercommon.h" 33 34 /* KRB5 KDF defined in RFC 3961, Section 5.1 */ 35 36 static OSSL_FUNC_kdf_newctx_fn krb5kdf_new; 37 static OSSL_FUNC_kdf_dupctx_fn krb5kdf_dup; 38 static OSSL_FUNC_kdf_freectx_fn krb5kdf_free; 39 static OSSL_FUNC_kdf_reset_fn krb5kdf_reset; 40 static OSSL_FUNC_kdf_derive_fn krb5kdf_derive; 41 static OSSL_FUNC_kdf_settable_ctx_params_fn krb5kdf_settable_ctx_params; 42 static OSSL_FUNC_kdf_set_ctx_params_fn krb5kdf_set_ctx_params; 43 static OSSL_FUNC_kdf_gettable_ctx_params_fn krb5kdf_gettable_ctx_params; 44 static OSSL_FUNC_kdf_get_ctx_params_fn krb5kdf_get_ctx_params; 45 46 static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine, 47 const unsigned char *key, size_t key_len, 48 const unsigned char *constant, size_t constant_len, 49 unsigned char *okey, size_t okey_len); 50 51 typedef struct { 52 void *provctx; 53 PROV_CIPHER cipher; 54 unsigned char *key; 55 size_t key_len; 56 unsigned char *constant; 57 size_t constant_len; 58 } KRB5KDF_CTX; 59 60 static void *krb5kdf_new(void *provctx) 61 { 62 KRB5KDF_CTX *ctx; 63 64 if (!ossl_prov_is_running()) 65 return NULL; 66 67 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) 68 return NULL; 69 ctx->provctx = provctx; 70 return ctx; 71 } 72 73 static void krb5kdf_free(void *vctx) 74 { 75 KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; 76 77 if (ctx != NULL) { 78 krb5kdf_reset(ctx); 79 OPENSSL_free(ctx); 80 } 81 } 82 83 static void krb5kdf_reset(void *vctx) 84 { 85 KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; 86 void *provctx = ctx->provctx; 87 88 ossl_prov_cipher_reset(&ctx->cipher); 89 OPENSSL_clear_free(ctx->key, ctx->key_len); 90 OPENSSL_clear_free(ctx->constant, ctx->constant_len); 91 memset(ctx, 0, sizeof(*ctx)); 92 ctx->provctx = provctx; 93 } 94 95 static int krb5kdf_set_membuf(unsigned char **dst, size_t *dst_len, 96 const OSSL_PARAM *p) 97 { 98 OPENSSL_clear_free(*dst, *dst_len); 99 *dst = NULL; 100 *dst_len = 0; 101 return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len); 102 } 103 104 static void *krb5kdf_dup(void *vctx) 105 { 106 const KRB5KDF_CTX *src = (const KRB5KDF_CTX *)vctx; 107 KRB5KDF_CTX *dest; 108 109 dest = krb5kdf_new(src->provctx); 110 if (dest != NULL) { 111 if (!ossl_prov_memdup(src->key, src->key_len, 112 &dest->key, &dest->key_len) 113 || !ossl_prov_memdup(src->constant, src->constant_len, 114 &dest->constant , &dest->constant_len) 115 || !ossl_prov_cipher_copy(&dest->cipher, &src->cipher)) 116 goto err; 117 } 118 return dest; 119 120 err: 121 krb5kdf_free(dest); 122 return NULL; 123 } 124 125 static int krb5kdf_derive(void *vctx, unsigned char *key, size_t keylen, 126 const OSSL_PARAM params[]) 127 { 128 KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; 129 const EVP_CIPHER *cipher; 130 ENGINE *engine; 131 132 if (!ossl_prov_is_running() || !krb5kdf_set_ctx_params(ctx, params)) 133 return 0; 134 135 cipher = ossl_prov_cipher_cipher(&ctx->cipher); 136 if (cipher == NULL) { 137 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER); 138 return 0; 139 } 140 if (ctx->key == NULL) { 141 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); 142 return 0; 143 } 144 if (ctx->constant == NULL) { 145 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONSTANT); 146 return 0; 147 } 148 engine = ossl_prov_cipher_engine(&ctx->cipher); 149 return KRB5KDF(cipher, engine, ctx->key, ctx->key_len, 150 ctx->constant, ctx->constant_len, 151 key, keylen); 152 } 153 154 static int krb5kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 155 { 156 const OSSL_PARAM *p; 157 KRB5KDF_CTX *ctx = vctx; 158 OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx); 159 160 if (ossl_param_is_empty(params)) 161 return 1; 162 163 if (!ossl_prov_cipher_load_from_params(&ctx->cipher, params, provctx)) 164 return 0; 165 166 if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) 167 if (!krb5kdf_set_membuf(&ctx->key, &ctx->key_len, p)) 168 return 0; 169 170 if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CONSTANT)) 171 != NULL) 172 if (!krb5kdf_set_membuf(&ctx->constant, &ctx->constant_len, p)) 173 return 0; 174 175 return 1; 176 } 177 178 static const OSSL_PARAM *krb5kdf_settable_ctx_params(ossl_unused void *ctx, 179 ossl_unused void *provctx) 180 { 181 static const OSSL_PARAM known_settable_ctx_params[] = { 182 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), 183 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0), 184 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), 185 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_CONSTANT, NULL, 0), 186 OSSL_PARAM_END 187 }; 188 return known_settable_ctx_params; 189 } 190 191 static int krb5kdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) 192 { 193 KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; 194 const EVP_CIPHER *cipher; 195 size_t len; 196 OSSL_PARAM *p; 197 198 cipher = ossl_prov_cipher_cipher(&ctx->cipher); 199 if (cipher) 200 len = EVP_CIPHER_get_key_length(cipher); 201 else 202 len = EVP_MAX_KEY_LENGTH; 203 204 if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) 205 return OSSL_PARAM_set_size_t(p, len); 206 return -2; 207 } 208 209 static const OSSL_PARAM *krb5kdf_gettable_ctx_params(ossl_unused void *ctx, 210 ossl_unused void *provctx) 211 { 212 static const OSSL_PARAM known_gettable_ctx_params[] = { 213 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), 214 OSSL_PARAM_END 215 }; 216 return known_gettable_ctx_params; 217 } 218 219 const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[] = { 220 { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))krb5kdf_new }, 221 { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))krb5kdf_dup }, 222 { OSSL_FUNC_KDF_FREECTX, (void(*)(void))krb5kdf_free }, 223 { OSSL_FUNC_KDF_RESET, (void(*)(void))krb5kdf_reset }, 224 { OSSL_FUNC_KDF_DERIVE, (void(*)(void))krb5kdf_derive }, 225 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, 226 (void(*)(void))krb5kdf_settable_ctx_params }, 227 { OSSL_FUNC_KDF_SET_CTX_PARAMS, 228 (void(*)(void))krb5kdf_set_ctx_params }, 229 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, 230 (void(*)(void))krb5kdf_gettable_ctx_params }, 231 { OSSL_FUNC_KDF_GET_CTX_PARAMS, 232 (void(*)(void))krb5kdf_get_ctx_params }, 233 OSSL_DISPATCH_END 234 }; 235 236 #ifndef OPENSSL_NO_DES 237 /* 238 * DES3 is a special case, it requires a random-to-key function and its 239 * input truncated to 21 bytes of the 24 produced by the cipher. 240 * See RFC3961 6.3.1 241 */ 242 static int fixup_des3_key(unsigned char *key) 243 { 244 unsigned char *cblock; 245 int i, j; 246 247 for (i = 2; i >= 0; i--) { 248 cblock = &key[i * 8]; 249 memmove(cblock, &key[i * 7], 7); 250 cblock[7] = 0; 251 for (j = 0; j < 7; j++) 252 cblock[7] |= (cblock[j] & 1) << (j + 1); 253 DES_set_odd_parity((DES_cblock *)cblock); 254 } 255 256 /* fail if keys are such that triple des degrades to single des */ 257 if (CRYPTO_memcmp(&key[0], &key[8], 8) == 0 || 258 CRYPTO_memcmp(&key[8], &key[16], 8) == 0) { 259 return 0; 260 } 261 262 return 1; 263 } 264 #endif 265 266 /* 267 * N-fold(K) where blocksize is N, and constant_len is K 268 * Note: Here |= denotes concatenation 269 * 270 * L = lcm(N,K) 271 * R = L/K 272 * 273 * for r: 1 -> R 274 * s |= constant rot 13*(r-1)) 275 * 276 * block = 0 277 * for k: 1 -> K 278 * block += s[N(k-1)..(N-1)k] (ones'-complement addition) 279 * 280 * Optimizing for space we compute: 281 * for each l in L-1 -> 0: 282 * s[l] = (constant rot 13*(l/K))[l%k] 283 * block[l % N] += s[l] (with carry) 284 * finally add carry if any 285 */ 286 static void n_fold(unsigned char *block, unsigned int blocksize, 287 const unsigned char *constant, size_t constant_len) 288 { 289 unsigned int tmp, gcd, remainder, lcm, carry; 290 int b, l; 291 292 if (constant_len == blocksize) { 293 memcpy(block, constant, constant_len); 294 return; 295 } 296 297 /* Least Common Multiple of lengths: LCM(a,b)*/ 298 gcd = blocksize; 299 remainder = constant_len; 300 /* Calculate Great Common Divisor first GCD(a,b) */ 301 while (remainder != 0) { 302 tmp = gcd % remainder; 303 gcd = remainder; 304 remainder = tmp; 305 } 306 /* resulting a is the GCD, LCM(a,b) = |a*b|/GCD(a,b) */ 307 lcm = blocksize * constant_len / gcd; 308 309 /* now spread out the bits */ 310 memset(block, 0, blocksize); 311 312 /* last to first to be able to bring carry forward */ 313 carry = 0; 314 for (l = lcm - 1; l >= 0; l--) { 315 unsigned int rotbits, rshift, rbyte; 316 317 /* destination byte in block is l % N */ 318 b = l % blocksize; 319 /* Our virtual s buffer is R = L/K long (K = constant_len) */ 320 /* So we rotate backwards from R-1 to 0 (none) rotations */ 321 rotbits = 13 * (l / constant_len); 322 /* find the byte on s where rotbits falls onto */ 323 rbyte = l - (rotbits / 8); 324 /* calculate how much shift on that byte */ 325 rshift = rotbits & 0x07; 326 /* rbyte % constant_len gives us the unrotated byte in the 327 * constant buffer, get also the previous byte then 328 * appropriately shift them to get the rotated byte we need */ 329 tmp = (constant[(rbyte-1) % constant_len] << (8 - rshift) 330 | constant[rbyte % constant_len] >> rshift) 331 & 0xff; 332 /* add with carry to any value placed by previous passes */ 333 tmp += carry + block[b]; 334 block[b] = tmp & 0xff; 335 /* save any carry that may be left */ 336 carry = tmp >> 8; 337 } 338 339 /* if any carry is left at the end, add it through the number */ 340 for (b = blocksize - 1; b >= 0 && carry != 0; b--) { 341 carry += block[b]; 342 block[b] = carry & 0xff; 343 carry >>= 8; 344 } 345 } 346 347 static int cipher_init(EVP_CIPHER_CTX *ctx, 348 const EVP_CIPHER *cipher, ENGINE *engine, 349 const unsigned char *key, size_t key_len) 350 { 351 int klen, ret; 352 353 ret = EVP_EncryptInit_ex(ctx, cipher, engine, key, NULL); 354 if (!ret) 355 goto out; 356 /* set the key len for the odd variable key len cipher */ 357 klen = EVP_CIPHER_CTX_get_key_length(ctx); 358 if (key_len != (size_t)klen) { 359 ret = EVP_CIPHER_CTX_set_key_length(ctx, key_len); 360 if (ret <= 0) { 361 ret = 0; 362 goto out; 363 } 364 } 365 /* we never want padding, either the length requested is a multiple of 366 * the cipher block size or we are passed a cipher that can cope with 367 * partial blocks via techniques like cipher text stealing */ 368 ret = EVP_CIPHER_CTX_set_padding(ctx, 0); 369 if (!ret) 370 goto out; 371 372 out: 373 return ret; 374 } 375 376 static int KRB5KDF(const EVP_CIPHER *cipher, ENGINE *engine, 377 const unsigned char *key, size_t key_len, 378 const unsigned char *constant, size_t constant_len, 379 unsigned char *okey, size_t okey_len) 380 { 381 EVP_CIPHER_CTX *ctx = NULL; 382 unsigned char block[EVP_MAX_BLOCK_LENGTH * 2]; 383 unsigned char *plainblock, *cipherblock; 384 size_t blocksize; 385 size_t cipherlen; 386 size_t osize; 387 #ifndef OPENSSL_NO_DES 388 int des3_no_fixup = 0; 389 #endif 390 int ret; 391 392 if (key_len != okey_len) { 393 #ifndef OPENSSL_NO_DES 394 /* special case for 3des, where the caller may be requesting 395 * the random raw key, instead of the fixed up key */ 396 if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc && 397 key_len == 24 && okey_len == 21) { 398 des3_no_fixup = 1; 399 } else { 400 #endif 401 ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); 402 return 0; 403 #ifndef OPENSSL_NO_DES 404 } 405 #endif 406 } 407 408 ctx = EVP_CIPHER_CTX_new(); 409 if (ctx == NULL) 410 return 0; 411 412 ret = cipher_init(ctx, cipher, engine, key, key_len); 413 if (!ret) 414 goto out; 415 416 /* Initialize input block */ 417 blocksize = EVP_CIPHER_CTX_get_block_size(ctx); 418 419 if (blocksize == 0) { 420 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER); 421 ret = 0; 422 goto out; 423 } 424 425 if (constant_len > blocksize) { 426 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH); 427 ret = 0; 428 goto out; 429 } 430 431 n_fold(block, blocksize, constant, constant_len); 432 plainblock = block; 433 cipherblock = block + EVP_MAX_BLOCK_LENGTH; 434 435 for (osize = 0; osize < okey_len; osize += cipherlen) { 436 int olen; 437 438 ret = EVP_EncryptUpdate(ctx, cipherblock, &olen, 439 plainblock, blocksize); 440 if (!ret) 441 goto out; 442 cipherlen = olen; 443 ret = EVP_EncryptFinal_ex(ctx, cipherblock, &olen); 444 if (!ret) 445 goto out; 446 if (olen != 0) { 447 ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); 448 ret = 0; 449 goto out; 450 } 451 452 /* write cipherblock out */ 453 if (cipherlen > okey_len - osize) 454 cipherlen = okey_len - osize; 455 memcpy(okey + osize, cipherblock, cipherlen); 456 457 if (okey_len > osize + cipherlen) { 458 /* we need to reinitialize cipher context per spec */ 459 ret = EVP_CIPHER_CTX_reset(ctx); 460 if (!ret) 461 goto out; 462 ret = cipher_init(ctx, cipher, engine, key, key_len); 463 if (!ret) 464 goto out; 465 466 /* also swap block offsets so last ciphertext becomes new 467 * plaintext */ 468 plainblock = cipherblock; 469 if (cipherblock == block) { 470 cipherblock += EVP_MAX_BLOCK_LENGTH; 471 } else { 472 cipherblock = block; 473 } 474 } 475 } 476 477 #ifndef OPENSSL_NO_DES 478 if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc && !des3_no_fixup) { 479 ret = fixup_des3_key(okey); 480 if (!ret) { 481 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY); 482 goto out; 483 } 484 } 485 #endif 486 487 ret = 1; 488 489 out: 490 EVP_CIPHER_CTX_free(ctx); 491 OPENSSL_cleanse(block, EVP_MAX_BLOCK_LENGTH * 2); 492 return ret; 493 } 494 495