crypto.c revision 120948
155682Smarkm/* 2120948Snectar * Copyright (c) 1997 - 2003 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" 35120948SnectarRCSID("$Id: crypto.c,v 1.73 2003/04/01 16:51:54 lha Exp $"); 3657428Smarkm/* RCSID("$FreeBSD: head/crypto/heimdal/lib/krb5/crypto.c 120948 2003-10-09 19:42:07Z nectar $"); */ 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 */ 7055682Smarkm 7155682Smarkmstruct salt_type { 7255682Smarkm krb5_salttype type; 7355682Smarkm const char *name; 7455682Smarkm krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, 75120948Snectar krb5_salt, krb5_data, krb5_keyblock*); 7655682Smarkm}; 7755682Smarkm 7855682Smarkmstruct key_type { 7955682Smarkm krb5_keytype type; /* XXX */ 8055682Smarkm const char *name; 8155682Smarkm size_t bits; 8255682Smarkm size_t size; 8355682Smarkm size_t schedule_size; 8455682Smarkm#if 0 8555682Smarkm krb5_enctype best_etype; 8655682Smarkm#endif 8755682Smarkm void (*random_key)(krb5_context, krb5_keyblock*); 8855682Smarkm void (*schedule)(krb5_context, struct key_data *); 8955682Smarkm struct salt_type *string_to_key; 9055682Smarkm}; 9155682Smarkm 9255682Smarkmstruct checksum_type { 9355682Smarkm krb5_cksumtype type; 9455682Smarkm const char *name; 9555682Smarkm size_t blocksize; 9655682Smarkm size_t checksumsize; 9755682Smarkm unsigned flags; 9872448Sassar void (*checksum)(krb5_context context, 9972448Sassar struct key_data *key, 10072448Sassar const void *buf, size_t len, 10172448Sassar unsigned usage, 10272448Sassar Checksum *csum); 10372448Sassar krb5_error_code (*verify)(krb5_context context, 10472448Sassar struct key_data *key, 10572448Sassar const void *buf, size_t len, 10672448Sassar unsigned usage, 10772448Sassar Checksum *csum); 10855682Smarkm}; 10955682Smarkm 11055682Smarkmstruct encryption_type { 11155682Smarkm krb5_enctype type; 11255682Smarkm const char *name; 11355682Smarkm size_t blocksize; 114120948Snectar size_t padsize; 11555682Smarkm size_t confoundersize; 11655682Smarkm struct key_type *keytype; 11778536Sassar struct checksum_type *checksum; 11855682Smarkm struct checksum_type *keyed_checksum; 11955682Smarkm unsigned flags; 12078536Sassar krb5_error_code (*encrypt)(krb5_context context, 12178536Sassar struct key_data *key, 12272448Sassar void *data, size_t len, 12372448Sassar krb5_boolean encrypt, 12472448Sassar int usage, 12572448Sassar void *ivec); 12655682Smarkm}; 12755682Smarkm 12855682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) 12955682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) 13055682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) 13155682Smarkm 13255682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type); 13355682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type); 13455682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type); 13555682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 13655682Smarkm unsigned, struct key_data**); 13755682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); 138120948Snectarstatic krb5_error_code derive_key(krb5_context context, 139120948Snectar struct encryption_type *et, 140120948Snectar struct key_data *key, 141120948Snectar const void *constant, 142120948Snectar size_t len); 143120948Snectarstatic void hmac(krb5_context context, 144120948Snectar struct checksum_type *cm, 145120948Snectar const void *data, 146120948Snectar size_t len, 147120948Snectar unsigned usage, 148120948Snectar struct key_data *keyblock, 149120948Snectar Checksum *result); 150120948Snectarstatic void free_key_data(krb5_context context, struct key_data *key); 15155682Smarkm 15255682Smarkm/************************************************************ 15355682Smarkm * * 15455682Smarkm ************************************************************/ 15555682Smarkm 15655682Smarkmstatic void 157102647Snectarkrb5_DES_random_key(krb5_context context, 15855682Smarkm krb5_keyblock *key) 15955682Smarkm{ 16055682Smarkm des_cblock *k = key->keyvalue.data; 16155682Smarkm do { 16255682Smarkm krb5_generate_random_block(k, sizeof(des_cblock)); 16355682Smarkm des_set_odd_parity(k); 16455682Smarkm } while(des_is_weak_key(k)); 16555682Smarkm} 16655682Smarkm 16755682Smarkmstatic void 168102647Snectarkrb5_DES_schedule(krb5_context context, 16955682Smarkm struct key_data *key) 17055682Smarkm{ 17155682Smarkm des_set_key(key->key->keyvalue.data, key->schedule->data); 17255682Smarkm} 17355682Smarkm 17490929Snectarstatic void 17590929SnectarDES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key) 17690929Snectar{ 17790929Snectar des_key_schedule schedule; 17890929Snectar int i; 17990929Snectar int reverse = 0; 18090929Snectar unsigned char *p; 18190929Snectar 18290929Snectar unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 18390929Snectar 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; 18490929Snectar memset(key, 0, 8); 18590929Snectar 18690929Snectar p = (unsigned char*)key; 18790929Snectar for (i = 0; i < length; i++) { 18890929Snectar unsigned char tmp = data[i]; 18990929Snectar if (!reverse) 19090929Snectar *p++ ^= (tmp << 1); 19190929Snectar else 19290929Snectar *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; 19390929Snectar if((i % 8) == 7) 19490929Snectar reverse = !reverse; 19590929Snectar } 19690929Snectar des_set_odd_parity(key); 19790929Snectar if(des_is_weak_key(key)) 19890929Snectar (*key)[7] ^= 0xF0; 19990929Snectar des_set_key(key, schedule); 20090929Snectar des_cbc_cksum((void*)data, key, length, schedule, key); 20190929Snectar memset(schedule, 0, sizeof(schedule)); 20290929Snectar des_set_odd_parity(key); 20390929Snectar} 20490929Snectar 20555682Smarkmstatic krb5_error_code 206102647Snectarkrb5_DES_string_to_key(krb5_context context, 20755682Smarkm krb5_enctype enctype, 20855682Smarkm krb5_data password, 20955682Smarkm krb5_salt salt, 210120948Snectar krb5_data opaque, 21155682Smarkm krb5_keyblock *key) 21255682Smarkm{ 21390929Snectar unsigned char *s; 21455682Smarkm size_t len; 21555682Smarkm des_cblock tmp; 21655682Smarkm 21790929Snectar len = password.length + salt.saltvalue.length; 21855682Smarkm s = malloc(len); 21990929Snectar if(len > 0 && s == NULL) { 22078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 22155682Smarkm return ENOMEM; 22278536Sassar } 22355682Smarkm memcpy(s, password.data, password.length); 22455682Smarkm memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 22590929Snectar DES_string_to_key_int(s, len, &tmp); 22655682Smarkm key->keytype = enctype; 22755682Smarkm krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 22855682Smarkm memset(&tmp, 0, sizeof(tmp)); 22955682Smarkm memset(s, 0, len); 23055682Smarkm free(s); 23155682Smarkm return 0; 23255682Smarkm} 23355682Smarkm 23455682Smarkm/* This defines the Andrew string_to_key function. It accepts a password 23555682Smarkm * string as input and converts its via a one-way encryption algorithm to a DES 23655682Smarkm * encryption key. It is compatible with the original Andrew authentication 23755682Smarkm * service password database. 23855682Smarkm */ 23955682Smarkm 24055682Smarkm/* 24155682Smarkm * Short passwords, i.e 8 characters or less. 24255682Smarkm */ 24355682Smarkmstatic void 244102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw, 24555682Smarkm krb5_data cell, 24655682Smarkm des_cblock *key) 24755682Smarkm{ 24855682Smarkm char password[8+1]; /* crypt is limited to 8 chars anyway */ 24955682Smarkm int i; 25055682Smarkm 25155682Smarkm for(i = 0; i < 8; i++) { 25255682Smarkm char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ 25372448Sassar ((i < cell.length) ? 25472448Sassar tolower(((unsigned char*)cell.data)[i]) : 0); 25555682Smarkm password[i] = c ? c : 'X'; 25655682Smarkm } 25755682Smarkm password[8] = '\0'; 25855682Smarkm 259120948Snectar memcpy(key, crypt(password, "p1") + 2, sizeof(des_cblock)); 26055682Smarkm 26155682Smarkm /* parity is inserted into the LSB so left shift each byte up one 26255682Smarkm bit. This allows ascii characters with a zero MSB to retain as 26355682Smarkm much significance as possible. */ 26455682Smarkm for (i = 0; i < sizeof(des_cblock); i++) 26555682Smarkm ((unsigned char*)key)[i] <<= 1; 26655682Smarkm des_set_odd_parity (key); 26755682Smarkm} 26855682Smarkm 26955682Smarkm/* 27055682Smarkm * Long passwords, i.e 9 characters or more. 27155682Smarkm */ 27255682Smarkmstatic void 273102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, 27455682Smarkm krb5_data cell, 27555682Smarkm des_cblock *key) 27655682Smarkm{ 27755682Smarkm des_key_schedule schedule; 27855682Smarkm des_cblock temp_key; 27955682Smarkm des_cblock ivec; 28055682Smarkm char password[512]; 28155682Smarkm size_t passlen; 28255682Smarkm 28355682Smarkm memcpy(password, pw.data, min(pw.length, sizeof(password))); 28472448Sassar if(pw.length < sizeof(password)) { 28572448Sassar int len = min(cell.length, sizeof(password) - pw.length); 28672448Sassar int i; 28772448Sassar 28872448Sassar memcpy(password + pw.length, cell.data, len); 28972448Sassar for (i = pw.length; i < pw.length + len; ++i) 29072448Sassar password[i] = tolower((unsigned char)password[i]); 29172448Sassar } 29255682Smarkm passlen = min(sizeof(password), pw.length + cell.length); 29355682Smarkm memcpy(&ivec, "kerberos", 8); 29455682Smarkm memcpy(&temp_key, "kerberos", 8); 29555682Smarkm des_set_odd_parity (&temp_key); 29655682Smarkm des_set_key (&temp_key, schedule); 29790929Snectar des_cbc_cksum (password, &ivec, passlen, schedule, &ivec); 29855682Smarkm 29955682Smarkm memcpy(&temp_key, &ivec, 8); 30055682Smarkm des_set_odd_parity (&temp_key); 30155682Smarkm des_set_key (&temp_key, schedule); 30290929Snectar des_cbc_cksum (password, key, passlen, schedule, &ivec); 30355682Smarkm memset(&schedule, 0, sizeof(schedule)); 30455682Smarkm memset(&temp_key, 0, sizeof(temp_key)); 30555682Smarkm memset(&ivec, 0, sizeof(ivec)); 30655682Smarkm memset(password, 0, sizeof(password)); 30755682Smarkm 30855682Smarkm des_set_odd_parity (key); 30955682Smarkm} 31055682Smarkm 31155682Smarkmstatic krb5_error_code 31255682SmarkmDES_AFS3_string_to_key(krb5_context context, 31355682Smarkm krb5_enctype enctype, 31455682Smarkm krb5_data password, 31555682Smarkm krb5_salt salt, 316120948Snectar krb5_data opaque, 31755682Smarkm krb5_keyblock *key) 31855682Smarkm{ 31955682Smarkm des_cblock tmp; 32055682Smarkm if(password.length > 8) 321102647Snectar krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); 32255682Smarkm else 323102647Snectar krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); 32455682Smarkm key->keytype = enctype; 32555682Smarkm krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 32655682Smarkm memset(&key, 0, sizeof(key)); 32755682Smarkm return 0; 32855682Smarkm} 32955682Smarkm 33055682Smarkmstatic void 33155682SmarkmDES3_random_key(krb5_context context, 33255682Smarkm krb5_keyblock *key) 33355682Smarkm{ 33455682Smarkm des_cblock *k = key->keyvalue.data; 33555682Smarkm do { 33655682Smarkm krb5_generate_random_block(k, 3 * sizeof(des_cblock)); 33755682Smarkm des_set_odd_parity(&k[0]); 33855682Smarkm des_set_odd_parity(&k[1]); 33955682Smarkm des_set_odd_parity(&k[2]); 34055682Smarkm } while(des_is_weak_key(&k[0]) || 34155682Smarkm des_is_weak_key(&k[1]) || 34255682Smarkm des_is_weak_key(&k[2])); 34355682Smarkm} 34455682Smarkm 34555682Smarkmstatic void 34655682SmarkmDES3_schedule(krb5_context context, 34755682Smarkm struct key_data *key) 34855682Smarkm{ 34955682Smarkm des_cblock *k = key->key->keyvalue.data; 35055682Smarkm des_key_schedule *s = key->schedule->data; 35155682Smarkm des_set_key(&k[0], s[0]); 35255682Smarkm des_set_key(&k[1], s[1]); 35355682Smarkm des_set_key(&k[2], s[2]); 35455682Smarkm} 35555682Smarkm 35655682Smarkm/* 35755682Smarkm * A = A xor B. A & B are 8 bytes. 35855682Smarkm */ 35955682Smarkm 36055682Smarkmstatic void 36155682Smarkmxor (des_cblock *key, const unsigned char *b) 36255682Smarkm{ 36355682Smarkm unsigned char *a = (unsigned char*)key; 36455682Smarkm a[0] ^= b[0]; 36555682Smarkm a[1] ^= b[1]; 36655682Smarkm a[2] ^= b[2]; 36755682Smarkm a[3] ^= b[3]; 36855682Smarkm a[4] ^= b[4]; 36955682Smarkm a[5] ^= b[5]; 37055682Smarkm a[6] ^= b[6]; 37155682Smarkm a[7] ^= b[7]; 37255682Smarkm} 37355682Smarkm 37455682Smarkmstatic krb5_error_code 37555682SmarkmDES3_string_to_key(krb5_context context, 37655682Smarkm krb5_enctype enctype, 37755682Smarkm krb5_data password, 37855682Smarkm krb5_salt salt, 379120948Snectar krb5_data opaque, 38055682Smarkm krb5_keyblock *key) 38155682Smarkm{ 38255682Smarkm char *str; 38355682Smarkm size_t len; 38455682Smarkm unsigned char tmp[24]; 38555682Smarkm des_cblock keys[3]; 38655682Smarkm 38755682Smarkm len = password.length + salt.saltvalue.length; 38855682Smarkm str = malloc(len); 38978536Sassar if(len != 0 && str == NULL) { 39078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 39155682Smarkm return ENOMEM; 39278536Sassar } 39355682Smarkm memcpy(str, password.data, password.length); 39455682Smarkm memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); 39555682Smarkm { 39655682Smarkm des_cblock ivec; 39755682Smarkm des_key_schedule s[3]; 39855682Smarkm int i; 39955682Smarkm 40055682Smarkm _krb5_n_fold(str, len, tmp, 24); 40155682Smarkm 40255682Smarkm for(i = 0; i < 3; i++){ 40355682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 40455682Smarkm des_set_odd_parity(keys + i); 40555682Smarkm if(des_is_weak_key(keys + i)) 406102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 40755682Smarkm des_set_key(keys + i, s[i]); 40855682Smarkm } 40955682Smarkm memset(&ivec, 0, sizeof(ivec)); 41090929Snectar des_ede3_cbc_encrypt(tmp, 41190929Snectar tmp, sizeof(tmp), 41255682Smarkm s[0], s[1], s[2], &ivec, DES_ENCRYPT); 41355682Smarkm memset(s, 0, sizeof(s)); 41455682Smarkm memset(&ivec, 0, sizeof(ivec)); 41555682Smarkm for(i = 0; i < 3; i++){ 41655682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 41755682Smarkm des_set_odd_parity(keys + i); 41855682Smarkm if(des_is_weak_key(keys + i)) 419102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 42055682Smarkm } 42155682Smarkm memset(tmp, 0, sizeof(tmp)); 42255682Smarkm } 42355682Smarkm key->keytype = enctype; 42455682Smarkm krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); 42555682Smarkm memset(keys, 0, sizeof(keys)); 42655682Smarkm memset(str, 0, len); 42755682Smarkm free(str); 42855682Smarkm return 0; 42955682Smarkm} 43055682Smarkm 43155682Smarkmstatic krb5_error_code 43255682SmarkmDES3_string_to_key_derived(krb5_context context, 43355682Smarkm krb5_enctype enctype, 43455682Smarkm krb5_data password, 43555682Smarkm krb5_salt salt, 436120948Snectar krb5_data opaque, 43755682Smarkm krb5_keyblock *key) 43855682Smarkm{ 43955682Smarkm krb5_error_code ret; 44055682Smarkm size_t len = password.length + salt.saltvalue.length; 44155682Smarkm char *s; 44255682Smarkm 44355682Smarkm s = malloc(len); 44478536Sassar if(len != 0 && s == NULL) { 44578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 44655682Smarkm return ENOMEM; 44778536Sassar } 44855682Smarkm memcpy(s, password.data, password.length); 44955682Smarkm memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 45055682Smarkm ret = krb5_string_to_key_derived(context, 45155682Smarkm s, 45255682Smarkm len, 45355682Smarkm enctype, 45455682Smarkm key); 45555682Smarkm memset(s, 0, len); 45655682Smarkm free(s); 45755682Smarkm return ret; 45855682Smarkm} 45955682Smarkm 46055682Smarkm/* 46155682Smarkm * ARCFOUR 46255682Smarkm */ 46355682Smarkm 46455682Smarkmstatic void 46555682SmarkmARCFOUR_random_key(krb5_context context, krb5_keyblock *key) 46655682Smarkm{ 46755682Smarkm krb5_generate_random_block (key->keyvalue.data, 46855682Smarkm key->keyvalue.length); 46955682Smarkm} 47055682Smarkm 47155682Smarkmstatic void 47255682SmarkmARCFOUR_schedule(krb5_context context, struct key_data *kd) 47355682Smarkm{ 47455682Smarkm RC4_set_key (kd->schedule->data, 47555682Smarkm kd->key->keyvalue.length, kd->key->keyvalue.data); 47655682Smarkm} 47755682Smarkm 47855682Smarkmstatic krb5_error_code 47955682SmarkmARCFOUR_string_to_key(krb5_context context, 48055682Smarkm krb5_enctype enctype, 48155682Smarkm krb5_data password, 48255682Smarkm krb5_salt salt, 483120948Snectar krb5_data opaque, 48455682Smarkm krb5_keyblock *key) 48555682Smarkm{ 48655682Smarkm char *s, *p; 48755682Smarkm size_t len; 48855682Smarkm int i; 48957416Smarkm MD4_CTX m; 49055682Smarkm 49172448Sassar len = 2 * password.length; 49255682Smarkm s = malloc (len); 49378536Sassar if (len != 0 && s == NULL) { 49478536Sassar krb5_set_error_string(context, "malloc: out of memory"); 49555682Smarkm return ENOMEM; 49678536Sassar } 49755682Smarkm for (p = s, i = 0; i < password.length; ++i) { 49855682Smarkm *p++ = ((char *)password.data)[i]; 49955682Smarkm *p++ = 0; 50055682Smarkm } 50172448Sassar MD4_Init (&m); 50272448Sassar MD4_Update (&m, s, len); 50355682Smarkm key->keytype = enctype; 50455682Smarkm krb5_data_alloc (&key->keyvalue, 16); 50572448Sassar MD4_Final (key->keyvalue.data, &m); 50655682Smarkm memset (s, 0, len); 50755682Smarkm free (s); 50855682Smarkm return 0; 50955682Smarkm} 51055682Smarkm 511120948Snectar#ifdef ENABLE_AES 512120948Snectar/* 513120948Snectar * AES 514120948Snectar */ 515120948Snectar 516120948Snectar/* iter is really 1 based, so iter == 0 will be 1 iteration */ 517120948Snectar 518120948Snectarkrb5_error_code 519120948Snectarkrb5_PKCS5_PBKDF2(krb5_context context, krb5_cksumtype cktype, 520120948Snectar krb5_data password, krb5_salt salt, u_int32_t iter, 521120948Snectar krb5_keytype type, krb5_keyblock *key) 522120948Snectar{ 523120948Snectar struct checksum_type *c = _find_checksum(cktype); 524120948Snectar struct key_type *kt; 525120948Snectar size_t datalen, leftofkey; 526120948Snectar krb5_error_code ret; 527120948Snectar u_int32_t keypart; 528120948Snectar struct key_data ksign; 529120948Snectar krb5_keyblock kb; 530120948Snectar Checksum result; 531120948Snectar char *data, *tmpcksum; 532120948Snectar int i, j; 533120948Snectar char *p; 534120948Snectar 535120948Snectar if (c == NULL) { 536120948Snectar krb5_set_error_string(context, "checksum %d not supported", cktype); 537120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; 538120948Snectar } 539120948Snectar 540120948Snectar kt = _find_keytype(type); 541120948Snectar if (kt == NULL) { 542120948Snectar krb5_set_error_string(context, "key type %d not supported", type); 543120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; 544120948Snectar } 545120948Snectar 546120948Snectar key->keytype = type; 547120948Snectar ret = krb5_data_alloc (&key->keyvalue, kt->bits / 8); 548120948Snectar if (ret) { 549120948Snectar krb5_set_error_string(context, "malloc: out of memory"); 550120948Snectar return ret; 551120948Snectar } 552120948Snectar 553120948Snectar ret = krb5_data_alloc (&result.checksum, c->checksumsize); 554120948Snectar if (ret) { 555120948Snectar krb5_set_error_string(context, "malloc: out of memory"); 556120948Snectar krb5_data_free (&key->keyvalue); 557120948Snectar return ret; 558120948Snectar } 559120948Snectar 560120948Snectar tmpcksum = malloc(c->checksumsize); 561120948Snectar if (tmpcksum == NULL) { 562120948Snectar krb5_set_error_string(context, "malloc: out of memory"); 563120948Snectar krb5_data_free (&key->keyvalue); 564120948Snectar krb5_data_free (&result.checksum); 565120948Snectar return ENOMEM; 566120948Snectar } 567120948Snectar 568120948Snectar datalen = salt.saltvalue.length + 4; 569120948Snectar data = malloc(datalen); 570120948Snectar if (data == NULL) { 571120948Snectar krb5_set_error_string(context, "malloc: out of memory"); 572120948Snectar free(tmpcksum); 573120948Snectar krb5_data_free (&key->keyvalue); 574120948Snectar krb5_data_free (&result.checksum); 575120948Snectar return ENOMEM; 576120948Snectar } 577120948Snectar 578120948Snectar kb.keyvalue = password; 579120948Snectar ksign.key = &kb; 580120948Snectar 581120948Snectar memcpy(data, salt.saltvalue.data, salt.saltvalue.length); 582120948Snectar 583120948Snectar keypart = 1; 584120948Snectar leftofkey = key->keyvalue.length; 585120948Snectar p = key->keyvalue.data; 586120948Snectar 587120948Snectar while (leftofkey) { 588120948Snectar int len; 589120948Snectar 590120948Snectar if (leftofkey > c->checksumsize) 591120948Snectar len = c->checksumsize; 592120948Snectar else 593120948Snectar len = leftofkey; 594120948Snectar 595120948Snectar _krb5_put_int(data + datalen - 4, keypart, 4); 596120948Snectar 597120948Snectar hmac(context, c, data, datalen, 0, &ksign, &result); 598120948Snectar memcpy(p, result.checksum.data, len); 599120948Snectar memcpy(tmpcksum, result.checksum.data, result.checksum.length); 600120948Snectar for (i = 0; i < iter; i++) { 601120948Snectar hmac(context, c, tmpcksum, result.checksum.length, 602120948Snectar 0, &ksign, &result); 603120948Snectar memcpy(tmpcksum, result.checksum.data, result.checksum.length); 604120948Snectar for (j = 0; j < len; j++) 605120948Snectar p[j] ^= tmpcksum[j]; 606120948Snectar } 607120948Snectar 608120948Snectar p += len; 609120948Snectar leftofkey -= len; 610120948Snectar keypart++; 611120948Snectar } 612120948Snectar 613120948Snectar free(data); 614120948Snectar free(tmpcksum); 615120948Snectar krb5_data_free (&result.checksum); 616120948Snectar 617120948Snectar return 0; 618120948Snectar} 619120948Snectar 620120948Snectarstatic krb5_error_code 621120948SnectarAES_string_to_key(krb5_context context, 622120948Snectar krb5_enctype enctype, 623120948Snectar krb5_data password, 624120948Snectar krb5_salt salt, 625120948Snectar krb5_data opaque, 626120948Snectar krb5_keyblock *key) 627120948Snectar{ 628120948Snectar krb5_error_code ret; 629120948Snectar u_int32_t iter; 630120948Snectar struct encryption_type *et; 631120948Snectar struct key_data kd; 632120948Snectar 633120948Snectar if (opaque.length == 0) 634120948Snectar iter = 45056 - 1; 635120948Snectar else if (opaque.length == 4) { 636120948Snectar unsigned long v; 637120948Snectar _krb5_get_int(opaque.data, &v, 4); 638120948Snectar iter = ((u_int32_t)v) - 1; 639120948Snectar } else 640120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ 641120948Snectar 642120948Snectar 643120948Snectar et = _find_enctype(enctype); 644120948Snectar if (et == NULL) 645120948Snectar return KRB5_PROG_KEYTYPE_NOSUPP; 646120948Snectar 647120948Snectar ret = krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt, 648120948Snectar iter, enctype, key); 649120948Snectar if (ret) 650120948Snectar return ret; 651120948Snectar 652120948Snectar ret = krb5_copy_keyblock(context, key, &kd.key); 653120948Snectar kd.schedule = NULL; 654120948Snectar 655120948Snectar ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); 656120948Snectar 657120948Snectar if (ret) { 658120948Snectar krb5_data_free(&key->keyvalue); 659120948Snectar } else { 660120948Snectar ret = krb5_copy_keyblock_contents(context, kd.key, key); 661120948Snectar free_key_data(context, &kd); 662120948Snectar } 663120948Snectar 664120948Snectar return ret; 665120948Snectar} 666120948Snectar 667120948Snectarstatic void 668120948SnectarAES_schedule(krb5_context context, struct key_data *kd) 669120948Snectar{ 670120948Snectar AES_KEY *key = kd->schedule->data; 671120948Snectar int bits = kd->key->keyvalue.length * 8; 672120948Snectar 673120948Snectar AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key[0]); 674120948Snectar AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key[1]); 675120948Snectar} 676120948Snectar 677120948Snectar/* 678120948Snectar * 679120948Snectar */ 680120948Snectar 681120948Snectarextern struct salt_type AES_salt[]; 682120948Snectar 683120948Snectar#endif /* ENABLE_AES */ 684120948Snectar 68555682Smarkmextern struct salt_type des_salt[], 68655682Smarkm des3_salt[], des3_salt_derived[], arcfour_salt[]; 68755682Smarkm 68855682Smarkmstruct key_type keytype_null = { 68955682Smarkm KEYTYPE_NULL, 69055682Smarkm "null", 69155682Smarkm 0, 69255682Smarkm 0, 69355682Smarkm 0, 69455682Smarkm NULL, 69555682Smarkm NULL, 69655682Smarkm NULL 69755682Smarkm}; 69855682Smarkm 69955682Smarkmstruct key_type keytype_des = { 70055682Smarkm KEYTYPE_DES, 70155682Smarkm "des", 70255682Smarkm 56, 70355682Smarkm sizeof(des_cblock), 70455682Smarkm sizeof(des_key_schedule), 705102647Snectar krb5_DES_random_key, 706102647Snectar krb5_DES_schedule, 70755682Smarkm des_salt 70855682Smarkm}; 70955682Smarkm 71055682Smarkmstruct key_type keytype_des3 = { 71155682Smarkm KEYTYPE_DES3, 71255682Smarkm "des3", 71355682Smarkm 168, 71455682Smarkm 3 * sizeof(des_cblock), 71555682Smarkm 3 * sizeof(des_key_schedule), 71655682Smarkm DES3_random_key, 71755682Smarkm DES3_schedule, 71855682Smarkm des3_salt 71955682Smarkm}; 72055682Smarkm 72155682Smarkmstruct key_type keytype_des3_derived = { 72255682Smarkm KEYTYPE_DES3, 72355682Smarkm "des3", 72455682Smarkm 168, 72555682Smarkm 3 * sizeof(des_cblock), 72655682Smarkm 3 * sizeof(des_key_schedule), 72755682Smarkm DES3_random_key, 72855682Smarkm DES3_schedule, 72955682Smarkm des3_salt_derived 73055682Smarkm}; 73155682Smarkm 732120948Snectar#ifdef ENABLE_AES 733120948Snectarstruct key_type keytype_aes128 = { 734120948Snectar KEYTYPE_AES128, 735120948Snectar "aes-128", 736120948Snectar 128, 737120948Snectar 16, 738120948Snectar sizeof(AES_KEY) * 2, 739120948Snectar NULL, 740120948Snectar AES_schedule, 741120948Snectar AES_salt 742120948Snectar}; 743120948Snectar 744120948Snectarstruct key_type keytype_aes256 = { 745120948Snectar KEYTYPE_AES256, 746120948Snectar "aes-256", 747120948Snectar 256, 748120948Snectar 16, 749120948Snectar sizeof(AES_KEY) * 2, 750120948Snectar NULL, 751120948Snectar AES_schedule, 752120948Snectar AES_salt 753120948Snectar}; 754120948Snectar#endif /* ENABLE_AES */ 755120948Snectar 75655682Smarkmstruct key_type keytype_arcfour = { 75755682Smarkm KEYTYPE_ARCFOUR, 75855682Smarkm "arcfour", 75955682Smarkm 128, 76055682Smarkm 16, 76155682Smarkm sizeof(RC4_KEY), 76255682Smarkm ARCFOUR_random_key, 76355682Smarkm ARCFOUR_schedule, 76455682Smarkm arcfour_salt 76555682Smarkm}; 76655682Smarkm 76755682Smarkmstruct key_type *keytypes[] = { 76855682Smarkm &keytype_null, 76955682Smarkm &keytype_des, 77055682Smarkm &keytype_des3_derived, 77155682Smarkm &keytype_des3, 772120948Snectar#ifdef ENABLE_AES 773120948Snectar &keytype_aes128, 774120948Snectar &keytype_aes256, 775120948Snectar#endif /* ENABLE_AES */ 77655682Smarkm &keytype_arcfour 77755682Smarkm}; 77855682Smarkm 77955682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]); 78055682Smarkm 78155682Smarkmstatic struct key_type * 78255682Smarkm_find_keytype(krb5_keytype type) 78355682Smarkm{ 78455682Smarkm int i; 78555682Smarkm for(i = 0; i < num_keytypes; i++) 78655682Smarkm if(keytypes[i]->type == type) 78755682Smarkm return keytypes[i]; 78855682Smarkm return NULL; 78955682Smarkm} 79055682Smarkm 79155682Smarkm 79255682Smarkmstruct salt_type des_salt[] = { 79355682Smarkm { 79455682Smarkm KRB5_PW_SALT, 79555682Smarkm "pw-salt", 796102647Snectar krb5_DES_string_to_key 79755682Smarkm }, 79855682Smarkm { 79955682Smarkm KRB5_AFS3_SALT, 80055682Smarkm "afs3-salt", 80155682Smarkm DES_AFS3_string_to_key 80255682Smarkm }, 80355682Smarkm { 0 } 80455682Smarkm}; 80555682Smarkm 80655682Smarkmstruct salt_type des3_salt[] = { 80755682Smarkm { 80855682Smarkm KRB5_PW_SALT, 80955682Smarkm "pw-salt", 81055682Smarkm DES3_string_to_key 81155682Smarkm }, 81255682Smarkm { 0 } 81355682Smarkm}; 81455682Smarkm 81555682Smarkmstruct salt_type des3_salt_derived[] = { 81655682Smarkm { 81755682Smarkm KRB5_PW_SALT, 81855682Smarkm "pw-salt", 81955682Smarkm DES3_string_to_key_derived 82055682Smarkm }, 82155682Smarkm { 0 } 82255682Smarkm}; 82355682Smarkm 824120948Snectar#ifdef ENABLE_AES 825120948Snectarstruct salt_type AES_salt[] = { 826120948Snectar { 827120948Snectar KRB5_PW_SALT, 828120948Snectar "pw-salt", 829120948Snectar AES_string_to_key 830120948Snectar }, 831120948Snectar { 0 } 832120948Snectar}; 833120948Snectar#endif /* ENABLE_AES */ 834120948Snectar 83555682Smarkmstruct salt_type arcfour_salt[] = { 83655682Smarkm { 83755682Smarkm KRB5_PW_SALT, 83855682Smarkm "pw-salt", 83955682Smarkm ARCFOUR_string_to_key 84055682Smarkm }, 84155682Smarkm { 0 } 84255682Smarkm}; 84355682Smarkm 84455682Smarkmkrb5_error_code 84555682Smarkmkrb5_salttype_to_string (krb5_context context, 84655682Smarkm krb5_enctype etype, 84755682Smarkm krb5_salttype stype, 84855682Smarkm char **string) 84955682Smarkm{ 85055682Smarkm struct encryption_type *e; 85155682Smarkm struct salt_type *st; 85255682Smarkm 85355682Smarkm e = _find_enctype (etype); 85478536Sassar if (e == NULL) { 85578536Sassar krb5_set_error_string(context, "encryption type %d not supported", 85678536Sassar etype); 85755682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 85878536Sassar } 85955682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 86055682Smarkm if (st->type == stype) { 86155682Smarkm *string = strdup (st->name); 86278536Sassar if (*string == NULL) { 86378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 86455682Smarkm return ENOMEM; 86578536Sassar } 86655682Smarkm return 0; 86755682Smarkm } 86855682Smarkm } 86978536Sassar krb5_set_error_string(context, "salttype %d not supported", stype); 87055682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 87155682Smarkm} 87255682Smarkm 87355682Smarkmkrb5_error_code 87455682Smarkmkrb5_string_to_salttype (krb5_context context, 87555682Smarkm krb5_enctype etype, 87655682Smarkm const char *string, 87755682Smarkm krb5_salttype *salttype) 87855682Smarkm{ 87955682Smarkm struct encryption_type *e; 88055682Smarkm struct salt_type *st; 88155682Smarkm 88255682Smarkm e = _find_enctype (etype); 88378536Sassar if (e == NULL) { 88478536Sassar krb5_set_error_string(context, "encryption type %d not supported", 88578536Sassar etype); 88655682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 88778536Sassar } 88855682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 88955682Smarkm if (strcasecmp (st->name, string) == 0) { 89055682Smarkm *salttype = st->type; 89155682Smarkm return 0; 89255682Smarkm } 89355682Smarkm } 89478536Sassar krb5_set_error_string(context, "salttype %s not supported", string); 89555682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 89655682Smarkm} 89755682Smarkm 89855682Smarkmkrb5_error_code 89955682Smarkmkrb5_get_pw_salt(krb5_context context, 90055682Smarkm krb5_const_principal principal, 90155682Smarkm krb5_salt *salt) 90255682Smarkm{ 90355682Smarkm size_t len; 90455682Smarkm int i; 90555682Smarkm krb5_error_code ret; 90655682Smarkm char *p; 90755682Smarkm 90855682Smarkm salt->salttype = KRB5_PW_SALT; 90955682Smarkm len = strlen(principal->realm); 91055682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) 91155682Smarkm len += strlen(principal->name.name_string.val[i]); 91255682Smarkm ret = krb5_data_alloc (&salt->saltvalue, len); 91355682Smarkm if (ret) 91455682Smarkm return ret; 91555682Smarkm p = salt->saltvalue.data; 91655682Smarkm memcpy (p, principal->realm, strlen(principal->realm)); 91755682Smarkm p += strlen(principal->realm); 91855682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) { 91955682Smarkm memcpy (p, 92055682Smarkm principal->name.name_string.val[i], 92155682Smarkm strlen(principal->name.name_string.val[i])); 92255682Smarkm p += strlen(principal->name.name_string.val[i]); 92355682Smarkm } 92455682Smarkm return 0; 92555682Smarkm} 92655682Smarkm 92755682Smarkmkrb5_error_code 92855682Smarkmkrb5_free_salt(krb5_context context, 92955682Smarkm krb5_salt salt) 93055682Smarkm{ 93155682Smarkm krb5_data_free(&salt.saltvalue); 93255682Smarkm return 0; 93355682Smarkm} 93455682Smarkm 93555682Smarkmkrb5_error_code 93655682Smarkmkrb5_string_to_key_data (krb5_context context, 93755682Smarkm krb5_enctype enctype, 93855682Smarkm krb5_data password, 93955682Smarkm krb5_principal principal, 94055682Smarkm krb5_keyblock *key) 94155682Smarkm{ 94255682Smarkm krb5_error_code ret; 94355682Smarkm krb5_salt salt; 94455682Smarkm 94555682Smarkm ret = krb5_get_pw_salt(context, principal, &salt); 94655682Smarkm if(ret) 94755682Smarkm return ret; 94855682Smarkm ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); 94955682Smarkm krb5_free_salt(context, salt); 95055682Smarkm return ret; 95155682Smarkm} 95255682Smarkm 95355682Smarkmkrb5_error_code 95455682Smarkmkrb5_string_to_key (krb5_context context, 95555682Smarkm krb5_enctype enctype, 95655682Smarkm const char *password, 95755682Smarkm krb5_principal principal, 95855682Smarkm krb5_keyblock *key) 95955682Smarkm{ 96055682Smarkm krb5_data pw; 96155682Smarkm pw.data = (void*)password; 96255682Smarkm pw.length = strlen(password); 96355682Smarkm return krb5_string_to_key_data(context, enctype, pw, principal, key); 96455682Smarkm} 96555682Smarkm 96655682Smarkmkrb5_error_code 96755682Smarkmkrb5_string_to_key_data_salt (krb5_context context, 96855682Smarkm krb5_enctype enctype, 96955682Smarkm krb5_data password, 97055682Smarkm krb5_salt salt, 97155682Smarkm krb5_keyblock *key) 97255682Smarkm{ 973120948Snectar krb5_data opaque; 974120948Snectar krb5_data_zero(&opaque); 975120948Snectar return krb5_string_to_key_data_salt_opaque(context, enctype, password, 976120948Snectar salt, opaque, key); 977120948Snectar} 978120948Snectar 979120948Snectar/* 980120948Snectar * Do a string -> key for encryption type `enctype' operation on 981120948Snectar * `password' (with salt `salt' and the enctype specific data string 982120948Snectar * `opaque'), returning the resulting key in `key' 983120948Snectar */ 984120948Snectar 985120948Snectarkrb5_error_code 986120948Snectarkrb5_string_to_key_data_salt_opaque (krb5_context context, 987120948Snectar krb5_enctype enctype, 988120948Snectar krb5_data password, 989120948Snectar krb5_salt salt, 990120948Snectar krb5_data opaque, 991120948Snectar krb5_keyblock *key) 992120948Snectar{ 99355682Smarkm struct encryption_type *et =_find_enctype(enctype); 99455682Smarkm struct salt_type *st; 99578536Sassar if(et == NULL) { 99678536Sassar krb5_set_error_string(context, "encryption type %d not supported", 99778536Sassar enctype); 99855682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 99978536Sassar } 100055682Smarkm for(st = et->keytype->string_to_key; st && st->type; st++) 100155682Smarkm if(st->type == salt.salttype) 1002120948Snectar return (*st->string_to_key)(context, enctype, password, 1003120948Snectar salt, opaque, key); 100478536Sassar krb5_set_error_string(context, "salt type %d not supported", 100578536Sassar salt.salttype); 100655682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 100755682Smarkm} 100855682Smarkm 100972448Sassar/* 101072448Sassar * Do a string -> key for encryption type `enctype' operation on the 101172448Sassar * string `password' (with salt `salt'), returning the resulting key 101272448Sassar * in `key' 101372448Sassar */ 101472448Sassar 101555682Smarkmkrb5_error_code 101655682Smarkmkrb5_string_to_key_salt (krb5_context context, 101755682Smarkm krb5_enctype enctype, 101855682Smarkm const char *password, 101955682Smarkm krb5_salt salt, 102055682Smarkm krb5_keyblock *key) 102155682Smarkm{ 102255682Smarkm krb5_data pw; 102355682Smarkm pw.data = (void*)password; 102455682Smarkm pw.length = strlen(password); 102555682Smarkm return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); 102655682Smarkm} 102755682Smarkm 102855682Smarkmkrb5_error_code 102955682Smarkmkrb5_keytype_to_string(krb5_context context, 103055682Smarkm krb5_keytype keytype, 103155682Smarkm char **string) 103255682Smarkm{ 103355682Smarkm struct key_type *kt = _find_keytype(keytype); 103478536Sassar if(kt == NULL) { 103578536Sassar krb5_set_error_string(context, "key type %d not supported", keytype); 103655682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 103778536Sassar } 103855682Smarkm *string = strdup(kt->name); 103978536Sassar if(*string == NULL) { 104078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 104155682Smarkm return ENOMEM; 104278536Sassar } 104355682Smarkm return 0; 104455682Smarkm} 104555682Smarkm 104655682Smarkmkrb5_error_code 104755682Smarkmkrb5_string_to_keytype(krb5_context context, 104855682Smarkm const char *string, 104955682Smarkm krb5_keytype *keytype) 105055682Smarkm{ 105155682Smarkm int i; 105255682Smarkm for(i = 0; i < num_keytypes; i++) 105355682Smarkm if(strcasecmp(keytypes[i]->name, string) == 0){ 105455682Smarkm *keytype = keytypes[i]->type; 105555682Smarkm return 0; 105655682Smarkm } 105778536Sassar krb5_set_error_string(context, "key type %s not supported", string); 105855682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 105955682Smarkm} 106055682Smarkm 106155682Smarkmkrb5_error_code 1062120948Snectarkrb5_enctype_keysize(krb5_context context, 1063120948Snectar krb5_enctype type, 1064120948Snectar size_t *keysize) 1065120948Snectar{ 1066120948Snectar struct encryption_type *et = _find_enctype(type); 1067120948Snectar if(et == NULL) { 1068120948Snectar krb5_set_error_string(context, "encryption type %d not supported", 1069120948Snectar type); 1070120948Snectar return KRB5_PROG_ETYPE_NOSUPP; 1071120948Snectar } 1072120948Snectar *keysize = et->keytype->size; 1073120948Snectar return 0; 1074120948Snectar} 1075120948Snectar 1076120948Snectarkrb5_error_code 107755682Smarkmkrb5_generate_random_keyblock(krb5_context context, 107855682Smarkm krb5_enctype type, 107955682Smarkm krb5_keyblock *key) 108055682Smarkm{ 108155682Smarkm krb5_error_code ret; 108255682Smarkm struct encryption_type *et = _find_enctype(type); 108378536Sassar if(et == NULL) { 108478536Sassar krb5_set_error_string(context, "encryption type %d not supported", 108578536Sassar type); 108655682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 108778536Sassar } 108855682Smarkm ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 108955682Smarkm if(ret) 109055682Smarkm return ret; 109155682Smarkm key->keytype = type; 109255682Smarkm if(et->keytype->random_key) 109355682Smarkm (*et->keytype->random_key)(context, key); 109455682Smarkm else 109555682Smarkm krb5_generate_random_block(key->keyvalue.data, 109655682Smarkm key->keyvalue.length); 109755682Smarkm return 0; 109855682Smarkm} 109955682Smarkm 110055682Smarkmstatic krb5_error_code 110155682Smarkm_key_schedule(krb5_context context, 110255682Smarkm struct key_data *key) 110355682Smarkm{ 110455682Smarkm krb5_error_code ret; 110555682Smarkm struct encryption_type *et = _find_enctype(key->key->keytype); 110655682Smarkm struct key_type *kt = et->keytype; 110755682Smarkm 110855682Smarkm if(kt->schedule == NULL) 110955682Smarkm return 0; 111072448Sassar if (key->schedule != NULL) 111172448Sassar return 0; 111255682Smarkm ALLOC(key->schedule, 1); 111378536Sassar if(key->schedule == NULL) { 111478536Sassar krb5_set_error_string(context, "malloc: out of memory"); 111555682Smarkm return ENOMEM; 111678536Sassar } 111755682Smarkm ret = krb5_data_alloc(key->schedule, kt->schedule_size); 111855682Smarkm if(ret) { 111955682Smarkm free(key->schedule); 112055682Smarkm key->schedule = NULL; 112155682Smarkm return ret; 112255682Smarkm } 112355682Smarkm (*kt->schedule)(context, key); 112455682Smarkm return 0; 112555682Smarkm} 112655682Smarkm 112755682Smarkm/************************************************************ 112855682Smarkm * * 112955682Smarkm ************************************************************/ 113055682Smarkm 113155682Smarkmstatic void 113255682SmarkmNONE_checksum(krb5_context context, 113355682Smarkm struct key_data *key, 113472448Sassar const void *data, 113555682Smarkm size_t len, 113672448Sassar unsigned usage, 113755682Smarkm Checksum *C) 113855682Smarkm{ 113955682Smarkm} 114055682Smarkm 114155682Smarkmstatic void 114255682SmarkmCRC32_checksum(krb5_context context, 114355682Smarkm struct key_data *key, 114472448Sassar const void *data, 114555682Smarkm size_t len, 114672448Sassar unsigned usage, 114755682Smarkm Checksum *C) 114855682Smarkm{ 114955682Smarkm u_int32_t crc; 115055682Smarkm unsigned char *r = C->checksum.data; 115155682Smarkm _krb5_crc_init_table (); 115255682Smarkm crc = _krb5_crc_update (data, len, 0); 115355682Smarkm r[0] = crc & 0xff; 115455682Smarkm r[1] = (crc >> 8) & 0xff; 115555682Smarkm r[2] = (crc >> 16) & 0xff; 115655682Smarkm r[3] = (crc >> 24) & 0xff; 115755682Smarkm} 115855682Smarkm 115955682Smarkmstatic void 116055682SmarkmRSA_MD4_checksum(krb5_context context, 116155682Smarkm struct key_data *key, 116272448Sassar const void *data, 116355682Smarkm size_t len, 116472448Sassar unsigned usage, 116555682Smarkm Checksum *C) 116655682Smarkm{ 116757416Smarkm MD4_CTX m; 116857416Smarkm 116972448Sassar MD4_Init (&m); 117072448Sassar MD4_Update (&m, data, len); 117172448Sassar MD4_Final (C->checksum.data, &m); 117255682Smarkm} 117355682Smarkm 117455682Smarkmstatic void 117555682SmarkmRSA_MD4_DES_checksum(krb5_context context, 117655682Smarkm struct key_data *key, 117772448Sassar const void *data, 117855682Smarkm size_t len, 117972448Sassar unsigned usage, 118055682Smarkm Checksum *cksum) 118155682Smarkm{ 118257416Smarkm MD4_CTX md4; 118355682Smarkm des_cblock ivec; 118455682Smarkm unsigned char *p = cksum->checksum.data; 118555682Smarkm 118655682Smarkm krb5_generate_random_block(p, 8); 118772448Sassar MD4_Init (&md4); 118872448Sassar MD4_Update (&md4, p, 8); 118972448Sassar MD4_Update (&md4, data, len); 119072448Sassar MD4_Final (p + 8, &md4); 119155682Smarkm memset (&ivec, 0, sizeof(ivec)); 119290929Snectar des_cbc_encrypt(p, 119390929Snectar p, 119455682Smarkm 24, 119555682Smarkm key->schedule->data, 119655682Smarkm &ivec, 119755682Smarkm DES_ENCRYPT); 119855682Smarkm} 119955682Smarkm 120055682Smarkmstatic krb5_error_code 120155682SmarkmRSA_MD4_DES_verify(krb5_context context, 120255682Smarkm struct key_data *key, 120372448Sassar const void *data, 120455682Smarkm size_t len, 120572448Sassar unsigned usage, 120655682Smarkm Checksum *C) 120755682Smarkm{ 120857416Smarkm MD4_CTX md4; 120955682Smarkm unsigned char tmp[24]; 121055682Smarkm unsigned char res[16]; 121155682Smarkm des_cblock ivec; 121255682Smarkm krb5_error_code ret = 0; 121355682Smarkm 121455682Smarkm memset(&ivec, 0, sizeof(ivec)); 121557416Smarkm des_cbc_encrypt(C->checksum.data, 121655682Smarkm (void*)tmp, 121755682Smarkm C->checksum.length, 121855682Smarkm key->schedule->data, 121955682Smarkm &ivec, 122055682Smarkm DES_DECRYPT); 122172448Sassar MD4_Init (&md4); 122272448Sassar MD4_Update (&md4, tmp, 8); /* confounder */ 122372448Sassar MD4_Update (&md4, data, len); 122472448Sassar MD4_Final (res, &md4); 122578536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 122678536Sassar krb5_clear_error_string (context); 122755682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 122878536Sassar } 122955682Smarkm memset(tmp, 0, sizeof(tmp)); 123055682Smarkm memset(res, 0, sizeof(res)); 123155682Smarkm return ret; 123255682Smarkm} 123355682Smarkm 123455682Smarkmstatic void 123555682SmarkmRSA_MD5_checksum(krb5_context context, 123655682Smarkm struct key_data *key, 123772448Sassar const void *data, 123855682Smarkm size_t len, 123972448Sassar unsigned usage, 124055682Smarkm Checksum *C) 124155682Smarkm{ 124257416Smarkm MD5_CTX m; 124357416Smarkm 124472448Sassar MD5_Init (&m); 124572448Sassar MD5_Update(&m, data, len); 124672448Sassar MD5_Final (C->checksum.data, &m); 124755682Smarkm} 124855682Smarkm 124955682Smarkmstatic void 125055682SmarkmRSA_MD5_DES_checksum(krb5_context context, 125155682Smarkm struct key_data *key, 125272448Sassar const void *data, 125355682Smarkm size_t len, 125472448Sassar unsigned usage, 125555682Smarkm Checksum *C) 125655682Smarkm{ 125757416Smarkm MD5_CTX md5; 125855682Smarkm des_cblock ivec; 125955682Smarkm unsigned char *p = C->checksum.data; 126055682Smarkm 126155682Smarkm krb5_generate_random_block(p, 8); 126272448Sassar MD5_Init (&md5); 126372448Sassar MD5_Update (&md5, p, 8); 126472448Sassar MD5_Update (&md5, data, len); 126572448Sassar MD5_Final (p + 8, &md5); 126655682Smarkm memset (&ivec, 0, sizeof(ivec)); 126790929Snectar des_cbc_encrypt(p, 126890929Snectar p, 126955682Smarkm 24, 127055682Smarkm key->schedule->data, 127155682Smarkm &ivec, 127255682Smarkm DES_ENCRYPT); 127355682Smarkm} 127455682Smarkm 127555682Smarkmstatic krb5_error_code 127655682SmarkmRSA_MD5_DES_verify(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; 128455682Smarkm unsigned char tmp[24]; 128555682Smarkm unsigned char res[16]; 128655682Smarkm des_cblock ivec; 128755682Smarkm des_key_schedule *sched = key->schedule->data; 128855682Smarkm krb5_error_code ret = 0; 128955682Smarkm 129055682Smarkm memset(&ivec, 0, sizeof(ivec)); 129155682Smarkm des_cbc_encrypt(C->checksum.data, 129255682Smarkm (void*)tmp, 129355682Smarkm C->checksum.length, 129455682Smarkm sched[0], 129555682Smarkm &ivec, 129655682Smarkm DES_DECRYPT); 129772448Sassar MD5_Init (&md5); 129872448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 129972448Sassar MD5_Update (&md5, data, len); 130072448Sassar MD5_Final (res, &md5); 130178536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 130278536Sassar krb5_clear_error_string (context); 130355682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 130478536Sassar } 130555682Smarkm memset(tmp, 0, sizeof(tmp)); 130655682Smarkm memset(res, 0, sizeof(res)); 130755682Smarkm return ret; 130855682Smarkm} 130955682Smarkm 131055682Smarkmstatic void 131155682SmarkmRSA_MD5_DES3_checksum(krb5_context context, 131255682Smarkm struct key_data *key, 131372448Sassar const void *data, 131455682Smarkm size_t len, 131572448Sassar unsigned usage, 131655682Smarkm Checksum *C) 131755682Smarkm{ 131857416Smarkm MD5_CTX md5; 131955682Smarkm des_cblock ivec; 132055682Smarkm unsigned char *p = C->checksum.data; 132155682Smarkm des_key_schedule *sched = key->schedule->data; 132255682Smarkm 132355682Smarkm krb5_generate_random_block(p, 8); 132472448Sassar MD5_Init (&md5); 132572448Sassar MD5_Update (&md5, p, 8); 132672448Sassar MD5_Update (&md5, data, len); 132772448Sassar MD5_Final (p + 8, &md5); 132855682Smarkm memset (&ivec, 0, sizeof(ivec)); 132990929Snectar des_ede3_cbc_encrypt(p, 133090929Snectar p, 133155682Smarkm 24, 133255682Smarkm sched[0], sched[1], sched[2], 133355682Smarkm &ivec, 133455682Smarkm DES_ENCRYPT); 133555682Smarkm} 133655682Smarkm 133755682Smarkmstatic krb5_error_code 133855682SmarkmRSA_MD5_DES3_verify(krb5_context context, 133955682Smarkm struct key_data *key, 134072448Sassar const void *data, 134155682Smarkm size_t len, 134272448Sassar unsigned usage, 134355682Smarkm Checksum *C) 134455682Smarkm{ 134557416Smarkm MD5_CTX md5; 134655682Smarkm unsigned char tmp[24]; 134755682Smarkm unsigned char res[16]; 134855682Smarkm des_cblock ivec; 134955682Smarkm des_key_schedule *sched = key->schedule->data; 135055682Smarkm krb5_error_code ret = 0; 135155682Smarkm 135255682Smarkm memset(&ivec, 0, sizeof(ivec)); 135355682Smarkm des_ede3_cbc_encrypt(C->checksum.data, 135455682Smarkm (void*)tmp, 135555682Smarkm C->checksum.length, 135655682Smarkm sched[0], sched[1], sched[2], 135755682Smarkm &ivec, 135855682Smarkm DES_DECRYPT); 135972448Sassar MD5_Init (&md5); 136072448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 136172448Sassar MD5_Update (&md5, data, len); 136272448Sassar MD5_Final (res, &md5); 136378536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 136478536Sassar krb5_clear_error_string (context); 136555682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 136678536Sassar } 136755682Smarkm memset(tmp, 0, sizeof(tmp)); 136855682Smarkm memset(res, 0, sizeof(res)); 136955682Smarkm return ret; 137055682Smarkm} 137155682Smarkm 137255682Smarkmstatic void 137355682SmarkmSHA1_checksum(krb5_context context, 137455682Smarkm struct key_data *key, 137572448Sassar const void *data, 137655682Smarkm size_t len, 137772448Sassar unsigned usage, 137855682Smarkm Checksum *C) 137955682Smarkm{ 138072448Sassar SHA_CTX m; 138157416Smarkm 138272448Sassar SHA1_Init(&m); 138372448Sassar SHA1_Update(&m, data, len); 138472448Sassar SHA1_Final(C->checksum.data, &m); 138555682Smarkm} 138655682Smarkm 138755682Smarkm/* HMAC according to RFC2104 */ 138855682Smarkmstatic void 138955682Smarkmhmac(krb5_context context, 139055682Smarkm struct checksum_type *cm, 139172448Sassar const void *data, 139255682Smarkm size_t len, 139372448Sassar unsigned usage, 139455682Smarkm struct key_data *keyblock, 139555682Smarkm Checksum *result) 139655682Smarkm{ 139755682Smarkm unsigned char *ipad, *opad; 139855682Smarkm unsigned char *key; 139955682Smarkm size_t key_len; 140055682Smarkm int i; 140155682Smarkm 140255682Smarkm if(keyblock->key->keyvalue.length > cm->blocksize){ 140355682Smarkm (*cm->checksum)(context, 140455682Smarkm keyblock, 140555682Smarkm keyblock->key->keyvalue.data, 140655682Smarkm keyblock->key->keyvalue.length, 140772448Sassar usage, 140855682Smarkm result); 140955682Smarkm key = result->checksum.data; 141055682Smarkm key_len = result->checksum.length; 141155682Smarkm } else { 141255682Smarkm key = keyblock->key->keyvalue.data; 141355682Smarkm key_len = keyblock->key->keyvalue.length; 141455682Smarkm } 141555682Smarkm ipad = malloc(cm->blocksize + len); 141655682Smarkm opad = malloc(cm->blocksize + cm->checksumsize); 141755682Smarkm memset(ipad, 0x36, cm->blocksize); 141855682Smarkm memset(opad, 0x5c, cm->blocksize); 141955682Smarkm for(i = 0; i < key_len; i++){ 142055682Smarkm ipad[i] ^= key[i]; 142155682Smarkm opad[i] ^= key[i]; 142255682Smarkm } 142355682Smarkm memcpy(ipad + cm->blocksize, data, len); 142472448Sassar (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, 142572448Sassar usage, result); 142655682Smarkm memcpy(opad + cm->blocksize, result->checksum.data, 142755682Smarkm result->checksum.length); 142855682Smarkm (*cm->checksum)(context, keyblock, opad, 142972448Sassar cm->blocksize + cm->checksumsize, usage, result); 143055682Smarkm memset(ipad, 0, cm->blocksize + len); 143155682Smarkm free(ipad); 143255682Smarkm memset(opad, 0, cm->blocksize + cm->checksumsize); 143355682Smarkm free(opad); 143455682Smarkm} 143555682Smarkm 143655682Smarkmstatic void 1437120948SnectarSP_HMAC_SHA1_checksum(krb5_context context, 1438120948Snectar struct key_data *key, 1439120948Snectar const void *data, 1440120948Snectar size_t len, 1441120948Snectar unsigned usage, 1442120948Snectar Checksum *result) 144355682Smarkm{ 144455682Smarkm struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); 1445120948Snectar Checksum res; 1446120948Snectar char sha1_data[20]; 144755682Smarkm 1448120948Snectar res.checksum.data = sha1_data; 1449120948Snectar res.checksum.length = sizeof(sha1_data); 1450120948Snectar 1451120948Snectar hmac(context, c, data, len, usage, key, &res); 1452120948Snectar memcpy(result->checksum.data, res.checksum.data, result->checksum.length); 145355682Smarkm} 145455682Smarkm 145572448Sassar/* 145672448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt 145772448Sassar */ 145872448Sassar 145972448Sassarstatic void 146072448SassarHMAC_MD5_checksum(krb5_context context, 146172448Sassar struct key_data *key, 146272448Sassar const void *data, 146372448Sassar size_t len, 146472448Sassar unsigned usage, 146572448Sassar Checksum *result) 146672448Sassar{ 146772448Sassar MD5_CTX md5; 146872448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 146972448Sassar const char signature[] = "signaturekey"; 147072448Sassar Checksum ksign_c; 147172448Sassar struct key_data ksign; 147272448Sassar krb5_keyblock kb; 147372448Sassar unsigned char t[4]; 147472448Sassar unsigned char tmp[16]; 147572448Sassar unsigned char ksign_c_data[16]; 147672448Sassar 147772448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 147872448Sassar ksign_c.checksum.data = ksign_c_data; 147972448Sassar hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); 148072448Sassar ksign.key = &kb; 148172448Sassar kb.keyvalue = ksign_c.checksum; 148272448Sassar MD5_Init (&md5); 148372448Sassar t[0] = (usage >> 0) & 0xFF; 148472448Sassar t[1] = (usage >> 8) & 0xFF; 148572448Sassar t[2] = (usage >> 16) & 0xFF; 148672448Sassar t[3] = (usage >> 24) & 0xFF; 148772448Sassar MD5_Update (&md5, t, 4); 148872448Sassar MD5_Update (&md5, data, len); 148972448Sassar MD5_Final (tmp, &md5); 149072448Sassar hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); 149172448Sassar} 149272448Sassar 149372448Sassar/* 149472448Sassar * same as previous but being used while encrypting. 149572448Sassar */ 149672448Sassar 149772448Sassarstatic void 149872448SassarHMAC_MD5_checksum_enc(krb5_context context, 149972448Sassar struct key_data *key, 150072448Sassar const void *data, 150172448Sassar size_t len, 150272448Sassar unsigned usage, 150372448Sassar Checksum *result) 150472448Sassar{ 150572448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 150672448Sassar Checksum ksign_c; 150772448Sassar struct key_data ksign; 150872448Sassar krb5_keyblock kb; 150972448Sassar unsigned char t[4]; 151072448Sassar unsigned char ksign_c_data[16]; 151172448Sassar 151272448Sassar t[0] = (usage >> 0) & 0xFF; 151372448Sassar t[1] = (usage >> 8) & 0xFF; 151472448Sassar t[2] = (usage >> 16) & 0xFF; 151572448Sassar t[3] = (usage >> 24) & 0xFF; 151672448Sassar 151772448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 151872448Sassar ksign_c.checksum.data = ksign_c_data; 151972448Sassar hmac(context, c, t, sizeof(t), 0, key, &ksign_c); 152072448Sassar ksign.key = &kb; 152172448Sassar kb.keyvalue = ksign_c.checksum; 152272448Sassar hmac(context, c, data, len, 0, &ksign, result); 152372448Sassar} 152472448Sassar 152555682Smarkmstruct checksum_type checksum_none = { 152655682Smarkm CKSUMTYPE_NONE, 152755682Smarkm "none", 152855682Smarkm 1, 152955682Smarkm 0, 153055682Smarkm 0, 153155682Smarkm NONE_checksum, 153255682Smarkm NULL 153355682Smarkm}; 153455682Smarkmstruct checksum_type checksum_crc32 = { 153555682Smarkm CKSUMTYPE_CRC32, 153655682Smarkm "crc32", 153755682Smarkm 1, 153855682Smarkm 4, 153955682Smarkm 0, 154055682Smarkm CRC32_checksum, 154155682Smarkm NULL 154255682Smarkm}; 154355682Smarkmstruct checksum_type checksum_rsa_md4 = { 154455682Smarkm CKSUMTYPE_RSA_MD4, 154555682Smarkm "rsa-md4", 154655682Smarkm 64, 154755682Smarkm 16, 154855682Smarkm F_CPROOF, 154955682Smarkm RSA_MD4_checksum, 155055682Smarkm NULL 155155682Smarkm}; 155255682Smarkmstruct checksum_type checksum_rsa_md4_des = { 155355682Smarkm CKSUMTYPE_RSA_MD4_DES, 155455682Smarkm "rsa-md4-des", 155555682Smarkm 64, 155655682Smarkm 24, 155755682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 155855682Smarkm RSA_MD4_DES_checksum, 155955682Smarkm RSA_MD4_DES_verify 156055682Smarkm}; 156155682Smarkm#if 0 156255682Smarkmstruct checksum_type checksum_des_mac = { 156355682Smarkm CKSUMTYPE_DES_MAC, 156455682Smarkm "des-mac", 156555682Smarkm 0, 156655682Smarkm 0, 156755682Smarkm 0, 156872448Sassar DES_MAC_checksum 156955682Smarkm}; 157055682Smarkmstruct checksum_type checksum_des_mac_k = { 157155682Smarkm CKSUMTYPE_DES_MAC_K, 157255682Smarkm "des-mac-k", 157355682Smarkm 0, 157455682Smarkm 0, 157555682Smarkm 0, 157672448Sassar DES_MAC_K_checksum 157755682Smarkm}; 157855682Smarkmstruct checksum_type checksum_rsa_md4_des_k = { 157955682Smarkm CKSUMTYPE_RSA_MD4_DES_K, 158055682Smarkm "rsa-md4-des-k", 158155682Smarkm 0, 158255682Smarkm 0, 158355682Smarkm 0, 158472448Sassar RSA_MD4_DES_K_checksum, 158572448Sassar RSA_MD4_DES_K_verify 158655682Smarkm}; 158755682Smarkm#endif 158855682Smarkmstruct checksum_type checksum_rsa_md5 = { 158955682Smarkm CKSUMTYPE_RSA_MD5, 159055682Smarkm "rsa-md5", 159155682Smarkm 64, 159255682Smarkm 16, 159355682Smarkm F_CPROOF, 159455682Smarkm RSA_MD5_checksum, 159555682Smarkm NULL 159655682Smarkm}; 159755682Smarkmstruct checksum_type checksum_rsa_md5_des = { 159855682Smarkm CKSUMTYPE_RSA_MD5_DES, 159955682Smarkm "rsa-md5-des", 160055682Smarkm 64, 160155682Smarkm 24, 160255682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 160355682Smarkm RSA_MD5_DES_checksum, 160472448Sassar RSA_MD5_DES_verify 160555682Smarkm}; 160655682Smarkmstruct checksum_type checksum_rsa_md5_des3 = { 160755682Smarkm CKSUMTYPE_RSA_MD5_DES3, 160855682Smarkm "rsa-md5-des3", 160955682Smarkm 64, 161055682Smarkm 24, 161155682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 161255682Smarkm RSA_MD5_DES3_checksum, 161372448Sassar RSA_MD5_DES3_verify 161455682Smarkm}; 161555682Smarkmstruct checksum_type checksum_sha1 = { 161655682Smarkm CKSUMTYPE_SHA1, 161755682Smarkm "sha1", 161855682Smarkm 64, 161955682Smarkm 20, 162055682Smarkm F_CPROOF, 162155682Smarkm SHA1_checksum, 162255682Smarkm NULL 162355682Smarkm}; 162455682Smarkmstruct checksum_type checksum_hmac_sha1_des3 = { 162555682Smarkm CKSUMTYPE_HMAC_SHA1_DES3, 162655682Smarkm "hmac-sha1-des3", 162755682Smarkm 64, 162855682Smarkm 20, 162955682Smarkm F_KEYED | F_CPROOF | F_DERIVED, 1630120948Snectar SP_HMAC_SHA1_checksum, 163155682Smarkm NULL 163255682Smarkm}; 163355682Smarkm 1634120948Snectar#ifdef ENABLE_AES 1635120948Snectarstruct checksum_type checksum_hmac_sha1_aes128 = { 1636120948Snectar CKSUMTYPE_HMAC_SHA1_96_AES_128, 1637120948Snectar "hmac-sha1-96-aes128", 1638120948Snectar 64, 1639120948Snectar 12, 1640120948Snectar F_KEYED | F_CPROOF | F_DERIVED, 1641120948Snectar SP_HMAC_SHA1_checksum, 1642120948Snectar NULL 1643120948Snectar}; 1644120948Snectar 1645120948Snectarstruct checksum_type checksum_hmac_sha1_aes256 = { 1646120948Snectar CKSUMTYPE_HMAC_SHA1_96_AES_256, 1647120948Snectar "hmac-sha1-96-aes256", 1648120948Snectar 64, 1649120948Snectar 12, 1650120948Snectar F_KEYED | F_CPROOF | F_DERIVED, 1651120948Snectar SP_HMAC_SHA1_checksum, 1652120948Snectar NULL 1653120948Snectar}; 1654120948Snectar#endif /* ENABLE_AES */ 1655120948Snectar 165672448Sassarstruct checksum_type checksum_hmac_md5 = { 165772448Sassar CKSUMTYPE_HMAC_MD5, 165872448Sassar "hmac-md5", 165972448Sassar 64, 166072448Sassar 16, 166172448Sassar F_KEYED | F_CPROOF, 166272448Sassar HMAC_MD5_checksum, 166372448Sassar NULL 166472448Sassar}; 166572448Sassar 166672448Sassarstruct checksum_type checksum_hmac_md5_enc = { 166772448Sassar CKSUMTYPE_HMAC_MD5_ENC, 166872448Sassar "hmac-md5-enc", 166972448Sassar 64, 167072448Sassar 16, 167172448Sassar F_KEYED | F_CPROOF | F_PSEUDO, 167272448Sassar HMAC_MD5_checksum_enc, 167372448Sassar NULL 167472448Sassar}; 167572448Sassar 167655682Smarkmstruct checksum_type *checksum_types[] = { 167755682Smarkm &checksum_none, 167855682Smarkm &checksum_crc32, 167955682Smarkm &checksum_rsa_md4, 168055682Smarkm &checksum_rsa_md4_des, 168155682Smarkm#if 0 168255682Smarkm &checksum_des_mac, 168355682Smarkm &checksum_des_mac_k, 168455682Smarkm &checksum_rsa_md4_des_k, 168555682Smarkm#endif 168655682Smarkm &checksum_rsa_md5, 168755682Smarkm &checksum_rsa_md5_des, 168855682Smarkm &checksum_rsa_md5_des3, 168955682Smarkm &checksum_sha1, 169072448Sassar &checksum_hmac_sha1_des3, 1691120948Snectar#ifdef ENABLE_AES 1692120948Snectar &checksum_hmac_sha1_aes128, 1693120948Snectar &checksum_hmac_sha1_aes256, 1694120948Snectar#endif 169572448Sassar &checksum_hmac_md5, 169672448Sassar &checksum_hmac_md5_enc 169755682Smarkm}; 169855682Smarkm 169955682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); 170055682Smarkm 170155682Smarkmstatic struct checksum_type * 170255682Smarkm_find_checksum(krb5_cksumtype type) 170355682Smarkm{ 170455682Smarkm int i; 170555682Smarkm for(i = 0; i < num_checksums; i++) 170655682Smarkm if(checksum_types[i]->type == type) 170755682Smarkm return checksum_types[i]; 170855682Smarkm return NULL; 170955682Smarkm} 171055682Smarkm 171155682Smarkmstatic krb5_error_code 171255682Smarkmget_checksum_key(krb5_context context, 171355682Smarkm krb5_crypto crypto, 171455682Smarkm unsigned usage, /* not krb5_key_usage */ 171555682Smarkm struct checksum_type *ct, 171655682Smarkm struct key_data **key) 171755682Smarkm{ 171855682Smarkm krb5_error_code ret = 0; 171955682Smarkm 172055682Smarkm if(ct->flags & F_DERIVED) 172155682Smarkm ret = _get_derived_key(context, crypto, usage, key); 172255682Smarkm else if(ct->flags & F_VARIANT) { 172355682Smarkm int i; 172455682Smarkm 172555682Smarkm *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); 172678536Sassar if(*key == NULL) { 172778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 172855682Smarkm return ENOMEM; 172978536Sassar } 173055682Smarkm ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); 173155682Smarkm if(ret) 173255682Smarkm return ret; 173355682Smarkm for(i = 0; i < (*key)->key->keyvalue.length; i++) 173455682Smarkm ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; 173555682Smarkm } else { 173655682Smarkm *key = &crypto->key; 173755682Smarkm } 173855682Smarkm if(ret == 0) 173955682Smarkm ret = _key_schedule(context, *key); 174055682Smarkm return ret; 174155682Smarkm} 174255682Smarkm 174355682Smarkmstatic krb5_error_code 174455682Smarkmdo_checksum (krb5_context context, 174555682Smarkm struct checksum_type *ct, 174655682Smarkm krb5_crypto crypto, 174755682Smarkm unsigned usage, 174855682Smarkm void *data, 174955682Smarkm size_t len, 175055682Smarkm Checksum *result) 175155682Smarkm{ 175255682Smarkm krb5_error_code ret; 175355682Smarkm struct key_data *dkey; 175455682Smarkm int keyed_checksum; 175555682Smarkm 175655682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 175778536Sassar if(keyed_checksum && crypto == NULL) { 175878536Sassar krb5_clear_error_string (context); 175955682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 176078536Sassar } 176172448Sassar if(keyed_checksum) { 176255682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 176372448Sassar if (ret) 176472448Sassar return ret; 176572448Sassar } else 176655682Smarkm dkey = NULL; 176755682Smarkm result->cksumtype = ct->type; 176855682Smarkm krb5_data_alloc(&result->checksum, ct->checksumsize); 176972448Sassar (*ct->checksum)(context, dkey, data, len, usage, result); 177055682Smarkm return 0; 177155682Smarkm} 177255682Smarkm 177355682Smarkmstatic krb5_error_code 177455682Smarkmcreate_checksum(krb5_context context, 177555682Smarkm krb5_crypto crypto, 177690929Snectar unsigned usage, /* not krb5_key_usage */ 177778536Sassar krb5_cksumtype type, /* 0 -> pick from crypto */ 177855682Smarkm void *data, 177955682Smarkm size_t len, 178055682Smarkm Checksum *result) 178155682Smarkm{ 178278536Sassar struct checksum_type *ct = NULL; 178355682Smarkm 178478536Sassar if (type) { 178578536Sassar ct = _find_checksum(type); 178678536Sassar } else if (crypto) { 178755682Smarkm ct = crypto->et->keyed_checksum; 178878536Sassar if (ct == NULL) 178978536Sassar ct = crypto->et->checksum; 179078536Sassar } 179178536Sassar 179278536Sassar if(ct == NULL) { 179378536Sassar krb5_set_error_string (context, "checksum type %d not supported", 179478536Sassar type); 179555682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 179678536Sassar } 179755682Smarkm return do_checksum (context, ct, crypto, usage, data, len, result); 179855682Smarkm} 179955682Smarkm 180055682Smarkmkrb5_error_code 180155682Smarkmkrb5_create_checksum(krb5_context context, 180255682Smarkm krb5_crypto crypto, 180378536Sassar krb5_key_usage usage, 180478536Sassar int type, 180555682Smarkm void *data, 180655682Smarkm size_t len, 180755682Smarkm Checksum *result) 180855682Smarkm{ 180955682Smarkm return create_checksum(context, crypto, 181078536Sassar CHECKSUM_USAGE(usage), 181178536Sassar type, data, len, result); 181255682Smarkm} 181355682Smarkm 181455682Smarkmstatic krb5_error_code 181555682Smarkmverify_checksum(krb5_context context, 181655682Smarkm krb5_crypto crypto, 181755682Smarkm unsigned usage, /* not krb5_key_usage */ 181855682Smarkm void *data, 181955682Smarkm size_t len, 182055682Smarkm Checksum *cksum) 182155682Smarkm{ 182255682Smarkm krb5_error_code ret; 182355682Smarkm struct key_data *dkey; 182455682Smarkm int keyed_checksum; 182555682Smarkm Checksum c; 182655682Smarkm struct checksum_type *ct; 182755682Smarkm 182855682Smarkm ct = _find_checksum(cksum->cksumtype); 182978536Sassar if(ct == NULL) { 183078536Sassar krb5_set_error_string (context, "checksum type %d not supported", 183178536Sassar cksum->cksumtype); 183255682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 183378536Sassar } 183478536Sassar if(ct->checksumsize != cksum->checksum.length) { 183578536Sassar krb5_clear_error_string (context); 183655682Smarkm return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ 183778536Sassar } 183855682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 183978536Sassar if(keyed_checksum && crypto == NULL) { 184078536Sassar krb5_clear_error_string (context); 184155682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 184278536Sassar } 184355682Smarkm if(keyed_checksum) 184455682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 184555682Smarkm else 184655682Smarkm dkey = NULL; 184755682Smarkm if(ct->verify) 184872448Sassar return (*ct->verify)(context, dkey, data, len, usage, cksum); 184955682Smarkm 185055682Smarkm ret = krb5_data_alloc (&c.checksum, ct->checksumsize); 185155682Smarkm if (ret) 185255682Smarkm return ret; 185355682Smarkm 185472448Sassar (*ct->checksum)(context, dkey, data, len, usage, &c); 185555682Smarkm 185655682Smarkm if(c.checksum.length != cksum->checksum.length || 185778536Sassar memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { 185878536Sassar krb5_clear_error_string (context); 185955682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 186078536Sassar } else { 186155682Smarkm ret = 0; 186278536Sassar } 186355682Smarkm krb5_data_free (&c.checksum); 186455682Smarkm return ret; 186555682Smarkm} 186655682Smarkm 186755682Smarkmkrb5_error_code 186855682Smarkmkrb5_verify_checksum(krb5_context context, 186955682Smarkm krb5_crypto crypto, 187055682Smarkm krb5_key_usage usage, 187155682Smarkm void *data, 187255682Smarkm size_t len, 187355682Smarkm Checksum *cksum) 187455682Smarkm{ 187555682Smarkm return verify_checksum(context, crypto, 187655682Smarkm CHECKSUM_USAGE(usage), data, len, cksum); 187755682Smarkm} 187855682Smarkm 187955682Smarkmkrb5_error_code 188055682Smarkmkrb5_checksumsize(krb5_context context, 188155682Smarkm krb5_cksumtype type, 188255682Smarkm size_t *size) 188355682Smarkm{ 188455682Smarkm struct checksum_type *ct = _find_checksum(type); 188578536Sassar if(ct == NULL) { 188678536Sassar krb5_set_error_string (context, "checksum type %d not supported", 188778536Sassar type); 188855682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 188978536Sassar } 189055682Smarkm *size = ct->checksumsize; 189155682Smarkm return 0; 189255682Smarkm} 189355682Smarkm 189455682Smarkmkrb5_boolean 189555682Smarkmkrb5_checksum_is_keyed(krb5_context context, 189655682Smarkm krb5_cksumtype type) 189755682Smarkm{ 189855682Smarkm struct checksum_type *ct = _find_checksum(type); 189978536Sassar if(ct == NULL) { 190078536Sassar krb5_set_error_string (context, "checksum type %d not supported", 190178536Sassar type); 190255682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 190378536Sassar } 190455682Smarkm return ct->flags & F_KEYED; 190555682Smarkm} 190655682Smarkm 190755682Smarkmkrb5_boolean 190855682Smarkmkrb5_checksum_is_collision_proof(krb5_context context, 190955682Smarkm krb5_cksumtype type) 191055682Smarkm{ 191155682Smarkm struct checksum_type *ct = _find_checksum(type); 191278536Sassar if(ct == NULL) { 191378536Sassar krb5_set_error_string (context, "checksum type %d not supported", 191478536Sassar type); 191555682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 191678536Sassar } 191755682Smarkm return ct->flags & F_CPROOF; 191855682Smarkm} 191955682Smarkm 192055682Smarkm/************************************************************ 192155682Smarkm * * 192255682Smarkm ************************************************************/ 192355682Smarkm 192472448Sassarstatic krb5_error_code 192578536SassarNULL_encrypt(krb5_context context, 192678536Sassar struct key_data *key, 192755682Smarkm void *data, 192855682Smarkm size_t len, 192972448Sassar krb5_boolean encrypt, 193072448Sassar int usage, 193172448Sassar void *ivec) 193255682Smarkm{ 193372448Sassar return 0; 193455682Smarkm} 193555682Smarkm 193672448Sassarstatic krb5_error_code 193778536SassarDES_CBC_encrypt_null_ivec(krb5_context context, 193878536Sassar struct key_data *key, 193955682Smarkm void *data, 194055682Smarkm size_t len, 194172448Sassar krb5_boolean encrypt, 194272448Sassar int usage, 194372448Sassar void *ignore_ivec) 194455682Smarkm{ 194555682Smarkm des_cblock ivec; 194655682Smarkm des_key_schedule *s = key->schedule->data; 194755682Smarkm memset(&ivec, 0, sizeof(ivec)); 194855682Smarkm des_cbc_encrypt(data, data, len, *s, &ivec, encrypt); 194972448Sassar return 0; 195055682Smarkm} 195155682Smarkm 195272448Sassarstatic krb5_error_code 195378536SassarDES_CBC_encrypt_key_ivec(krb5_context context, 195478536Sassar struct key_data *key, 195555682Smarkm void *data, 195655682Smarkm size_t len, 195772448Sassar krb5_boolean encrypt, 195872448Sassar int usage, 195972448Sassar void *ignore_ivec) 196055682Smarkm{ 196155682Smarkm des_cblock ivec; 196255682Smarkm des_key_schedule *s = key->schedule->data; 196355682Smarkm memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 196455682Smarkm des_cbc_encrypt(data, data, len, *s, &ivec, encrypt); 196572448Sassar return 0; 196655682Smarkm} 196755682Smarkm 196872448Sassarstatic krb5_error_code 196978536SassarDES3_CBC_encrypt(krb5_context context, 197078536Sassar struct key_data *key, 197155682Smarkm void *data, 197255682Smarkm size_t len, 197372448Sassar krb5_boolean encrypt, 197472448Sassar int usage, 1975103426Snectar void *ivec) 197655682Smarkm{ 1977103426Snectar des_cblock local_ivec; 197855682Smarkm des_key_schedule *s = key->schedule->data; 1979103426Snectar if(ivec == NULL) { 1980103426Snectar ivec = &local_ivec; 1981103426Snectar memset(local_ivec, 0, sizeof(local_ivec)); 1982103426Snectar } 198372448Sassar des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt); 198472448Sassar return 0; 198572448Sassar} 198672448Sassar 198772448Sassarstatic krb5_error_code 198878536SassarDES_CFB64_encrypt_null_ivec(krb5_context context, 198978536Sassar struct key_data *key, 199072448Sassar void *data, 199172448Sassar size_t len, 199272448Sassar krb5_boolean encrypt, 199372448Sassar int usage, 199472448Sassar void *ignore_ivec) 199572448Sassar{ 199672448Sassar des_cblock ivec; 199772448Sassar int num = 0; 199872448Sassar des_key_schedule *s = key->schedule->data; 199972448Sassar memset(&ivec, 0, sizeof(ivec)); 200072448Sassar 200172448Sassar des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt); 200272448Sassar return 0; 200372448Sassar} 200472448Sassar 200572448Sassarstatic krb5_error_code 200678536SassarDES_PCBC_encrypt_key_ivec(krb5_context context, 200778536Sassar struct key_data *key, 200872448Sassar void *data, 200972448Sassar size_t len, 201072448Sassar krb5_boolean encrypt, 201172448Sassar int usage, 201272448Sassar void *ignore_ivec) 201372448Sassar{ 201472448Sassar des_cblock ivec; 201572448Sassar des_key_schedule *s = key->schedule->data; 201672448Sassar memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 201772448Sassar 201872448Sassar des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt); 201972448Sassar return 0; 202072448Sassar} 202172448Sassar 2022120948Snectar#ifdef ENABLE_AES 2023120948Snectar 202472448Sassar/* 2025120948Snectar * AES draft-raeburn-krb-rijndael-krb-02 2026120948Snectar */ 2027120948Snectar 2028120948Snectarvoid 2029120948Snectar_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, 2030120948Snectar size_t len, const void *aes_key, 2031120948Snectar unsigned char *ivec, const int enc) 2032120948Snectar{ 2033120948Snectar unsigned char tmp[AES_BLOCK_SIZE]; 2034120948Snectar const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */ 2035120948Snectar int i; 2036120948Snectar 2037120948Snectar /* 2038120948Snectar * In the framework of kerberos, the length can never be shorter 2039120948Snectar * then at least one blocksize. 2040120948Snectar */ 2041120948Snectar 2042120948Snectar if (enc == AES_ENCRYPT) { 2043120948Snectar 2044120948Snectar while(len > AES_BLOCK_SIZE) { 2045120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2046120948Snectar tmp[i] = in[i] ^ ivec[i]; 2047120948Snectar AES_encrypt(tmp, out, key); 2048120948Snectar memcpy(ivec, out, AES_BLOCK_SIZE); 2049120948Snectar len -= AES_BLOCK_SIZE; 2050120948Snectar in += AES_BLOCK_SIZE; 2051120948Snectar out += AES_BLOCK_SIZE; 2052120948Snectar } 2053120948Snectar 2054120948Snectar for (i = 0; i < len; i++) 2055120948Snectar tmp[i] = in[i] ^ ivec[i]; 2056120948Snectar for (; i < AES_BLOCK_SIZE; i++) 2057120948Snectar tmp[i] = 0 ^ ivec[i]; 2058120948Snectar 2059120948Snectar AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); 2060120948Snectar 2061120948Snectar memcpy(out, ivec, len); 2062120948Snectar 2063120948Snectar } else { 2064120948Snectar char tmp2[AES_BLOCK_SIZE]; 2065120948Snectar char tmp3[AES_BLOCK_SIZE]; 2066120948Snectar 2067120948Snectar while(len > AES_BLOCK_SIZE * 2) { 2068120948Snectar memcpy(tmp, in, AES_BLOCK_SIZE); 2069120948Snectar AES_decrypt(in, out, key); 2070120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2071120948Snectar out[i] ^= ivec[i]; 2072120948Snectar memcpy(ivec, tmp, AES_BLOCK_SIZE); 2073120948Snectar len -= AES_BLOCK_SIZE; 2074120948Snectar in += AES_BLOCK_SIZE; 2075120948Snectar out += AES_BLOCK_SIZE; 2076120948Snectar } 2077120948Snectar 2078120948Snectar len -= AES_BLOCK_SIZE; 2079120948Snectar 2080120948Snectar AES_decrypt(in, tmp2, key); 2081120948Snectar 2082120948Snectar memcpy(tmp3, in + AES_BLOCK_SIZE, len); 2083120948Snectar memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ 2084120948Snectar 2085120948Snectar for (i = 0; i < len; i++) 2086120948Snectar out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; 2087120948Snectar 2088120948Snectar AES_decrypt(tmp3, out, key); 2089120948Snectar for (i = 0; i < AES_BLOCK_SIZE; i++) 2090120948Snectar out[i] ^= ivec[i]; 2091120948Snectar } 2092120948Snectar} 2093120948Snectar 2094120948Snectarstatic krb5_error_code 2095120948SnectarAES_CTS_encrypt(krb5_context context, 2096120948Snectar struct key_data *key, 2097120948Snectar void *data, 2098120948Snectar size_t len, 2099120948Snectar krb5_boolean encrypt, 2100120948Snectar int usage, 2101120948Snectar void *ivec) 2102120948Snectar{ 2103120948Snectar AES_KEY *k = key->schedule->data; 2104120948Snectar char local_ivec[AES_BLOCK_SIZE]; 2105120948Snectar 2106120948Snectar if (encrypt) 2107120948Snectar k = &k[0]; 2108120948Snectar else 2109120948Snectar k = &k[1]; 2110120948Snectar 2111120948Snectar if (len < AES_BLOCK_SIZE) 2112120948Snectar abort(); 2113120948Snectar if (len == AES_BLOCK_SIZE) { 2114120948Snectar if (encrypt) 2115120948Snectar AES_encrypt(data, data, k); 2116120948Snectar else 2117120948Snectar AES_decrypt(data, data, k); 2118120948Snectar } else { 2119120948Snectar if(ivec == NULL) { 2120120948Snectar memset(local_ivec, 0, sizeof(local_ivec)); 2121120948Snectar ivec = local_ivec; 2122120948Snectar } 2123120948Snectar _krb5_aes_cts_encrypt(data, data, len, k, ivec, encrypt); 2124120948Snectar } 2125120948Snectar 2126120948Snectar return 0; 2127120948Snectar} 2128120948Snectar#endif /* ENABLE_AES */ 2129120948Snectar 2130120948Snectar/* 213172448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 213272448Sassar * 213372448Sassar * warning: not for small children 213472448Sassar */ 213572448Sassar 213672448Sassarstatic krb5_error_code 213778536SassarARCFOUR_subencrypt(krb5_context context, 213878536Sassar struct key_data *key, 213972448Sassar void *data, 214072448Sassar size_t len, 214172448Sassar int usage, 214272448Sassar void *ivec) 214372448Sassar{ 214472448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 214572448Sassar Checksum k1_c, k2_c, k3_c, cksum; 214672448Sassar struct key_data ke; 214772448Sassar krb5_keyblock kb; 214872448Sassar unsigned char t[4]; 214972448Sassar RC4_KEY rc4_key; 215090929Snectar unsigned char *cdata = data; 215172448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 215272448Sassar 215372448Sassar t[0] = (usage >> 0) & 0xFF; 215472448Sassar t[1] = (usage >> 8) & 0xFF; 215572448Sassar t[2] = (usage >> 16) & 0xFF; 215672448Sassar t[3] = (usage >> 24) & 0xFF; 215772448Sassar 215872448Sassar k1_c.checksum.length = sizeof(k1_c_data); 215972448Sassar k1_c.checksum.data = k1_c_data; 216072448Sassar 216172448Sassar hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 216272448Sassar 216372448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 216472448Sassar 216572448Sassar k2_c.checksum.length = sizeof(k2_c_data); 216672448Sassar k2_c.checksum.data = k2_c_data; 216772448Sassar 216872448Sassar ke.key = &kb; 216972448Sassar kb.keyvalue = k2_c.checksum; 217072448Sassar 217172448Sassar cksum.checksum.length = 16; 217272448Sassar cksum.checksum.data = data; 217372448Sassar 217472448Sassar hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 217572448Sassar 217672448Sassar ke.key = &kb; 217772448Sassar kb.keyvalue = k1_c.checksum; 217872448Sassar 217972448Sassar k3_c.checksum.length = sizeof(k3_c_data); 218072448Sassar k3_c.checksum.data = k3_c_data; 218172448Sassar 218272448Sassar hmac(NULL, c, data, 16, 0, &ke, &k3_c); 218372448Sassar 218472448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 218572448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 218672448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 218772448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 218872448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 218972448Sassar return 0; 219072448Sassar} 219172448Sassar 219272448Sassarstatic krb5_error_code 219378536SassarARCFOUR_subdecrypt(krb5_context context, 219478536Sassar struct key_data *key, 219572448Sassar void *data, 219672448Sassar size_t len, 219772448Sassar int usage, 219872448Sassar void *ivec) 219972448Sassar{ 220072448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 220172448Sassar Checksum k1_c, k2_c, k3_c, cksum; 220272448Sassar struct key_data ke; 220372448Sassar krb5_keyblock kb; 220472448Sassar unsigned char t[4]; 220572448Sassar RC4_KEY rc4_key; 220690929Snectar unsigned char *cdata = data; 220772448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 220872448Sassar unsigned char cksum_data[16]; 220972448Sassar 221072448Sassar t[0] = (usage >> 0) & 0xFF; 221172448Sassar t[1] = (usage >> 8) & 0xFF; 221272448Sassar t[2] = (usage >> 16) & 0xFF; 221372448Sassar t[3] = (usage >> 24) & 0xFF; 221472448Sassar 221572448Sassar k1_c.checksum.length = sizeof(k1_c_data); 221672448Sassar k1_c.checksum.data = k1_c_data; 221772448Sassar 221872448Sassar hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 221972448Sassar 222072448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 222172448Sassar 222272448Sassar k2_c.checksum.length = sizeof(k2_c_data); 222372448Sassar k2_c.checksum.data = k2_c_data; 222472448Sassar 222572448Sassar ke.key = &kb; 222672448Sassar kb.keyvalue = k1_c.checksum; 222772448Sassar 222872448Sassar k3_c.checksum.length = sizeof(k3_c_data); 222972448Sassar k3_c.checksum.data = k3_c_data; 223072448Sassar 223172448Sassar hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); 223272448Sassar 223372448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 223472448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 223572448Sassar 223672448Sassar ke.key = &kb; 223772448Sassar kb.keyvalue = k2_c.checksum; 223872448Sassar 223972448Sassar cksum.checksum.length = 16; 224072448Sassar cksum.checksum.data = cksum_data; 224172448Sassar 224272448Sassar hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 224372448Sassar 224472448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 224572448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 224672448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 224772448Sassar 224878536Sassar if (memcmp (cksum.checksum.data, data, 16) != 0) { 224978536Sassar krb5_clear_error_string (context); 225072448Sassar return KRB5KRB_AP_ERR_BAD_INTEGRITY; 225178536Sassar } else { 225272448Sassar return 0; 225378536Sassar } 225472448Sassar} 225572448Sassar 225672448Sassar/* 225772448Sassar * convert the usage numbers used in 225872448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in 225972448Sassar * draft-brezak-win2k-krb-rc4-hmac-03.txt 226072448Sassar */ 226172448Sassar 2262102647Snectarstatic krb5_error_code 2263102647Snectarusage2arcfour (krb5_context context, int *usage) 226472448Sassar{ 2265102647Snectar switch (*usage) { 226672448Sassar case KRB5_KU_PA_ENC_TIMESTAMP : 2267102647Snectar *usage = 1; 2268102647Snectar return 0; 226972448Sassar case KRB5_KU_TICKET : 2270120948Snectar *usage = 2; 2271120948Snectar return 0; 227272448Sassar case KRB5_KU_AS_REP_ENC_PART : 2273102647Snectar *usage = 8; 2274102647Snectar return 0; 227572448Sassar case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION : 227672448Sassar case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY : 227772448Sassar case KRB5_KU_TGS_REQ_AUTH_CKSUM : 227872448Sassar case KRB5_KU_TGS_REQ_AUTH : 2279102647Snectar *usage = 7; 2280102647Snectar return 0; 228172448Sassar case KRB5_KU_TGS_REP_ENC_PART_SESSION : 228272448Sassar case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : 2283102647Snectar *usage = 8; 2284102647Snectar return 0; 228572448Sassar case KRB5_KU_AP_REQ_AUTH_CKSUM : 228672448Sassar case KRB5_KU_AP_REQ_AUTH : 228772448Sassar case KRB5_KU_AP_REQ_ENC_PART : 2288102647Snectar *usage = 11; 2289102647Snectar return 0; 229072448Sassar case KRB5_KU_KRB_PRIV : 2291102647Snectar *usage = 0; 229272448Sassar return 0; 229372448Sassar case KRB5_KU_KRB_CRED : 229472448Sassar case KRB5_KU_KRB_SAFE_CKSUM : 229572448Sassar case KRB5_KU_OTHER_ENCRYPTED : 229672448Sassar case KRB5_KU_OTHER_CKSUM : 229772448Sassar case KRB5_KU_KRB_ERROR : 229872448Sassar case KRB5_KU_AD_KDC_ISSUED : 229972448Sassar case KRB5_KU_MANDATORY_TICKET_EXTENSION : 230072448Sassar case KRB5_KU_AUTH_DATA_TICKET_EXTENSION : 230172448Sassar case KRB5_KU_USAGE_SEAL : 230272448Sassar case KRB5_KU_USAGE_SIGN : 230372448Sassar case KRB5_KU_USAGE_SEQ : 230472448Sassar default : 2305102647Snectar krb5_set_error_string(context, "unknown arcfour usage type %d", *usage); 2306102647Snectar return KRB5_PROG_ETYPE_NOSUPP; 230772448Sassar } 230872448Sassar} 230972448Sassar 231072448Sassarstatic krb5_error_code 231178536SassarARCFOUR_encrypt(krb5_context context, 231278536Sassar struct key_data *key, 231355682Smarkm void *data, 231455682Smarkm size_t len, 231572448Sassar krb5_boolean encrypt, 231672448Sassar int usage, 231772448Sassar void *ivec) 231855682Smarkm{ 2319102647Snectar krb5_error_code ret; 2320102647Snectar if((ret = usage2arcfour (context, &usage)) != 0) 2321102647Snectar return ret; 232255682Smarkm 232372448Sassar if (encrypt) 232478536Sassar return ARCFOUR_subencrypt (context, key, data, len, usage, ivec); 232572448Sassar else 232678536Sassar return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec); 232755682Smarkm} 232855682Smarkm 232972448Sassar 233055682Smarkm/* 233155682Smarkm * these should currently be in reverse preference order. 233272448Sassar * (only relevant for !F_PSEUDO) */ 233355682Smarkm 233478536Sassarstatic struct encryption_type enctype_null = { 233578536Sassar ETYPE_NULL, 233678536Sassar "null", 233778536Sassar 1, 2338120948Snectar 1, 233978536Sassar 0, 234078536Sassar &keytype_null, 234178536Sassar &checksum_none, 234278536Sassar NULL, 234378536Sassar 0, 234478536Sassar NULL_encrypt, 234555682Smarkm}; 234678536Sassarstatic struct encryption_type enctype_des_cbc_crc = { 234778536Sassar ETYPE_DES_CBC_CRC, 234878536Sassar "des-cbc-crc", 234978536Sassar 8, 235078536Sassar 8, 2351120948Snectar 8, 235278536Sassar &keytype_des, 235378536Sassar &checksum_crc32, 235478536Sassar NULL, 235578536Sassar 0, 235678536Sassar DES_CBC_encrypt_key_ivec, 235778536Sassar}; 235878536Sassarstatic struct encryption_type enctype_des_cbc_md4 = { 235978536Sassar ETYPE_DES_CBC_MD4, 236078536Sassar "des-cbc-md4", 236178536Sassar 8, 236278536Sassar 8, 2363120948Snectar 8, 236478536Sassar &keytype_des, 236578536Sassar &checksum_rsa_md4, 236678536Sassar &checksum_rsa_md4_des, 236778536Sassar 0, 236878536Sassar DES_CBC_encrypt_null_ivec, 236978536Sassar}; 237078536Sassarstatic struct encryption_type enctype_des_cbc_md5 = { 237178536Sassar ETYPE_DES_CBC_MD5, 237278536Sassar "des-cbc-md5", 237378536Sassar 8, 237478536Sassar 8, 2375120948Snectar 8, 237678536Sassar &keytype_des, 237778536Sassar &checksum_rsa_md5, 237878536Sassar &checksum_rsa_md5_des, 237978536Sassar 0, 238078536Sassar DES_CBC_encrypt_null_ivec, 238178536Sassar}; 238278536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = { 238378536Sassar ETYPE_ARCFOUR_HMAC_MD5, 238478536Sassar "arcfour-hmac-md5", 238578536Sassar 1, 2386120948Snectar 1, 238778536Sassar 8, 238878536Sassar &keytype_arcfour, 238990929Snectar &checksum_hmac_md5, 2390120948Snectar /* &checksum_hmac_md5_enc */ NULL, 239178536Sassar F_SPECIAL, 239278536Sassar ARCFOUR_encrypt 239378536Sassar}; 239478536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = { 239578536Sassar ETYPE_DES3_CBC_MD5, 239678536Sassar "des3-cbc-md5", 239778536Sassar 8, 239878536Sassar 8, 2399120948Snectar 8, 240078536Sassar &keytype_des3, 240178536Sassar &checksum_rsa_md5, 240278536Sassar &checksum_rsa_md5_des3, 240378536Sassar 0, 240478536Sassar DES3_CBC_encrypt, 240578536Sassar}; 240678536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = { 240778536Sassar ETYPE_DES3_CBC_SHA1, 240878536Sassar "des3-cbc-sha1", 240978536Sassar 8, 241078536Sassar 8, 2411120948Snectar 8, 241278536Sassar &keytype_des3_derived, 241378536Sassar &checksum_sha1, 241478536Sassar &checksum_hmac_sha1_des3, 241578536Sassar F_DERIVED, 241678536Sassar DES3_CBC_encrypt, 241778536Sassar}; 241878536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = { 241978536Sassar ETYPE_OLD_DES3_CBC_SHA1, 242078536Sassar "old-des3-cbc-sha1", 242178536Sassar 8, 242278536Sassar 8, 2423120948Snectar 8, 242478536Sassar &keytype_des3, 242578536Sassar &checksum_sha1, 242678536Sassar &checksum_hmac_sha1_des3, 242778536Sassar 0, 242878536Sassar DES3_CBC_encrypt, 242978536Sassar}; 2430120948Snectar#ifdef ENABLE_AES 2431120948Snectarstatic struct encryption_type enctype_aes128_cts_hmac_sha1 = { 2432120948Snectar ETYPE_AES128_CTS_HMAC_SHA1_96, 2433120948Snectar "aes128-cts-hmac-sha1-96", 2434120948Snectar 16, 2435120948Snectar 1, 2436120948Snectar 16, 2437120948Snectar &keytype_aes128, 2438120948Snectar &checksum_sha1, 2439120948Snectar &checksum_hmac_sha1_aes128, 2440120948Snectar 0, 2441120948Snectar AES_CTS_encrypt, 2442120948Snectar}; 2443120948Snectarstatic struct encryption_type enctype_aes256_cts_hmac_sha1 = { 2444120948Snectar ETYPE_AES256_CTS_HMAC_SHA1_96, 2445120948Snectar "aes256-cts-hmac-sha1-96", 2446120948Snectar 16, 2447120948Snectar 1, 2448120948Snectar 16, 2449120948Snectar &keytype_aes256, 2450120948Snectar &checksum_sha1, 2451120948Snectar &checksum_hmac_sha1_aes256, 2452120948Snectar 0, 2453120948Snectar AES_CTS_encrypt, 2454120948Snectar}; 2455120948Snectar#endif /* ENABLE_AES */ 245678536Sassarstatic struct encryption_type enctype_des_cbc_none = { 245778536Sassar ETYPE_DES_CBC_NONE, 245878536Sassar "des-cbc-none", 245978536Sassar 8, 2460120948Snectar 8, 246178536Sassar 0, 246278536Sassar &keytype_des, 246378536Sassar &checksum_none, 246478536Sassar NULL, 246578536Sassar F_PSEUDO, 246678536Sassar DES_CBC_encrypt_null_ivec, 246778536Sassar}; 246878536Sassarstatic struct encryption_type enctype_des_cfb64_none = { 246978536Sassar ETYPE_DES_CFB64_NONE, 247078536Sassar "des-cfb64-none", 247178536Sassar 1, 2472120948Snectar 1, 247378536Sassar 0, 247478536Sassar &keytype_des, 247578536Sassar &checksum_none, 247678536Sassar NULL, 247778536Sassar F_PSEUDO, 247878536Sassar DES_CFB64_encrypt_null_ivec, 247978536Sassar}; 248078536Sassarstatic struct encryption_type enctype_des_pcbc_none = { 248178536Sassar ETYPE_DES_PCBC_NONE, 248278536Sassar "des-pcbc-none", 248378536Sassar 8, 2484120948Snectar 8, 248578536Sassar 0, 248678536Sassar &keytype_des, 248778536Sassar &checksum_none, 248878536Sassar NULL, 248978536Sassar F_PSEUDO, 249078536Sassar DES_PCBC_encrypt_key_ivec, 249178536Sassar}; 249278536Sassarstatic struct encryption_type enctype_des3_cbc_none = { 249378536Sassar ETYPE_DES3_CBC_NONE, 249478536Sassar "des3-cbc-none", 249578536Sassar 8, 2496120948Snectar 8, 249778536Sassar 0, 249878536Sassar &keytype_des3_derived, 249978536Sassar &checksum_none, 250078536Sassar NULL, 250178536Sassar F_PSEUDO, 250278536Sassar DES3_CBC_encrypt, 250378536Sassar}; 250455682Smarkm 250578536Sassarstatic struct encryption_type *etypes[] = { 250678536Sassar &enctype_null, 250778536Sassar &enctype_des_cbc_crc, 250878536Sassar &enctype_des_cbc_md4, 250978536Sassar &enctype_des_cbc_md5, 251078536Sassar &enctype_arcfour_hmac_md5, 251178536Sassar &enctype_des3_cbc_md5, 251278536Sassar &enctype_des3_cbc_sha1, 251378536Sassar &enctype_old_des3_cbc_sha1, 2514120948Snectar#ifdef ENABLE_AES 2515120948Snectar &enctype_aes128_cts_hmac_sha1, 2516120948Snectar &enctype_aes256_cts_hmac_sha1, 2517120948Snectar#endif 251878536Sassar &enctype_des_cbc_none, 251978536Sassar &enctype_des_cfb64_none, 252078536Sassar &enctype_des_pcbc_none, 2521103426Snectar &enctype_des3_cbc_none 252278536Sassar}; 252378536Sassar 252455682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); 252555682Smarkm 252655682Smarkm 252755682Smarkmstatic struct encryption_type * 252855682Smarkm_find_enctype(krb5_enctype type) 252955682Smarkm{ 253055682Smarkm int i; 253155682Smarkm for(i = 0; i < num_etypes; i++) 253278536Sassar if(etypes[i]->type == type) 253378536Sassar return etypes[i]; 253455682Smarkm return NULL; 253555682Smarkm} 253655682Smarkm 253755682Smarkm 253855682Smarkmkrb5_error_code 253955682Smarkmkrb5_enctype_to_string(krb5_context context, 254055682Smarkm krb5_enctype etype, 254155682Smarkm char **string) 254255682Smarkm{ 254355682Smarkm struct encryption_type *e; 254455682Smarkm e = _find_enctype(etype); 254578536Sassar if(e == NULL) { 254678536Sassar krb5_set_error_string (context, "encryption type %d not supported", 254778536Sassar etype); 254855682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 254978536Sassar } 255055682Smarkm *string = strdup(e->name); 255178536Sassar if(*string == NULL) { 255278536Sassar krb5_set_error_string(context, "malloc: out of memory"); 255355682Smarkm return ENOMEM; 255478536Sassar } 255555682Smarkm return 0; 255655682Smarkm} 255755682Smarkm 255855682Smarkmkrb5_error_code 255955682Smarkmkrb5_string_to_enctype(krb5_context context, 256055682Smarkm const char *string, 256155682Smarkm krb5_enctype *etype) 256255682Smarkm{ 256355682Smarkm int i; 256455682Smarkm for(i = 0; i < num_etypes; i++) 256578536Sassar if(strcasecmp(etypes[i]->name, string) == 0){ 256678536Sassar *etype = etypes[i]->type; 256755682Smarkm return 0; 256855682Smarkm } 256978536Sassar krb5_set_error_string (context, "encryption type %s not supported", 257078536Sassar string); 257155682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 257255682Smarkm} 257355682Smarkm 257455682Smarkmkrb5_error_code 257555682Smarkmkrb5_enctype_to_keytype(krb5_context context, 257655682Smarkm krb5_enctype etype, 257755682Smarkm krb5_keytype *keytype) 257855682Smarkm{ 257955682Smarkm struct encryption_type *e = _find_enctype(etype); 258078536Sassar if(e == NULL) { 258178536Sassar krb5_set_error_string (context, "encryption type %d not supported", 258278536Sassar etype); 258355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 258478536Sassar } 258555682Smarkm *keytype = e->keytype->type; /* XXX */ 258655682Smarkm return 0; 258755682Smarkm} 258855682Smarkm 258955682Smarkm#if 0 259055682Smarkmkrb5_error_code 259155682Smarkmkrb5_keytype_to_enctype(krb5_context context, 259255682Smarkm krb5_keytype keytype, 259355682Smarkm krb5_enctype *etype) 259455682Smarkm{ 259555682Smarkm struct key_type *kt = _find_keytype(keytype); 259655682Smarkm krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); 259755682Smarkm if(kt == NULL) 259855682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 259955682Smarkm *etype = kt->best_etype; 260055682Smarkm return 0; 260155682Smarkm} 260255682Smarkm#endif 260355682Smarkm 260455682Smarkmkrb5_error_code 260555682Smarkmkrb5_keytype_to_enctypes (krb5_context context, 260655682Smarkm krb5_keytype keytype, 260755682Smarkm unsigned *len, 260890929Snectar krb5_enctype **val) 260955682Smarkm{ 261055682Smarkm int i; 261155682Smarkm unsigned n = 0; 261290929Snectar krb5_enctype *ret; 261355682Smarkm 261455682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 261578536Sassar if (etypes[i]->keytype->type == keytype 261678536Sassar && !(etypes[i]->flags & F_PSEUDO)) 261755682Smarkm ++n; 261855682Smarkm } 261990929Snectar ret = malloc(n * sizeof(*ret)); 262078536Sassar if (ret == NULL && n != 0) { 262178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 262255682Smarkm return ENOMEM; 262378536Sassar } 262455682Smarkm n = 0; 262555682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 262678536Sassar if (etypes[i]->keytype->type == keytype 262778536Sassar && !(etypes[i]->flags & F_PSEUDO)) 262878536Sassar ret[n++] = etypes[i]->type; 262955682Smarkm } 263055682Smarkm *len = n; 263155682Smarkm *val = ret; 263255682Smarkm return 0; 263355682Smarkm} 263455682Smarkm 263555682Smarkm/* 263655682Smarkm * First take the configured list of etypes for `keytype' if available, 263755682Smarkm * else, do `krb5_keytype_to_enctypes'. 263855682Smarkm */ 263955682Smarkm 264055682Smarkmkrb5_error_code 264155682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context, 264255682Smarkm krb5_keytype keytype, 264355682Smarkm unsigned *len, 264490929Snectar krb5_enctype **val) 264555682Smarkm{ 264655682Smarkm int i, n; 264790929Snectar krb5_enctype *ret; 264855682Smarkm 264955682Smarkm if (keytype != KEYTYPE_DES || context->etypes_des == NULL) 265055682Smarkm return krb5_keytype_to_enctypes (context, keytype, len, val); 265155682Smarkm 265255682Smarkm for (n = 0; context->etypes_des[n]; ++n) 265355682Smarkm ; 265455682Smarkm ret = malloc (n * sizeof(*ret)); 265578536Sassar if (ret == NULL && n != 0) { 265678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 265755682Smarkm return ENOMEM; 265878536Sassar } 265955682Smarkm for (i = 0; i < n; ++i) 266055682Smarkm ret[i] = context->etypes_des[i]; 266155682Smarkm *len = n; 266255682Smarkm *val = ret; 266355682Smarkm return 0; 266455682Smarkm} 266555682Smarkm 266655682Smarkmkrb5_error_code 266755682Smarkmkrb5_enctype_valid(krb5_context context, 266855682Smarkm krb5_enctype etype) 266955682Smarkm{ 267055682Smarkm return _find_enctype(etype) != NULL; 267155682Smarkm} 267255682Smarkm 267355682Smarkm/* if two enctypes have compatible keys */ 267455682Smarkmkrb5_boolean 267555682Smarkmkrb5_enctypes_compatible_keys(krb5_context context, 267655682Smarkm krb5_enctype etype1, 267755682Smarkm krb5_enctype etype2) 267855682Smarkm{ 267955682Smarkm struct encryption_type *e1 = _find_enctype(etype1); 268055682Smarkm struct encryption_type *e2 = _find_enctype(etype2); 268155682Smarkm return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; 268255682Smarkm} 268355682Smarkm 268455682Smarkmstatic krb5_boolean 268555682Smarkmderived_crypto(krb5_context context, 268655682Smarkm krb5_crypto crypto) 268755682Smarkm{ 268855682Smarkm return (crypto->et->flags & F_DERIVED) != 0; 268955682Smarkm} 269055682Smarkm 269172448Sassarstatic krb5_boolean 269272448Sassarspecial_crypto(krb5_context context, 269372448Sassar krb5_crypto crypto) 269472448Sassar{ 269572448Sassar return (crypto->et->flags & F_SPECIAL) != 0; 269672448Sassar} 269755682Smarkm 269855682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize) 269955682Smarkm#define CHECKSUMTYPE(C) ((C)->type) 270055682Smarkm 270155682Smarkmstatic krb5_error_code 270255682Smarkmencrypt_internal_derived(krb5_context context, 270355682Smarkm krb5_crypto crypto, 270455682Smarkm unsigned usage, 270555682Smarkm void *data, 270655682Smarkm size_t len, 270772448Sassar krb5_data *result, 270872448Sassar void *ivec) 270955682Smarkm{ 271090929Snectar size_t sz, block_sz, checksum_sz, total_sz; 271155682Smarkm Checksum cksum; 271255682Smarkm unsigned char *p, *q; 271355682Smarkm krb5_error_code ret; 271455682Smarkm struct key_data *dkey; 271590929Snectar const struct encryption_type *et = crypto->et; 271655682Smarkm 271755682Smarkm checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 271855682Smarkm 271990929Snectar sz = et->confoundersize + len; 2720120948Snectar block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 272190929Snectar total_sz = block_sz + checksum_sz; 272290929Snectar p = calloc(1, total_sz); 272390929Snectar if(p == NULL) { 272490929Snectar krb5_set_error_string(context, "malloc: out of memory"); 272555682Smarkm return ENOMEM; 272690929Snectar } 272755682Smarkm 272855682Smarkm q = p; 272955682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 273055682Smarkm q += et->confoundersize; 273155682Smarkm memcpy(q, data, len); 273255682Smarkm 273355682Smarkm ret = create_checksum(context, 273455682Smarkm crypto, 273555682Smarkm INTEGRITY_USAGE(usage), 273678536Sassar et->keyed_checksum->type, 273755682Smarkm p, 273855682Smarkm block_sz, 273955682Smarkm &cksum); 274072448Sassar if(ret == 0 && cksum.checksum.length != checksum_sz) { 274172448Sassar free_Checksum (&cksum); 274278536Sassar krb5_clear_error_string (context); 274372448Sassar ret = KRB5_CRYPTO_INTERNAL; 274472448Sassar } 274590929Snectar if(ret) 274690929Snectar goto fail; 274755682Smarkm memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 274872448Sassar free_Checksum (&cksum); 274955682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 275090929Snectar if(ret) 275190929Snectar goto fail; 275255682Smarkm ret = _key_schedule(context, dkey); 275390929Snectar if(ret) 275490929Snectar goto fail; 275555682Smarkm#ifdef CRYPTO_DEBUG 275655682Smarkm krb5_crypto_debug(context, 1, block_sz, dkey->key); 275755682Smarkm#endif 275890929Snectar ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 275990929Snectar if (ret) 276090929Snectar goto fail; 276155682Smarkm result->data = p; 276290929Snectar result->length = total_sz; 276355682Smarkm return 0; 276490929Snectar fail: 276590929Snectar memset(p, 0, total_sz); 276690929Snectar free(p); 276790929Snectar return ret; 276855682Smarkm} 276955682Smarkm 277090929Snectar 277155682Smarkmstatic krb5_error_code 277255682Smarkmencrypt_internal(krb5_context context, 277355682Smarkm krb5_crypto crypto, 277455682Smarkm void *data, 277555682Smarkm size_t len, 277672448Sassar krb5_data *result, 277772448Sassar void *ivec) 277855682Smarkm{ 277955682Smarkm size_t sz, block_sz, checksum_sz; 278055682Smarkm Checksum cksum; 278155682Smarkm unsigned char *p, *q; 278255682Smarkm krb5_error_code ret; 278390929Snectar const struct encryption_type *et = crypto->et; 278455682Smarkm 278578536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 278655682Smarkm 278755682Smarkm sz = et->confoundersize + checksum_sz + len; 2788120948Snectar block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 278955682Smarkm p = calloc(1, block_sz); 279078536Sassar if(p == NULL) { 279178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 279255682Smarkm return ENOMEM; 279378536Sassar } 279455682Smarkm 279555682Smarkm q = p; 279655682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 279755682Smarkm q += et->confoundersize; 279855682Smarkm memset(q, 0, checksum_sz); 279955682Smarkm q += checksum_sz; 280055682Smarkm memcpy(q, data, len); 280155682Smarkm 280255682Smarkm ret = create_checksum(context, 280378536Sassar crypto, 280455682Smarkm 0, 280578536Sassar et->checksum->type, 280655682Smarkm p, 280755682Smarkm block_sz, 280855682Smarkm &cksum); 280955682Smarkm if(ret == 0 && cksum.checksum.length != checksum_sz) { 281078536Sassar krb5_clear_error_string (context); 281190929Snectar free_Checksum(&cksum); 281255682Smarkm ret = KRB5_CRYPTO_INTERNAL; 281355682Smarkm } 281490929Snectar if(ret) 281590929Snectar goto fail; 281655682Smarkm memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); 281755682Smarkm free_Checksum(&cksum); 281855682Smarkm ret = _key_schedule(context, &crypto->key); 281990929Snectar if(ret) 282090929Snectar goto fail; 282190929Snectar#ifdef CRYPTO_DEBUG 282290929Snectar krb5_crypto_debug(context, 1, block_sz, crypto->key.key); 282390929Snectar#endif 282490929Snectar ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); 282590929Snectar if (ret) { 282655682Smarkm memset(p, 0, block_sz); 282755682Smarkm free(p); 282855682Smarkm return ret; 282955682Smarkm } 283055682Smarkm result->data = p; 283155682Smarkm result->length = block_sz; 283255682Smarkm return 0; 283390929Snectar fail: 283490929Snectar memset(p, 0, block_sz); 283590929Snectar free(p); 283690929Snectar return ret; 283755682Smarkm} 283855682Smarkm 283955682Smarkmstatic krb5_error_code 284072448Sassarencrypt_internal_special(krb5_context context, 284172448Sassar krb5_crypto crypto, 284272448Sassar int usage, 284372448Sassar void *data, 284472448Sassar size_t len, 284572448Sassar krb5_data *result, 284672448Sassar void *ivec) 284772448Sassar{ 284872448Sassar struct encryption_type *et = crypto->et; 284978536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 285072448Sassar size_t sz = len + cksum_sz + et->confoundersize; 285172448Sassar char *tmp, *p; 285290929Snectar krb5_error_code ret; 285372448Sassar 285472448Sassar tmp = malloc (sz); 285578536Sassar if (tmp == NULL) { 285678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 285772448Sassar return ENOMEM; 285878536Sassar } 285972448Sassar p = tmp; 286072448Sassar memset (p, 0, cksum_sz); 286172448Sassar p += cksum_sz; 286272448Sassar krb5_generate_random_block(p, et->confoundersize); 286372448Sassar p += et->confoundersize; 286472448Sassar memcpy (p, data, len); 286590929Snectar ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); 286690929Snectar if (ret) { 286790929Snectar memset(tmp, 0, sz); 286890929Snectar free(tmp); 286990929Snectar return ret; 287090929Snectar } 287172448Sassar result->data = tmp; 287272448Sassar result->length = sz; 287372448Sassar return 0; 287472448Sassar} 287572448Sassar 287672448Sassarstatic krb5_error_code 287755682Smarkmdecrypt_internal_derived(krb5_context context, 287855682Smarkm krb5_crypto crypto, 287955682Smarkm unsigned usage, 288055682Smarkm void *data, 288155682Smarkm size_t len, 288272448Sassar krb5_data *result, 288372448Sassar void *ivec) 288455682Smarkm{ 288555682Smarkm size_t checksum_sz; 288655682Smarkm Checksum cksum; 288755682Smarkm unsigned char *p; 288855682Smarkm krb5_error_code ret; 288955682Smarkm struct key_data *dkey; 289055682Smarkm struct encryption_type *et = crypto->et; 289155682Smarkm unsigned long l; 289255682Smarkm 289372448Sassar checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 289478536Sassar if (len < checksum_sz) { 289578536Sassar krb5_clear_error_string (context); 289678536Sassar return EINVAL; /* XXX - better error code? */ 289778536Sassar } 289872448Sassar 289955682Smarkm p = malloc(len); 290078536Sassar if(len != 0 && p == NULL) { 290178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 290255682Smarkm return ENOMEM; 290378536Sassar } 290455682Smarkm memcpy(p, data, len); 290555682Smarkm 290655682Smarkm len -= checksum_sz; 290755682Smarkm 290855682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 290955682Smarkm if(ret) { 291055682Smarkm free(p); 291155682Smarkm return ret; 291255682Smarkm } 291355682Smarkm ret = _key_schedule(context, dkey); 291455682Smarkm if(ret) { 291555682Smarkm free(p); 291655682Smarkm return ret; 291755682Smarkm } 291855682Smarkm#ifdef CRYPTO_DEBUG 291955682Smarkm krb5_crypto_debug(context, 0, len, dkey->key); 292055682Smarkm#endif 292190929Snectar ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 292290929Snectar if (ret) { 292390929Snectar free(p); 292490929Snectar return ret; 292590929Snectar } 292655682Smarkm 292755682Smarkm cksum.checksum.data = p + len; 292855682Smarkm cksum.checksum.length = checksum_sz; 292955682Smarkm cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 293055682Smarkm 293155682Smarkm ret = verify_checksum(context, 293255682Smarkm crypto, 293355682Smarkm INTEGRITY_USAGE(usage), 293455682Smarkm p, 293555682Smarkm len, 293655682Smarkm &cksum); 293755682Smarkm if(ret) { 293855682Smarkm free(p); 293955682Smarkm return ret; 294055682Smarkm } 294155682Smarkm l = len - et->confoundersize; 294255682Smarkm memmove(p, p + et->confoundersize, l); 294355682Smarkm result->data = realloc(p, l); 294478536Sassar if(result->data == NULL) { 294555682Smarkm free(p); 294678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 294755682Smarkm return ENOMEM; 294855682Smarkm } 294955682Smarkm result->length = l; 295055682Smarkm return 0; 295155682Smarkm} 295255682Smarkm 295355682Smarkmstatic krb5_error_code 295455682Smarkmdecrypt_internal(krb5_context context, 295555682Smarkm krb5_crypto crypto, 295655682Smarkm void *data, 295755682Smarkm size_t len, 295872448Sassar krb5_data *result, 295972448Sassar void *ivec) 296055682Smarkm{ 296155682Smarkm krb5_error_code ret; 296255682Smarkm unsigned char *p; 296355682Smarkm Checksum cksum; 296455682Smarkm size_t checksum_sz, l; 296555682Smarkm struct encryption_type *et = crypto->et; 296655682Smarkm 296778536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 296855682Smarkm p = malloc(len); 296978536Sassar if(len != 0 && p == NULL) { 297078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 297155682Smarkm return ENOMEM; 297278536Sassar } 297355682Smarkm memcpy(p, data, len); 297455682Smarkm 297555682Smarkm ret = _key_schedule(context, &crypto->key); 297655682Smarkm if(ret) { 297755682Smarkm free(p); 297855682Smarkm return ret; 297955682Smarkm } 298055682Smarkm#ifdef CRYPTO_DEBUG 298155682Smarkm krb5_crypto_debug(context, 0, len, crypto->key.key); 298255682Smarkm#endif 298390929Snectar ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); 298490929Snectar if (ret) { 298590929Snectar free(p); 298690929Snectar return ret; 298790929Snectar } 298855682Smarkm ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); 298955682Smarkm if(ret) { 299072448Sassar free(p); 299172448Sassar return ret; 299255682Smarkm } 299355682Smarkm memset(p + et->confoundersize, 0, checksum_sz); 299478536Sassar cksum.cksumtype = CHECKSUMTYPE(et->checksum); 299555682Smarkm ret = verify_checksum(context, NULL, 0, p, len, &cksum); 299655682Smarkm free_Checksum(&cksum); 299755682Smarkm if(ret) { 299855682Smarkm free(p); 299955682Smarkm return ret; 300055682Smarkm } 300155682Smarkm l = len - et->confoundersize - checksum_sz; 300255682Smarkm memmove(p, p + et->confoundersize + checksum_sz, l); 300355682Smarkm result->data = realloc(p, l); 300455682Smarkm if(result->data == NULL) { 300555682Smarkm free(p); 300678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 300755682Smarkm return ENOMEM; 300855682Smarkm } 300955682Smarkm result->length = l; 301055682Smarkm return 0; 301155682Smarkm} 301255682Smarkm 301372448Sassarstatic krb5_error_code 301472448Sassardecrypt_internal_special(krb5_context context, 301572448Sassar krb5_crypto crypto, 301672448Sassar int usage, 301772448Sassar void *data, 301872448Sassar size_t len, 301972448Sassar krb5_data *result, 302072448Sassar void *ivec) 302172448Sassar{ 302272448Sassar struct encryption_type *et = crypto->et; 302378536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 302472448Sassar size_t sz = len - cksum_sz - et->confoundersize; 302572448Sassar char *cdata = (char *)data; 302672448Sassar char *tmp; 302790929Snectar krb5_error_code ret; 302872448Sassar 302972448Sassar tmp = malloc (sz); 303078536Sassar if (tmp == NULL) { 303178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 303272448Sassar return ENOMEM; 303378536Sassar } 303472448Sassar 303590929Snectar ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec); 303690929Snectar if (ret) { 303790929Snectar free(tmp); 303890929Snectar return ret; 303990929Snectar } 304072448Sassar 304172448Sassar memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz); 304272448Sassar 304372448Sassar result->data = tmp; 304472448Sassar result->length = sz; 304572448Sassar return 0; 304672448Sassar} 304772448Sassar 304872448Sassar 304955682Smarkmkrb5_error_code 305072448Sassarkrb5_encrypt_ivec(krb5_context context, 305172448Sassar krb5_crypto crypto, 305272448Sassar unsigned usage, 305372448Sassar void *data, 305472448Sassar size_t len, 305572448Sassar krb5_data *result, 305672448Sassar void *ivec) 305772448Sassar{ 305872448Sassar if(derived_crypto(context, crypto)) 305972448Sassar return encrypt_internal_derived(context, crypto, usage, 306072448Sassar data, len, result, ivec); 306172448Sassar else if (special_crypto(context, crypto)) 306272448Sassar return encrypt_internal_special (context, crypto, usage, 306372448Sassar data, len, result, ivec); 306472448Sassar else 306572448Sassar return encrypt_internal(context, crypto, data, len, result, ivec); 306672448Sassar} 306772448Sassar 306872448Sassarkrb5_error_code 306955682Smarkmkrb5_encrypt(krb5_context context, 307055682Smarkm krb5_crypto crypto, 307155682Smarkm unsigned usage, 307255682Smarkm void *data, 307355682Smarkm size_t len, 307455682Smarkm krb5_data *result) 307555682Smarkm{ 307672448Sassar return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); 307755682Smarkm} 307855682Smarkm 307955682Smarkmkrb5_error_code 308055682Smarkmkrb5_encrypt_EncryptedData(krb5_context context, 308155682Smarkm krb5_crypto crypto, 308255682Smarkm unsigned usage, 308355682Smarkm void *data, 308455682Smarkm size_t len, 308555682Smarkm int kvno, 308655682Smarkm EncryptedData *result) 308755682Smarkm{ 308855682Smarkm result->etype = CRYPTO_ETYPE(crypto); 308955682Smarkm if(kvno){ 309055682Smarkm ALLOC(result->kvno, 1); 309155682Smarkm *result->kvno = kvno; 309255682Smarkm }else 309355682Smarkm result->kvno = NULL; 309455682Smarkm return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); 309555682Smarkm} 309655682Smarkm 309755682Smarkmkrb5_error_code 309872448Sassarkrb5_decrypt_ivec(krb5_context context, 309972448Sassar krb5_crypto crypto, 310072448Sassar unsigned usage, 310172448Sassar void *data, 310272448Sassar size_t len, 310372448Sassar krb5_data *result, 310472448Sassar void *ivec) 310572448Sassar{ 310672448Sassar if(derived_crypto(context, crypto)) 310772448Sassar return decrypt_internal_derived(context, crypto, usage, 310872448Sassar data, len, result, ivec); 310972448Sassar else if (special_crypto (context, crypto)) 311072448Sassar return decrypt_internal_special(context, crypto, usage, 311172448Sassar data, len, result, ivec); 311272448Sassar else 311372448Sassar return decrypt_internal(context, crypto, data, len, result, ivec); 311472448Sassar} 311572448Sassar 311672448Sassarkrb5_error_code 311755682Smarkmkrb5_decrypt(krb5_context context, 311855682Smarkm krb5_crypto crypto, 311955682Smarkm unsigned usage, 312055682Smarkm void *data, 312155682Smarkm size_t len, 312255682Smarkm krb5_data *result) 312355682Smarkm{ 312472448Sassar return krb5_decrypt_ivec (context, crypto, usage, data, len, result, 312572448Sassar NULL); 312655682Smarkm} 312755682Smarkm 312855682Smarkmkrb5_error_code 312955682Smarkmkrb5_decrypt_EncryptedData(krb5_context context, 313055682Smarkm krb5_crypto crypto, 313155682Smarkm unsigned usage, 313272448Sassar const EncryptedData *e, 313355682Smarkm krb5_data *result) 313455682Smarkm{ 313555682Smarkm return krb5_decrypt(context, crypto, usage, 313655682Smarkm e->cipher.data, e->cipher.length, result); 313755682Smarkm} 313855682Smarkm 313955682Smarkm/************************************************************ 314055682Smarkm * * 314155682Smarkm ************************************************************/ 314255682Smarkm 314390929Snectar#ifdef HAVE_OPENSSL 314478536Sassar#include <openssl/rand.h> 314578536Sassar 314678536Sassar/* From openssl/crypto/rand/rand_lcl.h */ 314778536Sassar#define ENTROPY_NEEDED 20 314878536Sassarstatic int 314978536Sassarseed_something(void) 315078536Sassar{ 315178536Sassar int fd = -1; 315278536Sassar char buf[1024], seedfile[256]; 315378536Sassar 315478536Sassar /* If there is a seed file, load it. But such a file cannot be trusted, 315578536Sassar so use 0 for the entropy estimate */ 315678536Sassar if (RAND_file_name(seedfile, sizeof(seedfile))) { 315778536Sassar fd = open(seedfile, O_RDONLY); 315878536Sassar if (fd >= 0) { 315978536Sassar read(fd, buf, sizeof(buf)); 316078536Sassar /* Use the full buffer anyway */ 316178536Sassar RAND_add(buf, sizeof(buf), 0.0); 316278536Sassar } else 316378536Sassar seedfile[0] = '\0'; 316478536Sassar } else 316578536Sassar seedfile[0] = '\0'; 316678536Sassar 316778536Sassar /* Calling RAND_status() will try to use /dev/urandom if it exists so 316878536Sassar we do not have to deal with it. */ 316978536Sassar if (RAND_status() != 1) { 317078536Sassar krb5_context context; 317190929Snectar const char *p; 317278536Sassar 317378536Sassar /* Try using egd */ 317478536Sassar if (!krb5_init_context(&context)) { 317578536Sassar p = krb5_config_get_string(context, NULL, "libdefaults", 317678536Sassar "egd_socket", NULL); 317778536Sassar if (p != NULL) 317878536Sassar RAND_egd_bytes(p, ENTROPY_NEEDED); 317978536Sassar krb5_free_context(context); 318078536Sassar } 318178536Sassar } 318278536Sassar 318378536Sassar if (RAND_status() == 1) { 318478536Sassar /* Update the seed file */ 318578536Sassar if (seedfile[0]) 318678536Sassar RAND_write_file(seedfile); 318778536Sassar 318878536Sassar return 0; 318978536Sassar } else 319078536Sassar return -1; 319178536Sassar} 319278536Sassar 319355682Smarkmvoid 319455682Smarkmkrb5_generate_random_block(void *buf, size_t len) 319555682Smarkm{ 319678536Sassar static int rng_initialized = 0; 319778536Sassar 319878536Sassar if (!rng_initialized) { 319978536Sassar if (seed_something()) 320078536Sassar krb5_abortx(NULL, "Fatal: could not seed the random number generator"); 320178536Sassar 320278536Sassar rng_initialized = 1; 320378536Sassar } 320478536Sassar RAND_bytes(buf, len); 320578536Sassar} 320678536Sassar 320778536Sassar#else 320878536Sassar 320978536Sassarvoid 321078536Sassarkrb5_generate_random_block(void *buf, size_t len) 321178536Sassar{ 321255682Smarkm des_cblock key, out; 321355682Smarkm static des_cblock counter; 321455682Smarkm static des_key_schedule schedule; 321555682Smarkm int i; 321655682Smarkm static int initialized = 0; 321755682Smarkm 321855682Smarkm if(!initialized) { 321955682Smarkm des_new_random_key(&key); 322055682Smarkm des_set_key(&key, schedule); 322155682Smarkm memset(&key, 0, sizeof(key)); 322255682Smarkm des_new_random_key(&counter); 322355682Smarkm } 322455682Smarkm while(len > 0) { 322555682Smarkm des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT); 322655682Smarkm for(i = 7; i >=0; i--) 322755682Smarkm if(counter[i]++) 322855682Smarkm break; 322955682Smarkm memcpy(buf, out, min(len, sizeof(out))); 323055682Smarkm len -= min(len, sizeof(out)); 323155682Smarkm buf = (char*)buf + sizeof(out); 323255682Smarkm } 323355682Smarkm} 323478536Sassar#endif 323555682Smarkm 323655682Smarkmstatic void 323755682SmarkmDES3_postproc(krb5_context context, 323855682Smarkm unsigned char *k, size_t len, struct key_data *key) 323955682Smarkm{ 324055682Smarkm unsigned char x[24]; 324155682Smarkm int i, j; 324255682Smarkm 324355682Smarkm memset(x, 0, sizeof(x)); 324455682Smarkm for (i = 0; i < 3; ++i) { 324555682Smarkm unsigned char foo; 324655682Smarkm 324755682Smarkm for (j = 0; j < 7; ++j) { 324855682Smarkm unsigned char b = k[7 * i + j]; 324955682Smarkm 325055682Smarkm x[8 * i + j] = b; 325155682Smarkm } 325255682Smarkm foo = 0; 325355682Smarkm for (j = 6; j >= 0; --j) { 325455682Smarkm foo |= k[7 * i + j] & 1; 325555682Smarkm foo <<= 1; 325655682Smarkm } 325755682Smarkm x[8 * i + 7] = foo; 325855682Smarkm } 325955682Smarkm k = key->key->keyvalue.data; 326055682Smarkm memcpy(k, x, 24); 326155682Smarkm memset(x, 0, sizeof(x)); 326255682Smarkm if (key->schedule) { 326355682Smarkm krb5_free_data(context, key->schedule); 326455682Smarkm key->schedule = NULL; 326555682Smarkm } 326655682Smarkm des_set_odd_parity((des_cblock*)k); 326755682Smarkm des_set_odd_parity((des_cblock*)(k + 8)); 326855682Smarkm des_set_odd_parity((des_cblock*)(k + 16)); 326955682Smarkm} 327055682Smarkm 327155682Smarkmstatic krb5_error_code 327255682Smarkmderive_key(krb5_context context, 327355682Smarkm struct encryption_type *et, 327455682Smarkm struct key_data *key, 327578536Sassar const void *constant, 327655682Smarkm size_t len) 327755682Smarkm{ 327855682Smarkm unsigned char *k; 327955682Smarkm unsigned int nblocks = 0, i; 328055682Smarkm krb5_error_code ret = 0; 328155682Smarkm 328255682Smarkm struct key_type *kt = et->keytype; 328355682Smarkm ret = _key_schedule(context, key); 328455682Smarkm if(ret) 328555682Smarkm return ret; 328672448Sassar if(et->blocksize * 8 < kt->bits || 328755682Smarkm len != et->blocksize) { 328855682Smarkm nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); 328955682Smarkm k = malloc(nblocks * et->blocksize); 329078536Sassar if(k == NULL) { 329178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 329255682Smarkm return ENOMEM; 329378536Sassar } 329455682Smarkm _krb5_n_fold(constant, len, k, et->blocksize); 329555682Smarkm for(i = 0; i < nblocks; i++) { 329655682Smarkm if(i > 0) 329755682Smarkm memcpy(k + i * et->blocksize, 329855682Smarkm k + (i - 1) * et->blocksize, 329955682Smarkm et->blocksize); 330078536Sassar (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, 330178536Sassar 1, 0, NULL); 330255682Smarkm } 330355682Smarkm } else { 330472448Sassar /* this case is probably broken, but won't be run anyway */ 330555682Smarkm void *c = malloc(len); 330655682Smarkm size_t res_len = (kt->bits + 7) / 8; 330755682Smarkm 330878536Sassar if(len != 0 && c == NULL) { 330978536Sassar krb5_set_error_string(context, "malloc: out of memory"); 331055682Smarkm return ENOMEM; 331178536Sassar } 331255682Smarkm memcpy(c, constant, len); 331378536Sassar (*et->encrypt)(context, key, c, len, 1, 0, NULL); 331455682Smarkm k = malloc(res_len); 331578536Sassar if(res_len != 0 && k == NULL) { 331678536Sassar free(c); 331778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 331855682Smarkm return ENOMEM; 331978536Sassar } 332055682Smarkm _krb5_n_fold(c, len, k, res_len); 332155682Smarkm free(c); 332255682Smarkm } 332355682Smarkm 332455682Smarkm /* XXX keytype dependent post-processing */ 332555682Smarkm switch(kt->type) { 332655682Smarkm case KEYTYPE_DES3: 332755682Smarkm DES3_postproc(context, k, nblocks * et->blocksize, key); 332855682Smarkm break; 3329120948Snectar#ifdef ENABLE_AES 3330120948Snectar case KEYTYPE_AES128: 3331120948Snectar case KEYTYPE_AES256: 3332120948Snectar memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); 3333120948Snectar break; 3334120948Snectar#endif /* ENABLE_AES */ 333555682Smarkm default: 333678536Sassar krb5_set_error_string(context, 333778536Sassar "derive_key() called with unknown keytype (%u)", 333878536Sassar kt->type); 333955682Smarkm ret = KRB5_CRYPTO_INTERNAL; 334055682Smarkm break; 334155682Smarkm } 334255682Smarkm memset(k, 0, nblocks * et->blocksize); 334355682Smarkm free(k); 334455682Smarkm return ret; 334555682Smarkm} 334655682Smarkm 334755682Smarkmstatic struct key_data * 334855682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage) 334955682Smarkm{ 335055682Smarkm struct key_usage *d = crypto->key_usage; 335155682Smarkm d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); 335255682Smarkm if(d == NULL) 335355682Smarkm return NULL; 335455682Smarkm crypto->key_usage = d; 335555682Smarkm d += crypto->num_key_usage++; 335655682Smarkm memset(d, 0, sizeof(*d)); 335755682Smarkm d->usage = usage; 335855682Smarkm return &d->key; 335955682Smarkm} 336055682Smarkm 336178536Sassarkrb5_error_code 336278536Sassarkrb5_derive_key(krb5_context context, 336378536Sassar const krb5_keyblock *key, 336478536Sassar krb5_enctype etype, 336578536Sassar const void *constant, 336678536Sassar size_t constant_len, 336778536Sassar krb5_keyblock **derived_key) 336878536Sassar{ 336978536Sassar krb5_error_code ret; 337078536Sassar struct encryption_type *et; 337178536Sassar struct key_data d; 337278536Sassar 337378536Sassar et = _find_enctype (etype); 337478536Sassar if (et == NULL) { 337578536Sassar krb5_set_error_string(context, "encryption type %d not supported", 337678536Sassar etype); 337778536Sassar return KRB5_PROG_ETYPE_NOSUPP; 337878536Sassar } 337978536Sassar 338078536Sassar ret = krb5_copy_keyblock(context, key, derived_key); 338178536Sassar if (ret) 338278536Sassar return ret; 338378536Sassar 338478536Sassar d.key = *derived_key; 338578536Sassar d.schedule = NULL; 338678536Sassar ret = derive_key(context, et, &d, constant, constant_len); 338778536Sassar if (ret) 338878536Sassar return ret; 338978536Sassar ret = krb5_copy_keyblock(context, d.key, derived_key); 339078536Sassar return ret; 339178536Sassar} 339278536Sassar 339355682Smarkmstatic krb5_error_code 339455682Smarkm_get_derived_key(krb5_context context, 339555682Smarkm krb5_crypto crypto, 339655682Smarkm unsigned usage, 339755682Smarkm struct key_data **key) 339855682Smarkm{ 339955682Smarkm int i; 340055682Smarkm struct key_data *d; 340155682Smarkm unsigned char constant[5]; 340255682Smarkm 340355682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 340455682Smarkm if(crypto->key_usage[i].usage == usage) { 340555682Smarkm *key = &crypto->key_usage[i].key; 340655682Smarkm return 0; 340755682Smarkm } 340855682Smarkm d = _new_derived_key(crypto, usage); 340978536Sassar if(d == NULL) { 341078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 341155682Smarkm return ENOMEM; 341278536Sassar } 341355682Smarkm krb5_copy_keyblock(context, crypto->key.key, &d->key); 341455682Smarkm _krb5_put_int(constant, usage, 5); 341555682Smarkm derive_key(context, crypto->et, d, constant, sizeof(constant)); 341655682Smarkm *key = d; 341755682Smarkm return 0; 341855682Smarkm} 341955682Smarkm 342055682Smarkm 342155682Smarkmkrb5_error_code 342255682Smarkmkrb5_crypto_init(krb5_context context, 342378536Sassar const krb5_keyblock *key, 342455682Smarkm krb5_enctype etype, 342555682Smarkm krb5_crypto *crypto) 342655682Smarkm{ 342755682Smarkm krb5_error_code ret; 342855682Smarkm ALLOC(*crypto, 1); 342978536Sassar if(*crypto == NULL) { 343078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 343155682Smarkm return ENOMEM; 343278536Sassar } 343355682Smarkm if(etype == ETYPE_NULL) 343455682Smarkm etype = key->keytype; 343555682Smarkm (*crypto)->et = _find_enctype(etype); 343655682Smarkm if((*crypto)->et == NULL) { 343755682Smarkm free(*crypto); 343878536Sassar krb5_set_error_string (context, "encryption type %d not supported", 343978536Sassar etype); 344055682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 344155682Smarkm } 3442102647Snectar if((*crypto)->et->keytype->size != key->keyvalue.length) { 3443102647Snectar free(*crypto); 3444102647Snectar krb5_set_error_string (context, "encryption key has bad length"); 3445102647Snectar return KRB5_BAD_KEYSIZE; 3446102647Snectar } 344755682Smarkm ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); 344855682Smarkm if(ret) { 344955682Smarkm free(*crypto); 345055682Smarkm return ret; 345155682Smarkm } 345255682Smarkm (*crypto)->key.schedule = NULL; 345355682Smarkm (*crypto)->num_key_usage = 0; 345455682Smarkm (*crypto)->key_usage = NULL; 345555682Smarkm return 0; 345655682Smarkm} 345755682Smarkm 345855682Smarkmstatic void 345955682Smarkmfree_key_data(krb5_context context, struct key_data *key) 346055682Smarkm{ 346155682Smarkm krb5_free_keyblock(context, key->key); 346255682Smarkm if(key->schedule) { 346355682Smarkm memset(key->schedule->data, 0, key->schedule->length); 346455682Smarkm krb5_free_data(context, key->schedule); 346555682Smarkm } 346655682Smarkm} 346755682Smarkm 346855682Smarkmstatic void 346955682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku) 347055682Smarkm{ 347155682Smarkm free_key_data(context, &ku->key); 347255682Smarkm} 347355682Smarkm 347455682Smarkmkrb5_error_code 347555682Smarkmkrb5_crypto_destroy(krb5_context context, 347655682Smarkm krb5_crypto crypto) 347755682Smarkm{ 347855682Smarkm int i; 347955682Smarkm 348055682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 348155682Smarkm free_key_usage(context, &crypto->key_usage[i]); 348255682Smarkm free(crypto->key_usage); 348355682Smarkm free_key_data(context, &crypto->key); 348455682Smarkm free (crypto); 348555682Smarkm return 0; 348655682Smarkm} 348755682Smarkm 348855682Smarkmkrb5_error_code 3489103426Snectarkrb5_crypto_getblocksize(krb5_context context, 3490103426Snectar krb5_crypto crypto, 3491103426Snectar size_t *blocksize) 3492103426Snectar{ 3493103426Snectar *blocksize = crypto->et->blocksize; 3494103426Snectar return 0; 3495103426Snectar} 3496103426Snectar 3497103426Snectarkrb5_error_code 349855682Smarkmkrb5_string_to_key_derived(krb5_context context, 349955682Smarkm const void *str, 350055682Smarkm size_t len, 350155682Smarkm krb5_enctype etype, 350255682Smarkm krb5_keyblock *key) 350355682Smarkm{ 350455682Smarkm struct encryption_type *et = _find_enctype(etype); 350555682Smarkm krb5_error_code ret; 350655682Smarkm struct key_data kd; 350790929Snectar size_t keylen = et->keytype->bits / 8; 350855682Smarkm u_char *tmp; 350955682Smarkm 351078536Sassar if(et == NULL) { 351178536Sassar krb5_set_error_string (context, "encryption type %d not supported", 351278536Sassar etype); 351355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 351478536Sassar } 351555682Smarkm ALLOC(kd.key, 1); 351690929Snectar if(kd.key == NULL) { 351790929Snectar krb5_set_error_string (context, "malloc: out of memory"); 351890929Snectar return ENOMEM; 351990929Snectar } 352090929Snectar ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); 352190929Snectar if(ret) { 352290929Snectar free(kd.key); 352390929Snectar return ret; 352490929Snectar } 352555682Smarkm kd.key->keytype = etype; 352690929Snectar tmp = malloc (keylen); 352790929Snectar if(tmp == NULL) { 352890929Snectar krb5_free_keyblock(context, kd.key); 352990929Snectar krb5_set_error_string (context, "malloc: out of memory"); 353090929Snectar return ENOMEM; 353190929Snectar } 353290929Snectar _krb5_n_fold(str, len, tmp, keylen); 353355682Smarkm kd.schedule = NULL; 353490929Snectar DES3_postproc (context, tmp, keylen, &kd); /* XXX */ 353590929Snectar memset(tmp, 0, keylen); 353690929Snectar free(tmp); 353790929Snectar ret = derive_key(context, 353855682Smarkm et, 353955682Smarkm &kd, 354055682Smarkm "kerberos", /* XXX well known constant */ 354155682Smarkm strlen("kerberos")); 354255682Smarkm ret = krb5_copy_keyblock_contents(context, kd.key, key); 354355682Smarkm free_key_data(context, &kd); 354455682Smarkm return ret; 354555682Smarkm} 354655682Smarkm 354772448Sassarstatic size_t 354872448Sassarwrapped_length (krb5_context context, 354972448Sassar krb5_crypto crypto, 355072448Sassar size_t data_len) 355172448Sassar{ 355272448Sassar struct encryption_type *et = crypto->et; 3553120948Snectar size_t padsize = et->padsize; 355472448Sassar size_t res; 355572448Sassar 355678536Sassar res = et->confoundersize + et->checksum->checksumsize + data_len; 3557120948Snectar res = (res + padsize - 1) / padsize * padsize; 355872448Sassar return res; 355972448Sassar} 356072448Sassar 356172448Sassarstatic size_t 356272448Sassarwrapped_length_dervied (krb5_context context, 356372448Sassar krb5_crypto crypto, 356472448Sassar size_t data_len) 356572448Sassar{ 356672448Sassar struct encryption_type *et = crypto->et; 3567120948Snectar size_t padsize = et->padsize; 356872448Sassar size_t res; 356972448Sassar 357072448Sassar res = et->confoundersize + data_len; 3571120948Snectar res = (res + padsize - 1) / padsize * padsize; 357278536Sassar res += et->checksum->checksumsize; 357372448Sassar return res; 357472448Sassar} 357572448Sassar 357655682Smarkm/* 357755682Smarkm * Return the size of an encrypted packet of length `data_len' 357855682Smarkm */ 357955682Smarkm 358055682Smarkmsize_t 358155682Smarkmkrb5_get_wrapped_length (krb5_context context, 358255682Smarkm krb5_crypto crypto, 358355682Smarkm size_t data_len) 358455682Smarkm{ 358572448Sassar if (derived_crypto (context, crypto)) 358672448Sassar return wrapped_length_dervied (context, crypto, data_len); 358772448Sassar else 358872448Sassar return wrapped_length (context, crypto, data_len); 358955682Smarkm} 359055682Smarkm 359155682Smarkm#ifdef CRYPTO_DEBUG 359255682Smarkm 359355682Smarkmstatic krb5_error_code 359455682Smarkmkrb5_get_keyid(krb5_context context, 359555682Smarkm krb5_keyblock *key, 359655682Smarkm u_int32_t *keyid) 359755682Smarkm{ 359857416Smarkm MD5_CTX md5; 359955682Smarkm unsigned char tmp[16]; 360057416Smarkm 360172448Sassar MD5_Init (&md5); 360272448Sassar MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); 360372448Sassar MD5_Final (tmp, &md5); 360455682Smarkm *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; 360555682Smarkm return 0; 360655682Smarkm} 360755682Smarkm 360855682Smarkmstatic void 360955682Smarkmkrb5_crypto_debug(krb5_context context, 361055682Smarkm int encrypt, 361155682Smarkm size_t len, 361255682Smarkm krb5_keyblock *key) 361355682Smarkm{ 361455682Smarkm u_int32_t keyid; 361555682Smarkm char *kt; 361655682Smarkm krb5_get_keyid(context, key, &keyid); 361755682Smarkm krb5_enctype_to_string(context, key->keytype, &kt); 361855682Smarkm krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", 361955682Smarkm encrypt ? "encrypting" : "decrypting", 362055682Smarkm (unsigned long)len, 362155682Smarkm keyid, 362255682Smarkm kt); 362355682Smarkm free(kt); 362455682Smarkm} 362555682Smarkm 362655682Smarkm#endif /* CRYPTO_DEBUG */ 362772448Sassar 362872448Sassar#if 0 362972448Sassarint 363072448Sassarmain() 363172448Sassar{ 363272448Sassar#if 0 363372448Sassar int i; 363472448Sassar krb5_context context; 363572448Sassar krb5_crypto crypto; 363672448Sassar struct key_data *d; 363772448Sassar krb5_keyblock key; 363872448Sassar char constant[4]; 363972448Sassar unsigned usage = ENCRYPTION_USAGE(3); 364072448Sassar krb5_error_code ret; 364172448Sassar 364272448Sassar ret = krb5_init_context(&context); 364372448Sassar if (ret) 364472448Sassar errx (1, "krb5_init_context failed: %d", ret); 364572448Sassar 364672448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 364772448Sassar key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" 364872448Sassar "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" 364972448Sassar "\xc8\xdf\xab\x26\x86\x64\x15\x25"; 365072448Sassar key.keyvalue.length = 24; 365172448Sassar 365272448Sassar krb5_crypto_init(context, &key, 0, &crypto); 365372448Sassar 365472448Sassar d = _new_derived_key(crypto, usage); 365572448Sassar if(d == NULL) 365672448Sassar return ENOMEM; 365772448Sassar krb5_copy_keyblock(context, crypto->key.key, &d->key); 365872448Sassar _krb5_put_int(constant, usage, 4); 365972448Sassar derive_key(context, crypto->et, d, constant, sizeof(constant)); 366072448Sassar return 0; 366172448Sassar#else 366272448Sassar int i; 366372448Sassar krb5_context context; 366472448Sassar krb5_crypto crypto; 366572448Sassar struct key_data *d; 366672448Sassar krb5_keyblock key; 366772448Sassar krb5_error_code ret; 366872448Sassar Checksum res; 366972448Sassar 367072448Sassar char *data = "what do ya want for nothing?"; 367172448Sassar 367272448Sassar ret = krb5_init_context(&context); 367372448Sassar if (ret) 367472448Sassar errx (1, "krb5_init_context failed: %d", ret); 367572448Sassar 367672448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 367772448Sassar key.keyvalue.data = "Jefe"; 367872448Sassar /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 367972448Sassar "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ 368072448Sassar key.keyvalue.length = 4; 368172448Sassar 368272448Sassar d = calloc(1, sizeof(*d)); 368372448Sassar 368472448Sassar d->key = &key; 368572448Sassar res.checksum.length = 20; 368672448Sassar res.checksum.data = malloc(res.checksum.length); 3687120948Snectar SP_HMAC_SHA1_checksum(context, d, data, 28, &res); 368872448Sassar 368972448Sassar return 0; 369072448Sassar#endif 369172448Sassar} 369272448Sassar#endif 3693