From: Tom Yu Date: Tue, 5 Jan 1999 05:14:31 +0000 (+0000) Subject: * dk.h: Add prototypes for krb5_marc_dk_* X-Git-Tag: krb5-1.1-beta1~424 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=474187a3c7d6bdef3618c192590703a36e353e95;p=krb5.git * dk.h: Add prototypes for krb5_marc_dk_* * dk_encrypt.c (krb5_marc_dk_encrypt): Add compat for 32-bit length coded ciphertext. * dk_decrypt.c (krb5_marc_dk_decrypt): Add compat for 32-bit length coded ciphertext. * checksum.c: Add compat for 32-bit length included checksum. Note that nothing uses this at the moment, and probably shouldn't. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11098 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/crypto/dk/ChangeLog b/src/lib/crypto/dk/ChangeLog index a8a4bda50..7f3300a94 100644 --- a/src/lib/crypto/dk/ChangeLog +++ b/src/lib/crypto/dk/ChangeLog @@ -1,3 +1,17 @@ +Tue Jan 5 00:09:13 1999 Tom Yu + + * dk.h: Add prototypes for krb5_marc_dk_*. + + * dk_encrypt.c (krb5_marc_dk_encrypt): Add compat for 32-bit + length coded ciphertext. + + * dk_decrypt.c (krb5_marc_dk_decrypt): Add compat for 32-bit + length coded ciphertext. + + * checksum.c: Add compat for 32-bit length included checksum. + Note that nothing uses this at the moment, and probably + shouldn't. + 1998-11-13 Theodore Ts'o * Makefile.in: Set the myfulldir and mydir variables (which are diff --git a/src/lib/crypto/dk/checksum.c b/src/lib/crypto/dk/checksum.c index db64e6cb6..b9318d239 100644 --- a/src/lib/crypto/dk/checksum.c +++ b/src/lib/crypto/dk/checksum.c @@ -102,3 +102,84 @@ cleanup: return(ret); } + +#ifdef ATHENA_DES3_KLUDGE +krb5_error_code +krb5_marc_dk_make_checksum(hash, key, usage, input, output) + krb5_const struct krb5_hash_provider *hash; + krb5_const krb5_keyblock *key; + krb5_keyusage usage; + krb5_const krb5_data *input; + krb5_data *output; +{ + int i; + struct krb5_enc_provider *enc; + size_t blocksize, keybytes, keylength; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data datain[2]; + unsigned char *kcdata; + krb5_keyblock kc; + + for (i=0; ienctype) + break; + } + + if (i == krb5_enctypes_length) + return(KRB5_BAD_ENCTYPE); + + enc = krb5_enctypes_list[i].enc; + + /* allocate and set to-be-derived keys */ + + (*(enc->block_size))(&blocksize); + (*(enc->keysize))(&keybytes, &keylength); + + /* key->length will be tested in enc->encrypt + output->length will be tested in krb5_hmac */ + + if ((kcdata = (unsigned char *) malloc(keylength)) == NULL) + return(ENOMEM); + + kc.contents = kcdata; + kc.length = keylength; + + /* derive the key */ + + datain[0].data = constantdata; + datain[0].length = K5CLENGTH; + + datain[0].data[0] = (usage>>24)&0xff; + datain[0].data[1] = (usage>>16)&0xff; + datain[0].data[2] = (usage>>8)&0xff; + datain[0].data[3] = usage&0xff; + + datain[0].data[4] = 0x99; + + if (ret = krb5_derive_key(enc, key, &kc, &datain[0])) + goto cleanup; + + /* hash the data */ + + datain[0].length = 4; + datain[0].data[0] = (input->length>>24)&0xff; + datain[0].data[1] = (input->length>>16)&0xff; + datain[0].data[2] = (input->length>>8)&0xff; + datain[0].data[3] = input->length&0xff; + + datain[1] = *input; + + if (ret = krb5_hmac(hash, &kc, 2, datain, output)) + memset(output->data, 0, output->length); + + /* ret is set correctly by the prior call */ + +cleanup: + memset(kcdata, 0, keylength); + + free(kcdata); + + return(ret); +} +#endif /* ATHENA_DES3_KLUDGE */ diff --git a/src/lib/crypto/dk/dk.h b/src/lib/crypto/dk/dk.h index e4acddabc..996fed1f2 100644 --- a/src/lib/crypto/dk/dk.h +++ b/src/lib/crypto/dk/dk.h @@ -59,3 +59,29 @@ krb5_error_code krb5_dk_make_checksum KRB5_PROTOTYPE((krb5_const struct krb5_hash_provider *hash, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *input, krb5_data *output)); + +#ifdef ATHENA_DES3_KLUDGE +void krb5_marc_dk_encrypt_length +KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc, + krb5_const struct krb5_hash_provider *hash, + size_t input, size_t *length)); + +krb5_error_code krb5_marc_dk_encrypt +KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc, + krb5_const struct krb5_hash_provider *hash, + krb5_const krb5_keyblock *key, krb5_keyusage usage, + krb5_const krb5_data *ivec, + krb5_const krb5_data *input, krb5_data *output)); + +krb5_error_code krb5_marc_dk_decrypt +KRB5_PROTOTYPE((krb5_const struct krb5_enc_provider *enc, + krb5_const struct krb5_hash_provider *hash, + krb5_const krb5_keyblock *key, krb5_keyusage usage, + krb5_const krb5_data *ivec, krb5_const krb5_data *input, + krb5_data *arg_output)); + +krb5_error_code krb5_marc_dk_make_checksum +KRB5_PROTOTYPE((krb5_const struct krb5_hash_provider *hash, + krb5_const krb5_keyblock *key, krb5_keyusage usage, + krb5_const krb5_data *input, krb5_data *output)); +#endif /* ATHENA_DES3_KLUDGE */ diff --git a/src/lib/crypto/dk/dk_decrypt.c b/src/lib/crypto/dk/dk_decrypt.c index 9fedffbc0..71fdb80d0 100644 --- a/src/lib/crypto/dk/dk_decrypt.c +++ b/src/lib/crypto/dk/dk_decrypt.c @@ -149,3 +149,134 @@ cleanup: return(ret); } + +#ifdef ATHENA_DES3_KLUDGE +krb5_error_code +krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output) + krb5_const struct krb5_enc_provider *enc; + krb5_const struct krb5_hash_provider *hash; + krb5_const krb5_keyblock *key; + krb5_keyusage usage; + krb5_const krb5_data *ivec; + krb5_const krb5_data *input; + krb5_data *output; +{ + krb5_error_code ret; + size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen; + unsigned char *plaindata, *kedata, *kidata, *cksum; + krb5_keyblock ke, ki; + krb5_data d1, d2; + unsigned char constantdata[K5CLENGTH]; + + /* allocate and set up ciphertext and to-be-derived keys */ + + (*(hash->hash_size))(&hashsize); + (*(enc->block_size))(&blocksize); + (*(enc->keysize))(&keybytes, &keylength); + + enclen = input->length - hashsize; + + if ((kedata = (unsigned char *) malloc(keylength)) == NULL) + return(ENOMEM); + if ((kidata = (unsigned char *) malloc(keylength)) == NULL) { + free(kedata); + return(ENOMEM); + } + if ((plaindata = (unsigned char *) malloc(enclen)) == NULL) { + free(kidata); + free(kedata); + return(ENOMEM); + } + if ((cksum = (unsigned char *) malloc(hashsize)) == NULL) { + free(plaindata); + free(kidata); + free(kedata); + return(ENOMEM); + } + + ke.contents = kedata; + ke.length = keylength; + ki.contents = kidata; + ki.length = keylength; + + /* derive the keys */ + + d1.data = constantdata; + d1.length = K5CLENGTH; + + d1.data[0] = (usage>>24)&0xff; + d1.data[1] = (usage>>16)&0xff; + d1.data[2] = (usage>>8)&0xff; + d1.data[3] = usage&0xff; + + d1.data[4] = 0xAA; + + if (ret = krb5_derive_key(enc, key, &ke, &d1)) + goto cleanup; + + d1.data[4] = 0x55; + + if (ret = krb5_derive_key(enc, key, &ki, &d1)) + goto cleanup; + + /* decrypt the ciphertext */ + + d1.length = enclen; + d1.data = input->data; + + d2.length = enclen; + d2.data = plaindata; + + if (ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) + goto cleanup; + + /* verify the hash */ + + d1.length = hashsize; + d1.data = cksum; + + if (ret = krb5_hmac(hash, &ki, 1, &d2, &d1)) + goto cleanup; + + if (memcmp(cksum, input->data+enclen, hashsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + /* because this encoding isn't self-describing wrt length, the + best we can do here is to compute the length minus the + confounder. */ + + /* get the real plaintext length and copy the data into the output */ + + plainlen = ((((plaindata+blocksize)[0])<<24) | + (((plaindata+blocksize)[1])<<16) | + (((plaindata+blocksize)[2])<<8) | + ((plaindata+blocksize)[3])); + + if (plainlen > (enclen - blocksize - 4)) + return(KRB5_BAD_MSIZE); + + if (output->length < plainlen) + return(KRB5_BAD_MSIZE); + + output->length = plainlen; + + memcpy(output->data, d2.data+4+blocksize, output->length); + + ret = 0; + +cleanup: + memset(kedata, 0, keylength); + memset(kidata, 0, keylength); + memset(plaindata, 0, enclen); + memset(cksum, 0, hashsize); + + free(cksum); + free(plaindata); + free(kidata); + free(kedata); + + return(ret); +} +#endif /* ATHENA_DES3_KLUDGE */ diff --git a/src/lib/crypto/dk/dk_encrypt.c b/src/lib/crypto/dk/dk_encrypt.c index 4a3a00b30..a1b85a3ac 100644 --- a/src/lib/crypto/dk/dk_encrypt.c +++ b/src/lib/crypto/dk/dk_encrypt.c @@ -165,3 +165,140 @@ cleanup: return(ret); } + +#ifdef ATHENA_DES3_KLUDGE +void +krb5_marc_dk_encrypt_length(enc, hash, inputlen, length) + krb5_const struct krb5_enc_provider *enc; + krb5_const struct krb5_hash_provider *hash; + size_t inputlen; + size_t *length; +{ + size_t blocksize, hashsize; + + (*(enc->block_size))(&blocksize); + (*(hash->hash_size))(&hashsize); + + *length = krb5_roundup(blocksize+4+inputlen, blocksize) + hashsize; +} + +krb5_error_code +krb5_marc_dk_encrypt(enc, hash, key, usage, ivec, input, output) + krb5_const struct krb5_enc_provider *enc; + krb5_const struct krb5_hash_provider *hash; + krb5_const krb5_keyblock *key; + krb5_keyusage usage; + krb5_const krb5_data *ivec; + krb5_const krb5_data *input; + krb5_data *output; +{ + size_t blocksize, keybytes, keylength, plainlen, enclen; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data d1, d2; + unsigned char *plaintext, *kedata, *kidata; + krb5_keyblock ke, ki; + + /* allocate and set up plaintext and to-be-derived keys */ + + (*(enc->block_size))(&blocksize); + (*(enc->keysize))(&keybytes, &keylength); + plainlen = krb5_roundup(blocksize+4+input->length, blocksize); + + krb5_dk_encrypt_length(enc, hash, input->length, &enclen); + + /* key->length, ivec will be tested in enc->encrypt */ + + if (output->length < enclen) + return(KRB5_BAD_MSIZE); + + if ((kedata = (unsigned char *) malloc(keylength)) == NULL) + return(ENOMEM); + if ((kidata = (unsigned char *) malloc(keylength)) == NULL) { + free(kedata); + return(ENOMEM); + } + if ((plaintext = (unsigned char *) malloc(plainlen)) == NULL) { + free(kidata); + free(kedata); + return(ENOMEM); + } + + ke.contents = kedata; + ke.length = keylength; + ki.contents = kidata; + ki.length = keylength; + + /* derive the keys */ + + d1.data = constantdata; + d1.length = K5CLENGTH; + + d1.data[0] = (usage>>24)&0xff; + d1.data[1] = (usage>>16)&0xff; + d1.data[2] = (usage>>8)&0xff; + d1.data[3] = usage&0xff; + + d1.data[4] = 0xAA; + + if (ret = krb5_derive_key(enc, key, &ke, &d1)) + goto cleanup; + + d1.data[4] = 0x55; + + if (ret = krb5_derive_key(enc, key, &ki, &d1)) + goto cleanup; + + /* put together the plaintext */ + + d1.length = blocksize; + d1.data = plaintext; + + if (ret = krb5_c_random_make_octets(/* XXX */ 0, &d1)) + goto cleanup; + + (plaintext+blocksize)[0] = (input->length>>24)&0xff; + (plaintext+blocksize)[1] = (input->length>>16)&0xff; + (plaintext+blocksize)[2] = (input->length>>8)&0xff; + (plaintext+blocksize)[3] = input->length&0xff; + + memcpy(plaintext+blocksize+4, input->data, input->length); + + memset(plaintext+blocksize+4+input->length, 0, + plainlen - (blocksize+4+input->length)); + + /* encrypt the plaintext */ + + d1.length = plainlen; + d1.data = plaintext; + + d2.length = plainlen; + d2.data = output->data; + + if (ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2))) + goto cleanup; + + /* hash the plaintext */ + + d2.length = enclen - plainlen; + d2.data = output->data+plainlen; + + output->length = enclen; + + if (ret = krb5_hmac(hash, &ki, 1, &d1, &d2)) + memset(d2.data, 0, d2.length); + + /* ret is set correctly by the prior call */ + +cleanup: + memset(kedata, 0, keylength); + memset(kidata, 0, keylength); + memset(plaintext, 0, plainlen); + + free(plaintext); + free(kidata); + free(kedata); + + return(ret); +} +#endif /* ATHENA_DES3_KLUDGE */