diff --git a/lib/krb5/encrypt.c b/lib/krb5/encrypt.c index 8cbc38fa2..ac5dba441 100644 --- a/lib/krb5/encrypt.c +++ b/lib/krb5/encrypt.c @@ -3,71 +3,131 @@ RCSID("$Id$"); -krb5_error_code -krb5_des_cbc_encrypt (krb5_context context, - void *ptr, - size_t len, - int etype, - krb5_keyblock *keyblock, - krb5_data *result) +struct encryption_type { + int type; + size_t blocksize; + size_t confoundersize; + size_t checksumsize; + void (*encrypt)(void *, size_t, const krb5_keyblock *, int); + void (*checksum)(void *, size_t, void *); +}; + +static void +NULL_checksum(void *p, size_t len, void *result) +{ +} + +static void +MD5_checksum(void *p, size_t len, void *result) +{ + struct md5 m; + md5init(&m); + md5_update(&m, p, len); + md5_finito(&m, result); +} + +static void +SHA1_checksum(void *p, size_t len, void *result) +{ + struct sha m; + sha_init(&m); + sha_update(&m, p, len); + sha_finito(&m, result); +} + +static void +CRC_checksum(void *p, size_t len, void *result) +{ + u_int32_t crc; + unsigned char *r = result; + crc_init_table (); + crc = crc_update (p, len, 0); + r[0] = crc & 0xff; + r[1] = (crc >> 8) & 0xff; + r[2] = (crc >> 16) & 0xff; + r[3] = (crc >> 24) & 0xff; +} + +static void +NULL_encrypt(void *p, size_t len, const krb5_keyblock *keyblock, int encrypt) +{ +} + +static void +DES_encrypt(void *p, size_t len, + const krb5_keyblock *keyblock, int encrypt) { - u_char *p; - size_t sz; des_cblock key; des_key_schedule schedule; + memcpy(&key, keyblock->keyvalue.data, sizeof(key)); + des_set_key(&key, schedule); + des_cbc_encrypt(p, p, len, schedule, &key, encrypt); +} - switch(etype){ - case ETYPE_DES_CBC_MD5: - sz = 16; - break; - case ETYPE_DES_CBC_CRC: - sz = 4; - break; - default: - return KRB5_PROG_ETYPE_NOSUPP; - } +static void +DES3_encrypt(void *p, size_t len, const krb5_keyblock *keyblock, int encrypt) +{ - sz += len + 8; - sz = (sz + 7) & ~7; /* pad to 8 bytes */ - p = calloc (1, sz); +} + +static struct encryption_type em [] = { + { ETYPE_DES_CBC_CRC, 8, 8, 4, DES_encrypt, CRC_checksum }, + { ETYPE_DES_CBC_MD5, 8, 8, 16, DES_encrypt, MD5_checksum }, + { ETYPE_NULL, 1, 0, 0, NULL_encrypt, NULL_checksum }, +}; + +static int num_etypes = sizeof(em) / sizeof(em[0]); + +static krb5_error_code +krb5_do_encrypt(krb5_context context, + void *ptr, + size_t len, + struct encryption_type *et, + krb5_keyblock *keyblock, + krb5_data *result) +{ + size_t size; + size_t sz; + unsigned char *p; + size = len + et->confoundersize + et->checksumsize; + sz = (size + et->blocksize - 1) & ~ (et->blocksize - 1); + p = calloc(1, sz); if (p == NULL) return ENOMEM; - des_new_random_key((des_cblock*)p); -#if 0 - des_rand_data ((des_cblock*)p, 8); -#endif - memcpy (p + 12, ptr, len); - switch(etype){ - case ETYPE_DES_CBC_MD5: - { - struct md5 m; - md5init(&m); - md5_update(&m, p, sz); - md5_finito(&m, p + 8); - break; - } - case ETYPE_DES_CBC_CRC: - { - u_int32_t crc; - crc_init_table (); - crc = crc_update (p, sz, 0); - p[8] = crc & 0xff; - p[9] = (crc >> 8) & 0xff; - p[10] = (crc >> 16) & 0xff; - p[11] = (crc >> 24) & 0xff; - break; - } - } - - memcpy (&key, keyblock->keyvalue.data, sizeof(key)); - des_set_key (&key, schedule); - des_cbc_encrypt ((des_cblock *)p, (des_cblock *)p, sz, - schedule, &key, DES_ENCRYPT); - + des_rand_data(p, et->confoundersize); + memcpy(p + et->confoundersize + et->checksumsize, ptr, len); + (*et->checksum)(p, size, p + et->confoundersize); + (*et->encrypt)(p, sz, keyblock, 1); result->data = p; result->length = sz; return 0; - +} + +static krb5_error_code +krb5_do_decrypt(krb5_context context, + void *ptr, + size_t len, + struct encryption_type *et, + const krb5_keyblock *keyblock, + krb5_data *result) +{ + unsigned char *his_checksum; + unsigned char *p = ptr; + size_t length = 0; /* magic! */ + (*et->encrypt)(ptr, len, keyblock, 0); + his_checksum = malloc(et->checksumsize); + memcpy(his_checksum, ptr + et->confoundersize, et->checksumsize); + memset(ptr + et->confoundersize, 0, et->checksumsize); + + (*et->checksum)(p, length, p + et->confoundersize); + if (memcmp(p + et->confoundersize, his_checksum, et->checksumsize)) + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + result->data = malloc(length); + if(result->data == NULL) + return ENOMEM; + result->length = length; + memcpy(result->data, p + et->confoundersize, et->checksumsize); + return 0; } krb5_error_code @@ -78,11 +138,9 @@ krb5_encrypt (krb5_context context, krb5_keyblock *keyblock, krb5_data *result) { - switch(etype){ - case ETYPE_DES_CBC_MD5: - case ETYPE_DES_CBC_CRC: - return krb5_des_cbc_encrypt(context, ptr, len, etype, - keyblock, result); - } + struct encryption_type *e; + for(e = em; e < em + num_etypes; e++) + if(etype == e->type) + return krb5_do_encrypt(context, ptr, len, e, keyblock, result); return KRB5_PROG_ETYPE_NOSUPP; }