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