]>
Commit | Line | Data |
---|---|---|
33f54da3 | 1 | /* |
da1c088f | 2 | * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. |
33f54da3 | 3 | * |
a6ed19dc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
33f54da3 SS |
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 | ||
c6fec81b P |
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 | ||
33f54da3 SS |
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> | |
2741128e | 24 | #include <openssl/proverr.h> |
33f54da3 SS |
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" | |
2b9e4e95 | 32 | #include "prov/providercommon.h" |
33f54da3 SS |
33 | |
34 | /* KRB5 KDF defined in RFC 3961, Section 5.1 */ | |
35 | ||
363b1e5d | 36 | static OSSL_FUNC_kdf_newctx_fn krb5kdf_new; |
4c1a841c | 37 | static OSSL_FUNC_kdf_dupctx_fn krb5kdf_dup; |
363b1e5d DMSP |
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; | |
33f54da3 SS |
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 | ||
2b9e4e95 P |
64 | if (!ossl_prov_is_running()) |
65 | return NULL; | |
66 | ||
e077455e | 67 | if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) |
5764c352 | 68 | return NULL; |
33f54da3 SS |
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 | ||
3c659415 P |
77 | if (ctx != NULL) { |
78 | krb5kdf_reset(ctx); | |
79 | OPENSSL_free(ctx); | |
80 | } | |
33f54da3 SS |
81 | } |
82 | ||
83 | static void krb5kdf_reset(void *vctx) | |
84 | { | |
85 | KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; | |
0577959c | 86 | void *provctx = ctx->provctx; |
33f54da3 SS |
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)); | |
0577959c | 92 | ctx->provctx = provctx; |
33f54da3 SS |
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; | |
d2217c88 | 100 | *dst_len = 0; |
33f54da3 SS |
101 | return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len); |
102 | } | |
103 | ||
4c1a841c P |
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 | ||
3469b388 P |
125 | static int krb5kdf_derive(void *vctx, unsigned char *key, size_t keylen, |
126 | const OSSL_PARAM params[]) | |
33f54da3 SS |
127 | { |
128 | KRB5KDF_CTX *ctx = (KRB5KDF_CTX *)vctx; | |
2b9e4e95 P |
129 | const EVP_CIPHER *cipher; |
130 | ENGINE *engine; | |
131 | ||
3469b388 | 132 | if (!ossl_prov_is_running() || !krb5kdf_set_ctx_params(ctx, params)) |
2b9e4e95 | 133 | return 0; |
33f54da3 | 134 | |
2b9e4e95 | 135 | cipher = ossl_prov_cipher_cipher(&ctx->cipher); |
33f54da3 SS |
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 | } | |
2b9e4e95 | 148 | engine = ossl_prov_cipher_engine(&ctx->cipher); |
33f54da3 SS |
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; | |
a829b735 | 158 | OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx); |
33f54da3 | 159 | |
c983a0e5 P |
160 | if (params == NULL) |
161 | return 1; | |
162 | ||
33f54da3 SS |
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 | ||
1e8e5c60 P |
178 | static const OSSL_PARAM *krb5kdf_settable_ctx_params(ossl_unused void *ctx, |
179 | ossl_unused void *provctx) | |
33f54da3 SS |
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) | |
ed576acd | 200 | len = EVP_CIPHER_get_key_length(cipher); |
33f54da3 SS |
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 | ||
1e8e5c60 P |
209 | static const OSSL_PARAM *krb5kdf_gettable_ctx_params(ossl_unused void *ctx, |
210 | ossl_unused void *provctx) | |
33f54da3 SS |
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 | ||
1be63951 | 219 | const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[] = { |
33f54da3 | 220 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))krb5kdf_new }, |
4c1a841c | 221 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))krb5kdf_dup }, |
33f54da3 SS |
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 }, | |
1e6bd31e | 233 | OSSL_DISPATCH_END |
33f54da3 SS |
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] (one's 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 */ | |
ed576acd | 357 | klen = EVP_CIPHER_CTX_get_key_length(ctx); |
33f54da3 SS |
358 | if (key_len != (size_t)klen) { |
359 | ret = EVP_CIPHER_CTX_set_key_length(ctx, key_len); | |
8d9fec17 PH |
360 | if (ret <= 0) { |
361 | ret = 0; | |
33f54da3 | 362 | goto out; |
8d9fec17 | 363 | } |
33f54da3 SS |
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; | |
74a5808b | 387 | #ifndef OPENSSL_NO_DES |
33f54da3 | 388 | int des3_no_fixup = 0; |
74a5808b | 389 | #endif |
33f54da3 SS |
390 | int ret; |
391 | ||
392 | if (key_len != okey_len) { | |
74a5808b | 393 | #ifndef OPENSSL_NO_DES |
33f54da3 SS |
394 | /* special case for 3des, where the caller may be requesting |
395 | * the random raw key, instead of the fixed up key */ | |
ed576acd | 396 | if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc && |
33f54da3 SS |
397 | key_len == 24 && okey_len == 21) { |
398 | des3_no_fixup = 1; | |
399 | } else { | |
74a5808b | 400 | #endif |
33f54da3 SS |
401 | ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); |
402 | return 0; | |
74a5808b | 403 | #ifndef OPENSSL_NO_DES |
33f54da3 | 404 | } |
74a5808b | 405 | #endif |
33f54da3 SS |
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 */ | |
ed576acd | 417 | blocksize = EVP_CIPHER_CTX_get_block_size(ctx); |
33f54da3 SS |
418 | |
419 | if (constant_len > blocksize) { | |
420 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONSTANT_LENGTH); | |
421 | ret = 0; | |
422 | goto out; | |
423 | } | |
424 | ||
425 | n_fold(block, blocksize, constant, constant_len); | |
426 | plainblock = block; | |
427 | cipherblock = block + EVP_MAX_BLOCK_LENGTH; | |
428 | ||
429 | for (osize = 0; osize < okey_len; osize += cipherlen) { | |
430 | int olen; | |
431 | ||
432 | ret = EVP_EncryptUpdate(ctx, cipherblock, &olen, | |
433 | plainblock, blocksize); | |
434 | if (!ret) | |
435 | goto out; | |
436 | cipherlen = olen; | |
437 | ret = EVP_EncryptFinal_ex(ctx, cipherblock, &olen); | |
438 | if (!ret) | |
439 | goto out; | |
440 | if (olen != 0) { | |
441 | ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); | |
442 | ret = 0; | |
443 | goto out; | |
444 | } | |
445 | ||
446 | /* write cipherblock out */ | |
447 | if (cipherlen > okey_len - osize) | |
448 | cipherlen = okey_len - osize; | |
449 | memcpy(okey + osize, cipherblock, cipherlen); | |
450 | ||
451 | if (okey_len > osize + cipherlen) { | |
452 | /* we need to reinitialize cipher context per spec */ | |
453 | ret = EVP_CIPHER_CTX_reset(ctx); | |
454 | if (!ret) | |
455 | goto out; | |
456 | ret = cipher_init(ctx, cipher, engine, key, key_len); | |
457 | if (!ret) | |
458 | goto out; | |
459 | ||
460 | /* also swap block offsets so last ciphertext becomes new | |
461 | * plaintext */ | |
462 | plainblock = cipherblock; | |
463 | if (cipherblock == block) { | |
464 | cipherblock += EVP_MAX_BLOCK_LENGTH; | |
465 | } else { | |
466 | cipherblock = block; | |
467 | } | |
468 | } | |
469 | } | |
470 | ||
471 | #ifndef OPENSSL_NO_DES | |
ed576acd | 472 | if (EVP_CIPHER_get_nid(cipher) == NID_des_ede3_cbc && !des3_no_fixup) { |
33f54da3 SS |
473 | ret = fixup_des3_key(okey); |
474 | if (!ret) { | |
475 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY); | |
476 | goto out; | |
477 | } | |
478 | } | |
479 | #endif | |
480 | ||
481 | ret = 1; | |
482 | ||
483 | out: | |
484 | EVP_CIPHER_CTX_free(ctx); | |
485 | OPENSSL_cleanse(block, EVP_MAX_BLOCK_LENGTH * 2); | |
486 | return ret; | |
487 | } | |
488 |