crypto.c revision 103426
155682Smarkm/* 290929Snectar * Copyright (c) 1997 - 2002 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" 35103426SnectarRCSID("$Id: crypto.c,v 1.66 2002/09/03 19:58:15 joda Exp $"); 3657428Smarkm/* RCSID("$FreeBSD: head/crypto/heimdal/lib/krb5/crypto.c 103426 2002-09-16 21:07:11Z 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, 7555682Smarkm krb5_salt, 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; 11455682Smarkm size_t confoundersize; 11555682Smarkm struct key_type *keytype; 11678536Sassar struct checksum_type *checksum; 11755682Smarkm struct checksum_type *keyed_checksum; 11855682Smarkm unsigned flags; 11978536Sassar krb5_error_code (*encrypt)(krb5_context context, 12078536Sassar struct key_data *key, 12172448Sassar void *data, size_t len, 12272448Sassar krb5_boolean encrypt, 12372448Sassar int usage, 12472448Sassar void *ivec); 12555682Smarkm}; 12655682Smarkm 12755682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) 12855682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) 12955682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) 13055682Smarkm 13155682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type); 13255682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type); 13355682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type); 13455682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 13555682Smarkm unsigned, struct key_data**); 13655682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); 13755682Smarkm 13855682Smarkm/************************************************************ 13955682Smarkm * * 14055682Smarkm ************************************************************/ 14155682Smarkm 14255682Smarkmstatic void 143102647Snectarkrb5_DES_random_key(krb5_context context, 14455682Smarkm krb5_keyblock *key) 14555682Smarkm{ 14655682Smarkm des_cblock *k = key->keyvalue.data; 14755682Smarkm do { 14855682Smarkm krb5_generate_random_block(k, sizeof(des_cblock)); 14955682Smarkm des_set_odd_parity(k); 15055682Smarkm } while(des_is_weak_key(k)); 15155682Smarkm} 15255682Smarkm 15355682Smarkmstatic void 154102647Snectarkrb5_DES_schedule(krb5_context context, 15555682Smarkm struct key_data *key) 15655682Smarkm{ 15755682Smarkm des_set_key(key->key->keyvalue.data, key->schedule->data); 15855682Smarkm} 15955682Smarkm 16090929Snectarstatic void 16190929SnectarDES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key) 16290929Snectar{ 16390929Snectar des_key_schedule schedule; 16490929Snectar int i; 16590929Snectar int reverse = 0; 16690929Snectar unsigned char *p; 16790929Snectar 16890929Snectar unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 16990929Snectar 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; 17090929Snectar memset(key, 0, 8); 17190929Snectar 17290929Snectar p = (unsigned char*)key; 17390929Snectar for (i = 0; i < length; i++) { 17490929Snectar unsigned char tmp = data[i]; 17590929Snectar if (!reverse) 17690929Snectar *p++ ^= (tmp << 1); 17790929Snectar else 17890929Snectar *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; 17990929Snectar if((i % 8) == 7) 18090929Snectar reverse = !reverse; 18190929Snectar } 18290929Snectar des_set_odd_parity(key); 18390929Snectar if(des_is_weak_key(key)) 18490929Snectar (*key)[7] ^= 0xF0; 18590929Snectar des_set_key(key, schedule); 18690929Snectar des_cbc_cksum((void*)data, key, length, schedule, key); 18790929Snectar memset(schedule, 0, sizeof(schedule)); 18890929Snectar des_set_odd_parity(key); 18990929Snectar} 19090929Snectar 19155682Smarkmstatic krb5_error_code 192102647Snectarkrb5_DES_string_to_key(krb5_context context, 19355682Smarkm krb5_enctype enctype, 19455682Smarkm krb5_data password, 19555682Smarkm krb5_salt salt, 19655682Smarkm krb5_keyblock *key) 19755682Smarkm{ 19890929Snectar unsigned char *s; 19955682Smarkm size_t len; 20055682Smarkm des_cblock tmp; 20155682Smarkm 20290929Snectar len = password.length + salt.saltvalue.length; 20355682Smarkm s = malloc(len); 20490929Snectar if(len > 0 && s == NULL) { 20578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 20655682Smarkm return ENOMEM; 20778536Sassar } 20855682Smarkm memcpy(s, password.data, password.length); 20955682Smarkm memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 21090929Snectar DES_string_to_key_int(s, len, &tmp); 21155682Smarkm key->keytype = enctype; 21255682Smarkm krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 21355682Smarkm memset(&tmp, 0, sizeof(tmp)); 21455682Smarkm memset(s, 0, len); 21555682Smarkm free(s); 21655682Smarkm return 0; 21755682Smarkm} 21855682Smarkm 21955682Smarkm/* This defines the Andrew string_to_key function. It accepts a password 22055682Smarkm * string as input and converts its via a one-way encryption algorithm to a DES 22155682Smarkm * encryption key. It is compatible with the original Andrew authentication 22255682Smarkm * service password database. 22355682Smarkm */ 22455682Smarkm 22555682Smarkm/* 22655682Smarkm * Short passwords, i.e 8 characters or less. 22755682Smarkm */ 22855682Smarkmstatic void 229102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw, 23055682Smarkm krb5_data cell, 23155682Smarkm des_cblock *key) 23255682Smarkm{ 23355682Smarkm char password[8+1]; /* crypt is limited to 8 chars anyway */ 23455682Smarkm int i; 23555682Smarkm 23655682Smarkm for(i = 0; i < 8; i++) { 23755682Smarkm char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ 23872448Sassar ((i < cell.length) ? 23972448Sassar tolower(((unsigned char*)cell.data)[i]) : 0); 24055682Smarkm password[i] = c ? c : 'X'; 24155682Smarkm } 24255682Smarkm password[8] = '\0'; 24355682Smarkm 24455682Smarkm memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock)); 24555682Smarkm 24655682Smarkm /* parity is inserted into the LSB so left shift each byte up one 24755682Smarkm bit. This allows ascii characters with a zero MSB to retain as 24855682Smarkm much significance as possible. */ 24955682Smarkm for (i = 0; i < sizeof(des_cblock); i++) 25055682Smarkm ((unsigned char*)key)[i] <<= 1; 25155682Smarkm des_set_odd_parity (key); 25255682Smarkm} 25355682Smarkm 25455682Smarkm/* 25555682Smarkm * Long passwords, i.e 9 characters or more. 25655682Smarkm */ 25755682Smarkmstatic void 258102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, 25955682Smarkm krb5_data cell, 26055682Smarkm des_cblock *key) 26155682Smarkm{ 26255682Smarkm des_key_schedule schedule; 26355682Smarkm des_cblock temp_key; 26455682Smarkm des_cblock ivec; 26555682Smarkm char password[512]; 26655682Smarkm size_t passlen; 26755682Smarkm 26855682Smarkm memcpy(password, pw.data, min(pw.length, sizeof(password))); 26972448Sassar if(pw.length < sizeof(password)) { 27072448Sassar int len = min(cell.length, sizeof(password) - pw.length); 27172448Sassar int i; 27272448Sassar 27372448Sassar memcpy(password + pw.length, cell.data, len); 27472448Sassar for (i = pw.length; i < pw.length + len; ++i) 27572448Sassar password[i] = tolower((unsigned char)password[i]); 27672448Sassar } 27755682Smarkm passlen = min(sizeof(password), pw.length + cell.length); 27855682Smarkm memcpy(&ivec, "kerberos", 8); 27955682Smarkm memcpy(&temp_key, "kerberos", 8); 28055682Smarkm des_set_odd_parity (&temp_key); 28155682Smarkm des_set_key (&temp_key, schedule); 28290929Snectar des_cbc_cksum (password, &ivec, passlen, schedule, &ivec); 28355682Smarkm 28455682Smarkm memcpy(&temp_key, &ivec, 8); 28555682Smarkm des_set_odd_parity (&temp_key); 28655682Smarkm des_set_key (&temp_key, schedule); 28790929Snectar des_cbc_cksum (password, key, passlen, schedule, &ivec); 28855682Smarkm memset(&schedule, 0, sizeof(schedule)); 28955682Smarkm memset(&temp_key, 0, sizeof(temp_key)); 29055682Smarkm memset(&ivec, 0, sizeof(ivec)); 29155682Smarkm memset(password, 0, sizeof(password)); 29255682Smarkm 29355682Smarkm des_set_odd_parity (key); 29455682Smarkm} 29555682Smarkm 29655682Smarkmstatic krb5_error_code 29755682SmarkmDES_AFS3_string_to_key(krb5_context context, 29855682Smarkm krb5_enctype enctype, 29955682Smarkm krb5_data password, 30055682Smarkm krb5_salt salt, 30155682Smarkm krb5_keyblock *key) 30255682Smarkm{ 30355682Smarkm des_cblock tmp; 30455682Smarkm if(password.length > 8) 305102647Snectar krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); 30655682Smarkm else 307102647Snectar krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); 30855682Smarkm key->keytype = enctype; 30955682Smarkm krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 31055682Smarkm memset(&key, 0, sizeof(key)); 31155682Smarkm return 0; 31255682Smarkm} 31355682Smarkm 31455682Smarkmstatic void 31555682SmarkmDES3_random_key(krb5_context context, 31655682Smarkm krb5_keyblock *key) 31755682Smarkm{ 31855682Smarkm des_cblock *k = key->keyvalue.data; 31955682Smarkm do { 32055682Smarkm krb5_generate_random_block(k, 3 * sizeof(des_cblock)); 32155682Smarkm des_set_odd_parity(&k[0]); 32255682Smarkm des_set_odd_parity(&k[1]); 32355682Smarkm des_set_odd_parity(&k[2]); 32455682Smarkm } while(des_is_weak_key(&k[0]) || 32555682Smarkm des_is_weak_key(&k[1]) || 32655682Smarkm des_is_weak_key(&k[2])); 32755682Smarkm} 32855682Smarkm 32955682Smarkmstatic void 33055682SmarkmDES3_schedule(krb5_context context, 33155682Smarkm struct key_data *key) 33255682Smarkm{ 33355682Smarkm des_cblock *k = key->key->keyvalue.data; 33455682Smarkm des_key_schedule *s = key->schedule->data; 33555682Smarkm des_set_key(&k[0], s[0]); 33655682Smarkm des_set_key(&k[1], s[1]); 33755682Smarkm des_set_key(&k[2], s[2]); 33855682Smarkm} 33955682Smarkm 34055682Smarkm/* 34155682Smarkm * A = A xor B. A & B are 8 bytes. 34255682Smarkm */ 34355682Smarkm 34455682Smarkmstatic void 34555682Smarkmxor (des_cblock *key, const unsigned char *b) 34655682Smarkm{ 34755682Smarkm unsigned char *a = (unsigned char*)key; 34855682Smarkm a[0] ^= b[0]; 34955682Smarkm a[1] ^= b[1]; 35055682Smarkm a[2] ^= b[2]; 35155682Smarkm a[3] ^= b[3]; 35255682Smarkm a[4] ^= b[4]; 35355682Smarkm a[5] ^= b[5]; 35455682Smarkm a[6] ^= b[6]; 35555682Smarkm a[7] ^= b[7]; 35655682Smarkm} 35755682Smarkm 35855682Smarkmstatic krb5_error_code 35955682SmarkmDES3_string_to_key(krb5_context context, 36055682Smarkm krb5_enctype enctype, 36155682Smarkm krb5_data password, 36255682Smarkm krb5_salt salt, 36355682Smarkm krb5_keyblock *key) 36455682Smarkm{ 36555682Smarkm char *str; 36655682Smarkm size_t len; 36755682Smarkm unsigned char tmp[24]; 36855682Smarkm des_cblock keys[3]; 36955682Smarkm 37055682Smarkm len = password.length + salt.saltvalue.length; 37155682Smarkm str = malloc(len); 37278536Sassar if(len != 0 && str == NULL) { 37378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 37455682Smarkm return ENOMEM; 37578536Sassar } 37655682Smarkm memcpy(str, password.data, password.length); 37755682Smarkm memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); 37855682Smarkm { 37955682Smarkm des_cblock ivec; 38055682Smarkm des_key_schedule s[3]; 38155682Smarkm int i; 38255682Smarkm 38355682Smarkm _krb5_n_fold(str, len, tmp, 24); 38455682Smarkm 38555682Smarkm for(i = 0; i < 3; i++){ 38655682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 38755682Smarkm des_set_odd_parity(keys + i); 38855682Smarkm if(des_is_weak_key(keys + i)) 389102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 39055682Smarkm des_set_key(keys + i, s[i]); 39155682Smarkm } 39255682Smarkm memset(&ivec, 0, sizeof(ivec)); 39390929Snectar des_ede3_cbc_encrypt(tmp, 39490929Snectar tmp, sizeof(tmp), 39555682Smarkm s[0], s[1], s[2], &ivec, DES_ENCRYPT); 39655682Smarkm memset(s, 0, sizeof(s)); 39755682Smarkm memset(&ivec, 0, sizeof(ivec)); 39855682Smarkm for(i = 0; i < 3; i++){ 39955682Smarkm memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); 40055682Smarkm des_set_odd_parity(keys + i); 40155682Smarkm if(des_is_weak_key(keys + i)) 402102647Snectar xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); 40355682Smarkm } 40455682Smarkm memset(tmp, 0, sizeof(tmp)); 40555682Smarkm } 40655682Smarkm key->keytype = enctype; 40755682Smarkm krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); 40855682Smarkm memset(keys, 0, sizeof(keys)); 40955682Smarkm memset(str, 0, len); 41055682Smarkm free(str); 41155682Smarkm return 0; 41255682Smarkm} 41355682Smarkm 41455682Smarkmstatic krb5_error_code 41555682SmarkmDES3_string_to_key_derived(krb5_context context, 41655682Smarkm krb5_enctype enctype, 41755682Smarkm krb5_data password, 41855682Smarkm krb5_salt salt, 41955682Smarkm krb5_keyblock *key) 42055682Smarkm{ 42155682Smarkm krb5_error_code ret; 42255682Smarkm size_t len = password.length + salt.saltvalue.length; 42355682Smarkm char *s; 42455682Smarkm 42555682Smarkm s = malloc(len); 42678536Sassar if(len != 0 && s == NULL) { 42778536Sassar krb5_set_error_string(context, "malloc: out of memory"); 42855682Smarkm return ENOMEM; 42978536Sassar } 43055682Smarkm memcpy(s, password.data, password.length); 43155682Smarkm memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 43255682Smarkm ret = krb5_string_to_key_derived(context, 43355682Smarkm s, 43455682Smarkm len, 43555682Smarkm enctype, 43655682Smarkm key); 43755682Smarkm memset(s, 0, len); 43855682Smarkm free(s); 43955682Smarkm return ret; 44055682Smarkm} 44155682Smarkm 44255682Smarkm/* 44355682Smarkm * ARCFOUR 44455682Smarkm */ 44555682Smarkm 44655682Smarkmstatic void 44755682SmarkmARCFOUR_random_key(krb5_context context, krb5_keyblock *key) 44855682Smarkm{ 44955682Smarkm krb5_generate_random_block (key->keyvalue.data, 45055682Smarkm key->keyvalue.length); 45155682Smarkm} 45255682Smarkm 45355682Smarkmstatic void 45455682SmarkmARCFOUR_schedule(krb5_context context, struct key_data *kd) 45555682Smarkm{ 45655682Smarkm RC4_set_key (kd->schedule->data, 45755682Smarkm kd->key->keyvalue.length, kd->key->keyvalue.data); 45855682Smarkm} 45955682Smarkm 46055682Smarkmstatic krb5_error_code 46155682SmarkmARCFOUR_string_to_key(krb5_context context, 46255682Smarkm krb5_enctype enctype, 46355682Smarkm krb5_data password, 46455682Smarkm krb5_salt salt, 46555682Smarkm krb5_keyblock *key) 46655682Smarkm{ 46755682Smarkm char *s, *p; 46855682Smarkm size_t len; 46955682Smarkm int i; 47057416Smarkm MD4_CTX m; 47155682Smarkm 47272448Sassar len = 2 * password.length; 47355682Smarkm s = malloc (len); 47478536Sassar if (len != 0 && s == NULL) { 47578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 47655682Smarkm return ENOMEM; 47778536Sassar } 47855682Smarkm for (p = s, i = 0; i < password.length; ++i) { 47955682Smarkm *p++ = ((char *)password.data)[i]; 48055682Smarkm *p++ = 0; 48155682Smarkm } 48272448Sassar MD4_Init (&m); 48372448Sassar MD4_Update (&m, s, len); 48455682Smarkm key->keytype = enctype; 48555682Smarkm krb5_data_alloc (&key->keyvalue, 16); 48672448Sassar MD4_Final (key->keyvalue.data, &m); 48755682Smarkm memset (s, 0, len); 48855682Smarkm free (s); 48955682Smarkm return 0; 49055682Smarkm} 49155682Smarkm 49255682Smarkmextern struct salt_type des_salt[], 49355682Smarkm des3_salt[], des3_salt_derived[], arcfour_salt[]; 49455682Smarkm 49555682Smarkmstruct key_type keytype_null = { 49655682Smarkm KEYTYPE_NULL, 49755682Smarkm "null", 49855682Smarkm 0, 49955682Smarkm 0, 50055682Smarkm 0, 50155682Smarkm NULL, 50255682Smarkm NULL, 50355682Smarkm NULL 50455682Smarkm}; 50555682Smarkm 50655682Smarkmstruct key_type keytype_des = { 50755682Smarkm KEYTYPE_DES, 50855682Smarkm "des", 50955682Smarkm 56, 51055682Smarkm sizeof(des_cblock), 51155682Smarkm sizeof(des_key_schedule), 512102647Snectar krb5_DES_random_key, 513102647Snectar krb5_DES_schedule, 51455682Smarkm des_salt 51555682Smarkm}; 51655682Smarkm 51755682Smarkmstruct key_type keytype_des3 = { 51855682Smarkm KEYTYPE_DES3, 51955682Smarkm "des3", 52055682Smarkm 168, 52155682Smarkm 3 * sizeof(des_cblock), 52255682Smarkm 3 * sizeof(des_key_schedule), 52355682Smarkm DES3_random_key, 52455682Smarkm DES3_schedule, 52555682Smarkm des3_salt 52655682Smarkm}; 52755682Smarkm 52855682Smarkmstruct key_type keytype_des3_derived = { 52955682Smarkm KEYTYPE_DES3, 53055682Smarkm "des3", 53155682Smarkm 168, 53255682Smarkm 3 * sizeof(des_cblock), 53355682Smarkm 3 * sizeof(des_key_schedule), 53455682Smarkm DES3_random_key, 53555682Smarkm DES3_schedule, 53655682Smarkm des3_salt_derived 53755682Smarkm}; 53855682Smarkm 53955682Smarkmstruct key_type keytype_arcfour = { 54055682Smarkm KEYTYPE_ARCFOUR, 54155682Smarkm "arcfour", 54255682Smarkm 128, 54355682Smarkm 16, 54455682Smarkm sizeof(RC4_KEY), 54555682Smarkm ARCFOUR_random_key, 54655682Smarkm ARCFOUR_schedule, 54755682Smarkm arcfour_salt 54855682Smarkm}; 54955682Smarkm 55055682Smarkmstruct key_type *keytypes[] = { 55155682Smarkm &keytype_null, 55255682Smarkm &keytype_des, 55355682Smarkm &keytype_des3_derived, 55455682Smarkm &keytype_des3, 55555682Smarkm &keytype_arcfour 55655682Smarkm}; 55755682Smarkm 55855682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]); 55955682Smarkm 56055682Smarkmstatic struct key_type * 56155682Smarkm_find_keytype(krb5_keytype type) 56255682Smarkm{ 56355682Smarkm int i; 56455682Smarkm for(i = 0; i < num_keytypes; i++) 56555682Smarkm if(keytypes[i]->type == type) 56655682Smarkm return keytypes[i]; 56755682Smarkm return NULL; 56855682Smarkm} 56955682Smarkm 57055682Smarkm 57155682Smarkmstruct salt_type des_salt[] = { 57255682Smarkm { 57355682Smarkm KRB5_PW_SALT, 57455682Smarkm "pw-salt", 575102647Snectar krb5_DES_string_to_key 57655682Smarkm }, 57755682Smarkm { 57855682Smarkm KRB5_AFS3_SALT, 57955682Smarkm "afs3-salt", 58055682Smarkm DES_AFS3_string_to_key 58155682Smarkm }, 58255682Smarkm { 0 } 58355682Smarkm}; 58455682Smarkm 58555682Smarkmstruct salt_type des3_salt[] = { 58655682Smarkm { 58755682Smarkm KRB5_PW_SALT, 58855682Smarkm "pw-salt", 58955682Smarkm DES3_string_to_key 59055682Smarkm }, 59155682Smarkm { 0 } 59255682Smarkm}; 59355682Smarkm 59455682Smarkmstruct salt_type des3_salt_derived[] = { 59555682Smarkm { 59655682Smarkm KRB5_PW_SALT, 59755682Smarkm "pw-salt", 59855682Smarkm DES3_string_to_key_derived 59955682Smarkm }, 60055682Smarkm { 0 } 60155682Smarkm}; 60255682Smarkm 60355682Smarkmstruct salt_type arcfour_salt[] = { 60455682Smarkm { 60555682Smarkm KRB5_PW_SALT, 60655682Smarkm "pw-salt", 60755682Smarkm ARCFOUR_string_to_key 60855682Smarkm }, 60955682Smarkm { 0 } 61055682Smarkm}; 61155682Smarkm 61255682Smarkmkrb5_error_code 61355682Smarkmkrb5_salttype_to_string (krb5_context context, 61455682Smarkm krb5_enctype etype, 61555682Smarkm krb5_salttype stype, 61655682Smarkm char **string) 61755682Smarkm{ 61855682Smarkm struct encryption_type *e; 61955682Smarkm struct salt_type *st; 62055682Smarkm 62155682Smarkm e = _find_enctype (etype); 62278536Sassar if (e == NULL) { 62378536Sassar krb5_set_error_string(context, "encryption type %d not supported", 62478536Sassar etype); 62555682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 62678536Sassar } 62755682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 62855682Smarkm if (st->type == stype) { 62955682Smarkm *string = strdup (st->name); 63078536Sassar if (*string == NULL) { 63178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 63255682Smarkm return ENOMEM; 63378536Sassar } 63455682Smarkm return 0; 63555682Smarkm } 63655682Smarkm } 63778536Sassar krb5_set_error_string(context, "salttype %d not supported", stype); 63855682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 63955682Smarkm} 64055682Smarkm 64155682Smarkmkrb5_error_code 64255682Smarkmkrb5_string_to_salttype (krb5_context context, 64355682Smarkm krb5_enctype etype, 64455682Smarkm const char *string, 64555682Smarkm krb5_salttype *salttype) 64655682Smarkm{ 64755682Smarkm struct encryption_type *e; 64855682Smarkm struct salt_type *st; 64955682Smarkm 65055682Smarkm e = _find_enctype (etype); 65178536Sassar if (e == NULL) { 65278536Sassar krb5_set_error_string(context, "encryption type %d not supported", 65378536Sassar etype); 65455682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 65578536Sassar } 65655682Smarkm for (st = e->keytype->string_to_key; st && st->type; st++) { 65755682Smarkm if (strcasecmp (st->name, string) == 0) { 65855682Smarkm *salttype = st->type; 65955682Smarkm return 0; 66055682Smarkm } 66155682Smarkm } 66278536Sassar krb5_set_error_string(context, "salttype %s not supported", string); 66355682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 66455682Smarkm} 66555682Smarkm 66655682Smarkmkrb5_error_code 66755682Smarkmkrb5_get_pw_salt(krb5_context context, 66855682Smarkm krb5_const_principal principal, 66955682Smarkm krb5_salt *salt) 67055682Smarkm{ 67155682Smarkm size_t len; 67255682Smarkm int i; 67355682Smarkm krb5_error_code ret; 67455682Smarkm char *p; 67555682Smarkm 67655682Smarkm salt->salttype = KRB5_PW_SALT; 67755682Smarkm len = strlen(principal->realm); 67855682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) 67955682Smarkm len += strlen(principal->name.name_string.val[i]); 68055682Smarkm ret = krb5_data_alloc (&salt->saltvalue, len); 68155682Smarkm if (ret) 68255682Smarkm return ret; 68355682Smarkm p = salt->saltvalue.data; 68455682Smarkm memcpy (p, principal->realm, strlen(principal->realm)); 68555682Smarkm p += strlen(principal->realm); 68655682Smarkm for (i = 0; i < principal->name.name_string.len; ++i) { 68755682Smarkm memcpy (p, 68855682Smarkm principal->name.name_string.val[i], 68955682Smarkm strlen(principal->name.name_string.val[i])); 69055682Smarkm p += strlen(principal->name.name_string.val[i]); 69155682Smarkm } 69255682Smarkm return 0; 69355682Smarkm} 69455682Smarkm 69555682Smarkmkrb5_error_code 69655682Smarkmkrb5_free_salt(krb5_context context, 69755682Smarkm krb5_salt salt) 69855682Smarkm{ 69955682Smarkm krb5_data_free(&salt.saltvalue); 70055682Smarkm return 0; 70155682Smarkm} 70255682Smarkm 70355682Smarkmkrb5_error_code 70455682Smarkmkrb5_string_to_key_data (krb5_context context, 70555682Smarkm krb5_enctype enctype, 70655682Smarkm krb5_data password, 70755682Smarkm krb5_principal principal, 70855682Smarkm krb5_keyblock *key) 70955682Smarkm{ 71055682Smarkm krb5_error_code ret; 71155682Smarkm krb5_salt salt; 71255682Smarkm 71355682Smarkm ret = krb5_get_pw_salt(context, principal, &salt); 71455682Smarkm if(ret) 71555682Smarkm return ret; 71655682Smarkm ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); 71755682Smarkm krb5_free_salt(context, salt); 71855682Smarkm return ret; 71955682Smarkm} 72055682Smarkm 72155682Smarkmkrb5_error_code 72255682Smarkmkrb5_string_to_key (krb5_context context, 72355682Smarkm krb5_enctype enctype, 72455682Smarkm const char *password, 72555682Smarkm krb5_principal principal, 72655682Smarkm krb5_keyblock *key) 72755682Smarkm{ 72855682Smarkm krb5_data pw; 72955682Smarkm pw.data = (void*)password; 73055682Smarkm pw.length = strlen(password); 73155682Smarkm return krb5_string_to_key_data(context, enctype, pw, principal, key); 73255682Smarkm} 73355682Smarkm 73472448Sassar/* 73572448Sassar * Do a string -> key for encryption type `enctype' operation on 73672448Sassar * `password' (with salt `salt'), returning the resulting key in `key' 73772448Sassar */ 73872448Sassar 73955682Smarkmkrb5_error_code 74055682Smarkmkrb5_string_to_key_data_salt (krb5_context context, 74155682Smarkm krb5_enctype enctype, 74255682Smarkm krb5_data password, 74355682Smarkm krb5_salt salt, 74455682Smarkm krb5_keyblock *key) 74555682Smarkm{ 74655682Smarkm struct encryption_type *et =_find_enctype(enctype); 74755682Smarkm struct salt_type *st; 74878536Sassar if(et == NULL) { 74978536Sassar krb5_set_error_string(context, "encryption type %d not supported", 75078536Sassar enctype); 75155682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 75278536Sassar } 75355682Smarkm for(st = et->keytype->string_to_key; st && st->type; st++) 75455682Smarkm if(st->type == salt.salttype) 75555682Smarkm return (*st->string_to_key)(context, enctype, password, salt, key); 75678536Sassar krb5_set_error_string(context, "salt type %d not supported", 75778536Sassar salt.salttype); 75855682Smarkm return HEIM_ERR_SALTTYPE_NOSUPP; 75955682Smarkm} 76055682Smarkm 76172448Sassar/* 76272448Sassar * Do a string -> key for encryption type `enctype' operation on the 76372448Sassar * string `password' (with salt `salt'), returning the resulting key 76472448Sassar * in `key' 76572448Sassar */ 76672448Sassar 76755682Smarkmkrb5_error_code 76855682Smarkmkrb5_string_to_key_salt (krb5_context context, 76955682Smarkm krb5_enctype enctype, 77055682Smarkm const char *password, 77155682Smarkm krb5_salt salt, 77255682Smarkm krb5_keyblock *key) 77355682Smarkm{ 77455682Smarkm krb5_data pw; 77555682Smarkm pw.data = (void*)password; 77655682Smarkm pw.length = strlen(password); 77755682Smarkm return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); 77855682Smarkm} 77955682Smarkm 78055682Smarkmkrb5_error_code 78155682Smarkmkrb5_keytype_to_string(krb5_context context, 78255682Smarkm krb5_keytype keytype, 78355682Smarkm char **string) 78455682Smarkm{ 78555682Smarkm struct key_type *kt = _find_keytype(keytype); 78678536Sassar if(kt == NULL) { 78778536Sassar krb5_set_error_string(context, "key type %d not supported", keytype); 78855682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 78978536Sassar } 79055682Smarkm *string = strdup(kt->name); 79178536Sassar if(*string == NULL) { 79278536Sassar krb5_set_error_string(context, "malloc: out of memory"); 79355682Smarkm return ENOMEM; 79478536Sassar } 79555682Smarkm return 0; 79655682Smarkm} 79755682Smarkm 79855682Smarkmkrb5_error_code 79955682Smarkmkrb5_string_to_keytype(krb5_context context, 80055682Smarkm const char *string, 80155682Smarkm krb5_keytype *keytype) 80255682Smarkm{ 80355682Smarkm int i; 80455682Smarkm for(i = 0; i < num_keytypes; i++) 80555682Smarkm if(strcasecmp(keytypes[i]->name, string) == 0){ 80655682Smarkm *keytype = keytypes[i]->type; 80755682Smarkm return 0; 80855682Smarkm } 80978536Sassar krb5_set_error_string(context, "key type %s not supported", string); 81055682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 81155682Smarkm} 81255682Smarkm 81355682Smarkmkrb5_error_code 81455682Smarkmkrb5_generate_random_keyblock(krb5_context context, 81555682Smarkm krb5_enctype type, 81655682Smarkm krb5_keyblock *key) 81755682Smarkm{ 81855682Smarkm krb5_error_code ret; 81955682Smarkm struct encryption_type *et = _find_enctype(type); 82078536Sassar if(et == NULL) { 82178536Sassar krb5_set_error_string(context, "encryption type %d not supported", 82278536Sassar type); 82355682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 82478536Sassar } 82555682Smarkm ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 82655682Smarkm if(ret) 82755682Smarkm return ret; 82855682Smarkm key->keytype = type; 82955682Smarkm if(et->keytype->random_key) 83055682Smarkm (*et->keytype->random_key)(context, key); 83155682Smarkm else 83255682Smarkm krb5_generate_random_block(key->keyvalue.data, 83355682Smarkm key->keyvalue.length); 83455682Smarkm return 0; 83555682Smarkm} 83655682Smarkm 83755682Smarkmstatic krb5_error_code 83855682Smarkm_key_schedule(krb5_context context, 83955682Smarkm struct key_data *key) 84055682Smarkm{ 84155682Smarkm krb5_error_code ret; 84255682Smarkm struct encryption_type *et = _find_enctype(key->key->keytype); 84355682Smarkm struct key_type *kt = et->keytype; 84455682Smarkm 84555682Smarkm if(kt->schedule == NULL) 84655682Smarkm return 0; 84772448Sassar if (key->schedule != NULL) 84872448Sassar return 0; 84955682Smarkm ALLOC(key->schedule, 1); 85078536Sassar if(key->schedule == NULL) { 85178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 85255682Smarkm return ENOMEM; 85378536Sassar } 85455682Smarkm ret = krb5_data_alloc(key->schedule, kt->schedule_size); 85555682Smarkm if(ret) { 85655682Smarkm free(key->schedule); 85755682Smarkm key->schedule = NULL; 85855682Smarkm return ret; 85955682Smarkm } 86055682Smarkm (*kt->schedule)(context, key); 86155682Smarkm return 0; 86255682Smarkm} 86355682Smarkm 86455682Smarkm/************************************************************ 86555682Smarkm * * 86655682Smarkm ************************************************************/ 86755682Smarkm 86855682Smarkmstatic void 86955682SmarkmNONE_checksum(krb5_context context, 87055682Smarkm struct key_data *key, 87172448Sassar const void *data, 87255682Smarkm size_t len, 87372448Sassar unsigned usage, 87455682Smarkm Checksum *C) 87555682Smarkm{ 87655682Smarkm} 87755682Smarkm 87855682Smarkmstatic void 87955682SmarkmCRC32_checksum(krb5_context context, 88055682Smarkm struct key_data *key, 88172448Sassar const void *data, 88255682Smarkm size_t len, 88372448Sassar unsigned usage, 88455682Smarkm Checksum *C) 88555682Smarkm{ 88655682Smarkm u_int32_t crc; 88755682Smarkm unsigned char *r = C->checksum.data; 88855682Smarkm _krb5_crc_init_table (); 88955682Smarkm crc = _krb5_crc_update (data, len, 0); 89055682Smarkm r[0] = crc & 0xff; 89155682Smarkm r[1] = (crc >> 8) & 0xff; 89255682Smarkm r[2] = (crc >> 16) & 0xff; 89355682Smarkm r[3] = (crc >> 24) & 0xff; 89455682Smarkm} 89555682Smarkm 89655682Smarkmstatic void 89755682SmarkmRSA_MD4_checksum(krb5_context context, 89855682Smarkm struct key_data *key, 89972448Sassar const void *data, 90055682Smarkm size_t len, 90172448Sassar unsigned usage, 90255682Smarkm Checksum *C) 90355682Smarkm{ 90457416Smarkm MD4_CTX m; 90557416Smarkm 90672448Sassar MD4_Init (&m); 90772448Sassar MD4_Update (&m, data, len); 90872448Sassar MD4_Final (C->checksum.data, &m); 90955682Smarkm} 91055682Smarkm 91155682Smarkmstatic void 91255682SmarkmRSA_MD4_DES_checksum(krb5_context context, 91355682Smarkm struct key_data *key, 91472448Sassar const void *data, 91555682Smarkm size_t len, 91672448Sassar unsigned usage, 91755682Smarkm Checksum *cksum) 91855682Smarkm{ 91957416Smarkm MD4_CTX md4; 92055682Smarkm des_cblock ivec; 92155682Smarkm unsigned char *p = cksum->checksum.data; 92255682Smarkm 92355682Smarkm krb5_generate_random_block(p, 8); 92472448Sassar MD4_Init (&md4); 92572448Sassar MD4_Update (&md4, p, 8); 92672448Sassar MD4_Update (&md4, data, len); 92772448Sassar MD4_Final (p + 8, &md4); 92855682Smarkm memset (&ivec, 0, sizeof(ivec)); 92990929Snectar des_cbc_encrypt(p, 93090929Snectar p, 93155682Smarkm 24, 93255682Smarkm key->schedule->data, 93355682Smarkm &ivec, 93455682Smarkm DES_ENCRYPT); 93555682Smarkm} 93655682Smarkm 93755682Smarkmstatic krb5_error_code 93855682SmarkmRSA_MD4_DES_verify(krb5_context context, 93955682Smarkm struct key_data *key, 94072448Sassar const void *data, 94155682Smarkm size_t len, 94272448Sassar unsigned usage, 94355682Smarkm Checksum *C) 94455682Smarkm{ 94557416Smarkm MD4_CTX md4; 94655682Smarkm unsigned char tmp[24]; 94755682Smarkm unsigned char res[16]; 94855682Smarkm des_cblock ivec; 94955682Smarkm krb5_error_code ret = 0; 95055682Smarkm 95155682Smarkm memset(&ivec, 0, sizeof(ivec)); 95257416Smarkm des_cbc_encrypt(C->checksum.data, 95355682Smarkm (void*)tmp, 95455682Smarkm C->checksum.length, 95555682Smarkm key->schedule->data, 95655682Smarkm &ivec, 95755682Smarkm DES_DECRYPT); 95872448Sassar MD4_Init (&md4); 95972448Sassar MD4_Update (&md4, tmp, 8); /* confounder */ 96072448Sassar MD4_Update (&md4, data, len); 96172448Sassar MD4_Final (res, &md4); 96278536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 96378536Sassar krb5_clear_error_string (context); 96455682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 96578536Sassar } 96655682Smarkm memset(tmp, 0, sizeof(tmp)); 96755682Smarkm memset(res, 0, sizeof(res)); 96855682Smarkm return ret; 96955682Smarkm} 97055682Smarkm 97155682Smarkmstatic void 97255682SmarkmRSA_MD5_checksum(krb5_context context, 97355682Smarkm struct key_data *key, 97472448Sassar const void *data, 97555682Smarkm size_t len, 97672448Sassar unsigned usage, 97755682Smarkm Checksum *C) 97855682Smarkm{ 97957416Smarkm MD5_CTX m; 98057416Smarkm 98172448Sassar MD5_Init (&m); 98272448Sassar MD5_Update(&m, data, len); 98372448Sassar MD5_Final (C->checksum.data, &m); 98455682Smarkm} 98555682Smarkm 98655682Smarkmstatic void 98755682SmarkmRSA_MD5_DES_checksum(krb5_context context, 98855682Smarkm struct key_data *key, 98972448Sassar const void *data, 99055682Smarkm size_t len, 99172448Sassar unsigned usage, 99255682Smarkm Checksum *C) 99355682Smarkm{ 99457416Smarkm MD5_CTX md5; 99555682Smarkm des_cblock ivec; 99655682Smarkm unsigned char *p = C->checksum.data; 99755682Smarkm 99855682Smarkm krb5_generate_random_block(p, 8); 99972448Sassar MD5_Init (&md5); 100072448Sassar MD5_Update (&md5, p, 8); 100172448Sassar MD5_Update (&md5, data, len); 100272448Sassar MD5_Final (p + 8, &md5); 100355682Smarkm memset (&ivec, 0, sizeof(ivec)); 100490929Snectar des_cbc_encrypt(p, 100590929Snectar p, 100655682Smarkm 24, 100755682Smarkm key->schedule->data, 100855682Smarkm &ivec, 100955682Smarkm DES_ENCRYPT); 101055682Smarkm} 101155682Smarkm 101255682Smarkmstatic krb5_error_code 101355682SmarkmRSA_MD5_DES_verify(krb5_context context, 101455682Smarkm struct key_data *key, 101572448Sassar const void *data, 101655682Smarkm size_t len, 101772448Sassar unsigned usage, 101855682Smarkm Checksum *C) 101955682Smarkm{ 102057416Smarkm MD5_CTX md5; 102155682Smarkm unsigned char tmp[24]; 102255682Smarkm unsigned char res[16]; 102355682Smarkm des_cblock ivec; 102455682Smarkm des_key_schedule *sched = key->schedule->data; 102555682Smarkm krb5_error_code ret = 0; 102655682Smarkm 102755682Smarkm memset(&ivec, 0, sizeof(ivec)); 102855682Smarkm des_cbc_encrypt(C->checksum.data, 102955682Smarkm (void*)tmp, 103055682Smarkm C->checksum.length, 103155682Smarkm sched[0], 103255682Smarkm &ivec, 103355682Smarkm DES_DECRYPT); 103472448Sassar MD5_Init (&md5); 103572448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 103672448Sassar MD5_Update (&md5, data, len); 103772448Sassar MD5_Final (res, &md5); 103878536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 103978536Sassar krb5_clear_error_string (context); 104055682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 104178536Sassar } 104255682Smarkm memset(tmp, 0, sizeof(tmp)); 104355682Smarkm memset(res, 0, sizeof(res)); 104455682Smarkm return ret; 104555682Smarkm} 104655682Smarkm 104755682Smarkmstatic void 104855682SmarkmRSA_MD5_DES3_checksum(krb5_context context, 104955682Smarkm struct key_data *key, 105072448Sassar const void *data, 105155682Smarkm size_t len, 105272448Sassar unsigned usage, 105355682Smarkm Checksum *C) 105455682Smarkm{ 105557416Smarkm MD5_CTX md5; 105655682Smarkm des_cblock ivec; 105755682Smarkm unsigned char *p = C->checksum.data; 105855682Smarkm des_key_schedule *sched = key->schedule->data; 105955682Smarkm 106055682Smarkm krb5_generate_random_block(p, 8); 106172448Sassar MD5_Init (&md5); 106272448Sassar MD5_Update (&md5, p, 8); 106372448Sassar MD5_Update (&md5, data, len); 106472448Sassar MD5_Final (p + 8, &md5); 106555682Smarkm memset (&ivec, 0, sizeof(ivec)); 106690929Snectar des_ede3_cbc_encrypt(p, 106790929Snectar p, 106855682Smarkm 24, 106955682Smarkm sched[0], sched[1], sched[2], 107055682Smarkm &ivec, 107155682Smarkm DES_ENCRYPT); 107255682Smarkm} 107355682Smarkm 107455682Smarkmstatic krb5_error_code 107555682SmarkmRSA_MD5_DES3_verify(krb5_context context, 107655682Smarkm struct key_data *key, 107772448Sassar const void *data, 107855682Smarkm size_t len, 107972448Sassar unsigned usage, 108055682Smarkm Checksum *C) 108155682Smarkm{ 108257416Smarkm MD5_CTX md5; 108355682Smarkm unsigned char tmp[24]; 108455682Smarkm unsigned char res[16]; 108555682Smarkm des_cblock ivec; 108655682Smarkm des_key_schedule *sched = key->schedule->data; 108755682Smarkm krb5_error_code ret = 0; 108855682Smarkm 108955682Smarkm memset(&ivec, 0, sizeof(ivec)); 109055682Smarkm des_ede3_cbc_encrypt(C->checksum.data, 109155682Smarkm (void*)tmp, 109255682Smarkm C->checksum.length, 109355682Smarkm sched[0], sched[1], sched[2], 109455682Smarkm &ivec, 109555682Smarkm DES_DECRYPT); 109672448Sassar MD5_Init (&md5); 109772448Sassar MD5_Update (&md5, tmp, 8); /* confounder */ 109872448Sassar MD5_Update (&md5, data, len); 109972448Sassar MD5_Final (res, &md5); 110078536Sassar if(memcmp(res, tmp + 8, sizeof(res)) != 0) { 110178536Sassar krb5_clear_error_string (context); 110255682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 110378536Sassar } 110455682Smarkm memset(tmp, 0, sizeof(tmp)); 110555682Smarkm memset(res, 0, sizeof(res)); 110655682Smarkm return ret; 110755682Smarkm} 110855682Smarkm 110955682Smarkmstatic void 111055682SmarkmSHA1_checksum(krb5_context context, 111155682Smarkm struct key_data *key, 111272448Sassar const void *data, 111355682Smarkm size_t len, 111472448Sassar unsigned usage, 111555682Smarkm Checksum *C) 111655682Smarkm{ 111772448Sassar SHA_CTX m; 111857416Smarkm 111972448Sassar SHA1_Init(&m); 112072448Sassar SHA1_Update(&m, data, len); 112172448Sassar SHA1_Final(C->checksum.data, &m); 112255682Smarkm} 112355682Smarkm 112455682Smarkm/* HMAC according to RFC2104 */ 112555682Smarkmstatic void 112655682Smarkmhmac(krb5_context context, 112755682Smarkm struct checksum_type *cm, 112872448Sassar const void *data, 112955682Smarkm size_t len, 113072448Sassar unsigned usage, 113155682Smarkm struct key_data *keyblock, 113255682Smarkm Checksum *result) 113355682Smarkm{ 113455682Smarkm unsigned char *ipad, *opad; 113555682Smarkm unsigned char *key; 113655682Smarkm size_t key_len; 113755682Smarkm int i; 113855682Smarkm 113955682Smarkm if(keyblock->key->keyvalue.length > cm->blocksize){ 114055682Smarkm (*cm->checksum)(context, 114155682Smarkm keyblock, 114255682Smarkm keyblock->key->keyvalue.data, 114355682Smarkm keyblock->key->keyvalue.length, 114472448Sassar usage, 114555682Smarkm result); 114655682Smarkm key = result->checksum.data; 114755682Smarkm key_len = result->checksum.length; 114855682Smarkm } else { 114955682Smarkm key = keyblock->key->keyvalue.data; 115055682Smarkm key_len = keyblock->key->keyvalue.length; 115155682Smarkm } 115255682Smarkm ipad = malloc(cm->blocksize + len); 115355682Smarkm opad = malloc(cm->blocksize + cm->checksumsize); 115455682Smarkm memset(ipad, 0x36, cm->blocksize); 115555682Smarkm memset(opad, 0x5c, cm->blocksize); 115655682Smarkm for(i = 0; i < key_len; i++){ 115755682Smarkm ipad[i] ^= key[i]; 115855682Smarkm opad[i] ^= key[i]; 115955682Smarkm } 116055682Smarkm memcpy(ipad + cm->blocksize, data, len); 116172448Sassar (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, 116272448Sassar usage, result); 116355682Smarkm memcpy(opad + cm->blocksize, result->checksum.data, 116455682Smarkm result->checksum.length); 116555682Smarkm (*cm->checksum)(context, keyblock, opad, 116672448Sassar cm->blocksize + cm->checksumsize, usage, result); 116755682Smarkm memset(ipad, 0, cm->blocksize + len); 116855682Smarkm free(ipad); 116955682Smarkm memset(opad, 0, cm->blocksize + cm->checksumsize); 117055682Smarkm free(opad); 117155682Smarkm} 117255682Smarkm 117355682Smarkmstatic void 117455682SmarkmHMAC_SHA1_DES3_checksum(krb5_context context, 117555682Smarkm struct key_data *key, 117672448Sassar const void *data, 117755682Smarkm size_t len, 117872448Sassar unsigned usage, 117955682Smarkm Checksum *result) 118055682Smarkm{ 118155682Smarkm struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); 118255682Smarkm 118372448Sassar hmac(context, c, data, len, usage, key, result); 118455682Smarkm} 118555682Smarkm 118672448Sassar/* 118772448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt 118872448Sassar */ 118972448Sassar 119072448Sassarstatic void 119172448SassarHMAC_MD5_checksum(krb5_context context, 119272448Sassar struct key_data *key, 119372448Sassar const void *data, 119472448Sassar size_t len, 119572448Sassar unsigned usage, 119672448Sassar Checksum *result) 119772448Sassar{ 119872448Sassar MD5_CTX md5; 119972448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 120072448Sassar const char signature[] = "signaturekey"; 120172448Sassar Checksum ksign_c; 120272448Sassar struct key_data ksign; 120372448Sassar krb5_keyblock kb; 120472448Sassar unsigned char t[4]; 120572448Sassar unsigned char tmp[16]; 120672448Sassar unsigned char ksign_c_data[16]; 120772448Sassar 120872448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 120972448Sassar ksign_c.checksum.data = ksign_c_data; 121072448Sassar hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); 121172448Sassar ksign.key = &kb; 121272448Sassar kb.keyvalue = ksign_c.checksum; 121372448Sassar MD5_Init (&md5); 121472448Sassar t[0] = (usage >> 0) & 0xFF; 121572448Sassar t[1] = (usage >> 8) & 0xFF; 121672448Sassar t[2] = (usage >> 16) & 0xFF; 121772448Sassar t[3] = (usage >> 24) & 0xFF; 121872448Sassar MD5_Update (&md5, t, 4); 121972448Sassar MD5_Update (&md5, data, len); 122072448Sassar MD5_Final (tmp, &md5); 122172448Sassar hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); 122272448Sassar} 122372448Sassar 122472448Sassar/* 122572448Sassar * same as previous but being used while encrypting. 122672448Sassar */ 122772448Sassar 122872448Sassarstatic void 122972448SassarHMAC_MD5_checksum_enc(krb5_context context, 123072448Sassar struct key_data *key, 123172448Sassar const void *data, 123272448Sassar size_t len, 123372448Sassar unsigned usage, 123472448Sassar Checksum *result) 123572448Sassar{ 123672448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 123772448Sassar Checksum ksign_c; 123872448Sassar struct key_data ksign; 123972448Sassar krb5_keyblock kb; 124072448Sassar unsigned char t[4]; 124172448Sassar unsigned char ksign_c_data[16]; 124272448Sassar 124372448Sassar t[0] = (usage >> 0) & 0xFF; 124472448Sassar t[1] = (usage >> 8) & 0xFF; 124572448Sassar t[2] = (usage >> 16) & 0xFF; 124672448Sassar t[3] = (usage >> 24) & 0xFF; 124772448Sassar 124872448Sassar ksign_c.checksum.length = sizeof(ksign_c_data); 124972448Sassar ksign_c.checksum.data = ksign_c_data; 125072448Sassar hmac(context, c, t, sizeof(t), 0, key, &ksign_c); 125172448Sassar ksign.key = &kb; 125272448Sassar kb.keyvalue = ksign_c.checksum; 125372448Sassar hmac(context, c, data, len, 0, &ksign, result); 125472448Sassar} 125572448Sassar 125655682Smarkmstruct checksum_type checksum_none = { 125755682Smarkm CKSUMTYPE_NONE, 125855682Smarkm "none", 125955682Smarkm 1, 126055682Smarkm 0, 126155682Smarkm 0, 126255682Smarkm NONE_checksum, 126355682Smarkm NULL 126455682Smarkm}; 126555682Smarkmstruct checksum_type checksum_crc32 = { 126655682Smarkm CKSUMTYPE_CRC32, 126755682Smarkm "crc32", 126855682Smarkm 1, 126955682Smarkm 4, 127055682Smarkm 0, 127155682Smarkm CRC32_checksum, 127255682Smarkm NULL 127355682Smarkm}; 127455682Smarkmstruct checksum_type checksum_rsa_md4 = { 127555682Smarkm CKSUMTYPE_RSA_MD4, 127655682Smarkm "rsa-md4", 127755682Smarkm 64, 127855682Smarkm 16, 127955682Smarkm F_CPROOF, 128055682Smarkm RSA_MD4_checksum, 128155682Smarkm NULL 128255682Smarkm}; 128355682Smarkmstruct checksum_type checksum_rsa_md4_des = { 128455682Smarkm CKSUMTYPE_RSA_MD4_DES, 128555682Smarkm "rsa-md4-des", 128655682Smarkm 64, 128755682Smarkm 24, 128855682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 128955682Smarkm RSA_MD4_DES_checksum, 129055682Smarkm RSA_MD4_DES_verify 129155682Smarkm}; 129255682Smarkm#if 0 129355682Smarkmstruct checksum_type checksum_des_mac = { 129455682Smarkm CKSUMTYPE_DES_MAC, 129555682Smarkm "des-mac", 129655682Smarkm 0, 129755682Smarkm 0, 129855682Smarkm 0, 129972448Sassar DES_MAC_checksum 130055682Smarkm}; 130155682Smarkmstruct checksum_type checksum_des_mac_k = { 130255682Smarkm CKSUMTYPE_DES_MAC_K, 130355682Smarkm "des-mac-k", 130455682Smarkm 0, 130555682Smarkm 0, 130655682Smarkm 0, 130772448Sassar DES_MAC_K_checksum 130855682Smarkm}; 130955682Smarkmstruct checksum_type checksum_rsa_md4_des_k = { 131055682Smarkm CKSUMTYPE_RSA_MD4_DES_K, 131155682Smarkm "rsa-md4-des-k", 131255682Smarkm 0, 131355682Smarkm 0, 131455682Smarkm 0, 131572448Sassar RSA_MD4_DES_K_checksum, 131672448Sassar RSA_MD4_DES_K_verify 131755682Smarkm}; 131855682Smarkm#endif 131955682Smarkmstruct checksum_type checksum_rsa_md5 = { 132055682Smarkm CKSUMTYPE_RSA_MD5, 132155682Smarkm "rsa-md5", 132255682Smarkm 64, 132355682Smarkm 16, 132455682Smarkm F_CPROOF, 132555682Smarkm RSA_MD5_checksum, 132655682Smarkm NULL 132755682Smarkm}; 132855682Smarkmstruct checksum_type checksum_rsa_md5_des = { 132955682Smarkm CKSUMTYPE_RSA_MD5_DES, 133055682Smarkm "rsa-md5-des", 133155682Smarkm 64, 133255682Smarkm 24, 133355682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 133455682Smarkm RSA_MD5_DES_checksum, 133572448Sassar RSA_MD5_DES_verify 133655682Smarkm}; 133755682Smarkmstruct checksum_type checksum_rsa_md5_des3 = { 133855682Smarkm CKSUMTYPE_RSA_MD5_DES3, 133955682Smarkm "rsa-md5-des3", 134055682Smarkm 64, 134155682Smarkm 24, 134255682Smarkm F_KEYED | F_CPROOF | F_VARIANT, 134355682Smarkm RSA_MD5_DES3_checksum, 134472448Sassar RSA_MD5_DES3_verify 134555682Smarkm}; 134655682Smarkmstruct checksum_type checksum_sha1 = { 134755682Smarkm CKSUMTYPE_SHA1, 134855682Smarkm "sha1", 134955682Smarkm 64, 135055682Smarkm 20, 135155682Smarkm F_CPROOF, 135255682Smarkm SHA1_checksum, 135355682Smarkm NULL 135455682Smarkm}; 135555682Smarkmstruct checksum_type checksum_hmac_sha1_des3 = { 135655682Smarkm CKSUMTYPE_HMAC_SHA1_DES3, 135755682Smarkm "hmac-sha1-des3", 135855682Smarkm 64, 135955682Smarkm 20, 136055682Smarkm F_KEYED | F_CPROOF | F_DERIVED, 136155682Smarkm HMAC_SHA1_DES3_checksum, 136255682Smarkm NULL 136355682Smarkm}; 136455682Smarkm 136572448Sassarstruct checksum_type checksum_hmac_md5 = { 136672448Sassar CKSUMTYPE_HMAC_MD5, 136772448Sassar "hmac-md5", 136872448Sassar 64, 136972448Sassar 16, 137072448Sassar F_KEYED | F_CPROOF, 137172448Sassar HMAC_MD5_checksum, 137272448Sassar NULL 137372448Sassar}; 137472448Sassar 137572448Sassarstruct checksum_type checksum_hmac_md5_enc = { 137672448Sassar CKSUMTYPE_HMAC_MD5_ENC, 137772448Sassar "hmac-md5-enc", 137872448Sassar 64, 137972448Sassar 16, 138072448Sassar F_KEYED | F_CPROOF | F_PSEUDO, 138172448Sassar HMAC_MD5_checksum_enc, 138272448Sassar NULL 138372448Sassar}; 138472448Sassar 138555682Smarkmstruct checksum_type *checksum_types[] = { 138655682Smarkm &checksum_none, 138755682Smarkm &checksum_crc32, 138855682Smarkm &checksum_rsa_md4, 138955682Smarkm &checksum_rsa_md4_des, 139055682Smarkm#if 0 139155682Smarkm &checksum_des_mac, 139255682Smarkm &checksum_des_mac_k, 139355682Smarkm &checksum_rsa_md4_des_k, 139455682Smarkm#endif 139555682Smarkm &checksum_rsa_md5, 139655682Smarkm &checksum_rsa_md5_des, 139755682Smarkm &checksum_rsa_md5_des3, 139855682Smarkm &checksum_sha1, 139972448Sassar &checksum_hmac_sha1_des3, 140072448Sassar &checksum_hmac_md5, 140172448Sassar &checksum_hmac_md5_enc 140255682Smarkm}; 140355682Smarkm 140455682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); 140555682Smarkm 140655682Smarkmstatic struct checksum_type * 140755682Smarkm_find_checksum(krb5_cksumtype type) 140855682Smarkm{ 140955682Smarkm int i; 141055682Smarkm for(i = 0; i < num_checksums; i++) 141155682Smarkm if(checksum_types[i]->type == type) 141255682Smarkm return checksum_types[i]; 141355682Smarkm return NULL; 141455682Smarkm} 141555682Smarkm 141655682Smarkmstatic krb5_error_code 141755682Smarkmget_checksum_key(krb5_context context, 141855682Smarkm krb5_crypto crypto, 141955682Smarkm unsigned usage, /* not krb5_key_usage */ 142055682Smarkm struct checksum_type *ct, 142155682Smarkm struct key_data **key) 142255682Smarkm{ 142355682Smarkm krb5_error_code ret = 0; 142455682Smarkm 142555682Smarkm if(ct->flags & F_DERIVED) 142655682Smarkm ret = _get_derived_key(context, crypto, usage, key); 142755682Smarkm else if(ct->flags & F_VARIANT) { 142855682Smarkm int i; 142955682Smarkm 143055682Smarkm *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); 143178536Sassar if(*key == NULL) { 143278536Sassar krb5_set_error_string(context, "malloc: out of memory"); 143355682Smarkm return ENOMEM; 143478536Sassar } 143555682Smarkm ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); 143655682Smarkm if(ret) 143755682Smarkm return ret; 143855682Smarkm for(i = 0; i < (*key)->key->keyvalue.length; i++) 143955682Smarkm ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; 144055682Smarkm } else { 144155682Smarkm *key = &crypto->key; 144255682Smarkm } 144355682Smarkm if(ret == 0) 144455682Smarkm ret = _key_schedule(context, *key); 144555682Smarkm return ret; 144655682Smarkm} 144755682Smarkm 144855682Smarkmstatic krb5_error_code 144955682Smarkmdo_checksum (krb5_context context, 145055682Smarkm struct checksum_type *ct, 145155682Smarkm krb5_crypto crypto, 145255682Smarkm unsigned usage, 145355682Smarkm void *data, 145455682Smarkm size_t len, 145555682Smarkm Checksum *result) 145655682Smarkm{ 145755682Smarkm krb5_error_code ret; 145855682Smarkm struct key_data *dkey; 145955682Smarkm int keyed_checksum; 146055682Smarkm 146155682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 146278536Sassar if(keyed_checksum && crypto == NULL) { 146378536Sassar krb5_clear_error_string (context); 146455682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 146578536Sassar } 146672448Sassar if(keyed_checksum) { 146755682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 146872448Sassar if (ret) 146972448Sassar return ret; 147072448Sassar } else 147155682Smarkm dkey = NULL; 147255682Smarkm result->cksumtype = ct->type; 147355682Smarkm krb5_data_alloc(&result->checksum, ct->checksumsize); 147472448Sassar (*ct->checksum)(context, dkey, data, len, usage, result); 147555682Smarkm return 0; 147655682Smarkm} 147755682Smarkm 147855682Smarkmstatic krb5_error_code 147955682Smarkmcreate_checksum(krb5_context context, 148055682Smarkm krb5_crypto crypto, 148190929Snectar unsigned usage, /* not krb5_key_usage */ 148278536Sassar krb5_cksumtype type, /* 0 -> pick from crypto */ 148355682Smarkm void *data, 148455682Smarkm size_t len, 148555682Smarkm Checksum *result) 148655682Smarkm{ 148778536Sassar struct checksum_type *ct = NULL; 148855682Smarkm 148978536Sassar if (type) { 149078536Sassar ct = _find_checksum(type); 149178536Sassar } else if (crypto) { 149255682Smarkm ct = crypto->et->keyed_checksum; 149378536Sassar if (ct == NULL) 149478536Sassar ct = crypto->et->checksum; 149578536Sassar } 149678536Sassar 149778536Sassar if(ct == NULL) { 149878536Sassar krb5_set_error_string (context, "checksum type %d not supported", 149978536Sassar type); 150055682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 150178536Sassar } 150255682Smarkm return do_checksum (context, ct, crypto, usage, data, len, result); 150355682Smarkm} 150455682Smarkm 150555682Smarkmkrb5_error_code 150655682Smarkmkrb5_create_checksum(krb5_context context, 150755682Smarkm krb5_crypto crypto, 150878536Sassar krb5_key_usage usage, 150978536Sassar int type, 151055682Smarkm void *data, 151155682Smarkm size_t len, 151255682Smarkm Checksum *result) 151355682Smarkm{ 151455682Smarkm return create_checksum(context, crypto, 151578536Sassar CHECKSUM_USAGE(usage), 151678536Sassar type, data, len, result); 151755682Smarkm} 151855682Smarkm 151955682Smarkmstatic krb5_error_code 152055682Smarkmverify_checksum(krb5_context context, 152155682Smarkm krb5_crypto crypto, 152255682Smarkm unsigned usage, /* not krb5_key_usage */ 152355682Smarkm void *data, 152455682Smarkm size_t len, 152555682Smarkm Checksum *cksum) 152655682Smarkm{ 152755682Smarkm krb5_error_code ret; 152855682Smarkm struct key_data *dkey; 152955682Smarkm int keyed_checksum; 153055682Smarkm Checksum c; 153155682Smarkm struct checksum_type *ct; 153255682Smarkm 153355682Smarkm ct = _find_checksum(cksum->cksumtype); 153478536Sassar if(ct == NULL) { 153578536Sassar krb5_set_error_string (context, "checksum type %d not supported", 153678536Sassar cksum->cksumtype); 153755682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 153878536Sassar } 153978536Sassar if(ct->checksumsize != cksum->checksum.length) { 154078536Sassar krb5_clear_error_string (context); 154155682Smarkm return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ 154278536Sassar } 154355682Smarkm keyed_checksum = (ct->flags & F_KEYED) != 0; 154478536Sassar if(keyed_checksum && crypto == NULL) { 154578536Sassar krb5_clear_error_string (context); 154655682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 154778536Sassar } 154855682Smarkm if(keyed_checksum) 154955682Smarkm ret = get_checksum_key(context, crypto, usage, ct, &dkey); 155055682Smarkm else 155155682Smarkm dkey = NULL; 155255682Smarkm if(ct->verify) 155372448Sassar return (*ct->verify)(context, dkey, data, len, usage, cksum); 155455682Smarkm 155555682Smarkm ret = krb5_data_alloc (&c.checksum, ct->checksumsize); 155655682Smarkm if (ret) 155755682Smarkm return ret; 155855682Smarkm 155972448Sassar (*ct->checksum)(context, dkey, data, len, usage, &c); 156055682Smarkm 156155682Smarkm if(c.checksum.length != cksum->checksum.length || 156278536Sassar memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { 156378536Sassar krb5_clear_error_string (context); 156455682Smarkm ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 156578536Sassar } else { 156655682Smarkm ret = 0; 156778536Sassar } 156855682Smarkm krb5_data_free (&c.checksum); 156955682Smarkm return ret; 157055682Smarkm} 157155682Smarkm 157255682Smarkmkrb5_error_code 157355682Smarkmkrb5_verify_checksum(krb5_context context, 157455682Smarkm krb5_crypto crypto, 157555682Smarkm krb5_key_usage usage, 157655682Smarkm void *data, 157755682Smarkm size_t len, 157855682Smarkm Checksum *cksum) 157955682Smarkm{ 158055682Smarkm return verify_checksum(context, crypto, 158155682Smarkm CHECKSUM_USAGE(usage), data, len, cksum); 158255682Smarkm} 158355682Smarkm 158455682Smarkmkrb5_error_code 158555682Smarkmkrb5_checksumsize(krb5_context context, 158655682Smarkm krb5_cksumtype type, 158755682Smarkm size_t *size) 158855682Smarkm{ 158955682Smarkm struct checksum_type *ct = _find_checksum(type); 159078536Sassar if(ct == NULL) { 159178536Sassar krb5_set_error_string (context, "checksum type %d not supported", 159278536Sassar type); 159355682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 159478536Sassar } 159555682Smarkm *size = ct->checksumsize; 159655682Smarkm return 0; 159755682Smarkm} 159855682Smarkm 159955682Smarkmkrb5_boolean 160055682Smarkmkrb5_checksum_is_keyed(krb5_context context, 160155682Smarkm krb5_cksumtype type) 160255682Smarkm{ 160355682Smarkm struct checksum_type *ct = _find_checksum(type); 160478536Sassar if(ct == NULL) { 160578536Sassar krb5_set_error_string (context, "checksum type %d not supported", 160678536Sassar type); 160755682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 160878536Sassar } 160955682Smarkm return ct->flags & F_KEYED; 161055682Smarkm} 161155682Smarkm 161255682Smarkmkrb5_boolean 161355682Smarkmkrb5_checksum_is_collision_proof(krb5_context context, 161455682Smarkm krb5_cksumtype type) 161555682Smarkm{ 161655682Smarkm struct checksum_type *ct = _find_checksum(type); 161778536Sassar if(ct == NULL) { 161878536Sassar krb5_set_error_string (context, "checksum type %d not supported", 161978536Sassar type); 162055682Smarkm return KRB5_PROG_SUMTYPE_NOSUPP; 162178536Sassar } 162255682Smarkm return ct->flags & F_CPROOF; 162355682Smarkm} 162455682Smarkm 162555682Smarkm/************************************************************ 162655682Smarkm * * 162755682Smarkm ************************************************************/ 162855682Smarkm 162972448Sassarstatic krb5_error_code 163078536SassarNULL_encrypt(krb5_context context, 163178536Sassar struct key_data *key, 163255682Smarkm void *data, 163355682Smarkm size_t len, 163472448Sassar krb5_boolean encrypt, 163572448Sassar int usage, 163672448Sassar void *ivec) 163755682Smarkm{ 163872448Sassar return 0; 163955682Smarkm} 164055682Smarkm 164172448Sassarstatic krb5_error_code 164278536SassarDES_CBC_encrypt_null_ivec(krb5_context context, 164378536Sassar struct key_data *key, 164455682Smarkm void *data, 164555682Smarkm size_t len, 164672448Sassar krb5_boolean encrypt, 164772448Sassar int usage, 164872448Sassar void *ignore_ivec) 164955682Smarkm{ 165055682Smarkm des_cblock ivec; 165155682Smarkm des_key_schedule *s = key->schedule->data; 165255682Smarkm memset(&ivec, 0, sizeof(ivec)); 165355682Smarkm des_cbc_encrypt(data, data, len, *s, &ivec, encrypt); 165472448Sassar return 0; 165555682Smarkm} 165655682Smarkm 165772448Sassarstatic krb5_error_code 165878536SassarDES_CBC_encrypt_key_ivec(krb5_context context, 165978536Sassar struct key_data *key, 166055682Smarkm void *data, 166155682Smarkm size_t len, 166272448Sassar krb5_boolean encrypt, 166372448Sassar int usage, 166472448Sassar void *ignore_ivec) 166555682Smarkm{ 166655682Smarkm des_cblock ivec; 166755682Smarkm des_key_schedule *s = key->schedule->data; 166855682Smarkm memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 166955682Smarkm des_cbc_encrypt(data, data, len, *s, &ivec, encrypt); 167072448Sassar return 0; 167155682Smarkm} 167255682Smarkm 167372448Sassarstatic krb5_error_code 167478536SassarDES3_CBC_encrypt(krb5_context context, 167578536Sassar struct key_data *key, 167655682Smarkm void *data, 167755682Smarkm size_t len, 167872448Sassar krb5_boolean encrypt, 167972448Sassar int usage, 1680103426Snectar void *ivec) 168155682Smarkm{ 1682103426Snectar des_cblock local_ivec; 168355682Smarkm des_key_schedule *s = key->schedule->data; 1684103426Snectar if(ivec == NULL) { 1685103426Snectar ivec = &local_ivec; 1686103426Snectar memset(local_ivec, 0, sizeof(local_ivec)); 1687103426Snectar } 168872448Sassar des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt); 168972448Sassar return 0; 169072448Sassar} 169172448Sassar 169272448Sassarstatic krb5_error_code 169378536SassarDES_CFB64_encrypt_null_ivec(krb5_context context, 169478536Sassar struct key_data *key, 169572448Sassar void *data, 169672448Sassar size_t len, 169772448Sassar krb5_boolean encrypt, 169872448Sassar int usage, 169972448Sassar void *ignore_ivec) 170072448Sassar{ 170172448Sassar des_cblock ivec; 170272448Sassar int num = 0; 170372448Sassar des_key_schedule *s = key->schedule->data; 170472448Sassar memset(&ivec, 0, sizeof(ivec)); 170572448Sassar 170672448Sassar des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt); 170772448Sassar return 0; 170872448Sassar} 170972448Sassar 171072448Sassarstatic krb5_error_code 171178536SassarDES_PCBC_encrypt_key_ivec(krb5_context context, 171278536Sassar struct key_data *key, 171372448Sassar void *data, 171472448Sassar size_t len, 171572448Sassar krb5_boolean encrypt, 171672448Sassar int usage, 171772448Sassar void *ignore_ivec) 171872448Sassar{ 171972448Sassar des_cblock ivec; 172072448Sassar des_key_schedule *s = key->schedule->data; 172172448Sassar memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); 172272448Sassar 172372448Sassar des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt); 172472448Sassar return 0; 172572448Sassar} 172672448Sassar 172772448Sassar/* 172872448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 172972448Sassar * 173072448Sassar * warning: not for small children 173172448Sassar */ 173272448Sassar 173372448Sassarstatic krb5_error_code 173478536SassarARCFOUR_subencrypt(krb5_context context, 173578536Sassar struct key_data *key, 173672448Sassar void *data, 173772448Sassar size_t len, 173872448Sassar int usage, 173972448Sassar void *ivec) 174072448Sassar{ 174172448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 174272448Sassar Checksum k1_c, k2_c, k3_c, cksum; 174372448Sassar struct key_data ke; 174472448Sassar krb5_keyblock kb; 174572448Sassar unsigned char t[4]; 174672448Sassar RC4_KEY rc4_key; 174790929Snectar unsigned char *cdata = data; 174872448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 174972448Sassar 175072448Sassar t[0] = (usage >> 0) & 0xFF; 175172448Sassar t[1] = (usage >> 8) & 0xFF; 175272448Sassar t[2] = (usage >> 16) & 0xFF; 175372448Sassar t[3] = (usage >> 24) & 0xFF; 175472448Sassar 175572448Sassar k1_c.checksum.length = sizeof(k1_c_data); 175672448Sassar k1_c.checksum.data = k1_c_data; 175772448Sassar 175872448Sassar hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 175972448Sassar 176072448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 176172448Sassar 176272448Sassar k2_c.checksum.length = sizeof(k2_c_data); 176372448Sassar k2_c.checksum.data = k2_c_data; 176472448Sassar 176572448Sassar ke.key = &kb; 176672448Sassar kb.keyvalue = k2_c.checksum; 176772448Sassar 176872448Sassar cksum.checksum.length = 16; 176972448Sassar cksum.checksum.data = data; 177072448Sassar 177172448Sassar hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 177272448Sassar 177372448Sassar ke.key = &kb; 177472448Sassar kb.keyvalue = k1_c.checksum; 177572448Sassar 177672448Sassar k3_c.checksum.length = sizeof(k3_c_data); 177772448Sassar k3_c.checksum.data = k3_c_data; 177872448Sassar 177972448Sassar hmac(NULL, c, data, 16, 0, &ke, &k3_c); 178072448Sassar 178172448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 178272448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 178372448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 178472448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 178572448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 178672448Sassar return 0; 178772448Sassar} 178872448Sassar 178972448Sassarstatic krb5_error_code 179078536SassarARCFOUR_subdecrypt(krb5_context context, 179178536Sassar struct key_data *key, 179272448Sassar void *data, 179372448Sassar size_t len, 179472448Sassar int usage, 179572448Sassar void *ivec) 179672448Sassar{ 179772448Sassar struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); 179872448Sassar Checksum k1_c, k2_c, k3_c, cksum; 179972448Sassar struct key_data ke; 180072448Sassar krb5_keyblock kb; 180172448Sassar unsigned char t[4]; 180272448Sassar RC4_KEY rc4_key; 180390929Snectar unsigned char *cdata = data; 180472448Sassar unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 180572448Sassar unsigned char cksum_data[16]; 180672448Sassar 180772448Sassar t[0] = (usage >> 0) & 0xFF; 180872448Sassar t[1] = (usage >> 8) & 0xFF; 180972448Sassar t[2] = (usage >> 16) & 0xFF; 181072448Sassar t[3] = (usage >> 24) & 0xFF; 181172448Sassar 181272448Sassar k1_c.checksum.length = sizeof(k1_c_data); 181372448Sassar k1_c.checksum.data = k1_c_data; 181472448Sassar 181572448Sassar hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 181672448Sassar 181772448Sassar memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 181872448Sassar 181972448Sassar k2_c.checksum.length = sizeof(k2_c_data); 182072448Sassar k2_c.checksum.data = k2_c_data; 182172448Sassar 182272448Sassar ke.key = &kb; 182372448Sassar kb.keyvalue = k1_c.checksum; 182472448Sassar 182572448Sassar k3_c.checksum.length = sizeof(k3_c_data); 182672448Sassar k3_c.checksum.data = k3_c_data; 182772448Sassar 182872448Sassar hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); 182972448Sassar 183072448Sassar RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); 183172448Sassar RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); 183272448Sassar 183372448Sassar ke.key = &kb; 183472448Sassar kb.keyvalue = k2_c.checksum; 183572448Sassar 183672448Sassar cksum.checksum.length = 16; 183772448Sassar cksum.checksum.data = cksum_data; 183872448Sassar 183972448Sassar hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 184072448Sassar 184172448Sassar memset (k1_c_data, 0, sizeof(k1_c_data)); 184272448Sassar memset (k2_c_data, 0, sizeof(k2_c_data)); 184372448Sassar memset (k3_c_data, 0, sizeof(k3_c_data)); 184472448Sassar 184578536Sassar if (memcmp (cksum.checksum.data, data, 16) != 0) { 184678536Sassar krb5_clear_error_string (context); 184772448Sassar return KRB5KRB_AP_ERR_BAD_INTEGRITY; 184878536Sassar } else { 184972448Sassar return 0; 185078536Sassar } 185172448Sassar} 185272448Sassar 185372448Sassar/* 185472448Sassar * convert the usage numbers used in 185572448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in 185672448Sassar * draft-brezak-win2k-krb-rc4-hmac-03.txt 185772448Sassar */ 185872448Sassar 1859102647Snectarstatic krb5_error_code 1860102647Snectarusage2arcfour (krb5_context context, int *usage) 186172448Sassar{ 1862102647Snectar switch (*usage) { 186372448Sassar case KRB5_KU_PA_ENC_TIMESTAMP : 1864102647Snectar *usage = 1; 1865102647Snectar return 0; 186672448Sassar case KRB5_KU_TICKET : 1867102647Snectar *usage = 8; 186872448Sassar case KRB5_KU_AS_REP_ENC_PART : 1869102647Snectar *usage = 8; 1870102647Snectar return 0; 187172448Sassar case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION : 187272448Sassar case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY : 187372448Sassar case KRB5_KU_TGS_REQ_AUTH_CKSUM : 187472448Sassar case KRB5_KU_TGS_REQ_AUTH : 1875102647Snectar *usage = 7; 1876102647Snectar return 0; 187772448Sassar case KRB5_KU_TGS_REP_ENC_PART_SESSION : 187872448Sassar case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : 1879102647Snectar *usage = 8; 1880102647Snectar return 0; 188172448Sassar case KRB5_KU_AP_REQ_AUTH_CKSUM : 188272448Sassar case KRB5_KU_AP_REQ_AUTH : 188372448Sassar case KRB5_KU_AP_REQ_ENC_PART : 1884102647Snectar *usage = 11; 1885102647Snectar return 0; 188672448Sassar case KRB5_KU_KRB_PRIV : 1887102647Snectar *usage = 0; 188872448Sassar return 0; 188972448Sassar case KRB5_KU_KRB_CRED : 189072448Sassar case KRB5_KU_KRB_SAFE_CKSUM : 189172448Sassar case KRB5_KU_OTHER_ENCRYPTED : 189272448Sassar case KRB5_KU_OTHER_CKSUM : 189372448Sassar case KRB5_KU_KRB_ERROR : 189472448Sassar case KRB5_KU_AD_KDC_ISSUED : 189572448Sassar case KRB5_KU_MANDATORY_TICKET_EXTENSION : 189672448Sassar case KRB5_KU_AUTH_DATA_TICKET_EXTENSION : 189772448Sassar case KRB5_KU_USAGE_SEAL : 189872448Sassar case KRB5_KU_USAGE_SIGN : 189972448Sassar case KRB5_KU_USAGE_SEQ : 190072448Sassar default : 1901102647Snectar krb5_set_error_string(context, "unknown arcfour usage type %d", *usage); 1902102647Snectar return KRB5_PROG_ETYPE_NOSUPP; 190372448Sassar } 190472448Sassar} 190572448Sassar 190672448Sassarstatic krb5_error_code 190778536SassarARCFOUR_encrypt(krb5_context context, 190878536Sassar struct key_data *key, 190955682Smarkm void *data, 191055682Smarkm size_t len, 191172448Sassar krb5_boolean encrypt, 191272448Sassar int usage, 191372448Sassar void *ivec) 191455682Smarkm{ 1915102647Snectar krb5_error_code ret; 1916102647Snectar if((ret = usage2arcfour (context, &usage)) != 0) 1917102647Snectar return ret; 191855682Smarkm 191972448Sassar if (encrypt) 192078536Sassar return ARCFOUR_subencrypt (context, key, data, len, usage, ivec); 192172448Sassar else 192278536Sassar return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec); 192355682Smarkm} 192455682Smarkm 192572448Sassar 192655682Smarkm/* 192755682Smarkm * these should currently be in reverse preference order. 192872448Sassar * (only relevant for !F_PSEUDO) */ 192955682Smarkm 193078536Sassarstatic struct encryption_type enctype_null = { 193178536Sassar ETYPE_NULL, 193278536Sassar "null", 193378536Sassar 1, 193478536Sassar 0, 193578536Sassar &keytype_null, 193678536Sassar &checksum_none, 193778536Sassar NULL, 193878536Sassar 0, 193978536Sassar NULL_encrypt, 194055682Smarkm}; 194178536Sassarstatic struct encryption_type enctype_des_cbc_crc = { 194278536Sassar ETYPE_DES_CBC_CRC, 194378536Sassar "des-cbc-crc", 194478536Sassar 8, 194578536Sassar 8, 194678536Sassar &keytype_des, 194778536Sassar &checksum_crc32, 194878536Sassar NULL, 194978536Sassar 0, 195078536Sassar DES_CBC_encrypt_key_ivec, 195178536Sassar}; 195278536Sassarstatic struct encryption_type enctype_des_cbc_md4 = { 195378536Sassar ETYPE_DES_CBC_MD4, 195478536Sassar "des-cbc-md4", 195578536Sassar 8, 195678536Sassar 8, 195778536Sassar &keytype_des, 195878536Sassar &checksum_rsa_md4, 195978536Sassar &checksum_rsa_md4_des, 196078536Sassar 0, 196178536Sassar DES_CBC_encrypt_null_ivec, 196278536Sassar}; 196378536Sassarstatic struct encryption_type enctype_des_cbc_md5 = { 196478536Sassar ETYPE_DES_CBC_MD5, 196578536Sassar "des-cbc-md5", 196678536Sassar 8, 196778536Sassar 8, 196878536Sassar &keytype_des, 196978536Sassar &checksum_rsa_md5, 197078536Sassar &checksum_rsa_md5_des, 197178536Sassar 0, 197278536Sassar DES_CBC_encrypt_null_ivec, 197378536Sassar}; 197478536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = { 197578536Sassar ETYPE_ARCFOUR_HMAC_MD5, 197678536Sassar "arcfour-hmac-md5", 197778536Sassar 1, 197878536Sassar 8, 197978536Sassar &keytype_arcfour, 198090929Snectar &checksum_hmac_md5, 198178536Sassar &checksum_hmac_md5_enc, 198278536Sassar F_SPECIAL, 198378536Sassar ARCFOUR_encrypt 198478536Sassar}; 198578536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = { 198678536Sassar ETYPE_DES3_CBC_MD5, 198778536Sassar "des3-cbc-md5", 198878536Sassar 8, 198978536Sassar 8, 199078536Sassar &keytype_des3, 199178536Sassar &checksum_rsa_md5, 199278536Sassar &checksum_rsa_md5_des3, 199378536Sassar 0, 199478536Sassar DES3_CBC_encrypt, 199578536Sassar}; 199678536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = { 199778536Sassar ETYPE_DES3_CBC_SHA1, 199878536Sassar "des3-cbc-sha1", 199978536Sassar 8, 200078536Sassar 8, 200178536Sassar &keytype_des3_derived, 200278536Sassar &checksum_sha1, 200378536Sassar &checksum_hmac_sha1_des3, 200478536Sassar F_DERIVED, 200578536Sassar DES3_CBC_encrypt, 200678536Sassar}; 200778536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = { 200878536Sassar ETYPE_OLD_DES3_CBC_SHA1, 200978536Sassar "old-des3-cbc-sha1", 201078536Sassar 8, 201178536Sassar 8, 201278536Sassar &keytype_des3, 201378536Sassar &checksum_sha1, 201478536Sassar &checksum_hmac_sha1_des3, 201578536Sassar 0, 201678536Sassar DES3_CBC_encrypt, 201778536Sassar}; 201878536Sassarstatic struct encryption_type enctype_des_cbc_none = { 201978536Sassar ETYPE_DES_CBC_NONE, 202078536Sassar "des-cbc-none", 202178536Sassar 8, 202278536Sassar 0, 202378536Sassar &keytype_des, 202478536Sassar &checksum_none, 202578536Sassar NULL, 202678536Sassar F_PSEUDO, 202778536Sassar DES_CBC_encrypt_null_ivec, 202878536Sassar}; 202978536Sassarstatic struct encryption_type enctype_des_cfb64_none = { 203078536Sassar ETYPE_DES_CFB64_NONE, 203178536Sassar "des-cfb64-none", 203278536Sassar 1, 203378536Sassar 0, 203478536Sassar &keytype_des, 203578536Sassar &checksum_none, 203678536Sassar NULL, 203778536Sassar F_PSEUDO, 203878536Sassar DES_CFB64_encrypt_null_ivec, 203978536Sassar}; 204078536Sassarstatic struct encryption_type enctype_des_pcbc_none = { 204178536Sassar ETYPE_DES_PCBC_NONE, 204278536Sassar "des-pcbc-none", 204378536Sassar 8, 204478536Sassar 0, 204578536Sassar &keytype_des, 204678536Sassar &checksum_none, 204778536Sassar NULL, 204878536Sassar F_PSEUDO, 204978536Sassar DES_PCBC_encrypt_key_ivec, 205078536Sassar}; 205178536Sassarstatic struct encryption_type enctype_des3_cbc_none = { 205278536Sassar ETYPE_DES3_CBC_NONE, 205378536Sassar "des3-cbc-none", 205478536Sassar 8, 205578536Sassar 0, 205678536Sassar &keytype_des3_derived, 205778536Sassar &checksum_none, 205878536Sassar NULL, 205978536Sassar F_PSEUDO, 206078536Sassar DES3_CBC_encrypt, 206178536Sassar}; 206255682Smarkm 206378536Sassarstatic struct encryption_type *etypes[] = { 206478536Sassar &enctype_null, 206578536Sassar &enctype_des_cbc_crc, 206678536Sassar &enctype_des_cbc_md4, 206778536Sassar &enctype_des_cbc_md5, 206878536Sassar &enctype_arcfour_hmac_md5, 206978536Sassar &enctype_des3_cbc_md5, 207078536Sassar &enctype_des3_cbc_sha1, 207178536Sassar &enctype_old_des3_cbc_sha1, 207278536Sassar &enctype_des_cbc_none, 207378536Sassar &enctype_des_cfb64_none, 207478536Sassar &enctype_des_pcbc_none, 2075103426Snectar &enctype_des3_cbc_none 207678536Sassar}; 207778536Sassar 207855682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); 207955682Smarkm 208055682Smarkm 208155682Smarkmstatic struct encryption_type * 208255682Smarkm_find_enctype(krb5_enctype type) 208355682Smarkm{ 208455682Smarkm int i; 208555682Smarkm for(i = 0; i < num_etypes; i++) 208678536Sassar if(etypes[i]->type == type) 208778536Sassar return etypes[i]; 208855682Smarkm return NULL; 208955682Smarkm} 209055682Smarkm 209155682Smarkm 209255682Smarkmkrb5_error_code 209355682Smarkmkrb5_enctype_to_string(krb5_context context, 209455682Smarkm krb5_enctype etype, 209555682Smarkm char **string) 209655682Smarkm{ 209755682Smarkm struct encryption_type *e; 209855682Smarkm e = _find_enctype(etype); 209978536Sassar if(e == NULL) { 210078536Sassar krb5_set_error_string (context, "encryption type %d not supported", 210178536Sassar etype); 210255682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 210378536Sassar } 210455682Smarkm *string = strdup(e->name); 210578536Sassar if(*string == NULL) { 210678536Sassar krb5_set_error_string(context, "malloc: out of memory"); 210755682Smarkm return ENOMEM; 210878536Sassar } 210955682Smarkm return 0; 211055682Smarkm} 211155682Smarkm 211255682Smarkmkrb5_error_code 211355682Smarkmkrb5_string_to_enctype(krb5_context context, 211455682Smarkm const char *string, 211555682Smarkm krb5_enctype *etype) 211655682Smarkm{ 211755682Smarkm int i; 211855682Smarkm for(i = 0; i < num_etypes; i++) 211978536Sassar if(strcasecmp(etypes[i]->name, string) == 0){ 212078536Sassar *etype = etypes[i]->type; 212155682Smarkm return 0; 212255682Smarkm } 212378536Sassar krb5_set_error_string (context, "encryption type %s not supported", 212478536Sassar string); 212555682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 212655682Smarkm} 212755682Smarkm 212855682Smarkmkrb5_error_code 212955682Smarkmkrb5_enctype_to_keytype(krb5_context context, 213055682Smarkm krb5_enctype etype, 213155682Smarkm krb5_keytype *keytype) 213255682Smarkm{ 213355682Smarkm struct encryption_type *e = _find_enctype(etype); 213478536Sassar if(e == NULL) { 213578536Sassar krb5_set_error_string (context, "encryption type %d not supported", 213678536Sassar etype); 213755682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 213878536Sassar } 213955682Smarkm *keytype = e->keytype->type; /* XXX */ 214055682Smarkm return 0; 214155682Smarkm} 214255682Smarkm 214355682Smarkm#if 0 214455682Smarkmkrb5_error_code 214555682Smarkmkrb5_keytype_to_enctype(krb5_context context, 214655682Smarkm krb5_keytype keytype, 214755682Smarkm krb5_enctype *etype) 214855682Smarkm{ 214955682Smarkm struct key_type *kt = _find_keytype(keytype); 215055682Smarkm krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); 215155682Smarkm if(kt == NULL) 215255682Smarkm return KRB5_PROG_KEYTYPE_NOSUPP; 215355682Smarkm *etype = kt->best_etype; 215455682Smarkm return 0; 215555682Smarkm} 215655682Smarkm#endif 215755682Smarkm 215855682Smarkmkrb5_error_code 215955682Smarkmkrb5_keytype_to_enctypes (krb5_context context, 216055682Smarkm krb5_keytype keytype, 216155682Smarkm unsigned *len, 216290929Snectar krb5_enctype **val) 216355682Smarkm{ 216455682Smarkm int i; 216555682Smarkm unsigned n = 0; 216690929Snectar krb5_enctype *ret; 216755682Smarkm 216855682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 216978536Sassar if (etypes[i]->keytype->type == keytype 217078536Sassar && !(etypes[i]->flags & F_PSEUDO)) 217155682Smarkm ++n; 217255682Smarkm } 217390929Snectar ret = malloc(n * sizeof(*ret)); 217478536Sassar if (ret == NULL && n != 0) { 217578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 217655682Smarkm return ENOMEM; 217778536Sassar } 217855682Smarkm n = 0; 217955682Smarkm for (i = num_etypes - 1; i >= 0; --i) { 218078536Sassar if (etypes[i]->keytype->type == keytype 218178536Sassar && !(etypes[i]->flags & F_PSEUDO)) 218278536Sassar ret[n++] = etypes[i]->type; 218355682Smarkm } 218455682Smarkm *len = n; 218555682Smarkm *val = ret; 218655682Smarkm return 0; 218755682Smarkm} 218855682Smarkm 218955682Smarkm/* 219055682Smarkm * First take the configured list of etypes for `keytype' if available, 219155682Smarkm * else, do `krb5_keytype_to_enctypes'. 219255682Smarkm */ 219355682Smarkm 219455682Smarkmkrb5_error_code 219555682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context, 219655682Smarkm krb5_keytype keytype, 219755682Smarkm unsigned *len, 219890929Snectar krb5_enctype **val) 219955682Smarkm{ 220055682Smarkm int i, n; 220190929Snectar krb5_enctype *ret; 220255682Smarkm 220355682Smarkm if (keytype != KEYTYPE_DES || context->etypes_des == NULL) 220455682Smarkm return krb5_keytype_to_enctypes (context, keytype, len, val); 220555682Smarkm 220655682Smarkm for (n = 0; context->etypes_des[n]; ++n) 220755682Smarkm ; 220855682Smarkm ret = malloc (n * sizeof(*ret)); 220978536Sassar if (ret == NULL && n != 0) { 221078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 221155682Smarkm return ENOMEM; 221278536Sassar } 221355682Smarkm for (i = 0; i < n; ++i) 221455682Smarkm ret[i] = context->etypes_des[i]; 221555682Smarkm *len = n; 221655682Smarkm *val = ret; 221755682Smarkm return 0; 221855682Smarkm} 221955682Smarkm 222055682Smarkmkrb5_error_code 222155682Smarkmkrb5_enctype_valid(krb5_context context, 222255682Smarkm krb5_enctype etype) 222355682Smarkm{ 222455682Smarkm return _find_enctype(etype) != NULL; 222555682Smarkm} 222655682Smarkm 222755682Smarkm/* if two enctypes have compatible keys */ 222855682Smarkmkrb5_boolean 222955682Smarkmkrb5_enctypes_compatible_keys(krb5_context context, 223055682Smarkm krb5_enctype etype1, 223155682Smarkm krb5_enctype etype2) 223255682Smarkm{ 223355682Smarkm struct encryption_type *e1 = _find_enctype(etype1); 223455682Smarkm struct encryption_type *e2 = _find_enctype(etype2); 223555682Smarkm return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; 223655682Smarkm} 223755682Smarkm 223855682Smarkmstatic krb5_boolean 223955682Smarkmderived_crypto(krb5_context context, 224055682Smarkm krb5_crypto crypto) 224155682Smarkm{ 224255682Smarkm return (crypto->et->flags & F_DERIVED) != 0; 224355682Smarkm} 224455682Smarkm 224572448Sassarstatic krb5_boolean 224672448Sassarspecial_crypto(krb5_context context, 224772448Sassar krb5_crypto crypto) 224872448Sassar{ 224972448Sassar return (crypto->et->flags & F_SPECIAL) != 0; 225072448Sassar} 225155682Smarkm 225255682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize) 225355682Smarkm#define CHECKSUMTYPE(C) ((C)->type) 225455682Smarkm 225555682Smarkmstatic krb5_error_code 225655682Smarkmencrypt_internal_derived(krb5_context context, 225755682Smarkm krb5_crypto crypto, 225855682Smarkm unsigned usage, 225955682Smarkm void *data, 226055682Smarkm size_t len, 226172448Sassar krb5_data *result, 226272448Sassar void *ivec) 226355682Smarkm{ 226490929Snectar size_t sz, block_sz, checksum_sz, total_sz; 226555682Smarkm Checksum cksum; 226655682Smarkm unsigned char *p, *q; 226755682Smarkm krb5_error_code ret; 226855682Smarkm struct key_data *dkey; 226990929Snectar const struct encryption_type *et = crypto->et; 227055682Smarkm 227155682Smarkm checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 227255682Smarkm 227390929Snectar sz = et->confoundersize + len; 227455682Smarkm block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */ 227590929Snectar total_sz = block_sz + checksum_sz; 227690929Snectar p = calloc(1, total_sz); 227790929Snectar if(p == NULL) { 227890929Snectar krb5_set_error_string(context, "malloc: out of memory"); 227955682Smarkm return ENOMEM; 228090929Snectar } 228155682Smarkm 228255682Smarkm q = p; 228355682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 228455682Smarkm q += et->confoundersize; 228555682Smarkm memcpy(q, data, len); 228655682Smarkm 228755682Smarkm ret = create_checksum(context, 228855682Smarkm crypto, 228955682Smarkm INTEGRITY_USAGE(usage), 229078536Sassar et->keyed_checksum->type, 229155682Smarkm p, 229255682Smarkm block_sz, 229355682Smarkm &cksum); 229472448Sassar if(ret == 0 && cksum.checksum.length != checksum_sz) { 229572448Sassar free_Checksum (&cksum); 229678536Sassar krb5_clear_error_string (context); 229772448Sassar ret = KRB5_CRYPTO_INTERNAL; 229872448Sassar } 229990929Snectar if(ret) 230090929Snectar goto fail; 230155682Smarkm memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 230272448Sassar free_Checksum (&cksum); 230355682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 230490929Snectar if(ret) 230590929Snectar goto fail; 230655682Smarkm ret = _key_schedule(context, dkey); 230790929Snectar if(ret) 230890929Snectar goto fail; 230955682Smarkm#ifdef CRYPTO_DEBUG 231055682Smarkm krb5_crypto_debug(context, 1, block_sz, dkey->key); 231155682Smarkm#endif 231290929Snectar ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 231390929Snectar if (ret) 231490929Snectar goto fail; 231555682Smarkm result->data = p; 231690929Snectar result->length = total_sz; 231755682Smarkm return 0; 231890929Snectar fail: 231990929Snectar memset(p, 0, total_sz); 232090929Snectar free(p); 232190929Snectar return ret; 232255682Smarkm} 232355682Smarkm 232490929Snectar 232555682Smarkmstatic krb5_error_code 232655682Smarkmencrypt_internal(krb5_context context, 232755682Smarkm krb5_crypto crypto, 232855682Smarkm void *data, 232955682Smarkm size_t len, 233072448Sassar krb5_data *result, 233172448Sassar void *ivec) 233255682Smarkm{ 233355682Smarkm size_t sz, block_sz, checksum_sz; 233455682Smarkm Checksum cksum; 233555682Smarkm unsigned char *p, *q; 233655682Smarkm krb5_error_code ret; 233790929Snectar const struct encryption_type *et = crypto->et; 233855682Smarkm 233978536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 234055682Smarkm 234155682Smarkm sz = et->confoundersize + checksum_sz + len; 234255682Smarkm block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */ 234355682Smarkm p = calloc(1, block_sz); 234478536Sassar if(p == NULL) { 234578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 234655682Smarkm return ENOMEM; 234778536Sassar } 234855682Smarkm 234955682Smarkm q = p; 235055682Smarkm krb5_generate_random_block(q, et->confoundersize); /* XXX */ 235155682Smarkm q += et->confoundersize; 235255682Smarkm memset(q, 0, checksum_sz); 235355682Smarkm q += checksum_sz; 235455682Smarkm memcpy(q, data, len); 235555682Smarkm 235655682Smarkm ret = create_checksum(context, 235778536Sassar crypto, 235855682Smarkm 0, 235978536Sassar et->checksum->type, 236055682Smarkm p, 236155682Smarkm block_sz, 236255682Smarkm &cksum); 236355682Smarkm if(ret == 0 && cksum.checksum.length != checksum_sz) { 236478536Sassar krb5_clear_error_string (context); 236590929Snectar free_Checksum(&cksum); 236655682Smarkm ret = KRB5_CRYPTO_INTERNAL; 236755682Smarkm } 236890929Snectar if(ret) 236990929Snectar goto fail; 237055682Smarkm memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); 237155682Smarkm free_Checksum(&cksum); 237255682Smarkm ret = _key_schedule(context, &crypto->key); 237390929Snectar if(ret) 237490929Snectar goto fail; 237590929Snectar#ifdef CRYPTO_DEBUG 237690929Snectar krb5_crypto_debug(context, 1, block_sz, crypto->key.key); 237790929Snectar#endif 237890929Snectar ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); 237990929Snectar if (ret) { 238055682Smarkm memset(p, 0, block_sz); 238155682Smarkm free(p); 238255682Smarkm return ret; 238355682Smarkm } 238455682Smarkm result->data = p; 238555682Smarkm result->length = block_sz; 238655682Smarkm return 0; 238790929Snectar fail: 238890929Snectar memset(p, 0, block_sz); 238990929Snectar free(p); 239090929Snectar return ret; 239155682Smarkm} 239255682Smarkm 239355682Smarkmstatic krb5_error_code 239472448Sassarencrypt_internal_special(krb5_context context, 239572448Sassar krb5_crypto crypto, 239672448Sassar int usage, 239772448Sassar void *data, 239872448Sassar size_t len, 239972448Sassar krb5_data *result, 240072448Sassar void *ivec) 240172448Sassar{ 240272448Sassar struct encryption_type *et = crypto->et; 240378536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 240472448Sassar size_t sz = len + cksum_sz + et->confoundersize; 240572448Sassar char *tmp, *p; 240690929Snectar krb5_error_code ret; 240772448Sassar 240872448Sassar tmp = malloc (sz); 240978536Sassar if (tmp == NULL) { 241078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 241172448Sassar return ENOMEM; 241278536Sassar } 241372448Sassar p = tmp; 241472448Sassar memset (p, 0, cksum_sz); 241572448Sassar p += cksum_sz; 241672448Sassar krb5_generate_random_block(p, et->confoundersize); 241772448Sassar p += et->confoundersize; 241872448Sassar memcpy (p, data, len); 241990929Snectar ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); 242090929Snectar if (ret) { 242190929Snectar memset(tmp, 0, sz); 242290929Snectar free(tmp); 242390929Snectar return ret; 242490929Snectar } 242572448Sassar result->data = tmp; 242672448Sassar result->length = sz; 242772448Sassar return 0; 242872448Sassar} 242972448Sassar 243072448Sassarstatic krb5_error_code 243155682Smarkmdecrypt_internal_derived(krb5_context context, 243255682Smarkm krb5_crypto crypto, 243355682Smarkm unsigned usage, 243455682Smarkm void *data, 243555682Smarkm size_t len, 243672448Sassar krb5_data *result, 243772448Sassar void *ivec) 243855682Smarkm{ 243955682Smarkm size_t checksum_sz; 244055682Smarkm Checksum cksum; 244155682Smarkm unsigned char *p; 244255682Smarkm krb5_error_code ret; 244355682Smarkm struct key_data *dkey; 244455682Smarkm struct encryption_type *et = crypto->et; 244555682Smarkm unsigned long l; 244655682Smarkm 244772448Sassar checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 244878536Sassar if (len < checksum_sz) { 244978536Sassar krb5_clear_error_string (context); 245078536Sassar return EINVAL; /* XXX - better error code? */ 245178536Sassar } 245272448Sassar 245355682Smarkm p = malloc(len); 245478536Sassar if(len != 0 && p == NULL) { 245578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 245655682Smarkm return ENOMEM; 245778536Sassar } 245855682Smarkm memcpy(p, data, len); 245955682Smarkm 246055682Smarkm len -= checksum_sz; 246155682Smarkm 246255682Smarkm ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 246355682Smarkm if(ret) { 246455682Smarkm free(p); 246555682Smarkm return ret; 246655682Smarkm } 246755682Smarkm ret = _key_schedule(context, dkey); 246855682Smarkm if(ret) { 246955682Smarkm free(p); 247055682Smarkm return ret; 247155682Smarkm } 247255682Smarkm#ifdef CRYPTO_DEBUG 247355682Smarkm krb5_crypto_debug(context, 0, len, dkey->key); 247455682Smarkm#endif 247590929Snectar ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 247690929Snectar if (ret) { 247790929Snectar free(p); 247890929Snectar return ret; 247990929Snectar } 248055682Smarkm 248155682Smarkm cksum.checksum.data = p + len; 248255682Smarkm cksum.checksum.length = checksum_sz; 248355682Smarkm cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 248455682Smarkm 248555682Smarkm ret = verify_checksum(context, 248655682Smarkm crypto, 248755682Smarkm INTEGRITY_USAGE(usage), 248855682Smarkm p, 248955682Smarkm len, 249055682Smarkm &cksum); 249155682Smarkm if(ret) { 249255682Smarkm free(p); 249355682Smarkm return ret; 249455682Smarkm } 249555682Smarkm l = len - et->confoundersize; 249655682Smarkm memmove(p, p + et->confoundersize, l); 249755682Smarkm result->data = realloc(p, l); 249878536Sassar if(result->data == NULL) { 249955682Smarkm free(p); 250078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 250155682Smarkm return ENOMEM; 250255682Smarkm } 250355682Smarkm result->length = l; 250455682Smarkm return 0; 250555682Smarkm} 250655682Smarkm 250755682Smarkmstatic krb5_error_code 250855682Smarkmdecrypt_internal(krb5_context context, 250955682Smarkm krb5_crypto crypto, 251055682Smarkm void *data, 251155682Smarkm size_t len, 251272448Sassar krb5_data *result, 251372448Sassar void *ivec) 251455682Smarkm{ 251555682Smarkm krb5_error_code ret; 251655682Smarkm unsigned char *p; 251755682Smarkm Checksum cksum; 251855682Smarkm size_t checksum_sz, l; 251955682Smarkm struct encryption_type *et = crypto->et; 252055682Smarkm 252178536Sassar checksum_sz = CHECKSUMSIZE(et->checksum); 252255682Smarkm p = malloc(len); 252378536Sassar if(len != 0 && p == NULL) { 252478536Sassar krb5_set_error_string(context, "malloc: out of memory"); 252555682Smarkm return ENOMEM; 252678536Sassar } 252755682Smarkm memcpy(p, data, len); 252855682Smarkm 252955682Smarkm ret = _key_schedule(context, &crypto->key); 253055682Smarkm if(ret) { 253155682Smarkm free(p); 253255682Smarkm return ret; 253355682Smarkm } 253455682Smarkm#ifdef CRYPTO_DEBUG 253555682Smarkm krb5_crypto_debug(context, 0, len, crypto->key.key); 253655682Smarkm#endif 253790929Snectar ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); 253890929Snectar if (ret) { 253990929Snectar free(p); 254090929Snectar return ret; 254190929Snectar } 254255682Smarkm ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); 254355682Smarkm if(ret) { 254472448Sassar free(p); 254572448Sassar return ret; 254655682Smarkm } 254755682Smarkm memset(p + et->confoundersize, 0, checksum_sz); 254878536Sassar cksum.cksumtype = CHECKSUMTYPE(et->checksum); 254955682Smarkm ret = verify_checksum(context, NULL, 0, p, len, &cksum); 255055682Smarkm free_Checksum(&cksum); 255155682Smarkm if(ret) { 255255682Smarkm free(p); 255355682Smarkm return ret; 255455682Smarkm } 255555682Smarkm l = len - et->confoundersize - checksum_sz; 255655682Smarkm memmove(p, p + et->confoundersize + checksum_sz, l); 255755682Smarkm result->data = realloc(p, l); 255855682Smarkm if(result->data == NULL) { 255955682Smarkm free(p); 256078536Sassar krb5_set_error_string(context, "malloc: out of memory"); 256155682Smarkm return ENOMEM; 256255682Smarkm } 256355682Smarkm result->length = l; 256455682Smarkm return 0; 256555682Smarkm} 256655682Smarkm 256772448Sassarstatic krb5_error_code 256872448Sassardecrypt_internal_special(krb5_context context, 256972448Sassar krb5_crypto crypto, 257072448Sassar int usage, 257172448Sassar void *data, 257272448Sassar size_t len, 257372448Sassar krb5_data *result, 257472448Sassar void *ivec) 257572448Sassar{ 257672448Sassar struct encryption_type *et = crypto->et; 257778536Sassar size_t cksum_sz = CHECKSUMSIZE(et->checksum); 257872448Sassar size_t sz = len - cksum_sz - et->confoundersize; 257972448Sassar char *cdata = (char *)data; 258072448Sassar char *tmp; 258190929Snectar krb5_error_code ret; 258272448Sassar 258372448Sassar tmp = malloc (sz); 258478536Sassar if (tmp == NULL) { 258578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 258672448Sassar return ENOMEM; 258778536Sassar } 258872448Sassar 258990929Snectar ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec); 259090929Snectar if (ret) { 259190929Snectar free(tmp); 259290929Snectar return ret; 259390929Snectar } 259472448Sassar 259572448Sassar memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz); 259672448Sassar 259772448Sassar result->data = tmp; 259872448Sassar result->length = sz; 259972448Sassar return 0; 260072448Sassar} 260172448Sassar 260272448Sassar 260355682Smarkmkrb5_error_code 260472448Sassarkrb5_encrypt_ivec(krb5_context context, 260572448Sassar krb5_crypto crypto, 260672448Sassar unsigned usage, 260772448Sassar void *data, 260872448Sassar size_t len, 260972448Sassar krb5_data *result, 261072448Sassar void *ivec) 261172448Sassar{ 261272448Sassar if(derived_crypto(context, crypto)) 261372448Sassar return encrypt_internal_derived(context, crypto, usage, 261472448Sassar data, len, result, ivec); 261572448Sassar else if (special_crypto(context, crypto)) 261672448Sassar return encrypt_internal_special (context, crypto, usage, 261772448Sassar data, len, result, ivec); 261872448Sassar else 261972448Sassar return encrypt_internal(context, crypto, data, len, result, ivec); 262072448Sassar} 262172448Sassar 262272448Sassarkrb5_error_code 262355682Smarkmkrb5_encrypt(krb5_context context, 262455682Smarkm krb5_crypto crypto, 262555682Smarkm unsigned usage, 262655682Smarkm void *data, 262755682Smarkm size_t len, 262855682Smarkm krb5_data *result) 262955682Smarkm{ 263072448Sassar return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); 263155682Smarkm} 263255682Smarkm 263355682Smarkmkrb5_error_code 263455682Smarkmkrb5_encrypt_EncryptedData(krb5_context context, 263555682Smarkm krb5_crypto crypto, 263655682Smarkm unsigned usage, 263755682Smarkm void *data, 263855682Smarkm size_t len, 263955682Smarkm int kvno, 264055682Smarkm EncryptedData *result) 264155682Smarkm{ 264255682Smarkm result->etype = CRYPTO_ETYPE(crypto); 264355682Smarkm if(kvno){ 264455682Smarkm ALLOC(result->kvno, 1); 264555682Smarkm *result->kvno = kvno; 264655682Smarkm }else 264755682Smarkm result->kvno = NULL; 264855682Smarkm return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); 264955682Smarkm} 265055682Smarkm 265155682Smarkmkrb5_error_code 265272448Sassarkrb5_decrypt_ivec(krb5_context context, 265372448Sassar krb5_crypto crypto, 265472448Sassar unsigned usage, 265572448Sassar void *data, 265672448Sassar size_t len, 265772448Sassar krb5_data *result, 265872448Sassar void *ivec) 265972448Sassar{ 266072448Sassar if(derived_crypto(context, crypto)) 266172448Sassar return decrypt_internal_derived(context, crypto, usage, 266272448Sassar data, len, result, ivec); 266372448Sassar else if (special_crypto (context, crypto)) 266472448Sassar return decrypt_internal_special(context, crypto, usage, 266572448Sassar data, len, result, ivec); 266672448Sassar else 266772448Sassar return decrypt_internal(context, crypto, data, len, result, ivec); 266872448Sassar} 266972448Sassar 267072448Sassarkrb5_error_code 267155682Smarkmkrb5_decrypt(krb5_context context, 267255682Smarkm krb5_crypto crypto, 267355682Smarkm unsigned usage, 267455682Smarkm void *data, 267555682Smarkm size_t len, 267655682Smarkm krb5_data *result) 267755682Smarkm{ 267872448Sassar return krb5_decrypt_ivec (context, crypto, usage, data, len, result, 267972448Sassar NULL); 268055682Smarkm} 268155682Smarkm 268255682Smarkmkrb5_error_code 268355682Smarkmkrb5_decrypt_EncryptedData(krb5_context context, 268455682Smarkm krb5_crypto crypto, 268555682Smarkm unsigned usage, 268672448Sassar const EncryptedData *e, 268755682Smarkm krb5_data *result) 268855682Smarkm{ 268955682Smarkm return krb5_decrypt(context, crypto, usage, 269055682Smarkm e->cipher.data, e->cipher.length, result); 269155682Smarkm} 269255682Smarkm 269355682Smarkm/************************************************************ 269455682Smarkm * * 269555682Smarkm ************************************************************/ 269655682Smarkm 269790929Snectar#ifdef HAVE_OPENSSL 269878536Sassar#include <openssl/rand.h> 269978536Sassar 270078536Sassar/* From openssl/crypto/rand/rand_lcl.h */ 270178536Sassar#define ENTROPY_NEEDED 20 270278536Sassarstatic int 270378536Sassarseed_something(void) 270478536Sassar{ 270578536Sassar int fd = -1; 270678536Sassar char buf[1024], seedfile[256]; 270778536Sassar 270878536Sassar /* If there is a seed file, load it. But such a file cannot be trusted, 270978536Sassar so use 0 for the entropy estimate */ 271078536Sassar if (RAND_file_name(seedfile, sizeof(seedfile))) { 271178536Sassar fd = open(seedfile, O_RDONLY); 271278536Sassar if (fd >= 0) { 271378536Sassar read(fd, buf, sizeof(buf)); 271478536Sassar /* Use the full buffer anyway */ 271578536Sassar RAND_add(buf, sizeof(buf), 0.0); 271678536Sassar } else 271778536Sassar seedfile[0] = '\0'; 271878536Sassar } else 271978536Sassar seedfile[0] = '\0'; 272078536Sassar 272178536Sassar /* Calling RAND_status() will try to use /dev/urandom if it exists so 272278536Sassar we do not have to deal with it. */ 272378536Sassar if (RAND_status() != 1) { 272478536Sassar krb5_context context; 272590929Snectar const char *p; 272678536Sassar 272778536Sassar /* Try using egd */ 272878536Sassar if (!krb5_init_context(&context)) { 272978536Sassar p = krb5_config_get_string(context, NULL, "libdefaults", 273078536Sassar "egd_socket", NULL); 273178536Sassar if (p != NULL) 273278536Sassar RAND_egd_bytes(p, ENTROPY_NEEDED); 273378536Sassar krb5_free_context(context); 273478536Sassar } 273578536Sassar } 273678536Sassar 273778536Sassar if (RAND_status() == 1) { 273878536Sassar /* Update the seed file */ 273978536Sassar if (seedfile[0]) 274078536Sassar RAND_write_file(seedfile); 274178536Sassar 274278536Sassar return 0; 274378536Sassar } else 274478536Sassar return -1; 274578536Sassar} 274678536Sassar 274755682Smarkmvoid 274855682Smarkmkrb5_generate_random_block(void *buf, size_t len) 274955682Smarkm{ 275078536Sassar static int rng_initialized = 0; 275178536Sassar 275278536Sassar if (!rng_initialized) { 275378536Sassar if (seed_something()) 275478536Sassar krb5_abortx(NULL, "Fatal: could not seed the random number generator"); 275578536Sassar 275678536Sassar rng_initialized = 1; 275778536Sassar } 275878536Sassar RAND_bytes(buf, len); 275978536Sassar} 276078536Sassar 276178536Sassar#else 276278536Sassar 276378536Sassarvoid 276478536Sassarkrb5_generate_random_block(void *buf, size_t len) 276578536Sassar{ 276655682Smarkm des_cblock key, out; 276755682Smarkm static des_cblock counter; 276855682Smarkm static des_key_schedule schedule; 276955682Smarkm int i; 277055682Smarkm static int initialized = 0; 277155682Smarkm 277255682Smarkm if(!initialized) { 277355682Smarkm des_new_random_key(&key); 277455682Smarkm des_set_key(&key, schedule); 277555682Smarkm memset(&key, 0, sizeof(key)); 277655682Smarkm des_new_random_key(&counter); 277755682Smarkm } 277855682Smarkm while(len > 0) { 277955682Smarkm des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT); 278055682Smarkm for(i = 7; i >=0; i--) 278155682Smarkm if(counter[i]++) 278255682Smarkm break; 278355682Smarkm memcpy(buf, out, min(len, sizeof(out))); 278455682Smarkm len -= min(len, sizeof(out)); 278555682Smarkm buf = (char*)buf + sizeof(out); 278655682Smarkm } 278755682Smarkm} 278878536Sassar#endif 278955682Smarkm 279055682Smarkmstatic void 279155682SmarkmDES3_postproc(krb5_context context, 279255682Smarkm unsigned char *k, size_t len, struct key_data *key) 279355682Smarkm{ 279455682Smarkm unsigned char x[24]; 279555682Smarkm int i, j; 279655682Smarkm 279755682Smarkm memset(x, 0, sizeof(x)); 279855682Smarkm for (i = 0; i < 3; ++i) { 279955682Smarkm unsigned char foo; 280055682Smarkm 280155682Smarkm for (j = 0; j < 7; ++j) { 280255682Smarkm unsigned char b = k[7 * i + j]; 280355682Smarkm 280455682Smarkm x[8 * i + j] = b; 280555682Smarkm } 280655682Smarkm foo = 0; 280755682Smarkm for (j = 6; j >= 0; --j) { 280855682Smarkm foo |= k[7 * i + j] & 1; 280955682Smarkm foo <<= 1; 281055682Smarkm } 281155682Smarkm x[8 * i + 7] = foo; 281255682Smarkm } 281355682Smarkm k = key->key->keyvalue.data; 281455682Smarkm memcpy(k, x, 24); 281555682Smarkm memset(x, 0, sizeof(x)); 281655682Smarkm if (key->schedule) { 281755682Smarkm krb5_free_data(context, key->schedule); 281855682Smarkm key->schedule = NULL; 281955682Smarkm } 282055682Smarkm des_set_odd_parity((des_cblock*)k); 282155682Smarkm des_set_odd_parity((des_cblock*)(k + 8)); 282255682Smarkm des_set_odd_parity((des_cblock*)(k + 16)); 282355682Smarkm} 282455682Smarkm 282555682Smarkmstatic krb5_error_code 282655682Smarkmderive_key(krb5_context context, 282755682Smarkm struct encryption_type *et, 282855682Smarkm struct key_data *key, 282978536Sassar const void *constant, 283055682Smarkm size_t len) 283155682Smarkm{ 283255682Smarkm unsigned char *k; 283355682Smarkm unsigned int nblocks = 0, i; 283455682Smarkm krb5_error_code ret = 0; 283555682Smarkm 283655682Smarkm struct key_type *kt = et->keytype; 283755682Smarkm ret = _key_schedule(context, key); 283855682Smarkm if(ret) 283955682Smarkm return ret; 284072448Sassar if(et->blocksize * 8 < kt->bits || 284155682Smarkm len != et->blocksize) { 284255682Smarkm nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); 284355682Smarkm k = malloc(nblocks * et->blocksize); 284478536Sassar if(k == NULL) { 284578536Sassar krb5_set_error_string(context, "malloc: out of memory"); 284655682Smarkm return ENOMEM; 284778536Sassar } 284855682Smarkm _krb5_n_fold(constant, len, k, et->blocksize); 284955682Smarkm for(i = 0; i < nblocks; i++) { 285055682Smarkm if(i > 0) 285155682Smarkm memcpy(k + i * et->blocksize, 285255682Smarkm k + (i - 1) * et->blocksize, 285355682Smarkm et->blocksize); 285478536Sassar (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, 285578536Sassar 1, 0, NULL); 285655682Smarkm } 285755682Smarkm } else { 285872448Sassar /* this case is probably broken, but won't be run anyway */ 285955682Smarkm void *c = malloc(len); 286055682Smarkm size_t res_len = (kt->bits + 7) / 8; 286155682Smarkm 286278536Sassar if(len != 0 && c == NULL) { 286378536Sassar krb5_set_error_string(context, "malloc: out of memory"); 286455682Smarkm return ENOMEM; 286578536Sassar } 286655682Smarkm memcpy(c, constant, len); 286778536Sassar (*et->encrypt)(context, key, c, len, 1, 0, NULL); 286855682Smarkm k = malloc(res_len); 286978536Sassar if(res_len != 0 && k == NULL) { 287078536Sassar free(c); 287178536Sassar krb5_set_error_string(context, "malloc: out of memory"); 287255682Smarkm return ENOMEM; 287378536Sassar } 287455682Smarkm _krb5_n_fold(c, len, k, res_len); 287555682Smarkm free(c); 287655682Smarkm } 287755682Smarkm 287855682Smarkm /* XXX keytype dependent post-processing */ 287955682Smarkm switch(kt->type) { 288055682Smarkm case KEYTYPE_DES3: 288155682Smarkm DES3_postproc(context, k, nblocks * et->blocksize, key); 288255682Smarkm break; 288355682Smarkm default: 288478536Sassar krb5_set_error_string(context, 288578536Sassar "derive_key() called with unknown keytype (%u)", 288678536Sassar kt->type); 288755682Smarkm ret = KRB5_CRYPTO_INTERNAL; 288855682Smarkm break; 288955682Smarkm } 289055682Smarkm memset(k, 0, nblocks * et->blocksize); 289155682Smarkm free(k); 289255682Smarkm return ret; 289355682Smarkm} 289455682Smarkm 289555682Smarkmstatic struct key_data * 289655682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage) 289755682Smarkm{ 289855682Smarkm struct key_usage *d = crypto->key_usage; 289955682Smarkm d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); 290055682Smarkm if(d == NULL) 290155682Smarkm return NULL; 290255682Smarkm crypto->key_usage = d; 290355682Smarkm d += crypto->num_key_usage++; 290455682Smarkm memset(d, 0, sizeof(*d)); 290555682Smarkm d->usage = usage; 290655682Smarkm return &d->key; 290755682Smarkm} 290855682Smarkm 290978536Sassarkrb5_error_code 291078536Sassarkrb5_derive_key(krb5_context context, 291178536Sassar const krb5_keyblock *key, 291278536Sassar krb5_enctype etype, 291378536Sassar const void *constant, 291478536Sassar size_t constant_len, 291578536Sassar krb5_keyblock **derived_key) 291678536Sassar{ 291778536Sassar krb5_error_code ret; 291878536Sassar struct encryption_type *et; 291978536Sassar struct key_data d; 292078536Sassar 292178536Sassar et = _find_enctype (etype); 292278536Sassar if (et == NULL) { 292378536Sassar krb5_set_error_string(context, "encryption type %d not supported", 292478536Sassar etype); 292578536Sassar return KRB5_PROG_ETYPE_NOSUPP; 292678536Sassar } 292778536Sassar 292878536Sassar ret = krb5_copy_keyblock(context, key, derived_key); 292978536Sassar if (ret) 293078536Sassar return ret; 293178536Sassar 293278536Sassar d.key = *derived_key; 293378536Sassar d.schedule = NULL; 293478536Sassar ret = derive_key(context, et, &d, constant, constant_len); 293578536Sassar if (ret) 293678536Sassar return ret; 293778536Sassar ret = krb5_copy_keyblock(context, d.key, derived_key); 293878536Sassar return ret; 293978536Sassar} 294078536Sassar 294155682Smarkmstatic krb5_error_code 294255682Smarkm_get_derived_key(krb5_context context, 294355682Smarkm krb5_crypto crypto, 294455682Smarkm unsigned usage, 294555682Smarkm struct key_data **key) 294655682Smarkm{ 294755682Smarkm int i; 294855682Smarkm struct key_data *d; 294955682Smarkm unsigned char constant[5]; 295055682Smarkm 295155682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 295255682Smarkm if(crypto->key_usage[i].usage == usage) { 295355682Smarkm *key = &crypto->key_usage[i].key; 295455682Smarkm return 0; 295555682Smarkm } 295655682Smarkm d = _new_derived_key(crypto, usage); 295778536Sassar if(d == NULL) { 295878536Sassar krb5_set_error_string(context, "malloc: out of memory"); 295955682Smarkm return ENOMEM; 296078536Sassar } 296155682Smarkm krb5_copy_keyblock(context, crypto->key.key, &d->key); 296255682Smarkm _krb5_put_int(constant, usage, 5); 296355682Smarkm derive_key(context, crypto->et, d, constant, sizeof(constant)); 296455682Smarkm *key = d; 296555682Smarkm return 0; 296655682Smarkm} 296755682Smarkm 296855682Smarkm 296955682Smarkmkrb5_error_code 297055682Smarkmkrb5_crypto_init(krb5_context context, 297178536Sassar const krb5_keyblock *key, 297255682Smarkm krb5_enctype etype, 297355682Smarkm krb5_crypto *crypto) 297455682Smarkm{ 297555682Smarkm krb5_error_code ret; 297655682Smarkm ALLOC(*crypto, 1); 297778536Sassar if(*crypto == NULL) { 297878536Sassar krb5_set_error_string(context, "malloc: out of memory"); 297955682Smarkm return ENOMEM; 298078536Sassar } 298155682Smarkm if(etype == ETYPE_NULL) 298255682Smarkm etype = key->keytype; 298355682Smarkm (*crypto)->et = _find_enctype(etype); 298455682Smarkm if((*crypto)->et == NULL) { 298555682Smarkm free(*crypto); 298678536Sassar krb5_set_error_string (context, "encryption type %d not supported", 298778536Sassar etype); 298855682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 298955682Smarkm } 2990102647Snectar if((*crypto)->et->keytype->size != key->keyvalue.length) { 2991102647Snectar free(*crypto); 2992102647Snectar krb5_set_error_string (context, "encryption key has bad length"); 2993102647Snectar return KRB5_BAD_KEYSIZE; 2994102647Snectar } 299555682Smarkm ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); 299655682Smarkm if(ret) { 299755682Smarkm free(*crypto); 299855682Smarkm return ret; 299955682Smarkm } 300055682Smarkm (*crypto)->key.schedule = NULL; 300155682Smarkm (*crypto)->num_key_usage = 0; 300255682Smarkm (*crypto)->key_usage = NULL; 300355682Smarkm return 0; 300455682Smarkm} 300555682Smarkm 300655682Smarkmstatic void 300755682Smarkmfree_key_data(krb5_context context, struct key_data *key) 300855682Smarkm{ 300955682Smarkm krb5_free_keyblock(context, key->key); 301055682Smarkm if(key->schedule) { 301155682Smarkm memset(key->schedule->data, 0, key->schedule->length); 301255682Smarkm krb5_free_data(context, key->schedule); 301355682Smarkm } 301455682Smarkm} 301555682Smarkm 301655682Smarkmstatic void 301755682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku) 301855682Smarkm{ 301955682Smarkm free_key_data(context, &ku->key); 302055682Smarkm} 302155682Smarkm 302255682Smarkmkrb5_error_code 302355682Smarkmkrb5_crypto_destroy(krb5_context context, 302455682Smarkm krb5_crypto crypto) 302555682Smarkm{ 302655682Smarkm int i; 302755682Smarkm 302855682Smarkm for(i = 0; i < crypto->num_key_usage; i++) 302955682Smarkm free_key_usage(context, &crypto->key_usage[i]); 303055682Smarkm free(crypto->key_usage); 303155682Smarkm free_key_data(context, &crypto->key); 303255682Smarkm free (crypto); 303355682Smarkm return 0; 303455682Smarkm} 303555682Smarkm 303655682Smarkmkrb5_error_code 3037103426Snectarkrb5_crypto_getblocksize(krb5_context context, 3038103426Snectar krb5_crypto crypto, 3039103426Snectar size_t *blocksize) 3040103426Snectar{ 3041103426Snectar *blocksize = crypto->et->blocksize; 3042103426Snectar return 0; 3043103426Snectar} 3044103426Snectar 3045103426Snectarkrb5_error_code 304655682Smarkmkrb5_string_to_key_derived(krb5_context context, 304755682Smarkm const void *str, 304855682Smarkm size_t len, 304955682Smarkm krb5_enctype etype, 305055682Smarkm krb5_keyblock *key) 305155682Smarkm{ 305255682Smarkm struct encryption_type *et = _find_enctype(etype); 305355682Smarkm krb5_error_code ret; 305455682Smarkm struct key_data kd; 305590929Snectar size_t keylen = et->keytype->bits / 8; 305655682Smarkm u_char *tmp; 305755682Smarkm 305878536Sassar if(et == NULL) { 305978536Sassar krb5_set_error_string (context, "encryption type %d not supported", 306078536Sassar etype); 306155682Smarkm return KRB5_PROG_ETYPE_NOSUPP; 306278536Sassar } 306355682Smarkm ALLOC(kd.key, 1); 306490929Snectar if(kd.key == NULL) { 306590929Snectar krb5_set_error_string (context, "malloc: out of memory"); 306690929Snectar return ENOMEM; 306790929Snectar } 306890929Snectar ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); 306990929Snectar if(ret) { 307090929Snectar free(kd.key); 307190929Snectar return ret; 307290929Snectar } 307355682Smarkm kd.key->keytype = etype; 307490929Snectar tmp = malloc (keylen); 307590929Snectar if(tmp == NULL) { 307690929Snectar krb5_free_keyblock(context, kd.key); 307790929Snectar krb5_set_error_string (context, "malloc: out of memory"); 307890929Snectar return ENOMEM; 307990929Snectar } 308090929Snectar _krb5_n_fold(str, len, tmp, keylen); 308155682Smarkm kd.schedule = NULL; 308290929Snectar DES3_postproc (context, tmp, keylen, &kd); /* XXX */ 308390929Snectar memset(tmp, 0, keylen); 308490929Snectar free(tmp); 308590929Snectar ret = derive_key(context, 308655682Smarkm et, 308755682Smarkm &kd, 308855682Smarkm "kerberos", /* XXX well known constant */ 308955682Smarkm strlen("kerberos")); 309055682Smarkm ret = krb5_copy_keyblock_contents(context, kd.key, key); 309155682Smarkm free_key_data(context, &kd); 309255682Smarkm return ret; 309355682Smarkm} 309455682Smarkm 309572448Sassarstatic size_t 309672448Sassarwrapped_length (krb5_context context, 309772448Sassar krb5_crypto crypto, 309872448Sassar size_t data_len) 309972448Sassar{ 310072448Sassar struct encryption_type *et = crypto->et; 310172448Sassar size_t blocksize = et->blocksize; 310272448Sassar size_t res; 310372448Sassar 310478536Sassar res = et->confoundersize + et->checksum->checksumsize + data_len; 310572448Sassar res = (res + blocksize - 1) / blocksize * blocksize; 310672448Sassar return res; 310772448Sassar} 310872448Sassar 310972448Sassarstatic size_t 311072448Sassarwrapped_length_dervied (krb5_context context, 311172448Sassar krb5_crypto crypto, 311272448Sassar size_t data_len) 311372448Sassar{ 311472448Sassar struct encryption_type *et = crypto->et; 311572448Sassar size_t blocksize = et->blocksize; 311672448Sassar size_t res; 311772448Sassar 311872448Sassar res = et->confoundersize + data_len; 311972448Sassar res = (res + blocksize - 1) / blocksize * blocksize; 312078536Sassar res += et->checksum->checksumsize; 312172448Sassar return res; 312272448Sassar} 312372448Sassar 312455682Smarkm/* 312555682Smarkm * Return the size of an encrypted packet of length `data_len' 312655682Smarkm */ 312755682Smarkm 312855682Smarkmsize_t 312955682Smarkmkrb5_get_wrapped_length (krb5_context context, 313055682Smarkm krb5_crypto crypto, 313155682Smarkm size_t data_len) 313255682Smarkm{ 313372448Sassar if (derived_crypto (context, crypto)) 313472448Sassar return wrapped_length_dervied (context, crypto, data_len); 313572448Sassar else 313672448Sassar return wrapped_length (context, crypto, data_len); 313755682Smarkm} 313855682Smarkm 313955682Smarkm#ifdef CRYPTO_DEBUG 314055682Smarkm 314155682Smarkmstatic krb5_error_code 314255682Smarkmkrb5_get_keyid(krb5_context context, 314355682Smarkm krb5_keyblock *key, 314455682Smarkm u_int32_t *keyid) 314555682Smarkm{ 314657416Smarkm MD5_CTX md5; 314755682Smarkm unsigned char tmp[16]; 314857416Smarkm 314972448Sassar MD5_Init (&md5); 315072448Sassar MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); 315172448Sassar MD5_Final (tmp, &md5); 315255682Smarkm *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; 315355682Smarkm return 0; 315455682Smarkm} 315555682Smarkm 315655682Smarkmstatic void 315755682Smarkmkrb5_crypto_debug(krb5_context context, 315855682Smarkm int encrypt, 315955682Smarkm size_t len, 316055682Smarkm krb5_keyblock *key) 316155682Smarkm{ 316255682Smarkm u_int32_t keyid; 316355682Smarkm char *kt; 316455682Smarkm krb5_get_keyid(context, key, &keyid); 316555682Smarkm krb5_enctype_to_string(context, key->keytype, &kt); 316655682Smarkm krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", 316755682Smarkm encrypt ? "encrypting" : "decrypting", 316855682Smarkm (unsigned long)len, 316955682Smarkm keyid, 317055682Smarkm kt); 317155682Smarkm free(kt); 317255682Smarkm} 317355682Smarkm 317455682Smarkm#endif /* CRYPTO_DEBUG */ 317572448Sassar 317672448Sassar#if 0 317772448Sassarint 317872448Sassarmain() 317972448Sassar{ 318072448Sassar#if 0 318172448Sassar int i; 318272448Sassar krb5_context context; 318372448Sassar krb5_crypto crypto; 318472448Sassar struct key_data *d; 318572448Sassar krb5_keyblock key; 318672448Sassar char constant[4]; 318772448Sassar unsigned usage = ENCRYPTION_USAGE(3); 318872448Sassar krb5_error_code ret; 318972448Sassar 319072448Sassar ret = krb5_init_context(&context); 319172448Sassar if (ret) 319272448Sassar errx (1, "krb5_init_context failed: %d", ret); 319372448Sassar 319472448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 319572448Sassar key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" 319672448Sassar "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" 319772448Sassar "\xc8\xdf\xab\x26\x86\x64\x15\x25"; 319872448Sassar key.keyvalue.length = 24; 319972448Sassar 320072448Sassar krb5_crypto_init(context, &key, 0, &crypto); 320172448Sassar 320272448Sassar d = _new_derived_key(crypto, usage); 320372448Sassar if(d == NULL) 320472448Sassar return ENOMEM; 320572448Sassar krb5_copy_keyblock(context, crypto->key.key, &d->key); 320672448Sassar _krb5_put_int(constant, usage, 4); 320772448Sassar derive_key(context, crypto->et, d, constant, sizeof(constant)); 320872448Sassar return 0; 320972448Sassar#else 321072448Sassar int i; 321172448Sassar krb5_context context; 321272448Sassar krb5_crypto crypto; 321372448Sassar struct key_data *d; 321472448Sassar krb5_keyblock key; 321572448Sassar krb5_error_code ret; 321672448Sassar Checksum res; 321772448Sassar 321872448Sassar char *data = "what do ya want for nothing?"; 321972448Sassar 322072448Sassar ret = krb5_init_context(&context); 322172448Sassar if (ret) 322272448Sassar errx (1, "krb5_init_context failed: %d", ret); 322372448Sassar 322472448Sassar key.keytype = ETYPE_NEW_DES3_CBC_SHA1; 322572448Sassar key.keyvalue.data = "Jefe"; 322672448Sassar /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 322772448Sassar "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ 322872448Sassar key.keyvalue.length = 4; 322972448Sassar 323072448Sassar d = calloc(1, sizeof(*d)); 323172448Sassar 323272448Sassar d->key = &key; 323372448Sassar res.checksum.length = 20; 323472448Sassar res.checksum.data = malloc(res.checksum.length); 323572448Sassar HMAC_SHA1_DES3_checksum(context, d, data, 28, &res); 323672448Sassar 323772448Sassar return 0; 323872448Sassar#endif 323972448Sassar} 324072448Sassar#endif 3241