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