1*ebfedea0SLionel Sambuc /* $NetBSD: crypto.c,v 1.1.1.1 2011/04/13 18:15:33 elric Exp $ */ 2*ebfedea0SLionel Sambuc 3*ebfedea0SLionel Sambuc /* 4*ebfedea0SLionel Sambuc * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan 5*ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden). 6*ebfedea0SLionel Sambuc * All rights reserved. 7*ebfedea0SLionel Sambuc * 8*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without 9*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions 10*ebfedea0SLionel Sambuc * are met: 11*ebfedea0SLionel Sambuc * 12*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 13*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer. 14*ebfedea0SLionel Sambuc * 15*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 16*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 17*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution. 18*ebfedea0SLionel Sambuc * 19*ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors 20*ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software 21*ebfedea0SLionel Sambuc * without specific prior written permission. 22*ebfedea0SLionel Sambuc * 23*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24*ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25*ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26*ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27*ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28*ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29*ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30*ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31*ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32*ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33*ebfedea0SLionel Sambuc * SUCH DAMAGE. 34*ebfedea0SLionel Sambuc */ 35*ebfedea0SLionel Sambuc 36*ebfedea0SLionel Sambuc #define KRB5_DEPRECATED 37*ebfedea0SLionel Sambuc 38*ebfedea0SLionel Sambuc #include "krb5_locl.h" 39*ebfedea0SLionel Sambuc 40*ebfedea0SLionel Sambuc struct _krb5_key_usage { 41*ebfedea0SLionel Sambuc unsigned usage; 42*ebfedea0SLionel Sambuc struct _krb5_key_data key; 43*ebfedea0SLionel Sambuc }; 44*ebfedea0SLionel Sambuc 45*ebfedea0SLionel Sambuc 46*ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER 47*ebfedea0SLionel Sambuc #define DES3_OLD_ENCTYPE 1 48*ebfedea0SLionel Sambuc #endif 49*ebfedea0SLionel Sambuc 50*ebfedea0SLionel Sambuc static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 51*ebfedea0SLionel Sambuc unsigned, struct _krb5_key_data**); 52*ebfedea0SLionel Sambuc static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); 53*ebfedea0SLionel Sambuc 54*ebfedea0SLionel Sambuc static void free_key_schedule(krb5_context, 55*ebfedea0SLionel Sambuc struct _krb5_key_data *, 56*ebfedea0SLionel Sambuc struct _krb5_encryption_type *); 57*ebfedea0SLionel Sambuc 58*ebfedea0SLionel Sambuc /************************************************************ 59*ebfedea0SLionel Sambuc * * 60*ebfedea0SLionel Sambuc ************************************************************/ 61*ebfedea0SLionel Sambuc 62*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 63*ebfedea0SLionel Sambuc krb5_enctype_keysize(krb5_context context, 64*ebfedea0SLionel Sambuc krb5_enctype type, 65*ebfedea0SLionel Sambuc size_t *keysize) 66*ebfedea0SLionel Sambuc { 67*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type); 68*ebfedea0SLionel Sambuc if(et == NULL) { 69*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 70*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 71*ebfedea0SLionel Sambuc type); 72*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 73*ebfedea0SLionel Sambuc } 74*ebfedea0SLionel Sambuc *keysize = et->keytype->size; 75*ebfedea0SLionel Sambuc return 0; 76*ebfedea0SLionel Sambuc } 77*ebfedea0SLionel Sambuc 78*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 79*ebfedea0SLionel Sambuc krb5_enctype_keybits(krb5_context context, 80*ebfedea0SLionel Sambuc krb5_enctype type, 81*ebfedea0SLionel Sambuc size_t *keybits) 82*ebfedea0SLionel Sambuc { 83*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type); 84*ebfedea0SLionel Sambuc if(et == NULL) { 85*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 86*ebfedea0SLionel Sambuc "encryption type %d not supported", 87*ebfedea0SLionel Sambuc type); 88*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 89*ebfedea0SLionel Sambuc } 90*ebfedea0SLionel Sambuc *keybits = et->keytype->bits; 91*ebfedea0SLionel Sambuc return 0; 92*ebfedea0SLionel Sambuc } 93*ebfedea0SLionel Sambuc 94*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 95*ebfedea0SLionel Sambuc krb5_generate_random_keyblock(krb5_context context, 96*ebfedea0SLionel Sambuc krb5_enctype type, 97*ebfedea0SLionel Sambuc krb5_keyblock *key) 98*ebfedea0SLionel Sambuc { 99*ebfedea0SLionel Sambuc krb5_error_code ret; 100*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type); 101*ebfedea0SLionel Sambuc if(et == NULL) { 102*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 103*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 104*ebfedea0SLionel Sambuc type); 105*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 106*ebfedea0SLionel Sambuc } 107*ebfedea0SLionel Sambuc ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 108*ebfedea0SLionel Sambuc if(ret) 109*ebfedea0SLionel Sambuc return ret; 110*ebfedea0SLionel Sambuc key->keytype = type; 111*ebfedea0SLionel Sambuc if(et->keytype->random_key) 112*ebfedea0SLionel Sambuc (*et->keytype->random_key)(context, key); 113*ebfedea0SLionel Sambuc else 114*ebfedea0SLionel Sambuc krb5_generate_random_block(key->keyvalue.data, 115*ebfedea0SLionel Sambuc key->keyvalue.length); 116*ebfedea0SLionel Sambuc return 0; 117*ebfedea0SLionel Sambuc } 118*ebfedea0SLionel Sambuc 119*ebfedea0SLionel Sambuc static krb5_error_code 120*ebfedea0SLionel Sambuc _key_schedule(krb5_context context, 121*ebfedea0SLionel Sambuc struct _krb5_key_data *key) 122*ebfedea0SLionel Sambuc { 123*ebfedea0SLionel Sambuc krb5_error_code ret; 124*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype); 125*ebfedea0SLionel Sambuc struct _krb5_key_type *kt; 126*ebfedea0SLionel Sambuc 127*ebfedea0SLionel Sambuc if (et == NULL) { 128*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 129*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 130*ebfedea0SLionel Sambuc key->key->keytype); 131*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 132*ebfedea0SLionel Sambuc } 133*ebfedea0SLionel Sambuc 134*ebfedea0SLionel Sambuc kt = et->keytype; 135*ebfedea0SLionel Sambuc 136*ebfedea0SLionel Sambuc if(kt->schedule == NULL) 137*ebfedea0SLionel Sambuc return 0; 138*ebfedea0SLionel Sambuc if (key->schedule != NULL) 139*ebfedea0SLionel Sambuc return 0; 140*ebfedea0SLionel Sambuc ALLOC(key->schedule, 1); 141*ebfedea0SLionel Sambuc if(key->schedule == NULL) { 142*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 143*ebfedea0SLionel Sambuc return ENOMEM; 144*ebfedea0SLionel Sambuc } 145*ebfedea0SLionel Sambuc ret = krb5_data_alloc(key->schedule, kt->schedule_size); 146*ebfedea0SLionel Sambuc if(ret) { 147*ebfedea0SLionel Sambuc free(key->schedule); 148*ebfedea0SLionel Sambuc key->schedule = NULL; 149*ebfedea0SLionel Sambuc return ret; 150*ebfedea0SLionel Sambuc } 151*ebfedea0SLionel Sambuc (*kt->schedule)(context, kt, key); 152*ebfedea0SLionel Sambuc return 0; 153*ebfedea0SLionel Sambuc } 154*ebfedea0SLionel Sambuc 155*ebfedea0SLionel Sambuc /************************************************************ 156*ebfedea0SLionel Sambuc * * 157*ebfedea0SLionel Sambuc ************************************************************/ 158*ebfedea0SLionel Sambuc 159*ebfedea0SLionel Sambuc static krb5_error_code 160*ebfedea0SLionel Sambuc SHA1_checksum(krb5_context context, 161*ebfedea0SLionel Sambuc struct _krb5_key_data *key, 162*ebfedea0SLionel Sambuc const void *data, 163*ebfedea0SLionel Sambuc size_t len, 164*ebfedea0SLionel Sambuc unsigned usage, 165*ebfedea0SLionel Sambuc Checksum *C) 166*ebfedea0SLionel Sambuc { 167*ebfedea0SLionel Sambuc if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1) 168*ebfedea0SLionel Sambuc krb5_abortx(context, "sha1 checksum failed"); 169*ebfedea0SLionel Sambuc return 0; 170*ebfedea0SLionel Sambuc } 171*ebfedea0SLionel Sambuc 172*ebfedea0SLionel Sambuc /* HMAC according to RFC2104 */ 173*ebfedea0SLionel Sambuc krb5_error_code 174*ebfedea0SLionel Sambuc _krb5_internal_hmac(krb5_context context, 175*ebfedea0SLionel Sambuc struct _krb5_checksum_type *cm, 176*ebfedea0SLionel Sambuc const void *data, 177*ebfedea0SLionel Sambuc size_t len, 178*ebfedea0SLionel Sambuc unsigned usage, 179*ebfedea0SLionel Sambuc struct _krb5_key_data *keyblock, 180*ebfedea0SLionel Sambuc Checksum *result) 181*ebfedea0SLionel Sambuc { 182*ebfedea0SLionel Sambuc unsigned char *ipad, *opad; 183*ebfedea0SLionel Sambuc unsigned char *key; 184*ebfedea0SLionel Sambuc size_t key_len; 185*ebfedea0SLionel Sambuc int i; 186*ebfedea0SLionel Sambuc 187*ebfedea0SLionel Sambuc ipad = malloc(cm->blocksize + len); 188*ebfedea0SLionel Sambuc if (ipad == NULL) 189*ebfedea0SLionel Sambuc return ENOMEM; 190*ebfedea0SLionel Sambuc opad = malloc(cm->blocksize + cm->checksumsize); 191*ebfedea0SLionel Sambuc if (opad == NULL) { 192*ebfedea0SLionel Sambuc free(ipad); 193*ebfedea0SLionel Sambuc return ENOMEM; 194*ebfedea0SLionel Sambuc } 195*ebfedea0SLionel Sambuc memset(ipad, 0x36, cm->blocksize); 196*ebfedea0SLionel Sambuc memset(opad, 0x5c, cm->blocksize); 197*ebfedea0SLionel Sambuc 198*ebfedea0SLionel Sambuc if(keyblock->key->keyvalue.length > cm->blocksize){ 199*ebfedea0SLionel Sambuc (*cm->checksum)(context, 200*ebfedea0SLionel Sambuc keyblock, 201*ebfedea0SLionel Sambuc keyblock->key->keyvalue.data, 202*ebfedea0SLionel Sambuc keyblock->key->keyvalue.length, 203*ebfedea0SLionel Sambuc usage, 204*ebfedea0SLionel Sambuc result); 205*ebfedea0SLionel Sambuc key = result->checksum.data; 206*ebfedea0SLionel Sambuc key_len = result->checksum.length; 207*ebfedea0SLionel Sambuc } else { 208*ebfedea0SLionel Sambuc key = keyblock->key->keyvalue.data; 209*ebfedea0SLionel Sambuc key_len = keyblock->key->keyvalue.length; 210*ebfedea0SLionel Sambuc } 211*ebfedea0SLionel Sambuc for(i = 0; i < key_len; i++){ 212*ebfedea0SLionel Sambuc ipad[i] ^= key[i]; 213*ebfedea0SLionel Sambuc opad[i] ^= key[i]; 214*ebfedea0SLionel Sambuc } 215*ebfedea0SLionel Sambuc memcpy(ipad + cm->blocksize, data, len); 216*ebfedea0SLionel Sambuc (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, 217*ebfedea0SLionel Sambuc usage, result); 218*ebfedea0SLionel Sambuc memcpy(opad + cm->blocksize, result->checksum.data, 219*ebfedea0SLionel Sambuc result->checksum.length); 220*ebfedea0SLionel Sambuc (*cm->checksum)(context, keyblock, opad, 221*ebfedea0SLionel Sambuc cm->blocksize + cm->checksumsize, usage, result); 222*ebfedea0SLionel Sambuc memset(ipad, 0, cm->blocksize + len); 223*ebfedea0SLionel Sambuc free(ipad); 224*ebfedea0SLionel Sambuc memset(opad, 0, cm->blocksize + cm->checksumsize); 225*ebfedea0SLionel Sambuc free(opad); 226*ebfedea0SLionel Sambuc 227*ebfedea0SLionel Sambuc return 0; 228*ebfedea0SLionel Sambuc } 229*ebfedea0SLionel Sambuc 230*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 231*ebfedea0SLionel Sambuc krb5_hmac(krb5_context context, 232*ebfedea0SLionel Sambuc krb5_cksumtype cktype, 233*ebfedea0SLionel Sambuc const void *data, 234*ebfedea0SLionel Sambuc size_t len, 235*ebfedea0SLionel Sambuc unsigned usage, 236*ebfedea0SLionel Sambuc krb5_keyblock *key, 237*ebfedea0SLionel Sambuc Checksum *result) 238*ebfedea0SLionel Sambuc { 239*ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(cktype); 240*ebfedea0SLionel Sambuc struct _krb5_key_data kd; 241*ebfedea0SLionel Sambuc krb5_error_code ret; 242*ebfedea0SLionel Sambuc 243*ebfedea0SLionel Sambuc if (c == NULL) { 244*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 245*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 246*ebfedea0SLionel Sambuc cktype); 247*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 248*ebfedea0SLionel Sambuc } 249*ebfedea0SLionel Sambuc 250*ebfedea0SLionel Sambuc kd.key = key; 251*ebfedea0SLionel Sambuc kd.schedule = NULL; 252*ebfedea0SLionel Sambuc 253*ebfedea0SLionel Sambuc ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result); 254*ebfedea0SLionel Sambuc 255*ebfedea0SLionel Sambuc if (kd.schedule) 256*ebfedea0SLionel Sambuc krb5_free_data(context, kd.schedule); 257*ebfedea0SLionel Sambuc 258*ebfedea0SLionel Sambuc return ret; 259*ebfedea0SLionel Sambuc } 260*ebfedea0SLionel Sambuc 261*ebfedea0SLionel Sambuc krb5_error_code 262*ebfedea0SLionel Sambuc _krb5_SP_HMAC_SHA1_checksum(krb5_context context, 263*ebfedea0SLionel Sambuc struct _krb5_key_data *key, 264*ebfedea0SLionel Sambuc const void *data, 265*ebfedea0SLionel Sambuc size_t len, 266*ebfedea0SLionel Sambuc unsigned usage, 267*ebfedea0SLionel Sambuc Checksum *result) 268*ebfedea0SLionel Sambuc { 269*ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1); 270*ebfedea0SLionel Sambuc Checksum res; 271*ebfedea0SLionel Sambuc char sha1_data[20]; 272*ebfedea0SLionel Sambuc krb5_error_code ret; 273*ebfedea0SLionel Sambuc 274*ebfedea0SLionel Sambuc res.checksum.data = sha1_data; 275*ebfedea0SLionel Sambuc res.checksum.length = sizeof(sha1_data); 276*ebfedea0SLionel Sambuc 277*ebfedea0SLionel Sambuc ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res); 278*ebfedea0SLionel Sambuc if (ret) 279*ebfedea0SLionel Sambuc krb5_abortx(context, "hmac failed"); 280*ebfedea0SLionel Sambuc memcpy(result->checksum.data, res.checksum.data, result->checksum.length); 281*ebfedea0SLionel Sambuc return 0; 282*ebfedea0SLionel Sambuc } 283*ebfedea0SLionel Sambuc 284*ebfedea0SLionel Sambuc struct _krb5_checksum_type _krb5_checksum_sha1 = { 285*ebfedea0SLionel Sambuc CKSUMTYPE_SHA1, 286*ebfedea0SLionel Sambuc "sha1", 287*ebfedea0SLionel Sambuc 64, 288*ebfedea0SLionel Sambuc 20, 289*ebfedea0SLionel Sambuc F_CPROOF, 290*ebfedea0SLionel Sambuc SHA1_checksum, 291*ebfedea0SLionel Sambuc NULL 292*ebfedea0SLionel Sambuc }; 293*ebfedea0SLionel Sambuc 294*ebfedea0SLionel Sambuc struct _krb5_checksum_type * 295*ebfedea0SLionel Sambuc _krb5_find_checksum(krb5_cksumtype type) 296*ebfedea0SLionel Sambuc { 297*ebfedea0SLionel Sambuc int i; 298*ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_checksums; i++) 299*ebfedea0SLionel Sambuc if(_krb5_checksum_types[i]->type == type) 300*ebfedea0SLionel Sambuc return _krb5_checksum_types[i]; 301*ebfedea0SLionel Sambuc return NULL; 302*ebfedea0SLionel Sambuc } 303*ebfedea0SLionel Sambuc 304*ebfedea0SLionel Sambuc static krb5_error_code 305*ebfedea0SLionel Sambuc get_checksum_key(krb5_context context, 306*ebfedea0SLionel Sambuc krb5_crypto crypto, 307*ebfedea0SLionel Sambuc unsigned usage, /* not krb5_key_usage */ 308*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct, 309*ebfedea0SLionel Sambuc struct _krb5_key_data **key) 310*ebfedea0SLionel Sambuc { 311*ebfedea0SLionel Sambuc krb5_error_code ret = 0; 312*ebfedea0SLionel Sambuc 313*ebfedea0SLionel Sambuc if(ct->flags & F_DERIVED) 314*ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, usage, key); 315*ebfedea0SLionel Sambuc else if(ct->flags & F_VARIANT) { 316*ebfedea0SLionel Sambuc int i; 317*ebfedea0SLionel Sambuc 318*ebfedea0SLionel Sambuc *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); 319*ebfedea0SLionel Sambuc if(*key == NULL) { 320*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 321*ebfedea0SLionel Sambuc return ENOMEM; 322*ebfedea0SLionel Sambuc } 323*ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); 324*ebfedea0SLionel Sambuc if(ret) 325*ebfedea0SLionel Sambuc return ret; 326*ebfedea0SLionel Sambuc for(i = 0; i < (*key)->key->keyvalue.length; i++) 327*ebfedea0SLionel Sambuc ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; 328*ebfedea0SLionel Sambuc } else { 329*ebfedea0SLionel Sambuc *key = &crypto->key; 330*ebfedea0SLionel Sambuc } 331*ebfedea0SLionel Sambuc if(ret == 0) 332*ebfedea0SLionel Sambuc ret = _key_schedule(context, *key); 333*ebfedea0SLionel Sambuc return ret; 334*ebfedea0SLionel Sambuc } 335*ebfedea0SLionel Sambuc 336*ebfedea0SLionel Sambuc static krb5_error_code 337*ebfedea0SLionel Sambuc create_checksum (krb5_context context, 338*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct, 339*ebfedea0SLionel Sambuc krb5_crypto crypto, 340*ebfedea0SLionel Sambuc unsigned usage, 341*ebfedea0SLionel Sambuc void *data, 342*ebfedea0SLionel Sambuc size_t len, 343*ebfedea0SLionel Sambuc Checksum *result) 344*ebfedea0SLionel Sambuc { 345*ebfedea0SLionel Sambuc krb5_error_code ret; 346*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 347*ebfedea0SLionel Sambuc int keyed_checksum; 348*ebfedea0SLionel Sambuc 349*ebfedea0SLionel Sambuc if (ct->flags & F_DISABLED) { 350*ebfedea0SLionel Sambuc krb5_clear_error_message (context); 351*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 352*ebfedea0SLionel Sambuc } 353*ebfedea0SLionel Sambuc keyed_checksum = (ct->flags & F_KEYED) != 0; 354*ebfedea0SLionel Sambuc if(keyed_checksum && crypto == NULL) { 355*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 356*ebfedea0SLionel Sambuc N_("Checksum type %s is keyed but no " 357*ebfedea0SLionel Sambuc "crypto context (key) was passed in", ""), 358*ebfedea0SLionel Sambuc ct->name); 359*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 360*ebfedea0SLionel Sambuc } 361*ebfedea0SLionel Sambuc if(keyed_checksum) { 362*ebfedea0SLionel Sambuc ret = get_checksum_key(context, crypto, usage, ct, &dkey); 363*ebfedea0SLionel Sambuc if (ret) 364*ebfedea0SLionel Sambuc return ret; 365*ebfedea0SLionel Sambuc } else 366*ebfedea0SLionel Sambuc dkey = NULL; 367*ebfedea0SLionel Sambuc result->cksumtype = ct->type; 368*ebfedea0SLionel Sambuc ret = krb5_data_alloc(&result->checksum, ct->checksumsize); 369*ebfedea0SLionel Sambuc if (ret) 370*ebfedea0SLionel Sambuc return (ret); 371*ebfedea0SLionel Sambuc return (*ct->checksum)(context, dkey, data, len, usage, result); 372*ebfedea0SLionel Sambuc } 373*ebfedea0SLionel Sambuc 374*ebfedea0SLionel Sambuc static int 375*ebfedea0SLionel Sambuc arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto) 376*ebfedea0SLionel Sambuc { 377*ebfedea0SLionel Sambuc return (ct->type == CKSUMTYPE_HMAC_MD5) && 378*ebfedea0SLionel Sambuc (crypto->key.key->keytype == KEYTYPE_ARCFOUR); 379*ebfedea0SLionel Sambuc } 380*ebfedea0SLionel Sambuc 381*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 382*ebfedea0SLionel Sambuc krb5_create_checksum(krb5_context context, 383*ebfedea0SLionel Sambuc krb5_crypto crypto, 384*ebfedea0SLionel Sambuc krb5_key_usage usage, 385*ebfedea0SLionel Sambuc int type, 386*ebfedea0SLionel Sambuc void *data, 387*ebfedea0SLionel Sambuc size_t len, 388*ebfedea0SLionel Sambuc Checksum *result) 389*ebfedea0SLionel Sambuc { 390*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = NULL; 391*ebfedea0SLionel Sambuc unsigned keyusage; 392*ebfedea0SLionel Sambuc 393*ebfedea0SLionel Sambuc /* type 0 -> pick from crypto */ 394*ebfedea0SLionel Sambuc if (type) { 395*ebfedea0SLionel Sambuc ct = _krb5_find_checksum(type); 396*ebfedea0SLionel Sambuc } else if (crypto) { 397*ebfedea0SLionel Sambuc ct = crypto->et->keyed_checksum; 398*ebfedea0SLionel Sambuc if (ct == NULL) 399*ebfedea0SLionel Sambuc ct = crypto->et->checksum; 400*ebfedea0SLionel Sambuc } 401*ebfedea0SLionel Sambuc 402*ebfedea0SLionel Sambuc if(ct == NULL) { 403*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 404*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 405*ebfedea0SLionel Sambuc type); 406*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 407*ebfedea0SLionel Sambuc } 408*ebfedea0SLionel Sambuc 409*ebfedea0SLionel Sambuc if (arcfour_checksum_p(ct, crypto)) { 410*ebfedea0SLionel Sambuc keyusage = usage; 411*ebfedea0SLionel Sambuc _krb5_usage2arcfour(context, &keyusage); 412*ebfedea0SLionel Sambuc } else 413*ebfedea0SLionel Sambuc keyusage = CHECKSUM_USAGE(usage); 414*ebfedea0SLionel Sambuc 415*ebfedea0SLionel Sambuc return create_checksum(context, ct, crypto, keyusage, 416*ebfedea0SLionel Sambuc data, len, result); 417*ebfedea0SLionel Sambuc } 418*ebfedea0SLionel Sambuc 419*ebfedea0SLionel Sambuc static krb5_error_code 420*ebfedea0SLionel Sambuc verify_checksum(krb5_context context, 421*ebfedea0SLionel Sambuc krb5_crypto crypto, 422*ebfedea0SLionel Sambuc unsigned usage, /* not krb5_key_usage */ 423*ebfedea0SLionel Sambuc void *data, 424*ebfedea0SLionel Sambuc size_t len, 425*ebfedea0SLionel Sambuc Checksum *cksum) 426*ebfedea0SLionel Sambuc { 427*ebfedea0SLionel Sambuc krb5_error_code ret; 428*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 429*ebfedea0SLionel Sambuc int keyed_checksum; 430*ebfedea0SLionel Sambuc Checksum c; 431*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct; 432*ebfedea0SLionel Sambuc 433*ebfedea0SLionel Sambuc ct = _krb5_find_checksum(cksum->cksumtype); 434*ebfedea0SLionel Sambuc if (ct == NULL || (ct->flags & F_DISABLED)) { 435*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 436*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 437*ebfedea0SLionel Sambuc cksum->cksumtype); 438*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 439*ebfedea0SLionel Sambuc } 440*ebfedea0SLionel Sambuc if(ct->checksumsize != cksum->checksum.length) { 441*ebfedea0SLionel Sambuc krb5_clear_error_message (context); 442*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY, 443*ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum type %s, " 444*ebfedea0SLionel Sambuc "length was %u, expected %u", ""), 445*ebfedea0SLionel Sambuc ct->name, (unsigned)cksum->checksum.length, 446*ebfedea0SLionel Sambuc (unsigned)ct->checksumsize); 447*ebfedea0SLionel Sambuc 448*ebfedea0SLionel Sambuc return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ 449*ebfedea0SLionel Sambuc } 450*ebfedea0SLionel Sambuc keyed_checksum = (ct->flags & F_KEYED) != 0; 451*ebfedea0SLionel Sambuc if(keyed_checksum) { 452*ebfedea0SLionel Sambuc struct _krb5_checksum_type *kct; 453*ebfedea0SLionel Sambuc if (crypto == NULL) { 454*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, 455*ebfedea0SLionel Sambuc N_("Checksum type %s is keyed but no " 456*ebfedea0SLionel Sambuc "crypto context (key) was passed in", ""), 457*ebfedea0SLionel Sambuc ct->name); 458*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 459*ebfedea0SLionel Sambuc } 460*ebfedea0SLionel Sambuc kct = crypto->et->keyed_checksum; 461*ebfedea0SLionel Sambuc if (kct != NULL && kct->type != ct->type) { 462*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, 463*ebfedea0SLionel Sambuc N_("Checksum type %s is keyed, but " 464*ebfedea0SLionel Sambuc "the key type %s passed didnt have that checksum " 465*ebfedea0SLionel Sambuc "type as the keyed type", ""), 466*ebfedea0SLionel Sambuc ct->name, crypto->et->name); 467*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 468*ebfedea0SLionel Sambuc } 469*ebfedea0SLionel Sambuc 470*ebfedea0SLionel Sambuc ret = get_checksum_key(context, crypto, usage, ct, &dkey); 471*ebfedea0SLionel Sambuc if (ret) 472*ebfedea0SLionel Sambuc return ret; 473*ebfedea0SLionel Sambuc } else 474*ebfedea0SLionel Sambuc dkey = NULL; 475*ebfedea0SLionel Sambuc 476*ebfedea0SLionel Sambuc /* 477*ebfedea0SLionel Sambuc * If checksum have a verify function, lets use that instead of 478*ebfedea0SLionel Sambuc * calling ->checksum and then compare result. 479*ebfedea0SLionel Sambuc */ 480*ebfedea0SLionel Sambuc 481*ebfedea0SLionel Sambuc if(ct->verify) { 482*ebfedea0SLionel Sambuc ret = (*ct->verify)(context, dkey, data, len, usage, cksum); 483*ebfedea0SLionel Sambuc if (ret) 484*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, 485*ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum " 486*ebfedea0SLionel Sambuc "type %s, key type %s", ""), 487*ebfedea0SLionel Sambuc ct->name, (crypto != NULL)? crypto->et->name : "(none)"); 488*ebfedea0SLionel Sambuc return ret; 489*ebfedea0SLionel Sambuc } 490*ebfedea0SLionel Sambuc 491*ebfedea0SLionel Sambuc ret = krb5_data_alloc (&c.checksum, ct->checksumsize); 492*ebfedea0SLionel Sambuc if (ret) 493*ebfedea0SLionel Sambuc return ret; 494*ebfedea0SLionel Sambuc 495*ebfedea0SLionel Sambuc ret = (*ct->checksum)(context, dkey, data, len, usage, &c); 496*ebfedea0SLionel Sambuc if (ret) { 497*ebfedea0SLionel Sambuc krb5_data_free(&c.checksum); 498*ebfedea0SLionel Sambuc return ret; 499*ebfedea0SLionel Sambuc } 500*ebfedea0SLionel Sambuc 501*ebfedea0SLionel Sambuc if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) { 502*ebfedea0SLionel Sambuc ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 503*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, 504*ebfedea0SLionel Sambuc N_("Decrypt integrity check failed for checksum " 505*ebfedea0SLionel Sambuc "type %s, key type %s", ""), 506*ebfedea0SLionel Sambuc ct->name, crypto ? crypto->et->name : "(unkeyed)"); 507*ebfedea0SLionel Sambuc } else { 508*ebfedea0SLionel Sambuc ret = 0; 509*ebfedea0SLionel Sambuc } 510*ebfedea0SLionel Sambuc krb5_data_free (&c.checksum); 511*ebfedea0SLionel Sambuc return ret; 512*ebfedea0SLionel Sambuc } 513*ebfedea0SLionel Sambuc 514*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 515*ebfedea0SLionel Sambuc krb5_verify_checksum(krb5_context context, 516*ebfedea0SLionel Sambuc krb5_crypto crypto, 517*ebfedea0SLionel Sambuc krb5_key_usage usage, 518*ebfedea0SLionel Sambuc void *data, 519*ebfedea0SLionel Sambuc size_t len, 520*ebfedea0SLionel Sambuc Checksum *cksum) 521*ebfedea0SLionel Sambuc { 522*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct; 523*ebfedea0SLionel Sambuc unsigned keyusage; 524*ebfedea0SLionel Sambuc 525*ebfedea0SLionel Sambuc ct = _krb5_find_checksum(cksum->cksumtype); 526*ebfedea0SLionel Sambuc if(ct == NULL) { 527*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 528*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 529*ebfedea0SLionel Sambuc cksum->cksumtype); 530*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 531*ebfedea0SLionel Sambuc } 532*ebfedea0SLionel Sambuc 533*ebfedea0SLionel Sambuc if (arcfour_checksum_p(ct, crypto)) { 534*ebfedea0SLionel Sambuc keyusage = usage; 535*ebfedea0SLionel Sambuc _krb5_usage2arcfour(context, &keyusage); 536*ebfedea0SLionel Sambuc } else 537*ebfedea0SLionel Sambuc keyusage = CHECKSUM_USAGE(usage); 538*ebfedea0SLionel Sambuc 539*ebfedea0SLionel Sambuc return verify_checksum(context, crypto, keyusage, 540*ebfedea0SLionel Sambuc data, len, cksum); 541*ebfedea0SLionel Sambuc } 542*ebfedea0SLionel Sambuc 543*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 544*ebfedea0SLionel Sambuc krb5_crypto_get_checksum_type(krb5_context context, 545*ebfedea0SLionel Sambuc krb5_crypto crypto, 546*ebfedea0SLionel Sambuc krb5_cksumtype *type) 547*ebfedea0SLionel Sambuc { 548*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = NULL; 549*ebfedea0SLionel Sambuc 550*ebfedea0SLionel Sambuc if (crypto != NULL) { 551*ebfedea0SLionel Sambuc ct = crypto->et->keyed_checksum; 552*ebfedea0SLionel Sambuc if (ct == NULL) 553*ebfedea0SLionel Sambuc ct = crypto->et->checksum; 554*ebfedea0SLionel Sambuc } 555*ebfedea0SLionel Sambuc 556*ebfedea0SLionel Sambuc if (ct == NULL) { 557*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 558*ebfedea0SLionel Sambuc N_("checksum type not found", "")); 559*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 560*ebfedea0SLionel Sambuc } 561*ebfedea0SLionel Sambuc 562*ebfedea0SLionel Sambuc *type = ct->type; 563*ebfedea0SLionel Sambuc 564*ebfedea0SLionel Sambuc return 0; 565*ebfedea0SLionel Sambuc } 566*ebfedea0SLionel Sambuc 567*ebfedea0SLionel Sambuc 568*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 569*ebfedea0SLionel Sambuc krb5_checksumsize(krb5_context context, 570*ebfedea0SLionel Sambuc krb5_cksumtype type, 571*ebfedea0SLionel Sambuc size_t *size) 572*ebfedea0SLionel Sambuc { 573*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 574*ebfedea0SLionel Sambuc if(ct == NULL) { 575*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 576*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 577*ebfedea0SLionel Sambuc type); 578*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 579*ebfedea0SLionel Sambuc } 580*ebfedea0SLionel Sambuc *size = ct->checksumsize; 581*ebfedea0SLionel Sambuc return 0; 582*ebfedea0SLionel Sambuc } 583*ebfedea0SLionel Sambuc 584*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 585*ebfedea0SLionel Sambuc krb5_checksum_is_keyed(krb5_context context, 586*ebfedea0SLionel Sambuc krb5_cksumtype type) 587*ebfedea0SLionel Sambuc { 588*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 589*ebfedea0SLionel Sambuc if(ct == NULL) { 590*ebfedea0SLionel Sambuc if (context) 591*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 592*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 593*ebfedea0SLionel Sambuc type); 594*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 595*ebfedea0SLionel Sambuc } 596*ebfedea0SLionel Sambuc return ct->flags & F_KEYED; 597*ebfedea0SLionel Sambuc } 598*ebfedea0SLionel Sambuc 599*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 600*ebfedea0SLionel Sambuc krb5_checksum_is_collision_proof(krb5_context context, 601*ebfedea0SLionel Sambuc krb5_cksumtype type) 602*ebfedea0SLionel Sambuc { 603*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 604*ebfedea0SLionel Sambuc if(ct == NULL) { 605*ebfedea0SLionel Sambuc if (context) 606*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 607*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 608*ebfedea0SLionel Sambuc type); 609*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 610*ebfedea0SLionel Sambuc } 611*ebfedea0SLionel Sambuc return ct->flags & F_CPROOF; 612*ebfedea0SLionel Sambuc } 613*ebfedea0SLionel Sambuc 614*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 615*ebfedea0SLionel Sambuc krb5_checksum_disable(krb5_context context, 616*ebfedea0SLionel Sambuc krb5_cksumtype type) 617*ebfedea0SLionel Sambuc { 618*ebfedea0SLionel Sambuc struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 619*ebfedea0SLionel Sambuc if(ct == NULL) { 620*ebfedea0SLionel Sambuc if (context) 621*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 622*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 623*ebfedea0SLionel Sambuc type); 624*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 625*ebfedea0SLionel Sambuc } 626*ebfedea0SLionel Sambuc ct->flags |= F_DISABLED; 627*ebfedea0SLionel Sambuc return 0; 628*ebfedea0SLionel Sambuc } 629*ebfedea0SLionel Sambuc 630*ebfedea0SLionel Sambuc /************************************************************ 631*ebfedea0SLionel Sambuc * * 632*ebfedea0SLionel Sambuc ************************************************************/ 633*ebfedea0SLionel Sambuc 634*ebfedea0SLionel Sambuc struct _krb5_encryption_type * 635*ebfedea0SLionel Sambuc _krb5_find_enctype(krb5_enctype type) 636*ebfedea0SLionel Sambuc { 637*ebfedea0SLionel Sambuc int i; 638*ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++) 639*ebfedea0SLionel Sambuc if(_krb5_etypes[i]->type == type) 640*ebfedea0SLionel Sambuc return _krb5_etypes[i]; 641*ebfedea0SLionel Sambuc return NULL; 642*ebfedea0SLionel Sambuc } 643*ebfedea0SLionel Sambuc 644*ebfedea0SLionel Sambuc 645*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 646*ebfedea0SLionel Sambuc krb5_enctype_to_string(krb5_context context, 647*ebfedea0SLionel Sambuc krb5_enctype etype, 648*ebfedea0SLionel Sambuc char **string) 649*ebfedea0SLionel Sambuc { 650*ebfedea0SLionel Sambuc struct _krb5_encryption_type *e; 651*ebfedea0SLionel Sambuc e = _krb5_find_enctype(etype); 652*ebfedea0SLionel Sambuc if(e == NULL) { 653*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 654*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 655*ebfedea0SLionel Sambuc etype); 656*ebfedea0SLionel Sambuc *string = NULL; 657*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 658*ebfedea0SLionel Sambuc } 659*ebfedea0SLionel Sambuc *string = strdup(e->name); 660*ebfedea0SLionel Sambuc if(*string == NULL) { 661*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 662*ebfedea0SLionel Sambuc return ENOMEM; 663*ebfedea0SLionel Sambuc } 664*ebfedea0SLionel Sambuc return 0; 665*ebfedea0SLionel Sambuc } 666*ebfedea0SLionel Sambuc 667*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 668*ebfedea0SLionel Sambuc krb5_string_to_enctype(krb5_context context, 669*ebfedea0SLionel Sambuc const char *string, 670*ebfedea0SLionel Sambuc krb5_enctype *etype) 671*ebfedea0SLionel Sambuc { 672*ebfedea0SLionel Sambuc int i; 673*ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++) 674*ebfedea0SLionel Sambuc if(strcasecmp(_krb5_etypes[i]->name, string) == 0){ 675*ebfedea0SLionel Sambuc *etype = _krb5_etypes[i]->type; 676*ebfedea0SLionel Sambuc return 0; 677*ebfedea0SLionel Sambuc } 678*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 679*ebfedea0SLionel Sambuc N_("encryption type %s not supported", ""), 680*ebfedea0SLionel Sambuc string); 681*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 682*ebfedea0SLionel Sambuc } 683*ebfedea0SLionel Sambuc 684*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 685*ebfedea0SLionel Sambuc krb5_enctype_to_keytype(krb5_context context, 686*ebfedea0SLionel Sambuc krb5_enctype etype, 687*ebfedea0SLionel Sambuc krb5_keytype *keytype) 688*ebfedea0SLionel Sambuc { 689*ebfedea0SLionel Sambuc struct _krb5_encryption_type *e = _krb5_find_enctype(etype); 690*ebfedea0SLionel Sambuc if(e == NULL) { 691*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 692*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 693*ebfedea0SLionel Sambuc etype); 694*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 695*ebfedea0SLionel Sambuc } 696*ebfedea0SLionel Sambuc *keytype = e->keytype->type; /* XXX */ 697*ebfedea0SLionel Sambuc return 0; 698*ebfedea0SLionel Sambuc } 699*ebfedea0SLionel Sambuc 700*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 701*ebfedea0SLionel Sambuc krb5_enctype_valid(krb5_context context, 702*ebfedea0SLionel Sambuc krb5_enctype etype) 703*ebfedea0SLionel Sambuc { 704*ebfedea0SLionel Sambuc struct _krb5_encryption_type *e = _krb5_find_enctype(etype); 705*ebfedea0SLionel Sambuc if(e == NULL) { 706*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 707*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 708*ebfedea0SLionel Sambuc etype); 709*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 710*ebfedea0SLionel Sambuc } 711*ebfedea0SLionel Sambuc if (e->flags & F_DISABLED) { 712*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 713*ebfedea0SLionel Sambuc N_("encryption type %s is disabled", ""), 714*ebfedea0SLionel Sambuc e->name); 715*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 716*ebfedea0SLionel Sambuc } 717*ebfedea0SLionel Sambuc return 0; 718*ebfedea0SLionel Sambuc } 719*ebfedea0SLionel Sambuc 720*ebfedea0SLionel Sambuc /** 721*ebfedea0SLionel Sambuc * Return the coresponding encryption type for a checksum type. 722*ebfedea0SLionel Sambuc * 723*ebfedea0SLionel Sambuc * @param context Kerberos context 724*ebfedea0SLionel Sambuc * @param ctype The checksum type to get the result enctype for 725*ebfedea0SLionel Sambuc * @param etype The returned encryption, when the matching etype is 726*ebfedea0SLionel Sambuc * not found, etype is set to ETYPE_NULL. 727*ebfedea0SLionel Sambuc * 728*ebfedea0SLionel Sambuc * @return Return an error code for an failure or 0 on success. 729*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 730*ebfedea0SLionel Sambuc */ 731*ebfedea0SLionel Sambuc 732*ebfedea0SLionel Sambuc 733*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 734*ebfedea0SLionel Sambuc krb5_cksumtype_to_enctype(krb5_context context, 735*ebfedea0SLionel Sambuc krb5_cksumtype ctype, 736*ebfedea0SLionel Sambuc krb5_enctype *etype) 737*ebfedea0SLionel Sambuc { 738*ebfedea0SLionel Sambuc int i; 739*ebfedea0SLionel Sambuc 740*ebfedea0SLionel Sambuc *etype = ETYPE_NULL; 741*ebfedea0SLionel Sambuc 742*ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++) { 743*ebfedea0SLionel Sambuc if(_krb5_etypes[i]->keyed_checksum && 744*ebfedea0SLionel Sambuc _krb5_etypes[i]->keyed_checksum->type == ctype) 745*ebfedea0SLionel Sambuc { 746*ebfedea0SLionel Sambuc *etype = _krb5_etypes[i]->type; 747*ebfedea0SLionel Sambuc return 0; 748*ebfedea0SLionel Sambuc } 749*ebfedea0SLionel Sambuc } 750*ebfedea0SLionel Sambuc 751*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 752*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 753*ebfedea0SLionel Sambuc (int)ctype); 754*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 755*ebfedea0SLionel Sambuc } 756*ebfedea0SLionel Sambuc 757*ebfedea0SLionel Sambuc 758*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 759*ebfedea0SLionel Sambuc krb5_cksumtype_valid(krb5_context context, 760*ebfedea0SLionel Sambuc krb5_cksumtype ctype) 761*ebfedea0SLionel Sambuc { 762*ebfedea0SLionel Sambuc struct _krb5_checksum_type *c = _krb5_find_checksum(ctype); 763*ebfedea0SLionel Sambuc if (c == NULL) { 764*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 765*ebfedea0SLionel Sambuc N_("checksum type %d not supported", ""), 766*ebfedea0SLionel Sambuc ctype); 767*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 768*ebfedea0SLionel Sambuc } 769*ebfedea0SLionel Sambuc if (c->flags & F_DISABLED) { 770*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 771*ebfedea0SLionel Sambuc N_("checksum type %s is disabled", ""), 772*ebfedea0SLionel Sambuc c->name); 773*ebfedea0SLionel Sambuc return KRB5_PROG_SUMTYPE_NOSUPP; 774*ebfedea0SLionel Sambuc } 775*ebfedea0SLionel Sambuc return 0; 776*ebfedea0SLionel Sambuc } 777*ebfedea0SLionel Sambuc 778*ebfedea0SLionel Sambuc 779*ebfedea0SLionel Sambuc static krb5_boolean 780*ebfedea0SLionel Sambuc derived_crypto(krb5_context context, 781*ebfedea0SLionel Sambuc krb5_crypto crypto) 782*ebfedea0SLionel Sambuc { 783*ebfedea0SLionel Sambuc return (crypto->et->flags & F_DERIVED) != 0; 784*ebfedea0SLionel Sambuc } 785*ebfedea0SLionel Sambuc 786*ebfedea0SLionel Sambuc static krb5_boolean 787*ebfedea0SLionel Sambuc special_crypto(krb5_context context, 788*ebfedea0SLionel Sambuc krb5_crypto crypto) 789*ebfedea0SLionel Sambuc { 790*ebfedea0SLionel Sambuc return (crypto->et->flags & F_SPECIAL) != 0; 791*ebfedea0SLionel Sambuc } 792*ebfedea0SLionel Sambuc 793*ebfedea0SLionel Sambuc #define CHECKSUMSIZE(C) ((C)->checksumsize) 794*ebfedea0SLionel Sambuc #define CHECKSUMTYPE(C) ((C)->type) 795*ebfedea0SLionel Sambuc 796*ebfedea0SLionel Sambuc static krb5_error_code 797*ebfedea0SLionel Sambuc encrypt_internal_derived(krb5_context context, 798*ebfedea0SLionel Sambuc krb5_crypto crypto, 799*ebfedea0SLionel Sambuc unsigned usage, 800*ebfedea0SLionel Sambuc const void *data, 801*ebfedea0SLionel Sambuc size_t len, 802*ebfedea0SLionel Sambuc krb5_data *result, 803*ebfedea0SLionel Sambuc void *ivec) 804*ebfedea0SLionel Sambuc { 805*ebfedea0SLionel Sambuc size_t sz, block_sz, checksum_sz, total_sz; 806*ebfedea0SLionel Sambuc Checksum cksum; 807*ebfedea0SLionel Sambuc unsigned char *p, *q; 808*ebfedea0SLionel Sambuc krb5_error_code ret; 809*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 810*ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et; 811*ebfedea0SLionel Sambuc 812*ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 813*ebfedea0SLionel Sambuc 814*ebfedea0SLionel Sambuc sz = et->confoundersize + len; 815*ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 816*ebfedea0SLionel Sambuc total_sz = block_sz + checksum_sz; 817*ebfedea0SLionel Sambuc p = calloc(1, total_sz); 818*ebfedea0SLionel Sambuc if(p == NULL) { 819*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 820*ebfedea0SLionel Sambuc return ENOMEM; 821*ebfedea0SLionel Sambuc } 822*ebfedea0SLionel Sambuc 823*ebfedea0SLionel Sambuc q = p; 824*ebfedea0SLionel Sambuc krb5_generate_random_block(q, et->confoundersize); /* XXX */ 825*ebfedea0SLionel Sambuc q += et->confoundersize; 826*ebfedea0SLionel Sambuc memcpy(q, data, len); 827*ebfedea0SLionel Sambuc 828*ebfedea0SLionel Sambuc ret = create_checksum(context, 829*ebfedea0SLionel Sambuc et->keyed_checksum, 830*ebfedea0SLionel Sambuc crypto, 831*ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage), 832*ebfedea0SLionel Sambuc p, 833*ebfedea0SLionel Sambuc block_sz, 834*ebfedea0SLionel Sambuc &cksum); 835*ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != checksum_sz) { 836*ebfedea0SLionel Sambuc free_Checksum (&cksum); 837*ebfedea0SLionel Sambuc krb5_clear_error_message (context); 838*ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL; 839*ebfedea0SLionel Sambuc } 840*ebfedea0SLionel Sambuc if(ret) 841*ebfedea0SLionel Sambuc goto fail; 842*ebfedea0SLionel Sambuc memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 843*ebfedea0SLionel Sambuc free_Checksum (&cksum); 844*ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 845*ebfedea0SLionel Sambuc if(ret) 846*ebfedea0SLionel Sambuc goto fail; 847*ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey); 848*ebfedea0SLionel Sambuc if(ret) 849*ebfedea0SLionel Sambuc goto fail; 850*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 851*ebfedea0SLionel Sambuc if (ret) 852*ebfedea0SLionel Sambuc goto fail; 853*ebfedea0SLionel Sambuc result->data = p; 854*ebfedea0SLionel Sambuc result->length = total_sz; 855*ebfedea0SLionel Sambuc return 0; 856*ebfedea0SLionel Sambuc fail: 857*ebfedea0SLionel Sambuc memset(p, 0, total_sz); 858*ebfedea0SLionel Sambuc free(p); 859*ebfedea0SLionel Sambuc return ret; 860*ebfedea0SLionel Sambuc } 861*ebfedea0SLionel Sambuc 862*ebfedea0SLionel Sambuc 863*ebfedea0SLionel Sambuc static krb5_error_code 864*ebfedea0SLionel Sambuc encrypt_internal(krb5_context context, 865*ebfedea0SLionel Sambuc krb5_crypto crypto, 866*ebfedea0SLionel Sambuc const void *data, 867*ebfedea0SLionel Sambuc size_t len, 868*ebfedea0SLionel Sambuc krb5_data *result, 869*ebfedea0SLionel Sambuc void *ivec) 870*ebfedea0SLionel Sambuc { 871*ebfedea0SLionel Sambuc size_t sz, block_sz, checksum_sz; 872*ebfedea0SLionel Sambuc Checksum cksum; 873*ebfedea0SLionel Sambuc unsigned char *p, *q; 874*ebfedea0SLionel Sambuc krb5_error_code ret; 875*ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et; 876*ebfedea0SLionel Sambuc 877*ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->checksum); 878*ebfedea0SLionel Sambuc 879*ebfedea0SLionel Sambuc sz = et->confoundersize + checksum_sz + len; 880*ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 881*ebfedea0SLionel Sambuc p = calloc(1, block_sz); 882*ebfedea0SLionel Sambuc if(p == NULL) { 883*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 884*ebfedea0SLionel Sambuc return ENOMEM; 885*ebfedea0SLionel Sambuc } 886*ebfedea0SLionel Sambuc 887*ebfedea0SLionel Sambuc q = p; 888*ebfedea0SLionel Sambuc krb5_generate_random_block(q, et->confoundersize); /* XXX */ 889*ebfedea0SLionel Sambuc q += et->confoundersize; 890*ebfedea0SLionel Sambuc memset(q, 0, checksum_sz); 891*ebfedea0SLionel Sambuc q += checksum_sz; 892*ebfedea0SLionel Sambuc memcpy(q, data, len); 893*ebfedea0SLionel Sambuc 894*ebfedea0SLionel Sambuc ret = create_checksum(context, 895*ebfedea0SLionel Sambuc et->checksum, 896*ebfedea0SLionel Sambuc crypto, 897*ebfedea0SLionel Sambuc 0, 898*ebfedea0SLionel Sambuc p, 899*ebfedea0SLionel Sambuc block_sz, 900*ebfedea0SLionel Sambuc &cksum); 901*ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != checksum_sz) { 902*ebfedea0SLionel Sambuc krb5_clear_error_message (context); 903*ebfedea0SLionel Sambuc free_Checksum(&cksum); 904*ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL; 905*ebfedea0SLionel Sambuc } 906*ebfedea0SLionel Sambuc if(ret) 907*ebfedea0SLionel Sambuc goto fail; 908*ebfedea0SLionel Sambuc memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); 909*ebfedea0SLionel Sambuc free_Checksum(&cksum); 910*ebfedea0SLionel Sambuc ret = _key_schedule(context, &crypto->key); 911*ebfedea0SLionel Sambuc if(ret) 912*ebfedea0SLionel Sambuc goto fail; 913*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); 914*ebfedea0SLionel Sambuc if (ret) { 915*ebfedea0SLionel Sambuc memset(p, 0, block_sz); 916*ebfedea0SLionel Sambuc free(p); 917*ebfedea0SLionel Sambuc return ret; 918*ebfedea0SLionel Sambuc } 919*ebfedea0SLionel Sambuc result->data = p; 920*ebfedea0SLionel Sambuc result->length = block_sz; 921*ebfedea0SLionel Sambuc return 0; 922*ebfedea0SLionel Sambuc fail: 923*ebfedea0SLionel Sambuc memset(p, 0, block_sz); 924*ebfedea0SLionel Sambuc free(p); 925*ebfedea0SLionel Sambuc return ret; 926*ebfedea0SLionel Sambuc } 927*ebfedea0SLionel Sambuc 928*ebfedea0SLionel Sambuc static krb5_error_code 929*ebfedea0SLionel Sambuc encrypt_internal_special(krb5_context context, 930*ebfedea0SLionel Sambuc krb5_crypto crypto, 931*ebfedea0SLionel Sambuc int usage, 932*ebfedea0SLionel Sambuc const void *data, 933*ebfedea0SLionel Sambuc size_t len, 934*ebfedea0SLionel Sambuc krb5_data *result, 935*ebfedea0SLionel Sambuc void *ivec) 936*ebfedea0SLionel Sambuc { 937*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 938*ebfedea0SLionel Sambuc size_t cksum_sz = CHECKSUMSIZE(et->checksum); 939*ebfedea0SLionel Sambuc size_t sz = len + cksum_sz + et->confoundersize; 940*ebfedea0SLionel Sambuc char *tmp, *p; 941*ebfedea0SLionel Sambuc krb5_error_code ret; 942*ebfedea0SLionel Sambuc 943*ebfedea0SLionel Sambuc tmp = malloc (sz); 944*ebfedea0SLionel Sambuc if (tmp == NULL) { 945*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 946*ebfedea0SLionel Sambuc return ENOMEM; 947*ebfedea0SLionel Sambuc } 948*ebfedea0SLionel Sambuc p = tmp; 949*ebfedea0SLionel Sambuc memset (p, 0, cksum_sz); 950*ebfedea0SLionel Sambuc p += cksum_sz; 951*ebfedea0SLionel Sambuc krb5_generate_random_block(p, et->confoundersize); 952*ebfedea0SLionel Sambuc p += et->confoundersize; 953*ebfedea0SLionel Sambuc memcpy (p, data, len); 954*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); 955*ebfedea0SLionel Sambuc if (ret) { 956*ebfedea0SLionel Sambuc memset(tmp, 0, sz); 957*ebfedea0SLionel Sambuc free(tmp); 958*ebfedea0SLionel Sambuc return ret; 959*ebfedea0SLionel Sambuc } 960*ebfedea0SLionel Sambuc result->data = tmp; 961*ebfedea0SLionel Sambuc result->length = sz; 962*ebfedea0SLionel Sambuc return 0; 963*ebfedea0SLionel Sambuc } 964*ebfedea0SLionel Sambuc 965*ebfedea0SLionel Sambuc static krb5_error_code 966*ebfedea0SLionel Sambuc decrypt_internal_derived(krb5_context context, 967*ebfedea0SLionel Sambuc krb5_crypto crypto, 968*ebfedea0SLionel Sambuc unsigned usage, 969*ebfedea0SLionel Sambuc void *data, 970*ebfedea0SLionel Sambuc size_t len, 971*ebfedea0SLionel Sambuc krb5_data *result, 972*ebfedea0SLionel Sambuc void *ivec) 973*ebfedea0SLionel Sambuc { 974*ebfedea0SLionel Sambuc size_t checksum_sz; 975*ebfedea0SLionel Sambuc Checksum cksum; 976*ebfedea0SLionel Sambuc unsigned char *p; 977*ebfedea0SLionel Sambuc krb5_error_code ret; 978*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 979*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 980*ebfedea0SLionel Sambuc unsigned long l; 981*ebfedea0SLionel Sambuc 982*ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 983*ebfedea0SLionel Sambuc if (len < checksum_sz + et->confoundersize) { 984*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE, 985*ebfedea0SLionel Sambuc N_("Encrypted data shorter then " 986*ebfedea0SLionel Sambuc "checksum + confunder", "")); 987*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 988*ebfedea0SLionel Sambuc } 989*ebfedea0SLionel Sambuc 990*ebfedea0SLionel Sambuc if (((len - checksum_sz) % et->padsize) != 0) { 991*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 992*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 993*ebfedea0SLionel Sambuc } 994*ebfedea0SLionel Sambuc 995*ebfedea0SLionel Sambuc p = malloc(len); 996*ebfedea0SLionel Sambuc if(len != 0 && p == NULL) { 997*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 998*ebfedea0SLionel Sambuc return ENOMEM; 999*ebfedea0SLionel Sambuc } 1000*ebfedea0SLionel Sambuc memcpy(p, data, len); 1001*ebfedea0SLionel Sambuc 1002*ebfedea0SLionel Sambuc len -= checksum_sz; 1003*ebfedea0SLionel Sambuc 1004*ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1005*ebfedea0SLionel Sambuc if(ret) { 1006*ebfedea0SLionel Sambuc free(p); 1007*ebfedea0SLionel Sambuc return ret; 1008*ebfedea0SLionel Sambuc } 1009*ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey); 1010*ebfedea0SLionel Sambuc if(ret) { 1011*ebfedea0SLionel Sambuc free(p); 1012*ebfedea0SLionel Sambuc return ret; 1013*ebfedea0SLionel Sambuc } 1014*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 1015*ebfedea0SLionel Sambuc if (ret) { 1016*ebfedea0SLionel Sambuc free(p); 1017*ebfedea0SLionel Sambuc return ret; 1018*ebfedea0SLionel Sambuc } 1019*ebfedea0SLionel Sambuc 1020*ebfedea0SLionel Sambuc cksum.checksum.data = p + len; 1021*ebfedea0SLionel Sambuc cksum.checksum.length = checksum_sz; 1022*ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1023*ebfedea0SLionel Sambuc 1024*ebfedea0SLionel Sambuc ret = verify_checksum(context, 1025*ebfedea0SLionel Sambuc crypto, 1026*ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage), 1027*ebfedea0SLionel Sambuc p, 1028*ebfedea0SLionel Sambuc len, 1029*ebfedea0SLionel Sambuc &cksum); 1030*ebfedea0SLionel Sambuc if(ret) { 1031*ebfedea0SLionel Sambuc free(p); 1032*ebfedea0SLionel Sambuc return ret; 1033*ebfedea0SLionel Sambuc } 1034*ebfedea0SLionel Sambuc l = len - et->confoundersize; 1035*ebfedea0SLionel Sambuc memmove(p, p + et->confoundersize, l); 1036*ebfedea0SLionel Sambuc result->data = realloc(p, l); 1037*ebfedea0SLionel Sambuc if(result->data == NULL && l != 0) { 1038*ebfedea0SLionel Sambuc free(p); 1039*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1040*ebfedea0SLionel Sambuc return ENOMEM; 1041*ebfedea0SLionel Sambuc } 1042*ebfedea0SLionel Sambuc result->length = l; 1043*ebfedea0SLionel Sambuc return 0; 1044*ebfedea0SLionel Sambuc } 1045*ebfedea0SLionel Sambuc 1046*ebfedea0SLionel Sambuc static krb5_error_code 1047*ebfedea0SLionel Sambuc decrypt_internal(krb5_context context, 1048*ebfedea0SLionel Sambuc krb5_crypto crypto, 1049*ebfedea0SLionel Sambuc void *data, 1050*ebfedea0SLionel Sambuc size_t len, 1051*ebfedea0SLionel Sambuc krb5_data *result, 1052*ebfedea0SLionel Sambuc void *ivec) 1053*ebfedea0SLionel Sambuc { 1054*ebfedea0SLionel Sambuc krb5_error_code ret; 1055*ebfedea0SLionel Sambuc unsigned char *p; 1056*ebfedea0SLionel Sambuc Checksum cksum; 1057*ebfedea0SLionel Sambuc size_t checksum_sz, l; 1058*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 1059*ebfedea0SLionel Sambuc 1060*ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) { 1061*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1062*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1063*ebfedea0SLionel Sambuc } 1064*ebfedea0SLionel Sambuc checksum_sz = CHECKSUMSIZE(et->checksum); 1065*ebfedea0SLionel Sambuc if (len < checksum_sz + et->confoundersize) { 1066*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE, 1067*ebfedea0SLionel Sambuc N_("Encrypted data shorter then " 1068*ebfedea0SLionel Sambuc "checksum + confunder", "")); 1069*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1070*ebfedea0SLionel Sambuc } 1071*ebfedea0SLionel Sambuc 1072*ebfedea0SLionel Sambuc p = malloc(len); 1073*ebfedea0SLionel Sambuc if(len != 0 && p == NULL) { 1074*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1075*ebfedea0SLionel Sambuc return ENOMEM; 1076*ebfedea0SLionel Sambuc } 1077*ebfedea0SLionel Sambuc memcpy(p, data, len); 1078*ebfedea0SLionel Sambuc 1079*ebfedea0SLionel Sambuc ret = _key_schedule(context, &crypto->key); 1080*ebfedea0SLionel Sambuc if(ret) { 1081*ebfedea0SLionel Sambuc free(p); 1082*ebfedea0SLionel Sambuc return ret; 1083*ebfedea0SLionel Sambuc } 1084*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); 1085*ebfedea0SLionel Sambuc if (ret) { 1086*ebfedea0SLionel Sambuc free(p); 1087*ebfedea0SLionel Sambuc return ret; 1088*ebfedea0SLionel Sambuc } 1089*ebfedea0SLionel Sambuc ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); 1090*ebfedea0SLionel Sambuc if(ret) { 1091*ebfedea0SLionel Sambuc free(p); 1092*ebfedea0SLionel Sambuc return ret; 1093*ebfedea0SLionel Sambuc } 1094*ebfedea0SLionel Sambuc memset(p + et->confoundersize, 0, checksum_sz); 1095*ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->checksum); 1096*ebfedea0SLionel Sambuc ret = verify_checksum(context, NULL, 0, p, len, &cksum); 1097*ebfedea0SLionel Sambuc free_Checksum(&cksum); 1098*ebfedea0SLionel Sambuc if(ret) { 1099*ebfedea0SLionel Sambuc free(p); 1100*ebfedea0SLionel Sambuc return ret; 1101*ebfedea0SLionel Sambuc } 1102*ebfedea0SLionel Sambuc l = len - et->confoundersize - checksum_sz; 1103*ebfedea0SLionel Sambuc memmove(p, p + et->confoundersize + checksum_sz, l); 1104*ebfedea0SLionel Sambuc result->data = realloc(p, l); 1105*ebfedea0SLionel Sambuc if(result->data == NULL && l != 0) { 1106*ebfedea0SLionel Sambuc free(p); 1107*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1108*ebfedea0SLionel Sambuc return ENOMEM; 1109*ebfedea0SLionel Sambuc } 1110*ebfedea0SLionel Sambuc result->length = l; 1111*ebfedea0SLionel Sambuc return 0; 1112*ebfedea0SLionel Sambuc } 1113*ebfedea0SLionel Sambuc 1114*ebfedea0SLionel Sambuc static krb5_error_code 1115*ebfedea0SLionel Sambuc decrypt_internal_special(krb5_context context, 1116*ebfedea0SLionel Sambuc krb5_crypto crypto, 1117*ebfedea0SLionel Sambuc int usage, 1118*ebfedea0SLionel Sambuc void *data, 1119*ebfedea0SLionel Sambuc size_t len, 1120*ebfedea0SLionel Sambuc krb5_data *result, 1121*ebfedea0SLionel Sambuc void *ivec) 1122*ebfedea0SLionel Sambuc { 1123*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 1124*ebfedea0SLionel Sambuc size_t cksum_sz = CHECKSUMSIZE(et->checksum); 1125*ebfedea0SLionel Sambuc size_t sz = len - cksum_sz - et->confoundersize; 1126*ebfedea0SLionel Sambuc unsigned char *p; 1127*ebfedea0SLionel Sambuc krb5_error_code ret; 1128*ebfedea0SLionel Sambuc 1129*ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) { 1130*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1131*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1132*ebfedea0SLionel Sambuc } 1133*ebfedea0SLionel Sambuc if (len < cksum_sz + et->confoundersize) { 1134*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE, 1135*ebfedea0SLionel Sambuc N_("Encrypted data shorter then " 1136*ebfedea0SLionel Sambuc "checksum + confunder", "")); 1137*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1138*ebfedea0SLionel Sambuc } 1139*ebfedea0SLionel Sambuc 1140*ebfedea0SLionel Sambuc p = malloc (len); 1141*ebfedea0SLionel Sambuc if (p == NULL) { 1142*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1143*ebfedea0SLionel Sambuc return ENOMEM; 1144*ebfedea0SLionel Sambuc } 1145*ebfedea0SLionel Sambuc memcpy(p, data, len); 1146*ebfedea0SLionel Sambuc 1147*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec); 1148*ebfedea0SLionel Sambuc if (ret) { 1149*ebfedea0SLionel Sambuc free(p); 1150*ebfedea0SLionel Sambuc return ret; 1151*ebfedea0SLionel Sambuc } 1152*ebfedea0SLionel Sambuc 1153*ebfedea0SLionel Sambuc memmove (p, p + cksum_sz + et->confoundersize, sz); 1154*ebfedea0SLionel Sambuc result->data = realloc(p, sz); 1155*ebfedea0SLionel Sambuc if(result->data == NULL && sz != 0) { 1156*ebfedea0SLionel Sambuc free(p); 1157*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1158*ebfedea0SLionel Sambuc return ENOMEM; 1159*ebfedea0SLionel Sambuc } 1160*ebfedea0SLionel Sambuc result->length = sz; 1161*ebfedea0SLionel Sambuc return 0; 1162*ebfedea0SLionel Sambuc } 1163*ebfedea0SLionel Sambuc 1164*ebfedea0SLionel Sambuc static krb5_crypto_iov * 1165*ebfedea0SLionel Sambuc find_iv(krb5_crypto_iov *data, int num_data, int type) 1166*ebfedea0SLionel Sambuc { 1167*ebfedea0SLionel Sambuc int i; 1168*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) 1169*ebfedea0SLionel Sambuc if (data[i].flags == type) 1170*ebfedea0SLionel Sambuc return &data[i]; 1171*ebfedea0SLionel Sambuc return NULL; 1172*ebfedea0SLionel Sambuc } 1173*ebfedea0SLionel Sambuc 1174*ebfedea0SLionel Sambuc /** 1175*ebfedea0SLionel Sambuc * Inline encrypt a kerberos message 1176*ebfedea0SLionel Sambuc * 1177*ebfedea0SLionel Sambuc * @param context Kerberos context 1178*ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context 1179*ebfedea0SLionel Sambuc * @param usage Key usage for this buffer 1180*ebfedea0SLionel Sambuc * @param data array of buffers to process 1181*ebfedea0SLionel Sambuc * @param num_data length of array 1182*ebfedea0SLionel Sambuc * @param ivec initial cbc/cts vector 1183*ebfedea0SLionel Sambuc * 1184*ebfedea0SLionel Sambuc * @return Return an error code or 0. 1185*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 1186*ebfedea0SLionel Sambuc * 1187*ebfedea0SLionel Sambuc * Kerberos encrypted data look like this: 1188*ebfedea0SLionel Sambuc * 1189*ebfedea0SLionel Sambuc * 1. KRB5_CRYPTO_TYPE_HEADER 1190*ebfedea0SLionel Sambuc * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...] 1191*ebfedea0SLionel Sambuc * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver 1192*ebfedea0SLionel Sambuc * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is 1193*ebfedea0SLionel Sambuc * commonly used headers and trailers. 1194*ebfedea0SLionel Sambuc * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1 1195*ebfedea0SLionel Sambuc * 4. KRB5_CRYPTO_TYPE_TRAILER 1196*ebfedea0SLionel Sambuc */ 1197*ebfedea0SLionel Sambuc 1198*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1199*ebfedea0SLionel Sambuc krb5_encrypt_iov_ivec(krb5_context context, 1200*ebfedea0SLionel Sambuc krb5_crypto crypto, 1201*ebfedea0SLionel Sambuc unsigned usage, 1202*ebfedea0SLionel Sambuc krb5_crypto_iov *data, 1203*ebfedea0SLionel Sambuc int num_data, 1204*ebfedea0SLionel Sambuc void *ivec) 1205*ebfedea0SLionel Sambuc { 1206*ebfedea0SLionel Sambuc size_t headersz, trailersz, len; 1207*ebfedea0SLionel Sambuc int i; 1208*ebfedea0SLionel Sambuc size_t sz, block_sz, pad_sz; 1209*ebfedea0SLionel Sambuc Checksum cksum; 1210*ebfedea0SLionel Sambuc unsigned char *p, *q; 1211*ebfedea0SLionel Sambuc krb5_error_code ret; 1212*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 1213*ebfedea0SLionel Sambuc const struct _krb5_encryption_type *et = crypto->et; 1214*ebfedea0SLionel Sambuc krb5_crypto_iov *tiv, *piv, *hiv; 1215*ebfedea0SLionel Sambuc 1216*ebfedea0SLionel Sambuc if (num_data < 0) { 1217*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1218*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1219*ebfedea0SLionel Sambuc } 1220*ebfedea0SLionel Sambuc 1221*ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) { 1222*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1223*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1224*ebfedea0SLionel Sambuc } 1225*ebfedea0SLionel Sambuc 1226*ebfedea0SLionel Sambuc headersz = et->confoundersize; 1227*ebfedea0SLionel Sambuc trailersz = CHECKSUMSIZE(et->keyed_checksum); 1228*ebfedea0SLionel Sambuc 1229*ebfedea0SLionel Sambuc for (len = 0, i = 0; i < num_data; i++) { 1230*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1231*ebfedea0SLionel Sambuc continue; 1232*ebfedea0SLionel Sambuc len += data[i].data.length; 1233*ebfedea0SLionel Sambuc } 1234*ebfedea0SLionel Sambuc 1235*ebfedea0SLionel Sambuc sz = headersz + len; 1236*ebfedea0SLionel Sambuc block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 1237*ebfedea0SLionel Sambuc 1238*ebfedea0SLionel Sambuc pad_sz = block_sz - sz; 1239*ebfedea0SLionel Sambuc 1240*ebfedea0SLionel Sambuc /* header */ 1241*ebfedea0SLionel Sambuc 1242*ebfedea0SLionel Sambuc hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1243*ebfedea0SLionel Sambuc if (hiv == NULL || hiv->data.length != headersz) 1244*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1245*ebfedea0SLionel Sambuc 1246*ebfedea0SLionel Sambuc krb5_generate_random_block(hiv->data.data, hiv->data.length); 1247*ebfedea0SLionel Sambuc 1248*ebfedea0SLionel Sambuc /* padding */ 1249*ebfedea0SLionel Sambuc piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING); 1250*ebfedea0SLionel Sambuc /* its ok to have no TYPE_PADDING if there is no padding */ 1251*ebfedea0SLionel Sambuc if (piv == NULL && pad_sz != 0) 1252*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1253*ebfedea0SLionel Sambuc if (piv) { 1254*ebfedea0SLionel Sambuc if (piv->data.length < pad_sz) 1255*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1256*ebfedea0SLionel Sambuc piv->data.length = pad_sz; 1257*ebfedea0SLionel Sambuc if (pad_sz) 1258*ebfedea0SLionel Sambuc memset(piv->data.data, pad_sz, pad_sz); 1259*ebfedea0SLionel Sambuc else 1260*ebfedea0SLionel Sambuc piv = NULL; 1261*ebfedea0SLionel Sambuc } 1262*ebfedea0SLionel Sambuc 1263*ebfedea0SLionel Sambuc /* trailer */ 1264*ebfedea0SLionel Sambuc tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); 1265*ebfedea0SLionel Sambuc if (tiv == NULL || tiv->data.length != trailersz) 1266*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1267*ebfedea0SLionel Sambuc 1268*ebfedea0SLionel Sambuc /* 1269*ebfedea0SLionel Sambuc * XXX replace with EVP_Sign? at least make create_checksum an iov 1270*ebfedea0SLionel Sambuc * function. 1271*ebfedea0SLionel Sambuc * XXX CTS EVP is broken, can't handle multi buffers :( 1272*ebfedea0SLionel Sambuc */ 1273*ebfedea0SLionel Sambuc 1274*ebfedea0SLionel Sambuc len = block_sz; 1275*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1276*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1277*ebfedea0SLionel Sambuc continue; 1278*ebfedea0SLionel Sambuc len += data[i].data.length; 1279*ebfedea0SLionel Sambuc } 1280*ebfedea0SLionel Sambuc 1281*ebfedea0SLionel Sambuc p = q = malloc(len); 1282*ebfedea0SLionel Sambuc 1283*ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length); 1284*ebfedea0SLionel Sambuc q += hiv->data.length; 1285*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1286*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1287*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1288*ebfedea0SLionel Sambuc continue; 1289*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1290*ebfedea0SLionel Sambuc q += data[i].data.length; 1291*ebfedea0SLionel Sambuc } 1292*ebfedea0SLionel Sambuc if (piv) 1293*ebfedea0SLionel Sambuc memset(q, 0, piv->data.length); 1294*ebfedea0SLionel Sambuc 1295*ebfedea0SLionel Sambuc ret = create_checksum(context, 1296*ebfedea0SLionel Sambuc et->keyed_checksum, 1297*ebfedea0SLionel Sambuc crypto, 1298*ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage), 1299*ebfedea0SLionel Sambuc p, 1300*ebfedea0SLionel Sambuc len, 1301*ebfedea0SLionel Sambuc &cksum); 1302*ebfedea0SLionel Sambuc free(p); 1303*ebfedea0SLionel Sambuc if(ret == 0 && cksum.checksum.length != trailersz) { 1304*ebfedea0SLionel Sambuc free_Checksum (&cksum); 1305*ebfedea0SLionel Sambuc krb5_clear_error_message (context); 1306*ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL; 1307*ebfedea0SLionel Sambuc } 1308*ebfedea0SLionel Sambuc if(ret) 1309*ebfedea0SLionel Sambuc return ret; 1310*ebfedea0SLionel Sambuc 1311*ebfedea0SLionel Sambuc /* save cksum at end */ 1312*ebfedea0SLionel Sambuc memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length); 1313*ebfedea0SLionel Sambuc free_Checksum (&cksum); 1314*ebfedea0SLionel Sambuc 1315*ebfedea0SLionel Sambuc /* XXX replace with EVP_Cipher */ 1316*ebfedea0SLionel Sambuc p = q = malloc(block_sz); 1317*ebfedea0SLionel Sambuc if(p == NULL) 1318*ebfedea0SLionel Sambuc return ENOMEM; 1319*ebfedea0SLionel Sambuc 1320*ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length); 1321*ebfedea0SLionel Sambuc q += hiv->data.length; 1322*ebfedea0SLionel Sambuc 1323*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1324*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1325*ebfedea0SLionel Sambuc continue; 1326*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1327*ebfedea0SLionel Sambuc q += data[i].data.length; 1328*ebfedea0SLionel Sambuc } 1329*ebfedea0SLionel Sambuc if (piv) 1330*ebfedea0SLionel Sambuc memset(q, 0, piv->data.length); 1331*ebfedea0SLionel Sambuc 1332*ebfedea0SLionel Sambuc 1333*ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1334*ebfedea0SLionel Sambuc if(ret) { 1335*ebfedea0SLionel Sambuc free(p); 1336*ebfedea0SLionel Sambuc return ret; 1337*ebfedea0SLionel Sambuc } 1338*ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey); 1339*ebfedea0SLionel Sambuc if(ret) { 1340*ebfedea0SLionel Sambuc free(p); 1341*ebfedea0SLionel Sambuc return ret; 1342*ebfedea0SLionel Sambuc } 1343*ebfedea0SLionel Sambuc 1344*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 1345*ebfedea0SLionel Sambuc if (ret) { 1346*ebfedea0SLionel Sambuc free(p); 1347*ebfedea0SLionel Sambuc return ret; 1348*ebfedea0SLionel Sambuc } 1349*ebfedea0SLionel Sambuc 1350*ebfedea0SLionel Sambuc /* now copy data back to buffers */ 1351*ebfedea0SLionel Sambuc q = p; 1352*ebfedea0SLionel Sambuc 1353*ebfedea0SLionel Sambuc memcpy(hiv->data.data, q, hiv->data.length); 1354*ebfedea0SLionel Sambuc q += hiv->data.length; 1355*ebfedea0SLionel Sambuc 1356*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1357*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1358*ebfedea0SLionel Sambuc continue; 1359*ebfedea0SLionel Sambuc memcpy(data[i].data.data, q, data[i].data.length); 1360*ebfedea0SLionel Sambuc q += data[i].data.length; 1361*ebfedea0SLionel Sambuc } 1362*ebfedea0SLionel Sambuc if (piv) 1363*ebfedea0SLionel Sambuc memcpy(piv->data.data, q, pad_sz); 1364*ebfedea0SLionel Sambuc 1365*ebfedea0SLionel Sambuc free(p); 1366*ebfedea0SLionel Sambuc 1367*ebfedea0SLionel Sambuc return ret; 1368*ebfedea0SLionel Sambuc } 1369*ebfedea0SLionel Sambuc 1370*ebfedea0SLionel Sambuc /** 1371*ebfedea0SLionel Sambuc * Inline decrypt a Kerberos message. 1372*ebfedea0SLionel Sambuc * 1373*ebfedea0SLionel Sambuc * @param context Kerberos context 1374*ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context 1375*ebfedea0SLionel Sambuc * @param usage Key usage for this buffer 1376*ebfedea0SLionel Sambuc * @param data array of buffers to process 1377*ebfedea0SLionel Sambuc * @param num_data length of array 1378*ebfedea0SLionel Sambuc * @param ivec initial cbc/cts vector 1379*ebfedea0SLionel Sambuc * 1380*ebfedea0SLionel Sambuc * @return Return an error code or 0. 1381*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 1382*ebfedea0SLionel Sambuc * 1383*ebfedea0SLionel Sambuc * 1. KRB5_CRYPTO_TYPE_HEADER 1384*ebfedea0SLionel Sambuc * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in 1385*ebfedea0SLionel Sambuc * any order, however the receiver have to aware of the 1386*ebfedea0SLionel Sambuc * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted 1387*ebfedea0SLionel Sambuc * protocol headers and trailers. The output data will be of same 1388*ebfedea0SLionel Sambuc * size as the input data or shorter. 1389*ebfedea0SLionel Sambuc */ 1390*ebfedea0SLionel Sambuc 1391*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1392*ebfedea0SLionel Sambuc krb5_decrypt_iov_ivec(krb5_context context, 1393*ebfedea0SLionel Sambuc krb5_crypto crypto, 1394*ebfedea0SLionel Sambuc unsigned usage, 1395*ebfedea0SLionel Sambuc krb5_crypto_iov *data, 1396*ebfedea0SLionel Sambuc unsigned int num_data, 1397*ebfedea0SLionel Sambuc void *ivec) 1398*ebfedea0SLionel Sambuc { 1399*ebfedea0SLionel Sambuc unsigned int i; 1400*ebfedea0SLionel Sambuc size_t headersz, trailersz, len; 1401*ebfedea0SLionel Sambuc Checksum cksum; 1402*ebfedea0SLionel Sambuc unsigned char *p, *q; 1403*ebfedea0SLionel Sambuc krb5_error_code ret; 1404*ebfedea0SLionel Sambuc struct _krb5_key_data *dkey; 1405*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 1406*ebfedea0SLionel Sambuc krb5_crypto_iov *tiv, *hiv; 1407*ebfedea0SLionel Sambuc 1408*ebfedea0SLionel Sambuc if (num_data < 0) { 1409*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1410*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1411*ebfedea0SLionel Sambuc } 1412*ebfedea0SLionel Sambuc 1413*ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) { 1414*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1415*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1416*ebfedea0SLionel Sambuc } 1417*ebfedea0SLionel Sambuc 1418*ebfedea0SLionel Sambuc headersz = et->confoundersize; 1419*ebfedea0SLionel Sambuc 1420*ebfedea0SLionel Sambuc hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1421*ebfedea0SLionel Sambuc if (hiv == NULL || hiv->data.length != headersz) 1422*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1423*ebfedea0SLionel Sambuc 1424*ebfedea0SLionel Sambuc /* trailer */ 1425*ebfedea0SLionel Sambuc trailersz = CHECKSUMSIZE(et->keyed_checksum); 1426*ebfedea0SLionel Sambuc 1427*ebfedea0SLionel Sambuc tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); 1428*ebfedea0SLionel Sambuc if (tiv->data.length != trailersz) 1429*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1430*ebfedea0SLionel Sambuc 1431*ebfedea0SLionel Sambuc /* Find length of data we will decrypt */ 1432*ebfedea0SLionel Sambuc 1433*ebfedea0SLionel Sambuc len = headersz; 1434*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1435*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1436*ebfedea0SLionel Sambuc continue; 1437*ebfedea0SLionel Sambuc len += data[i].data.length; 1438*ebfedea0SLionel Sambuc } 1439*ebfedea0SLionel Sambuc 1440*ebfedea0SLionel Sambuc if ((len % et->padsize) != 0) { 1441*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1442*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1443*ebfedea0SLionel Sambuc } 1444*ebfedea0SLionel Sambuc 1445*ebfedea0SLionel Sambuc /* XXX replace with EVP_Cipher */ 1446*ebfedea0SLionel Sambuc 1447*ebfedea0SLionel Sambuc p = q = malloc(len); 1448*ebfedea0SLionel Sambuc if (p == NULL) 1449*ebfedea0SLionel Sambuc return ENOMEM; 1450*ebfedea0SLionel Sambuc 1451*ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length); 1452*ebfedea0SLionel Sambuc q += hiv->data.length; 1453*ebfedea0SLionel Sambuc 1454*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1455*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1456*ebfedea0SLionel Sambuc continue; 1457*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1458*ebfedea0SLionel Sambuc q += data[i].data.length; 1459*ebfedea0SLionel Sambuc } 1460*ebfedea0SLionel Sambuc 1461*ebfedea0SLionel Sambuc ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1462*ebfedea0SLionel Sambuc if(ret) { 1463*ebfedea0SLionel Sambuc free(p); 1464*ebfedea0SLionel Sambuc return ret; 1465*ebfedea0SLionel Sambuc } 1466*ebfedea0SLionel Sambuc ret = _key_schedule(context, dkey); 1467*ebfedea0SLionel Sambuc if(ret) { 1468*ebfedea0SLionel Sambuc free(p); 1469*ebfedea0SLionel Sambuc return ret; 1470*ebfedea0SLionel Sambuc } 1471*ebfedea0SLionel Sambuc 1472*ebfedea0SLionel Sambuc ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 1473*ebfedea0SLionel Sambuc if (ret) { 1474*ebfedea0SLionel Sambuc free(p); 1475*ebfedea0SLionel Sambuc return ret; 1476*ebfedea0SLionel Sambuc } 1477*ebfedea0SLionel Sambuc 1478*ebfedea0SLionel Sambuc /* copy data back to buffers */ 1479*ebfedea0SLionel Sambuc memcpy(hiv->data.data, p, hiv->data.length); 1480*ebfedea0SLionel Sambuc q = p + hiv->data.length; 1481*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1482*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1483*ebfedea0SLionel Sambuc continue; 1484*ebfedea0SLionel Sambuc memcpy(data[i].data.data, q, data[i].data.length); 1485*ebfedea0SLionel Sambuc q += data[i].data.length; 1486*ebfedea0SLionel Sambuc } 1487*ebfedea0SLionel Sambuc 1488*ebfedea0SLionel Sambuc free(p); 1489*ebfedea0SLionel Sambuc 1490*ebfedea0SLionel Sambuc /* check signature */ 1491*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1492*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1493*ebfedea0SLionel Sambuc continue; 1494*ebfedea0SLionel Sambuc len += data[i].data.length; 1495*ebfedea0SLionel Sambuc } 1496*ebfedea0SLionel Sambuc 1497*ebfedea0SLionel Sambuc p = q = malloc(len); 1498*ebfedea0SLionel Sambuc if (p == NULL) 1499*ebfedea0SLionel Sambuc return ENOMEM; 1500*ebfedea0SLionel Sambuc 1501*ebfedea0SLionel Sambuc memcpy(q, hiv->data.data, hiv->data.length); 1502*ebfedea0SLionel Sambuc q += hiv->data.length; 1503*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1504*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1505*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1506*ebfedea0SLionel Sambuc continue; 1507*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1508*ebfedea0SLionel Sambuc q += data[i].data.length; 1509*ebfedea0SLionel Sambuc } 1510*ebfedea0SLionel Sambuc 1511*ebfedea0SLionel Sambuc cksum.checksum.data = tiv->data.data; 1512*ebfedea0SLionel Sambuc cksum.checksum.length = tiv->data.length; 1513*ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1514*ebfedea0SLionel Sambuc 1515*ebfedea0SLionel Sambuc ret = verify_checksum(context, 1516*ebfedea0SLionel Sambuc crypto, 1517*ebfedea0SLionel Sambuc INTEGRITY_USAGE(usage), 1518*ebfedea0SLionel Sambuc p, 1519*ebfedea0SLionel Sambuc len, 1520*ebfedea0SLionel Sambuc &cksum); 1521*ebfedea0SLionel Sambuc free(p); 1522*ebfedea0SLionel Sambuc return ret; 1523*ebfedea0SLionel Sambuc } 1524*ebfedea0SLionel Sambuc 1525*ebfedea0SLionel Sambuc /** 1526*ebfedea0SLionel Sambuc * Create a Kerberos message checksum. 1527*ebfedea0SLionel Sambuc * 1528*ebfedea0SLionel Sambuc * @param context Kerberos context 1529*ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context 1530*ebfedea0SLionel Sambuc * @param usage Key usage for this buffer 1531*ebfedea0SLionel Sambuc * @param data array of buffers to process 1532*ebfedea0SLionel Sambuc * @param num_data length of array 1533*ebfedea0SLionel Sambuc * @param type output data 1534*ebfedea0SLionel Sambuc * 1535*ebfedea0SLionel Sambuc * @return Return an error code or 0. 1536*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 1537*ebfedea0SLionel Sambuc */ 1538*ebfedea0SLionel Sambuc 1539*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1540*ebfedea0SLionel Sambuc krb5_create_checksum_iov(krb5_context context, 1541*ebfedea0SLionel Sambuc krb5_crypto crypto, 1542*ebfedea0SLionel Sambuc unsigned usage, 1543*ebfedea0SLionel Sambuc krb5_crypto_iov *data, 1544*ebfedea0SLionel Sambuc unsigned int num_data, 1545*ebfedea0SLionel Sambuc krb5_cksumtype *type) 1546*ebfedea0SLionel Sambuc { 1547*ebfedea0SLionel Sambuc Checksum cksum; 1548*ebfedea0SLionel Sambuc krb5_crypto_iov *civ; 1549*ebfedea0SLionel Sambuc krb5_error_code ret; 1550*ebfedea0SLionel Sambuc int i; 1551*ebfedea0SLionel Sambuc size_t len; 1552*ebfedea0SLionel Sambuc char *p, *q; 1553*ebfedea0SLionel Sambuc 1554*ebfedea0SLionel Sambuc if (num_data < 0) { 1555*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1556*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1557*ebfedea0SLionel Sambuc } 1558*ebfedea0SLionel Sambuc 1559*ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) { 1560*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1561*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1562*ebfedea0SLionel Sambuc } 1563*ebfedea0SLionel Sambuc 1564*ebfedea0SLionel Sambuc civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); 1565*ebfedea0SLionel Sambuc if (civ == NULL) 1566*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1567*ebfedea0SLionel Sambuc 1568*ebfedea0SLionel Sambuc len = 0; 1569*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1570*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1571*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1572*ebfedea0SLionel Sambuc continue; 1573*ebfedea0SLionel Sambuc len += data[i].data.length; 1574*ebfedea0SLionel Sambuc } 1575*ebfedea0SLionel Sambuc 1576*ebfedea0SLionel Sambuc p = q = malloc(len); 1577*ebfedea0SLionel Sambuc 1578*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1579*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1580*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1581*ebfedea0SLionel Sambuc continue; 1582*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1583*ebfedea0SLionel Sambuc q += data[i].data.length; 1584*ebfedea0SLionel Sambuc } 1585*ebfedea0SLionel Sambuc 1586*ebfedea0SLionel Sambuc ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum); 1587*ebfedea0SLionel Sambuc free(p); 1588*ebfedea0SLionel Sambuc if (ret) 1589*ebfedea0SLionel Sambuc return ret; 1590*ebfedea0SLionel Sambuc 1591*ebfedea0SLionel Sambuc if (type) 1592*ebfedea0SLionel Sambuc *type = cksum.cksumtype; 1593*ebfedea0SLionel Sambuc 1594*ebfedea0SLionel Sambuc if (cksum.checksum.length > civ->data.length) { 1595*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_BAD_MSIZE, 1596*ebfedea0SLionel Sambuc N_("Checksum larger then input buffer", "")); 1597*ebfedea0SLionel Sambuc free_Checksum(&cksum); 1598*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1599*ebfedea0SLionel Sambuc } 1600*ebfedea0SLionel Sambuc 1601*ebfedea0SLionel Sambuc civ->data.length = cksum.checksum.length; 1602*ebfedea0SLionel Sambuc memcpy(civ->data.data, cksum.checksum.data, civ->data.length); 1603*ebfedea0SLionel Sambuc free_Checksum(&cksum); 1604*ebfedea0SLionel Sambuc 1605*ebfedea0SLionel Sambuc return 0; 1606*ebfedea0SLionel Sambuc } 1607*ebfedea0SLionel Sambuc 1608*ebfedea0SLionel Sambuc /** 1609*ebfedea0SLionel Sambuc * Verify a Kerberos message checksum. 1610*ebfedea0SLionel Sambuc * 1611*ebfedea0SLionel Sambuc * @param context Kerberos context 1612*ebfedea0SLionel Sambuc * @param crypto Kerberos crypto context 1613*ebfedea0SLionel Sambuc * @param usage Key usage for this buffer 1614*ebfedea0SLionel Sambuc * @param data array of buffers to process 1615*ebfedea0SLionel Sambuc * @param num_data length of array 1616*ebfedea0SLionel Sambuc * @param type return checksum type if not NULL 1617*ebfedea0SLionel Sambuc * 1618*ebfedea0SLionel Sambuc * @return Return an error code or 0. 1619*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 1620*ebfedea0SLionel Sambuc */ 1621*ebfedea0SLionel Sambuc 1622*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1623*ebfedea0SLionel Sambuc krb5_verify_checksum_iov(krb5_context context, 1624*ebfedea0SLionel Sambuc krb5_crypto crypto, 1625*ebfedea0SLionel Sambuc unsigned usage, 1626*ebfedea0SLionel Sambuc krb5_crypto_iov *data, 1627*ebfedea0SLionel Sambuc unsigned int num_data, 1628*ebfedea0SLionel Sambuc krb5_cksumtype *type) 1629*ebfedea0SLionel Sambuc { 1630*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 1631*ebfedea0SLionel Sambuc Checksum cksum; 1632*ebfedea0SLionel Sambuc krb5_crypto_iov *civ; 1633*ebfedea0SLionel Sambuc krb5_error_code ret; 1634*ebfedea0SLionel Sambuc int i; 1635*ebfedea0SLionel Sambuc size_t len; 1636*ebfedea0SLionel Sambuc char *p, *q; 1637*ebfedea0SLionel Sambuc 1638*ebfedea0SLionel Sambuc if (num_data < 0) { 1639*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1640*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1641*ebfedea0SLionel Sambuc } 1642*ebfedea0SLionel Sambuc 1643*ebfedea0SLionel Sambuc if(!derived_crypto(context, crypto)) { 1644*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 1645*ebfedea0SLionel Sambuc return KRB5_CRYPTO_INTERNAL; 1646*ebfedea0SLionel Sambuc } 1647*ebfedea0SLionel Sambuc 1648*ebfedea0SLionel Sambuc civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); 1649*ebfedea0SLionel Sambuc if (civ == NULL) 1650*ebfedea0SLionel Sambuc return KRB5_BAD_MSIZE; 1651*ebfedea0SLionel Sambuc 1652*ebfedea0SLionel Sambuc len = 0; 1653*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1654*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1655*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1656*ebfedea0SLionel Sambuc continue; 1657*ebfedea0SLionel Sambuc len += data[i].data.length; 1658*ebfedea0SLionel Sambuc } 1659*ebfedea0SLionel Sambuc 1660*ebfedea0SLionel Sambuc p = q = malloc(len); 1661*ebfedea0SLionel Sambuc 1662*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1663*ebfedea0SLionel Sambuc if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1664*ebfedea0SLionel Sambuc data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1665*ebfedea0SLionel Sambuc continue; 1666*ebfedea0SLionel Sambuc memcpy(q, data[i].data.data, data[i].data.length); 1667*ebfedea0SLionel Sambuc q += data[i].data.length; 1668*ebfedea0SLionel Sambuc } 1669*ebfedea0SLionel Sambuc 1670*ebfedea0SLionel Sambuc cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1671*ebfedea0SLionel Sambuc cksum.checksum.length = civ->data.length; 1672*ebfedea0SLionel Sambuc cksum.checksum.data = civ->data.data; 1673*ebfedea0SLionel Sambuc 1674*ebfedea0SLionel Sambuc ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum); 1675*ebfedea0SLionel Sambuc free(p); 1676*ebfedea0SLionel Sambuc 1677*ebfedea0SLionel Sambuc if (ret == 0 && type) 1678*ebfedea0SLionel Sambuc *type = cksum.cksumtype; 1679*ebfedea0SLionel Sambuc 1680*ebfedea0SLionel Sambuc return ret; 1681*ebfedea0SLionel Sambuc } 1682*ebfedea0SLionel Sambuc 1683*ebfedea0SLionel Sambuc 1684*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1685*ebfedea0SLionel Sambuc krb5_crypto_length(krb5_context context, 1686*ebfedea0SLionel Sambuc krb5_crypto crypto, 1687*ebfedea0SLionel Sambuc int type, 1688*ebfedea0SLionel Sambuc size_t *len) 1689*ebfedea0SLionel Sambuc { 1690*ebfedea0SLionel Sambuc if (!derived_crypto(context, crypto)) { 1691*ebfedea0SLionel Sambuc krb5_set_error_message(context, EINVAL, "not a derived crypto"); 1692*ebfedea0SLionel Sambuc return EINVAL; 1693*ebfedea0SLionel Sambuc } 1694*ebfedea0SLionel Sambuc 1695*ebfedea0SLionel Sambuc switch(type) { 1696*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_EMPTY: 1697*ebfedea0SLionel Sambuc *len = 0; 1698*ebfedea0SLionel Sambuc return 0; 1699*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_HEADER: 1700*ebfedea0SLionel Sambuc *len = crypto->et->blocksize; 1701*ebfedea0SLionel Sambuc return 0; 1702*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_DATA: 1703*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_SIGN_ONLY: 1704*ebfedea0SLionel Sambuc /* len must already been filled in */ 1705*ebfedea0SLionel Sambuc return 0; 1706*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_PADDING: 1707*ebfedea0SLionel Sambuc if (crypto->et->padsize > 1) 1708*ebfedea0SLionel Sambuc *len = crypto->et->padsize; 1709*ebfedea0SLionel Sambuc else 1710*ebfedea0SLionel Sambuc *len = 0; 1711*ebfedea0SLionel Sambuc return 0; 1712*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_TRAILER: 1713*ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->keyed_checksum); 1714*ebfedea0SLionel Sambuc return 0; 1715*ebfedea0SLionel Sambuc case KRB5_CRYPTO_TYPE_CHECKSUM: 1716*ebfedea0SLionel Sambuc if (crypto->et->keyed_checksum) 1717*ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->keyed_checksum); 1718*ebfedea0SLionel Sambuc else 1719*ebfedea0SLionel Sambuc *len = CHECKSUMSIZE(crypto->et->checksum); 1720*ebfedea0SLionel Sambuc return 0; 1721*ebfedea0SLionel Sambuc } 1722*ebfedea0SLionel Sambuc krb5_set_error_message(context, EINVAL, 1723*ebfedea0SLionel Sambuc "%d not a supported type", type); 1724*ebfedea0SLionel Sambuc return EINVAL; 1725*ebfedea0SLionel Sambuc } 1726*ebfedea0SLionel Sambuc 1727*ebfedea0SLionel Sambuc 1728*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1729*ebfedea0SLionel Sambuc krb5_crypto_length_iov(krb5_context context, 1730*ebfedea0SLionel Sambuc krb5_crypto crypto, 1731*ebfedea0SLionel Sambuc krb5_crypto_iov *data, 1732*ebfedea0SLionel Sambuc unsigned int num_data) 1733*ebfedea0SLionel Sambuc { 1734*ebfedea0SLionel Sambuc krb5_error_code ret; 1735*ebfedea0SLionel Sambuc int i; 1736*ebfedea0SLionel Sambuc 1737*ebfedea0SLionel Sambuc for (i = 0; i < num_data; i++) { 1738*ebfedea0SLionel Sambuc ret = krb5_crypto_length(context, crypto, 1739*ebfedea0SLionel Sambuc data[i].flags, 1740*ebfedea0SLionel Sambuc &data[i].data.length); 1741*ebfedea0SLionel Sambuc if (ret) 1742*ebfedea0SLionel Sambuc return ret; 1743*ebfedea0SLionel Sambuc } 1744*ebfedea0SLionel Sambuc return 0; 1745*ebfedea0SLionel Sambuc } 1746*ebfedea0SLionel Sambuc 1747*ebfedea0SLionel Sambuc 1748*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1749*ebfedea0SLionel Sambuc krb5_encrypt_ivec(krb5_context context, 1750*ebfedea0SLionel Sambuc krb5_crypto crypto, 1751*ebfedea0SLionel Sambuc unsigned usage, 1752*ebfedea0SLionel Sambuc const void *data, 1753*ebfedea0SLionel Sambuc size_t len, 1754*ebfedea0SLionel Sambuc krb5_data *result, 1755*ebfedea0SLionel Sambuc void *ivec) 1756*ebfedea0SLionel Sambuc { 1757*ebfedea0SLionel Sambuc if(derived_crypto(context, crypto)) 1758*ebfedea0SLionel Sambuc return encrypt_internal_derived(context, crypto, usage, 1759*ebfedea0SLionel Sambuc data, len, result, ivec); 1760*ebfedea0SLionel Sambuc else if (special_crypto(context, crypto)) 1761*ebfedea0SLionel Sambuc return encrypt_internal_special (context, crypto, usage, 1762*ebfedea0SLionel Sambuc data, len, result, ivec); 1763*ebfedea0SLionel Sambuc else 1764*ebfedea0SLionel Sambuc return encrypt_internal(context, crypto, data, len, result, ivec); 1765*ebfedea0SLionel Sambuc } 1766*ebfedea0SLionel Sambuc 1767*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1768*ebfedea0SLionel Sambuc krb5_encrypt(krb5_context context, 1769*ebfedea0SLionel Sambuc krb5_crypto crypto, 1770*ebfedea0SLionel Sambuc unsigned usage, 1771*ebfedea0SLionel Sambuc const void *data, 1772*ebfedea0SLionel Sambuc size_t len, 1773*ebfedea0SLionel Sambuc krb5_data *result) 1774*ebfedea0SLionel Sambuc { 1775*ebfedea0SLionel Sambuc return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); 1776*ebfedea0SLionel Sambuc } 1777*ebfedea0SLionel Sambuc 1778*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1779*ebfedea0SLionel Sambuc krb5_encrypt_EncryptedData(krb5_context context, 1780*ebfedea0SLionel Sambuc krb5_crypto crypto, 1781*ebfedea0SLionel Sambuc unsigned usage, 1782*ebfedea0SLionel Sambuc void *data, 1783*ebfedea0SLionel Sambuc size_t len, 1784*ebfedea0SLionel Sambuc int kvno, 1785*ebfedea0SLionel Sambuc EncryptedData *result) 1786*ebfedea0SLionel Sambuc { 1787*ebfedea0SLionel Sambuc result->etype = CRYPTO_ETYPE(crypto); 1788*ebfedea0SLionel Sambuc if(kvno){ 1789*ebfedea0SLionel Sambuc ALLOC(result->kvno, 1); 1790*ebfedea0SLionel Sambuc *result->kvno = kvno; 1791*ebfedea0SLionel Sambuc }else 1792*ebfedea0SLionel Sambuc result->kvno = NULL; 1793*ebfedea0SLionel Sambuc return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); 1794*ebfedea0SLionel Sambuc } 1795*ebfedea0SLionel Sambuc 1796*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1797*ebfedea0SLionel Sambuc krb5_decrypt_ivec(krb5_context context, 1798*ebfedea0SLionel Sambuc krb5_crypto crypto, 1799*ebfedea0SLionel Sambuc unsigned usage, 1800*ebfedea0SLionel Sambuc void *data, 1801*ebfedea0SLionel Sambuc size_t len, 1802*ebfedea0SLionel Sambuc krb5_data *result, 1803*ebfedea0SLionel Sambuc void *ivec) 1804*ebfedea0SLionel Sambuc { 1805*ebfedea0SLionel Sambuc if(derived_crypto(context, crypto)) 1806*ebfedea0SLionel Sambuc return decrypt_internal_derived(context, crypto, usage, 1807*ebfedea0SLionel Sambuc data, len, result, ivec); 1808*ebfedea0SLionel Sambuc else if (special_crypto (context, crypto)) 1809*ebfedea0SLionel Sambuc return decrypt_internal_special(context, crypto, usage, 1810*ebfedea0SLionel Sambuc data, len, result, ivec); 1811*ebfedea0SLionel Sambuc else 1812*ebfedea0SLionel Sambuc return decrypt_internal(context, crypto, data, len, result, ivec); 1813*ebfedea0SLionel Sambuc } 1814*ebfedea0SLionel Sambuc 1815*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1816*ebfedea0SLionel Sambuc krb5_decrypt(krb5_context context, 1817*ebfedea0SLionel Sambuc krb5_crypto crypto, 1818*ebfedea0SLionel Sambuc unsigned usage, 1819*ebfedea0SLionel Sambuc void *data, 1820*ebfedea0SLionel Sambuc size_t len, 1821*ebfedea0SLionel Sambuc krb5_data *result) 1822*ebfedea0SLionel Sambuc { 1823*ebfedea0SLionel Sambuc return krb5_decrypt_ivec (context, crypto, usage, data, len, result, 1824*ebfedea0SLionel Sambuc NULL); 1825*ebfedea0SLionel Sambuc } 1826*ebfedea0SLionel Sambuc 1827*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1828*ebfedea0SLionel Sambuc krb5_decrypt_EncryptedData(krb5_context context, 1829*ebfedea0SLionel Sambuc krb5_crypto crypto, 1830*ebfedea0SLionel Sambuc unsigned usage, 1831*ebfedea0SLionel Sambuc const EncryptedData *e, 1832*ebfedea0SLionel Sambuc krb5_data *result) 1833*ebfedea0SLionel Sambuc { 1834*ebfedea0SLionel Sambuc return krb5_decrypt(context, crypto, usage, 1835*ebfedea0SLionel Sambuc e->cipher.data, e->cipher.length, result); 1836*ebfedea0SLionel Sambuc } 1837*ebfedea0SLionel Sambuc 1838*ebfedea0SLionel Sambuc /************************************************************ 1839*ebfedea0SLionel Sambuc * * 1840*ebfedea0SLionel Sambuc ************************************************************/ 1841*ebfedea0SLionel Sambuc 1842*ebfedea0SLionel Sambuc krb5_error_code 1843*ebfedea0SLionel Sambuc _krb5_derive_key(krb5_context context, 1844*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et, 1845*ebfedea0SLionel Sambuc struct _krb5_key_data *key, 1846*ebfedea0SLionel Sambuc const void *constant, 1847*ebfedea0SLionel Sambuc size_t len) 1848*ebfedea0SLionel Sambuc { 1849*ebfedea0SLionel Sambuc unsigned char *k = NULL; 1850*ebfedea0SLionel Sambuc unsigned int nblocks = 0, i; 1851*ebfedea0SLionel Sambuc krb5_error_code ret = 0; 1852*ebfedea0SLionel Sambuc struct _krb5_key_type *kt = et->keytype; 1853*ebfedea0SLionel Sambuc 1854*ebfedea0SLionel Sambuc ret = _key_schedule(context, key); 1855*ebfedea0SLionel Sambuc if(ret) 1856*ebfedea0SLionel Sambuc return ret; 1857*ebfedea0SLionel Sambuc if(et->blocksize * 8 < kt->bits || len != et->blocksize) { 1858*ebfedea0SLionel Sambuc nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); 1859*ebfedea0SLionel Sambuc k = malloc(nblocks * et->blocksize); 1860*ebfedea0SLionel Sambuc if(k == NULL) { 1861*ebfedea0SLionel Sambuc ret = ENOMEM; 1862*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1863*ebfedea0SLionel Sambuc goto out; 1864*ebfedea0SLionel Sambuc } 1865*ebfedea0SLionel Sambuc ret = _krb5_n_fold(constant, len, k, et->blocksize); 1866*ebfedea0SLionel Sambuc if (ret) { 1867*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1868*ebfedea0SLionel Sambuc goto out; 1869*ebfedea0SLionel Sambuc } 1870*ebfedea0SLionel Sambuc 1871*ebfedea0SLionel Sambuc for(i = 0; i < nblocks; i++) { 1872*ebfedea0SLionel Sambuc if(i > 0) 1873*ebfedea0SLionel Sambuc memcpy(k + i * et->blocksize, 1874*ebfedea0SLionel Sambuc k + (i - 1) * et->blocksize, 1875*ebfedea0SLionel Sambuc et->blocksize); 1876*ebfedea0SLionel Sambuc (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, 1877*ebfedea0SLionel Sambuc 1, 0, NULL); 1878*ebfedea0SLionel Sambuc } 1879*ebfedea0SLionel Sambuc } else { 1880*ebfedea0SLionel Sambuc /* this case is probably broken, but won't be run anyway */ 1881*ebfedea0SLionel Sambuc void *c = malloc(len); 1882*ebfedea0SLionel Sambuc size_t res_len = (kt->bits + 7) / 8; 1883*ebfedea0SLionel Sambuc 1884*ebfedea0SLionel Sambuc if(len != 0 && c == NULL) { 1885*ebfedea0SLionel Sambuc ret = ENOMEM; 1886*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1887*ebfedea0SLionel Sambuc goto out; 1888*ebfedea0SLionel Sambuc } 1889*ebfedea0SLionel Sambuc memcpy(c, constant, len); 1890*ebfedea0SLionel Sambuc (*et->encrypt)(context, key, c, len, 1, 0, NULL); 1891*ebfedea0SLionel Sambuc k = malloc(res_len); 1892*ebfedea0SLionel Sambuc if(res_len != 0 && k == NULL) { 1893*ebfedea0SLionel Sambuc free(c); 1894*ebfedea0SLionel Sambuc ret = ENOMEM; 1895*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1896*ebfedea0SLionel Sambuc goto out; 1897*ebfedea0SLionel Sambuc } 1898*ebfedea0SLionel Sambuc ret = _krb5_n_fold(c, len, k, res_len); 1899*ebfedea0SLionel Sambuc free(c); 1900*ebfedea0SLionel Sambuc if (ret) { 1901*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1902*ebfedea0SLionel Sambuc goto out; 1903*ebfedea0SLionel Sambuc } 1904*ebfedea0SLionel Sambuc } 1905*ebfedea0SLionel Sambuc 1906*ebfedea0SLionel Sambuc /* XXX keytype dependent post-processing */ 1907*ebfedea0SLionel Sambuc switch(kt->type) { 1908*ebfedea0SLionel Sambuc case KEYTYPE_DES3: 1909*ebfedea0SLionel Sambuc _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize); 1910*ebfedea0SLionel Sambuc break; 1911*ebfedea0SLionel Sambuc case KEYTYPE_AES128: 1912*ebfedea0SLionel Sambuc case KEYTYPE_AES256: 1913*ebfedea0SLionel Sambuc memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); 1914*ebfedea0SLionel Sambuc break; 1915*ebfedea0SLionel Sambuc default: 1916*ebfedea0SLionel Sambuc ret = KRB5_CRYPTO_INTERNAL; 1917*ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, 1918*ebfedea0SLionel Sambuc N_("derive_key() called with unknown keytype (%u)", ""), 1919*ebfedea0SLionel Sambuc kt->type); 1920*ebfedea0SLionel Sambuc break; 1921*ebfedea0SLionel Sambuc } 1922*ebfedea0SLionel Sambuc out: 1923*ebfedea0SLionel Sambuc if (key->schedule) { 1924*ebfedea0SLionel Sambuc free_key_schedule(context, key, et); 1925*ebfedea0SLionel Sambuc key->schedule = NULL; 1926*ebfedea0SLionel Sambuc } 1927*ebfedea0SLionel Sambuc if (k) { 1928*ebfedea0SLionel Sambuc memset(k, 0, nblocks * et->blocksize); 1929*ebfedea0SLionel Sambuc free(k); 1930*ebfedea0SLionel Sambuc } 1931*ebfedea0SLionel Sambuc return ret; 1932*ebfedea0SLionel Sambuc } 1933*ebfedea0SLionel Sambuc 1934*ebfedea0SLionel Sambuc static struct _krb5_key_data * 1935*ebfedea0SLionel Sambuc _new_derived_key(krb5_crypto crypto, unsigned usage) 1936*ebfedea0SLionel Sambuc { 1937*ebfedea0SLionel Sambuc struct _krb5_key_usage *d = crypto->key_usage; 1938*ebfedea0SLionel Sambuc d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); 1939*ebfedea0SLionel Sambuc if(d == NULL) 1940*ebfedea0SLionel Sambuc return NULL; 1941*ebfedea0SLionel Sambuc crypto->key_usage = d; 1942*ebfedea0SLionel Sambuc d += crypto->num_key_usage++; 1943*ebfedea0SLionel Sambuc memset(d, 0, sizeof(*d)); 1944*ebfedea0SLionel Sambuc d->usage = usage; 1945*ebfedea0SLionel Sambuc return &d->key; 1946*ebfedea0SLionel Sambuc } 1947*ebfedea0SLionel Sambuc 1948*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1949*ebfedea0SLionel Sambuc krb5_derive_key(krb5_context context, 1950*ebfedea0SLionel Sambuc const krb5_keyblock *key, 1951*ebfedea0SLionel Sambuc krb5_enctype etype, 1952*ebfedea0SLionel Sambuc const void *constant, 1953*ebfedea0SLionel Sambuc size_t constant_len, 1954*ebfedea0SLionel Sambuc krb5_keyblock **derived_key) 1955*ebfedea0SLionel Sambuc { 1956*ebfedea0SLionel Sambuc krb5_error_code ret; 1957*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et; 1958*ebfedea0SLionel Sambuc struct _krb5_key_data d; 1959*ebfedea0SLionel Sambuc 1960*ebfedea0SLionel Sambuc *derived_key = NULL; 1961*ebfedea0SLionel Sambuc 1962*ebfedea0SLionel Sambuc et = _krb5_find_enctype (etype); 1963*ebfedea0SLionel Sambuc if (et == NULL) { 1964*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 1965*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 1966*ebfedea0SLionel Sambuc etype); 1967*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 1968*ebfedea0SLionel Sambuc } 1969*ebfedea0SLionel Sambuc 1970*ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, key, &d.key); 1971*ebfedea0SLionel Sambuc if (ret) 1972*ebfedea0SLionel Sambuc return ret; 1973*ebfedea0SLionel Sambuc 1974*ebfedea0SLionel Sambuc d.schedule = NULL; 1975*ebfedea0SLionel Sambuc ret = _krb5_derive_key(context, et, &d, constant, constant_len); 1976*ebfedea0SLionel Sambuc if (ret == 0) 1977*ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, d.key, derived_key); 1978*ebfedea0SLionel Sambuc _krb5_free_key_data(context, &d, et); 1979*ebfedea0SLionel Sambuc return ret; 1980*ebfedea0SLionel Sambuc } 1981*ebfedea0SLionel Sambuc 1982*ebfedea0SLionel Sambuc static krb5_error_code 1983*ebfedea0SLionel Sambuc _get_derived_key(krb5_context context, 1984*ebfedea0SLionel Sambuc krb5_crypto crypto, 1985*ebfedea0SLionel Sambuc unsigned usage, 1986*ebfedea0SLionel Sambuc struct _krb5_key_data **key) 1987*ebfedea0SLionel Sambuc { 1988*ebfedea0SLionel Sambuc int i; 1989*ebfedea0SLionel Sambuc struct _krb5_key_data *d; 1990*ebfedea0SLionel Sambuc unsigned char constant[5]; 1991*ebfedea0SLionel Sambuc 1992*ebfedea0SLionel Sambuc for(i = 0; i < crypto->num_key_usage; i++) 1993*ebfedea0SLionel Sambuc if(crypto->key_usage[i].usage == usage) { 1994*ebfedea0SLionel Sambuc *key = &crypto->key_usage[i].key; 1995*ebfedea0SLionel Sambuc return 0; 1996*ebfedea0SLionel Sambuc } 1997*ebfedea0SLionel Sambuc d = _new_derived_key(crypto, usage); 1998*ebfedea0SLionel Sambuc if(d == NULL) { 1999*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 2000*ebfedea0SLionel Sambuc return ENOMEM; 2001*ebfedea0SLionel Sambuc } 2002*ebfedea0SLionel Sambuc krb5_copy_keyblock(context, crypto->key.key, &d->key); 2003*ebfedea0SLionel Sambuc _krb5_put_int(constant, usage, 5); 2004*ebfedea0SLionel Sambuc _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant)); 2005*ebfedea0SLionel Sambuc *key = d; 2006*ebfedea0SLionel Sambuc return 0; 2007*ebfedea0SLionel Sambuc } 2008*ebfedea0SLionel Sambuc 2009*ebfedea0SLionel Sambuc /** 2010*ebfedea0SLionel Sambuc * Create a crypto context used for all encryption and signature 2011*ebfedea0SLionel Sambuc * operation. The encryption type to use is taken from the key, but 2012*ebfedea0SLionel Sambuc * can be overridden with the enctype parameter. This can be useful 2013*ebfedea0SLionel Sambuc * for encryptions types which is compatiable (DES for example). 2014*ebfedea0SLionel Sambuc * 2015*ebfedea0SLionel Sambuc * To free the crypto context, use krb5_crypto_destroy(). 2016*ebfedea0SLionel Sambuc * 2017*ebfedea0SLionel Sambuc * @param context Kerberos context 2018*ebfedea0SLionel Sambuc * @param key the key block information with all key data 2019*ebfedea0SLionel Sambuc * @param etype the encryption type 2020*ebfedea0SLionel Sambuc * @param crypto the resulting crypto context 2021*ebfedea0SLionel Sambuc * 2022*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2023*ebfedea0SLionel Sambuc * 2024*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2025*ebfedea0SLionel Sambuc */ 2026*ebfedea0SLionel Sambuc 2027*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2028*ebfedea0SLionel Sambuc krb5_crypto_init(krb5_context context, 2029*ebfedea0SLionel Sambuc const krb5_keyblock *key, 2030*ebfedea0SLionel Sambuc krb5_enctype etype, 2031*ebfedea0SLionel Sambuc krb5_crypto *crypto) 2032*ebfedea0SLionel Sambuc { 2033*ebfedea0SLionel Sambuc krb5_error_code ret; 2034*ebfedea0SLionel Sambuc ALLOC(*crypto, 1); 2035*ebfedea0SLionel Sambuc if(*crypto == NULL) { 2036*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 2037*ebfedea0SLionel Sambuc return ENOMEM; 2038*ebfedea0SLionel Sambuc } 2039*ebfedea0SLionel Sambuc if(etype == ETYPE_NULL) 2040*ebfedea0SLionel Sambuc etype = key->keytype; 2041*ebfedea0SLionel Sambuc (*crypto)->et = _krb5_find_enctype(etype); 2042*ebfedea0SLionel Sambuc if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { 2043*ebfedea0SLionel Sambuc free(*crypto); 2044*ebfedea0SLionel Sambuc *crypto = NULL; 2045*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 2046*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 2047*ebfedea0SLionel Sambuc etype); 2048*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2049*ebfedea0SLionel Sambuc } 2050*ebfedea0SLionel Sambuc if((*crypto)->et->keytype->size != key->keyvalue.length) { 2051*ebfedea0SLionel Sambuc free(*crypto); 2052*ebfedea0SLionel Sambuc *crypto = NULL; 2053*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_BAD_KEYSIZE, 2054*ebfedea0SLionel Sambuc "encryption key has bad length"); 2055*ebfedea0SLionel Sambuc return KRB5_BAD_KEYSIZE; 2056*ebfedea0SLionel Sambuc } 2057*ebfedea0SLionel Sambuc ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); 2058*ebfedea0SLionel Sambuc if(ret) { 2059*ebfedea0SLionel Sambuc free(*crypto); 2060*ebfedea0SLionel Sambuc *crypto = NULL; 2061*ebfedea0SLionel Sambuc return ret; 2062*ebfedea0SLionel Sambuc } 2063*ebfedea0SLionel Sambuc (*crypto)->key.schedule = NULL; 2064*ebfedea0SLionel Sambuc (*crypto)->num_key_usage = 0; 2065*ebfedea0SLionel Sambuc (*crypto)->key_usage = NULL; 2066*ebfedea0SLionel Sambuc return 0; 2067*ebfedea0SLionel Sambuc } 2068*ebfedea0SLionel Sambuc 2069*ebfedea0SLionel Sambuc static void 2070*ebfedea0SLionel Sambuc free_key_schedule(krb5_context context, 2071*ebfedea0SLionel Sambuc struct _krb5_key_data *key, 2072*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et) 2073*ebfedea0SLionel Sambuc { 2074*ebfedea0SLionel Sambuc if (et->keytype->cleanup) 2075*ebfedea0SLionel Sambuc (*et->keytype->cleanup)(context, key); 2076*ebfedea0SLionel Sambuc memset(key->schedule->data, 0, key->schedule->length); 2077*ebfedea0SLionel Sambuc krb5_free_data(context, key->schedule); 2078*ebfedea0SLionel Sambuc } 2079*ebfedea0SLionel Sambuc 2080*ebfedea0SLionel Sambuc void 2081*ebfedea0SLionel Sambuc _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key, 2082*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et) 2083*ebfedea0SLionel Sambuc { 2084*ebfedea0SLionel Sambuc krb5_free_keyblock(context, key->key); 2085*ebfedea0SLionel Sambuc if(key->schedule) { 2086*ebfedea0SLionel Sambuc free_key_schedule(context, key, et); 2087*ebfedea0SLionel Sambuc key->schedule = NULL; 2088*ebfedea0SLionel Sambuc } 2089*ebfedea0SLionel Sambuc } 2090*ebfedea0SLionel Sambuc 2091*ebfedea0SLionel Sambuc static void 2092*ebfedea0SLionel Sambuc free_key_usage(krb5_context context, struct _krb5_key_usage *ku, 2093*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et) 2094*ebfedea0SLionel Sambuc { 2095*ebfedea0SLionel Sambuc _krb5_free_key_data(context, &ku->key, et); 2096*ebfedea0SLionel Sambuc } 2097*ebfedea0SLionel Sambuc 2098*ebfedea0SLionel Sambuc /** 2099*ebfedea0SLionel Sambuc * Free a crypto context created by krb5_crypto_init(). 2100*ebfedea0SLionel Sambuc * 2101*ebfedea0SLionel Sambuc * @param context Kerberos context 2102*ebfedea0SLionel Sambuc * @param crypto crypto context to free 2103*ebfedea0SLionel Sambuc * 2104*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2105*ebfedea0SLionel Sambuc * 2106*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2107*ebfedea0SLionel Sambuc */ 2108*ebfedea0SLionel Sambuc 2109*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2110*ebfedea0SLionel Sambuc krb5_crypto_destroy(krb5_context context, 2111*ebfedea0SLionel Sambuc krb5_crypto crypto) 2112*ebfedea0SLionel Sambuc { 2113*ebfedea0SLionel Sambuc int i; 2114*ebfedea0SLionel Sambuc 2115*ebfedea0SLionel Sambuc for(i = 0; i < crypto->num_key_usage; i++) 2116*ebfedea0SLionel Sambuc free_key_usage(context, &crypto->key_usage[i], crypto->et); 2117*ebfedea0SLionel Sambuc free(crypto->key_usage); 2118*ebfedea0SLionel Sambuc _krb5_free_key_data(context, &crypto->key, crypto->et); 2119*ebfedea0SLionel Sambuc free (crypto); 2120*ebfedea0SLionel Sambuc return 0; 2121*ebfedea0SLionel Sambuc } 2122*ebfedea0SLionel Sambuc 2123*ebfedea0SLionel Sambuc /** 2124*ebfedea0SLionel Sambuc * Return the blocksize used algorithm referenced by the crypto context 2125*ebfedea0SLionel Sambuc * 2126*ebfedea0SLionel Sambuc * @param context Kerberos context 2127*ebfedea0SLionel Sambuc * @param crypto crypto context to query 2128*ebfedea0SLionel Sambuc * @param blocksize the resulting blocksize 2129*ebfedea0SLionel Sambuc * 2130*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2131*ebfedea0SLionel Sambuc * 2132*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2133*ebfedea0SLionel Sambuc */ 2134*ebfedea0SLionel Sambuc 2135*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2136*ebfedea0SLionel Sambuc krb5_crypto_getblocksize(krb5_context context, 2137*ebfedea0SLionel Sambuc krb5_crypto crypto, 2138*ebfedea0SLionel Sambuc size_t *blocksize) 2139*ebfedea0SLionel Sambuc { 2140*ebfedea0SLionel Sambuc *blocksize = crypto->et->blocksize; 2141*ebfedea0SLionel Sambuc return 0; 2142*ebfedea0SLionel Sambuc } 2143*ebfedea0SLionel Sambuc 2144*ebfedea0SLionel Sambuc /** 2145*ebfedea0SLionel Sambuc * Return the encryption type used by the crypto context 2146*ebfedea0SLionel Sambuc * 2147*ebfedea0SLionel Sambuc * @param context Kerberos context 2148*ebfedea0SLionel Sambuc * @param crypto crypto context to query 2149*ebfedea0SLionel Sambuc * @param enctype the resulting encryption type 2150*ebfedea0SLionel Sambuc * 2151*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2152*ebfedea0SLionel Sambuc * 2153*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2154*ebfedea0SLionel Sambuc */ 2155*ebfedea0SLionel Sambuc 2156*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2157*ebfedea0SLionel Sambuc krb5_crypto_getenctype(krb5_context context, 2158*ebfedea0SLionel Sambuc krb5_crypto crypto, 2159*ebfedea0SLionel Sambuc krb5_enctype *enctype) 2160*ebfedea0SLionel Sambuc { 2161*ebfedea0SLionel Sambuc *enctype = crypto->et->type; 2162*ebfedea0SLionel Sambuc return 0; 2163*ebfedea0SLionel Sambuc } 2164*ebfedea0SLionel Sambuc 2165*ebfedea0SLionel Sambuc /** 2166*ebfedea0SLionel Sambuc * Return the padding size used by the crypto context 2167*ebfedea0SLionel Sambuc * 2168*ebfedea0SLionel Sambuc * @param context Kerberos context 2169*ebfedea0SLionel Sambuc * @param crypto crypto context to query 2170*ebfedea0SLionel Sambuc * @param padsize the return padding size 2171*ebfedea0SLionel Sambuc * 2172*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2173*ebfedea0SLionel Sambuc * 2174*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2175*ebfedea0SLionel Sambuc */ 2176*ebfedea0SLionel Sambuc 2177*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2178*ebfedea0SLionel Sambuc krb5_crypto_getpadsize(krb5_context context, 2179*ebfedea0SLionel Sambuc krb5_crypto crypto, 2180*ebfedea0SLionel Sambuc size_t *padsize) 2181*ebfedea0SLionel Sambuc { 2182*ebfedea0SLionel Sambuc *padsize = crypto->et->padsize; 2183*ebfedea0SLionel Sambuc return 0; 2184*ebfedea0SLionel Sambuc } 2185*ebfedea0SLionel Sambuc 2186*ebfedea0SLionel Sambuc /** 2187*ebfedea0SLionel Sambuc * Return the confounder size used by the crypto context 2188*ebfedea0SLionel Sambuc * 2189*ebfedea0SLionel Sambuc * @param context Kerberos context 2190*ebfedea0SLionel Sambuc * @param crypto crypto context to query 2191*ebfedea0SLionel Sambuc * @param confoundersize the returned confounder size 2192*ebfedea0SLionel Sambuc * 2193*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2194*ebfedea0SLionel Sambuc * 2195*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2196*ebfedea0SLionel Sambuc */ 2197*ebfedea0SLionel Sambuc 2198*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2199*ebfedea0SLionel Sambuc krb5_crypto_getconfoundersize(krb5_context context, 2200*ebfedea0SLionel Sambuc krb5_crypto crypto, 2201*ebfedea0SLionel Sambuc size_t *confoundersize) 2202*ebfedea0SLionel Sambuc { 2203*ebfedea0SLionel Sambuc *confoundersize = crypto->et->confoundersize; 2204*ebfedea0SLionel Sambuc return 0; 2205*ebfedea0SLionel Sambuc } 2206*ebfedea0SLionel Sambuc 2207*ebfedea0SLionel Sambuc 2208*ebfedea0SLionel Sambuc /** 2209*ebfedea0SLionel Sambuc * Disable encryption type 2210*ebfedea0SLionel Sambuc * 2211*ebfedea0SLionel Sambuc * @param context Kerberos 5 context 2212*ebfedea0SLionel Sambuc * @param enctype encryption type to disable 2213*ebfedea0SLionel Sambuc * 2214*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2215*ebfedea0SLionel Sambuc * 2216*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2217*ebfedea0SLionel Sambuc */ 2218*ebfedea0SLionel Sambuc 2219*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2220*ebfedea0SLionel Sambuc krb5_enctype_disable(krb5_context context, 2221*ebfedea0SLionel Sambuc krb5_enctype enctype) 2222*ebfedea0SLionel Sambuc { 2223*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); 2224*ebfedea0SLionel Sambuc if(et == NULL) { 2225*ebfedea0SLionel Sambuc if (context) 2226*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 2227*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 2228*ebfedea0SLionel Sambuc enctype); 2229*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2230*ebfedea0SLionel Sambuc } 2231*ebfedea0SLionel Sambuc et->flags |= F_DISABLED; 2232*ebfedea0SLionel Sambuc return 0; 2233*ebfedea0SLionel Sambuc } 2234*ebfedea0SLionel Sambuc 2235*ebfedea0SLionel Sambuc /** 2236*ebfedea0SLionel Sambuc * Enable encryption type 2237*ebfedea0SLionel Sambuc * 2238*ebfedea0SLionel Sambuc * @param context Kerberos 5 context 2239*ebfedea0SLionel Sambuc * @param enctype encryption type to enable 2240*ebfedea0SLionel Sambuc * 2241*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2242*ebfedea0SLionel Sambuc * 2243*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2244*ebfedea0SLionel Sambuc */ 2245*ebfedea0SLionel Sambuc 2246*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2247*ebfedea0SLionel Sambuc krb5_enctype_enable(krb5_context context, 2248*ebfedea0SLionel Sambuc krb5_enctype enctype) 2249*ebfedea0SLionel Sambuc { 2250*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); 2251*ebfedea0SLionel Sambuc if(et == NULL) { 2252*ebfedea0SLionel Sambuc if (context) 2253*ebfedea0SLionel Sambuc krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 2254*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 2255*ebfedea0SLionel Sambuc enctype); 2256*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2257*ebfedea0SLionel Sambuc } 2258*ebfedea0SLionel Sambuc et->flags &= ~F_DISABLED; 2259*ebfedea0SLionel Sambuc return 0; 2260*ebfedea0SLionel Sambuc } 2261*ebfedea0SLionel Sambuc 2262*ebfedea0SLionel Sambuc /** 2263*ebfedea0SLionel Sambuc * Enable or disable all weak encryption types 2264*ebfedea0SLionel Sambuc * 2265*ebfedea0SLionel Sambuc * @param context Kerberos 5 context 2266*ebfedea0SLionel Sambuc * @param enable true to enable, false to disable 2267*ebfedea0SLionel Sambuc * 2268*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2269*ebfedea0SLionel Sambuc * 2270*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2271*ebfedea0SLionel Sambuc */ 2272*ebfedea0SLionel Sambuc 2273*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2274*ebfedea0SLionel Sambuc krb5_allow_weak_crypto(krb5_context context, 2275*ebfedea0SLionel Sambuc krb5_boolean enable) 2276*ebfedea0SLionel Sambuc { 2277*ebfedea0SLionel Sambuc int i; 2278*ebfedea0SLionel Sambuc 2279*ebfedea0SLionel Sambuc for(i = 0; i < _krb5_num_etypes; i++) 2280*ebfedea0SLionel Sambuc if(_krb5_etypes[i]->flags & F_WEAK) { 2281*ebfedea0SLionel Sambuc if(enable) 2282*ebfedea0SLionel Sambuc _krb5_etypes[i]->flags &= ~F_DISABLED; 2283*ebfedea0SLionel Sambuc else 2284*ebfedea0SLionel Sambuc _krb5_etypes[i]->flags |= F_DISABLED; 2285*ebfedea0SLionel Sambuc } 2286*ebfedea0SLionel Sambuc return 0; 2287*ebfedea0SLionel Sambuc } 2288*ebfedea0SLionel Sambuc 2289*ebfedea0SLionel Sambuc static size_t 2290*ebfedea0SLionel Sambuc wrapped_length (krb5_context context, 2291*ebfedea0SLionel Sambuc krb5_crypto crypto, 2292*ebfedea0SLionel Sambuc size_t data_len) 2293*ebfedea0SLionel Sambuc { 2294*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 2295*ebfedea0SLionel Sambuc size_t padsize = et->padsize; 2296*ebfedea0SLionel Sambuc size_t checksumsize = CHECKSUMSIZE(et->checksum); 2297*ebfedea0SLionel Sambuc size_t res; 2298*ebfedea0SLionel Sambuc 2299*ebfedea0SLionel Sambuc res = et->confoundersize + checksumsize + data_len; 2300*ebfedea0SLionel Sambuc res = (res + padsize - 1) / padsize * padsize; 2301*ebfedea0SLionel Sambuc return res; 2302*ebfedea0SLionel Sambuc } 2303*ebfedea0SLionel Sambuc 2304*ebfedea0SLionel Sambuc static size_t 2305*ebfedea0SLionel Sambuc wrapped_length_dervied (krb5_context context, 2306*ebfedea0SLionel Sambuc krb5_crypto crypto, 2307*ebfedea0SLionel Sambuc size_t data_len) 2308*ebfedea0SLionel Sambuc { 2309*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 2310*ebfedea0SLionel Sambuc size_t padsize = et->padsize; 2311*ebfedea0SLionel Sambuc size_t res; 2312*ebfedea0SLionel Sambuc 2313*ebfedea0SLionel Sambuc res = et->confoundersize + data_len; 2314*ebfedea0SLionel Sambuc res = (res + padsize - 1) / padsize * padsize; 2315*ebfedea0SLionel Sambuc if (et->keyed_checksum) 2316*ebfedea0SLionel Sambuc res += et->keyed_checksum->checksumsize; 2317*ebfedea0SLionel Sambuc else 2318*ebfedea0SLionel Sambuc res += et->checksum->checksumsize; 2319*ebfedea0SLionel Sambuc return res; 2320*ebfedea0SLionel Sambuc } 2321*ebfedea0SLionel Sambuc 2322*ebfedea0SLionel Sambuc /* 2323*ebfedea0SLionel Sambuc * Return the size of an encrypted packet of length `data_len' 2324*ebfedea0SLionel Sambuc */ 2325*ebfedea0SLionel Sambuc 2326*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL 2327*ebfedea0SLionel Sambuc krb5_get_wrapped_length (krb5_context context, 2328*ebfedea0SLionel Sambuc krb5_crypto crypto, 2329*ebfedea0SLionel Sambuc size_t data_len) 2330*ebfedea0SLionel Sambuc { 2331*ebfedea0SLionel Sambuc if (derived_crypto (context, crypto)) 2332*ebfedea0SLionel Sambuc return wrapped_length_dervied (context, crypto, data_len); 2333*ebfedea0SLionel Sambuc else 2334*ebfedea0SLionel Sambuc return wrapped_length (context, crypto, data_len); 2335*ebfedea0SLionel Sambuc } 2336*ebfedea0SLionel Sambuc 2337*ebfedea0SLionel Sambuc /* 2338*ebfedea0SLionel Sambuc * Return the size of an encrypted packet of length `data_len' 2339*ebfedea0SLionel Sambuc */ 2340*ebfedea0SLionel Sambuc 2341*ebfedea0SLionel Sambuc static size_t 2342*ebfedea0SLionel Sambuc crypto_overhead (krb5_context context, 2343*ebfedea0SLionel Sambuc krb5_crypto crypto) 2344*ebfedea0SLionel Sambuc { 2345*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 2346*ebfedea0SLionel Sambuc size_t res; 2347*ebfedea0SLionel Sambuc 2348*ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->checksum); 2349*ebfedea0SLionel Sambuc res += et->confoundersize; 2350*ebfedea0SLionel Sambuc if (et->padsize > 1) 2351*ebfedea0SLionel Sambuc res += et->padsize; 2352*ebfedea0SLionel Sambuc return res; 2353*ebfedea0SLionel Sambuc } 2354*ebfedea0SLionel Sambuc 2355*ebfedea0SLionel Sambuc static size_t 2356*ebfedea0SLionel Sambuc crypto_overhead_dervied (krb5_context context, 2357*ebfedea0SLionel Sambuc krb5_crypto crypto) 2358*ebfedea0SLionel Sambuc { 2359*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 2360*ebfedea0SLionel Sambuc size_t res; 2361*ebfedea0SLionel Sambuc 2362*ebfedea0SLionel Sambuc if (et->keyed_checksum) 2363*ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->keyed_checksum); 2364*ebfedea0SLionel Sambuc else 2365*ebfedea0SLionel Sambuc res = CHECKSUMSIZE(et->checksum); 2366*ebfedea0SLionel Sambuc res += et->confoundersize; 2367*ebfedea0SLionel Sambuc if (et->padsize > 1) 2368*ebfedea0SLionel Sambuc res += et->padsize; 2369*ebfedea0SLionel Sambuc return res; 2370*ebfedea0SLionel Sambuc } 2371*ebfedea0SLionel Sambuc 2372*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL 2373*ebfedea0SLionel Sambuc krb5_crypto_overhead (krb5_context context, krb5_crypto crypto) 2374*ebfedea0SLionel Sambuc { 2375*ebfedea0SLionel Sambuc if (derived_crypto (context, crypto)) 2376*ebfedea0SLionel Sambuc return crypto_overhead_dervied (context, crypto); 2377*ebfedea0SLionel Sambuc else 2378*ebfedea0SLionel Sambuc return crypto_overhead (context, crypto); 2379*ebfedea0SLionel Sambuc } 2380*ebfedea0SLionel Sambuc 2381*ebfedea0SLionel Sambuc /** 2382*ebfedea0SLionel Sambuc * Converts the random bytestring to a protocol key according to 2383*ebfedea0SLionel Sambuc * Kerberos crypto frame work. It may be assumed that all the bits of 2384*ebfedea0SLionel Sambuc * the input string are equally random, even though the entropy 2385*ebfedea0SLionel Sambuc * present in the random source may be limited. 2386*ebfedea0SLionel Sambuc * 2387*ebfedea0SLionel Sambuc * @param context Kerberos 5 context 2388*ebfedea0SLionel Sambuc * @param type the enctype resulting key will be of 2389*ebfedea0SLionel Sambuc * @param data input random data to convert to a key 2390*ebfedea0SLionel Sambuc * @param size size of input random data, at least krb5_enctype_keysize() long 2391*ebfedea0SLionel Sambuc * @param key key, output key, free with krb5_free_keyblock_contents() 2392*ebfedea0SLionel Sambuc * 2393*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2394*ebfedea0SLionel Sambuc * 2395*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2396*ebfedea0SLionel Sambuc */ 2397*ebfedea0SLionel Sambuc 2398*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2399*ebfedea0SLionel Sambuc krb5_random_to_key(krb5_context context, 2400*ebfedea0SLionel Sambuc krb5_enctype type, 2401*ebfedea0SLionel Sambuc const void *data, 2402*ebfedea0SLionel Sambuc size_t size, 2403*ebfedea0SLionel Sambuc krb5_keyblock *key) 2404*ebfedea0SLionel Sambuc { 2405*ebfedea0SLionel Sambuc krb5_error_code ret; 2406*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type); 2407*ebfedea0SLionel Sambuc if(et == NULL) { 2408*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2409*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 2410*ebfedea0SLionel Sambuc type); 2411*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2412*ebfedea0SLionel Sambuc } 2413*ebfedea0SLionel Sambuc if ((et->keytype->bits + 7) / 8 > size) { 2414*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2415*ebfedea0SLionel Sambuc N_("encryption key %s needs %d bytes " 2416*ebfedea0SLionel Sambuc "of random to make an encryption key " 2417*ebfedea0SLionel Sambuc "out of it", ""), 2418*ebfedea0SLionel Sambuc et->name, (int)et->keytype->size); 2419*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2420*ebfedea0SLionel Sambuc } 2421*ebfedea0SLionel Sambuc ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 2422*ebfedea0SLionel Sambuc if(ret) 2423*ebfedea0SLionel Sambuc return ret; 2424*ebfedea0SLionel Sambuc key->keytype = type; 2425*ebfedea0SLionel Sambuc if (et->keytype->random_to_key) 2426*ebfedea0SLionel Sambuc (*et->keytype->random_to_key)(context, key, data, size); 2427*ebfedea0SLionel Sambuc else 2428*ebfedea0SLionel Sambuc memcpy(key->keyvalue.data, data, et->keytype->size); 2429*ebfedea0SLionel Sambuc 2430*ebfedea0SLionel Sambuc return 0; 2431*ebfedea0SLionel Sambuc } 2432*ebfedea0SLionel Sambuc 2433*ebfedea0SLionel Sambuc 2434*ebfedea0SLionel Sambuc 2435*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2436*ebfedea0SLionel Sambuc krb5_crypto_prf_length(krb5_context context, 2437*ebfedea0SLionel Sambuc krb5_enctype type, 2438*ebfedea0SLionel Sambuc size_t *length) 2439*ebfedea0SLionel Sambuc { 2440*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = _krb5_find_enctype(type); 2441*ebfedea0SLionel Sambuc 2442*ebfedea0SLionel Sambuc if(et == NULL || et->prf_length == 0) { 2443*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2444*ebfedea0SLionel Sambuc N_("encryption type %d not supported", ""), 2445*ebfedea0SLionel Sambuc type); 2446*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2447*ebfedea0SLionel Sambuc } 2448*ebfedea0SLionel Sambuc 2449*ebfedea0SLionel Sambuc *length = et->prf_length; 2450*ebfedea0SLionel Sambuc return 0; 2451*ebfedea0SLionel Sambuc } 2452*ebfedea0SLionel Sambuc 2453*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2454*ebfedea0SLionel Sambuc krb5_crypto_prf(krb5_context context, 2455*ebfedea0SLionel Sambuc const krb5_crypto crypto, 2456*ebfedea0SLionel Sambuc const krb5_data *input, 2457*ebfedea0SLionel Sambuc krb5_data *output) 2458*ebfedea0SLionel Sambuc { 2459*ebfedea0SLionel Sambuc struct _krb5_encryption_type *et = crypto->et; 2460*ebfedea0SLionel Sambuc 2461*ebfedea0SLionel Sambuc krb5_data_zero(output); 2462*ebfedea0SLionel Sambuc 2463*ebfedea0SLionel Sambuc if(et->prf == NULL) { 2464*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2465*ebfedea0SLionel Sambuc "kerberos prf for %s not supported", 2466*ebfedea0SLionel Sambuc et->name); 2467*ebfedea0SLionel Sambuc return KRB5_PROG_ETYPE_NOSUPP; 2468*ebfedea0SLionel Sambuc } 2469*ebfedea0SLionel Sambuc 2470*ebfedea0SLionel Sambuc return (*et->prf)(context, crypto, input, output); 2471*ebfedea0SLionel Sambuc } 2472*ebfedea0SLionel Sambuc 2473*ebfedea0SLionel Sambuc static krb5_error_code 2474*ebfedea0SLionel Sambuc krb5_crypto_prfplus(krb5_context context, 2475*ebfedea0SLionel Sambuc const krb5_crypto crypto, 2476*ebfedea0SLionel Sambuc const krb5_data *input, 2477*ebfedea0SLionel Sambuc size_t length, 2478*ebfedea0SLionel Sambuc krb5_data *output) 2479*ebfedea0SLionel Sambuc { 2480*ebfedea0SLionel Sambuc krb5_error_code ret; 2481*ebfedea0SLionel Sambuc krb5_data input2; 2482*ebfedea0SLionel Sambuc unsigned char i = 1; 2483*ebfedea0SLionel Sambuc unsigned char *p; 2484*ebfedea0SLionel Sambuc 2485*ebfedea0SLionel Sambuc krb5_data_zero(&input2); 2486*ebfedea0SLionel Sambuc krb5_data_zero(output); 2487*ebfedea0SLionel Sambuc 2488*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 2489*ebfedea0SLionel Sambuc 2490*ebfedea0SLionel Sambuc ret = krb5_data_alloc(output, length); 2491*ebfedea0SLionel Sambuc if (ret) goto out; 2492*ebfedea0SLionel Sambuc ret = krb5_data_alloc(&input2, input->length + 1); 2493*ebfedea0SLionel Sambuc if (ret) goto out; 2494*ebfedea0SLionel Sambuc 2495*ebfedea0SLionel Sambuc krb5_clear_error_message(context); 2496*ebfedea0SLionel Sambuc 2497*ebfedea0SLionel Sambuc memcpy(((unsigned char *)input2.data) + 1, input->data, input->length); 2498*ebfedea0SLionel Sambuc 2499*ebfedea0SLionel Sambuc p = output->data; 2500*ebfedea0SLionel Sambuc 2501*ebfedea0SLionel Sambuc while (length) { 2502*ebfedea0SLionel Sambuc krb5_data block; 2503*ebfedea0SLionel Sambuc 2504*ebfedea0SLionel Sambuc ((unsigned char *)input2.data)[0] = i++; 2505*ebfedea0SLionel Sambuc 2506*ebfedea0SLionel Sambuc ret = krb5_crypto_prf(context, crypto, &input2, &block); 2507*ebfedea0SLionel Sambuc if (ret) 2508*ebfedea0SLionel Sambuc goto out; 2509*ebfedea0SLionel Sambuc 2510*ebfedea0SLionel Sambuc if (block.length < length) { 2511*ebfedea0SLionel Sambuc memcpy(p, block.data, block.length); 2512*ebfedea0SLionel Sambuc length -= block.length; 2513*ebfedea0SLionel Sambuc } else { 2514*ebfedea0SLionel Sambuc memcpy(p, block.data, length); 2515*ebfedea0SLionel Sambuc length = 0; 2516*ebfedea0SLionel Sambuc } 2517*ebfedea0SLionel Sambuc p += block.length; 2518*ebfedea0SLionel Sambuc krb5_data_free(&block); 2519*ebfedea0SLionel Sambuc } 2520*ebfedea0SLionel Sambuc 2521*ebfedea0SLionel Sambuc out: 2522*ebfedea0SLionel Sambuc krb5_data_free(&input2); 2523*ebfedea0SLionel Sambuc if (ret) 2524*ebfedea0SLionel Sambuc krb5_data_free(output); 2525*ebfedea0SLionel Sambuc return 0; 2526*ebfedea0SLionel Sambuc } 2527*ebfedea0SLionel Sambuc 2528*ebfedea0SLionel Sambuc /** 2529*ebfedea0SLionel Sambuc * The FX-CF2 key derivation function, used in FAST and preauth framework. 2530*ebfedea0SLionel Sambuc * 2531*ebfedea0SLionel Sambuc * @param context Kerberos 5 context 2532*ebfedea0SLionel Sambuc * @param crypto1 first key to combine 2533*ebfedea0SLionel Sambuc * @param crypto2 second key to combine 2534*ebfedea0SLionel Sambuc * @param pepper1 factor to combine with first key to garante uniqueness 2535*ebfedea0SLionel Sambuc * @param pepper2 factor to combine with second key to garante uniqueness 2536*ebfedea0SLionel Sambuc * @param enctype the encryption type of the resulting key 2537*ebfedea0SLionel Sambuc * @param res allocated key, free with krb5_free_keyblock_contents() 2538*ebfedea0SLionel Sambuc * 2539*ebfedea0SLionel Sambuc * @return Return an error code or 0. 2540*ebfedea0SLionel Sambuc * 2541*ebfedea0SLionel Sambuc * @ingroup krb5_crypto 2542*ebfedea0SLionel Sambuc */ 2543*ebfedea0SLionel Sambuc 2544*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2545*ebfedea0SLionel Sambuc krb5_crypto_fx_cf2(krb5_context context, 2546*ebfedea0SLionel Sambuc const krb5_crypto crypto1, 2547*ebfedea0SLionel Sambuc const krb5_crypto crypto2, 2548*ebfedea0SLionel Sambuc krb5_data *pepper1, 2549*ebfedea0SLionel Sambuc krb5_data *pepper2, 2550*ebfedea0SLionel Sambuc krb5_enctype enctype, 2551*ebfedea0SLionel Sambuc krb5_keyblock *res) 2552*ebfedea0SLionel Sambuc { 2553*ebfedea0SLionel Sambuc krb5_error_code ret; 2554*ebfedea0SLionel Sambuc krb5_data os1, os2; 2555*ebfedea0SLionel Sambuc size_t i, keysize; 2556*ebfedea0SLionel Sambuc 2557*ebfedea0SLionel Sambuc memset(res, 0, sizeof(*res)); 2558*ebfedea0SLionel Sambuc 2559*ebfedea0SLionel Sambuc ret = krb5_enctype_keysize(context, enctype, &keysize); 2560*ebfedea0SLionel Sambuc if (ret) 2561*ebfedea0SLionel Sambuc return ret; 2562*ebfedea0SLionel Sambuc 2563*ebfedea0SLionel Sambuc ret = krb5_data_alloc(&res->keyvalue, keysize); 2564*ebfedea0SLionel Sambuc if (ret) 2565*ebfedea0SLionel Sambuc goto out; 2566*ebfedea0SLionel Sambuc ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1); 2567*ebfedea0SLionel Sambuc if (ret) 2568*ebfedea0SLionel Sambuc goto out; 2569*ebfedea0SLionel Sambuc ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2); 2570*ebfedea0SLionel Sambuc if (ret) 2571*ebfedea0SLionel Sambuc goto out; 2572*ebfedea0SLionel Sambuc 2573*ebfedea0SLionel Sambuc res->keytype = enctype; 2574*ebfedea0SLionel Sambuc { 2575*ebfedea0SLionel Sambuc unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data; 2576*ebfedea0SLionel Sambuc for (i = 0; i < keysize; i++) 2577*ebfedea0SLionel Sambuc p3[i] = p1[i] ^ p2[i]; 2578*ebfedea0SLionel Sambuc } 2579*ebfedea0SLionel Sambuc out: 2580*ebfedea0SLionel Sambuc if (ret) 2581*ebfedea0SLionel Sambuc krb5_data_free(&res->keyvalue); 2582*ebfedea0SLionel Sambuc krb5_data_free(&os1); 2583*ebfedea0SLionel Sambuc krb5_data_free(&os2); 2584*ebfedea0SLionel Sambuc 2585*ebfedea0SLionel Sambuc return ret; 2586*ebfedea0SLionel Sambuc } 2587*ebfedea0SLionel Sambuc 2588*ebfedea0SLionel Sambuc 2589*ebfedea0SLionel Sambuc 2590*ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER 2591*ebfedea0SLionel Sambuc 2592*ebfedea0SLionel Sambuc /** 2593*ebfedea0SLionel Sambuc * Deprecated: keytypes doesn't exists, they are really enctypes. 2594*ebfedea0SLionel Sambuc * 2595*ebfedea0SLionel Sambuc * @ingroup krb5_deprecated 2596*ebfedea0SLionel Sambuc */ 2597*ebfedea0SLionel Sambuc 2598*ebfedea0SLionel Sambuc KRB5_DEPRECATED 2599*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2600*ebfedea0SLionel Sambuc krb5_keytype_to_enctypes (krb5_context context, 2601*ebfedea0SLionel Sambuc krb5_keytype keytype, 2602*ebfedea0SLionel Sambuc unsigned *len, 2603*ebfedea0SLionel Sambuc krb5_enctype **val) 2604*ebfedea0SLionel Sambuc { 2605*ebfedea0SLionel Sambuc int i; 2606*ebfedea0SLionel Sambuc unsigned n = 0; 2607*ebfedea0SLionel Sambuc krb5_enctype *ret; 2608*ebfedea0SLionel Sambuc 2609*ebfedea0SLionel Sambuc for (i = _krb5_num_etypes - 1; i >= 0; --i) { 2610*ebfedea0SLionel Sambuc if (_krb5_etypes[i]->keytype->type == keytype 2611*ebfedea0SLionel Sambuc && !(_krb5_etypes[i]->flags & F_PSEUDO) 2612*ebfedea0SLionel Sambuc && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) 2613*ebfedea0SLionel Sambuc ++n; 2614*ebfedea0SLionel Sambuc } 2615*ebfedea0SLionel Sambuc if (n == 0) { 2616*ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, 2617*ebfedea0SLionel Sambuc "Keytype have no mapping"); 2618*ebfedea0SLionel Sambuc return KRB5_PROG_KEYTYPE_NOSUPP; 2619*ebfedea0SLionel Sambuc } 2620*ebfedea0SLionel Sambuc 2621*ebfedea0SLionel Sambuc ret = malloc(n * sizeof(*ret)); 2622*ebfedea0SLionel Sambuc if (ret == NULL && n != 0) { 2623*ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 2624*ebfedea0SLionel Sambuc return ENOMEM; 2625*ebfedea0SLionel Sambuc } 2626*ebfedea0SLionel Sambuc n = 0; 2627*ebfedea0SLionel Sambuc for (i = _krb5_num_etypes - 1; i >= 0; --i) { 2628*ebfedea0SLionel Sambuc if (_krb5_etypes[i]->keytype->type == keytype 2629*ebfedea0SLionel Sambuc && !(_krb5_etypes[i]->flags & F_PSEUDO) 2630*ebfedea0SLionel Sambuc && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) 2631*ebfedea0SLionel Sambuc ret[n++] = _krb5_etypes[i]->type; 2632*ebfedea0SLionel Sambuc } 2633*ebfedea0SLionel Sambuc *len = n; 2634*ebfedea0SLionel Sambuc *val = ret; 2635*ebfedea0SLionel Sambuc return 0; 2636*ebfedea0SLionel Sambuc } 2637*ebfedea0SLionel Sambuc 2638*ebfedea0SLionel Sambuc /** 2639*ebfedea0SLionel Sambuc * Deprecated: keytypes doesn't exists, they are really enctypes. 2640*ebfedea0SLionel Sambuc * 2641*ebfedea0SLionel Sambuc * @ingroup krb5_deprecated 2642*ebfedea0SLionel Sambuc */ 2643*ebfedea0SLionel Sambuc 2644*ebfedea0SLionel Sambuc /* if two enctypes have compatible keys */ 2645*ebfedea0SLionel Sambuc KRB5_DEPRECATED 2646*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 2647*ebfedea0SLionel Sambuc krb5_enctypes_compatible_keys(krb5_context context, 2648*ebfedea0SLionel Sambuc krb5_enctype etype1, 2649*ebfedea0SLionel Sambuc krb5_enctype etype2) 2650*ebfedea0SLionel Sambuc { 2651*ebfedea0SLionel Sambuc struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1); 2652*ebfedea0SLionel Sambuc struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2); 2653*ebfedea0SLionel Sambuc return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; 2654*ebfedea0SLionel Sambuc } 2655*ebfedea0SLionel Sambuc 2656*ebfedea0SLionel Sambuc #endif /* HEIMDAL_SMALLER */ 2657