155682Smarkm/* 2178828Sdfr * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 35178828SdfrRCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $"); 3657428Smarkm/* RCSID("$FreeBSD$"); */ 3755682Smarkm 3855682Smarkm#undef CRYPTO_DEBUG 3955682Smarkm#ifdef CRYPTO_DEBUG 4055682Smarkmstatic void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*); 4155682Smarkm#endif 4255682Smarkm 4355682Smarkm 4455682Smarkmstruct key_data { 4555682Smarkm krb5_keyblock *key; 4655682Smarkm krb5_data *schedule; 4755682Smarkm}; 4855682Smarkm 4955682Smarkmstruct key_usage { 5055682Smarkm unsigned usage; 5155682Smarkm struct key_data key; 5255682Smarkm}; 5355682Smarkm 5455682Smarkmstruct krb5_crypto_data { 5555682Smarkm struct encryption_type *et; 5655682Smarkm struct key_data key; 5755682Smarkm int num_key_usage; 5855682Smarkm struct key_usage *key_usage; 5955682Smarkm}; 6055682Smarkm 6155682Smarkm#define CRYPTO_ETYPE(C) ((C)->et->type) 6255682Smarkm 6355682Smarkm/* bits for `flags' below */ 6455682Smarkm#define F_KEYED 1 /* checksum is keyed */ 6555682Smarkm#define F_CPROOF 2 /* checksum is collision proof */ 6655682Smarkm#define F_DERIVED 4 /* uses derived keys */ 6755682Smarkm#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */ 6855682Smarkm#define F_PSEUDO 16 /* not a real protocol type */ 6972448Sassar#define F_SPECIAL 32 /* backwards */ 70178828Sdfr#define F_DISABLED 64 /* enctype/checksum disabled */ 7155682Smarkm 7255682Smarkmstruct salt_type { 7355682Smarkm krb5_salttype type; 7455682Smarkm const char *name; 7555682Smarkm krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, 76120948Snectar krb5_salt, krb5_data, krb5_keyblock*); 7755682Smarkm}; 7855682Smarkm 7955682Smarkmstruct key_type { 8055682Smarkm krb5_keytype type; /* XXX */ 8155682Smarkm const char *name; 8255682Smarkm size_t bits; 8355682Smarkm size_t size; 8455682Smarkm size_t schedule_size; 8555682Smarkm#if 0 8655682Smarkm krb5_enctype best_etype; 8755682Smarkm#endif 8855682Smarkm void (*random_key)(krb5_context, krb5_keyblock*); 8955682Smarkm void (*schedule)(krb5_context, struct key_data *); 9055682Smarkm struct salt_type *string_to_key; 91178828Sdfr void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); 9255682Smarkm}; 9355682Smarkm 9455682Smarkmstruct checksum_type { 9555682Smarkm krb5_cksumtype type; 9655682Smarkm const char *name; 9755682Smarkm size_t blocksize; 9855682Smarkm size_t checksumsize; 9955682Smarkm unsigned flags; 10072448Sassar void (*checksum)(krb5_context context, 10172448Sassar struct key_data *key, 10272448Sassar const void *buf, size_t len, 10372448Sassar unsigned usage, 10472448Sassar Checksum *csum); 10572448Sassar krb5_error_code (*verify)(krb5_context context, 10672448Sassar struct key_data *key, 10772448Sassar const void *buf, size_t len, 10872448Sassar unsigned usage, 10972448Sassar Checksum *csum); 11055682Smarkm}; 11155682Smarkm 11255682Smarkmstruct encryption_type { 11355682Smarkm krb5_enctype type; 11455682Smarkm const char *name; 115178828Sdfr heim_oid *oid; 11655682Smarkm size_t blocksize; 117120948Snectar size_t padsize; 11855682Smarkm size_t confoundersize; 11955682Smarkm struct key_type *keytype; 12078536Sassar struct checksum_type *checksum; 12155682Smarkm struct checksum_type *keyed_checksum; 12255682Smarkm unsigned flags; 12378536Sassar krb5_error_code (*encrypt)(krb5_context context, 12478536Sassar struct key_data *key, 12572448Sassar void *data, size_t len, 126178828Sdfr krb5_boolean encryptp, 12772448Sassar int usage, 12872448Sassar void *ivec); 129178828Sdfr size_t prf_length; 130178828Sdfr krb5_error_code (*prf)(krb5_context, 131178828Sdfr krb5_crypto, const krb5_data *, krb5_data *); 13255682Smarkm}; 13355682Smarkm 13455682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) 13555682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) 13655682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) 13755682Smarkm 13855682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type); 13955682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type); 14055682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type); 14155682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 14255682Smarkm unsigned, struct key_data**); 14355682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); 144120948Snectarstatic krb5_error_code derive_key(krb5_context context, 145120948Snectar struct encryption_type *et, 146120948Snectar struct key_data *key, 147120948Snectar const void *constant, 148120948Snectar size_t len); 149127811Snectarstatic krb5_error_code hmac(krb5_context context, 150127811Snectar struct checksum_type *cm, 151127811Snectar const void *data, 152127811Snectar size_t len, 153127811Snectar unsigned usage, 154127811Snectar struct key_data *keyblock, 155127811Snectar Checksum *result); 156120948Snectarstatic void free_key_data(krb5_context context, struct key_data *key); 157178828Sdfrstatic krb5_error_code usage2arcfour (krb5_context, unsigned *); 158178828Sdfrstatic void xor (DES_cblock *, const unsigned char *); 15955682Smarkm 16055682Smarkm/************************************************************ 16155682Smarkm * * 16255682Smarkm ************************************************************/ 16355682Smarkm 164178828Sdfrstatic HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; 165178828Sdfr 166178828Sdfr 16755682Smarkmstatic void 168102647Snectarkrb5_DES_random_key(krb5_context context, 16955682Smarkm krb5_keyblock *key) 17055682Smarkm{ 171178828Sdfr DES_cblock *k = key->keyvalue.data; 17255682Smarkm do { 173178828Sdfr krb5_generate_random_block(k, sizeof(DES_cblock)); 174178828Sdfr DES_set_odd_parity(k); 175178828Sdfr } while(DES_is_weak_key(k)); 17655682Smarkm} 17755682Smarkm 17855682Smarkmstatic void 179102647Snectarkrb5_DES_schedule(krb5_context context, 180178828Sdfr struct key_data *key) 18155682Smarkm{ 182178828Sdfr DES_set_key(key->key->keyvalue.data, key->schedule->data); 18355682Smarkm} 18455682Smarkm 185178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY 18690929Snectar 18755682Smarkm/* This defines the Andrew string_to_key function. It accepts a password 188178828Sdfr * string as input and converts it via a one-way encryption algorithm to a DES 18955682Smarkm * encryption key. It is compatible with the original Andrew authentication 19055682Smarkm * service password database. 19155682Smarkm */ 19255682Smarkm 19355682Smarkm/* 19455682Smarkm * Short passwords, i.e 8 characters or less. 19555682Smarkm */ 19655682Smarkmstatic void 197102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw, 19855682Smarkm krb5_data cell, 199178828Sdfr DES_cblock *key) 20055682Smarkm{ 20155682Smarkm char password[8+1]; /* crypt is limited to 8 chars anyway */ 20255682Smarkm int i; 20355682Smarkm 20455682Smarkm for(i = 0; i < 8; i++) { 20555682Smarkm char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ 20672448Sassar ((i < cell.length) ? 20772448Sassar tolower(((unsigned char*)cell.data)[i]) : 0); 20855682Smarkm password[i] = c ? c : 'X'; 20955682Smarkm } 21055682Smarkm password[8] = '\0'; 21155682Smarkm 212178828Sdfr memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock)); 21355682Smarkm 21455682Smarkm /* parity is inserted into the LSB so left shift each byte up one 21555682Smarkm bit. This allows ascii characters with a zero MSB to retain as 21655682Smarkm much significance as possible. */ 217178828Sdfr for (i = 0; i < sizeof(DES_cblock); i++) 21855682Smarkm ((unsigned char*)key)[i] <<= 1; 219178828Sdfr DES_set_odd_parity (key); 22055682Smarkm} 22155682Smarkm 22255682Smarkm/* 22355682Smarkm * Long passwords, i.e 9 characters or more. 22455682Smarkm */ 22555682Smarkmstatic void 226102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, 22755682Smarkm krb5_data cell, 228178828Sdfr DES_cblock *key) 22955682Smarkm{ 230178828Sdfr DES_key_schedule schedule; 231178828Sdfr DES_cblock temp_key; 232178828Sdfr DES_cblock ivec; 23355682Smarkm char password[512]; 23455682Smarkm size_t passlen; 23555682Smarkm 23655682Smarkm memcpy(password, pw.data, min(pw.length, sizeof(password))); 23772448Sassar if(pw.length < sizeof(password)) { 23872448Sassar int len = min(cell.length, sizeof(password) - pw.length); 23972448Sassar int i; 24072448Sassar 24172448Sassar memcpy(password + pw.length, cell.data, len); 24272448Sassar for (i = pw.length; i < pw.length + len; ++i) 24372448Sassar password[i] = tolower((unsigned char)password[i]); 24472448Sassar } 24555682Smarkm passlen = min(sizeof(password), pw.length + cell.length); 24655682Smarkm memcpy(&ivec, "kerberos", 8); 24755682Smarkm memcpy(&temp_key, "kerberos", 8); 248178828Sdfr DES_set_odd_parity (&temp_key); 249178828Sdfr DES_set_key (&temp_key, &schedule); 250178828Sdfr DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec); 25155682Smarkm 25255682Smarkm memcpy(&temp_key, &ivec, 8); 253178828Sdfr DES_set_odd_parity (&temp_key); 254178828Sdfr DES_set_key (&temp_key, &schedule); 255178828Sdfr DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec); 25655682Smarkm memset(&schedule, 0, sizeof(schedule)); 25755682Smarkm memset(&temp_key, 0, sizeof(temp_key)); 25855682Smarkm memset(&ivec, 0, sizeof(ivec)); 25955682Smarkm memset(password, 0, sizeof(password)); 26055682Smarkm 261178828Sdfr DES_set_odd_parity (key); 26255682Smarkm} 26355682Smarkm 26455682Smarkmstatic krb5_error_code 26555682SmarkmDES_AFS3_string_to_key(krb5_context context, 26655682Smarkm krb5_enctype enctype, 26755682Smarkm krb5_data password, 26855682Smarkm krb5_salt salt, 269120948Snectar krb5_data opaque, 27055682Smarkm krb5_keyblock *key) 27155682Smarkm{ 272178828Sdfr DES_cblock tmp; 27355682Smarkm if(password.length > 8) 274102647Snectar krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); 27555682Smarkm else 276102647Snectar krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); 27755682Smarkm key->keytype = enctype; 27855682Smarkm krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 27955682Smarkm memset(&key, 0, sizeof(key)); 28055682Smarkm return 0; 28155682Smarkm} 282178828Sdfr#endif /* ENABLE_AFS_STRING_TO_KEY */ 28355682Smarkm 28455682Smarkmstatic void 285178828SdfrDES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) 286178828Sdfr{ 287178828Sdfr DES_key_schedule schedule; 288178828Sdfr int i; 289178828Sdfr int reverse = 0; 290178828Sdfr unsigned char *p; 291178828Sdfr 292178828Sdfr unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 293178828Sdfr 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; 294178828Sdfr memset(key, 0, 8); 295178828Sdfr 296178828Sdfr p = (unsigned char*)key; 297178828Sdfr for (i = 0; i < length; i++) { 298178828Sdfr unsigned char tmp = data[i]; 299178828Sdfr if (!reverse) 300178828Sdfr *p++ ^= (tmp << 1); 301178828Sdfr else 302178828Sdfr *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; 303178828Sdfr if((i % 8) == 7) 304178828Sdfr reverse = !reverse; 305178828Sdfr } 306178828Sdfr DES_set_odd_parity(key); 307178828Sdfr if(DES_is_weak_key(key)) 308178828Sdfr (*key)[7] ^= 0xF0; 309178828Sdfr DES_set_key(key, &schedule); 310178828Sdfr DES_cbc_cksum((void*)data, key, length, &schedule, key); 311178828Sdfr memset(&schedule, 0, sizeof(schedule)); 312178828Sdfr DES_set_odd_parity(key); 313178828Sdfr if(DES_is_weak_key(key)) 314178828Sdfr (*key)[7] ^= 0xF0; 315178828Sdfr} 316178828Sdfr 317178828Sdfrstatic krb5_error_code 318178828Sdfrkrb5_DES_string_to_key(krb5_context context, 319178828Sdfr krb5_enctype enctype, 320178828Sdfr krb5_data password, 321178828Sdfr krb5_salt salt, 322178828Sdfr krb5_data opaque, 323178828Sdfr krb5_keyblock *key) 324178828Sdfr{ 325178828Sdfr unsigned char *s; 326178828Sdfr size_t len; 327178828Sdfr DES_cblock tmp; 328178828Sdfr 329178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY 330178828Sdfr if (opaque.length == 1) { 331178828Sdfr unsigned long v; 332178828Sdfr _krb5_get_int(opaque.data, &v, 1); 333178828Sdfr if (v == 1) 334178828Sdfr return DES_AFS3_string_to_key(context, enctype, password, 335178828Sdfr salt, opaque, key); 336178828Sdfr } 337178828Sdfr#endif 338178828Sdfr 339178828Sdfr len = password.length + salt.saltvalue.length; 340178828Sdfr s = malloc(len); 341178828Sdfr if(len > 0 && s == NULL) { 342178828Sdfr krb5_set_error_string(context, "malloc: out of memory"); 343178828Sdfr return ENOMEM; 344178828Sdfr } 345178828Sdfr memcpy(s, password.data, password.length); 346178828Sdfr memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 347178828Sdfr DES_string_to_key_int(s, len, &tmp); 348178828Sdfr key->keytype = enctype; 349178828Sdfr krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 350178828Sdfr memset(&tmp, 0, sizeof(tmp)); 351178828Sdfr memset(s, 0, len); 352178828Sdfr free(s); 353178828Sdfr return 0; 354178828Sdfr} 355178828Sdfr 356178828Sdfrstatic void 357178828Sdfrkrb5_DES_random_to_key(krb5_context context, 358178828Sdfr krb5_keyblock *key, 359178828Sdfr const void *data, 360178828Sdfr size_t size) 361178828Sdfr{ 362178828Sdfr DES_cblock *k = key->keyvalue.data; 363178828Sdfr memcpy(k, data, key->keyvalue.length); 364178828Sdfr DES_set_odd_parity(k); 365178828Sdfr if(DES_is_weak_key(k)) 366178828Sdfr xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 367178828Sdfr} 368178828Sdfr 369178828Sdfr/* 370178828Sdfr * 371178828Sdfr */ 372178828Sdfr 373178828Sdfrstatic void 37455682SmarkmDES3_random_key(krb5_context context, 37555682Smarkm krb5_keyblock *key) 37655682Smarkm{ 377178828Sdfr DES_cblock *k = key->keyvalue.data; 37855682Smarkm do { 379178828Sdfr krb5_generate_random_block(k, 3 * sizeof(DES_cblock)); 380178828Sdfr DES_set_odd_parity(&k[0]); 381178828Sdfr DES_set_odd_parity(&k[1]); 382178828Sdfr DES_set_odd_parity(&k[2]); 383178828Sdfr } while(DES_is_weak_key(&k[0]) || 384178828Sdfr DES_is_weak_key(&k[1]) || 385178828Sdfr DES_is_weak_key(&k[2])); 38655682Smarkm} 38755682Smarkm 38855682Smarkmstatic void 38955682SmarkmDES3_schedule(krb5_context context, 39055682Smarkm struct key_data *key) 39155682Smarkm{ 392178828Sdfr DES_cblock *k = key->key->keyvalue.data; 393178828Sdfr DES_key_schedule *s = key->schedule->data; 394178828Sdfr DES_set_key(&k[0], &s[0]); 395178828Sdfr DES_set_key(&k[1], &s[1]); 396178828Sdfr DES_set_key(&k[2], &s[2]); 39755682Smarkm} 39855682Smarkm 39955682Smarkm/* 40055682Smarkm * A = A xor B. A & B are 8 bytes. 40155682Smarkm */ 40255682Smarkm 40355682Smarkmstatic void 404178828Sdfrxor (DES_cblock *key, const unsigned char *b) 40555682Smarkm{ 40655682Smarkm unsigned char *a = (unsigned char*)key; 40755682Smarkm a[0] ^= b[0]; 40855682Smarkm a[1] ^= b[1]; 40955682Smarkm a[2] ^= b[2]; 41055682Smarkm a[3] ^= b[3]; 41155682Smarkm a[4] ^= b[4]; 41255682Smarkm a[5] ^= b[5]; 41355682Smarkm a[6] ^= b[6]; 41455682Smarkm a[7] ^= b[7]; 41555682Smarkm} 41655682Smarkm 41755682Smarkmstatic krb5_error_code 41855682SmarkmDES3_string_to_key(krb5_context context, 41955682Smarkm krb5_enctype enctype, 42055682Smarkm krb5_data password, 42155682Smarkm krb5_salt salt, 422120948Snectar krb5_data opaque, 42355682Smarkm krb5_keyblock *key) 42455682Smarkm{ 42555682Smarkm char *str; 42655682Smarkm size_t len; 42755682Smarkm unsigned char tmp[24]; 428178828Sdfr DES_cblock keys[3]; 429178828Sdfr krb5_error_code ret; 43055682Smarkm 43155682Smarkm len = password.length + salt.saltvalue.length; 43255682Smarkm str = malloc(len); 43378536Sassar if(len != 0 && str == NULL) { 43478536Sassar krb5_set_error_string(context, "malloc: out of memory"); 43555682Smarkm return ENOMEM; 43678536Sassar } 43755682Smarkm memcpy(str, password.data, password.length); 43855682Smarkm memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); 43955682Smarkm { 440178828Sdfr DES_cblock ivec; 441178828Sdfr DES_key_schedule s[3]; 44255682Smarkm int i; 44355682Smarkm 444178828Sdfr ret = _krb5_n_fold(str, len, tmp, 24); 445178828Sdfr if (ret) { 446178828Sdfr memset(str, 0, len); 447178828Sdfr free(str); 448178828Sdfr krb5_set_error_string(context, "out of memory"); 449178828Sdfr return ret; 450178828Sdfr } 45155682Smarkm 45255682Smarkm for(i = 0; i < 3; i++){ 45355682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 454178828Sdfr DES_set_odd_parity(keys + i); 455178828Sdfr if(DES_is_weak_key(keys + i)) 456102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 457178828Sdfr DES_set_key(keys + i, &s[i]); 45855682Smarkm } 45955682Smarkm memset(&ivec, 0, sizeof(ivec)); 460178828Sdfr DES_ede3_cbc_encrypt(tmp, 46190929Snectar tmp, sizeof(tmp), 462178828Sdfr &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT); 46355682Smarkm memset(s, 0, sizeof(s)); 46455682Smarkm memset(&ivec, 0, sizeof(ivec)); 46555682Smarkm for(i = 0; i < 3; i++){ 46655682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 467178828Sdfr DES_set_odd_parity(keys + i); 468178828Sdfr if(DES_is_weak_key(keys + i)) 469102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 47055682Smarkm } 47155682Smarkm memset(tmp, 0, sizeof(tmp)); 47255682Smarkm } 47355682Smarkm key->keytype = enctype; 47455682Smarkm krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); 47555682Smarkm memset(keys, 0, sizeof(keys)); 47655682Smarkm memset(str, 0, len); 47755682Smarkm free(str); 47855682Smarkm return 0; 47955682Smarkm} 48055682Smarkm 48155682Smarkmstatic krb5_error_code 48255682SmarkmDES3_string_to_key_derived(krb5_context context, 48355682Smarkm krb5_enctype enctype, 48455682Smarkm krb5_data password, 48555682Smarkm krb5_salt salt, 486120948Snectar krb5_data opaque, 48755682Smarkm krb5_keyblock *key) 48855682Smarkm{ 48955682Smarkm krb5_error_code ret; 49055682Smarkm size_t len = password.length + salt.saltvalue.length; 49155682Smarkm char *s; 49255682Smarkm 49355682Smarkm s = malloc(len); 49478536Sassar if(len != 0 && s == NULL) { 49578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 49655682Smarkm return ENOMEM; 49778536Sassar } 49855682Smarkm memcpy(s, password.data, password.length); 49955682Smarkm memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 50055682Smarkm ret = krb5_string_to_key_derived(context, 50155682Smarkm s, 50255682Smarkm len, 50355682Smarkm enctype, 50455682Smarkm key); 50555682Smarkm memset(s, 0, len); 50655682Smarkm free(s); 50755682Smarkm return ret; 50855682Smarkm} 50955682Smarkm 510178828Sdfrstatic void 511178828SdfrDES3_random_to_key(krb5_context context, 512178828Sdfr krb5_keyblock *key, 513178828Sdfr const void *data, 514178828Sdfr size_t size) 515178828Sdfr{ 516178828Sdfr unsigned char *x = key->keyvalue.data; 517178828Sdfr const u_char *q = data; 518178828Sdfr DES_cblock *k; 519178828Sdfr int i, j; 520178828Sdfr 521178828Sdfr memset(x, 0, sizeof(x)); 522178828Sdfr for (i = 0; i < 3; ++i) { 523178828Sdfr unsigned char foo; 524178828Sdfr for (j = 0; j < 7; ++j) { 525178828Sdfr unsigned char b = q[7 * i + j]; 526178828Sdfr 527178828Sdfr x[8 * i + j] = b; 528178828Sdfr } 529178828Sdfr foo = 0; 530178828Sdfr for (j = 6; j >= 0; --j) { 531178828Sdfr foo |= q[7 * i + j] & 1; 532178828Sdfr foo <<= 1; 533178828Sdfr } 534178828Sdfr x[8 * i + 7] = foo; 535178828Sdfr } 536178828Sdfr k = key->keyvalue.data; 537178828Sdfr for (i = 0; i < 3; i++) { 538178828Sdfr DES_set_odd_parity(&k[i]); 539178828Sdfr if(DES_is_weak_key(&k[i])) 540178828Sdfr xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 541178828Sdfr } 542178828Sdfr} 543178828Sdfr 54455682Smarkm/* 54555682Smarkm * ARCFOUR 54655682Smarkm */ 54755682Smarkm 54855682Smarkmstatic void 549178828SdfrARCFOUR_schedule(krb5_context context, 550178828Sdfr struct key_data *kd) 55155682Smarkm{ 55255682Smarkm RC4_set_key (kd->schedule->data, 55355682Smarkm kd->key->keyvalue.length, kd->key->keyvalue.data); 55455682Smarkm} 55555682Smarkm 55655682Smarkmstatic krb5_error_code 55755682SmarkmARCFOUR_string_to_key(krb5_context context, 55855682Smarkm krb5_enctype enctype, 55955682Smarkm krb5_data password, 56055682Smarkm krb5_salt salt, 561120948Snectar krb5_data opaque, 56255682Smarkm krb5_keyblock *key) 56355682Smarkm{ 56455682Smarkm char *s, *p; 56555682Smarkm size_t len; 56655682Smarkm int i; 56757416Smarkm MD4_CTX m; 568178828Sdfr krb5_error_code ret; 56955682Smarkm 57072448Sassar len = 2 * password.length; 57155682Smarkm s = malloc (len); 57278536Sassar if (len != 0 && s == NULL) { 57378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 574178828Sdfr ret = ENOMEM; 575178828Sdfr goto out; 57678536Sassar } 57755682Smarkm for (p = s, i = 0; i < password.length; ++i) { 57855682Smarkm *p++ = ((char *)password.data)[i]; 57955682Smarkm *p++ = 0; 58055682Smarkm } 58172448Sassar MD4_Init (&m); 58272448Sassar MD4_Update (&m, s, len); 58355682Smarkm key->keytype = enctype; 584178828Sdfr ret = krb5_data_alloc (&key->keyvalue, 16); 585178828Sdfr if (ret) { 586178828Sdfr krb5_set_error_string(context, "malloc: out of memory"); 587178828Sdfr goto out; 588178828Sdfr } 58972448Sassar MD4_Final (key->keyvalue.data, &m); 59055682Smarkm memset (s, 0, len); 591178828Sdfr ret = 0; 592178828Sdfrout: 59355682Smarkm free (s); 594178828Sdfr return ret; 59555682Smarkm} 59655682Smarkm 597120948Snectar/* 598120948Snectar * AES 599120948Snectar */ 600120948Snectar 601178828Sdfrint _krb5_AES_string_to_default_iterator = 4096; 602120948Snectar 603120948Snectarstatic krb5_error_code 604120948SnectarAES_string_to_key(krb5_context context, 605120948Snectar krb5_enctype enctype, 606120948Snectar krb5_data password, 607120948Snectar krb5_salt salt, 608120948Snectar krb5_data opaque, 609120948Snectar krb5_keyblock *key) 610120948Snectar{ 611120948Snectar krb5_error_code ret; 612178828Sdfr uint32_t iter; 613120948Snectar struct encryption_type *et; 614120948Snectar struct key_data kd; 615120948Snectar 616120948Snectar if (opaque.length == 0) 617178828Sdfr iter = _krb5_AES_string_to_default_iterator; 618120948Snectar else if (opaque.length == 4) { 619120948Snectar unsigned long v; 620120948Snectar _krb5_get_int(opaque.data, &v, 4); 621178828Sdfr iter = ((uint32_t)v); 622120948Snectar } else 623120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ 624120948Snectar 625120948Snectar et = _find_enctype(enctype); 626120948Snectar if (et == NULL) 627120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; 628120948Snectar 629178828Sdfr kd.schedule = NULL; 630178828Sdfr ALLOC(kd.key, 1); 631178828Sdfr if(kd.key == NULL) { 632178828Sdfr krb5_set_error_string (context, "malloc: out of memory"); 633178828Sdfr return ENOMEM; 634178828Sdfr } 635178828Sdfr kd.key->keytype = enctype; 636178828Sdfr ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); 637178828Sdfr if (ret) { 638178828Sdfr krb5_set_error_string(context, "Failed to allocate pkcs5 key"); 639120948Snectar return ret; 640178828Sdfr } 641120948Snectar 642178828Sdfr ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, 643178828Sdfr salt.saltvalue.data, salt.saltvalue.length, 644178828Sdfr iter, 645178828Sdfr et->keytype->size, kd.key->keyvalue.data); 646178828Sdfr if (ret != 1) { 647178828Sdfr free_key_data(context, &kd); 648178828Sdfr krb5_set_error_string(context, "Error calculating s2k"); 649178828Sdfr return KRB5_PROG_KEYTYPE_NOSUPP; 650178828Sdfr } 651120948Snectar 652120948Snectar ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); 653178828Sdfr if (ret == 0) 654120948Snectar ret = krb5_copy_keyblock_contents(context, kd.key, key); 655178828Sdfr free_key_data(context, &kd); 656120948Snectar 657120948Snectar return ret; 658120948Snectar} 659120948Snectar 660178828Sdfrstruct krb5_aes_schedule { 661178828Sdfr AES_KEY ekey; 662178828Sdfr AES_KEY dkey; 663178828Sdfr}; 664178828Sdfr 665120948Snectarstatic void 666178828SdfrAES_schedule(krb5_context context, 667178828Sdfr struct key_data *kd) 668120948Snectar{ 669178828Sdfr struct krb5_aes_schedule *key = kd->schedule->data; 670120948Snectar int bits = kd->key->keyvalue.length * 8; 671178828Sdfr 672178828Sdfr memset(key, 0, sizeof(*key)); 673178828Sdfr AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey); 674178828Sdfr AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey); 675120948Snectar} 676120948Snectar 677120948Snectar/* 678120948Snectar * 679120948Snectar */ 680120948Snectar 681178828Sdfrstatic struct salt_type des_salt[] = { 682178828Sdfr { 683178828Sdfr KRB5_PW_SALT, 684178828Sdfr "pw-salt", 685178828Sdfr krb5_DES_string_to_key 686178828Sdfr }, 687178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY 688178828Sdfr { 689178828Sdfr KRB5_AFS3_SALT, 690178828Sdfr "afs3-salt", 691178828Sdfr DES_AFS3_string_to_key 692178828Sdfr }, 693178828Sdfr#endif 694178828Sdfr { 0 } 695178828Sdfr}; 696120948Snectar 697178828Sdfrstatic struct salt_type des3_salt[] = { 698178828Sdfr { 699178828Sdfr KRB5_PW_SALT, 700178828Sdfr "pw-salt", 701178828Sdfr DES3_string_to_key 702178828Sdfr }, 703178828Sdfr { 0 } 704178828Sdfr}; 705120948Snectar 706178828Sdfrstatic struct salt_type des3_salt_derived[] = { 707178828Sdfr { 708178828Sdfr KRB5_PW_SALT, 709178828Sdfr "pw-salt", 710178828Sdfr DES3_string_to_key_derived 711178828Sdfr }, 712178828Sdfr { 0 } 713178828Sdfr}; 71455682Smarkm 715178828Sdfrstatic struct salt_type AES_salt[] = { 716178828Sdfr { 717178828Sdfr KRB5_PW_SALT, 718178828Sdfr "pw-salt", 719178828Sdfr AES_string_to_key 720178828Sdfr }, 721178828Sdfr { 0 } 722178828Sdfr}; 723178828Sdfr 724178828Sdfrstatic struct salt_type arcfour_salt[] = { 725178828Sdfr { 726178828Sdfr KRB5_PW_SALT, 727178828Sdfr "pw-salt", 728178828Sdfr ARCFOUR_string_to_key 729178828Sdfr }, 730178828Sdfr { 0 } 731178828Sdfr}; 732178828Sdfr 733178828Sdfr/* 734178828Sdfr * 735178828Sdfr */ 736178828Sdfr 737178828Sdfrstatic struct key_type keytype_null = { 73855682Smarkm KEYTYPE_NULL, 73955682Smarkm "null", 74055682Smarkm 0, 74155682Smarkm 0, 74255682Smarkm 0, 74355682Smarkm NULL, 74455682Smarkm NULL, 74555682Smarkm NULL 74655682Smarkm}; 74755682Smarkm 748178828Sdfrstatic struct key_type keytype_des = { 74955682Smarkm KEYTYPE_DES, 75055682Smarkm "des", 75155682Smarkm 56, 752178828Sdfr sizeof(DES_cblock), 753178828Sdfr sizeof(DES_key_schedule), 754102647Snectar krb5_DES_random_key, 755102647Snectar krb5_DES_schedule, 756178828Sdfr des_salt, 757178828Sdfr krb5_DES_random_to_key 75855682Smarkm}; 75955682Smarkm 760178828Sdfrstatic struct key_type keytype_des3 = { 76155682Smarkm KEYTYPE_DES3, 76255682Smarkm "des3", 76355682Smarkm 168, 764178828Sdfr 3 * sizeof(DES_cblock), 765178828Sdfr 3 * sizeof(DES_key_schedule), 76655682Smarkm DES3_random_key, 76755682Smarkm DES3_schedule, 768178828Sdfr des3_salt, 769178828Sdfr DES3_random_to_key 77055682Smarkm}; 77155682Smarkm 772178828Sdfrstatic struct key_type keytype_des3_derived = { 77355682Smarkm KEYTYPE_DES3, 77455682Smarkm "des3", 77555682Smarkm 168, 776178828Sdfr 3 * sizeof(DES_cblock), 777178828Sdfr 3 * sizeof(DES_key_schedule), 77855682Smarkm DES3_random_key, 77955682Smarkm DES3_schedule, 780178828Sdfr des3_salt_derived, 781178828Sdfr DES3_random_to_key 78255682Smarkm}; 78355682Smarkm 784178828Sdfrstatic struct key_type keytype_aes128 = { 785120948Snectar KEYTYPE_AES128, 786120948Snectar "aes-128", 787120948Snectar 128, 788120948Snectar 16, 789178828Sdfr sizeof(struct krb5_aes_schedule), 790120948Snectar NULL, 791120948Snectar AES_schedule, 792120948Snectar AES_salt 793120948Snectar}; 794120948Snectar 795178828Sdfrstatic struct key_type keytype_aes256 = { 796120948Snectar KEYTYPE_AES256, 797120948Snectar "aes-256", 798120948Snectar 256, 799178828Sdfr 32, 800178828Sdfr sizeof(struct krb5_aes_schedule), 801120948Snectar NULL, 802120948Snectar AES_schedule, 803120948Snectar AES_salt 804120948Snectar}; 805120948Snectar 806178828Sdfrstatic struct key_type keytype_arcfour = { 80755682Smarkm KEYTYPE_ARCFOUR, 80855682Smarkm "arcfour", 80955682Smarkm 128, 81055682Smarkm 16, 81155682Smarkm sizeof(RC4_KEY), 812178828Sdfr NULL, 81355682Smarkm ARCFOUR_schedule, 81455682Smarkm arcfour_salt 81555682Smarkm}; 81655682Smarkm 817178828Sdfrstatic struct key_type *keytypes[] = { 81855682Smarkm &keytype_null, 81955682Smarkm &keytype_des, 82055682Smarkm &keytype_des3_derived, 82155682Smarkm &keytype_des3, 822120948Snectar &keytype_aes128, 823120948Snectar &keytype_aes256, 82455682Smarkm &keytype_arcfour 82555682Smarkm}; 82655682Smarkm 82755682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]); 82855682Smarkm 82955682Smarkmstatic struct key_type * 83055682Smarkm_find_keytype(krb5_keytype type) 83155682Smarkm{ 83255682Smarkm int i; 83355682Smarkm for(i = 0; i < num_keytypes; i++) 83455682Smarkm if(keytypes[i]->type == type) 83555682Smarkm return keytypes[i]; 83655682Smarkm return NULL; 83755682Smarkm} 83855682Smarkm 83955682Smarkm 840178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 84155682Smarkmkrb5_salttype_to_string (krb5_context context, 84255682Smarkm krb5_enctype etype, 84355682Smarkm krb5_salttype stype, 84455682Smarkm char **string) 84555682Smarkm{ 84655682Smarkm struct encryption_type *e; 84755682Smarkm struct salt_type *st; 84855682Smarkm 84955682Smarkm e = _find_enctype (etype); 85078536Sassar if (e == NULL) { 85178536Sassar krb5_set_error_string(context, "encryption type %d not supported", 85278536Sassar etype); 85355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 85478536Sassar } 85555682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 85655682Smarkm if (st->type == stype) { 85755682Smarkm *string = strdup (st->name); 85878536Sassar if (*string == NULL) { 85978536Sassar krb5_set_error_string(context, "malloc: out of memory"); 86055682Smarkm return ENOMEM; 86178536Sassar } 86255682Smarkm return 0; 86355682Smarkm } 86455682Smarkm } 86578536Sassar krb5_set_error_string(context, "salttype %d not supported", stype); 86655682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 86755682Smarkm} 86855682Smarkm 869178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 87055682Smarkmkrb5_string_to_salttype (krb5_context context, 87155682Smarkm krb5_enctype etype, 87255682Smarkm const char *string, 87355682Smarkm krb5_salttype *salttype) 87455682Smarkm{ 87555682Smarkm struct encryption_type *e; 87655682Smarkm struct salt_type *st; 87755682Smarkm 87855682Smarkm e = _find_enctype (etype); 87978536Sassar if (e == NULL) { 88078536Sassar krb5_set_error_string(context, "encryption type %d not supported", 88178536Sassar etype); 88255682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 88378536Sassar } 88455682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 88555682Smarkm if (strcasecmp (st->name, string) == 0) { 88655682Smarkm *salttype = st->type; 88755682Smarkm return 0; 88855682Smarkm } 88955682Smarkm } 89078536Sassar krb5_set_error_string(context, "salttype %s not supported", string); 89155682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 89255682Smarkm} 89355682Smarkm 894178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 89555682Smarkmkrb5_get_pw_salt(krb5_context context, 89655682Smarkm krb5_const_principal principal, 89755682Smarkm krb5_salt *salt) 89855682Smarkm{ 89955682Smarkm size_t len; 90055682Smarkm int i; 90155682Smarkm krb5_error_code ret; 90255682Smarkm char *p; 90355682Smarkm 90455682Smarkm salt->salttype = KRB5_PW_SALT; 90555682Smarkm len = strlen(principal->realm); 90655682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) 90755682Smarkm len += strlen(principal->name.name_string.val[i]); 90855682Smarkm ret = krb5_data_alloc (&salt->saltvalue, len); 90955682Smarkm if (ret) 91055682Smarkm return ret; 91155682Smarkm p = salt->saltvalue.data; 91255682Smarkm memcpy (p, principal->realm, strlen(principal->realm)); 91355682Smarkm p += strlen(principal->realm); 91455682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) { 91555682Smarkm memcpy (p, 91655682Smarkm principal->name.name_string.val[i], 91755682Smarkm strlen(principal->name.name_string.val[i])); 91855682Smarkm p += strlen(principal->name.name_string.val[i]); 91955682Smarkm } 92055682Smarkm return 0; 92155682Smarkm} 92255682Smarkm 923178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 92455682Smarkmkrb5_free_salt(krb5_context context, 92555682Smarkm krb5_salt salt) 92655682Smarkm{ 92755682Smarkm krb5_data_free(&salt.saltvalue); 92855682Smarkm return 0; 92955682Smarkm} 93055682Smarkm 931178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 93255682Smarkmkrb5_string_to_key_data (krb5_context context, 93355682Smarkm krb5_enctype enctype, 93455682Smarkm krb5_data password, 93555682Smarkm krb5_principal principal, 93655682Smarkm krb5_keyblock *key) 93755682Smarkm{ 93855682Smarkm krb5_error_code ret; 93955682Smarkm krb5_salt salt; 94055682Smarkm 94155682Smarkm ret = krb5_get_pw_salt(context, principal, &salt); 94255682Smarkm if(ret) 94355682Smarkm return ret; 94455682Smarkm ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); 94555682Smarkm krb5_free_salt(context, salt); 94655682Smarkm return ret; 94755682Smarkm} 94855682Smarkm 949178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 95055682Smarkmkrb5_string_to_key (krb5_context context, 95155682Smarkm krb5_enctype enctype, 95255682Smarkm const char *password, 95355682Smarkm krb5_principal principal, 95455682Smarkm krb5_keyblock *key) 95555682Smarkm{ 95655682Smarkm krb5_data pw; 957178828Sdfr pw.data = rk_UNCONST(password); 95855682Smarkm pw.length = strlen(password); 95955682Smarkm return krb5_string_to_key_data(context, enctype, pw, principal, key); 96055682Smarkm} 96155682Smarkm 962178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 96355682Smarkmkrb5_string_to_key_data_salt (krb5_context context, 96455682Smarkm krb5_enctype enctype, 96555682Smarkm krb5_data password, 96655682Smarkm krb5_salt salt, 96755682Smarkm krb5_keyblock *key) 96855682Smarkm{ 969120948Snectar krb5_data opaque; 970120948Snectar krb5_data_zero(&opaque); 971120948Snectar return krb5_string_to_key_data_salt_opaque(context, enctype, password, 972120948Snectar salt, opaque, key); 973120948Snectar} 974120948Snectar 975120948Snectar/* 976120948Snectar * Do a string -> key for encryption type `enctype' operation on 977120948Snectar * `password' (with salt `salt' and the enctype specific data string 978120948Snectar * `opaque'), returning the resulting key in `key' 979120948Snectar */ 980120948Snectar 981178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 982120948Snectarkrb5_string_to_key_data_salt_opaque (krb5_context context, 983120948Snectar krb5_enctype enctype, 984120948Snectar krb5_data password, 985120948Snectar krb5_salt salt, 986120948Snectar krb5_data opaque, 987120948Snectar krb5_keyblock *key) 988120948Snectar{ 98955682Smarkm struct encryption_type *et =_find_enctype(enctype); 99055682Smarkm struct salt_type *st; 99178536Sassar if(et == NULL) { 99278536Sassar krb5_set_error_string(context, "encryption type %d not supported", 99378536Sassar enctype); 99455682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 99578536Sassar } 99655682Smarkm for(st = et->keytype->string_to_key; st && st->type; st++) 99755682Smarkm if(st->type == salt.salttype) 998120948Snectar return (*st->string_to_key)(context, enctype, password, 999120948Snectar salt, opaque, key); 100078536Sassar krb5_set_error_string(context, "salt type %d not supported", 100178536Sassar salt.salttype); 100255682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 100355682Smarkm} 100455682Smarkm 100572448Sassar/* 100672448Sassar * Do a string -> key for encryption type `enctype' operation on the 100772448Sassar * string `password' (with salt `salt'), returning the resulting key 100872448Sassar * in `key' 100972448Sassar */ 101072448Sassar 1011178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 101255682Smarkmkrb5_string_to_key_salt (krb5_context context, 101355682Smarkm krb5_enctype enctype, 101455682Smarkm const char *password, 101555682Smarkm krb5_salt salt, 101655682Smarkm krb5_keyblock *key) 101755682Smarkm{ 101855682Smarkm krb5_data pw; 1019178828Sdfr pw.data = rk_UNCONST(password); 102055682Smarkm pw.length = strlen(password); 102155682Smarkm return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); 102255682Smarkm} 102355682Smarkm 1024178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1025178828Sdfrkrb5_string_to_key_salt_opaque (krb5_context context, 1026178828Sdfr krb5_enctype enctype, 1027178828Sdfr const char *password, 1028178828Sdfr krb5_salt salt, 1029178828Sdfr krb5_data opaque, 1030178828Sdfr krb5_keyblock *key) 1031178828Sdfr{ 1032178828Sdfr krb5_data pw; 1033178828Sdfr pw.data = rk_UNCONST(password); 1034178828Sdfr pw.length = strlen(password); 1035178828Sdfr return krb5_string_to_key_data_salt_opaque(context, enctype, 1036178828Sdfr pw, salt, opaque, key); 1037178828Sdfr} 1038178828Sdfr 1039178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 104055682Smarkmkrb5_keytype_to_string(krb5_context context, 104155682Smarkm krb5_keytype keytype, 104255682Smarkm char **string) 104355682Smarkm{ 104455682Smarkm struct key_type *kt = _find_keytype(keytype); 104578536Sassar if(kt == NULL) { 104678536Sassar krb5_set_error_string(context, "key type %d not supported", keytype); 104755682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 104878536Sassar } 104955682Smarkm *string = strdup(kt->name); 105078536Sassar if(*string == NULL) { 105178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 105255682Smarkm return ENOMEM; 105378536Sassar } 105455682Smarkm return 0; 105555682Smarkm} 105655682Smarkm 1057178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 105855682Smarkmkrb5_string_to_keytype(krb5_context context, 105955682Smarkm const char *string, 106055682Smarkm krb5_keytype *keytype) 106155682Smarkm{ 106255682Smarkm int i; 106355682Smarkm for(i = 0; i < num_keytypes; i++) 106455682Smarkm if(strcasecmp(keytypes[i]->name, string) == 0){ 106555682Smarkm *keytype = keytypes[i]->type; 106655682Smarkm return 0; 106755682Smarkm } 106878536Sassar krb5_set_error_string(context, "key type %s not supported", string); 106955682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 107055682Smarkm} 107155682Smarkm 1072178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1073120948Snectarkrb5_enctype_keysize(krb5_context context, 1074120948Snectar krb5_enctype type, 1075120948Snectar size_t *keysize) 1076120948Snectar{ 1077120948Snectar struct encryption_type *et = _find_enctype(type); 1078120948Snectar if(et == NULL) { 1079120948Snectar krb5_set_error_string(context, "encryption type %d not supported", 1080120948Snectar type); 1081120948Snectar return KRB5_PROG_ETYPE_NOSUPP; 1082120948Snectar } 1083120948Snectar *keysize = et->keytype->size; 1084120948Snectar return 0; 1085120948Snectar} 1086120948Snectar 1087178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1088178828Sdfrkrb5_enctype_keybits(krb5_context context, 1089178828Sdfr krb5_enctype type, 1090178828Sdfr size_t *keybits) 1091178828Sdfr{ 1092178828Sdfr struct encryption_type *et = _find_enctype(type); 1093178828Sdfr if(et == NULL) { 1094178828Sdfr krb5_set_error_string(context, "encryption type %d not supported", 1095178828Sdfr type); 1096178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 1097178828Sdfr } 1098178828Sdfr *keybits = et->keytype->bits; 1099178828Sdfr return 0; 1100178828Sdfr} 1101178828Sdfr 1102178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 110355682Smarkmkrb5_generate_random_keyblock(krb5_context context, 110455682Smarkm krb5_enctype type, 110555682Smarkm krb5_keyblock *key) 110655682Smarkm{ 110755682Smarkm krb5_error_code ret; 110855682Smarkm struct encryption_type *et = _find_enctype(type); 110978536Sassar if(et == NULL) { 111078536Sassar krb5_set_error_string(context, "encryption type %d not supported", 111178536Sassar type); 111255682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 111378536Sassar } 111455682Smarkm ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 111555682Smarkm if(ret) 111655682Smarkm return ret; 111755682Smarkm key->keytype = type; 111855682Smarkm if(et->keytype->random_key) 111955682Smarkm (*et->keytype->random_key)(context, key); 112055682Smarkm else 112155682Smarkm krb5_generate_random_block(key->keyvalue.data, 112255682Smarkm key->keyvalue.length); 112355682Smarkm return 0; 112455682Smarkm} 112555682Smarkm 112655682Smarkmstatic krb5_error_code 112755682Smarkm_key_schedule(krb5_context context, 112855682Smarkm struct key_data *key) 112955682Smarkm{ 113055682Smarkm krb5_error_code ret; 113155682Smarkm struct encryption_type *et = _find_enctype(key->key->keytype); 113255682Smarkm struct key_type *kt = et->keytype; 113355682Smarkm 113455682Smarkm if(kt->schedule == NULL) 113555682Smarkm return 0; 113672448Sassar if (key->schedule != NULL) 113772448Sassar return 0; 113855682Smarkm ALLOC(key->schedule, 1); 113978536Sassar if(key->schedule == NULL) { 114078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 114155682Smarkm return ENOMEM; 114278536Sassar } 114355682Smarkm ret = krb5_data_alloc(key->schedule, kt->schedule_size); 114455682Smarkm if(ret) { 114555682Smarkm free(key->schedule); 114655682Smarkm key->schedule = NULL; 114755682Smarkm return ret; 114855682Smarkm } 114955682Smarkm (*kt->schedule)(context, key); 115055682Smarkm return 0; 115155682Smarkm} 115255682Smarkm 115355682Smarkm/************************************************************ 115455682Smarkm * * 115555682Smarkm ************************************************************/ 115655682Smarkm 115755682Smarkmstatic void 115855682SmarkmNONE_checksum(krb5_context context, 115955682Smarkm struct key_data *key, 116072448Sassar const void *data, 116155682Smarkm size_t len, 116272448Sassar unsigned usage, 116355682Smarkm Checksum *C) 116455682Smarkm{ 116555682Smarkm} 116655682Smarkm 116755682Smarkmstatic void 116855682SmarkmCRC32_checksum(krb5_context context, 116955682Smarkm struct key_data *key, 117072448Sassar const void *data, 117155682Smarkm size_t len, 117272448Sassar unsigned usage, 117355682Smarkm Checksum *C) 117455682Smarkm{ 1175178828Sdfr uint32_t crc; 117655682Smarkm unsigned char *r = C->checksum.data; 117755682Smarkm _krb5_crc_init_table (); 117855682Smarkm crc = _krb5_crc_update (data, len, 0); 117955682Smarkm r[0] = crc & 0xff; 118055682Smarkm r[1] = (crc >> 8) & 0xff; 118155682Smarkm r[2] = (crc >> 16) & 0xff; 118255682Smarkm r[3] = (crc >> 24) & 0xff; 118355682Smarkm} 118455682Smarkm 118555682Smarkmstatic void 118655682SmarkmRSA_MD4_checksum(krb5_context context, 118755682Smarkm struct key_data *key, 118872448Sassar const void *data, 118955682Smarkm size_t len, 119072448Sassar unsigned usage, 119155682Smarkm Checksum *C) 119255682Smarkm{ 119357416Smarkm MD4_CTX m; 119457416Smarkm 119572448Sassar MD4_Init (&m); 119672448Sassar MD4_Update (&m, data, len); 119772448Sassar MD4_Final (C->checksum.data, &m); 119855682Smarkm} 119955682Smarkm 120055682Smarkmstatic void 120155682SmarkmRSA_MD4_DES_checksum(krb5_context context, 120255682Smarkm struct key_data *key, 120372448Sassar const void *data, 120455682Smarkm size_t len, 120572448Sassar unsigned usage, 120655682Smarkm Checksum *cksum) 120755682Smarkm{ 120857416Smarkm MD4_CTX md4; 1209178828Sdfr DES_cblock ivec; 121055682Smarkm unsigned char *p = cksum->checksum.data; 121155682Smarkm 121255682Smarkm krb5_generate_random_block(p, 8); 121372448Sassar MD4_Init (&md4); 121472448Sassar MD4_Update (&md4, p, 8); 121572448Sassar MD4_Update (&md4, data, len); 121672448Sassar MD4_Final (p + 8, &md4); 121755682Smarkm memset (&ivec, 0, sizeof(ivec)); 1218178828Sdfr DES_cbc_encrypt(p, 121990929Snectar p, 122055682Smarkm 24, 122155682Smarkm key->schedule->data, 122255682Smarkm &ivec, 122355682Smarkm DES_ENCRYPT); 122455682Smarkm} 122555682Smarkm 122655682Smarkmstatic krb5_error_code 122755682SmarkmRSA_MD4_DES_verify(krb5_context context, 122855682Smarkm struct key_data *key, 122972448Sassar const void *data, 123055682Smarkm size_t len, 123172448Sassar unsigned usage, 123255682Smarkm Checksum *C) 123355682Smarkm{ 123457416Smarkm MD4_CTX md4; 123555682Smarkm unsigned char tmp[24]; 123655682Smarkm unsigned char res[16]; 1237178828Sdfr DES_cblock ivec; 123855682Smarkm krb5_error_code ret = 0; 123955682Smarkm 124055682Smarkm memset(&ivec, 0, sizeof(ivec)); 1241178828Sdfr DES_cbc_encrypt(C->checksum.data, 124255682Smarkm (void*)tmp, 124355682Smarkm C->checksum.length, 124455682Smarkm key->schedule->data, 124555682Smarkm &ivec, 124655682Smarkm DES_DECRYPT); 124772448Sassar MD4_Init (&md4); 124872448Sassar MD4_Update (&md4, tmp, 8); /* confounder */ 124972448Sassar MD4_Update (&md4, data, len); 125072448Sassar MD4_Final (res, &md4); 125178536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 125278536Sassar krb5_clear_error_string (context); 125355682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 125478536Sassar } 125555682Smarkm memset(tmp, 0, sizeof(tmp)); 125655682Smarkm memset(res, 0, sizeof(res)); 125755682Smarkm return ret; 125855682Smarkm} 125955682Smarkm 126055682Smarkmstatic void 126155682SmarkmRSA_MD5_checksum(krb5_context context, 126255682Smarkm struct key_data *key, 126372448Sassar const void *data, 126455682Smarkm size_t len, 126572448Sassar unsigned usage, 126655682Smarkm Checksum *C) 126755682Smarkm{ 126857416Smarkm MD5_CTX m; 126957416Smarkm 127072448Sassar MD5_Init (&m); 127172448Sassar MD5_Update(&m, data, len); 127272448Sassar MD5_Final (C->checksum.data, &m); 127355682Smarkm} 127455682Smarkm 127555682Smarkmstatic void 127655682SmarkmRSA_MD5_DES_checksum(krb5_context context, 127755682Smarkm struct key_data *key, 127872448Sassar const void *data, 127955682Smarkm size_t len, 128072448Sassar unsigned usage, 128155682Smarkm Checksum *C) 128255682Smarkm{ 128357416Smarkm MD5_CTX md5; 1284178828Sdfr DES_cblock ivec; 128555682Smarkm unsigned char *p = C->checksum.data; 128655682Smarkm 128755682Smarkm krb5_generate_random_block(p, 8); 128872448Sassar MD5_Init (&md5); 128972448Sassar MD5_Update (&md5, p, 8); 129072448Sassar MD5_Update (&md5, data, len); 129172448Sassar MD5_Final (p + 8, &md5); 129255682Smarkm memset (&ivec, 0, sizeof(ivec)); 1293178828Sdfr DES_cbc_encrypt(p, 129490929Snectar p, 129555682Smarkm 24, 129655682Smarkm key->schedule->data, 129755682Smarkm &ivec, 129855682Smarkm DES_ENCRYPT); 129955682Smarkm} 130055682Smarkm 130155682Smarkmstatic krb5_error_code 130255682SmarkmRSA_MD5_DES_verify(krb5_context context, 130355682Smarkm struct key_data *key, 130472448Sassar const void *data, 130555682Smarkm size_t len, 130672448Sassar unsigned usage, 130755682Smarkm Checksum *C) 130855682Smarkm{ 130957416Smarkm MD5_CTX md5; 131055682Smarkm unsigned char tmp[24]; 131155682Smarkm unsigned char res[16]; 1312178828Sdfr DES_cblock ivec; 1313178828Sdfr DES_key_schedule *sched = key->schedule->data; 131455682Smarkm krb5_error_code ret = 0; 131555682Smarkm 131655682Smarkm memset(&ivec, 0, sizeof(ivec)); 1317178828Sdfr DES_cbc_encrypt(C->checksum.data, 131855682Smarkm (void*)tmp, 131955682Smarkm C->checksum.length, 1320178828Sdfr &sched[0], 132155682Smarkm &ivec, 132255682Smarkm DES_DECRYPT); 132372448Sassar MD5_Init (&md5); 132472448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 132572448Sassar MD5_Update (&md5, data, len); 132672448Sassar MD5_Final (res, &md5); 132778536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 132878536Sassar krb5_clear_error_string (context); 132955682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 133078536Sassar } 133155682Smarkm memset(tmp, 0, sizeof(tmp)); 133255682Smarkm memset(res, 0, sizeof(res)); 133355682Smarkm return ret; 133455682Smarkm} 133555682Smarkm 133655682Smarkmstatic void 133755682SmarkmRSA_MD5_DES3_checksum(krb5_context context, 133855682Smarkm struct key_data *key, 133972448Sassar const void *data, 134055682Smarkm size_t len, 134172448Sassar unsigned usage, 134255682Smarkm Checksum *C) 134355682Smarkm{ 134457416Smarkm MD5_CTX md5; 1345178828Sdfr DES_cblock ivec; 134655682Smarkm unsigned char *p = C->checksum.data; 1347178828Sdfr DES_key_schedule *sched = key->schedule->data; 134855682Smarkm 134955682Smarkm krb5_generate_random_block(p, 8); 135072448Sassar MD5_Init (&md5); 135172448Sassar MD5_Update (&md5, p, 8); 135272448Sassar MD5_Update (&md5, data, len); 135372448Sassar MD5_Final (p + 8, &md5); 135455682Smarkm memset (&ivec, 0, sizeof(ivec)); 1355178828Sdfr DES_ede3_cbc_encrypt(p, 135690929Snectar p, 135755682Smarkm 24, 1358178828Sdfr &sched[0], &sched[1], &sched[2], 135955682Smarkm &ivec, 136055682Smarkm DES_ENCRYPT); 136155682Smarkm} 136255682Smarkm 136355682Smarkmstatic krb5_error_code 136455682SmarkmRSA_MD5_DES3_verify(krb5_context context, 136555682Smarkm struct key_data *key, 136672448Sassar const void *data, 136755682Smarkm size_t len, 136872448Sassar unsigned usage, 136955682Smarkm Checksum *C) 137055682Smarkm{ 137157416Smarkm MD5_CTX md5; 137255682Smarkm unsigned char tmp[24]; 137355682Smarkm unsigned char res[16]; 1374178828Sdfr DES_cblock ivec; 1375178828Sdfr DES_key_schedule *sched = key->schedule->data; 137655682Smarkm krb5_error_code ret = 0; 137755682Smarkm 137855682Smarkm memset(&ivec, 0, sizeof(ivec)); 1379178828Sdfr DES_ede3_cbc_encrypt(C->checksum.data, 138055682Smarkm (void*)tmp, 138155682Smarkm C->checksum.length, 1382178828Sdfr &sched[0], &sched[1], &sched[2], 138355682Smarkm &ivec, 138455682Smarkm DES_DECRYPT); 138572448Sassar MD5_Init (&md5); 138672448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 138772448Sassar MD5_Update (&md5, data, len); 138872448Sassar MD5_Final (res, &md5); 138978536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 139078536Sassar krb5_clear_error_string (context); 139155682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 139278536Sassar } 139355682Smarkm memset(tmp, 0, sizeof(tmp)); 139455682Smarkm memset(res, 0, sizeof(res)); 139555682Smarkm return ret; 139655682Smarkm} 139755682Smarkm 139855682Smarkmstatic void 139955682SmarkmSHA1_checksum(krb5_context context, 140055682Smarkm struct key_data *key, 140172448Sassar const void *data, 140255682Smarkm size_t len, 140372448Sassar unsigned usage, 140455682Smarkm Checksum *C) 140555682Smarkm{ 140672448Sassar SHA_CTX m; 140757416Smarkm 140872448Sassar SHA1_Init(&m); 140972448Sassar SHA1_Update(&m, data, len); 141072448Sassar SHA1_Final(C->checksum.data, &m); 141155682Smarkm} 141255682Smarkm 141355682Smarkm/* HMAC according to RFC2104 */ 1414127811Snectarstatic krb5_error_code 141555682Smarkmhmac(krb5_context context, 141655682Smarkm struct checksum_type *cm, 141772448Sassar const void *data, 141855682Smarkm size_t len, 141972448Sassar unsigned usage, 142055682Smarkm struct key_data *keyblock, 142155682Smarkm Checksum *result) 142255682Smarkm{ 142355682Smarkm unsigned char *ipad, *opad; 142455682Smarkm unsigned char *key; 142555682Smarkm size_t key_len; 142655682Smarkm int i; 142755682Smarkm 1428127811Snectar ipad = malloc(cm->blocksize + len); 1429127811Snectar if (ipad == NULL) 1430127811Snectar return ENOMEM; 1431127811Snectar opad = malloc(cm->blocksize + cm->checksumsize); 1432127811Snectar if (opad == NULL) { 1433127811Snectar free(ipad); 1434127811Snectar return ENOMEM; 1435127811Snectar } 1436127811Snectar memset(ipad, 0x36, cm->blocksize); 1437127811Snectar memset(opad, 0x5c, cm->blocksize); 1438127811Snectar 143955682Smarkm if(keyblock->key->keyvalue.length > cm->blocksize){ 144055682Smarkm (*cm->checksum)(context, 144155682Smarkm keyblock, 144255682Smarkm keyblock->key->keyvalue.data, 144355682Smarkm keyblock->key->keyvalue.length, 144472448Sassar usage, 144555682Smarkm result); 144655682Smarkm key = result->checksum.data; 144755682Smarkm key_len = result->checksum.length; 144855682Smarkm } else { 144955682Smarkm key = keyblock->key->keyvalue.data; 145055682Smarkm key_len = keyblock->key->keyvalue.length; 145155682Smarkm } 145255682Smarkm for(i = 0; i < key_len; i++){ 145355682Smarkm ipad[i] ^= key[i]; 145455682Smarkm opad[i] ^= key[i]; 145555682Smarkm } 145655682Smarkm memcpy(ipad + cm->blocksize, data, len); 145772448Sassar (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, 145872448Sassar usage, result); 145955682Smarkm memcpy(opad + cm->blocksize, result->checksum.data, 146055682Smarkm result->checksum.length); 146155682Smarkm (*cm->checksum)(context, keyblock, opad, 146272448Sassar cm->blocksize + cm->checksumsize, usage, result); 146355682Smarkm memset(ipad, 0, cm->blocksize + len); 146455682Smarkm free(ipad); 146555682Smarkm memset(opad, 0, cm->blocksize + cm->checksumsize); 146655682Smarkm free(opad); 1467127811Snectar 1468127811Snectar return 0; 146955682Smarkm} 147055682Smarkm 1471178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1472127811Snectarkrb5_hmac(krb5_context context, 1473127811Snectar krb5_cksumtype cktype, 1474127811Snectar const void *data, 1475127811Snectar size_t len, 1476127811Snectar unsigned usage, 1477127811Snectar krb5_keyblock *key, 1478127811Snectar Checksum *result) 1479127811Snectar{ 1480127811Snectar struct checksum_type *c = _find_checksum(cktype); 1481127811Snectar struct key_data kd; 1482127811Snectar krb5_error_code ret; 1483127811Snectar 1484127811Snectar if (c == NULL) { 1485127811Snectar krb5_set_error_string (context, "checksum type %d not supported", 1486127811Snectar cktype); 1487127811Snectar return KRB5_PROG_SUMTYPE_NOSUPP; 1488127811Snectar } 1489127811Snectar 1490127811Snectar kd.key = key; 1491127811Snectar kd.schedule = NULL; 1492127811Snectar 1493127811Snectar ret = hmac(context, c, data, len, usage, &kd, result); 1494127811Snectar 1495127811Snectar if (kd.schedule) 1496127811Snectar krb5_free_data(context, kd.schedule); 1497127811Snectar 1498127811Snectar return ret; 1499127811Snectar } 1500127811Snectar 150155682Smarkmstatic void 1502120948SnectarSP_HMAC_SHA1_checksum(krb5_context context, 1503120948Snectar struct key_data *key, 1504120948Snectar const void *data, 1505120948Snectar size_t len, 1506120948Snectar unsigned usage, 1507120948Snectar Checksum *result) 150855682Smarkm{ 150955682Smarkm struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); 1510120948Snectar Checksum res; 1511120948Snectar char sha1_data[20]; 1512127811Snectar krb5_error_code ret; 151355682Smarkm 1514120948Snectar res.checksum.data = sha1_data; 1515120948Snectar res.checksum.length = sizeof(sha1_data); 1516120948Snectar 1517127811Snectar ret = hmac(context, c, data, len, usage, key, &res); 1518127811Snectar if (ret) 1519127811Snectar krb5_abortx(context, "hmac failed"); 1520120948Snectar memcpy(result->checksum.data, res.checksum.data, result->checksum.length); 152155682Smarkm} 152255682Smarkm 152372448Sassar/* 152472448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt 152572448Sassar */ 152672448Sassar 152772448Sassarstatic void 152872448SassarHMAC_MD5_checksum(krb5_context context, 152972448Sassar struct key_data *key, 153072448Sassar const void *data, 153172448Sassar size_t len, 153272448Sassar unsigned usage, 153372448Sassar Checksum *result) 153472448Sassar{ 153572448Sassar MD5_CTX md5; 153672448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 153772448Sassar const char signature[] = "signaturekey"; 153872448Sassar Checksum ksign_c; 153972448Sassar struct key_data ksign; 154072448Sassar krb5_keyblock kb; 154172448Sassar unsigned char t[4]; 154272448Sassar unsigned char tmp[16]; 154372448Sassar unsigned char ksign_c_data[16]; 1544127811Snectar krb5_error_code ret; 154572448Sassar 154672448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 154772448Sassar ksign_c.checksum.data = ksign_c_data; 1548127811Snectar ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); 1549127811Snectar if (ret) 1550127811Snectar krb5_abortx(context, "hmac failed"); 155172448Sassar ksign.key = &kb; 155272448Sassar kb.keyvalue = ksign_c.checksum; 155372448Sassar MD5_Init (&md5); 155472448Sassar t[0] = (usage >> 0) & 0xFF; 155572448Sassar t[1] = (usage >> 8) & 0xFF; 155672448Sassar t[2] = (usage >> 16) & 0xFF; 155772448Sassar t[3] = (usage >> 24) & 0xFF; 155872448Sassar MD5_Update (&md5, t, 4); 155972448Sassar MD5_Update (&md5, data, len); 156072448Sassar MD5_Final (tmp, &md5); 1561127811Snectar ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); 1562127811Snectar if (ret) 1563127811Snectar krb5_abortx(context, "hmac failed"); 156472448Sassar} 156572448Sassar 156672448Sassar/* 156772448Sassar * same as previous but being used while encrypting. 156872448Sassar */ 156972448Sassar 157072448Sassarstatic void 157172448SassarHMAC_MD5_checksum_enc(krb5_context context, 157272448Sassar struct key_data *key, 157372448Sassar const void *data, 157472448Sassar size_t len, 157572448Sassar unsigned usage, 157672448Sassar Checksum *result) 157772448Sassar{ 157872448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 157972448Sassar Checksum ksign_c; 158072448Sassar struct key_data ksign; 158172448Sassar krb5_keyblock kb; 158272448Sassar unsigned char t[4]; 158372448Sassar unsigned char ksign_c_data[16]; 1584127811Snectar krb5_error_code ret; 158572448Sassar 158672448Sassar t[0] = (usage >> 0) & 0xFF; 158772448Sassar t[1] = (usage >> 8) & 0xFF; 158872448Sassar t[2] = (usage >> 16) & 0xFF; 158972448Sassar t[3] = (usage >> 24) & 0xFF; 159072448Sassar 159172448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 159272448Sassar ksign_c.checksum.data = ksign_c_data; 1593127811Snectar ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c); 1594127811Snectar if (ret) 1595127811Snectar krb5_abortx(context, "hmac failed"); 159672448Sassar ksign.key = &kb; 159772448Sassar kb.keyvalue = ksign_c.checksum; 1598127811Snectar ret = hmac(context, c, data, len, 0, &ksign, result); 1599127811Snectar if (ret) 1600127811Snectar krb5_abortx(context, "hmac failed"); 160172448Sassar} 160272448Sassar 1603178828Sdfrstatic struct checksum_type checksum_none = { 160455682Smarkm CKSUMTYPE_NONE, 160555682Smarkm "none", 160655682Smarkm 1, 160755682Smarkm 0, 1608178828Sdfr 0, 160955682Smarkm NONE_checksum, 161055682Smarkm NULL 161155682Smarkm}; 1612178828Sdfrstatic struct checksum_type checksum_crc32 = { 161355682Smarkm CKSUMTYPE_CRC32, 161455682Smarkm "crc32", 161555682Smarkm 1, 161655682Smarkm 4, 161755682Smarkm 0, 161855682Smarkm CRC32_checksum, 161955682Smarkm NULL 162055682Smarkm}; 1621178828Sdfrstatic struct checksum_type checksum_rsa_md4 = { 162255682Smarkm CKSUMTYPE_RSA_MD4, 162355682Smarkm "rsa-md4", 162455682Smarkm 64, 162555682Smarkm 16, 162655682Smarkm F_CPROOF, 162755682Smarkm RSA_MD4_checksum, 162855682Smarkm NULL 162955682Smarkm}; 1630178828Sdfrstatic struct checksum_type checksum_rsa_md4_des = { 163155682Smarkm CKSUMTYPE_RSA_MD4_DES, 163255682Smarkm "rsa-md4-des", 163355682Smarkm 64, 163455682Smarkm 24, 163555682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 163655682Smarkm RSA_MD4_DES_checksum, 163755682Smarkm RSA_MD4_DES_verify 163855682Smarkm}; 163955682Smarkm#if 0 1640178828Sdfrstatic struct checksum_type checksum_des_mac = { 164155682Smarkm CKSUMTYPE_DES_MAC, 164255682Smarkm "des-mac", 164355682Smarkm 0, 164455682Smarkm 0, 164555682Smarkm 0, 164672448Sassar DES_MAC_checksum 164755682Smarkm}; 1648178828Sdfrstatic struct checksum_type checksum_des_mac_k = { 164955682Smarkm CKSUMTYPE_DES_MAC_K, 165055682Smarkm "des-mac-k", 165155682Smarkm 0, 165255682Smarkm 0, 165355682Smarkm 0, 165472448Sassar DES_MAC_K_checksum 165555682Smarkm}; 1656178828Sdfrstatic struct checksum_type checksum_rsa_md4_des_k = { 165755682Smarkm CKSUMTYPE_RSA_MD4_DES_K, 165855682Smarkm "rsa-md4-des-k", 165955682Smarkm 0, 166055682Smarkm 0, 166155682Smarkm 0, 166272448Sassar RSA_MD4_DES_K_checksum, 166372448Sassar RSA_MD4_DES_K_verify 166455682Smarkm}; 166555682Smarkm#endif 1666178828Sdfrstatic struct checksum_type checksum_rsa_md5 = { 166755682Smarkm CKSUMTYPE_RSA_MD5, 166855682Smarkm "rsa-md5", 166955682Smarkm 64, 167055682Smarkm 16, 167155682Smarkm F_CPROOF, 167255682Smarkm RSA_MD5_checksum, 167355682Smarkm NULL 167455682Smarkm}; 1675178828Sdfrstatic struct checksum_type checksum_rsa_md5_des = { 167655682Smarkm CKSUMTYPE_RSA_MD5_DES, 167755682Smarkm "rsa-md5-des", 167855682Smarkm 64, 167955682Smarkm 24, 168055682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 168155682Smarkm RSA_MD5_DES_checksum, 168272448Sassar RSA_MD5_DES_verify 168355682Smarkm}; 1684178828Sdfrstatic struct checksum_type checksum_rsa_md5_des3 = { 168555682Smarkm CKSUMTYPE_RSA_MD5_DES3, 168655682Smarkm "rsa-md5-des3", 168755682Smarkm 64, 168855682Smarkm 24, 168955682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 169055682Smarkm RSA_MD5_DES3_checksum, 169172448Sassar RSA_MD5_DES3_verify 169255682Smarkm}; 1693178828Sdfrstatic struct checksum_type checksum_sha1 = { 169455682Smarkm CKSUMTYPE_SHA1, 169555682Smarkm "sha1", 169655682Smarkm 64, 169755682Smarkm 20, 169855682Smarkm F_CPROOF, 169955682Smarkm SHA1_checksum, 170055682Smarkm NULL 170155682Smarkm}; 1702178828Sdfrstatic struct checksum_type checksum_hmac_sha1_des3 = { 170355682Smarkm CKSUMTYPE_HMAC_SHA1_DES3, 170455682Smarkm "hmac-sha1-des3", 170555682Smarkm 64, 170655682Smarkm 20, 170755682Smarkm F_KEYED | F_CPROOF | F_DERIVED, 1708120948Snectar SP_HMAC_SHA1_checksum, 170955682Smarkm NULL 171055682Smarkm}; 171155682Smarkm 1712178828Sdfrstatic struct checksum_type checksum_hmac_sha1_aes128 = { 1713120948Snectar CKSUMTYPE_HMAC_SHA1_96_AES_128, 1714120948Snectar "hmac-sha1-96-aes128", 1715120948Snectar 64, 1716120948Snectar 12, 1717120948Snectar F_KEYED | F_CPROOF | F_DERIVED, 1718120948Snectar SP_HMAC_SHA1_checksum, 1719120948Snectar NULL 1720120948Snectar}; 1721120948Snectar 1722178828Sdfrstatic struct checksum_type checksum_hmac_sha1_aes256 = { 1723120948Snectar CKSUMTYPE_HMAC_SHA1_96_AES_256, 1724120948Snectar "hmac-sha1-96-aes256", 1725120948Snectar 64, 1726120948Snectar 12, 1727120948Snectar F_KEYED | F_CPROOF | F_DERIVED, 1728120948Snectar SP_HMAC_SHA1_checksum, 1729120948Snectar NULL 1730120948Snectar}; 1731120948Snectar 1732178828Sdfrstatic struct checksum_type checksum_hmac_md5 = { 173372448Sassar CKSUMTYPE_HMAC_MD5, 173472448Sassar "hmac-md5", 173572448Sassar 64, 173672448Sassar 16, 173772448Sassar F_KEYED | F_CPROOF, 173872448Sassar HMAC_MD5_checksum, 173972448Sassar NULL 174072448Sassar}; 174172448Sassar 1742178828Sdfrstatic struct checksum_type checksum_hmac_md5_enc = { 174372448Sassar CKSUMTYPE_HMAC_MD5_ENC, 174472448Sassar "hmac-md5-enc", 174572448Sassar 64, 174672448Sassar 16, 174772448Sassar F_KEYED | F_CPROOF | F_PSEUDO, 174872448Sassar HMAC_MD5_checksum_enc, 174972448Sassar NULL 175072448Sassar}; 175172448Sassar 1752178828Sdfrstatic struct checksum_type *checksum_types[] = { 175355682Smarkm &checksum_none, 175455682Smarkm &checksum_crc32, 175555682Smarkm &checksum_rsa_md4, 175655682Smarkm &checksum_rsa_md4_des, 175755682Smarkm#if 0 175855682Smarkm &checksum_des_mac, 175955682Smarkm &checksum_des_mac_k, 176055682Smarkm &checksum_rsa_md4_des_k, 176155682Smarkm#endif 176255682Smarkm &checksum_rsa_md5, 176355682Smarkm &checksum_rsa_md5_des, 176455682Smarkm &checksum_rsa_md5_des3, 176555682Smarkm &checksum_sha1, 176672448Sassar &checksum_hmac_sha1_des3, 1767120948Snectar &checksum_hmac_sha1_aes128, 1768120948Snectar &checksum_hmac_sha1_aes256, 176972448Sassar &checksum_hmac_md5, 177072448Sassar &checksum_hmac_md5_enc 177155682Smarkm}; 177255682Smarkm 177355682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); 177455682Smarkm 177555682Smarkmstatic struct checksum_type * 177655682Smarkm_find_checksum(krb5_cksumtype type) 177755682Smarkm{ 177855682Smarkm int i; 177955682Smarkm for(i = 0; i < num_checksums; i++) 178055682Smarkm if(checksum_types[i]->type == type) 178155682Smarkm return checksum_types[i]; 178255682Smarkm return NULL; 178355682Smarkm} 178455682Smarkm 178555682Smarkmstatic krb5_error_code 178655682Smarkmget_checksum_key(krb5_context context, 178755682Smarkm krb5_crypto crypto, 178855682Smarkm unsigned usage, /* not krb5_key_usage */ 178955682Smarkm struct checksum_type *ct, 179055682Smarkm struct key_data **key) 179155682Smarkm{ 179255682Smarkm krb5_error_code ret = 0; 179355682Smarkm 179455682Smarkm if(ct->flags & F_DERIVED) 179555682Smarkm ret = _get_derived_key(context, crypto, usage, key); 179655682Smarkm else if(ct->flags & F_VARIANT) { 179755682Smarkm int i; 179855682Smarkm 179955682Smarkm *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); 180078536Sassar if(*key == NULL) { 180178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 180255682Smarkm return ENOMEM; 180378536Sassar } 180455682Smarkm ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); 180555682Smarkm if(ret) 180655682Smarkm return ret; 180755682Smarkm for(i = 0; i < (*key)->key->keyvalue.length; i++) 180855682Smarkm ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; 180955682Smarkm } else { 181055682Smarkm *key = &crypto->key; 181155682Smarkm } 181255682Smarkm if(ret == 0) 181355682Smarkm ret = _key_schedule(context, *key); 181455682Smarkm return ret; 181555682Smarkm} 181655682Smarkm 181755682Smarkmstatic krb5_error_code 1818127811Snectarcreate_checksum (krb5_context context, 1819127811Snectar struct checksum_type *ct, 1820127811Snectar krb5_crypto crypto, 1821127811Snectar unsigned usage, 1822127811Snectar void *data, 1823127811Snectar size_t len, 1824127811Snectar Checksum *result) 182555682Smarkm{ 182655682Smarkm krb5_error_code ret; 182755682Smarkm struct key_data *dkey; 182855682Smarkm int keyed_checksum; 1829127811Snectar 1830178828Sdfr if (ct->flags & F_DISABLED) { 1831178828Sdfr krb5_clear_error_string (context); 1832178828Sdfr return KRB5_PROG_SUMTYPE_NOSUPP; 1833178828Sdfr } 183455682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 183578536Sassar if(keyed_checksum && crypto == NULL) { 1836178828Sdfr krb5_set_error_string (context, "Checksum type %s is keyed " 1837178828Sdfr "but no crypto context (key) was passed in", 1838178828Sdfr ct->name); 183955682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 184078536Sassar } 184172448Sassar if(keyed_checksum) { 184255682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 184372448Sassar if (ret) 184472448Sassar return ret; 184572448Sassar } else 184655682Smarkm dkey = NULL; 184755682Smarkm result->cksumtype = ct->type; 1848178828Sdfr ret = krb5_data_alloc(&result->checksum, ct->checksumsize); 1849178828Sdfr if (ret) 1850178828Sdfr return (ret); 185172448Sassar (*ct->checksum)(context, dkey, data, len, usage, result); 185255682Smarkm return 0; 185355682Smarkm} 185455682Smarkm 1855127811Snectarstatic int 1856127811Snectararcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto) 185755682Smarkm{ 1858127811Snectar return (ct->type == CKSUMTYPE_HMAC_MD5) && 1859127811Snectar (crypto->key.key->keytype == KEYTYPE_ARCFOUR); 1860127811Snectar} 1861127811Snectar 1862178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1863127811Snectarkrb5_create_checksum(krb5_context context, 1864127811Snectar krb5_crypto crypto, 1865127811Snectar krb5_key_usage usage, 1866127811Snectar int type, 1867127811Snectar void *data, 1868127811Snectar size_t len, 1869127811Snectar Checksum *result) 1870127811Snectar{ 187178536Sassar struct checksum_type *ct = NULL; 1872127811Snectar unsigned keyusage; 187355682Smarkm 1874127811Snectar /* type 0 -> pick from crypto */ 187578536Sassar if (type) { 187678536Sassar ct = _find_checksum(type); 187778536Sassar } else if (crypto) { 187855682Smarkm ct = crypto->et->keyed_checksum; 187978536Sassar if (ct == NULL) 188078536Sassar ct = crypto->et->checksum; 188178536Sassar } 188278536Sassar 188378536Sassar if(ct == NULL) { 188478536Sassar krb5_set_error_string (context, "checksum type %d not supported", 188578536Sassar type); 188655682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 188778536Sassar } 188855682Smarkm 1889127811Snectar if (arcfour_checksum_p(ct, crypto)) { 1890127811Snectar keyusage = usage; 1891127811Snectar usage2arcfour(context, &keyusage); 1892127811Snectar } else 1893127811Snectar keyusage = CHECKSUM_USAGE(usage); 1894127811Snectar 1895127811Snectar return create_checksum(context, ct, crypto, keyusage, 1896127811Snectar data, len, result); 189755682Smarkm} 189855682Smarkm 189955682Smarkmstatic krb5_error_code 190055682Smarkmverify_checksum(krb5_context context, 190155682Smarkm krb5_crypto crypto, 190255682Smarkm unsigned usage, /* not krb5_key_usage */ 190355682Smarkm void *data, 190455682Smarkm size_t len, 190555682Smarkm Checksum *cksum) 190655682Smarkm{ 190755682Smarkm krb5_error_code ret; 190855682Smarkm struct key_data *dkey; 190955682Smarkm int keyed_checksum; 191055682Smarkm Checksum c; 191155682Smarkm struct checksum_type *ct; 191255682Smarkm 191355682Smarkm ct = _find_checksum(cksum->cksumtype); 1914178828Sdfr if (ct == NULL || (ct->flags & F_DISABLED)) { 191578536Sassar krb5_set_error_string (context, "checksum type %d not supported", 191678536Sassar cksum->cksumtype); 191755682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 191878536Sassar } 191978536Sassar if(ct->checksumsize != cksum->checksum.length) { 192078536Sassar krb5_clear_error_string (context); 192155682Smarkm return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ 192278536Sassar } 192355682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 192478536Sassar if(keyed_checksum && crypto == NULL) { 1925178828Sdfr krb5_set_error_string (context, "Checksum type %s is keyed " 1926178828Sdfr "but no crypto context (key) was passed in", 1927178828Sdfr ct->name); 192855682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 192978536Sassar } 193055682Smarkm if(keyed_checksum) 193155682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 193255682Smarkm else 193355682Smarkm dkey = NULL; 193455682Smarkm if(ct->verify) 193572448Sassar return (*ct->verify)(context, dkey, data, len, usage, cksum); 193655682Smarkm 193755682Smarkm ret = krb5_data_alloc (&c.checksum, ct->checksumsize); 193855682Smarkm if (ret) 193955682Smarkm return ret; 194055682Smarkm 194172448Sassar (*ct->checksum)(context, dkey, data, len, usage, &c); 194255682Smarkm 194355682Smarkm if(c.checksum.length != cksum->checksum.length || 194478536Sassar memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { 194578536Sassar krb5_clear_error_string (context); 194655682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 194778536Sassar } else { 194855682Smarkm ret = 0; 194978536Sassar } 195055682Smarkm krb5_data_free (&c.checksum); 195155682Smarkm return ret; 195255682Smarkm} 195355682Smarkm 1954178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 195555682Smarkmkrb5_verify_checksum(krb5_context context, 195655682Smarkm krb5_crypto crypto, 195755682Smarkm krb5_key_usage usage, 195855682Smarkm void *data, 195955682Smarkm size_t len, 196055682Smarkm Checksum *cksum) 196155682Smarkm{ 1962127811Snectar struct checksum_type *ct; 1963127811Snectar unsigned keyusage; 1964127811Snectar 1965127811Snectar ct = _find_checksum(cksum->cksumtype); 1966127811Snectar if(ct == NULL) { 1967127811Snectar krb5_set_error_string (context, "checksum type %d not supported", 1968127811Snectar cksum->cksumtype); 1969127811Snectar return KRB5_PROG_SUMTYPE_NOSUPP; 1970127811Snectar } 1971127811Snectar 1972127811Snectar if (arcfour_checksum_p(ct, crypto)) { 1973127811Snectar keyusage = usage; 1974127811Snectar usage2arcfour(context, &keyusage); 1975127811Snectar } else 1976127811Snectar keyusage = CHECKSUM_USAGE(usage); 1977127811Snectar 1978127811Snectar return verify_checksum(context, crypto, keyusage, 1979127811Snectar data, len, cksum); 198055682Smarkm} 198155682Smarkm 1982178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 1983178828Sdfrkrb5_crypto_get_checksum_type(krb5_context context, 1984178828Sdfr krb5_crypto crypto, 1985178828Sdfr krb5_cksumtype *type) 1986178828Sdfr{ 1987178828Sdfr struct checksum_type *ct = NULL; 1988178828Sdfr 1989178828Sdfr if (crypto != NULL) { 1990178828Sdfr ct = crypto->et->keyed_checksum; 1991178828Sdfr if (ct == NULL) 1992178828Sdfr ct = crypto->et->checksum; 1993178828Sdfr } 1994178828Sdfr 1995178828Sdfr if (ct == NULL) { 1996178828Sdfr krb5_set_error_string (context, "checksum type not found"); 1997178828Sdfr return KRB5_PROG_SUMTYPE_NOSUPP; 1998178828Sdfr } 1999178828Sdfr 2000178828Sdfr *type = ct->type; 2001178828Sdfr 2002178828Sdfr return 0; 2003178828Sdfr} 2004178828Sdfr 2005178828Sdfr 2006178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 200755682Smarkmkrb5_checksumsize(krb5_context context, 200855682Smarkm krb5_cksumtype type, 200955682Smarkm size_t *size) 201055682Smarkm{ 201155682Smarkm struct checksum_type *ct = _find_checksum(type); 201278536Sassar if(ct == NULL) { 201378536Sassar krb5_set_error_string (context, "checksum type %d not supported", 201478536Sassar type); 201555682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 201678536Sassar } 201755682Smarkm *size = ct->checksumsize; 201855682Smarkm return 0; 201955682Smarkm} 202055682Smarkm 2021178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION 202255682Smarkmkrb5_checksum_is_keyed(krb5_context context, 202355682Smarkm krb5_cksumtype type) 202455682Smarkm{ 202555682Smarkm struct checksum_type *ct = _find_checksum(type); 202678536Sassar if(ct == NULL) { 2027178828Sdfr if (context) 2028178828Sdfr krb5_set_error_string (context, "checksum type %d not supported", 2029178828Sdfr type); 203055682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 203178536Sassar } 203255682Smarkm return ct->flags & F_KEYED; 203355682Smarkm} 203455682Smarkm 2035178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION 203655682Smarkmkrb5_checksum_is_collision_proof(krb5_context context, 203755682Smarkm krb5_cksumtype type) 203855682Smarkm{ 203955682Smarkm struct checksum_type *ct = _find_checksum(type); 204078536Sassar if(ct == NULL) { 2041178828Sdfr if (context) 2042178828Sdfr krb5_set_error_string (context, "checksum type %d not supported", 2043178828Sdfr type); 204455682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 204578536Sassar } 204655682Smarkm return ct->flags & F_CPROOF; 204755682Smarkm} 204855682Smarkm 2049178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 2050178828Sdfrkrb5_checksum_disable(krb5_context context, 2051178828Sdfr krb5_cksumtype type) 2052178828Sdfr{ 2053178828Sdfr struct checksum_type *ct = _find_checksum(type); 2054178828Sdfr if(ct == NULL) { 2055178828Sdfr if (context) 2056178828Sdfr krb5_set_error_string (context, "checksum type %d not supported", 2057178828Sdfr type); 2058178828Sdfr return KRB5_PROG_SUMTYPE_NOSUPP; 2059178828Sdfr } 2060178828Sdfr ct->flags |= F_DISABLED; 2061178828Sdfr return 0; 2062178828Sdfr} 2063178828Sdfr 206455682Smarkm/************************************************************ 206555682Smarkm * * 206655682Smarkm ************************************************************/ 206755682Smarkm 206872448Sassarstatic krb5_error_code 206978536SassarNULL_encrypt(krb5_context context, 207078536Sassar struct key_data *key, 207155682Smarkm void *data, 207255682Smarkm size_t len, 2073178828Sdfr krb5_boolean encryptp, 207472448Sassar int usage, 207572448Sassar void *ivec) 207655682Smarkm{ 207772448Sassar return 0; 207855682Smarkm} 207955682Smarkm 208072448Sassarstatic krb5_error_code 208178536SassarDES_CBC_encrypt_null_ivec(krb5_context context, 208278536Sassar struct key_data *key, 208355682Smarkm void *data, 208455682Smarkm size_t len, 2085178828Sdfr krb5_boolean encryptp, 208672448Sassar int usage, 208772448Sassar void *ignore_ivec) 208855682Smarkm{ 2089178828Sdfr DES_cblock ivec; 2090178828Sdfr DES_key_schedule *s = key->schedule->data; 209155682Smarkm memset(&ivec, 0, sizeof(ivec)); 2092178828Sdfr DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); 209372448Sassar return 0; 209455682Smarkm} 209555682Smarkm 209672448Sassarstatic krb5_error_code 209778536SassarDES_CBC_encrypt_key_ivec(krb5_context context, 209878536Sassar struct key_data *key, 209955682Smarkm void *data, 210055682Smarkm size_t len, 2101178828Sdfr krb5_boolean encryptp, 210272448Sassar int usage, 210372448Sassar void *ignore_ivec) 210455682Smarkm{ 2105178828Sdfr DES_cblock ivec; 2106178828Sdfr DES_key_schedule *s = key->schedule->data; 210755682Smarkm memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 2108178828Sdfr DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); 210972448Sassar return 0; 211055682Smarkm} 211155682Smarkm 211272448Sassarstatic krb5_error_code 211378536SassarDES3_CBC_encrypt(krb5_context context, 211478536Sassar struct key_data *key, 211555682Smarkm void *data, 211655682Smarkm size_t len, 2117178828Sdfr krb5_boolean encryptp, 211872448Sassar int usage, 2119103426Snectar void *ivec) 212055682Smarkm{ 2121178828Sdfr DES_cblock local_ivec; 2122178828Sdfr DES_key_schedule *s = key->schedule->data; 2123103426Snectar if(ivec == NULL) { 2124103426Snectar ivec = &local_ivec; 2125103426Snectar memset(local_ivec, 0, sizeof(local_ivec)); 2126103426Snectar } 2127178828Sdfr DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encryptp); 212872448Sassar return 0; 212972448Sassar} 213072448Sassar 213172448Sassarstatic krb5_error_code 213278536SassarDES_CFB64_encrypt_null_ivec(krb5_context context, 213378536Sassar struct key_data *key, 213472448Sassar void *data, 213572448Sassar size_t len, 2136178828Sdfr krb5_boolean encryptp, 213772448Sassar int usage, 213872448Sassar void *ignore_ivec) 213972448Sassar{ 2140178828Sdfr DES_cblock ivec; 214172448Sassar int num = 0; 2142178828Sdfr DES_key_schedule *s = key->schedule->data; 214372448Sassar memset(&ivec, 0, sizeof(ivec)); 214472448Sassar 2145178828Sdfr DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp); 214672448Sassar return 0; 214772448Sassar} 214872448Sassar 214972448Sassarstatic krb5_error_code 215078536SassarDES_PCBC_encrypt_key_ivec(krb5_context context, 215178536Sassar struct key_data *key, 215272448Sassar void *data, 215372448Sassar size_t len, 2154178828Sdfr krb5_boolean encryptp, 215572448Sassar int usage, 215672448Sassar void *ignore_ivec) 215772448Sassar{ 2158178828Sdfr DES_cblock ivec; 2159178828Sdfr DES_key_schedule *s = key->schedule->data; 216072448Sassar memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 216172448Sassar 2162178828Sdfr DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); 216372448Sassar return 0; 216472448Sassar} 216572448Sassar 216672448Sassar/* 2167120948Snectar * AES draft-raeburn-krb-rijndael-krb-02 2168120948Snectar */ 2169120948Snectar 2170178828Sdfrvoid KRB5_LIB_FUNCTION 2171120948Snectar_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, 2172178828Sdfr size_t len, const AES_KEY *key, 2173178828Sdfr unsigned char *ivec, const int encryptp) 2174120948Snectar{ 2175120948Snectar unsigned char tmp[AES_BLOCK_SIZE]; 2176120948Snectar int i; 2177120948Snectar 2178120948Snectar /* 2179120948Snectar * In the framework of kerberos, the length can never be shorter 2180120948Snectar * then at least one blocksize. 2181120948Snectar */ 2182120948Snectar 2183178828Sdfr if (encryptp) { 2184120948Snectar 2185120948Snectar while(len > AES_BLOCK_SIZE) { 2186120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2187120948Snectar tmp[i] = in[i] ^ ivec[i]; 2188120948Snectar AES_encrypt(tmp, out, key); 2189120948Snectar memcpy(ivec, out, AES_BLOCK_SIZE); 2190120948Snectar len -= AES_BLOCK_SIZE; 2191120948Snectar in += AES_BLOCK_SIZE; 2192120948Snectar out += AES_BLOCK_SIZE; 2193120948Snectar } 2194120948Snectar 2195120948Snectar for (i = 0; i < len; i++) 2196120948Snectar tmp[i] = in[i] ^ ivec[i]; 2197120948Snectar for (; i < AES_BLOCK_SIZE; i++) 2198120948Snectar tmp[i] = 0 ^ ivec[i]; 2199120948Snectar 2200120948Snectar AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); 2201120948Snectar 2202120948Snectar memcpy(out, ivec, len); 2203178828Sdfr memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); 2204120948Snectar 2205120948Snectar } else { 2206178828Sdfr unsigned char tmp2[AES_BLOCK_SIZE]; 2207178828Sdfr unsigned char tmp3[AES_BLOCK_SIZE]; 2208120948Snectar 2209120948Snectar while(len > AES_BLOCK_SIZE * 2) { 2210120948Snectar memcpy(tmp, in, AES_BLOCK_SIZE); 2211120948Snectar AES_decrypt(in, out, key); 2212120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2213120948Snectar out[i] ^= ivec[i]; 2214120948Snectar memcpy(ivec, tmp, AES_BLOCK_SIZE); 2215120948Snectar len -= AES_BLOCK_SIZE; 2216120948Snectar in += AES_BLOCK_SIZE; 2217120948Snectar out += AES_BLOCK_SIZE; 2218120948Snectar } 2219120948Snectar 2220120948Snectar len -= AES_BLOCK_SIZE; 2221120948Snectar 2222178828Sdfr memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */ 2223120948Snectar AES_decrypt(in, tmp2, key); 2224120948Snectar 2225120948Snectar memcpy(tmp3, in + AES_BLOCK_SIZE, len); 2226120948Snectar memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ 2227120948Snectar 2228120948Snectar for (i = 0; i < len; i++) 2229120948Snectar out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; 2230120948Snectar 2231120948Snectar AES_decrypt(tmp3, out, key); 2232120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2233120948Snectar out[i] ^= ivec[i]; 2234178828Sdfr memcpy(ivec, tmp, AES_BLOCK_SIZE); 2235120948Snectar } 2236120948Snectar} 2237120948Snectar 2238120948Snectarstatic krb5_error_code 2239120948SnectarAES_CTS_encrypt(krb5_context context, 2240120948Snectar struct key_data *key, 2241120948Snectar void *data, 2242120948Snectar size_t len, 2243178828Sdfr krb5_boolean encryptp, 2244120948Snectar int usage, 2245120948Snectar void *ivec) 2246120948Snectar{ 2247178828Sdfr struct krb5_aes_schedule *aeskey = key->schedule->data; 2248120948Snectar char local_ivec[AES_BLOCK_SIZE]; 2249178828Sdfr AES_KEY *k; 2250120948Snectar 2251178828Sdfr if (encryptp) 2252178828Sdfr k = &aeskey->ekey; 2253120948Snectar else 2254178828Sdfr k = &aeskey->dkey; 2255120948Snectar 2256120948Snectar if (len < AES_BLOCK_SIZE) 2257127811Snectar krb5_abortx(context, "invalid use of AES_CTS_encrypt"); 2258120948Snectar if (len == AES_BLOCK_SIZE) { 2259178828Sdfr if (encryptp) 2260120948Snectar AES_encrypt(data, data, k); 2261120948Snectar else 2262120948Snectar AES_decrypt(data, data, k); 2263120948Snectar } else { 2264120948Snectar if(ivec == NULL) { 2265120948Snectar memset(local_ivec, 0, sizeof(local_ivec)); 2266120948Snectar ivec = local_ivec; 2267120948Snectar } 2268178828Sdfr _krb5_aes_cts_encrypt(data, data, len, k, ivec, encryptp); 2269120948Snectar } 2270120948Snectar 2271120948Snectar return 0; 2272120948Snectar} 2273120948Snectar 2274120948Snectar/* 227572448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 227672448Sassar * 227772448Sassar * warning: not for small children 227872448Sassar */ 227972448Sassar 228072448Sassarstatic krb5_error_code 228178536SassarARCFOUR_subencrypt(krb5_context context, 228278536Sassar struct key_data *key, 228372448Sassar void *data, 228472448Sassar size_t len, 2285178828Sdfr unsigned usage, 228672448Sassar void *ivec) 228772448Sassar{ 228872448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 228972448Sassar Checksum k1_c, k2_c, k3_c, cksum; 229072448Sassar struct key_data ke; 229172448Sassar krb5_keyblock kb; 229272448Sassar unsigned char t[4]; 229372448Sassar RC4_KEY rc4_key; 229490929Snectar unsigned char *cdata = data; 229572448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 2296127811Snectar krb5_error_code ret; 229772448Sassar 229872448Sassar t[0] = (usage >> 0) & 0xFF; 229972448Sassar t[1] = (usage >> 8) & 0xFF; 230072448Sassar t[2] = (usage >> 16) & 0xFF; 230172448Sassar t[3] = (usage >> 24) & 0xFF; 230272448Sassar 230372448Sassar k1_c.checksum.length = sizeof(k1_c_data); 230472448Sassar k1_c.checksum.data = k1_c_data; 230572448Sassar 2306127811Snectar ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 2307127811Snectar if (ret) 2308127811Snectar krb5_abortx(context, "hmac failed"); 230972448Sassar 231072448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 231172448Sassar 231272448Sassar k2_c.checksum.length = sizeof(k2_c_data); 231372448Sassar k2_c.checksum.data = k2_c_data; 231472448Sassar 231572448Sassar ke.key = &kb; 231672448Sassar kb.keyvalue = k2_c.checksum; 231772448Sassar 231872448Sassar cksum.checksum.length = 16; 231972448Sassar cksum.checksum.data = data; 232072448Sassar 2321127811Snectar ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 2322127811Snectar if (ret) 2323127811Snectar krb5_abortx(context, "hmac failed"); 232472448Sassar 232572448Sassar ke.key = &kb; 232672448Sassar kb.keyvalue = k1_c.checksum; 232772448Sassar 232872448Sassar k3_c.checksum.length = sizeof(k3_c_data); 232972448Sassar k3_c.checksum.data = k3_c_data; 233072448Sassar 2331127811Snectar ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c); 2332127811Snectar if (ret) 2333127811Snectar krb5_abortx(context, "hmac failed"); 233472448Sassar 233572448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 233672448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 233772448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 233872448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 233972448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 234072448Sassar return 0; 234172448Sassar} 234272448Sassar 234372448Sassarstatic krb5_error_code 234478536SassarARCFOUR_subdecrypt(krb5_context context, 234578536Sassar struct key_data *key, 234672448Sassar void *data, 234772448Sassar size_t len, 2348178828Sdfr unsigned usage, 234972448Sassar void *ivec) 235072448Sassar{ 235172448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 235272448Sassar Checksum k1_c, k2_c, k3_c, cksum; 235372448Sassar struct key_data ke; 235472448Sassar krb5_keyblock kb; 235572448Sassar unsigned char t[4]; 235672448Sassar RC4_KEY rc4_key; 235790929Snectar unsigned char *cdata = data; 235872448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 235972448Sassar unsigned char cksum_data[16]; 2360127811Snectar krb5_error_code ret; 236172448Sassar 236272448Sassar t[0] = (usage >> 0) & 0xFF; 236372448Sassar t[1] = (usage >> 8) & 0xFF; 236472448Sassar t[2] = (usage >> 16) & 0xFF; 236572448Sassar t[3] = (usage >> 24) & 0xFF; 236672448Sassar 236772448Sassar k1_c.checksum.length = sizeof(k1_c_data); 236872448Sassar k1_c.checksum.data = k1_c_data; 236972448Sassar 2370127811Snectar ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 2371127811Snectar if (ret) 2372127811Snectar krb5_abortx(context, "hmac failed"); 237372448Sassar 237472448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 237572448Sassar 237672448Sassar k2_c.checksum.length = sizeof(k2_c_data); 237772448Sassar k2_c.checksum.data = k2_c_data; 237872448Sassar 237972448Sassar ke.key = &kb; 238072448Sassar kb.keyvalue = k1_c.checksum; 238172448Sassar 238272448Sassar k3_c.checksum.length = sizeof(k3_c_data); 238372448Sassar k3_c.checksum.data = k3_c_data; 238472448Sassar 2385127811Snectar ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); 2386127811Snectar if (ret) 2387127811Snectar krb5_abortx(context, "hmac failed"); 238872448Sassar 238972448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 239072448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 239172448Sassar 239272448Sassar ke.key = &kb; 239372448Sassar kb.keyvalue = k2_c.checksum; 239472448Sassar 239572448Sassar cksum.checksum.length = 16; 239672448Sassar cksum.checksum.data = cksum_data; 239772448Sassar 2398127811Snectar ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 2399127811Snectar if (ret) 2400127811Snectar krb5_abortx(context, "hmac failed"); 240172448Sassar 240272448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 240372448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 240472448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 240572448Sassar 240678536Sassar if (memcmp (cksum.checksum.data, data, 16) != 0) { 240778536Sassar krb5_clear_error_string (context); 240872448Sassar return KRB5KRB_AP_ERR_BAD_INTEGRITY; 240978536Sassar } else { 241072448Sassar return 0; 241178536Sassar } 241272448Sassar} 241372448Sassar 241472448Sassar/* 241572448Sassar * convert the usage numbers used in 241672448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in 2417127811Snectar * draft-brezak-win2k-krb-rc4-hmac-04.txt 241872448Sassar */ 241972448Sassar 2420102647Snectarstatic krb5_error_code 2421178828Sdfrusage2arcfour (krb5_context context, unsigned *usage) 242272448Sassar{ 2423102647Snectar switch (*usage) { 2424127811Snectar case KRB5_KU_AS_REP_ENC_PART : /* 3 */ 2425127811Snectar case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */ 2426102647Snectar *usage = 8; 2427102647Snectar return 0; 2428127811Snectar case KRB5_KU_USAGE_SEAL : /* 22 */ 2429127811Snectar *usage = 13; 2430102647Snectar return 0; 2431127811Snectar case KRB5_KU_USAGE_SIGN : /* 23 */ 2432127811Snectar *usage = 15; 2433127811Snectar return 0; 2434127811Snectar case KRB5_KU_USAGE_SEQ: /* 24 */ 2435102647Snectar *usage = 0; 243672448Sassar return 0; 243772448Sassar default : 2438127811Snectar return 0; 243972448Sassar } 244072448Sassar} 244172448Sassar 244272448Sassarstatic krb5_error_code 244378536SassarARCFOUR_encrypt(krb5_context context, 244478536Sassar struct key_data *key, 244555682Smarkm void *data, 244655682Smarkm size_t len, 2447178828Sdfr krb5_boolean encryptp, 244872448Sassar int usage, 244972448Sassar void *ivec) 245055682Smarkm{ 2451102647Snectar krb5_error_code ret; 2452178828Sdfr unsigned keyusage = usage; 2453178828Sdfr 2454178828Sdfr if((ret = usage2arcfour (context, &keyusage)) != 0) 2455102647Snectar return ret; 245655682Smarkm 2457178828Sdfr if (encryptp) 2458178828Sdfr return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); 245972448Sassar else 2460178828Sdfr return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); 246155682Smarkm} 246255682Smarkm 246372448Sassar 246455682Smarkm/* 2465178828Sdfr * 2466178828Sdfr */ 2467178828Sdfr 2468178828Sdfrstatic krb5_error_code 2469178828SdfrAES_PRF(krb5_context context, 2470178828Sdfr krb5_crypto crypto, 2471178828Sdfr const krb5_data *in, 2472178828Sdfr krb5_data *out) 2473178828Sdfr{ 2474178828Sdfr struct checksum_type *ct = crypto->et->checksum; 2475178828Sdfr krb5_error_code ret; 2476178828Sdfr Checksum result; 2477178828Sdfr krb5_keyblock *derived; 2478178828Sdfr 2479178828Sdfr result.cksumtype = ct->type; 2480178828Sdfr ret = krb5_data_alloc(&result.checksum, ct->checksumsize); 2481178828Sdfr if (ret) { 2482178828Sdfr krb5_set_error_string(context, "out memory"); 2483178828Sdfr return ret; 2484178828Sdfr } 2485178828Sdfr 2486178828Sdfr (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); 2487178828Sdfr 2488178828Sdfr if (result.checksum.length < crypto->et->blocksize) 2489178828Sdfr krb5_abortx(context, "internal prf error"); 2490178828Sdfr 2491178828Sdfr derived = NULL; 2492178828Sdfr ret = krb5_derive_key(context, crypto->key.key, 2493178828Sdfr crypto->et->type, "prf", 3, &derived); 2494178828Sdfr if (ret) 2495178828Sdfr krb5_abortx(context, "krb5_derive_key"); 2496178828Sdfr 2497178828Sdfr ret = krb5_data_alloc(out, crypto->et->blocksize); 2498178828Sdfr if (ret) 2499178828Sdfr krb5_abortx(context, "malloc failed"); 2500178828Sdfr 2501178828Sdfr { 2502178828Sdfr AES_KEY key; 2503178828Sdfr 2504178828Sdfr AES_set_encrypt_key(derived->keyvalue.data, 2505178828Sdfr crypto->et->keytype->bits, &key); 2506178828Sdfr AES_encrypt(result.checksum.data, out->data, &key); 2507178828Sdfr memset(&key, 0, sizeof(key)); 2508178828Sdfr } 2509178828Sdfr 2510178828Sdfr krb5_data_free(&result.checksum); 2511178828Sdfr krb5_free_keyblock(context, derived); 2512178828Sdfr 2513178828Sdfr return ret; 2514178828Sdfr} 2515178828Sdfr 2516178828Sdfr/* 251755682Smarkm * these should currently be in reverse preference order. 251872448Sassar * (only relevant for !F_PSEUDO) */ 251955682Smarkm 252078536Sassarstatic struct encryption_type enctype_null = { 252178536Sassar ETYPE_NULL, 252278536Sassar "null", 2523178828Sdfr NULL, 252478536Sassar 1, 2525120948Snectar 1, 252678536Sassar 0, 252778536Sassar &keytype_null, 252878536Sassar &checksum_none, 252978536Sassar NULL, 2530178828Sdfr F_DISABLED, 2531178828Sdfr NULL_encrypt, 253278536Sassar 0, 2533178828Sdfr NULL 253455682Smarkm}; 253578536Sassarstatic struct encryption_type enctype_des_cbc_crc = { 253678536Sassar ETYPE_DES_CBC_CRC, 253778536Sassar "des-cbc-crc", 2538178828Sdfr NULL, 253978536Sassar 8, 254078536Sassar 8, 2541120948Snectar 8, 254278536Sassar &keytype_des, 254378536Sassar &checksum_crc32, 254478536Sassar NULL, 254578536Sassar 0, 254678536Sassar DES_CBC_encrypt_key_ivec, 2547178828Sdfr 0, 2548178828Sdfr NULL 254978536Sassar}; 255078536Sassarstatic struct encryption_type enctype_des_cbc_md4 = { 255178536Sassar ETYPE_DES_CBC_MD4, 255278536Sassar "des-cbc-md4", 2553178828Sdfr NULL, 255478536Sassar 8, 255578536Sassar 8, 2556120948Snectar 8, 255778536Sassar &keytype_des, 255878536Sassar &checksum_rsa_md4, 255978536Sassar &checksum_rsa_md4_des, 256078536Sassar 0, 256178536Sassar DES_CBC_encrypt_null_ivec, 2562178828Sdfr 0, 2563178828Sdfr NULL 256478536Sassar}; 256578536Sassarstatic struct encryption_type enctype_des_cbc_md5 = { 256678536Sassar ETYPE_DES_CBC_MD5, 256778536Sassar "des-cbc-md5", 2568178828Sdfr NULL, 256978536Sassar 8, 257078536Sassar 8, 2571120948Snectar 8, 257278536Sassar &keytype_des, 257378536Sassar &checksum_rsa_md5, 257478536Sassar &checksum_rsa_md5_des, 257578536Sassar 0, 257678536Sassar DES_CBC_encrypt_null_ivec, 2577178828Sdfr 0, 2578178828Sdfr NULL 257978536Sassar}; 258078536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = { 258178536Sassar ETYPE_ARCFOUR_HMAC_MD5, 258278536Sassar "arcfour-hmac-md5", 2583178828Sdfr NULL, 258478536Sassar 1, 2585120948Snectar 1, 258678536Sassar 8, 258778536Sassar &keytype_arcfour, 258890929Snectar &checksum_hmac_md5, 2589178828Sdfr NULL, 259078536Sassar F_SPECIAL, 2591178828Sdfr ARCFOUR_encrypt, 2592178828Sdfr 0, 2593178828Sdfr NULL 259478536Sassar}; 259578536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = { 259678536Sassar ETYPE_DES3_CBC_MD5, 259778536Sassar "des3-cbc-md5", 2598178828Sdfr NULL, 259978536Sassar 8, 260078536Sassar 8, 2601120948Snectar 8, 260278536Sassar &keytype_des3, 260378536Sassar &checksum_rsa_md5, 260478536Sassar &checksum_rsa_md5_des3, 260578536Sassar 0, 260678536Sassar DES3_CBC_encrypt, 2607178828Sdfr 0, 2608178828Sdfr NULL 260978536Sassar}; 261078536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = { 261178536Sassar ETYPE_DES3_CBC_SHA1, 261278536Sassar "des3-cbc-sha1", 2613178828Sdfr NULL, 261478536Sassar 8, 261578536Sassar 8, 2616120948Snectar 8, 261778536Sassar &keytype_des3_derived, 261878536Sassar &checksum_sha1, 261978536Sassar &checksum_hmac_sha1_des3, 262078536Sassar F_DERIVED, 262178536Sassar DES3_CBC_encrypt, 2622178828Sdfr 0, 2623178828Sdfr NULL 262478536Sassar}; 262578536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = { 262678536Sassar ETYPE_OLD_DES3_CBC_SHA1, 262778536Sassar "old-des3-cbc-sha1", 2628178828Sdfr NULL, 262978536Sassar 8, 263078536Sassar 8, 2631120948Snectar 8, 263278536Sassar &keytype_des3, 263378536Sassar &checksum_sha1, 263478536Sassar &checksum_hmac_sha1_des3, 263578536Sassar 0, 263678536Sassar DES3_CBC_encrypt, 2637178828Sdfr 0, 2638178828Sdfr NULL 263978536Sassar}; 2640120948Snectarstatic struct encryption_type enctype_aes128_cts_hmac_sha1 = { 2641120948Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 2642120948Snectar "aes128-cts-hmac-sha1-96", 2643178828Sdfr NULL, 2644120948Snectar 16, 2645120948Snectar 1, 2646120948Snectar 16, 2647120948Snectar &keytype_aes128, 2648120948Snectar &checksum_sha1, 2649120948Snectar &checksum_hmac_sha1_aes128, 2650178828Sdfr F_DERIVED, 2651120948Snectar AES_CTS_encrypt, 2652178828Sdfr 16, 2653178828Sdfr AES_PRF 2654120948Snectar}; 2655120948Snectarstatic struct encryption_type enctype_aes256_cts_hmac_sha1 = { 2656120948Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 2657120948Snectar "aes256-cts-hmac-sha1-96", 2658178828Sdfr NULL, 2659120948Snectar 16, 2660120948Snectar 1, 2661120948Snectar 16, 2662120948Snectar &keytype_aes256, 2663120948Snectar &checksum_sha1, 2664120948Snectar &checksum_hmac_sha1_aes256, 2665178828Sdfr F_DERIVED, 2666120948Snectar AES_CTS_encrypt, 2667178828Sdfr 16, 2668178828Sdfr AES_PRF 2669120948Snectar}; 267078536Sassarstatic struct encryption_type enctype_des_cbc_none = { 267178536Sassar ETYPE_DES_CBC_NONE, 267278536Sassar "des-cbc-none", 2673178828Sdfr NULL, 267478536Sassar 8, 2675120948Snectar 8, 267678536Sassar 0, 267778536Sassar &keytype_des, 267878536Sassar &checksum_none, 267978536Sassar NULL, 268078536Sassar F_PSEUDO, 268178536Sassar DES_CBC_encrypt_null_ivec, 2682178828Sdfr 0, 2683178828Sdfr NULL 268478536Sassar}; 268578536Sassarstatic struct encryption_type enctype_des_cfb64_none = { 268678536Sassar ETYPE_DES_CFB64_NONE, 268778536Sassar "des-cfb64-none", 2688178828Sdfr NULL, 268978536Sassar 1, 2690120948Snectar 1, 269178536Sassar 0, 269278536Sassar &keytype_des, 269378536Sassar &checksum_none, 269478536Sassar NULL, 269578536Sassar F_PSEUDO, 269678536Sassar DES_CFB64_encrypt_null_ivec, 2697178828Sdfr 0, 2698178828Sdfr NULL 269978536Sassar}; 270078536Sassarstatic struct encryption_type enctype_des_pcbc_none = { 270178536Sassar ETYPE_DES_PCBC_NONE, 270278536Sassar "des-pcbc-none", 2703178828Sdfr NULL, 270478536Sassar 8, 2705120948Snectar 8, 270678536Sassar 0, 270778536Sassar &keytype_des, 270878536Sassar &checksum_none, 270978536Sassar NULL, 271078536Sassar F_PSEUDO, 271178536Sassar DES_PCBC_encrypt_key_ivec, 2712178828Sdfr 0, 2713178828Sdfr NULL 271478536Sassar}; 271578536Sassarstatic struct encryption_type enctype_des3_cbc_none = { 271678536Sassar ETYPE_DES3_CBC_NONE, 271778536Sassar "des3-cbc-none", 2718178828Sdfr NULL, 271978536Sassar 8, 2720120948Snectar 8, 272178536Sassar 0, 272278536Sassar &keytype_des3_derived, 272378536Sassar &checksum_none, 272478536Sassar NULL, 272578536Sassar F_PSEUDO, 272678536Sassar DES3_CBC_encrypt, 2727178828Sdfr 0, 2728178828Sdfr NULL 272978536Sassar}; 273055682Smarkm 273178536Sassarstatic struct encryption_type *etypes[] = { 273278536Sassar &enctype_null, 273378536Sassar &enctype_des_cbc_crc, 273478536Sassar &enctype_des_cbc_md4, 273578536Sassar &enctype_des_cbc_md5, 273678536Sassar &enctype_arcfour_hmac_md5, 273778536Sassar &enctype_des3_cbc_md5, 273878536Sassar &enctype_des3_cbc_sha1, 273978536Sassar &enctype_old_des3_cbc_sha1, 2740120948Snectar &enctype_aes128_cts_hmac_sha1, 2741120948Snectar &enctype_aes256_cts_hmac_sha1, 274278536Sassar &enctype_des_cbc_none, 274378536Sassar &enctype_des_cfb64_none, 274478536Sassar &enctype_des_pcbc_none, 2745103426Snectar &enctype_des3_cbc_none 274678536Sassar}; 274778536Sassar 274855682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); 274955682Smarkm 275055682Smarkm 275155682Smarkmstatic struct encryption_type * 275255682Smarkm_find_enctype(krb5_enctype type) 275355682Smarkm{ 275455682Smarkm int i; 275555682Smarkm for(i = 0; i < num_etypes; i++) 275678536Sassar if(etypes[i]->type == type) 275778536Sassar return etypes[i]; 275855682Smarkm return NULL; 275955682Smarkm} 276055682Smarkm 276155682Smarkm 2762178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 276355682Smarkmkrb5_enctype_to_string(krb5_context context, 276455682Smarkm krb5_enctype etype, 276555682Smarkm char **string) 276655682Smarkm{ 276755682Smarkm struct encryption_type *e; 276855682Smarkm e = _find_enctype(etype); 276978536Sassar if(e == NULL) { 277078536Sassar krb5_set_error_string (context, "encryption type %d not supported", 277178536Sassar etype); 2772178828Sdfr *string = NULL; 277355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 277478536Sassar } 277555682Smarkm *string = strdup(e->name); 277678536Sassar if(*string == NULL) { 277778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 277855682Smarkm return ENOMEM; 277978536Sassar } 278055682Smarkm return 0; 278155682Smarkm} 278255682Smarkm 2783178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 278455682Smarkmkrb5_string_to_enctype(krb5_context context, 278555682Smarkm const char *string, 278655682Smarkm krb5_enctype *etype) 278755682Smarkm{ 278855682Smarkm int i; 278955682Smarkm for(i = 0; i < num_etypes; i++) 279078536Sassar if(strcasecmp(etypes[i]->name, string) == 0){ 279178536Sassar *etype = etypes[i]->type; 279255682Smarkm return 0; 279355682Smarkm } 279478536Sassar krb5_set_error_string (context, "encryption type %s not supported", 279578536Sassar string); 279655682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 279755682Smarkm} 279855682Smarkm 2799178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 2800178828Sdfr_krb5_enctype_to_oid(krb5_context context, 2801178828Sdfr krb5_enctype etype, 2802178828Sdfr heim_oid *oid) 2803178828Sdfr{ 2804178828Sdfr struct encryption_type *et = _find_enctype(etype); 2805178828Sdfr if(et == NULL) { 2806178828Sdfr krb5_set_error_string (context, "encryption type %d not supported", 2807178828Sdfr etype); 2808178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 2809178828Sdfr } 2810178828Sdfr if(et->oid == NULL) { 2811178828Sdfr krb5_set_error_string (context, "%s have not oid", et->name); 2812178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 2813178828Sdfr } 2814178828Sdfr krb5_clear_error_string(context); 2815178828Sdfr return der_copy_oid(et->oid, oid); 2816178828Sdfr} 2817178828Sdfr 2818178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 2819178828Sdfr_krb5_oid_to_enctype(krb5_context context, 2820178828Sdfr const heim_oid *oid, 2821178828Sdfr krb5_enctype *etype) 2822178828Sdfr{ 2823178828Sdfr int i; 2824178828Sdfr for(i = 0; i < num_etypes; i++) { 2825178828Sdfr if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) { 2826178828Sdfr *etype = etypes[i]->type; 2827178828Sdfr return 0; 2828178828Sdfr } 2829178828Sdfr } 2830178828Sdfr krb5_set_error_string(context, "enctype for oid not supported"); 2831178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 2832178828Sdfr} 2833178828Sdfr 2834178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 283555682Smarkmkrb5_enctype_to_keytype(krb5_context context, 283655682Smarkm krb5_enctype etype, 283755682Smarkm krb5_keytype *keytype) 283855682Smarkm{ 283955682Smarkm struct encryption_type *e = _find_enctype(etype); 284078536Sassar if(e == NULL) { 284178536Sassar krb5_set_error_string (context, "encryption type %d not supported", 284278536Sassar etype); 284355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 284478536Sassar } 284555682Smarkm *keytype = e->keytype->type; /* XXX */ 284655682Smarkm return 0; 284755682Smarkm} 284855682Smarkm 284955682Smarkm#if 0 2850178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 285155682Smarkmkrb5_keytype_to_enctype(krb5_context context, 285255682Smarkm krb5_keytype keytype, 285355682Smarkm krb5_enctype *etype) 285455682Smarkm{ 285555682Smarkm struct key_type *kt = _find_keytype(keytype); 285655682Smarkm krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); 285755682Smarkm if(kt == NULL) 285855682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 285955682Smarkm *etype = kt->best_etype; 286055682Smarkm return 0; 286155682Smarkm} 286255682Smarkm#endif 286355682Smarkm 2864178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 286555682Smarkmkrb5_keytype_to_enctypes (krb5_context context, 286655682Smarkm krb5_keytype keytype, 286755682Smarkm unsigned *len, 286890929Snectar krb5_enctype **val) 286955682Smarkm{ 287055682Smarkm int i; 287155682Smarkm unsigned n = 0; 287290929Snectar krb5_enctype *ret; 287355682Smarkm 287455682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 287578536Sassar if (etypes[i]->keytype->type == keytype 287678536Sassar && !(etypes[i]->flags & F_PSEUDO)) 287755682Smarkm ++n; 287855682Smarkm } 287990929Snectar ret = malloc(n * sizeof(*ret)); 288078536Sassar if (ret == NULL && n != 0) { 288178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 288255682Smarkm return ENOMEM; 288378536Sassar } 288455682Smarkm n = 0; 288555682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 288678536Sassar if (etypes[i]->keytype->type == keytype 288778536Sassar && !(etypes[i]->flags & F_PSEUDO)) 288878536Sassar ret[n++] = etypes[i]->type; 288955682Smarkm } 289055682Smarkm *len = n; 289155682Smarkm *val = ret; 289255682Smarkm return 0; 289355682Smarkm} 289455682Smarkm 289555682Smarkm/* 289655682Smarkm * First take the configured list of etypes for `keytype' if available, 289755682Smarkm * else, do `krb5_keytype_to_enctypes'. 289855682Smarkm */ 289955682Smarkm 2900178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 290155682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context, 290255682Smarkm krb5_keytype keytype, 290355682Smarkm unsigned *len, 290490929Snectar krb5_enctype **val) 290555682Smarkm{ 290655682Smarkm int i, n; 290790929Snectar krb5_enctype *ret; 290855682Smarkm 290955682Smarkm if (keytype != KEYTYPE_DES || context->etypes_des == NULL) 291055682Smarkm return krb5_keytype_to_enctypes (context, keytype, len, val); 291155682Smarkm 291255682Smarkm for (n = 0; context->etypes_des[n]; ++n) 291355682Smarkm ; 291455682Smarkm ret = malloc (n * sizeof(*ret)); 291578536Sassar if (ret == NULL && n != 0) { 291678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 291755682Smarkm return ENOMEM; 291878536Sassar } 291955682Smarkm for (i = 0; i < n; ++i) 292055682Smarkm ret[i] = context->etypes_des[i]; 292155682Smarkm *len = n; 292255682Smarkm *val = ret; 292355682Smarkm return 0; 292455682Smarkm} 292555682Smarkm 2926178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 292755682Smarkmkrb5_enctype_valid(krb5_context context, 292855682Smarkm krb5_enctype etype) 292955682Smarkm{ 2930178828Sdfr struct encryption_type *e = _find_enctype(etype); 2931178828Sdfr if(e == NULL) { 2932178828Sdfr krb5_set_error_string (context, "encryption type %d not supported", 2933178828Sdfr etype); 2934178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 2935178828Sdfr } 2936178828Sdfr if (e->flags & F_DISABLED) { 2937178828Sdfr krb5_set_error_string (context, "encryption type %s is disabled", 2938178828Sdfr e->name); 2939178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 2940178828Sdfr } 2941178828Sdfr return 0; 294255682Smarkm} 294355682Smarkm 2944178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 2945178828Sdfrkrb5_cksumtype_valid(krb5_context context, 2946178828Sdfr krb5_cksumtype ctype) 2947178828Sdfr{ 2948178828Sdfr struct checksum_type *c = _find_checksum(ctype); 2949178828Sdfr if (c == NULL) { 2950178828Sdfr krb5_set_error_string (context, "checksum type %d not supported", 2951178828Sdfr ctype); 2952178828Sdfr return KRB5_PROG_SUMTYPE_NOSUPP; 2953178828Sdfr } 2954178828Sdfr if (c->flags & F_DISABLED) { 2955178828Sdfr krb5_set_error_string (context, "checksum type %s is disabled", 2956178828Sdfr c->name); 2957178828Sdfr return KRB5_PROG_SUMTYPE_NOSUPP; 2958178828Sdfr } 2959178828Sdfr return 0; 2960178828Sdfr} 2961178828Sdfr 2962178828Sdfr 296355682Smarkm/* if two enctypes have compatible keys */ 2964178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION 296555682Smarkmkrb5_enctypes_compatible_keys(krb5_context context, 296655682Smarkm krb5_enctype etype1, 296755682Smarkm krb5_enctype etype2) 296855682Smarkm{ 296955682Smarkm struct encryption_type *e1 = _find_enctype(etype1); 297055682Smarkm struct encryption_type *e2 = _find_enctype(etype2); 297155682Smarkm return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; 297255682Smarkm} 297355682Smarkm 297455682Smarkmstatic krb5_boolean 297555682Smarkmderived_crypto(krb5_context context, 297655682Smarkm krb5_crypto crypto) 297755682Smarkm{ 297855682Smarkm return (crypto->et->flags & F_DERIVED) != 0; 297955682Smarkm} 298055682Smarkm 298172448Sassarstatic krb5_boolean 298272448Sassarspecial_crypto(krb5_context context, 298372448Sassar krb5_crypto crypto) 298472448Sassar{ 298572448Sassar return (crypto->et->flags & F_SPECIAL) != 0; 298672448Sassar} 298755682Smarkm 298855682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize) 298955682Smarkm#define CHECKSUMTYPE(C) ((C)->type) 299055682Smarkm 299155682Smarkmstatic krb5_error_code 299255682Smarkmencrypt_internal_derived(krb5_context context, 299355682Smarkm krb5_crypto crypto, 299455682Smarkm unsigned usage, 2995178828Sdfr const void *data, 299655682Smarkm size_t len, 299772448Sassar krb5_data *result, 299872448Sassar void *ivec) 299955682Smarkm{ 300090929Snectar size_t sz, block_sz, checksum_sz, total_sz; 300155682Smarkm Checksum cksum; 300255682Smarkm unsigned char *p, *q; 300355682Smarkm krb5_error_code ret; 300455682Smarkm struct key_data *dkey; 300590929Snectar const struct encryption_type *et = crypto->et; 300655682Smarkm 300755682Smarkm checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 300855682Smarkm 300990929Snectar sz = et->confoundersize + len; 3010120948Snectar block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 301190929Snectar total_sz = block_sz + checksum_sz; 301290929Snectar p = calloc(1, total_sz); 301390929Snectar if(p == NULL) { 301490929Snectar krb5_set_error_string(context, "malloc: out of memory"); 301555682Smarkm return ENOMEM; 301690929Snectar } 301755682Smarkm 301855682Smarkm q = p; 301955682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 302055682Smarkm q += et->confoundersize; 302155682Smarkm memcpy(q, data, len); 302255682Smarkm 302355682Smarkm ret = create_checksum(context, 3024127811Snectar et->keyed_checksum, 302555682Smarkm crypto, 302655682Smarkm INTEGRITY_USAGE(usage), 302755682Smarkm p, 302855682Smarkm block_sz, 302955682Smarkm &cksum); 303072448Sassar if(ret == 0 && cksum.checksum.length != checksum_sz) { 303172448Sassar free_Checksum (&cksum); 303278536Sassar krb5_clear_error_string (context); 303372448Sassar ret = KRB5_CRYPTO_INTERNAL; 303472448Sassar } 303590929Snectar if(ret) 303690929Snectar goto fail; 303755682Smarkm memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 303872448Sassar free_Checksum (&cksum); 303955682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 304090929Snectar if(ret) 304190929Snectar goto fail; 304255682Smarkm ret = _key_schedule(context, dkey); 304390929Snectar if(ret) 304490929Snectar goto fail; 304555682Smarkm#ifdef CRYPTO_DEBUG 304655682Smarkm krb5_crypto_debug(context, 1, block_sz, dkey->key); 304755682Smarkm#endif 304890929Snectar ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 304990929Snectar if (ret) 305090929Snectar goto fail; 305155682Smarkm result->data = p; 305290929Snectar result->length = total_sz; 305355682Smarkm return 0; 305490929Snectar fail: 305590929Snectar memset(p, 0, total_sz); 305690929Snectar free(p); 305790929Snectar return ret; 305855682Smarkm} 305955682Smarkm 306090929Snectar 306155682Smarkmstatic krb5_error_code 306255682Smarkmencrypt_internal(krb5_context context, 306355682Smarkm krb5_crypto crypto, 3064178828Sdfr const void *data, 306555682Smarkm size_t len, 306672448Sassar krb5_data *result, 306772448Sassar void *ivec) 306855682Smarkm{ 306955682Smarkm size_t sz, block_sz, checksum_sz; 307055682Smarkm Checksum cksum; 307155682Smarkm unsigned char *p, *q; 307255682Smarkm krb5_error_code ret; 307390929Snectar const struct encryption_type *et = crypto->et; 307455682Smarkm 307578536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 307655682Smarkm 307755682Smarkm sz = et->confoundersize + checksum_sz + len; 3078120948Snectar block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 307955682Smarkm p = calloc(1, block_sz); 308078536Sassar if(p == NULL) { 308178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 308255682Smarkm return ENOMEM; 308378536Sassar } 308455682Smarkm 308555682Smarkm q = p; 308655682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 308755682Smarkm q += et->confoundersize; 308855682Smarkm memset(q, 0, checksum_sz); 308955682Smarkm q += checksum_sz; 309055682Smarkm memcpy(q, data, len); 309155682Smarkm 309255682Smarkm ret = create_checksum(context, 3093127811Snectar et->checksum, 309478536Sassar crypto, 309555682Smarkm 0, 309655682Smarkm p, 309755682Smarkm block_sz, 309855682Smarkm &cksum); 309955682Smarkm if(ret == 0 && cksum.checksum.length != checksum_sz) { 310078536Sassar krb5_clear_error_string (context); 310190929Snectar free_Checksum(&cksum); 310255682Smarkm ret = KRB5_CRYPTO_INTERNAL; 310355682Smarkm } 310490929Snectar if(ret) 310590929Snectar goto fail; 310655682Smarkm memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); 310755682Smarkm free_Checksum(&cksum); 310855682Smarkm ret = _key_schedule(context, &crypto->key); 310990929Snectar if(ret) 311090929Snectar goto fail; 311190929Snectar#ifdef CRYPTO_DEBUG 311290929Snectar krb5_crypto_debug(context, 1, block_sz, crypto->key.key); 311390929Snectar#endif 311490929Snectar ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); 311590929Snectar if (ret) { 311655682Smarkm memset(p, 0, block_sz); 311755682Smarkm free(p); 311855682Smarkm return ret; 311955682Smarkm } 312055682Smarkm result->data = p; 312155682Smarkm result->length = block_sz; 312255682Smarkm return 0; 312390929Snectar fail: 312490929Snectar memset(p, 0, block_sz); 312590929Snectar free(p); 312690929Snectar return ret; 312755682Smarkm} 312855682Smarkm 312955682Smarkmstatic krb5_error_code 313072448Sassarencrypt_internal_special(krb5_context context, 313172448Sassar krb5_crypto crypto, 313272448Sassar int usage, 3133178828Sdfr const void *data, 313472448Sassar size_t len, 313572448Sassar krb5_data *result, 313672448Sassar void *ivec) 313772448Sassar{ 313872448Sassar struct encryption_type *et = crypto->et; 313978536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 314072448Sassar size_t sz = len + cksum_sz + et->confoundersize; 314172448Sassar char *tmp, *p; 314290929Snectar krb5_error_code ret; 314372448Sassar 314472448Sassar tmp = malloc (sz); 314578536Sassar if (tmp == NULL) { 314678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 314772448Sassar return ENOMEM; 314878536Sassar } 314972448Sassar p = tmp; 315072448Sassar memset (p, 0, cksum_sz); 315172448Sassar p += cksum_sz; 315272448Sassar krb5_generate_random_block(p, et->confoundersize); 315372448Sassar p += et->confoundersize; 315472448Sassar memcpy (p, data, len); 315590929Snectar ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); 315690929Snectar if (ret) { 315790929Snectar memset(tmp, 0, sz); 315890929Snectar free(tmp); 315990929Snectar return ret; 316090929Snectar } 316172448Sassar result->data = tmp; 316272448Sassar result->length = sz; 316372448Sassar return 0; 316472448Sassar} 316572448Sassar 316672448Sassarstatic krb5_error_code 316755682Smarkmdecrypt_internal_derived(krb5_context context, 316855682Smarkm krb5_crypto crypto, 316955682Smarkm unsigned usage, 317055682Smarkm void *data, 317155682Smarkm size_t len, 317272448Sassar krb5_data *result, 317372448Sassar void *ivec) 317455682Smarkm{ 317555682Smarkm size_t checksum_sz; 317655682Smarkm Checksum cksum; 317755682Smarkm unsigned char *p; 317855682Smarkm krb5_error_code ret; 317955682Smarkm struct key_data *dkey; 318055682Smarkm struct encryption_type *et = crypto->et; 318155682Smarkm unsigned long l; 318255682Smarkm 318372448Sassar checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 3184178828Sdfr if (len < checksum_sz + et->confoundersize) { 3185178828Sdfr krb5_set_error_string(context, "Encrypted data shorter then " 3186178828Sdfr "checksum + confunder"); 3187178828Sdfr return KRB5_BAD_MSIZE; 318878536Sassar } 318972448Sassar 3190127811Snectar if (((len - checksum_sz) % et->padsize) != 0) { 3191127811Snectar krb5_clear_error_string(context); 3192127811Snectar return KRB5_BAD_MSIZE; 3193127811Snectar } 3194127811Snectar 319555682Smarkm p = malloc(len); 319678536Sassar if(len != 0 && p == NULL) { 319778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 319855682Smarkm return ENOMEM; 319978536Sassar } 320055682Smarkm memcpy(p, data, len); 320155682Smarkm 320255682Smarkm len -= checksum_sz; 320355682Smarkm 320455682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 320555682Smarkm if(ret) { 320655682Smarkm free(p); 320755682Smarkm return ret; 320855682Smarkm } 320955682Smarkm ret = _key_schedule(context, dkey); 321055682Smarkm if(ret) { 321155682Smarkm free(p); 321255682Smarkm return ret; 321355682Smarkm } 321455682Smarkm#ifdef CRYPTO_DEBUG 321555682Smarkm krb5_crypto_debug(context, 0, len, dkey->key); 321655682Smarkm#endif 321790929Snectar ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 321890929Snectar if (ret) { 321990929Snectar free(p); 322090929Snectar return ret; 322190929Snectar } 322255682Smarkm 322355682Smarkm cksum.checksum.data = p + len; 322455682Smarkm cksum.checksum.length = checksum_sz; 322555682Smarkm cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 322655682Smarkm 322755682Smarkm ret = verify_checksum(context, 322855682Smarkm crypto, 322955682Smarkm INTEGRITY_USAGE(usage), 323055682Smarkm p, 323155682Smarkm len, 323255682Smarkm &cksum); 323355682Smarkm if(ret) { 323455682Smarkm free(p); 323555682Smarkm return ret; 323655682Smarkm } 323755682Smarkm l = len - et->confoundersize; 323855682Smarkm memmove(p, p + et->confoundersize, l); 323955682Smarkm result->data = realloc(p, l); 3240178828Sdfr if(result->data == NULL && l != 0) { 324155682Smarkm free(p); 324278536Sassar krb5_set_error_string(context, "malloc: out of memory"); 324355682Smarkm return ENOMEM; 324455682Smarkm } 324555682Smarkm result->length = l; 324655682Smarkm return 0; 324755682Smarkm} 324855682Smarkm 324955682Smarkmstatic krb5_error_code 325055682Smarkmdecrypt_internal(krb5_context context, 325155682Smarkm krb5_crypto crypto, 325255682Smarkm void *data, 325355682Smarkm size_t len, 325472448Sassar krb5_data *result, 325572448Sassar void *ivec) 325655682Smarkm{ 325755682Smarkm krb5_error_code ret; 325855682Smarkm unsigned char *p; 325955682Smarkm Checksum cksum; 326055682Smarkm size_t checksum_sz, l; 326155682Smarkm struct encryption_type *et = crypto->et; 326255682Smarkm 3263127811Snectar if ((len % et->padsize) != 0) { 3264127811Snectar krb5_clear_error_string(context); 3265127811Snectar return KRB5_BAD_MSIZE; 3266127811Snectar } 3267127811Snectar 326878536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 326955682Smarkm p = malloc(len); 327078536Sassar if(len != 0 && p == NULL) { 327178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 327255682Smarkm return ENOMEM; 327378536Sassar } 327455682Smarkm memcpy(p, data, len); 327555682Smarkm 327655682Smarkm ret = _key_schedule(context, &crypto->key); 327755682Smarkm if(ret) { 327855682Smarkm free(p); 327955682Smarkm return ret; 328055682Smarkm } 328155682Smarkm#ifdef CRYPTO_DEBUG 328255682Smarkm krb5_crypto_debug(context, 0, len, crypto->key.key); 328355682Smarkm#endif 328490929Snectar ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); 328590929Snectar if (ret) { 328690929Snectar free(p); 328790929Snectar return ret; 328890929Snectar } 328955682Smarkm ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); 329055682Smarkm if(ret) { 329172448Sassar free(p); 329272448Sassar return ret; 329355682Smarkm } 329455682Smarkm memset(p + et->confoundersize, 0, checksum_sz); 329578536Sassar cksum.cksumtype = CHECKSUMTYPE(et->checksum); 329655682Smarkm ret = verify_checksum(context, NULL, 0, p, len, &cksum); 329755682Smarkm free_Checksum(&cksum); 329855682Smarkm if(ret) { 329955682Smarkm free(p); 330055682Smarkm return ret; 330155682Smarkm } 330255682Smarkm l = len - et->confoundersize - checksum_sz; 330355682Smarkm memmove(p, p + et->confoundersize + checksum_sz, l); 330455682Smarkm result->data = realloc(p, l); 3305178828Sdfr if(result->data == NULL && l != 0) { 330655682Smarkm free(p); 330778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 330855682Smarkm return ENOMEM; 330955682Smarkm } 331055682Smarkm result->length = l; 331155682Smarkm return 0; 331255682Smarkm} 331355682Smarkm 331472448Sassarstatic krb5_error_code 331572448Sassardecrypt_internal_special(krb5_context context, 331672448Sassar krb5_crypto crypto, 331772448Sassar int usage, 331872448Sassar void *data, 331972448Sassar size_t len, 332072448Sassar krb5_data *result, 332172448Sassar void *ivec) 332272448Sassar{ 332372448Sassar struct encryption_type *et = crypto->et; 332478536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 332572448Sassar size_t sz = len - cksum_sz - et->confoundersize; 3326127811Snectar unsigned char *p; 332790929Snectar krb5_error_code ret; 332872448Sassar 3329127811Snectar if ((len % et->padsize) != 0) { 3330127811Snectar krb5_clear_error_string(context); 3331127811Snectar return KRB5_BAD_MSIZE; 3332127811Snectar } 3333127811Snectar 3334127811Snectar p = malloc (len); 3335127811Snectar if (p == NULL) { 333678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 333772448Sassar return ENOMEM; 333878536Sassar } 3339127811Snectar memcpy(p, data, len); 334072448Sassar 3341127811Snectar ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec); 334290929Snectar if (ret) { 3343127811Snectar free(p); 334490929Snectar return ret; 334590929Snectar } 334672448Sassar 3347127811Snectar memmove (p, p + cksum_sz + et->confoundersize, sz); 3348127811Snectar result->data = realloc(p, sz); 3349178828Sdfr if(result->data == NULL && sz != 0) { 3350127811Snectar free(p); 3351127811Snectar krb5_set_error_string(context, "malloc: out of memory"); 3352127811Snectar return ENOMEM; 3353127811Snectar } 335472448Sassar result->length = sz; 335572448Sassar return 0; 335672448Sassar} 335772448Sassar 335872448Sassar 3359178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 336072448Sassarkrb5_encrypt_ivec(krb5_context context, 336172448Sassar krb5_crypto crypto, 336272448Sassar unsigned usage, 3363178828Sdfr const void *data, 336472448Sassar size_t len, 336572448Sassar krb5_data *result, 336672448Sassar void *ivec) 336772448Sassar{ 336872448Sassar if(derived_crypto(context, crypto)) 336972448Sassar return encrypt_internal_derived(context, crypto, usage, 337072448Sassar data, len, result, ivec); 337172448Sassar else if (special_crypto(context, crypto)) 337272448Sassar return encrypt_internal_special (context, crypto, usage, 337372448Sassar data, len, result, ivec); 337472448Sassar else 337572448Sassar return encrypt_internal(context, crypto, data, len, result, ivec); 337672448Sassar} 337772448Sassar 3378178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 337955682Smarkmkrb5_encrypt(krb5_context context, 338055682Smarkm krb5_crypto crypto, 338155682Smarkm unsigned usage, 3382178828Sdfr const void *data, 338355682Smarkm size_t len, 338455682Smarkm krb5_data *result) 338555682Smarkm{ 338672448Sassar return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); 338755682Smarkm} 338855682Smarkm 3389178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 339055682Smarkmkrb5_encrypt_EncryptedData(krb5_context context, 339155682Smarkm krb5_crypto crypto, 339255682Smarkm unsigned usage, 339355682Smarkm void *data, 339455682Smarkm size_t len, 339555682Smarkm int kvno, 339655682Smarkm EncryptedData *result) 339755682Smarkm{ 339855682Smarkm result->etype = CRYPTO_ETYPE(crypto); 339955682Smarkm if(kvno){ 340055682Smarkm ALLOC(result->kvno, 1); 340155682Smarkm *result->kvno = kvno; 340255682Smarkm }else 340355682Smarkm result->kvno = NULL; 340455682Smarkm return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); 340555682Smarkm} 340655682Smarkm 3407178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 340872448Sassarkrb5_decrypt_ivec(krb5_context context, 340972448Sassar krb5_crypto crypto, 341072448Sassar unsigned usage, 341172448Sassar void *data, 341272448Sassar size_t len, 341372448Sassar krb5_data *result, 341472448Sassar void *ivec) 341572448Sassar{ 341672448Sassar if(derived_crypto(context, crypto)) 341772448Sassar return decrypt_internal_derived(context, crypto, usage, 341872448Sassar data, len, result, ivec); 341972448Sassar else if (special_crypto (context, crypto)) 342072448Sassar return decrypt_internal_special(context, crypto, usage, 342172448Sassar data, len, result, ivec); 342272448Sassar else 342372448Sassar return decrypt_internal(context, crypto, data, len, result, ivec); 342472448Sassar} 342572448Sassar 3426178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 342755682Smarkmkrb5_decrypt(krb5_context context, 342855682Smarkm krb5_crypto crypto, 342955682Smarkm unsigned usage, 343055682Smarkm void *data, 343155682Smarkm size_t len, 343255682Smarkm krb5_data *result) 343355682Smarkm{ 343472448Sassar return krb5_decrypt_ivec (context, crypto, usage, data, len, result, 343572448Sassar NULL); 343655682Smarkm} 343755682Smarkm 3438178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 343955682Smarkmkrb5_decrypt_EncryptedData(krb5_context context, 344055682Smarkm krb5_crypto crypto, 344155682Smarkm unsigned usage, 344272448Sassar const EncryptedData *e, 344355682Smarkm krb5_data *result) 344455682Smarkm{ 344555682Smarkm return krb5_decrypt(context, crypto, usage, 344655682Smarkm e->cipher.data, e->cipher.length, result); 344755682Smarkm} 344855682Smarkm 344955682Smarkm/************************************************************ 345055682Smarkm * * 345155682Smarkm ************************************************************/ 345255682Smarkm 3453178828Sdfr#define ENTROPY_NEEDED 128 345478536Sassar 345578536Sassarstatic int 345678536Sassarseed_something(void) 345778536Sassar{ 345878536Sassar char buf[1024], seedfile[256]; 345978536Sassar 346078536Sassar /* If there is a seed file, load it. But such a file cannot be trusted, 346178536Sassar so use 0 for the entropy estimate */ 346278536Sassar if (RAND_file_name(seedfile, sizeof(seedfile))) { 3463178828Sdfr int fd; 346478536Sassar fd = open(seedfile, O_RDONLY); 346578536Sassar if (fd >= 0) { 3466178828Sdfr ssize_t ret; 3467178828Sdfr ret = read(fd, buf, sizeof(buf)); 3468178828Sdfr if (ret > 0) 3469178828Sdfr RAND_add(buf, ret, 0.0); 3470178828Sdfr close(fd); 347178536Sassar } else 347278536Sassar seedfile[0] = '\0'; 347378536Sassar } else 347478536Sassar seedfile[0] = '\0'; 347578536Sassar 347678536Sassar /* Calling RAND_status() will try to use /dev/urandom if it exists so 347778536Sassar we do not have to deal with it. */ 347878536Sassar if (RAND_status() != 1) { 347978536Sassar krb5_context context; 348090929Snectar const char *p; 348178536Sassar 348278536Sassar /* Try using egd */ 348378536Sassar if (!krb5_init_context(&context)) { 348478536Sassar p = krb5_config_get_string(context, NULL, "libdefaults", 348578536Sassar "egd_socket", NULL); 348678536Sassar if (p != NULL) 348778536Sassar RAND_egd_bytes(p, ENTROPY_NEEDED); 348878536Sassar krb5_free_context(context); 348978536Sassar } 349078536Sassar } 349178536Sassar 349278536Sassar if (RAND_status() == 1) { 349378536Sassar /* Update the seed file */ 349478536Sassar if (seedfile[0]) 349578536Sassar RAND_write_file(seedfile); 349678536Sassar 349778536Sassar return 0; 349878536Sassar } else 349978536Sassar return -1; 350078536Sassar} 350178536Sassar 3502178828Sdfrvoid KRB5_LIB_FUNCTION 350355682Smarkmkrb5_generate_random_block(void *buf, size_t len) 350455682Smarkm{ 350578536Sassar static int rng_initialized = 0; 350678536Sassar 3507178828Sdfr HEIMDAL_MUTEX_lock(&crypto_mutex); 350878536Sassar if (!rng_initialized) { 350978536Sassar if (seed_something()) 3510178828Sdfr krb5_abortx(NULL, "Fatal: could not seed the " 3511178828Sdfr "random number generator"); 351278536Sassar 351378536Sassar rng_initialized = 1; 351478536Sassar } 3515178828Sdfr HEIMDAL_MUTEX_unlock(&crypto_mutex); 3516178828Sdfr if (RAND_bytes(buf, len) != 1) 3517178828Sdfr krb5_abortx(NULL, "Failed to generate random block"); 351878536Sassar} 351978536Sassar 352055682Smarkmstatic void 352155682SmarkmDES3_postproc(krb5_context context, 352255682Smarkm unsigned char *k, size_t len, struct key_data *key) 352355682Smarkm{ 3524178828Sdfr DES3_random_to_key(context, key->key, k, len); 352555682Smarkm 352655682Smarkm if (key->schedule) { 352755682Smarkm krb5_free_data(context, key->schedule); 352855682Smarkm key->schedule = NULL; 352955682Smarkm } 353055682Smarkm} 353155682Smarkm 353255682Smarkmstatic krb5_error_code 353355682Smarkmderive_key(krb5_context context, 353455682Smarkm struct encryption_type *et, 353555682Smarkm struct key_data *key, 353678536Sassar const void *constant, 353755682Smarkm size_t len) 353855682Smarkm{ 353955682Smarkm unsigned char *k; 354055682Smarkm unsigned int nblocks = 0, i; 354155682Smarkm krb5_error_code ret = 0; 354255682Smarkm struct key_type *kt = et->keytype; 3543178828Sdfr 354455682Smarkm ret = _key_schedule(context, key); 354555682Smarkm if(ret) 354655682Smarkm return ret; 3547178828Sdfr if(et->blocksize * 8 < kt->bits || len != et->blocksize) { 354855682Smarkm nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); 354955682Smarkm k = malloc(nblocks * et->blocksize); 355078536Sassar if(k == NULL) { 355178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 355255682Smarkm return ENOMEM; 355378536Sassar } 3554178828Sdfr ret = _krb5_n_fold(constant, len, k, et->blocksize); 3555178828Sdfr if (ret) { 3556178828Sdfr free(k); 3557178828Sdfr krb5_set_error_string(context, "out of memory"); 3558178828Sdfr return ret; 3559178828Sdfr } 356055682Smarkm for(i = 0; i < nblocks; i++) { 356155682Smarkm if(i > 0) 356255682Smarkm memcpy(k + i * et->blocksize, 356355682Smarkm k + (i - 1) * et->blocksize, 356455682Smarkm et->blocksize); 356578536Sassar (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, 356678536Sassar 1, 0, NULL); 356755682Smarkm } 356855682Smarkm } else { 356972448Sassar /* this case is probably broken, but won't be run anyway */ 357055682Smarkm void *c = malloc(len); 357155682Smarkm size_t res_len = (kt->bits + 7) / 8; 357255682Smarkm 357378536Sassar if(len != 0 && c == NULL) { 357478536Sassar krb5_set_error_string(context, "malloc: out of memory"); 357555682Smarkm return ENOMEM; 357678536Sassar } 357755682Smarkm memcpy(c, constant, len); 357878536Sassar (*et->encrypt)(context, key, c, len, 1, 0, NULL); 357955682Smarkm k = malloc(res_len); 358078536Sassar if(res_len != 0 && k == NULL) { 358178536Sassar free(c); 358278536Sassar krb5_set_error_string(context, "malloc: out of memory"); 358355682Smarkm return ENOMEM; 358478536Sassar } 3585178828Sdfr ret = _krb5_n_fold(c, len, k, res_len); 3586178828Sdfr if (ret) { 3587178828Sdfr free(k); 3588178828Sdfr krb5_set_error_string(context, "out of memory"); 3589178828Sdfr return ret; 3590178828Sdfr } 359155682Smarkm free(c); 359255682Smarkm } 359355682Smarkm 359455682Smarkm /* XXX keytype dependent post-processing */ 359555682Smarkm switch(kt->type) { 359655682Smarkm case KEYTYPE_DES3: 359755682Smarkm DES3_postproc(context, k, nblocks * et->blocksize, key); 359855682Smarkm break; 3599120948Snectar case KEYTYPE_AES128: 3600120948Snectar case KEYTYPE_AES256: 3601120948Snectar memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); 3602120948Snectar break; 360355682Smarkm default: 360478536Sassar krb5_set_error_string(context, 360578536Sassar "derive_key() called with unknown keytype (%u)", 360678536Sassar kt->type); 360755682Smarkm ret = KRB5_CRYPTO_INTERNAL; 360855682Smarkm break; 360955682Smarkm } 3610178828Sdfr if (key->schedule) { 3611178828Sdfr krb5_free_data(context, key->schedule); 3612178828Sdfr key->schedule = NULL; 3613178828Sdfr } 361455682Smarkm memset(k, 0, nblocks * et->blocksize); 361555682Smarkm free(k); 361655682Smarkm return ret; 361755682Smarkm} 361855682Smarkm 361955682Smarkmstatic struct key_data * 362055682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage) 362155682Smarkm{ 362255682Smarkm struct key_usage *d = crypto->key_usage; 362355682Smarkm d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); 362455682Smarkm if(d == NULL) 362555682Smarkm return NULL; 362655682Smarkm crypto->key_usage = d; 362755682Smarkm d += crypto->num_key_usage++; 362855682Smarkm memset(d, 0, sizeof(*d)); 362955682Smarkm d->usage = usage; 363055682Smarkm return &d->key; 363155682Smarkm} 363255682Smarkm 3633178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 363478536Sassarkrb5_derive_key(krb5_context context, 363578536Sassar const krb5_keyblock *key, 363678536Sassar krb5_enctype etype, 363778536Sassar const void *constant, 363878536Sassar size_t constant_len, 363978536Sassar krb5_keyblock **derived_key) 364078536Sassar{ 364178536Sassar krb5_error_code ret; 364278536Sassar struct encryption_type *et; 364378536Sassar struct key_data d; 364478536Sassar 3645178828Sdfr *derived_key = NULL; 3646178828Sdfr 364778536Sassar et = _find_enctype (etype); 364878536Sassar if (et == NULL) { 364978536Sassar krb5_set_error_string(context, "encryption type %d not supported", 365078536Sassar etype); 365178536Sassar return KRB5_PROG_ETYPE_NOSUPP; 365278536Sassar } 365378536Sassar 3654178828Sdfr ret = krb5_copy_keyblock(context, key, &d.key); 365578536Sassar if (ret) 365678536Sassar return ret; 365778536Sassar 365878536Sassar d.schedule = NULL; 365978536Sassar ret = derive_key(context, et, &d, constant, constant_len); 3660178828Sdfr if (ret == 0) 3661178828Sdfr ret = krb5_copy_keyblock(context, d.key, derived_key); 3662178828Sdfr free_key_data(context, &d); 366378536Sassar return ret; 366478536Sassar} 366578536Sassar 366655682Smarkmstatic krb5_error_code 366755682Smarkm_get_derived_key(krb5_context context, 366855682Smarkm krb5_crypto crypto, 366955682Smarkm unsigned usage, 367055682Smarkm struct key_data **key) 367155682Smarkm{ 367255682Smarkm int i; 367355682Smarkm struct key_data *d; 367455682Smarkm unsigned char constant[5]; 367555682Smarkm 367655682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 367755682Smarkm if(crypto->key_usage[i].usage == usage) { 367855682Smarkm *key = &crypto->key_usage[i].key; 367955682Smarkm return 0; 368055682Smarkm } 368155682Smarkm d = _new_derived_key(crypto, usage); 368278536Sassar if(d == NULL) { 368378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 368455682Smarkm return ENOMEM; 368578536Sassar } 368655682Smarkm krb5_copy_keyblock(context, crypto->key.key, &d->key); 368755682Smarkm _krb5_put_int(constant, usage, 5); 368855682Smarkm derive_key(context, crypto->et, d, constant, sizeof(constant)); 368955682Smarkm *key = d; 369055682Smarkm return 0; 369155682Smarkm} 369255682Smarkm 369355682Smarkm 3694178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 369555682Smarkmkrb5_crypto_init(krb5_context context, 369678536Sassar const krb5_keyblock *key, 369755682Smarkm krb5_enctype etype, 369855682Smarkm krb5_crypto *crypto) 369955682Smarkm{ 370055682Smarkm krb5_error_code ret; 370155682Smarkm ALLOC(*crypto, 1); 370278536Sassar if(*crypto == NULL) { 370378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 370455682Smarkm return ENOMEM; 370578536Sassar } 370655682Smarkm if(etype == ETYPE_NULL) 370755682Smarkm etype = key->keytype; 370855682Smarkm (*crypto)->et = _find_enctype(etype); 3709178828Sdfr if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { 371055682Smarkm free(*crypto); 3711178828Sdfr *crypto = NULL; 371278536Sassar krb5_set_error_string (context, "encryption type %d not supported", 371378536Sassar etype); 371455682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 371555682Smarkm } 3716102647Snectar if((*crypto)->et->keytype->size != key->keyvalue.length) { 3717102647Snectar free(*crypto); 3718178828Sdfr *crypto = NULL; 3719102647Snectar krb5_set_error_string (context, "encryption key has bad length"); 3720102647Snectar return KRB5_BAD_KEYSIZE; 3721102647Snectar } 372255682Smarkm ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); 372355682Smarkm if(ret) { 372455682Smarkm free(*crypto); 3725178828Sdfr *crypto = NULL; 372655682Smarkm return ret; 372755682Smarkm } 372855682Smarkm (*crypto)->key.schedule = NULL; 372955682Smarkm (*crypto)->num_key_usage = 0; 373055682Smarkm (*crypto)->key_usage = NULL; 373155682Smarkm return 0; 373255682Smarkm} 373355682Smarkm 373455682Smarkmstatic void 373555682Smarkmfree_key_data(krb5_context context, struct key_data *key) 373655682Smarkm{ 373755682Smarkm krb5_free_keyblock(context, key->key); 373855682Smarkm if(key->schedule) { 373955682Smarkm memset(key->schedule->data, 0, key->schedule->length); 374055682Smarkm krb5_free_data(context, key->schedule); 374155682Smarkm } 374255682Smarkm} 374355682Smarkm 374455682Smarkmstatic void 374555682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku) 374655682Smarkm{ 374755682Smarkm free_key_data(context, &ku->key); 374855682Smarkm} 374955682Smarkm 3750178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 375155682Smarkmkrb5_crypto_destroy(krb5_context context, 375255682Smarkm krb5_crypto crypto) 375355682Smarkm{ 375455682Smarkm int i; 375555682Smarkm 375655682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 375755682Smarkm free_key_usage(context, &crypto->key_usage[i]); 375855682Smarkm free(crypto->key_usage); 375955682Smarkm free_key_data(context, &crypto->key); 376055682Smarkm free (crypto); 376155682Smarkm return 0; 376255682Smarkm} 376355682Smarkm 3764178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3765103426Snectarkrb5_crypto_getblocksize(krb5_context context, 3766103426Snectar krb5_crypto crypto, 3767103426Snectar size_t *blocksize) 3768103426Snectar{ 3769103426Snectar *blocksize = crypto->et->blocksize; 3770103426Snectar return 0; 3771103426Snectar} 3772103426Snectar 3773178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3774178828Sdfrkrb5_crypto_getenctype(krb5_context context, 3775178828Sdfr krb5_crypto crypto, 3776178828Sdfr krb5_enctype *enctype) 3777178828Sdfr{ 3778178828Sdfr *enctype = crypto->et->type; 3779178828Sdfr return 0; 3780178828Sdfr} 3781178828Sdfr 3782178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3783178828Sdfrkrb5_crypto_getpadsize(krb5_context context, 3784178828Sdfr krb5_crypto crypto, 3785178828Sdfr size_t *padsize) 3786178828Sdfr{ 3787178828Sdfr *padsize = crypto->et->padsize; 3788178828Sdfr return 0; 3789178828Sdfr} 3790178828Sdfr 3791178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3792178828Sdfrkrb5_crypto_getconfoundersize(krb5_context context, 3793178828Sdfr krb5_crypto crypto, 3794178828Sdfr size_t *confoundersize) 3795178828Sdfr{ 3796178828Sdfr *confoundersize = crypto->et->confoundersize; 3797178828Sdfr return 0; 3798178828Sdfr} 3799178828Sdfr 3800178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3801178828Sdfrkrb5_enctype_disable(krb5_context context, 3802178828Sdfr krb5_enctype enctype) 3803178828Sdfr{ 3804178828Sdfr struct encryption_type *et = _find_enctype(enctype); 3805178828Sdfr if(et == NULL) { 3806178828Sdfr if (context) 3807178828Sdfr krb5_set_error_string (context, "encryption type %d not supported", 3808178828Sdfr enctype); 3809178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 3810178828Sdfr } 3811178828Sdfr et->flags |= F_DISABLED; 3812178828Sdfr return 0; 3813178828Sdfr} 3814178828Sdfr 3815178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 381655682Smarkmkrb5_string_to_key_derived(krb5_context context, 381755682Smarkm const void *str, 381855682Smarkm size_t len, 381955682Smarkm krb5_enctype etype, 382055682Smarkm krb5_keyblock *key) 382155682Smarkm{ 382255682Smarkm struct encryption_type *et = _find_enctype(etype); 382355682Smarkm krb5_error_code ret; 382455682Smarkm struct key_data kd; 3825178828Sdfr size_t keylen; 382655682Smarkm u_char *tmp; 382755682Smarkm 382878536Sassar if(et == NULL) { 382978536Sassar krb5_set_error_string (context, "encryption type %d not supported", 383078536Sassar etype); 383155682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 383278536Sassar } 3833178828Sdfr keylen = et->keytype->bits / 8; 3834178828Sdfr 383555682Smarkm ALLOC(kd.key, 1); 383690929Snectar if(kd.key == NULL) { 383790929Snectar krb5_set_error_string (context, "malloc: out of memory"); 383890929Snectar return ENOMEM; 383990929Snectar } 384090929Snectar ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); 384190929Snectar if(ret) { 384290929Snectar free(kd.key); 384390929Snectar return ret; 384490929Snectar } 384555682Smarkm kd.key->keytype = etype; 384690929Snectar tmp = malloc (keylen); 384790929Snectar if(tmp == NULL) { 384890929Snectar krb5_free_keyblock(context, kd.key); 384990929Snectar krb5_set_error_string (context, "malloc: out of memory"); 385090929Snectar return ENOMEM; 385190929Snectar } 3852178828Sdfr ret = _krb5_n_fold(str, len, tmp, keylen); 3853178828Sdfr if (ret) { 3854178828Sdfr free(tmp); 3855178828Sdfr krb5_set_error_string(context, "out of memory"); 3856178828Sdfr return ret; 3857178828Sdfr } 385855682Smarkm kd.schedule = NULL; 385990929Snectar DES3_postproc (context, tmp, keylen, &kd); /* XXX */ 386090929Snectar memset(tmp, 0, keylen); 386190929Snectar free(tmp); 386290929Snectar ret = derive_key(context, 386355682Smarkm et, 386455682Smarkm &kd, 386555682Smarkm "kerberos", /* XXX well known constant */ 386655682Smarkm strlen("kerberos")); 386755682Smarkm ret = krb5_copy_keyblock_contents(context, kd.key, key); 386855682Smarkm free_key_data(context, &kd); 386955682Smarkm return ret; 387055682Smarkm} 387155682Smarkm 387272448Sassarstatic size_t 387372448Sassarwrapped_length (krb5_context context, 387472448Sassar krb5_crypto crypto, 387572448Sassar size_t data_len) 387672448Sassar{ 387772448Sassar struct encryption_type *et = crypto->et; 3878120948Snectar size_t padsize = et->padsize; 3879178828Sdfr size_t checksumsize = CHECKSUMSIZE(et->checksum); 388072448Sassar size_t res; 388172448Sassar 3882178828Sdfr res = et->confoundersize + checksumsize + data_len; 3883120948Snectar res = (res + padsize - 1) / padsize * padsize; 388472448Sassar return res; 388572448Sassar} 388672448Sassar 388772448Sassarstatic size_t 388872448Sassarwrapped_length_dervied (krb5_context context, 388972448Sassar krb5_crypto crypto, 389072448Sassar size_t data_len) 389172448Sassar{ 389272448Sassar struct encryption_type *et = crypto->et; 3893120948Snectar size_t padsize = et->padsize; 389472448Sassar size_t res; 389572448Sassar 389672448Sassar res = et->confoundersize + data_len; 3897120948Snectar res = (res + padsize - 1) / padsize * padsize; 3898178828Sdfr if (et->keyed_checksum) 3899178828Sdfr res += et->keyed_checksum->checksumsize; 3900178828Sdfr else 3901178828Sdfr res += et->checksum->checksumsize; 390272448Sassar return res; 390372448Sassar} 390472448Sassar 390555682Smarkm/* 390655682Smarkm * Return the size of an encrypted packet of length `data_len' 390755682Smarkm */ 390855682Smarkm 390955682Smarkmsize_t 391055682Smarkmkrb5_get_wrapped_length (krb5_context context, 391155682Smarkm krb5_crypto crypto, 391255682Smarkm size_t data_len) 391355682Smarkm{ 391472448Sassar if (derived_crypto (context, crypto)) 391572448Sassar return wrapped_length_dervied (context, crypto, data_len); 391672448Sassar else 391772448Sassar return wrapped_length (context, crypto, data_len); 391855682Smarkm} 391955682Smarkm 3920178828Sdfr/* 3921178828Sdfr * Return the size of an encrypted packet of length `data_len' 3922178828Sdfr */ 3923178828Sdfr 3924178828Sdfrstatic size_t 3925178828Sdfrcrypto_overhead (krb5_context context, 3926178828Sdfr krb5_crypto crypto) 3927178828Sdfr{ 3928178828Sdfr struct encryption_type *et = crypto->et; 3929178828Sdfr size_t res; 3930178828Sdfr 3931178828Sdfr res = CHECKSUMSIZE(et->checksum); 3932178828Sdfr res += et->confoundersize; 3933178828Sdfr if (et->padsize > 1) 3934178828Sdfr res += et->padsize; 3935178828Sdfr return res; 3936178828Sdfr} 3937178828Sdfr 3938178828Sdfrstatic size_t 3939178828Sdfrcrypto_overhead_dervied (krb5_context context, 3940178828Sdfr krb5_crypto crypto) 3941178828Sdfr{ 3942178828Sdfr struct encryption_type *et = crypto->et; 3943178828Sdfr size_t res; 3944178828Sdfr 3945178828Sdfr if (et->keyed_checksum) 3946178828Sdfr res = CHECKSUMSIZE(et->keyed_checksum); 3947178828Sdfr else 3948178828Sdfr res = CHECKSUMSIZE(et->checksum); 3949178828Sdfr res += et->confoundersize; 3950178828Sdfr if (et->padsize > 1) 3951178828Sdfr res += et->padsize; 3952178828Sdfr return res; 3953178828Sdfr} 3954178828Sdfr 3955178828Sdfrsize_t 3956178828Sdfrkrb5_crypto_overhead (krb5_context context, krb5_crypto crypto) 3957178828Sdfr{ 3958178828Sdfr if (derived_crypto (context, crypto)) 3959178828Sdfr return crypto_overhead_dervied (context, crypto); 3960178828Sdfr else 3961178828Sdfr return crypto_overhead (context, crypto); 3962178828Sdfr} 3963178828Sdfr 3964178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 3965178828Sdfrkrb5_random_to_key(krb5_context context, 3966178828Sdfr krb5_enctype type, 3967178828Sdfr const void *data, 3968178828Sdfr size_t size, 3969178828Sdfr krb5_keyblock *key) 3970178828Sdfr{ 3971178828Sdfr krb5_error_code ret; 3972178828Sdfr struct encryption_type *et = _find_enctype(type); 3973178828Sdfr if(et == NULL) { 3974178828Sdfr krb5_set_error_string(context, "encryption type %d not supported", 3975178828Sdfr type); 3976178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 3977178828Sdfr } 3978178828Sdfr if ((et->keytype->bits + 7) / 8 > size) { 3979178828Sdfr krb5_set_error_string(context, "encryption key %s needs %d bytes " 3980178828Sdfr "of random to make an encryption key out of it", 3981178828Sdfr et->name, (int)et->keytype->size); 3982178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 3983178828Sdfr } 3984178828Sdfr ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 3985178828Sdfr if(ret) 3986178828Sdfr return ret; 3987178828Sdfr key->keytype = type; 3988178828Sdfr if (et->keytype->random_to_key) 3989178828Sdfr (*et->keytype->random_to_key)(context, key, data, size); 3990178828Sdfr else 3991178828Sdfr memcpy(key->keyvalue.data, data, et->keytype->size); 3992178828Sdfr 3993178828Sdfr return 0; 3994178828Sdfr} 3995178828Sdfr 3996178828Sdfrkrb5_error_code 3997178828Sdfr_krb5_pk_octetstring2key(krb5_context context, 3998178828Sdfr krb5_enctype type, 3999178828Sdfr const void *dhdata, 4000178828Sdfr size_t dhsize, 4001178828Sdfr const heim_octet_string *c_n, 4002178828Sdfr const heim_octet_string *k_n, 4003178828Sdfr krb5_keyblock *key) 4004178828Sdfr{ 4005178828Sdfr struct encryption_type *et = _find_enctype(type); 4006178828Sdfr krb5_error_code ret; 4007178828Sdfr size_t keylen, offset; 4008178828Sdfr void *keydata; 4009178828Sdfr unsigned char counter; 4010178828Sdfr unsigned char shaoutput[20]; 4011178828Sdfr 4012178828Sdfr if(et == NULL) { 4013178828Sdfr krb5_set_error_string(context, "encryption type %d not supported", 4014178828Sdfr type); 4015178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 4016178828Sdfr } 4017178828Sdfr keylen = (et->keytype->bits + 7) / 8; 4018178828Sdfr 4019178828Sdfr keydata = malloc(keylen); 4020178828Sdfr if (keydata == NULL) { 4021178828Sdfr krb5_set_error_string(context, "malloc: out of memory"); 4022178828Sdfr return ENOMEM; 4023178828Sdfr } 4024178828Sdfr 4025178828Sdfr counter = 0; 4026178828Sdfr offset = 0; 4027178828Sdfr do { 4028178828Sdfr SHA_CTX m; 4029178828Sdfr 4030178828Sdfr SHA1_Init(&m); 4031178828Sdfr SHA1_Update(&m, &counter, 1); 4032178828Sdfr SHA1_Update(&m, dhdata, dhsize); 4033178828Sdfr if (c_n) 4034178828Sdfr SHA1_Update(&m, c_n->data, c_n->length); 4035178828Sdfr if (k_n) 4036178828Sdfr SHA1_Update(&m, k_n->data, k_n->length); 4037178828Sdfr SHA1_Final(shaoutput, &m); 4038178828Sdfr 4039178828Sdfr memcpy((unsigned char *)keydata + offset, 4040178828Sdfr shaoutput, 4041178828Sdfr min(keylen - offset, sizeof(shaoutput))); 4042178828Sdfr 4043178828Sdfr offset += sizeof(shaoutput); 4044178828Sdfr counter++; 4045178828Sdfr } while(offset < keylen); 4046178828Sdfr memset(shaoutput, 0, sizeof(shaoutput)); 4047178828Sdfr 4048178828Sdfr ret = krb5_random_to_key(context, type, keydata, keylen, key); 4049178828Sdfr memset(keydata, 0, sizeof(keylen)); 4050178828Sdfr free(keydata); 4051178828Sdfr return ret; 4052178828Sdfr} 4053178828Sdfr 4054178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 4055178828Sdfrkrb5_crypto_prf_length(krb5_context context, 4056178828Sdfr krb5_enctype type, 4057178828Sdfr size_t *length) 4058178828Sdfr{ 4059178828Sdfr struct encryption_type *et = _find_enctype(type); 4060178828Sdfr 4061178828Sdfr if(et == NULL || et->prf_length == 0) { 4062178828Sdfr krb5_set_error_string(context, "encryption type %d not supported", 4063178828Sdfr type); 4064178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 4065178828Sdfr } 4066178828Sdfr 4067178828Sdfr *length = et->prf_length; 4068178828Sdfr return 0; 4069178828Sdfr} 4070178828Sdfr 4071178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION 4072178828Sdfrkrb5_crypto_prf(krb5_context context, 4073178828Sdfr const krb5_crypto crypto, 4074178828Sdfr const krb5_data *input, 4075178828Sdfr krb5_data *output) 4076178828Sdfr{ 4077178828Sdfr struct encryption_type *et = crypto->et; 4078178828Sdfr 4079178828Sdfr krb5_data_zero(output); 4080178828Sdfr 4081178828Sdfr if(et->prf == NULL) { 4082178828Sdfr krb5_set_error_string(context, "kerberos prf for %s not supported", 4083178828Sdfr et->name); 4084178828Sdfr return KRB5_PROG_ETYPE_NOSUPP; 4085178828Sdfr } 4086178828Sdfr 4087178828Sdfr return (*et->prf)(context, crypto, input, output); 4088178828Sdfr} 4089178828Sdfr 4090178828Sdfr 4091178828Sdfr 4092178828Sdfr 409355682Smarkm#ifdef CRYPTO_DEBUG 409455682Smarkm 409555682Smarkmstatic krb5_error_code 409655682Smarkmkrb5_get_keyid(krb5_context context, 409755682Smarkm krb5_keyblock *key, 4098178828Sdfr uint32_t *keyid) 409955682Smarkm{ 410057416Smarkm MD5_CTX md5; 410155682Smarkm unsigned char tmp[16]; 410257416Smarkm 410372448Sassar MD5_Init (&md5); 410472448Sassar MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); 410572448Sassar MD5_Final (tmp, &md5); 410655682Smarkm *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; 410755682Smarkm return 0; 410855682Smarkm} 410955682Smarkm 411055682Smarkmstatic void 411155682Smarkmkrb5_crypto_debug(krb5_context context, 4112178828Sdfr int encryptp, 411355682Smarkm size_t len, 411455682Smarkm krb5_keyblock *key) 411555682Smarkm{ 4116178828Sdfr uint32_t keyid; 411755682Smarkm char *kt; 411855682Smarkm krb5_get_keyid(context, key, &keyid); 411955682Smarkm krb5_enctype_to_string(context, key->keytype, &kt); 412055682Smarkm krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", 4121178828Sdfr encryptp ? "encrypting" : "decrypting", 412255682Smarkm (unsigned long)len, 412355682Smarkm keyid, 412455682Smarkm kt); 412555682Smarkm free(kt); 412655682Smarkm} 412755682Smarkm 412855682Smarkm#endif /* CRYPTO_DEBUG */ 412972448Sassar 413072448Sassar#if 0 413172448Sassarint 413272448Sassarmain() 413372448Sassar{ 413472448Sassar#if 0 413572448Sassar int i; 413672448Sassar krb5_context context; 413772448Sassar krb5_crypto crypto; 413872448Sassar struct key_data *d; 413972448Sassar krb5_keyblock key; 414072448Sassar char constant[4]; 414172448Sassar unsigned usage = ENCRYPTION_USAGE(3); 414272448Sassar krb5_error_code ret; 414372448Sassar 414472448Sassar ret = krb5_init_context(&context); 414572448Sassar if (ret) 414672448Sassar errx (1, "krb5_init_context failed: %d", ret); 414772448Sassar 414872448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 414972448Sassar key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" 415072448Sassar "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" 415172448Sassar "\xc8\xdf\xab\x26\x86\x64\x15\x25"; 415272448Sassar key.keyvalue.length = 24; 415372448Sassar 415472448Sassar krb5_crypto_init(context, &key, 0, &crypto); 415572448Sassar 415672448Sassar d = _new_derived_key(crypto, usage); 415772448Sassar if(d == NULL) 4158178828Sdfr krb5_errx(context, 1, "_new_derived_key failed"); 415972448Sassar krb5_copy_keyblock(context, crypto->key.key, &d->key); 416072448Sassar _krb5_put_int(constant, usage, 4); 416172448Sassar derive_key(context, crypto->et, d, constant, sizeof(constant)); 416272448Sassar return 0; 416372448Sassar#else 416472448Sassar int i; 416572448Sassar krb5_context context; 416672448Sassar krb5_crypto crypto; 416772448Sassar struct key_data *d; 416872448Sassar krb5_keyblock key; 416972448Sassar krb5_error_code ret; 417072448Sassar Checksum res; 417172448Sassar 417272448Sassar char *data = "what do ya want for nothing?"; 417372448Sassar 417472448Sassar ret = krb5_init_context(&context); 417572448Sassar if (ret) 417672448Sassar errx (1, "krb5_init_context failed: %d", ret); 417772448Sassar 417872448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 417972448Sassar key.keyvalue.data = "Jefe"; 418072448Sassar /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 418172448Sassar "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ 418272448Sassar key.keyvalue.length = 4; 418372448Sassar 4184178828Sdfr d = ecalloc(1, sizeof(*d)); 418572448Sassar d->key = &key; 418672448Sassar res.checksum.length = 20; 4187178828Sdfr res.checksum.data = emalloc(res.checksum.length); 4188120948Snectar SP_HMAC_SHA1_checksum(context, d, data, 28, &res); 418972448Sassar 419072448Sassar return 0; 419172448Sassar#endif 419272448Sassar} 419372448Sassar#endif 4194