/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- krb5_DES_random_key
- krb5_DES_schedule_old
- krb5_DES_AFS3_CMU_string_to_key
- krb5_DES_AFS3_Transarc_string_to_key
- DES_AFS3_string_to_key
- DES_string_to_key_int
- krb5_DES_string_to_key
- krb5_DES_random_to_key
- DES3_random_key
- xor
- DES3_string_to_key
- DES3_string_to_key_derived
- DES3_random_to_key
- ARCFOUR_schedule
- ARCFOUR_string_to_key
- AES_string_to_key
- evp_schedule
- evp_cleanup
- krb5_salttype_to_string
- krb5_string_to_salttype
- krb5_get_pw_salt
- krb5_free_salt
- krb5_string_to_key_data
- krb5_string_to_key
- krb5_string_to_key_data_salt
- krb5_string_to_key_data_salt_opaque
- krb5_string_to_key_salt
- krb5_string_to_key_salt_opaque
- krb5_enctype_keysize
- krb5_enctype_keybits
- krb5_generate_random_keyblock
- _key_schedule
- NONE_checksum
- CRC32_checksum
- RSA_MD4_checksum
- des_checksum
- des_verify
- RSA_MD4_DES_checksum
- RSA_MD4_DES_verify
- RSA_MD5_checksum
- RSA_MD5_DES_checksum
- RSA_MD5_DES_verify
- RSA_MD5_DES3_checksum
- RSA_MD5_DES3_verify
- SHA1_checksum
- hmac
- krb5_hmac
- SP_HMAC_SHA1_checksum
- HMAC_MD5_checksum
- _find_checksum
- get_checksum_key
- create_checksum
- arcfour_checksum_p
- krb5_create_checksum
- verify_checksum
- krb5_verify_checksum
- krb5_crypto_get_checksum_type
- krb5_checksumsize
- krb5_checksum_is_keyed
- krb5_checksum_is_collision_proof
- krb5_checksum_disable
- NULL_encrypt
- evp_encrypt
- evp_des_encrypt_null_ivec
- evp_des_encrypt_key_ivec
- DES_CFB64_encrypt_null_ivec
- DES_PCBC_encrypt_key_ivec
- ARCFOUR_subencrypt
- ARCFOUR_subdecrypt
- usage2arcfour
- ARCFOUR_encrypt
- AES_PRF
- _find_enctype
- krb5_enctype_to_string
- krb5_string_to_enctype
- krb5_enctype_to_keytype
- krb5_enctype_valid
- krb5_cksumtype_to_enctype
- krb5_cksumtype_valid
- krb5_enctypes_compatible_keys
- derived_crypto
- special_crypto
- encrypt_internal_derived
- encrypt_internal
- encrypt_internal_special
- decrypt_internal_derived
- decrypt_internal
- decrypt_internal_special
- find_iv
- krb5_encrypt_iov_ivec
- krb5_decrypt_iov_ivec
- krb5_create_checksum_iov
- krb5_crypto_length
- krb5_encrypt_ivec
- krb5_encrypt
- krb5_encrypt_EncryptedData
- krb5_decrypt_ivec
- krb5_decrypt
- krb5_decrypt_EncryptedData
- seed_something
- krb5_generate_random_block
- DES3_postproc
- derive_key
- _new_derived_key
- krb5_derive_key
- _get_derived_key
- krb5_crypto_init
- free_key_data
- free_key_usage
- krb5_crypto_destroy
- krb5_crypto_getblocksize
- krb5_crypto_getenctype
- krb5_crypto_getpadsize
- krb5_crypto_getconfoundersize
- krb5_enctype_disable
- krb5_enctype_enable
- krb5_string_to_key_derived
- wrapped_length
- wrapped_length_dervied
- krb5_get_wrapped_length
- crypto_overhead
- crypto_overhead_dervied
- krb5_crypto_overhead
- krb5_random_to_key
- _krb5_pk_octetstring2key
- encode_uvinfo
- encode_otherinfo
- _krb5_pk_kdf
- krb5_crypto_prf_length
- krb5_crypto_prf
- _find_keytype
- krb5_keytype_to_enctypes_default
- krb5_keytype_to_string
- krb5_string_to_keytype
- krb5_keytype_to_enctypes
1 /*
2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "krb5_locl.h"
35 RCSID("$Id$");
36 #include <pkinit_asn1.h>
37
38 #undef __attribute__
39 #define __attribute__(X)
40
41 #define WEAK_ENCTYPES 1
42
43 #ifndef HEIMDAL_SMALLER
44 #define DES3_OLD_ENCTYPE 1
45 #endif
46
47
48 #ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
49 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void);
50 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void);
51 #define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
52 #define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
53 #endif
54
55 struct key_data {
56 krb5_keyblock *key;
57 krb5_data *schedule;
58 };
59
60 struct key_usage {
61 unsigned usage;
62 struct key_data key;
63 };
64
65 struct krb5_crypto_data {
66 struct encryption_type *et;
67 struct key_data key;
68 int num_key_usage;
69 struct key_usage *key_usage;
70 };
71
72 #define CRYPTO_ETYPE(C) ((C)->et->type)
73
74 /* bits for `flags' below */
75 #define F_KEYED 1 /* checksum is keyed */
76 #define F_CPROOF 2 /* checksum is collision proof */
77 #define F_DERIVED 4 /* uses derived keys */
78 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
79 #define F_PSEUDO 16 /* not a real protocol type */
80 #define F_SPECIAL 32 /* backwards */
81 #define F_DISABLED 64 /* enctype/checksum disabled */
82
83 struct salt_type {
84 krb5_salttype type;
85 const char *name;
86 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
87 krb5_salt, krb5_data, krb5_keyblock*);
88 };
89
90 struct key_type {
91 krb5_keytype type; /* XXX */
92 const char *name;
93 size_t bits;
94 size_t size;
95 size_t schedule_size;
96 void (*random_key)(krb5_context, krb5_keyblock*);
97 void (*schedule)(krb5_context, struct key_type *, struct key_data *);
98 struct salt_type *string_to_key;
99 void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
100 void (*cleanup)(krb5_context, struct key_data *);
101 const EVP_CIPHER *(*evp)(void);
102 };
103
104 struct checksum_type {
105 krb5_cksumtype type;
106 const char *name;
107 size_t blocksize;
108 size_t checksumsize;
109 unsigned flags;
110 krb5_enctype (*checksum)(krb5_context context,
111 struct key_data *key,
112 const void *buf, size_t len,
113 unsigned usage,
114 Checksum *csum);
115 krb5_error_code (*verify)(krb5_context context,
116 struct key_data *key,
117 const void *buf, size_t len,
118 unsigned usage,
119 Checksum *csum);
120 };
121
122 struct encryption_type {
123 krb5_enctype type;
124 const char *name;
125 size_t blocksize;
126 size_t padsize;
127 size_t confoundersize;
128 struct key_type *keytype;
129 struct checksum_type *checksum;
130 struct checksum_type *keyed_checksum;
131 unsigned flags;
132 krb5_error_code (*encrypt)(krb5_context context,
133 struct key_data *key,
134 void *data, size_t len,
135 krb5_boolean encryptp,
136 int usage,
137 void *ivec);
138 size_t prf_length;
139 krb5_error_code (*prf)(krb5_context,
140 krb5_crypto, const krb5_data *, krb5_data *);
141 };
142
143 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
144 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
145 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
146
147 static struct checksum_type *_find_checksum(krb5_cksumtype type);
148 static struct encryption_type *_find_enctype(krb5_enctype type);
149 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
150 unsigned, struct key_data**);
151 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
152 static krb5_error_code derive_key(krb5_context context,
153 struct encryption_type *et,
154 struct key_data *key,
155 const void *constant,
156 size_t len);
157 static krb5_error_code hmac(krb5_context context,
158 struct checksum_type *cm,
159 const void *data,
160 size_t len,
161 unsigned usage,
162 struct key_data *keyblock,
163 Checksum *result);
164 static void free_key_data(krb5_context,
165 struct key_data *,
166 struct encryption_type *);
167 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
168 static void xor (DES_cblock *, const unsigned char *);
169
170 /************************************************************
171 * *
172 ************************************************************/
173
174 struct evp_schedule {
175 EVP_CIPHER_CTX ectx;
176 EVP_CIPHER_CTX dctx;
177 };
178
179
180 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
181
182 #ifdef WEAK_ENCTYPES
183 static void
184 krb5_DES_random_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
185 krb5_keyblock *key)
186 {
187 DES_cblock *k = key->keyvalue.data;
188 do {
189 krb5_generate_random_block(k, sizeof(DES_cblock));
190 DES_set_odd_parity(k);
191 } while(DES_is_weak_key(k));
192 }
193
194 static void
195 krb5_DES_schedule_old(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
196 struct key_type *kt,
197 struct key_data *key)
198 {
199 DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
200 }
201
202 #ifdef ENABLE_AFS_STRING_TO_KEY
203
204 /* This defines the Andrew string_to_key function. It accepts a password
205 * string as input and converts it via a one-way encryption algorithm to a DES
206 * encryption key. It is compatible with the original Andrew authentication
207 * service password database.
208 */
209
210 /*
211 * Short passwords, i.e 8 characters or less.
212 */
213 static void
214 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
/* [<][>][^][v][top][bottom][index][help] */
215 krb5_data cell,
216 DES_cblock *key)
217 {
218 char password[8+1]; /* crypt is limited to 8 chars anyway */
219 int i;
220
221 for(i = 0; i < 8; i++) {
222 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
223 ((i < cell.length) ?
224 tolower(((unsigned char*)cell.data)[i]) : 0);
225 password[i] = c ? c : 'X';
226 }
227 password[8] = '\0';
228
229 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
230
231 /* parity is inserted into the LSB so left shift each byte up one
232 bit. This allows ascii characters with a zero MSB to retain as
233 much significance as possible. */
234 for (i = 0; i < sizeof(DES_cblock); i++)
235 ((unsigned char*)key)[i] <<= 1;
236 DES_set_odd_parity (key);
237 }
238
239 /*
240 * Long passwords, i.e 9 characters or more.
241 */
242 static void
243 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
/* [<][>][^][v][top][bottom][index][help] */
244 krb5_data cell,
245 DES_cblock *key)
246 {
247 DES_key_schedule schedule;
248 DES_cblock temp_key;
249 DES_cblock ivec;
250 char password[512];
251 size_t passlen;
252
253 memcpy(password, pw.data, min(pw.length, sizeof(password)));
254 if(pw.length < sizeof(password)) {
255 int len = min(cell.length, sizeof(password) - pw.length);
256 int i;
257
258 memcpy(password + pw.length, cell.data, len);
259 for (i = pw.length; i < pw.length + len; ++i)
260 password[i] = tolower((unsigned char)password[i]);
261 }
262 passlen = min(sizeof(password), pw.length + cell.length);
263 memcpy(&ivec, "kerberos", 8);
264 memcpy(&temp_key, "kerberos", 8);
265 DES_set_odd_parity (&temp_key);
266 DES_set_key_unchecked (&temp_key, &schedule);
267 DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
268
269 memcpy(&temp_key, &ivec, 8);
270 DES_set_odd_parity (&temp_key);
271 DES_set_key_unchecked (&temp_key, &schedule);
272 DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
273 memset(&schedule, 0, sizeof(schedule));
274 memset(&temp_key, 0, sizeof(temp_key));
275 memset(&ivec, 0, sizeof(ivec));
276 memset(password, 0, sizeof(password));
277
278 DES_set_odd_parity (key);
279 }
280
281 static krb5_error_code
282 DES_AFS3_string_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
283 krb5_enctype enctype,
284 krb5_data password,
285 krb5_salt salt,
286 krb5_data opaque,
287 krb5_keyblock *key)
288 {
289 DES_cblock tmp;
290 if(password.length > 8)
291 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
292 else
293 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
294 key->keytype = enctype;
295 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
296 memset(&key, 0, sizeof(key));
297 return 0;
298 }
299 #endif /* ENABLE_AFS_STRING_TO_KEY */
300
301 static void
302 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
/* [<][>][^][v][top][bottom][index][help] */
303 {
304 DES_key_schedule schedule;
305 int i;
306 int reverse = 0;
307 unsigned char *p;
308
309 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
310 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
311 memset(key, 0, 8);
312
313 p = (unsigned char*)key;
314 for (i = 0; i < length; i++) {
315 unsigned char tmp = data[i];
316 if (!reverse)
317 *p++ ^= (tmp << 1);
318 else
319 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
320 if((i % 8) == 7)
321 reverse = !reverse;
322 }
323 DES_set_odd_parity(key);
324 if(DES_is_weak_key(key))
325 (*key)[7] ^= 0xF0;
326 DES_set_key_unchecked(key, &schedule);
327 DES_cbc_cksum((void*)data, key, length, &schedule, key);
328 memset(&schedule, 0, sizeof(schedule));
329 DES_set_odd_parity(key);
330 if(DES_is_weak_key(key))
331 (*key)[7] ^= 0xF0;
332 }
333
334 static krb5_error_code
335 krb5_DES_string_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
336 krb5_enctype enctype,
337 krb5_data password,
338 krb5_salt salt,
339 krb5_data opaque,
340 krb5_keyblock *key)
341 {
342 unsigned char *s;
343 size_t len;
344 DES_cblock tmp;
345
346 #ifdef ENABLE_AFS_STRING_TO_KEY
347 if (opaque.length == 1) {
348 unsigned long v;
349 _krb5_get_int(opaque.data, &v, 1);
350 if (v == 1)
351 return DES_AFS3_string_to_key(context, enctype, password,
352 salt, opaque, key);
353 }
354 #endif
355
356 len = password.length + salt.saltvalue.length;
357 s = malloc(len);
358 if(len > 0 && s == NULL) {
359 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
360 return ENOMEM;
361 }
362 memcpy(s, password.data, password.length);
363 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
364 DES_string_to_key_int(s, len, &tmp);
365 key->keytype = enctype;
366 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
367 memset(&tmp, 0, sizeof(tmp));
368 memset(s, 0, len);
369 free(s);
370 return 0;
371 }
372
373 static void
374 krb5_DES_random_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
375 krb5_keyblock *key,
376 const void *data,
377 size_t size)
378 {
379 DES_cblock *k = key->keyvalue.data;
380 memcpy(k, data, key->keyvalue.length);
381 DES_set_odd_parity(k);
382 if(DES_is_weak_key(k))
383 xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
384 }
385 #endif
386
387 /*
388 *
389 */
390
391 static void
392 DES3_random_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
393 krb5_keyblock *key)
394 {
395 DES_cblock *k = key->keyvalue.data;
396 do {
397 krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
398 DES_set_odd_parity(&k[0]);
399 DES_set_odd_parity(&k[1]);
400 DES_set_odd_parity(&k[2]);
401 } while(DES_is_weak_key(&k[0]) ||
402 DES_is_weak_key(&k[1]) ||
403 DES_is_weak_key(&k[2]));
404 }
405
406 /*
407 * A = A xor B. A & B are 8 bytes.
408 */
409
410 static void
411 xor (DES_cblock *key, const unsigned char *b)
/* [<][>][^][v][top][bottom][index][help] */
412 {
413 unsigned char *a = (unsigned char*)key;
414 a[0] ^= b[0];
415 a[1] ^= b[1];
416 a[2] ^= b[2];
417 a[3] ^= b[3];
418 a[4] ^= b[4];
419 a[5] ^= b[5];
420 a[6] ^= b[6];
421 a[7] ^= b[7];
422 }
423
424 #ifdef DES3_OLD_ENCTYPE
425 static krb5_error_code
426 DES3_string_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
427 krb5_enctype enctype,
428 krb5_data password,
429 krb5_salt salt,
430 krb5_data opaque,
431 krb5_keyblock *key)
432 {
433 char *str;
434 size_t len;
435 unsigned char tmp[24];
436 DES_cblock keys[3];
437 krb5_error_code ret;
438
439 len = password.length + salt.saltvalue.length;
440 str = malloc(len);
441 if(len != 0 && str == NULL) {
442 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
443 return ENOMEM;
444 }
445 memcpy(str, password.data, password.length);
446 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
447 {
448 DES_cblock ivec;
449 DES_key_schedule s[3];
450 int i;
451
452 ret = _krb5_n_fold(str, len, tmp, 24);
453 if (ret) {
454 memset(str, 0, len);
455 free(str);
456 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
457 return ret;
458 }
459
460 for(i = 0; i < 3; i++){
461 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
462 DES_set_odd_parity(keys + i);
463 if(DES_is_weak_key(keys + i))
464 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
465 DES_set_key_unchecked(keys + i, &s[i]);
466 }
467 memset(&ivec, 0, sizeof(ivec));
468 DES_ede3_cbc_encrypt(tmp,
469 tmp, sizeof(tmp),
470 &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
471 memset(s, 0, sizeof(s));
472 memset(&ivec, 0, sizeof(ivec));
473 for(i = 0; i < 3; i++){
474 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
475 DES_set_odd_parity(keys + i);
476 if(DES_is_weak_key(keys + i))
477 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
478 }
479 memset(tmp, 0, sizeof(tmp));
480 }
481 key->keytype = enctype;
482 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
483 memset(keys, 0, sizeof(keys));
484 memset(str, 0, len);
485 free(str);
486 return 0;
487 }
488 #endif
489
490 static krb5_error_code
491 DES3_string_to_key_derived(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
492 krb5_enctype enctype,
493 krb5_data password,
494 krb5_salt salt,
495 krb5_data opaque,
496 krb5_keyblock *key)
497 {
498 krb5_error_code ret;
499 size_t len = password.length + salt.saltvalue.length;
500 char *s;
501
502 s = malloc(len);
503 if(len != 0 && s == NULL) {
504 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
505 return ENOMEM;
506 }
507 memcpy(s, password.data, password.length);
508 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
509 ret = krb5_string_to_key_derived(context,
510 s,
511 len,
512 enctype,
513 key);
514 memset(s, 0, len);
515 free(s);
516 return ret;
517 }
518
519 static void
520 DES3_random_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
521 krb5_keyblock *key,
522 const void *data,
523 size_t size)
524 {
525 unsigned char *x = key->keyvalue.data;
526 const u_char *q = data;
527 DES_cblock *k;
528 int i, j;
529
530 memset(x, 0, sizeof(x));
531 for (i = 0; i < 3; ++i) {
532 unsigned char foo;
533 for (j = 0; j < 7; ++j) {
534 unsigned char b = q[7 * i + j];
535
536 x[8 * i + j] = b;
537 }
538 foo = 0;
539 for (j = 6; j >= 0; --j) {
540 foo |= q[7 * i + j] & 1;
541 foo <<= 1;
542 }
543 x[8 * i + 7] = foo;
544 }
545 k = key->keyvalue.data;
546 for (i = 0; i < 3; i++) {
547 DES_set_odd_parity(&k[i]);
548 if(DES_is_weak_key(&k[i]))
549 xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
550 }
551 }
552
553 /*
554 * ARCFOUR
555 */
556
557 static void
558 ARCFOUR_schedule(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
559 struct key_type *kt,
560 struct key_data *kd)
561 {
562 RC4_set_key (kd->schedule->data,
563 kd->key->keyvalue.length, kd->key->keyvalue.data);
564 }
565
566 static krb5_error_code
567 ARCFOUR_string_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
568 krb5_enctype enctype,
569 krb5_data password,
570 krb5_salt salt,
571 krb5_data opaque,
572 krb5_keyblock *key)
573 {
574 krb5_error_code ret;
575 uint16_t *s = NULL;
576 size_t len, i;
577 EVP_MD_CTX *m;
578
579 m = EVP_MD_CTX_create();
580 if (m == NULL) {
581 ret = ENOMEM;
582 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
583 goto out;
584 }
585
586 EVP_DigestInit_ex(m, EVP_md4(), NULL);
587
588 ret = wind_utf8ucs2_length(password.data, &len);
589 if (ret) {
590 krb5_set_error_message (context, ret,
591 N_("Password not an UCS2 string", ""));
592 goto out;
593 }
594
595 s = malloc (len * sizeof(s[0]));
596 if (len != 0 && s == NULL) {
597 krb5_set_error_message (context, ENOMEM,
598 N_("malloc: out of memory", ""));
599 ret = ENOMEM;
600 goto out;
601 }
602
603 ret = wind_utf8ucs2(password.data, s, &len);
604 if (ret) {
605 krb5_set_error_message (context, ret,
606 N_("Password not an UCS2 string", ""));
607 goto out;
608 }
609
610 /* LE encoding */
611 for (i = 0; i < len; i++) {
612 unsigned char p;
613 p = (s[i] & 0xff);
614 EVP_DigestUpdate (m, &p, 1);
615 p = (s[i] >> 8) & 0xff;
616 EVP_DigestUpdate (m, &p, 1);
617 }
618
619 key->keytype = enctype;
620 ret = krb5_data_alloc (&key->keyvalue, 16);
621 if (ret) {
622 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
623 goto out;
624 }
625 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
626
627 out:
628 EVP_MD_CTX_destroy(m);
629 if (s)
630 memset (s, 0, len);
631 free (s);
632 return ret;
633 }
634
635 /*
636 * AES
637 */
638
639 int _krb5_AES_string_to_default_iterator = 4096;
640
641 static krb5_error_code
642 AES_string_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
643 krb5_enctype enctype,
644 krb5_data password,
645 krb5_salt salt,
646 krb5_data opaque,
647 krb5_keyblock *key)
648 {
649 krb5_error_code ret;
650 uint32_t iter;
651 struct encryption_type *et;
652 struct key_data kd;
653
654 if (opaque.length == 0)
655 iter = _krb5_AES_string_to_default_iterator;
656 else if (opaque.length == 4) {
657 unsigned long v;
658 _krb5_get_int(opaque.data, &v, 4);
659 iter = ((uint32_t)v);
660 } else
661 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
662
663 et = _find_enctype(enctype);
664 if (et == NULL)
665 return KRB5_PROG_KEYTYPE_NOSUPP;
666
667 kd.schedule = NULL;
668 ALLOC(kd.key, 1);
669 if(kd.key == NULL) {
670 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
671 return ENOMEM;
672 }
673 kd.key->keytype = enctype;
674 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
675 if (ret) {
676 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
677 return ret;
678 }
679
680 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
681 salt.saltvalue.data, salt.saltvalue.length,
682 iter,
683 et->keytype->size, kd.key->keyvalue.data);
684 if (ret != 1) {
685 free_key_data(context, &kd, et);
686 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
687 "Error calculating s2k");
688 return KRB5_PROG_KEYTYPE_NOSUPP;
689 }
690
691 ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
692 if (ret == 0)
693 ret = krb5_copy_keyblock_contents(context, kd.key, key);
694 free_key_data(context, &kd, et);
695
696 return ret;
697 }
698
699 static void
700 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
/* [<][>][^][v][top][bottom][index][help] */
701 {
702 struct evp_schedule *key = kd->schedule->data;
703 const EVP_CIPHER *c = (*kt->evp)();
704
705 EVP_CIPHER_CTX_init(&key->ectx);
706 EVP_CIPHER_CTX_init(&key->dctx);
707
708 EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
709 EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
710 }
711
712 static void
713 evp_cleanup(krb5_context context, struct key_data *kd)
/* [<][>][^][v][top][bottom][index][help] */
714 {
715 struct evp_schedule *key = kd->schedule->data;
716 EVP_CIPHER_CTX_cleanup(&key->ectx);
717 EVP_CIPHER_CTX_cleanup(&key->dctx);
718 }
719
720 /*
721 *
722 */
723
724 #ifdef WEAK_ENCTYPES
725 static struct salt_type des_salt[] = {
726 {
727 KRB5_PW_SALT,
728 "pw-salt",
729 krb5_DES_string_to_key
730 },
731 #ifdef ENABLE_AFS_STRING_TO_KEY
732 {
733 KRB5_AFS3_SALT,
734 "afs3-salt",
735 DES_AFS3_string_to_key
736 },
737 #endif
738 { 0 }
739 };
740 #endif
741
742 #ifdef DES3_OLD_ENCTYPE
743 static struct salt_type des3_salt[] = {
744 {
745 KRB5_PW_SALT,
746 "pw-salt",
747 DES3_string_to_key
748 },
749 { 0 }
750 };
751 #endif
752
753 static struct salt_type des3_salt_derived[] = {
754 {
755 KRB5_PW_SALT,
756 "pw-salt",
757 DES3_string_to_key_derived
758 },
759 { 0 }
760 };
761
762 static struct salt_type AES_salt[] = {
763 {
764 KRB5_PW_SALT,
765 "pw-salt",
766 AES_string_to_key
767 },
768 { 0 }
769 };
770
771 static struct salt_type arcfour_salt[] = {
772 {
773 KRB5_PW_SALT,
774 "pw-salt",
775 ARCFOUR_string_to_key
776 },
777 { 0 }
778 };
779
780 /*
781 *
782 */
783
784 static struct key_type keytype_null = {
785 KEYTYPE_NULL,
786 "null",
787 0,
788 0,
789 0,
790 NULL,
791 NULL,
792 NULL
793 };
794
795 #ifdef WEAK_ENCTYPES
796 static struct key_type keytype_des_old = {
797 KEYTYPE_DES,
798 "des-old",
799 56,
800 8,
801 sizeof(DES_key_schedule),
802 krb5_DES_random_key,
803 krb5_DES_schedule_old,
804 des_salt,
805 krb5_DES_random_to_key
806 };
807
808 static struct key_type keytype_des = {
809 KEYTYPE_DES,
810 "des",
811 56,
812 8,
813 sizeof(struct evp_schedule),
814 krb5_DES_random_key,
815 evp_schedule,
816 des_salt,
817 krb5_DES_random_to_key,
818 evp_cleanup,
819 EVP_des_cbc
820 };
821 #endif /* WEAK_ENCTYPES */
822
823 #ifdef DES3_OLD_ENCTYPE
824 static struct key_type keytype_des3 = {
825 KEYTYPE_DES3,
826 "des3",
827 168,
828 24,
829 sizeof(struct evp_schedule),
830 DES3_random_key,
831 evp_schedule,
832 des3_salt,
833 DES3_random_to_key,
834 evp_cleanup,
835 EVP_des_ede3_cbc
836 };
837 #endif
838
839 static struct key_type keytype_des3_derived = {
840 KEYTYPE_DES3,
841 "des3",
842 168,
843 24,
844 sizeof(struct evp_schedule),
845 DES3_random_key,
846 evp_schedule,
847 des3_salt_derived,
848 DES3_random_to_key,
849 evp_cleanup,
850 EVP_des_ede3_cbc
851 };
852
853 static struct key_type keytype_aes128 = {
854 KEYTYPE_AES128,
855 "aes-128",
856 128,
857 16,
858 sizeof(struct evp_schedule),
859 NULL,
860 evp_schedule,
861 AES_salt,
862 NULL,
863 evp_cleanup,
864 EVP_hcrypto_aes_128_cts
865 };
866
867 static struct key_type keytype_aes256 = {
868 KEYTYPE_AES256,
869 "aes-256",
870 256,
871 32,
872 sizeof(struct evp_schedule),
873 NULL,
874 evp_schedule,
875 AES_salt,
876 NULL,
877 evp_cleanup,
878 EVP_hcrypto_aes_256_cts
879 };
880
881 static struct key_type keytype_arcfour = {
882 KEYTYPE_ARCFOUR,
883 "arcfour",
884 128,
885 16,
886 sizeof(RC4_KEY),
887 NULL,
888 ARCFOUR_schedule,
889 arcfour_salt
890 };
891
892 krb5_error_code KRB5_LIB_FUNCTION
893 krb5_salttype_to_string (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
894 krb5_enctype etype,
895 krb5_salttype stype,
896 char **string)
897 {
898 struct encryption_type *e;
899 struct salt_type *st;
900
901 e = _find_enctype (etype);
902 if (e == NULL) {
903 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
904 "encryption type %d not supported",
905 etype);
906 return KRB5_PROG_ETYPE_NOSUPP;
907 }
908 for (st = e->keytype->string_to_key; st && st->type; st++) {
909 if (st->type == stype) {
910 *string = strdup (st->name);
911 if (*string == NULL) {
912 krb5_set_error_message (context, ENOMEM,
913 N_("malloc: out of memory", ""));
914 return ENOMEM;
915 }
916 return 0;
917 }
918 }
919 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
920 "salttype %d not supported", stype);
921 return HEIM_ERR_SALTTYPE_NOSUPP;
922 }
923
924 krb5_error_code KRB5_LIB_FUNCTION
925 krb5_string_to_salttype (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
926 krb5_enctype etype,
927 const char *string,
928 krb5_salttype *salttype)
929 {
930 struct encryption_type *e;
931 struct salt_type *st;
932
933 e = _find_enctype (etype);
934 if (e == NULL) {
935 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
936 N_("encryption type %d not supported", ""),
937 etype);
938 return KRB5_PROG_ETYPE_NOSUPP;
939 }
940 for (st = e->keytype->string_to_key; st && st->type; st++) {
941 if (strcasecmp (st->name, string) == 0) {
942 *salttype = st->type;
943 return 0;
944 }
945 }
946 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
947 N_("salttype %s not supported", ""), string);
948 return HEIM_ERR_SALTTYPE_NOSUPP;
949 }
950
951 krb5_error_code KRB5_LIB_FUNCTION
952 krb5_get_pw_salt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
953 krb5_const_principal principal,
954 krb5_salt *salt)
955 {
956 size_t len;
957 int i;
958 krb5_error_code ret;
959 char *p;
960
961 salt->salttype = KRB5_PW_SALT;
962 len = strlen(principal->realm);
963 for (i = 0; i < principal->name.name_string.len; ++i)
964 len += strlen(principal->name.name_string.val[i]);
965 ret = krb5_data_alloc (&salt->saltvalue, len);
966 if (ret)
967 return ret;
968 p = salt->saltvalue.data;
969 memcpy (p, principal->realm, strlen(principal->realm));
970 p += strlen(principal->realm);
971 for (i = 0; i < principal->name.name_string.len; ++i) {
972 memcpy (p,
973 principal->name.name_string.val[i],
974 strlen(principal->name.name_string.val[i]));
975 p += strlen(principal->name.name_string.val[i]);
976 }
977 return 0;
978 }
979
980 krb5_error_code KRB5_LIB_FUNCTION
981 krb5_free_salt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
982 krb5_salt salt)
983 {
984 krb5_data_free(&salt.saltvalue);
985 return 0;
986 }
987
988 krb5_error_code KRB5_LIB_FUNCTION
989 krb5_string_to_key_data (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
990 krb5_enctype enctype,
991 krb5_data password,
992 krb5_principal principal,
993 krb5_keyblock *key)
994 {
995 krb5_error_code ret;
996 krb5_salt salt;
997
998 ret = krb5_get_pw_salt(context, principal, &salt);
999 if(ret)
1000 return ret;
1001 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
1002 krb5_free_salt(context, salt);
1003 return ret;
1004 }
1005
1006 krb5_error_code KRB5_LIB_FUNCTION
1007 krb5_string_to_key (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1008 krb5_enctype enctype,
1009 const char *password,
1010 krb5_principal principal,
1011 krb5_keyblock *key)
1012 {
1013 krb5_data pw;
1014 pw.data = rk_UNCONST(password);
1015 pw.length = strlen(password);
1016 return krb5_string_to_key_data(context, enctype, pw, principal, key);
1017 }
1018
1019 krb5_error_code KRB5_LIB_FUNCTION
1020 krb5_string_to_key_data_salt (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1021 krb5_enctype enctype,
1022 krb5_data password,
1023 krb5_salt salt,
1024 krb5_keyblock *key)
1025 {
1026 krb5_data opaque;
1027 krb5_data_zero(&opaque);
1028 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1029 salt, opaque, key);
1030 }
1031
1032 /*
1033 * Do a string -> key for encryption type `enctype' operation on
1034 * `password' (with salt `salt' and the enctype specific data string
1035 * `opaque'), returning the resulting key in `key'
1036 */
1037
1038 krb5_error_code KRB5_LIB_FUNCTION
1039 krb5_string_to_key_data_salt_opaque (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1040 krb5_enctype enctype,
1041 krb5_data password,
1042 krb5_salt salt,
1043 krb5_data opaque,
1044 krb5_keyblock *key)
1045 {
1046 struct encryption_type *et =_find_enctype(enctype);
1047 struct salt_type *st;
1048 if(et == NULL) {
1049 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1050 N_("encryption type %d not supported", ""),
1051 enctype);
1052 return KRB5_PROG_ETYPE_NOSUPP;
1053 }
1054 for(st = et->keytype->string_to_key; st && st->type; st++)
1055 if(st->type == salt.salttype)
1056 return (*st->string_to_key)(context, enctype, password,
1057 salt, opaque, key);
1058 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1059 N_("salt type %d not supported", ""),
1060 salt.salttype);
1061 return HEIM_ERR_SALTTYPE_NOSUPP;
1062 }
1063
1064 /*
1065 * Do a string -> key for encryption type `enctype' operation on the
1066 * string `password' (with salt `salt'), returning the resulting key
1067 * in `key'
1068 */
1069
1070 krb5_error_code KRB5_LIB_FUNCTION
1071 krb5_string_to_key_salt (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1072 krb5_enctype enctype,
1073 const char *password,
1074 krb5_salt salt,
1075 krb5_keyblock *key)
1076 {
1077 krb5_data pw;
1078 pw.data = rk_UNCONST(password);
1079 pw.length = strlen(password);
1080 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1081 }
1082
1083 krb5_error_code KRB5_LIB_FUNCTION
1084 krb5_string_to_key_salt_opaque (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1085 krb5_enctype enctype,
1086 const char *password,
1087 krb5_salt salt,
1088 krb5_data opaque,
1089 krb5_keyblock *key)
1090 {
1091 krb5_data pw;
1092 pw.data = rk_UNCONST(password);
1093 pw.length = strlen(password);
1094 return krb5_string_to_key_data_salt_opaque(context, enctype,
1095 pw, salt, opaque, key);
1096 }
1097
1098 krb5_error_code KRB5_LIB_FUNCTION
1099 krb5_enctype_keysize(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1100 krb5_enctype type,
1101 size_t *keysize)
1102 {
1103 struct encryption_type *et = _find_enctype(type);
1104 if(et == NULL) {
1105 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1106 N_("encryption type %d not supported", ""),
1107 type);
1108 return KRB5_PROG_ETYPE_NOSUPP;
1109 }
1110 *keysize = et->keytype->size;
1111 return 0;
1112 }
1113
1114 krb5_error_code KRB5_LIB_FUNCTION
1115 krb5_enctype_keybits(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1116 krb5_enctype type,
1117 size_t *keybits)
1118 {
1119 struct encryption_type *et = _find_enctype(type);
1120 if(et == NULL) {
1121 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1122 "encryption type %d not supported",
1123 type);
1124 return KRB5_PROG_ETYPE_NOSUPP;
1125 }
1126 *keybits = et->keytype->bits;
1127 return 0;
1128 }
1129
1130 krb5_error_code KRB5_LIB_FUNCTION
1131 krb5_generate_random_keyblock(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1132 krb5_enctype type,
1133 krb5_keyblock *key)
1134 {
1135 krb5_error_code ret;
1136 struct encryption_type *et = _find_enctype(type);
1137 if(et == NULL) {
1138 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1139 N_("encryption type %d not supported", ""),
1140 type);
1141 return KRB5_PROG_ETYPE_NOSUPP;
1142 }
1143 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1144 if(ret)
1145 return ret;
1146 key->keytype = type;
1147 if(et->keytype->random_key)
1148 (*et->keytype->random_key)(context, key);
1149 else
1150 krb5_generate_random_block(key->keyvalue.data,
1151 key->keyvalue.length);
1152 return 0;
1153 }
1154
1155 static krb5_error_code
1156 _key_schedule(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1157 struct key_data *key)
1158 {
1159 krb5_error_code ret;
1160 struct encryption_type *et = _find_enctype(key->key->keytype);
1161 struct key_type *kt = et->keytype;
1162
1163 if(kt->schedule == NULL)
1164 return 0;
1165 if (key->schedule != NULL)
1166 return 0;
1167 ALLOC(key->schedule, 1);
1168 if(key->schedule == NULL) {
1169 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1170 return ENOMEM;
1171 }
1172 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1173 if(ret) {
1174 free(key->schedule);
1175 key->schedule = NULL;
1176 return ret;
1177 }
1178 (*kt->schedule)(context, kt, key);
1179 return 0;
1180 }
1181
1182 /************************************************************
1183 * *
1184 ************************************************************/
1185
1186 static krb5_error_code
1187 NONE_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1188 struct key_data *key,
1189 const void *data,
1190 size_t len,
1191 unsigned usage,
1192 Checksum *C)
1193 {
1194 return 0;
1195 }
1196
1197 static krb5_error_code
1198 CRC32_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1199 struct key_data *key,
1200 const void *data,
1201 size_t len,
1202 unsigned usage,
1203 Checksum *C)
1204 {
1205 uint32_t crc;
1206 unsigned char *r = C->checksum.data;
1207 _krb5_crc_init_table ();
1208 crc = _krb5_crc_update (data, len, 0);
1209 r[0] = crc & 0xff;
1210 r[1] = (crc >> 8) & 0xff;
1211 r[2] = (crc >> 16) & 0xff;
1212 r[3] = (crc >> 24) & 0xff;
1213 return 0;
1214 }
1215
1216 static krb5_error_code
1217 RSA_MD4_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1218 struct key_data *key,
1219 const void *data,
1220 size_t len,
1221 unsigned usage,
1222 Checksum *C)
1223 {
1224 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1225 krb5_abortx(context, "md4 checksum failed");
1226 return 0;
1227 }
1228
1229 static krb5_error_code
1230 des_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1231 const EVP_MD *evp_md,
1232 struct key_data *key,
1233 const void *data,
1234 size_t len,
1235 Checksum *cksum)
1236 {
1237 struct evp_schedule *ctx = key->schedule->data;
1238 EVP_MD_CTX *m;
1239 DES_cblock ivec;
1240 unsigned char *p = cksum->checksum.data;
1241
1242 krb5_generate_random_block(p, 8);
1243
1244 m = EVP_MD_CTX_create();
1245 if (m == NULL) {
1246 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1247 return ENOMEM;
1248 }
1249
1250 EVP_DigestInit_ex(m, evp_md, NULL);
1251 EVP_DigestUpdate(m, p, 8);
1252 EVP_DigestUpdate(m, data, len);
1253 EVP_DigestFinal_ex (m, p + 8, NULL);
1254 EVP_MD_CTX_destroy(m);
1255 memset (&ivec, 0, sizeof(ivec));
1256 EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1257 EVP_Cipher(&ctx->ectx, p, p, 24);
1258
1259 return 0;
1260 }
1261
1262 static krb5_error_code
1263 des_verify(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1264 const EVP_MD *evp_md,
1265 struct key_data *key,
1266 const void *data,
1267 size_t len,
1268 Checksum *C)
1269 {
1270 struct evp_schedule *ctx = key->schedule->data;
1271 EVP_MD_CTX *m;
1272 unsigned char tmp[24];
1273 unsigned char res[16];
1274 DES_cblock ivec;
1275 krb5_error_code ret = 0;
1276
1277 m = EVP_MD_CTX_create();
1278 if (m == NULL) {
1279 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1280 return ENOMEM;
1281 }
1282
1283 memset(&ivec, 0, sizeof(ivec));
1284 EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1285 EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1286
1287 EVP_DigestInit_ex(m, evp_md, NULL);
1288 EVP_DigestUpdate(m, tmp, 8); /* confounder */
1289 EVP_DigestUpdate(m, data, len);
1290 EVP_DigestFinal_ex (m, res, NULL);
1291 EVP_MD_CTX_destroy(m);
1292 if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
1293 krb5_clear_error_message (context);
1294 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1295 }
1296 memset(tmp, 0, sizeof(tmp));
1297 memset(res, 0, sizeof(res));
1298 return ret;
1299 }
1300
1301 static krb5_error_code
1302 RSA_MD4_DES_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1303 struct key_data *key,
1304 const void *data,
1305 size_t len,
1306 unsigned usage,
1307 Checksum *cksum)
1308 {
1309 return des_checksum(context, EVP_md4(), key, data, len, cksum);
1310 }
1311
1312 static krb5_error_code
1313 RSA_MD4_DES_verify(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1314 struct key_data *key,
1315 const void *data,
1316 size_t len,
1317 unsigned usage,
1318 Checksum *C)
1319 {
1320 return des_verify(context, EVP_md5(), key, data, len, C);
1321 }
1322
1323 static krb5_error_code
1324 RSA_MD5_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1325 struct key_data *key,
1326 const void *data,
1327 size_t len,
1328 unsigned usage,
1329 Checksum *C)
1330 {
1331 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1332 krb5_abortx(context, "md5 checksum failed");
1333 return 0;
1334 }
1335
1336 static krb5_error_code
1337 RSA_MD5_DES_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1338 struct key_data *key,
1339 const void *data,
1340 size_t len,
1341 unsigned usage,
1342 Checksum *C)
1343 {
1344 return des_checksum(context, EVP_md5(), key, data, len, C);
1345 }
1346
1347 static krb5_error_code
1348 RSA_MD5_DES_verify(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1349 struct key_data *key,
1350 const void *data,
1351 size_t len,
1352 unsigned usage,
1353 Checksum *C)
1354 {
1355 return des_verify(context, EVP_md5(), key, data, len, C);
1356 }
1357
1358 #ifdef DES3_OLD_ENCTYPE
1359 static krb5_error_code
1360 RSA_MD5_DES3_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1361 struct key_data *key,
1362 const void *data,
1363 size_t len,
1364 unsigned usage,
1365 Checksum *C)
1366 {
1367 return des_checksum(context, EVP_md5(), key, data, len, C);
1368 }
1369
1370 static krb5_error_code
1371 RSA_MD5_DES3_verify(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1372 struct key_data *key,
1373 const void *data,
1374 size_t len,
1375 unsigned usage,
1376 Checksum *C)
1377 {
1378 return des_verify(context, EVP_md5(), key, data, len, C);
1379 }
1380 #endif
1381
1382 static krb5_error_code
1383 SHA1_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1384 struct key_data *key,
1385 const void *data,
1386 size_t len,
1387 unsigned usage,
1388 Checksum *C)
1389 {
1390 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1391 krb5_abortx(context, "sha1 checksum failed");
1392 return 0;
1393 }
1394
1395 /* HMAC according to RFC2104 */
1396 static krb5_error_code
1397 hmac(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1398 struct checksum_type *cm,
1399 const void *data,
1400 size_t len,
1401 unsigned usage,
1402 struct key_data *keyblock,
1403 Checksum *result)
1404 {
1405 unsigned char *ipad, *opad;
1406 unsigned char *key;
1407 size_t key_len;
1408 int i;
1409
1410 ipad = malloc(cm->blocksize + len);
1411 if (ipad == NULL)
1412 return ENOMEM;
1413 opad = malloc(cm->blocksize + cm->checksumsize);
1414 if (opad == NULL) {
1415 free(ipad);
1416 return ENOMEM;
1417 }
1418 memset(ipad, 0x36, cm->blocksize);
1419 memset(opad, 0x5c, cm->blocksize);
1420
1421 if(keyblock->key->keyvalue.length > cm->blocksize){
1422 (*cm->checksum)(context,
1423 keyblock,
1424 keyblock->key->keyvalue.data,
1425 keyblock->key->keyvalue.length,
1426 usage,
1427 result);
1428 key = result->checksum.data;
1429 key_len = result->checksum.length;
1430 } else {
1431 key = keyblock->key->keyvalue.data;
1432 key_len = keyblock->key->keyvalue.length;
1433 }
1434 for(i = 0; i < key_len; i++){
1435 ipad[i] ^= key[i];
1436 opad[i] ^= key[i];
1437 }
1438 memcpy(ipad + cm->blocksize, data, len);
1439 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1440 usage, result);
1441 memcpy(opad + cm->blocksize, result->checksum.data,
1442 result->checksum.length);
1443 (*cm->checksum)(context, keyblock, opad,
1444 cm->blocksize + cm->checksumsize, usage, result);
1445 memset(ipad, 0, cm->blocksize + len);
1446 free(ipad);
1447 memset(opad, 0, cm->blocksize + cm->checksumsize);
1448 free(opad);
1449
1450 return 0;
1451 }
1452
1453 krb5_error_code KRB5_LIB_FUNCTION
1454 krb5_hmac(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1455 krb5_cksumtype cktype,
1456 const void *data,
1457 size_t len,
1458 unsigned usage,
1459 krb5_keyblock *key,
1460 Checksum *result)
1461 {
1462 struct checksum_type *c = _find_checksum(cktype);
1463 struct key_data kd;
1464 krb5_error_code ret;
1465
1466 if (c == NULL) {
1467 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1468 N_("checksum type %d not supported", ""),
1469 cktype);
1470 return KRB5_PROG_SUMTYPE_NOSUPP;
1471 }
1472
1473 kd.key = key;
1474 kd.schedule = NULL;
1475
1476 ret = hmac(context, c, data, len, usage, &kd, result);
1477
1478 if (kd.schedule)
1479 krb5_free_data(context, kd.schedule);
1480
1481 return ret;
1482 }
1483
1484 static krb5_error_code
1485 SP_HMAC_SHA1_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1486 struct key_data *key,
1487 const void *data,
1488 size_t len,
1489 unsigned usage,
1490 Checksum *result)
1491 {
1492 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1493 Checksum res;
1494 char sha1_data[20];
1495 krb5_error_code ret;
1496
1497 res.checksum.data = sha1_data;
1498 res.checksum.length = sizeof(sha1_data);
1499
1500 ret = hmac(context, c, data, len, usage, key, &res);
1501 if (ret)
1502 krb5_abortx(context, "hmac failed");
1503 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1504 return 0;
1505 }
1506
1507 /*
1508 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1509 */
1510
1511 static krb5_error_code
1512 HMAC_MD5_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1513 struct key_data *key,
1514 const void *data,
1515 size_t len,
1516 unsigned usage,
1517 Checksum *result)
1518 {
1519 EVP_MD_CTX *m;
1520 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1521 const char signature[] = "signaturekey";
1522 Checksum ksign_c;
1523 struct key_data ksign;
1524 krb5_keyblock kb;
1525 unsigned char t[4];
1526 unsigned char tmp[16];
1527 unsigned char ksign_c_data[16];
1528 krb5_error_code ret;
1529
1530 m = EVP_MD_CTX_create();
1531 if (m == NULL) {
1532 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1533 return ENOMEM;
1534 }
1535 ksign_c.checksum.length = sizeof(ksign_c_data);
1536 ksign_c.checksum.data = ksign_c_data;
1537 ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1538 if (ret) {
1539 EVP_MD_CTX_destroy(m);
1540 return ret;
1541 }
1542 ksign.key = &kb;
1543 kb.keyvalue = ksign_c.checksum;
1544 EVP_DigestInit_ex(m, EVP_md5(), NULL);
1545 t[0] = (usage >> 0) & 0xFF;
1546 t[1] = (usage >> 8) & 0xFF;
1547 t[2] = (usage >> 16) & 0xFF;
1548 t[3] = (usage >> 24) & 0xFF;
1549 EVP_DigestUpdate(m, t, 4);
1550 EVP_DigestUpdate(m, data, len);
1551 EVP_DigestFinal_ex (m, tmp, NULL);
1552 EVP_MD_CTX_destroy(m);
1553
1554 ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1555 if (ret)
1556 return ret;
1557 return 0;
1558 }
1559
1560 static struct checksum_type checksum_none = {
1561 CKSUMTYPE_NONE,
1562 "none",
1563 1,
1564 0,
1565 0,
1566 NONE_checksum,
1567 NULL
1568 };
1569 static struct checksum_type checksum_crc32 = {
1570 CKSUMTYPE_CRC32,
1571 "crc32",
1572 1,
1573 4,
1574 0,
1575 CRC32_checksum,
1576 NULL
1577 };
1578 static struct checksum_type checksum_rsa_md4 = {
1579 CKSUMTYPE_RSA_MD4,
1580 "rsa-md4",
1581 64,
1582 16,
1583 F_CPROOF,
1584 RSA_MD4_checksum,
1585 NULL
1586 };
1587 static struct checksum_type checksum_rsa_md4_des = {
1588 CKSUMTYPE_RSA_MD4_DES,
1589 "rsa-md4-des",
1590 64,
1591 24,
1592 F_KEYED | F_CPROOF | F_VARIANT,
1593 RSA_MD4_DES_checksum,
1594 RSA_MD4_DES_verify
1595 };
1596 static struct checksum_type checksum_rsa_md5 = {
1597 CKSUMTYPE_RSA_MD5,
1598 "rsa-md5",
1599 64,
1600 16,
1601 F_CPROOF,
1602 RSA_MD5_checksum,
1603 NULL
1604 };
1605 static struct checksum_type checksum_rsa_md5_des = {
1606 CKSUMTYPE_RSA_MD5_DES,
1607 "rsa-md5-des",
1608 64,
1609 24,
1610 F_KEYED | F_CPROOF | F_VARIANT,
1611 RSA_MD5_DES_checksum,
1612 RSA_MD5_DES_verify
1613 };
1614 #ifdef DES3_OLD_ENCTYPE
1615 static struct checksum_type checksum_rsa_md5_des3 = {
1616 CKSUMTYPE_RSA_MD5_DES3,
1617 "rsa-md5-des3",
1618 64,
1619 24,
1620 F_KEYED | F_CPROOF | F_VARIANT,
1621 RSA_MD5_DES3_checksum,
1622 RSA_MD5_DES3_verify
1623 };
1624 #endif
1625 static struct checksum_type checksum_sha1 = {
1626 CKSUMTYPE_SHA1,
1627 "sha1",
1628 64,
1629 20,
1630 F_CPROOF,
1631 SHA1_checksum,
1632 NULL
1633 };
1634 static struct checksum_type checksum_hmac_sha1_des3 = {
1635 CKSUMTYPE_HMAC_SHA1_DES3,
1636 "hmac-sha1-des3",
1637 64,
1638 20,
1639 F_KEYED | F_CPROOF | F_DERIVED,
1640 SP_HMAC_SHA1_checksum,
1641 NULL
1642 };
1643
1644 static struct checksum_type checksum_hmac_sha1_aes128 = {
1645 CKSUMTYPE_HMAC_SHA1_96_AES_128,
1646 "hmac-sha1-96-aes128",
1647 64,
1648 12,
1649 F_KEYED | F_CPROOF | F_DERIVED,
1650 SP_HMAC_SHA1_checksum,
1651 NULL
1652 };
1653
1654 static struct checksum_type checksum_hmac_sha1_aes256 = {
1655 CKSUMTYPE_HMAC_SHA1_96_AES_256,
1656 "hmac-sha1-96-aes256",
1657 64,
1658 12,
1659 F_KEYED | F_CPROOF | F_DERIVED,
1660 SP_HMAC_SHA1_checksum,
1661 NULL
1662 };
1663
1664 static struct checksum_type checksum_hmac_md5 = {
1665 CKSUMTYPE_HMAC_MD5,
1666 "hmac-md5",
1667 64,
1668 16,
1669 F_KEYED | F_CPROOF,
1670 HMAC_MD5_checksum,
1671 NULL
1672 };
1673
1674 static struct checksum_type *checksum_types[] = {
1675 &checksum_none,
1676 &checksum_crc32,
1677 &checksum_rsa_md4,
1678 &checksum_rsa_md4_des,
1679 &checksum_rsa_md5,
1680 &checksum_rsa_md5_des,
1681 #ifdef DES3_OLD_ENCTYPE
1682 &checksum_rsa_md5_des3,
1683 #endif
1684 &checksum_sha1,
1685 &checksum_hmac_sha1_des3,
1686 &checksum_hmac_sha1_aes128,
1687 &checksum_hmac_sha1_aes256,
1688 &checksum_hmac_md5
1689 };
1690
1691 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1692
1693 static struct checksum_type *
1694 _find_checksum(krb5_cksumtype type)
/* [<][>][^][v][top][bottom][index][help] */
1695 {
1696 int i;
1697 for(i = 0; i < num_checksums; i++)
1698 if(checksum_types[i]->type == type)
1699 return checksum_types[i];
1700 return NULL;
1701 }
1702
1703 static krb5_error_code
1704 get_checksum_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1705 krb5_crypto crypto,
1706 unsigned usage, /* not krb5_key_usage */
1707 struct checksum_type *ct,
1708 struct key_data **key)
1709 {
1710 krb5_error_code ret = 0;
1711
1712 if(ct->flags & F_DERIVED)
1713 ret = _get_derived_key(context, crypto, usage, key);
1714 else if(ct->flags & F_VARIANT) {
1715 int i;
1716
1717 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1718 if(*key == NULL) {
1719 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1720 return ENOMEM;
1721 }
1722 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1723 if(ret)
1724 return ret;
1725 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1726 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1727 } else {
1728 *key = &crypto->key;
1729 }
1730 if(ret == 0)
1731 ret = _key_schedule(context, *key);
1732 return ret;
1733 }
1734
1735 static krb5_error_code
1736 create_checksum (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1737 struct checksum_type *ct,
1738 krb5_crypto crypto,
1739 unsigned usage,
1740 void *data,
1741 size_t len,
1742 Checksum *result)
1743 {
1744 krb5_error_code ret;
1745 struct key_data *dkey;
1746 int keyed_checksum;
1747
1748 if (ct->flags & F_DISABLED) {
1749 krb5_clear_error_message (context);
1750 return KRB5_PROG_SUMTYPE_NOSUPP;
1751 }
1752 keyed_checksum = (ct->flags & F_KEYED) != 0;
1753 if(keyed_checksum && crypto == NULL) {
1754 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1755 N_("Checksum type %s is keyed but no "
1756 "crypto context (key) was passed in", ""),
1757 ct->name);
1758 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1759 }
1760 if(keyed_checksum) {
1761 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1762 if (ret)
1763 return ret;
1764 } else
1765 dkey = NULL;
1766 result->cksumtype = ct->type;
1767 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1768 if (ret)
1769 return (ret);
1770 return (*ct->checksum)(context, dkey, data, len, usage, result);
1771 }
1772
1773 static int
1774 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
/* [<][>][^][v][top][bottom][index][help] */
1775 {
1776 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1777 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1778 }
1779
1780 krb5_error_code KRB5_LIB_FUNCTION
1781 krb5_create_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1782 krb5_crypto crypto,
1783 krb5_key_usage usage,
1784 int type,
1785 void *data,
1786 size_t len,
1787 Checksum *result)
1788 {
1789 struct checksum_type *ct = NULL;
1790 unsigned keyusage;
1791
1792 /* type 0 -> pick from crypto */
1793 if (type) {
1794 ct = _find_checksum(type);
1795 } else if (crypto) {
1796 ct = crypto->et->keyed_checksum;
1797 if (ct == NULL)
1798 ct = crypto->et->checksum;
1799 }
1800
1801 if(ct == NULL) {
1802 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1803 N_("checksum type %d not supported", ""),
1804 type);
1805 return KRB5_PROG_SUMTYPE_NOSUPP;
1806 }
1807
1808 if (arcfour_checksum_p(ct, crypto)) {
1809 keyusage = usage;
1810 usage2arcfour(context, &keyusage);
1811 } else
1812 keyusage = CHECKSUM_USAGE(usage);
1813
1814 return create_checksum(context, ct, crypto, keyusage,
1815 data, len, result);
1816 }
1817
1818 static krb5_error_code
1819 verify_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1820 krb5_crypto crypto,
1821 unsigned usage, /* not krb5_key_usage */
1822 void *data,
1823 size_t len,
1824 Checksum *cksum)
1825 {
1826 krb5_error_code ret;
1827 struct key_data *dkey;
1828 int keyed_checksum;
1829 Checksum c;
1830 struct checksum_type *ct;
1831
1832 ct = _find_checksum(cksum->cksumtype);
1833 if (ct == NULL || (ct->flags & F_DISABLED)) {
1834 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1835 N_("checksum type %d not supported", ""),
1836 cksum->cksumtype);
1837 return KRB5_PROG_SUMTYPE_NOSUPP;
1838 }
1839 if(ct->checksumsize != cksum->checksum.length) {
1840 krb5_clear_error_message (context);
1841 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1842 }
1843 keyed_checksum = (ct->flags & F_KEYED) != 0;
1844 if(keyed_checksum && crypto == NULL) {
1845 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1846 N_("Checksum type %s is keyed but no "
1847 "crypto context (key) was passed in", ""),
1848 ct->name);
1849 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1850 }
1851 if(keyed_checksum) {
1852 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1853 if (ret)
1854 return ret;
1855 } else
1856 dkey = NULL;
1857 if(ct->verify)
1858 return (*ct->verify)(context, dkey, data, len, usage, cksum);
1859
1860 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1861 if (ret)
1862 return ret;
1863
1864 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1865 if (ret) {
1866 krb5_data_free(&c.checksum);
1867 return ret;
1868 }
1869
1870 if(c.checksum.length != cksum->checksum.length ||
1871 memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1872 krb5_clear_error_message (context);
1873 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1874 } else {
1875 ret = 0;
1876 }
1877 krb5_data_free (&c.checksum);
1878 return ret;
1879 }
1880
1881 krb5_error_code KRB5_LIB_FUNCTION
1882 krb5_verify_checksum(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1883 krb5_crypto crypto,
1884 krb5_key_usage usage,
1885 void *data,
1886 size_t len,
1887 Checksum *cksum)
1888 {
1889 struct checksum_type *ct;
1890 unsigned keyusage;
1891
1892 ct = _find_checksum(cksum->cksumtype);
1893 if(ct == NULL) {
1894 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1895 N_("checksum type %d not supported", ""),
1896 cksum->cksumtype);
1897 return KRB5_PROG_SUMTYPE_NOSUPP;
1898 }
1899
1900 if (arcfour_checksum_p(ct, crypto)) {
1901 keyusage = usage;
1902 usage2arcfour(context, &keyusage);
1903 } else
1904 keyusage = CHECKSUM_USAGE(usage);
1905
1906 return verify_checksum(context, crypto, keyusage,
1907 data, len, cksum);
1908 }
1909
1910 krb5_error_code KRB5_LIB_FUNCTION
1911 krb5_crypto_get_checksum_type(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1912 krb5_crypto crypto,
1913 krb5_cksumtype *type)
1914 {
1915 struct checksum_type *ct = NULL;
1916
1917 if (crypto != NULL) {
1918 ct = crypto->et->keyed_checksum;
1919 if (ct == NULL)
1920 ct = crypto->et->checksum;
1921 }
1922
1923 if (ct == NULL) {
1924 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1925 N_("checksum type not found", ""));
1926 return KRB5_PROG_SUMTYPE_NOSUPP;
1927 }
1928
1929 *type = ct->type;
1930
1931 return 0;
1932 }
1933
1934
1935 krb5_error_code KRB5_LIB_FUNCTION
1936 krb5_checksumsize(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1937 krb5_cksumtype type,
1938 size_t *size)
1939 {
1940 struct checksum_type *ct = _find_checksum(type);
1941 if(ct == NULL) {
1942 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1943 N_("checksum type %d not supported", ""),
1944 type);
1945 return KRB5_PROG_SUMTYPE_NOSUPP;
1946 }
1947 *size = ct->checksumsize;
1948 return 0;
1949 }
1950
1951 krb5_boolean KRB5_LIB_FUNCTION
1952 krb5_checksum_is_keyed(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1953 krb5_cksumtype type)
1954 {
1955 struct checksum_type *ct = _find_checksum(type);
1956 if(ct == NULL) {
1957 if (context)
1958 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1959 N_("checksum type %d not supported", ""),
1960 type);
1961 return KRB5_PROG_SUMTYPE_NOSUPP;
1962 }
1963 return ct->flags & F_KEYED;
1964 }
1965
1966 krb5_boolean KRB5_LIB_FUNCTION
1967 krb5_checksum_is_collision_proof(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1968 krb5_cksumtype type)
1969 {
1970 struct checksum_type *ct = _find_checksum(type);
1971 if(ct == NULL) {
1972 if (context)
1973 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1974 N_("checksum type %d not supported", ""),
1975 type);
1976 return KRB5_PROG_SUMTYPE_NOSUPP;
1977 }
1978 return ct->flags & F_CPROOF;
1979 }
1980
1981 krb5_error_code KRB5_LIB_FUNCTION
1982 krb5_checksum_disable(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1983 krb5_cksumtype type)
1984 {
1985 struct checksum_type *ct = _find_checksum(type);
1986 if(ct == NULL) {
1987 if (context)
1988 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1989 N_("checksum type %d not supported", ""),
1990 type);
1991 return KRB5_PROG_SUMTYPE_NOSUPP;
1992 }
1993 ct->flags |= F_DISABLED;
1994 return 0;
1995 }
1996
1997 /************************************************************
1998 * *
1999 ************************************************************/
2000
2001 static krb5_error_code
2002 NULL_encrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2003 struct key_data *key,
2004 void *data,
2005 size_t len,
2006 krb5_boolean encryptp,
2007 int usage,
2008 void *ivec)
2009 {
2010 return 0;
2011 }
2012
2013 static krb5_error_code
2014 evp_encrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2015 struct key_data *key,
2016 void *data,
2017 size_t len,
2018 krb5_boolean encryptp,
2019 int usage,
2020 void *ivec)
2021 {
2022 struct evp_schedule *ctx = key->schedule->data;
2023 EVP_CIPHER_CTX *c;
2024 c = encryptp ? &ctx->ectx : &ctx->dctx;
2025 if (ivec == NULL) {
2026 /* alloca ? */
2027 size_t len = EVP_CIPHER_CTX_iv_length(c);
2028 void *loiv = malloc(len);
2029 if (loiv == NULL) {
2030 krb5_clear_error_message(context);
2031 return ENOMEM;
2032 }
2033 memset(loiv, 0, len);
2034 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2035 free(loiv);
2036 } else
2037 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2038 EVP_Cipher(c, data, data, len);
2039 return 0;
2040 }
2041
2042 #ifdef WEAK_ENCTYPES
2043 static krb5_error_code
2044 evp_des_encrypt_null_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2045 struct key_data *key,
2046 void *data,
2047 size_t len,
2048 krb5_boolean encryptp,
2049 int usage,
2050 void *ignore_ivec)
2051 {
2052 struct evp_schedule *ctx = key->schedule->data;
2053 EVP_CIPHER_CTX *c;
2054 DES_cblock ivec;
2055 memset(&ivec, 0, sizeof(ivec));
2056 c = encryptp ? &ctx->ectx : &ctx->dctx;
2057 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2058 EVP_Cipher(c, data, data, len);
2059 return 0;
2060 }
2061
2062 static krb5_error_code
2063 evp_des_encrypt_key_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2064 struct key_data *key,
2065 void *data,
2066 size_t len,
2067 krb5_boolean encryptp,
2068 int usage,
2069 void *ignore_ivec)
2070 {
2071 struct evp_schedule *ctx = key->schedule->data;
2072 EVP_CIPHER_CTX *c;
2073 DES_cblock ivec;
2074 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2075 c = encryptp ? &ctx->ectx : &ctx->dctx;
2076 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2077 EVP_Cipher(c, data, data, len);
2078 return 0;
2079 }
2080
2081 static krb5_error_code
2082 DES_CFB64_encrypt_null_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2083 struct key_data *key,
2084 void *data,
2085 size_t len,
2086 krb5_boolean encryptp,
2087 int usage,
2088 void *ignore_ivec)
2089 {
2090 DES_cblock ivec;
2091 int num = 0;
2092 DES_key_schedule *s = key->schedule->data;
2093 memset(&ivec, 0, sizeof(ivec));
2094
2095 DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2096 return 0;
2097 }
2098
2099 static krb5_error_code
2100 DES_PCBC_encrypt_key_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2101 struct key_data *key,
2102 void *data,
2103 size_t len,
2104 krb5_boolean encryptp,
2105 int usage,
2106 void *ignore_ivec)
2107 {
2108 DES_cblock ivec;
2109 DES_key_schedule *s = key->schedule->data;
2110 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2111
2112 DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2113 return 0;
2114 }
2115 #endif
2116
2117 /*
2118 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2119 *
2120 * warning: not for small children
2121 */
2122
2123 static krb5_error_code
2124 ARCFOUR_subencrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2125 struct key_data *key,
2126 void *data,
2127 size_t len,
2128 unsigned usage,
2129 void *ivec)
2130 {
2131 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2132 Checksum k1_c, k2_c, k3_c, cksum;
2133 struct key_data ke;
2134 krb5_keyblock kb;
2135 unsigned char t[4];
2136 RC4_KEY rc4_key;
2137 unsigned char *cdata = data;
2138 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2139 krb5_error_code ret;
2140
2141 t[0] = (usage >> 0) & 0xFF;
2142 t[1] = (usage >> 8) & 0xFF;
2143 t[2] = (usage >> 16) & 0xFF;
2144 t[3] = (usage >> 24) & 0xFF;
2145
2146 k1_c.checksum.length = sizeof(k1_c_data);
2147 k1_c.checksum.data = k1_c_data;
2148
2149 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2150 if (ret)
2151 krb5_abortx(context, "hmac failed");
2152
2153 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2154
2155 k2_c.checksum.length = sizeof(k2_c_data);
2156 k2_c.checksum.data = k2_c_data;
2157
2158 ke.key = &kb;
2159 kb.keyvalue = k2_c.checksum;
2160
2161 cksum.checksum.length = 16;
2162 cksum.checksum.data = data;
2163
2164 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2165 if (ret)
2166 krb5_abortx(context, "hmac failed");
2167
2168 ke.key = &kb;
2169 kb.keyvalue = k1_c.checksum;
2170
2171 k3_c.checksum.length = sizeof(k3_c_data);
2172 k3_c.checksum.data = k3_c_data;
2173
2174 ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2175 if (ret)
2176 krb5_abortx(context, "hmac failed");
2177
2178 RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2179 RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2180 memset (k1_c_data, 0, sizeof(k1_c_data));
2181 memset (k2_c_data, 0, sizeof(k2_c_data));
2182 memset (k3_c_data, 0, sizeof(k3_c_data));
2183 return 0;
2184 }
2185
2186 static krb5_error_code
2187 ARCFOUR_subdecrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2188 struct key_data *key,
2189 void *data,
2190 size_t len,
2191 unsigned usage,
2192 void *ivec)
2193 {
2194 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2195 Checksum k1_c, k2_c, k3_c, cksum;
2196 struct key_data ke;
2197 krb5_keyblock kb;
2198 unsigned char t[4];
2199 RC4_KEY rc4_key;
2200 unsigned char *cdata = data;
2201 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2202 unsigned char cksum_data[16];
2203 krb5_error_code ret;
2204
2205 t[0] = (usage >> 0) & 0xFF;
2206 t[1] = (usage >> 8) & 0xFF;
2207 t[2] = (usage >> 16) & 0xFF;
2208 t[3] = (usage >> 24) & 0xFF;
2209
2210 k1_c.checksum.length = sizeof(k1_c_data);
2211 k1_c.checksum.data = k1_c_data;
2212
2213 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2214 if (ret)
2215 krb5_abortx(context, "hmac failed");
2216
2217 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2218
2219 k2_c.checksum.length = sizeof(k2_c_data);
2220 k2_c.checksum.data = k2_c_data;
2221
2222 ke.key = &kb;
2223 kb.keyvalue = k1_c.checksum;
2224
2225 k3_c.checksum.length = sizeof(k3_c_data);
2226 k3_c.checksum.data = k3_c_data;
2227
2228 ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2229 if (ret)
2230 krb5_abortx(context, "hmac failed");
2231
2232 RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2233 RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2234
2235 ke.key = &kb;
2236 kb.keyvalue = k2_c.checksum;
2237
2238 cksum.checksum.length = 16;
2239 cksum.checksum.data = cksum_data;
2240
2241 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2242 if (ret)
2243 krb5_abortx(context, "hmac failed");
2244
2245 memset (k1_c_data, 0, sizeof(k1_c_data));
2246 memset (k2_c_data, 0, sizeof(k2_c_data));
2247 memset (k3_c_data, 0, sizeof(k3_c_data));
2248
2249 if (memcmp (cksum.checksum.data, data, 16) != 0) {
2250 krb5_clear_error_message (context);
2251 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2252 } else {
2253 return 0;
2254 }
2255 }
2256
2257 /*
2258 * convert the usage numbers used in
2259 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2260 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2261 */
2262
2263 static krb5_error_code
2264 usage2arcfour (krb5_context context, unsigned *usage)
/* [<][>][^][v][top][bottom][index][help] */
2265 {
2266 switch (*usage) {
2267 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2268 case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2269 *usage = 8;
2270 return 0;
2271 case KRB5_KU_USAGE_SEAL : /* 22 */
2272 *usage = 13;
2273 return 0;
2274 case KRB5_KU_USAGE_SIGN : /* 23 */
2275 *usage = 15;
2276 return 0;
2277 case KRB5_KU_USAGE_SEQ: /* 24 */
2278 *usage = 0;
2279 return 0;
2280 default :
2281 return 0;
2282 }
2283 }
2284
2285 static krb5_error_code
2286 ARCFOUR_encrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2287 struct key_data *key,
2288 void *data,
2289 size_t len,
2290 krb5_boolean encryptp,
2291 int usage,
2292 void *ivec)
2293 {
2294 krb5_error_code ret;
2295 unsigned keyusage = usage;
2296
2297 if((ret = usage2arcfour (context, &keyusage)) != 0)
2298 return ret;
2299
2300 if (encryptp)
2301 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2302 else
2303 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2304 }
2305
2306
2307 /*
2308 *
2309 */
2310
2311 static krb5_error_code
2312 AES_PRF(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2313 krb5_crypto crypto,
2314 const krb5_data *in,
2315 krb5_data *out)
2316 {
2317 struct checksum_type *ct = crypto->et->checksum;
2318 krb5_error_code ret;
2319 Checksum result;
2320 krb5_keyblock *derived;
2321
2322 result.cksumtype = ct->type;
2323 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2324 if (ret) {
2325 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2326 return ret;
2327 }
2328
2329 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2330 if (ret) {
2331 krb5_data_free(&result.checksum);
2332 return ret;
2333 }
2334
2335 if (result.checksum.length < crypto->et->blocksize)
2336 krb5_abortx(context, "internal prf error");
2337
2338 derived = NULL;
2339 ret = krb5_derive_key(context, crypto->key.key,
2340 crypto->et->type, "prf", 3, &derived);
2341 if (ret)
2342 krb5_abortx(context, "krb5_derive_key");
2343
2344 ret = krb5_data_alloc(out, crypto->et->blocksize);
2345 if (ret)
2346 krb5_abortx(context, "malloc failed");
2347
2348 {
2349 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2350 EVP_CIPHER_CTX ctx;
2351 /* XXX blksz 1 for cts, so we can't use that */
2352 EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2353 EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2354 EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
2355 EVP_CIPHER_CTX_cleanup(&ctx);
2356 }
2357
2358 krb5_data_free(&result.checksum);
2359 krb5_free_keyblock(context, derived);
2360
2361 return ret;
2362 }
2363
2364 /*
2365 * these should currently be in reverse preference order.
2366 * (only relevant for !F_PSEUDO) */
2367
2368 static struct encryption_type enctype_null = {
2369 ETYPE_NULL,
2370 "null",
2371 1,
2372 1,
2373 0,
2374 &keytype_null,
2375 &checksum_none,
2376 NULL,
2377 F_DISABLED,
2378 NULL_encrypt,
2379 0,
2380 NULL
2381 };
2382 static struct encryption_type enctype_arcfour_hmac_md5 = {
2383 ETYPE_ARCFOUR_HMAC_MD5,
2384 "arcfour-hmac-md5",
2385 1,
2386 1,
2387 8,
2388 &keytype_arcfour,
2389 &checksum_hmac_md5,
2390 NULL,
2391 F_SPECIAL,
2392 ARCFOUR_encrypt,
2393 0,
2394 NULL
2395 };
2396 #ifdef DES3_OLD_ENCTYPE
2397 static struct encryption_type enctype_des3_cbc_md5 = {
2398 ETYPE_DES3_CBC_MD5,
2399 "des3-cbc-md5",
2400 8,
2401 8,
2402 8,
2403 &keytype_des3,
2404 &checksum_rsa_md5,
2405 &checksum_rsa_md5_des3,
2406 0,
2407 evp_encrypt,
2408 0,
2409 NULL
2410 };
2411 #endif
2412 static struct encryption_type enctype_des3_cbc_sha1 = {
2413 ETYPE_DES3_CBC_SHA1,
2414 "des3-cbc-sha1",
2415 8,
2416 8,
2417 8,
2418 &keytype_des3_derived,
2419 &checksum_sha1,
2420 &checksum_hmac_sha1_des3,
2421 F_DERIVED,
2422 evp_encrypt,
2423 0,
2424 NULL
2425 };
2426 #ifdef DES3_OLD_ENCTYPE
2427 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2428 ETYPE_OLD_DES3_CBC_SHA1,
2429 "old-des3-cbc-sha1",
2430 8,
2431 8,
2432 8,
2433 &keytype_des3,
2434 &checksum_sha1,
2435 &checksum_hmac_sha1_des3,
2436 0,
2437 evp_encrypt,
2438 0,
2439 NULL
2440 };
2441 #endif
2442 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2443 ETYPE_AES128_CTS_HMAC_SHA1_96,
2444 "aes128-cts-hmac-sha1-96",
2445 16,
2446 1,
2447 16,
2448 &keytype_aes128,
2449 &checksum_sha1,
2450 &checksum_hmac_sha1_aes128,
2451 F_DERIVED,
2452 evp_encrypt,
2453 16,
2454 AES_PRF
2455 };
2456 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2457 ETYPE_AES256_CTS_HMAC_SHA1_96,
2458 "aes256-cts-hmac-sha1-96",
2459 16,
2460 1,
2461 16,
2462 &keytype_aes256,
2463 &checksum_sha1,
2464 &checksum_hmac_sha1_aes256,
2465 F_DERIVED,
2466 evp_encrypt,
2467 16,
2468 AES_PRF
2469 };
2470 static struct encryption_type enctype_des3_cbc_none = {
2471 ETYPE_DES3_CBC_NONE,
2472 "des3-cbc-none",
2473 8,
2474 8,
2475 0,
2476 &keytype_des3_derived,
2477 &checksum_none,
2478 NULL,
2479 F_PSEUDO,
2480 evp_encrypt,
2481 0,
2482 NULL
2483 };
2484 #ifdef WEAK_ENCTYPES
2485 static struct encryption_type enctype_des_cbc_crc = {
2486 ETYPE_DES_CBC_CRC,
2487 "des-cbc-crc",
2488 8,
2489 8,
2490 8,
2491 &keytype_des,
2492 &checksum_crc32,
2493 NULL,
2494 F_DISABLED,
2495 evp_des_encrypt_key_ivec,
2496 0,
2497 NULL
2498 };
2499 static struct encryption_type enctype_des_cbc_md4 = {
2500 ETYPE_DES_CBC_MD4,
2501 "des-cbc-md4",
2502 8,
2503 8,
2504 8,
2505 &keytype_des,
2506 &checksum_rsa_md4,
2507 &checksum_rsa_md4_des,
2508 F_DISABLED,
2509 evp_des_encrypt_null_ivec,
2510 0,
2511 NULL
2512 };
2513 static struct encryption_type enctype_des_cbc_md5 = {
2514 ETYPE_DES_CBC_MD5,
2515 "des-cbc-md5",
2516 8,
2517 8,
2518 8,
2519 &keytype_des,
2520 &checksum_rsa_md5,
2521 &checksum_rsa_md5_des,
2522 F_DISABLED,
2523 evp_des_encrypt_null_ivec,
2524 0,
2525 NULL
2526 };
2527 static struct encryption_type enctype_des_cbc_none = {
2528 ETYPE_DES_CBC_NONE,
2529 "des-cbc-none",
2530 8,
2531 8,
2532 0,
2533 &keytype_des,
2534 &checksum_none,
2535 NULL,
2536 F_PSEUDO|F_DISABLED,
2537 evp_des_encrypt_null_ivec,
2538 0,
2539 NULL
2540 };
2541 static struct encryption_type enctype_des_cfb64_none = {
2542 ETYPE_DES_CFB64_NONE,
2543 "des-cfb64-none",
2544 1,
2545 1,
2546 0,
2547 &keytype_des_old,
2548 &checksum_none,
2549 NULL,
2550 F_PSEUDO|F_DISABLED,
2551 DES_CFB64_encrypt_null_ivec,
2552 0,
2553 NULL
2554 };
2555 static struct encryption_type enctype_des_pcbc_none = {
2556 ETYPE_DES_PCBC_NONE,
2557 "des-pcbc-none",
2558 8,
2559 8,
2560 0,
2561 &keytype_des_old,
2562 &checksum_none,
2563 NULL,
2564 F_PSEUDO|F_DISABLED,
2565 DES_PCBC_encrypt_key_ivec,
2566 0,
2567 NULL
2568 };
2569 #endif /* WEAK_ENCTYPES */
2570
2571 static struct encryption_type *etypes[] = {
2572 &enctype_aes256_cts_hmac_sha1,
2573 &enctype_aes128_cts_hmac_sha1,
2574 &enctype_des3_cbc_sha1,
2575 &enctype_des3_cbc_none, /* used by the gss-api mech */
2576 &enctype_arcfour_hmac_md5,
2577 #ifdef DES3_OLD_ENCTYPE
2578 &enctype_des3_cbc_md5,
2579 &enctype_old_des3_cbc_sha1,
2580 #endif
2581 #ifdef WEAK_ENCTYPES
2582 &enctype_des_cbc_crc,
2583 &enctype_des_cbc_md4,
2584 &enctype_des_cbc_md5,
2585 &enctype_des_cbc_none,
2586 &enctype_des_cfb64_none,
2587 &enctype_des_pcbc_none,
2588 #endif
2589 &enctype_null
2590 };
2591
2592 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2593
2594
2595 static struct encryption_type *
2596 _find_enctype(krb5_enctype type)
/* [<][>][^][v][top][bottom][index][help] */
2597 {
2598 int i;
2599 for(i = 0; i < num_etypes; i++)
2600 if(etypes[i]->type == type)
2601 return etypes[i];
2602 return NULL;
2603 }
2604
2605
2606 krb5_error_code KRB5_LIB_FUNCTION
2607 krb5_enctype_to_string(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2608 krb5_enctype etype,
2609 char **string)
2610 {
2611 struct encryption_type *e;
2612 e = _find_enctype(etype);
2613 if(e == NULL) {
2614 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2615 N_("encryption type %d not supported", ""),
2616 etype);
2617 *string = NULL;
2618 return KRB5_PROG_ETYPE_NOSUPP;
2619 }
2620 *string = strdup(e->name);
2621 if(*string == NULL) {
2622 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2623 return ENOMEM;
2624 }
2625 return 0;
2626 }
2627
2628 krb5_error_code KRB5_LIB_FUNCTION
2629 krb5_string_to_enctype(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2630 const char *string,
2631 krb5_enctype *etype)
2632 {
2633 int i;
2634 for(i = 0; i < num_etypes; i++)
2635 if(strcasecmp(etypes[i]->name, string) == 0){
2636 *etype = etypes[i]->type;
2637 return 0;
2638 }
2639 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2640 N_("encryption type %s not supported", ""),
2641 string);
2642 return KRB5_PROG_ETYPE_NOSUPP;
2643 }
2644
2645 krb5_error_code KRB5_LIB_FUNCTION
2646 krb5_enctype_to_keytype(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2647 krb5_enctype etype,
2648 krb5_keytype *keytype)
2649 {
2650 struct encryption_type *e = _find_enctype(etype);
2651 if(e == NULL) {
2652 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2653 N_("encryption type %d not supported", ""),
2654 etype);
2655 return KRB5_PROG_ETYPE_NOSUPP;
2656 }
2657 *keytype = e->keytype->type; /* XXX */
2658 return 0;
2659 }
2660
2661 krb5_error_code KRB5_LIB_FUNCTION
2662 krb5_enctype_valid(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2663 krb5_enctype etype)
2664 {
2665 struct encryption_type *e = _find_enctype(etype);
2666 if(e == NULL) {
2667 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2668 N_("encryption type %d not supported", ""),
2669 etype);
2670 return KRB5_PROG_ETYPE_NOSUPP;
2671 }
2672 if (e->flags & F_DISABLED) {
2673 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2674 N_("encryption type %s is disabled", ""),
2675 e->name);
2676 return KRB5_PROG_ETYPE_NOSUPP;
2677 }
2678 return 0;
2679 }
2680
2681 /**
2682 * Return the coresponding encryption type for a checksum type.
2683 *
2684 * @param context Kerberos context
2685 * @param ctype The checksum type to get the result enctype for
2686 * @param etype The returned encryption, when the matching etype is
2687 * not found, etype is set to ETYPE_NULL.
2688 *
2689 * @return Return an error code for an failure or 0 on success.
2690 * @ingroup krb5_crypto
2691 */
2692
2693
2694 krb5_error_code KRB5_LIB_FUNCTION
2695 krb5_cksumtype_to_enctype(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2696 krb5_cksumtype ctype,
2697 krb5_enctype *etype)
2698 {
2699 int i;
2700
2701 *etype = ETYPE_NULL;
2702
2703 for(i = 0; i < num_etypes; i++) {
2704 if(etypes[i]->keyed_checksum &&
2705 etypes[i]->keyed_checksum->type == ctype)
2706 {
2707 *etype = etypes[i]->type;
2708 return 0;
2709 }
2710 }
2711
2712 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2713 N_("checksum type %d not supported", ""),
2714 (int)ctype);
2715 return KRB5_PROG_SUMTYPE_NOSUPP;
2716 }
2717
2718
2719 krb5_error_code KRB5_LIB_FUNCTION
2720 krb5_cksumtype_valid(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2721 krb5_cksumtype ctype)
2722 {
2723 struct checksum_type *c = _find_checksum(ctype);
2724 if (c == NULL) {
2725 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2726 N_("checksum type %d not supported", ""),
2727 ctype);
2728 return KRB5_PROG_SUMTYPE_NOSUPP;
2729 }
2730 if (c->flags & F_DISABLED) {
2731 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2732 N_("checksum type %s is disabled", ""),
2733 c->name);
2734 return KRB5_PROG_SUMTYPE_NOSUPP;
2735 }
2736 return 0;
2737 }
2738
2739
2740 /* if two enctypes have compatible keys */
2741 krb5_boolean KRB5_LIB_FUNCTION
2742 krb5_enctypes_compatible_keys(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2743 krb5_enctype etype1,
2744 krb5_enctype etype2)
2745 {
2746 struct encryption_type *e1 = _find_enctype(etype1);
2747 struct encryption_type *e2 = _find_enctype(etype2);
2748 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2749 }
2750
2751 static krb5_boolean
2752 derived_crypto(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2753 krb5_crypto crypto)
2754 {
2755 return (crypto->et->flags & F_DERIVED) != 0;
2756 }
2757
2758 static krb5_boolean
2759 special_crypto(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2760 krb5_crypto crypto)
2761 {
2762 return (crypto->et->flags & F_SPECIAL) != 0;
2763 }
2764
2765 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2766 #define CHECKSUMTYPE(C) ((C)->type)
2767
2768 static krb5_error_code
2769 encrypt_internal_derived(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2770 krb5_crypto crypto,
2771 unsigned usage,
2772 const void *data,
2773 size_t len,
2774 krb5_data *result,
2775 void *ivec)
2776 {
2777 size_t sz, block_sz, checksum_sz, total_sz;
2778 Checksum cksum;
2779 unsigned char *p, *q;
2780 krb5_error_code ret;
2781 struct key_data *dkey;
2782 const struct encryption_type *et = crypto->et;
2783
2784 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2785
2786 sz = et->confoundersize + len;
2787 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2788 total_sz = block_sz + checksum_sz;
2789 p = calloc(1, total_sz);
2790 if(p == NULL) {
2791 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2792 return ENOMEM;
2793 }
2794
2795 q = p;
2796 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2797 q += et->confoundersize;
2798 memcpy(q, data, len);
2799
2800 ret = create_checksum(context,
2801 et->keyed_checksum,
2802 crypto,
2803 INTEGRITY_USAGE(usage),
2804 p,
2805 block_sz,
2806 &cksum);
2807 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2808 free_Checksum (&cksum);
2809 krb5_clear_error_message (context);
2810 ret = KRB5_CRYPTO_INTERNAL;
2811 }
2812 if(ret)
2813 goto fail;
2814 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2815 free_Checksum (&cksum);
2816 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2817 if(ret)
2818 goto fail;
2819 ret = _key_schedule(context, dkey);
2820 if(ret)
2821 goto fail;
2822 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2823 if (ret)
2824 goto fail;
2825 result->data = p;
2826 result->length = total_sz;
2827 return 0;
2828 fail:
2829 memset(p, 0, total_sz);
2830 free(p);
2831 return ret;
2832 }
2833
2834
2835 static krb5_error_code
2836 encrypt_internal(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2837 krb5_crypto crypto,
2838 const void *data,
2839 size_t len,
2840 krb5_data *result,
2841 void *ivec)
2842 {
2843 size_t sz, block_sz, checksum_sz;
2844 Checksum cksum;
2845 unsigned char *p, *q;
2846 krb5_error_code ret;
2847 const struct encryption_type *et = crypto->et;
2848
2849 checksum_sz = CHECKSUMSIZE(et->checksum);
2850
2851 sz = et->confoundersize + checksum_sz + len;
2852 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2853 p = calloc(1, block_sz);
2854 if(p == NULL) {
2855 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2856 return ENOMEM;
2857 }
2858
2859 q = p;
2860 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2861 q += et->confoundersize;
2862 memset(q, 0, checksum_sz);
2863 q += checksum_sz;
2864 memcpy(q, data, len);
2865
2866 ret = create_checksum(context,
2867 et->checksum,
2868 crypto,
2869 0,
2870 p,
2871 block_sz,
2872 &cksum);
2873 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2874 krb5_clear_error_message (context);
2875 free_Checksum(&cksum);
2876 ret = KRB5_CRYPTO_INTERNAL;
2877 }
2878 if(ret)
2879 goto fail;
2880 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2881 free_Checksum(&cksum);
2882 ret = _key_schedule(context, &crypto->key);
2883 if(ret)
2884 goto fail;
2885 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2886 if (ret) {
2887 memset(p, 0, block_sz);
2888 free(p);
2889 return ret;
2890 }
2891 result->data = p;
2892 result->length = block_sz;
2893 return 0;
2894 fail:
2895 memset(p, 0, block_sz);
2896 free(p);
2897 return ret;
2898 }
2899
2900 static krb5_error_code
2901 encrypt_internal_special(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2902 krb5_crypto crypto,
2903 int usage,
2904 const void *data,
2905 size_t len,
2906 krb5_data *result,
2907 void *ivec)
2908 {
2909 struct encryption_type *et = crypto->et;
2910 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2911 size_t sz = len + cksum_sz + et->confoundersize;
2912 char *tmp, *p;
2913 krb5_error_code ret;
2914
2915 tmp = malloc (sz);
2916 if (tmp == NULL) {
2917 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2918 return ENOMEM;
2919 }
2920 p = tmp;
2921 memset (p, 0, cksum_sz);
2922 p += cksum_sz;
2923 krb5_generate_random_block(p, et->confoundersize);
2924 p += et->confoundersize;
2925 memcpy (p, data, len);
2926 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2927 if (ret) {
2928 memset(tmp, 0, sz);
2929 free(tmp);
2930 return ret;
2931 }
2932 result->data = tmp;
2933 result->length = sz;
2934 return 0;
2935 }
2936
2937 static krb5_error_code
2938 decrypt_internal_derived(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
2939 krb5_crypto crypto,
2940 unsigned usage,
2941 void *data,
2942 size_t len,
2943 krb5_data *result,
2944 void *ivec)
2945 {
2946 size_t checksum_sz;
2947 Checksum cksum;
2948 unsigned char *p;
2949 krb5_error_code ret;
2950 struct key_data *dkey;
2951 struct encryption_type *et = crypto->et;
2952 unsigned long l;
2953
2954 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2955 if (len < checksum_sz + et->confoundersize) {
2956 krb5_set_error_message(context, KRB5_BAD_MSIZE,
2957 N_("Encrypted data shorter then "
2958 "checksum + confunder", ""));
2959 return KRB5_BAD_MSIZE;
2960 }
2961
2962 if (((len - checksum_sz) % et->padsize) != 0) {
2963 krb5_clear_error_message(context);
2964 return KRB5_BAD_MSIZE;
2965 }
2966
2967 p = malloc(len);
2968 if(len != 0 && p == NULL) {
2969 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2970 return ENOMEM;
2971 }
2972 memcpy(p, data, len);
2973
2974 len -= checksum_sz;
2975
2976 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2977 if(ret) {
2978 free(p);
2979 return ret;
2980 }
2981 ret = _key_schedule(context, dkey);
2982 if(ret) {
2983 free(p);
2984 return ret;
2985 }
2986 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
2987 if (ret) {
2988 free(p);
2989 return ret;
2990 }
2991
2992 cksum.checksum.data = p + len;
2993 cksum.checksum.length = checksum_sz;
2994 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
2995
2996 ret = verify_checksum(context,
2997 crypto,
2998 INTEGRITY_USAGE(usage),
2999 p,
3000 len,
3001 &cksum);
3002 if(ret) {
3003 free(p);
3004 return ret;
3005 }
3006 l = len - et->confoundersize;
3007 memmove(p, p + et->confoundersize, l);
3008 result->data = realloc(p, l);
3009 if(result->data == NULL && l != 0) {
3010 free(p);
3011 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3012 return ENOMEM;
3013 }
3014 result->length = l;
3015 return 0;
3016 }
3017
3018 static krb5_error_code
3019 decrypt_internal(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3020 krb5_crypto crypto,
3021 void *data,
3022 size_t len,
3023 krb5_data *result,
3024 void *ivec)
3025 {
3026 krb5_error_code ret;
3027 unsigned char *p;
3028 Checksum cksum;
3029 size_t checksum_sz, l;
3030 struct encryption_type *et = crypto->et;
3031
3032 if ((len % et->padsize) != 0) {
3033 krb5_clear_error_message(context);
3034 return KRB5_BAD_MSIZE;
3035 }
3036
3037 checksum_sz = CHECKSUMSIZE(et->checksum);
3038 p = malloc(len);
3039 if(len != 0 && p == NULL) {
3040 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3041 return ENOMEM;
3042 }
3043 memcpy(p, data, len);
3044
3045 ret = _key_schedule(context, &crypto->key);
3046 if(ret) {
3047 free(p);
3048 return ret;
3049 }
3050 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3051 if (ret) {
3052 free(p);
3053 return ret;
3054 }
3055 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3056 if(ret) {
3057 free(p);
3058 return ret;
3059 }
3060 memset(p + et->confoundersize, 0, checksum_sz);
3061 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3062 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3063 free_Checksum(&cksum);
3064 if(ret) {
3065 free(p);
3066 return ret;
3067 }
3068 l = len - et->confoundersize - checksum_sz;
3069 memmove(p, p + et->confoundersize + checksum_sz, l);
3070 result->data = realloc(p, l);
3071 if(result->data == NULL && l != 0) {
3072 free(p);
3073 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3074 return ENOMEM;
3075 }
3076 result->length = l;
3077 return 0;
3078 }
3079
3080 static krb5_error_code
3081 decrypt_internal_special(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3082 krb5_crypto crypto,
3083 int usage,
3084 void *data,
3085 size_t len,
3086 krb5_data *result,
3087 void *ivec)
3088 {
3089 struct encryption_type *et = crypto->et;
3090 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3091 size_t sz = len - cksum_sz - et->confoundersize;
3092 unsigned char *p;
3093 krb5_error_code ret;
3094
3095 if ((len % et->padsize) != 0) {
3096 krb5_clear_error_message(context);
3097 return KRB5_BAD_MSIZE;
3098 }
3099
3100 p = malloc (len);
3101 if (p == NULL) {
3102 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3103 return ENOMEM;
3104 }
3105 memcpy(p, data, len);
3106
3107 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3108 if (ret) {
3109 free(p);
3110 return ret;
3111 }
3112
3113 memmove (p, p + cksum_sz + et->confoundersize, sz);
3114 result->data = realloc(p, sz);
3115 if(result->data == NULL && sz != 0) {
3116 free(p);
3117 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3118 return ENOMEM;
3119 }
3120 result->length = sz;
3121 return 0;
3122 }
3123
3124 static krb5_crypto_iov *
3125 find_iv(krb5_crypto_iov *data, int num_data, int type)
/* [<][>][^][v][top][bottom][index][help] */
3126 {
3127 int i;
3128 for (i = 0; i < num_data; i++)
3129 if (data[i].flags == type)
3130 return &data[i];
3131 return NULL;
3132 }
3133
3134 /**
3135 * Inline encrypt a kerberos message
3136 *
3137 * @param context Kerberos context
3138 * @param crypto Kerberos crypto context
3139 * @param usage Key usage for this buffer
3140 * @param data array of buffers to process
3141 * @param num_data length of array
3142 * @param ivec initial cbc/cts vector
3143 *
3144 * @return Return an error code or 0.
3145 * @ingroup krb5_crypto
3146 *
3147 * Kerberos encrypted data look like this:
3148 *
3149 * 1. KRB5_CRYPTO_TYPE_HEADER
3150 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3151 * any order, however the receiver have to aware of the
3152 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
3153 * trailers.
3154 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3155 * 4. KRB5_CRYPTO_TYPE_TRAILER
3156 */
3157
3158 krb5_error_code KRB5_LIB_FUNCTION
3159 krb5_encrypt_iov_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3160 krb5_crypto crypto,
3161 unsigned usage,
3162 krb5_crypto_iov *data,
3163 size_t num_data,
3164 void *ivec)
3165 {
3166 size_t headersz, trailersz, len;
3167 size_t i, sz, block_sz, pad_sz;
3168 Checksum cksum;
3169 unsigned char *p, *q;
3170 krb5_error_code ret;
3171 struct key_data *dkey;
3172 const struct encryption_type *et = crypto->et;
3173 krb5_crypto_iov *tiv, *piv, *hiv;
3174
3175 if(!derived_crypto(context, crypto)) {
3176 krb5_clear_error_message(context);
3177 return KRB5_CRYPTO_INTERNAL;
3178 }
3179
3180 headersz = et->confoundersize;
3181 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3182
3183 for (len = 0, i = 0; i < num_data; i++) {
3184 if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3185 data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
3186 len += data[i].data.length;
3187 }
3188 }
3189
3190 sz = headersz + len;
3191 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3192
3193 pad_sz = block_sz - sz;
3194 trailersz += pad_sz;
3195
3196 /* header */
3197
3198 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3199 if (hiv == NULL || hiv->data.length != headersz)
3200 return KRB5_BAD_MSIZE;
3201
3202 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3203
3204 /* padding */
3205
3206 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3207 /* its ok to have no TYPE_PADDING if there is no padding */
3208 if (piv == NULL && pad_sz != 0)
3209 return KRB5_BAD_MSIZE;
3210 if (piv) {
3211 if (piv->data.length < pad_sz)
3212 return KRB5_BAD_MSIZE;
3213 piv->data.length = pad_sz;
3214 }
3215
3216
3217 /* trailer */
3218
3219 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3220 if (tiv == NULL || tiv->data.length != trailersz)
3221 return KRB5_BAD_MSIZE;
3222
3223
3224 /*
3225 * XXX replace with EVP_Sign? at least make create_checksum an iov
3226 * function.
3227 * XXX CTS EVP is broken, can't handle multi buffers :(
3228 */
3229
3230 len = hiv->data.length;
3231 for (i = 0; i < num_data; i++) {
3232 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3233 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3234 continue;
3235 len += data[i].data.length;
3236 }
3237
3238 p = q = malloc(len);
3239
3240 memcpy(q, hiv->data.data, hiv->data.length);
3241 q += hiv->data.length;
3242 for (i = 0; i < num_data; i++) {
3243 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3244 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3245 continue;
3246 memcpy(q, data[i].data.data, data[i].data.length);
3247 q += data[i].data.length;
3248 }
3249
3250 ret = create_checksum(context,
3251 et->keyed_checksum,
3252 crypto,
3253 INTEGRITY_USAGE(usage),
3254 p,
3255 len,
3256 &cksum);
3257 free(p);
3258 if(ret == 0 && cksum.checksum.length != trailersz) {
3259 free_Checksum (&cksum);
3260 krb5_clear_error_message (context);
3261 ret = KRB5_CRYPTO_INTERNAL;
3262 }
3263 if(ret)
3264 return ret;
3265
3266 /* save cksum at end */
3267 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3268 free_Checksum (&cksum);
3269
3270 /* now encrypt data */
3271
3272 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3273 if(ret)
3274 return ret;
3275 ret = _key_schedule(context, dkey);
3276 if(ret)
3277 return ret;
3278
3279 /* XXX replace with EVP_Cipher */
3280
3281 len = hiv->data.length;
3282 for (i = 0; i < num_data; i++) {
3283 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3284 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3285 continue;
3286 len += data[i].data.length;
3287 }
3288
3289 p = q = malloc(len);
3290 if(p == NULL)
3291 return ENOMEM;
3292
3293 memcpy(q, hiv->data.data, hiv->data.length);
3294 q += hiv->data.length;
3295 for (i = 0; i < num_data; i++) {
3296 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3297 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3298 continue;
3299 memcpy(q, data[i].data.data, data[i].data.length);
3300 q += data[i].data.length;
3301 }
3302
3303 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3304 if(ret) {
3305 free(p);
3306 return ret;
3307 }
3308 ret = _key_schedule(context, dkey);
3309 if(ret) {
3310 free(p);
3311 return ret;
3312 }
3313
3314 ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
3315 if (ret) {
3316 free(p);
3317 return ret;
3318 }
3319
3320 /* now copy data back to buffers */
3321 q = p;
3322 memcpy(hiv->data.data, q, hiv->data.length);
3323 q += hiv->data.length;
3324
3325 for (i = 0; i < num_data; i++) {
3326 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3327 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3328 continue;
3329 memcpy(data[i].data.data, q, data[i].data.length);
3330 q += data[i].data.length;
3331 }
3332 free(p);
3333
3334 return ret;
3335 }
3336
3337 /**
3338 * Inline decrypt a Kerberos message.
3339 *
3340 * @param context Kerberos context
3341 * @param crypto Kerberos crypto context
3342 * @param usage Key usage for this buffer
3343 * @param data array of buffers to process
3344 * @param num_data length of array
3345 * @param ivec initial cbc/cts vector
3346 *
3347 * @return Return an error code or 0.
3348 * @ingroup krb5_crypto
3349 *
3350 * 1. KRB5_CRYPTO_TYPE_HEADER
3351 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3352 * any order, however the receiver have to aware of the
3353 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3354 * protocol headers and trailers. The output data will be of same
3355 * size as the input data or shorter.
3356 */
3357
3358 krb5_error_code KRB5_LIB_FUNCTION
3359 krb5_decrypt_iov_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3360 krb5_crypto crypto,
3361 unsigned usage,
3362 krb5_crypto_iov *data,
3363 size_t num_data,
3364 void *ivec)
3365 {
3366 size_t headersz, trailersz, len;
3367 size_t i, sz, block_sz, pad_sz;
3368 Checksum cksum;
3369 unsigned char *p, *q;
3370 krb5_error_code ret;
3371 struct key_data *dkey;
3372 struct encryption_type *et = crypto->et;
3373 krb5_crypto_iov *tiv, *hiv;
3374
3375 if(!derived_crypto(context, crypto)) {
3376 krb5_clear_error_message(context);
3377 return KRB5_CRYPTO_INTERNAL;
3378 }
3379
3380 headersz = et->confoundersize;
3381 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3382
3383 for (len = 0, i = 0; i < num_data; i++)
3384 if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
3385 len += data[i].data.length;
3386
3387 sz = headersz + len;
3388 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3389
3390 pad_sz = block_sz - sz;
3391 trailersz += pad_sz;
3392
3393 /* header */
3394
3395 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3396 if (hiv == NULL || hiv->data.length < headersz)
3397 return KRB5_BAD_MSIZE;
3398 hiv->data.length = headersz;
3399
3400 /* trailer */
3401
3402 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3403 if (tiv == NULL || tiv->data.length < trailersz)
3404 return KRB5_BAD_MSIZE;
3405 tiv->data.length = trailersz;
3406
3407 /* body */
3408
3409 /* XXX replace with EVP_Cipher */
3410
3411 for (len = 0, i = 0; i < num_data; i++) {
3412 if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3413 data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3414 continue;
3415 len += data[i].data.length;
3416 }
3417
3418 p = q = malloc(len);
3419 if (p == NULL)
3420 return ENOMEM;
3421
3422 memcpy(q, hiv->data.data, hiv->data.length);
3423 q += hiv->data.length;
3424 for (i = 0; i < num_data; i++) {
3425 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3426 continue;
3427 memcpy(q, data[i].data.data, data[i].data.length);
3428 q += data[i].data.length;
3429 }
3430
3431 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3432 if(ret) {
3433 free(p);
3434 return ret;
3435 }
3436 ret = _key_schedule(context, dkey);
3437 if(ret) {
3438 free(p);
3439 return ret;
3440 }
3441
3442 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3443 if (ret) {
3444 free(p);
3445 return ret;
3446 }
3447
3448 /* XXX now copy data back to buffers */
3449 q = p;
3450 memcpy(hiv->data.data, q, hiv->data.length);
3451 q += hiv->data.length;
3452 len -= hiv->data.length;
3453
3454 for (i = 0; i < num_data; i++) {
3455 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3456 continue;
3457 if (len < data[i].data.length)
3458 data[i].data.length = len;
3459 memcpy(data[i].data.data, q, data[i].data.length);
3460 q += data[i].data.length;
3461 len -= data[i].data.length;
3462 }
3463 free(p);
3464 if (len)
3465 krb5_abortx(context, "data still in the buffer");
3466
3467 len = hiv->data.length;
3468 for (i = 0; i < num_data; i++) {
3469 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3470 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3471 continue;
3472 len += data[i].data.length;
3473 }
3474
3475 p = q = malloc(len);
3476
3477 memcpy(q, hiv->data.data, hiv->data.length);
3478 q += hiv->data.length;
3479 for (i = 0; i < num_data; i++) {
3480 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3481 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3482 continue;
3483 memcpy(q, data[i].data.data, data[i].data.length);
3484 q += data[i].data.length;
3485 }
3486
3487 cksum.checksum.data = tiv->data.data;
3488 cksum.checksum.length = tiv->data.length;
3489 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3490
3491 ret = verify_checksum(context,
3492 crypto,
3493 INTEGRITY_USAGE(usage),
3494 p,
3495 len,
3496 &cksum);
3497 free(p);
3498 return ret;
3499 }
3500
3501 /**
3502 * Create a Kerberos message checksum.
3503 *
3504 * @param context Kerberos context
3505 * @param crypto Kerberos crypto context
3506 * @param usage Key usage for this buffer
3507 * @param data array of buffers to process
3508 * @param num_data length of array
3509 * @param result output data
3510 *
3511 * @return Return an error code or 0.
3512 * @ingroup krb5_crypto
3513 */
3514
3515 krb5_error_code KRB5_LIB_FUNCTION
3516 krb5_create_checksum_iov(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3517 krb5_crypto crypto,
3518 unsigned usage,
3519 krb5_crypto_iov *data,
3520 size_t num_data,
3521 krb5_cksumtype *type)
3522 {
3523 Checksum cksum;
3524 krb5_crypto_iov *civ;
3525 krb5_error_code ret;
3526 unsigned int i;
3527 size_t len;
3528 char *p, *q;
3529
3530 if(!derived_crypto(context, crypto)) {
3531 krb5_clear_error_message(context);
3532 return KRB5_CRYPTO_INTERNAL;
3533 }
3534
3535 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3536 if (civ == NULL)
3537 return KRB5_BAD_MSIZE;
3538
3539 len = 0;
3540 for (i = 0; i < num_data; i++) {
3541 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3542 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3543 continue;
3544 len += data[i].data.length;
3545 }
3546
3547 p = q = malloc(len);
3548
3549 for (i = 0; i < num_data; i++) {
3550 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3551 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3552 continue;
3553 memcpy(q, data[i].data.data, data[i].data.length);
3554 q += data[i].data.length;
3555 }
3556
3557 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3558 free(p);
3559 if (ret)
3560 return ret;
3561
3562 if (type)
3563 *type = cksum.cksumtype;
3564
3565 if (cksum.checksum.length > civ->data.length) {
3566 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3567 N_("Checksum larger then input buffer", ""));
3568 free_Checksum(&cksum);
3569 return KRB5_BAD_MSIZE;
3570 }
3571
3572 civ->data.length = cksum.checksum.length;
3573 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3574 free_Checksum(&cksum);
3575
3576 return 0;
3577 }
3578
3579
3580 size_t KRB5_LIB_FUNCTION
3581 krb5_crypto_length(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3582 krb5_crypto crypto,
3583 int type)
3584 {
3585 if (!derived_crypto(context, crypto))
3586 return (size_t)-1;
3587 switch(type) {
3588 case KRB5_CRYPTO_TYPE_EMPTY:
3589 return 0;
3590 case KRB5_CRYPTO_TYPE_HEADER:
3591 return crypto->et->blocksize;
3592 case KRB5_CRYPTO_TYPE_PADDING:
3593 if (crypto->et->padsize > 1)
3594 return crypto->et->padsize;
3595 return 0;
3596 case KRB5_CRYPTO_TYPE_TRAILER:
3597 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3598 case KRB5_CRYPTO_TYPE_CHECKSUM:
3599 if (crypto->et->keyed_checksum)
3600 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3601 return CHECKSUMSIZE(crypto->et->checksum);
3602 }
3603 return (size_t)-1;
3604 }
3605
3606 krb5_error_code KRB5_LIB_FUNCTION
3607 krb5_encrypt_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3608 krb5_crypto crypto,
3609 unsigned usage,
3610 const void *data,
3611 size_t len,
3612 krb5_data *result,
3613 void *ivec)
3614 {
3615 if(derived_crypto(context, crypto))
3616 return encrypt_internal_derived(context, crypto, usage,
3617 data, len, result, ivec);
3618 else if (special_crypto(context, crypto))
3619 return encrypt_internal_special (context, crypto, usage,
3620 data, len, result, ivec);
3621 else
3622 return encrypt_internal(context, crypto, data, len, result, ivec);
3623 }
3624
3625 krb5_error_code KRB5_LIB_FUNCTION
3626 krb5_encrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3627 krb5_crypto crypto,
3628 unsigned usage,
3629 const void *data,
3630 size_t len,
3631 krb5_data *result)
3632 {
3633 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3634 }
3635
3636 krb5_error_code KRB5_LIB_FUNCTION
3637 krb5_encrypt_EncryptedData(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3638 krb5_crypto crypto,
3639 unsigned usage,
3640 void *data,
3641 size_t len,
3642 int kvno,
3643 EncryptedData *result)
3644 {
3645 result->etype = CRYPTO_ETYPE(crypto);
3646 if(kvno){
3647 ALLOC(result->kvno, 1);
3648 *result->kvno = kvno;
3649 }else
3650 result->kvno = NULL;
3651 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3652 }
3653
3654 krb5_error_code KRB5_LIB_FUNCTION
3655 krb5_decrypt_ivec(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3656 krb5_crypto crypto,
3657 unsigned usage,
3658 void *data,
3659 size_t len,
3660 krb5_data *result,
3661 void *ivec)
3662 {
3663 if(derived_crypto(context, crypto))
3664 return decrypt_internal_derived(context, crypto, usage,
3665 data, len, result, ivec);
3666 else if (special_crypto (context, crypto))
3667 return decrypt_internal_special(context, crypto, usage,
3668 data, len, result, ivec);
3669 else
3670 return decrypt_internal(context, crypto, data, len, result, ivec);
3671 }
3672
3673 krb5_error_code KRB5_LIB_FUNCTION
3674 krb5_decrypt(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3675 krb5_crypto crypto,
3676 unsigned usage,
3677 void *data,
3678 size_t len,
3679 krb5_data *result)
3680 {
3681 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3682 NULL);
3683 }
3684
3685 krb5_error_code KRB5_LIB_FUNCTION
3686 krb5_decrypt_EncryptedData(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3687 krb5_crypto crypto,
3688 unsigned usage,
3689 const EncryptedData *e,
3690 krb5_data *result)
3691 {
3692 return krb5_decrypt(context, crypto, usage,
3693 e->cipher.data, e->cipher.length, result);
3694 }
3695
3696 /************************************************************
3697 * *
3698 ************************************************************/
3699
3700 #define ENTROPY_NEEDED 128
3701
3702 static int
3703 seed_something(void)
/* [<][>][^][v][top][bottom][index][help] */
3704 {
3705 char buf[1024], seedfile[256];
3706
3707 /* If there is a seed file, load it. But such a file cannot be trusted,
3708 so use 0 for the entropy estimate */
3709 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3710 int fd;
3711 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3712 if (fd >= 0) {
3713 ssize_t ret;
3714 rk_cloexec(fd);
3715 ret = read(fd, buf, sizeof(buf));
3716 if (ret > 0)
3717 RAND_add(buf, ret, 0.0);
3718 close(fd);
3719 } else
3720 seedfile[0] = '\0';
3721 } else
3722 seedfile[0] = '\0';
3723
3724 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3725 we do not have to deal with it. */
3726 if (RAND_status() != 1) {
3727 krb5_context context;
3728 const char *p;
3729
3730 /* Try using egd */
3731 if (!krb5_init_context(&context)) {
3732 p = krb5_config_get_string(context, NULL, "libdefaults",
3733 "egd_socket", NULL);
3734 if (p != NULL)
3735 RAND_egd_bytes(p, ENTROPY_NEEDED);
3736 krb5_free_context(context);
3737 }
3738 }
3739
3740 if (RAND_status() == 1) {
3741 /* Update the seed file */
3742 if (seedfile[0])
3743 RAND_write_file(seedfile);
3744
3745 return 0;
3746 } else
3747 return -1;
3748 }
3749
3750 void KRB5_LIB_FUNCTION
3751 krb5_generate_random_block(void *buf, size_t len)
/* [<][>][^][v][top][bottom][index][help] */
3752 {
3753 static int rng_initialized = 0;
3754
3755 HEIMDAL_MUTEX_lock(&crypto_mutex);
3756 if (!rng_initialized) {
3757 if (seed_something())
3758 krb5_abortx(NULL, "Fatal: could not seed the "
3759 "random number generator");
3760
3761 rng_initialized = 1;
3762 }
3763 HEIMDAL_MUTEX_unlock(&crypto_mutex);
3764 if (RAND_bytes(buf, len) != 1)
3765 krb5_abortx(NULL, "Failed to generate random block");
3766 }
3767
3768 static void
3769 DES3_postproc(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3770 unsigned char *k, size_t len, struct key_data *key)
3771 {
3772 DES3_random_to_key(context, key->key, k, len);
3773
3774 if (key->schedule) {
3775 krb5_free_data(context, key->schedule);
3776 key->schedule = NULL;
3777 }
3778 }
3779
3780 static krb5_error_code
3781 derive_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3782 struct encryption_type *et,
3783 struct key_data *key,
3784 const void *constant,
3785 size_t len)
3786 {
3787 unsigned char *k;
3788 unsigned int nblocks = 0, i;
3789 krb5_error_code ret = 0;
3790 struct key_type *kt = et->keytype;
3791
3792 ret = _key_schedule(context, key);
3793 if(ret)
3794 return ret;
3795 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3796 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3797 k = malloc(nblocks * et->blocksize);
3798 if(k == NULL) {
3799 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3800 return ENOMEM;
3801 }
3802 ret = _krb5_n_fold(constant, len, k, et->blocksize);
3803 if (ret) {
3804 free(k);
3805 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3806 return ret;
3807 }
3808 for(i = 0; i < nblocks; i++) {
3809 if(i > 0)
3810 memcpy(k + i * et->blocksize,
3811 k + (i - 1) * et->blocksize,
3812 et->blocksize);
3813 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
3814 1, 0, NULL);
3815 }
3816 } else {
3817 /* this case is probably broken, but won't be run anyway */
3818 void *c = malloc(len);
3819 size_t res_len = (kt->bits + 7) / 8;
3820
3821 if(len != 0 && c == NULL) {
3822 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3823 return ENOMEM;
3824 }
3825 memcpy(c, constant, len);
3826 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
3827 k = malloc(res_len);
3828 if(res_len != 0 && k == NULL) {
3829 free(c);
3830 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3831 return ENOMEM;
3832 }
3833 ret = _krb5_n_fold(c, len, k, res_len);
3834 if (ret) {
3835 free(k);
3836 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3837 return ret;
3838 }
3839 free(c);
3840 }
3841
3842 /* XXX keytype dependent post-processing */
3843 switch(kt->type) {
3844 case KEYTYPE_DES3:
3845 DES3_postproc(context, k, nblocks * et->blocksize, key);
3846 break;
3847 case KEYTYPE_AES128:
3848 case KEYTYPE_AES256:
3849 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3850 break;
3851 default:
3852 ret = KRB5_CRYPTO_INTERNAL;
3853 krb5_set_error_message(context, ret,
3854 N_("derive_key() called with unknown keytype (%u)", ""),
3855 kt->type);
3856 break;
3857 }
3858 if (key->schedule) {
3859 krb5_free_data(context, key->schedule);
3860 key->schedule = NULL;
3861 }
3862 memset(k, 0, nblocks * et->blocksize);
3863 free(k);
3864 return ret;
3865 }
3866
3867 static struct key_data *
3868 _new_derived_key(krb5_crypto crypto, unsigned usage)
/* [<][>][^][v][top][bottom][index][help] */
3869 {
3870 struct key_usage *d = crypto->key_usage;
3871 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
3872 if(d == NULL)
3873 return NULL;
3874 crypto->key_usage = d;
3875 d += crypto->num_key_usage++;
3876 memset(d, 0, sizeof(*d));
3877 d->usage = usage;
3878 return &d->key;
3879 }
3880
3881 krb5_error_code KRB5_LIB_FUNCTION
3882 krb5_derive_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3883 const krb5_keyblock *key,
3884 krb5_enctype etype,
3885 const void *constant,
3886 size_t constant_len,
3887 krb5_keyblock **derived_key)
3888 {
3889 krb5_error_code ret;
3890 struct encryption_type *et;
3891 struct key_data d;
3892
3893 *derived_key = NULL;
3894
3895 et = _find_enctype (etype);
3896 if (et == NULL) {
3897 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3898 N_("encryption type %d not supported", ""),
3899 etype);
3900 return KRB5_PROG_ETYPE_NOSUPP;
3901 }
3902
3903 ret = krb5_copy_keyblock(context, key, &d.key);
3904 if (ret)
3905 return ret;
3906
3907 d.schedule = NULL;
3908 ret = derive_key(context, et, &d, constant, constant_len);
3909 if (ret == 0)
3910 ret = krb5_copy_keyblock(context, d.key, derived_key);
3911 free_key_data(context, &d, et);
3912 return ret;
3913 }
3914
3915 static krb5_error_code
3916 _get_derived_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3917 krb5_crypto crypto,
3918 unsigned usage,
3919 struct key_data **key)
3920 {
3921 int i;
3922 struct key_data *d;
3923 unsigned char constant[5];
3924
3925 for(i = 0; i < crypto->num_key_usage; i++)
3926 if(crypto->key_usage[i].usage == usage) {
3927 *key = &crypto->key_usage[i].key;
3928 return 0;
3929 }
3930 d = _new_derived_key(crypto, usage);
3931 if(d == NULL) {
3932 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3933 return ENOMEM;
3934 }
3935 krb5_copy_keyblock(context, crypto->key.key, &d->key);
3936 _krb5_put_int(constant, usage, 5);
3937 derive_key(context, crypto->et, d, constant, sizeof(constant));
3938 *key = d;
3939 return 0;
3940 }
3941
3942
3943 krb5_error_code KRB5_LIB_FUNCTION
3944 krb5_crypto_init(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
3945 const krb5_keyblock *key,
3946 krb5_enctype etype,
3947 krb5_crypto *crypto)
3948 {
3949 krb5_error_code ret;
3950 ALLOC(*crypto, 1);
3951 if(*crypto == NULL) {
3952 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3953 return ENOMEM;
3954 }
3955 if(etype == ETYPE_NULL)
3956 etype = key->keytype;
3957 (*crypto)->et = _find_enctype(etype);
3958 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
3959 free(*crypto);
3960 *crypto = NULL;
3961 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
3962 N_("encryption type %d not supported", ""),
3963 etype);
3964 return KRB5_PROG_ETYPE_NOSUPP;
3965 }
3966 if((*crypto)->et->keytype->size != key->keyvalue.length) {
3967 free(*crypto);
3968 *crypto = NULL;
3969 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
3970 "encryption key has bad length");
3971 return KRB5_BAD_KEYSIZE;
3972 }
3973 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
3974 if(ret) {
3975 free(*crypto);
3976 *crypto = NULL;
3977 return ret;
3978 }
3979 (*crypto)->key.schedule = NULL;
3980 (*crypto)->num_key_usage = 0;
3981 (*crypto)->key_usage = NULL;
3982 return 0;
3983 }
3984
3985 static void
3986 free_key_data(krb5_context context, struct key_data *key,
/* [<][>][^][v][top][bottom][index][help] */
3987 struct encryption_type *et)
3988 {
3989 krb5_free_keyblock(context, key->key);
3990 if(key->schedule) {
3991 if (et->keytype->cleanup)
3992 (*et->keytype->cleanup)(context, key);
3993 memset(key->schedule->data, 0, key->schedule->length);
3994 krb5_free_data(context, key->schedule);
3995 }
3996 }
3997
3998 static void
3999 free_key_usage(krb5_context context, struct key_usage *ku,
/* [<][>][^][v][top][bottom][index][help] */
4000 struct encryption_type *et)
4001 {
4002 free_key_data(context, &ku->key, et);
4003 }
4004
4005 krb5_error_code KRB5_LIB_FUNCTION
4006 krb5_crypto_destroy(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4007 krb5_crypto crypto)
4008 {
4009 int i;
4010
4011 for(i = 0; i < crypto->num_key_usage; i++)
4012 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4013 free(crypto->key_usage);
4014 free_key_data(context, &crypto->key, crypto->et);
4015 free (crypto);
4016 return 0;
4017 }
4018
4019 krb5_error_code KRB5_LIB_FUNCTION
4020 krb5_crypto_getblocksize(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4021 krb5_crypto crypto,
4022 size_t *blocksize)
4023 {
4024 *blocksize = crypto->et->blocksize;
4025 return 0;
4026 }
4027
4028 krb5_error_code KRB5_LIB_FUNCTION
4029 krb5_crypto_getenctype(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4030 krb5_crypto crypto,
4031 krb5_enctype *enctype)
4032 {
4033 *enctype = crypto->et->type;
4034 return 0;
4035 }
4036
4037 krb5_error_code KRB5_LIB_FUNCTION
4038 krb5_crypto_getpadsize(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4039 krb5_crypto crypto,
4040 size_t *padsize)
4041 {
4042 *padsize = crypto->et->padsize;
4043 return 0;
4044 }
4045
4046 krb5_error_code KRB5_LIB_FUNCTION
4047 krb5_crypto_getconfoundersize(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4048 krb5_crypto crypto,
4049 size_t *confoundersize)
4050 {
4051 *confoundersize = crypto->et->confoundersize;
4052 return 0;
4053 }
4054
4055
4056 /**
4057 * Disable encryption type
4058 *
4059 * @param context Kerberos 5 context
4060 * @param enctype encryption type to disable
4061 *
4062 * @return Return an error code or 0.
4063 *
4064 * @ingroup krb5_crypto
4065 */
4066
4067 krb5_error_code KRB5_LIB_FUNCTION
4068 krb5_enctype_disable(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4069 krb5_enctype enctype)
4070 {
4071 struct encryption_type *et = _find_enctype(enctype);
4072 if(et == NULL) {
4073 if (context)
4074 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4075 N_("encryption type %d not supported", ""),
4076 enctype);
4077 return KRB5_PROG_ETYPE_NOSUPP;
4078 }
4079 et->flags |= F_DISABLED;
4080 return 0;
4081 }
4082
4083 /**
4084 * Enable encryption type
4085 *
4086 * @param context Kerberos 5 context
4087 * @param enctype encryption type to enable
4088 *
4089 * @return Return an error code or 0.
4090 *
4091 * @ingroup krb5_crypto
4092 */
4093
4094 krb5_error_code KRB5_LIB_FUNCTION
4095 krb5_enctype_enable(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4096 krb5_enctype enctype)
4097 {
4098 struct encryption_type *et = _find_enctype(enctype);
4099 if(et == NULL) {
4100 if (context)
4101 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4102 N_("encryption type %d not supported", ""),
4103 enctype);
4104 return KRB5_PROG_ETYPE_NOSUPP;
4105 }
4106 et->flags &= ~F_DISABLED;
4107 return 0;
4108 }
4109
4110
4111 krb5_error_code KRB5_LIB_FUNCTION
4112 krb5_string_to_key_derived(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4113 const void *str,
4114 size_t len,
4115 krb5_enctype etype,
4116 krb5_keyblock *key)
4117 {
4118 struct encryption_type *et = _find_enctype(etype);
4119 krb5_error_code ret;
4120 struct key_data kd;
4121 size_t keylen;
4122 u_char *tmp;
4123
4124 if(et == NULL) {
4125 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4126 N_("encryption type %d not supported", ""),
4127 etype);
4128 return KRB5_PROG_ETYPE_NOSUPP;
4129 }
4130 keylen = et->keytype->bits / 8;
4131
4132 ALLOC(kd.key, 1);
4133 if(kd.key == NULL) {
4134 krb5_set_error_message (context, ENOMEM,
4135 N_("malloc: out of memory", ""));
4136 return ENOMEM;
4137 }
4138 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4139 if(ret) {
4140 free(kd.key);
4141 return ret;
4142 }
4143 kd.key->keytype = etype;
4144 tmp = malloc (keylen);
4145 if(tmp == NULL) {
4146 krb5_free_keyblock(context, kd.key);
4147 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4148 return ENOMEM;
4149 }
4150 ret = _krb5_n_fold(str, len, tmp, keylen);
4151 if (ret) {
4152 free(tmp);
4153 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4154 return ret;
4155 }
4156 kd.schedule = NULL;
4157 DES3_postproc (context, tmp, keylen, &kd); /* XXX */
4158 memset(tmp, 0, keylen);
4159 free(tmp);
4160 ret = derive_key(context,
4161 et,
4162 &kd,
4163 "kerberos", /* XXX well known constant */
4164 strlen("kerberos"));
4165 if (ret) {
4166 free_key_data(context, &kd, et);
4167 return ret;
4168 }
4169 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4170 free_key_data(context, &kd, et);
4171 return ret;
4172 }
4173
4174 static size_t
4175 wrapped_length (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4176 krb5_crypto crypto,
4177 size_t data_len)
4178 {
4179 struct encryption_type *et = crypto->et;
4180 size_t padsize = et->padsize;
4181 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4182 size_t res;
4183
4184 res = et->confoundersize + checksumsize + data_len;
4185 res = (res + padsize - 1) / padsize * padsize;
4186 return res;
4187 }
4188
4189 static size_t
4190 wrapped_length_dervied (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4191 krb5_crypto crypto,
4192 size_t data_len)
4193 {
4194 struct encryption_type *et = crypto->et;
4195 size_t padsize = et->padsize;
4196 size_t res;
4197
4198 res = et->confoundersize + data_len;
4199 res = (res + padsize - 1) / padsize * padsize;
4200 if (et->keyed_checksum)
4201 res += et->keyed_checksum->checksumsize;
4202 else
4203 res += et->checksum->checksumsize;
4204 return res;
4205 }
4206
4207 /*
4208 * Return the size of an encrypted packet of length `data_len'
4209 */
4210
4211 size_t
4212 krb5_get_wrapped_length (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4213 krb5_crypto crypto,
4214 size_t data_len)
4215 {
4216 if (derived_crypto (context, crypto))
4217 return wrapped_length_dervied (context, crypto, data_len);
4218 else
4219 return wrapped_length (context, crypto, data_len);
4220 }
4221
4222 /*
4223 * Return the size of an encrypted packet of length `data_len'
4224 */
4225
4226 static size_t
4227 crypto_overhead (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4228 krb5_crypto crypto)
4229 {
4230 struct encryption_type *et = crypto->et;
4231 size_t res;
4232
4233 res = CHECKSUMSIZE(et->checksum);
4234 res += et->confoundersize;
4235 if (et->padsize > 1)
4236 res += et->padsize;
4237 return res;
4238 }
4239
4240 static size_t
4241 crypto_overhead_dervied (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4242 krb5_crypto crypto)
4243 {
4244 struct encryption_type *et = crypto->et;
4245 size_t res;
4246
4247 if (et->keyed_checksum)
4248 res = CHECKSUMSIZE(et->keyed_checksum);
4249 else
4250 res = CHECKSUMSIZE(et->checksum);
4251 res += et->confoundersize;
4252 if (et->padsize > 1)
4253 res += et->padsize;
4254 return res;
4255 }
4256
4257 size_t
4258 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
/* [<][>][^][v][top][bottom][index][help] */
4259 {
4260 if (derived_crypto (context, crypto))
4261 return crypto_overhead_dervied (context, crypto);
4262 else
4263 return crypto_overhead (context, crypto);
4264 }
4265
4266 krb5_error_code KRB5_LIB_FUNCTION
4267 krb5_random_to_key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4268 krb5_enctype type,
4269 const void *data,
4270 size_t size,
4271 krb5_keyblock *key)
4272 {
4273 krb5_error_code ret;
4274 struct encryption_type *et = _find_enctype(type);
4275 if(et == NULL) {
4276 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4277 N_("encryption type %d not supported", ""),
4278 type);
4279 return KRB5_PROG_ETYPE_NOSUPP;
4280 }
4281 if ((et->keytype->bits + 7) / 8 > size) {
4282 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4283 N_("encryption key %s needs %d bytes "
4284 "of random to make an encryption key "
4285 "out of it", ""),
4286 et->name, (int)et->keytype->size);
4287 return KRB5_PROG_ETYPE_NOSUPP;
4288 }
4289 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4290 if(ret)
4291 return ret;
4292 key->keytype = type;
4293 if (et->keytype->random_to_key)
4294 (*et->keytype->random_to_key)(context, key, data, size);
4295 else
4296 memcpy(key->keyvalue.data, data, et->keytype->size);
4297
4298 return 0;
4299 }
4300
4301 krb5_error_code
4302 _krb5_pk_octetstring2key(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4303 krb5_enctype type,
4304 const void *dhdata,
4305 size_t dhsize,
4306 const heim_octet_string *c_n,
4307 const heim_octet_string *k_n,
4308 krb5_keyblock *key)
4309 {
4310 struct encryption_type *et = _find_enctype(type);
4311 krb5_error_code ret;
4312 size_t keylen, offset;
4313 void *keydata;
4314 unsigned char counter;
4315 unsigned char shaoutput[20];
4316
4317 if(et == NULL) {
4318 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4319 N_("encryption type %d not supported", ""),
4320 type);
4321 return KRB5_PROG_ETYPE_NOSUPP;
4322 }
4323 keylen = (et->keytype->bits + 7) / 8;
4324
4325 keydata = malloc(keylen);
4326 if (keydata == NULL) {
4327 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4328 return ENOMEM;
4329 }
4330
4331 counter = 0;
4332 offset = 0;
4333 do {
4334 SHA_CTX m;
4335
4336 SHA1_Init(&m);
4337 SHA1_Update(&m, &counter, 1);
4338 SHA1_Update(&m, dhdata, dhsize);
4339 if (c_n)
4340 SHA1_Update(&m, c_n->data, c_n->length);
4341 if (k_n)
4342 SHA1_Update(&m, k_n->data, k_n->length);
4343 SHA1_Final(shaoutput, &m);
4344
4345 memcpy((unsigned char *)keydata + offset,
4346 shaoutput,
4347 min(keylen - offset, sizeof(shaoutput)));
4348
4349 offset += sizeof(shaoutput);
4350 counter++;
4351 } while(offset < keylen);
4352 memset(shaoutput, 0, sizeof(shaoutput));
4353
4354 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4355 memset(keydata, 0, sizeof(keylen));
4356 free(keydata);
4357 return ret;
4358 }
4359
4360 static krb5_error_code
4361 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
/* [<][>][^][v][top][bottom][index][help] */
4362 {
4363 KRB5PrincipalName pn;
4364 krb5_error_code ret;
4365 size_t size;
4366
4367 pn.principalName = p->name;
4368 pn.realm = p->realm;
4369
4370 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4371 &pn, &size, ret);
4372 if (ret) {
4373 krb5_data_zero(data);
4374 krb5_set_error_message(context, ret,
4375 N_("Failed to encode KRB5PrincipalName", ""));
4376 return ret;
4377 }
4378 if (data->length != size)
4379 krb5_abortx(context, "asn1 compiler internal error");
4380 return 0;
4381 }
4382
4383 static krb5_error_code
4384 encode_otherinfo(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4385 const AlgorithmIdentifier *ai,
4386 krb5_const_principal client,
4387 krb5_const_principal server,
4388 krb5_enctype enctype,
4389 const krb5_data *as_req,
4390 const krb5_data *pk_as_rep,
4391 const Ticket *ticket,
4392 krb5_data *other)
4393 {
4394 PkinitSP80056AOtherInfo otherinfo;
4395 PkinitSuppPubInfo pubinfo;
4396 krb5_error_code ret;
4397 krb5_data pub;
4398 size_t size;
4399
4400 krb5_data_zero(other);
4401 memset(&otherinfo, 0, sizeof(otherinfo));
4402 memset(&pubinfo, 0, sizeof(pubinfo));
4403
4404 pubinfo.enctype = enctype;
4405 pubinfo.as_REQ = *as_req;
4406 pubinfo.pk_as_rep = *pk_as_rep;
4407 pubinfo.ticket = *ticket;
4408 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4409 &pubinfo, &size, ret);
4410 if (ret) {
4411 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4412 return ret;
4413 }
4414 if (pub.length != size)
4415 krb5_abortx(context, "asn1 compiler internal error");
4416
4417 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4418 if (ret) {
4419 free(pub.data);
4420 return ret;
4421 }
4422 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4423 if (ret) {
4424 free(otherinfo.partyUInfo.data);
4425 free(pub.data);
4426 return ret;
4427 }
4428
4429 otherinfo.algorithmID = *ai;
4430 otherinfo.suppPubInfo = &pub;
4431
4432 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4433 &otherinfo, &size, ret);
4434 free(otherinfo.partyUInfo.data);
4435 free(otherinfo.partyVInfo.data);
4436 free(pub.data);
4437 if (ret) {
4438 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4439 return ret;
4440 }
4441 if (other->length != size)
4442 krb5_abortx(context, "asn1 compiler internal error");
4443
4444 return 0;
4445 }
4446
4447 krb5_error_code
4448 _krb5_pk_kdf(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4449 const struct AlgorithmIdentifier *ai,
4450 const void *dhdata,
4451 size_t dhsize,
4452 krb5_const_principal client,
4453 krb5_const_principal server,
4454 krb5_enctype enctype,
4455 const krb5_data *as_req,
4456 const krb5_data *pk_as_rep,
4457 const Ticket *ticket,
4458 krb5_keyblock *key)
4459 {
4460 struct encryption_type *et;
4461 krb5_error_code ret;
4462 krb5_data other;
4463 size_t keylen, offset;
4464 uint32_t counter;
4465 unsigned char *keydata;
4466 unsigned char shaoutput[20];
4467
4468 if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
4469 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4470 N_("KDF not supported", ""));
4471 return KRB5_PROG_ETYPE_NOSUPP;
4472 }
4473 if (ai->parameters != NULL &&
4474 (ai->parameters->length != 2 ||
4475 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4476 {
4477 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4478 N_("kdf params not NULL or the NULL-type",
4479 ""));
4480 return KRB5_PROG_ETYPE_NOSUPP;
4481 }
4482
4483 et = _find_enctype(enctype);
4484 if(et == NULL) {
4485 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4486 N_("encryption type %d not supported", ""),
4487 enctype);
4488 return KRB5_PROG_ETYPE_NOSUPP;
4489 }
4490 keylen = (et->keytype->bits + 7) / 8;
4491
4492 keydata = malloc(keylen);
4493 if (keydata == NULL) {
4494 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4495 return ENOMEM;
4496 }
4497
4498 ret = encode_otherinfo(context, ai, client, server,
4499 enctype, as_req, pk_as_rep, ticket, &other);
4500 if (ret) {
4501 free(keydata);
4502 return ret;
4503 }
4504
4505 offset = 0;
4506 counter = 1;
4507 do {
4508 unsigned char cdata[4];
4509 SHA_CTX m;
4510
4511 SHA1_Init(&m);
4512 _krb5_put_int(cdata, counter, 4);
4513 SHA1_Update(&m, cdata, 4);
4514 SHA1_Update(&m, dhdata, dhsize);
4515 SHA1_Update(&m, other.data, other.length);
4516 SHA1_Final(shaoutput, &m);
4517
4518 memcpy((unsigned char *)keydata + offset,
4519 shaoutput,
4520 min(keylen - offset, sizeof(shaoutput)));
4521
4522 offset += sizeof(shaoutput);
4523 counter++;
4524 } while(offset < keylen);
4525 memset(shaoutput, 0, sizeof(shaoutput));
4526
4527 free(other.data);
4528
4529 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4530 memset(keydata, 0, sizeof(keylen));
4531 free(keydata);
4532
4533 return ret;
4534 }
4535
4536
4537 krb5_error_code KRB5_LIB_FUNCTION
4538 krb5_crypto_prf_length(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4539 krb5_enctype type,
4540 size_t *length)
4541 {
4542 struct encryption_type *et = _find_enctype(type);
4543
4544 if(et == NULL || et->prf_length == 0) {
4545 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4546 N_("encryption type %d not supported", ""),
4547 type);
4548 return KRB5_PROG_ETYPE_NOSUPP;
4549 }
4550
4551 *length = et->prf_length;
4552 return 0;
4553 }
4554
4555 krb5_error_code KRB5_LIB_FUNCTION
4556 krb5_crypto_prf(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4557 const krb5_crypto crypto,
4558 const krb5_data *input,
4559 krb5_data *output)
4560 {
4561 struct encryption_type *et = crypto->et;
4562
4563 krb5_data_zero(output);
4564
4565 if(et->prf == NULL) {
4566 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4567 "kerberos prf for %s not supported",
4568 et->name);
4569 return KRB5_PROG_ETYPE_NOSUPP;
4570 }
4571
4572 return (*et->prf)(context, crypto, input, output);
4573 }
4574
4575 #ifndef HEIMDAL_SMALLER
4576
4577 static struct key_type *keytypes[] = {
4578 &keytype_null,
4579 &keytype_des,
4580 &keytype_des3_derived,
4581 #ifdef DES3_OLD_ENCTYPE
4582 &keytype_des3,
4583 #endif
4584 &keytype_aes128,
4585 &keytype_aes256,
4586 &keytype_arcfour
4587 };
4588
4589 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
4590
4591
4592 static struct key_type *
4593 _find_keytype(krb5_keytype type)
/* [<][>][^][v][top][bottom][index][help] */
4594 {
4595 int i;
4596 for(i = 0; i < num_keytypes; i++)
4597 if(keytypes[i]->type == type)
4598 return keytypes[i];
4599 return NULL;
4600 }
4601
4602 /*
4603 * First take the configured list of etypes for `keytype' if available,
4604 * else, do `krb5_keytype_to_enctypes'.
4605 */
4606
4607 krb5_error_code KRB5_LIB_FUNCTION
4608 krb5_keytype_to_enctypes_default (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4609 krb5_keytype keytype,
4610 unsigned *len,
4611 krb5_enctype **val)
4612 __attribute__((deprecated))
4613 {
4614 unsigned int i, n;
4615 krb5_enctype *ret;
4616
4617 if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
4618 return krb5_keytype_to_enctypes (context, keytype, len, val);
4619
4620 for (n = 0; context->etypes_des[n]; ++n)
4621 ;
4622 ret = malloc (n * sizeof(*ret));
4623 if (ret == NULL && n != 0) {
4624 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4625 return ENOMEM;
4626 }
4627 for (i = 0; i < n; ++i)
4628 ret[i] = context->etypes_des[i];
4629 *len = n;
4630 *val = ret;
4631 return 0;
4632 }
4633
4634 krb5_error_code KRB5_LIB_FUNCTION
4635 krb5_keytype_to_string(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4636 krb5_keytype keytype,
4637 char **string)
4638 __attribute__((deprecated))
4639 {
4640 struct key_type *kt = _find_keytype(keytype);
4641 if(kt == NULL) {
4642 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4643 "key type %d not supported", keytype);
4644 return KRB5_PROG_KEYTYPE_NOSUPP;
4645 }
4646 *string = strdup(kt->name);
4647 if(*string == NULL) {
4648 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4649 return ENOMEM;
4650 }
4651 return 0;
4652 }
4653
4654
4655 krb5_error_code KRB5_LIB_FUNCTION
4656 krb5_string_to_keytype(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4657 const char *string,
4658 krb5_keytype *keytype)
4659 __attribute__((deprecated))
4660 {
4661 char *end;
4662 int i;
4663
4664 for(i = 0; i < num_keytypes; i++)
4665 if(strcasecmp(keytypes[i]->name, string) == 0){
4666 *keytype = keytypes[i]->type;
4667 return 0;
4668 }
4669
4670 /* check if the enctype is a number */
4671 *keytype = strtol(string, &end, 0);
4672 if(*end == '\0' && *keytype != 0) {
4673 if (krb5_enctype_valid(context, *keytype) == 0)
4674 return 0;
4675 }
4676
4677 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4678 "key type %s not supported", string);
4679 return KRB5_PROG_KEYTYPE_NOSUPP;
4680 }
4681
4682 krb5_error_code KRB5_LIB_FUNCTION
4683 krb5_keytype_to_enctypes (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
4684 krb5_keytype keytype,
4685 unsigned *len,
4686 krb5_enctype **val)
4687 {
4688 int i;
4689 unsigned n = 0;
4690 krb5_enctype *ret;
4691
4692 for (i = num_etypes - 1; i >= 0; --i) {
4693 if (etypes[i]->keytype->type == keytype
4694 && !(etypes[i]->flags & F_PSEUDO))
4695 ++n;
4696 }
4697 ret = malloc(n * sizeof(*ret));
4698 if (ret == NULL && n != 0) {
4699 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4700 return ENOMEM;
4701 }
4702 n = 0;
4703 for (i = num_etypes - 1; i >= 0; --i) {
4704 if (etypes[i]->keytype->type == keytype
4705 && !(etypes[i]->flags & F_PSEUDO))
4706 ret[n++] = etypes[i]->type;
4707 }
4708 *len = n;
4709 *val = ret;
4710 return 0;
4711 }
4712
4713 #endif /* HEIMDAL_SMALLER */