Skip to content

Commit

Permalink
For RC4, checksum is in header, not trailer
Browse files Browse the repository at this point in the history
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mskrb-integ-crypto-iov@21226 dc483132-0cff-0310-8789-dd5450dbe970
  • Loading branch information
hartmans committed Dec 1, 2008
1 parent d8dd17d commit e56fd08
Showing 1 changed file with 32 additions and 19 deletions.
51 changes: 32 additions & 19 deletions src/lib/crypto/arcfour/arcfour_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
size_t num_data)
{
krb5_error_code ret;
krb5_crypto_iov *header, *trailer, *padding;
krb5_crypto_iov *header, *trailer;
krb5_keyblock k1, k2, k3;
krb5_data d1, d2, d3;
krb5_data checksum, confounder;
krb5_keyusage ms_usage;
char salt_data[14];
krb5_data salt;
Expand All @@ -102,22 +103,15 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
* and trailer; per RFC 4757 we will arrange it as:
*
* Checksum | E(Confounder | Plaintext)
*
* There is no pad required, but if one is provided we will
* set it to the pad value as would be done in GSS.
*/

header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
if (header == NULL || header->data.length < CONFOUNDERLENGTH)
if (header == NULL || header->data.length < hash->hashsize + CONFOUNDERLENGTH)
return KRB5_BAD_MSIZE;

trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
if (trailer == NULL || trailer->data.length < hash->hashsize)
return KRB5_BAD_MSIZE;

padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
if (padding != NULL)
memset(padding->data.data, padding->data.length & 0xFF, padding->data.length);
if (trailer != NULL)
trailer->data.length = 0;

ret = alloc_derived_key(enc, &k1, &d1, key);
if (ret != 0)
Expand Down Expand Up @@ -153,17 +147,23 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
memset(k1.contents + 7, 0xAB, 9);

header->data.length = CONFOUNDERLENGTH;
header->data.length = hash->hashsize + CONFOUNDERLENGTH;

confounder.data = header->data.data + hash->hashsize;
confounder.length = CONFOUNDERLENGTH;

ret = krb5_c_random_make_octets(0, &header->data);
ret = krb5_c_random_make_octets(0, &confounder);
if (ret != 0)
goto cleanup;

ret = krb5_hmac_iov(hash, &k2, data, num_data, &trailer->data);
checksum.data = header->data.data;
checksum.length = hash->hashsize;

ret = krb5_hmac_iov(hash, &k2, data, num_data, &checksum);
if (ret != 0)
goto cleanup;

ret = krb5_hmac(hash, &k1, 1, &trailer->data, &d3);
ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
if (ret != 0)
goto cleanup;

Expand Down Expand Up @@ -202,6 +202,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
krb5_crypto_iov *header, *trailer;
krb5_keyblock k1, k2, k3;
krb5_data d1, d2, d3;
krb5_data checksum;
krb5_keyusage ms_usage;
char salt_data[14];
krb5_data salt;
Expand All @@ -210,11 +211,11 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
d1.data = d2.data = d3.data = NULL;

header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
if (header == NULL || header->data.length != CONFOUNDERLENGTH)
if (header == NULL || header->data.length != hash->hashsize + CONFOUNDERLENGTH)
return KRB5_BAD_MSIZE;

trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
if (trailer == NULL || header->data.length != hash->hashsize)
if (trailer == NULL || trailer->data.length != 0)
return KRB5_BAD_MSIZE;

ret = alloc_derived_key(enc, &k1, &d1, key);
Expand Down Expand Up @@ -251,19 +252,31 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
memset(k1.contents + 7, 0xAB, 9);

ret = krb5_hmac(hash, &k1, 1, &trailer->data, &d3);
checksum.data = header->data.data;
checksum.length = hash->hashsize;

ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
if (ret != 0)
goto cleanup;

/* Adjust pointers so confounder is at start of header */

header->data.length -= hash->hashsize;
header->data.data += hash->hashsize;

ret = enc->decrypt_iov(&k3, ivec, data, num_data);

header->data.length += hash->hashsize;
header->data.data -= hash->hashsize;

if (ret != 0)
goto cleanup;

ret = krb5_hmac_iov(hash, &k2, data, num_data, &d1);
if (ret != 0)
goto cleanup;

if (memcmp(trailer->data.data, d1.data, hash->hashsize) != 0) {
if (memcmp(header->data.data, d1.data, hash->hashsize) != 0) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
goto cleanup;
}
Expand Down

0 comments on commit e56fd08

Please sign in to comment.