const krb5_keyblock *key, krb5_keyusage usage,
const krb5_data *input, krb5_data *output)
{
- int i;
+ const struct krb5_keytypes *ktp;
const struct krb5_enc_provider *enc;
- size_t blocksize, keybytes, keylength;
+ size_t keylength;
krb5_error_code ret;
unsigned char constantdata[K5CLENGTH];
krb5_data datain;
unsigned char *kcdata;
krb5_keyblock kc;
- for (i=0; i<krb5_enctypes_length; i++) {
- if (krb5_enctypes_list[i].etype == key->enctype)
- break;
- }
+ ktp = find_enctype(key->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
- if (i == krb5_enctypes_length)
- return(KRB5_BAD_ENCTYPE);
+ /*
+ * key->length will be tested in enc->encrypt.
+ * output->length will be tested in krb5_hmac.
+ */
- enc = krb5_enctypes_list[i].enc;
-
- /* allocate and set to-be-derived keys */
-
- blocksize = enc->block_size;
- keybytes = enc->keybytes;
+ /* Allocate and set to-be-derived keys. */
keylength = enc->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);
+ kcdata = malloc(keylength);
+ if (kcdata == NULL)
+ return ENOMEM;
kc.contents = kcdata;
kc.length = keylength;
- /* derive the key */
+ /* Derive the key. */
datain.data = (char *) constantdata;
datain.length = K5CLENGTH;
datain.data[4] = (char) 0x99;
- if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0)
+ ret = krb5_derive_key(enc, key, &kc, &datain);
+ if (ret)
goto cleanup;
/* hash the data */
datain = *input;
- if ((ret = krb5_hmac(hash, &kc, 1, &datain, output)) != 0)
+ ret = krb5_hmac(hash, &kc, 1, &datain, output);
+ if (ret)
memset(output->data, 0, output->length);
- /* ret is set correctly by the prior call */
-
cleanup:
- memset(kcdata, 0, keylength);
-
- free(kcdata);
-
- return(ret);
+ zapfree(kcdata, keylength);
+ return ret;
}
krb5_error_code
const krb5_crypto_iov *data, size_t num_data,
krb5_data *output)
{
- int i;
+ const struct krb5_keytypes *ktp;
const struct krb5_enc_provider *enc;
- size_t blocksize, keybytes, keylength;
+ size_t keylength;
krb5_error_code ret;
unsigned char constantdata[K5CLENGTH];
krb5_data datain;
unsigned char *kcdata;
krb5_keyblock kc;
- for (i=0; i<krb5_enctypes_length; i++) {
- if (krb5_enctypes_list[i].etype == key->enctype)
- break;
- }
-
- if (i == krb5_enctypes_length)
- return(KRB5_BAD_ENCTYPE);
+ ktp = find_enctype(key->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
- enc = krb5_enctypes_list[i].enc;
+ /*
+ * key->length will be tested in enc->encrypt.
+ * output->length will be tested in krb5_hmac.
+ */
- /* allocate and set to-be-derived keys */
+ /* Allocate and set to-be-derived keys. */
- blocksize = enc->block_size;
- keybytes = enc->keybytes;
keylength = enc->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);
+ kcdata = malloc(keylength);
+ if (kcdata == NULL)
+ return ENOMEM;
kc.contents = kcdata;
kc.length = keylength;
- /* derive the key */
+ /* Derive the key. */
datain.data = (char *) constantdata;
datain.length = K5CLENGTH;
datain.data[4] = (char) 0x99;
- if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0)
+ ret = krb5_derive_key(enc, key, &kc, &datain);
+ if (ret)
goto cleanup;
- /* hash the data */
+ /* Hash the data. */
- if ((ret = krb5int_hmac_iov(hash, &kc, data, num_data, output)) != 0)
+ ret = krb5int_hmac_iov(hash, &kc, data, num_data, output);
+ if (ret)
memset(output->data, 0, output->length);
- /* ret is set correctly by the prior call */
-
cleanup:
- memset(kcdata, 0, keylength);
-
- free(kcdata);
+ zapfree(kcdata, keylength);
return(ret);
}
const krb5_keyblock *inkey, krb5_keyblock *outkey,
const krb5_data *in_constant)
{
- size_t blocksize, keybytes, keylength, n;
- unsigned char *inblockdata, *outblockdata, *rawkey;
+ size_t blocksize, keybytes, n;
+ unsigned char *inblockdata = NULL, *outblockdata = NULL, *rawkey = NULL;
krb5_data inblock, outblock;
+ krb5_error_code ret;
blocksize = enc->block_size;
keybytes = enc->keybytes;
- keylength = enc->keylength;
- if ((inkey->length != keylength) ||
- (outkey->length != keylength))
- return(KRB5_CRYPTO_INTERNAL);
+ if (inkey->length != enc->keylength || outkey->length != enc->keylength)
+ return KRB5_CRYPTO_INTERNAL;
- /* allocate and set up buffers */
-
- if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
- return(ENOMEM);
-
- if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
- free(inblockdata);
- return(ENOMEM);
- }
-
- if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
- free(outblockdata);
- free(inblockdata);
- return(ENOMEM);
- }
+ /* Allocate and set up buffers. */
+ inblockdata = k5alloc(blocksize, &ret);
+ if (ret)
+ goto cleanup;
+ outblockdata = k5alloc(blocksize, &ret);
+ if (ret)
+ goto cleanup;
+ rawkey = k5alloc(keybytes, &ret);
+ if (ret)
+ goto cleanup;
inblock.data = (char *) inblockdata;
inblock.length = blocksize;
outblock.data = (char *) outblockdata;
outblock.length = blocksize;
- /* initialize the input block */
+ /* Initialize the input block. */
if (in_constant->length == inblock.length) {
memcpy(inblock.data, in_constant->data, inblock.length);
inblock.length*8, (unsigned char *) inblock.data);
}
- /* loop encrypting the blocks until enough key bytes are generated */
+ /* Loop encrypting the blocks until enough key bytes are generated */
n = 0;
while (n < keybytes) {
- (*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+ ret = (*enc->encrypt)(inkey, 0, &inblock, &outblock);
+ if (ret)
+ goto cleanup;
if ((keybytes - n) <= outblock.length) {
- memcpy(rawkey+n, outblock.data, (keybytes - n));
+ memcpy(rawkey + n, outblock.data, (keybytes - n));
break;
}
inblock.data = (char *) rawkey;
inblock.length = keybytes;
- (*(enc->make_key))(&inblock, outkey);
-
- /* clean memory, free resources and exit */
-
- memset(inblockdata, 0, blocksize);
- memset(outblockdata, 0, blocksize);
- memset(rawkey, 0, keybytes);
+ ret = (*enc->make_key)(&inblock, outkey);
+ if (ret)
+ goto cleanup;
- free(rawkey);
- free(outblockdata);
- free(inblockdata);
-
- return(0);
+cleanup:
+ zapfree(inblockdata, blocksize);
+ zapfree(outblockdata, blocksize);
+ zapfree(rawkey, keybytes);
+ return ret;
}
const krb5_keyblock *inkey, krb5_data *outrnd,
const krb5_data *in_constant)
{
- size_t blocksize, keybytes, keylength, n;
- unsigned char *inblockdata, *outblockdata, *rawkey;
+ size_t blocksize, keybytes, n;
+ unsigned char *inblockdata = NULL, *outblockdata = NULL, *rawkey = NULL;
krb5_data inblock, outblock;
+ krb5_error_code ret;
blocksize = enc->block_size;
keybytes = enc->keybytes;
- keylength = enc->keylength;
-
- if ((inkey->length != keylength) ||
- (outrnd->length != keybytes))
- return(KRB5_CRYPTO_INTERNAL);
- /* allocate and set up buffers */
+ if (inkey->length != enc->keylength || outrnd->length != keybytes)
+ return KRB5_CRYPTO_INTERNAL;
- if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
- return(ENOMEM);
+ /* Allocate and set up buffers. */
- if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
- free(inblockdata);
- return(ENOMEM);
- }
-
- if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
- free(outblockdata);
- free(inblockdata);
- return(ENOMEM);
- }
+ inblockdata = k5alloc(blocksize, &ret);
+ if (ret)
+ goto cleanup;
+ outblockdata = k5alloc(blocksize, &ret);
+ if (ret)
+ goto cleanup;
+ rawkey = k5alloc(keybytes, &ret);
+ if (ret)
+ goto cleanup;
inblock.data = (char *) inblockdata;
inblock.length = blocksize;
outblock.data = (char *) outblockdata;
outblock.length = blocksize;
- /* initialize the input block */
-
+ /* Initialize the input block. */
if (in_constant->length == inblock.length) {
memcpy(inblock.data, in_constant->data, inblock.length);
} else {
inblock.length*8, (unsigned char *) inblock.data);
}
- /* loop encrypting the blocks until enough key bytes are generated */
-
+ /* Loop encrypting the blocks until enough key bytes are generated. */
n = 0;
while (n < keybytes) {
- (*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+ ret = (*enc->encrypt)(inkey, 0, &inblock, &outblock);
+ if (ret)
+ goto cleanup;
if ((keybytes - n) <= outblock.length) {
- memcpy(rawkey+n, outblock.data, (keybytes - n));
+ memcpy(rawkey + n, outblock.data, (keybytes - n));
break;
}
n += outblock.length;
}
- /* postprocess the key */
-
- memcpy (outrnd->data, rawkey, keybytes);
-
- /* clean memory, free resources and exit */
-
- memset(inblockdata, 0, blocksize);
- memset(outblockdata, 0, blocksize);
- memset(rawkey, 0, keybytes);
-
- free(rawkey);
- free(outblockdata);
- free(inblockdata);
-
- return(0);
-}
-
-#if 0
-#include "etypes.h"
-void
-krb5_random2key (krb5_enctype enctype, krb5_data *inblock,
- krb5_keyblock *outkey)
-{
- int i;
- const struct krb5_enc_provider *enc;
-
- for (i=0; i<krb5_enctypes_length; i++) {
- if (krb5_enctypes_list[i].etype == enctype)
- break;
- }
-
- if (i == krb5_enctypes_length)
- abort ();
-
- enc = krb5_enctypes_list[i].enc;
+ /* Postprocess the key. */
+ memcpy(outrnd->data, rawkey, keybytes);
- enc->make_key (inblock, outkey);
+cleanup:
+ zapfree(inblockdata, blocksize);
+ zapfree(outblockdata, blocksize);
+ zapfree(rawkey, keybytes);
+ return ret;
}
-#endif
#include "k5-int.h"
-void krb5_dk_encrypt_length
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- size_t input, size_t *length);
-
-krb5_error_code krb5_dk_encrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec,
- const krb5_data *input, krb5_data *output);
-
-void krb5int_aes_encrypt_length
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- size_t input, size_t *length);
-
-krb5_error_code krb5int_aes_dk_encrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec,
- const krb5_data *input, krb5_data *output);
-
-krb5_error_code krb5_dk_decrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec, const krb5_data *input,
- krb5_data *arg_output);
-
-krb5_error_code krb5int_aes_dk_decrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec, const krb5_data *input,
- krb5_data *arg_output);
-
-krb5_error_code krb5int_dk_string_to_key
-(const struct krb5_enc_provider *enc,
- const krb5_data *string, const krb5_data *salt,
- const krb5_data *params, krb5_keyblock *key);
-
-krb5_error_code krb5_derive_key
-(const struct krb5_enc_provider *enc,
- const krb5_keyblock *inkey,
- krb5_keyblock *outkey, const krb5_data *in_constant);
-
-krb5_error_code krb5_dk_make_checksum
-(const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *input, krb5_data *output);
+void krb5_dk_encrypt_length(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ size_t input, size_t *length);
+
+krb5_error_code krb5_dk_encrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output);
+
+void krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ size_t input, size_t *length);
+
+krb5_error_code krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ const krb5_data *input,
+ krb5_data *output);
+
+krb5_error_code krb5_dk_decrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec, const krb5_data *input,
+ krb5_data *arg_output);
+
+krb5_error_code krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ const krb5_data *input,
+ krb5_data *arg_output);
+
+krb5_error_code krb5int_dk_string_to_key(const struct krb5_enc_provider *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+
+krb5_error_code krb5_derive_key(const struct krb5_enc_provider *enc,
+ const krb5_keyblock *inkey,
+ krb5_keyblock *outkey,
+ const krb5_data *in_constant);
+
+krb5_error_code krb5_dk_make_checksum(const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *input,
+ krb5_data *output);
krb5_error_code
krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_crypto_iov *data, size_t num_data,
- krb5_data *output);
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output);
krb5_error_code
krb5_derive_random(const struct krb5_enc_provider *enc,
extern const struct krb5_aead_provider krb5int_aead_dk;
extern const struct krb5_aead_provider krb5int_aead_aes;
-
-/* CCM */
-
-void
-krb5int_ccm_encrypt_length(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- size_t inputlen, size_t *length);
-
-extern const struct krb5_aead_provider krb5int_aead_ccm;
-
-krb5_error_code krb5int_ccm_encrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec, const krb5_data *input,
- krb5_data *arg_output);
-
-krb5_error_code krb5int_ccm_decrypt
-(const struct krb5_enc_provider *enc,
- const struct krb5_hash_provider *hash,
- const krb5_keyblock *key, krb5_keyusage usage,
- const krb5_data *ivec, const krb5_data *input,
- krb5_data *arg_output);
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
- *
+ *
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
/* E(Confounder | Plaintext | Pad) | Checksum */
- ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize);
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING,
+ &blocksize);
if (ret != 0)
return ret;
- ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &hmacsize);
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER,
+ &hmacsize);
if (ret != 0)
return ret;
return KRB5_BAD_MSIZE;
if (blocksize != 0) {
- /* Check that the input data is correctly padded */
+ /* Check that the input data is correctly padded. */
if (plainlen % blocksize)
padsize = blocksize - (plainlen % blocksize);
}
}
ke.length = enc->keylength;
- ke.contents = malloc(ke.length);
- if (ke.contents == NULL) {
- ret = ENOMEM;
+ ke.contents = k5alloc(ke.length, &ret);
+ if (ret != 0)
goto cleanup;
- }
ki.length = enc->keylength;
- ki.contents = malloc(ki.length);
- if (ki.contents == NULL) {
- ret = ENOMEM;
+ ki.contents = k5alloc(ki.length, &ret);
+ if (ret != 0)
goto cleanup;
- }
- cksum = (unsigned char *)malloc(hash->hashsize);
- if (cksum == NULL) {
- ret = ENOMEM;
+ cksum = k5alloc(hash->hashsize, &ret);
+ if (ret != 0)
goto cleanup;
- }
- /* derive the keys */
+ /* Derive the keys. */
d1.data = (char *)constantdata;
d1.length = K5CLENGTH;
if (ret != 0)
goto cleanup;
- /* generate confounder */
+ /* Generate confounder. */
header->data.length = enc->block_size;
if (ret != 0)
goto cleanup;
- /* hash the plaintext */
+ /* Hash the plaintext. */
d2.length = hash->hashsize;
d2.data = (char *)cksum;
if (ret != 0)
goto cleanup;
- /* encrypt the plaintext (header | data | padding) */
+ /* Encrypt the plaintext (header | data | padding) */
assert(enc->encrypt_iov != NULL);
- ret = enc->encrypt_iov(&ke, ivec, data, num_data); /* will update ivec */
+ ret = (*enc->encrypt_iov)(&ke, ivec, data, num_data); /* updates ivec */
if (ret != 0)
goto cleanup;
- /* possibly truncate the hash */
+ /* Possibly truncate the hash */
assert(hmacsize <= d2.length);
memcpy(trailer->data.data, cksum, hmacsize);
trailer->data.length = hmacsize;
cleanup:
- if (ke.contents != NULL) {
- memset(ke.contents, 0, ke.length);
- free(ke.contents);
- }
- if (ki.contents != NULL) {
- memset(ki.contents, 0, ki.length);
- free(ki.contents);
- }
- if (cksum != NULL) {
- free(cksum);
- }
-
+ zapfree(ke.contents, ke.length);
+ zapfree(ki.contents, ki.length);
+ free(cksum);
return ret;
}
krb5_crypto_iov *header, *trailer;
krb5_keyblock ke, ki;
size_t i;
- unsigned int blocksize = 0; /* careful, this is enc block size not confounder len */
+ unsigned int blocksize = 0; /* enc block size, not confounder len */
unsigned int cipherlen = 0;
unsigned int hmacsize = 0;
unsigned char *cksum = NULL;
- if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) {
+ if (krb5int_c_locate_iov(data, num_data,
+ KRB5_CRYPTO_TYPE_STREAM) != NULL) {
return krb5int_c_iov_decrypt_stream(aead, enc, hash, key,
usage, ivec, data, num_data);
}
/* E(Confounder | Plaintext | Pad) | Checksum */
- ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize);
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING,
+ &blocksize);
if (ret != 0)
return ret;
- ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &hmacsize);
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER,
+ &hmacsize);
if (ret != 0)
return ret;
return KRB5_BAD_MSIZE;
ke.length = enc->keylength;
- ke.contents = malloc(ke.length);
- if (ke.contents == NULL) {
- ret = ENOMEM;
+ ke.contents = k5alloc(ke.length, &ret);
+ if (ret != 0)
goto cleanup;
- }
ki.length = enc->keylength;
- ki.contents = malloc(ki.length);
- if (ki.contents == NULL) {
- ret = ENOMEM;
+ ki.contents = k5alloc(ki.length, &ret);
+ if (ret != 0)
goto cleanup;
- }
- cksum = (unsigned char *)malloc(hash->hashsize);
- if (cksum == NULL) {
- ret = ENOMEM;
+ cksum = k5alloc(hash->hashsize, &ret);
+ if (ret != 0)
goto cleanup;
- }
- /* derive the keys */
+ /* Derive the keys. */
d1.data = (char *)constantdata;
d1.length = K5CLENGTH;
if (ret != 0)
goto cleanup;
- /* decrypt the plaintext (header | data | padding) */
+ /* Decrypt the plaintext (header | data | padding). */
assert(enc->decrypt_iov != NULL);
- ret = enc->decrypt_iov(&ke, ivec, data, num_data); /* will update ivec */
+ ret = (*enc->decrypt_iov)(&ke, ivec, data, num_data); /* updates ivec */
if (ret != 0)
goto cleanup;
- /* verify the hash */
+ /* Verify the hash. */
d1.length = hash->hashsize; /* non-truncated length */
d1.data = (char *)cksum;
if (ret != 0)
goto cleanup;
- /* compare only the possibly truncated length */
+ /* Compare only the possibly truncated length. */
if (memcmp(cksum, trailer->data.data, hmacsize) != 0) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
goto cleanup;
}
cleanup:
- if (ke.contents != NULL) {
- memset(ke.contents, 0, ke.length);
- free(ke.contents);
- }
- if (ki.contents != NULL) {
- memset(ki.contents, 0, ki.length);
- free(ki.contents);
- }
- if (cksum != NULL) {
- free(cksum);
- }
+ zapfree(ke.contents, ke.length);
+ zapfree(ki.contents, ki.length);
+ free(cksum);
return ret;
}
krb5int_dk_encrypt_iov,
krb5int_dk_decrypt_iov
};
-
int ivec_mode)
{
krb5_error_code ret;
- size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen;
- unsigned char *plaindata, *kedata, *kidata, *cksum, *cn;
+ size_t hashsize, blocksize, keylength, enclen, plainlen;
+ unsigned char *plaindata = NULL, *kedata = NULL, *kidata = NULL;
+ unsigned char *cksum = NULL, *cn;
krb5_keyblock ke, ki;
krb5_data d1, d2;
unsigned char constantdata[K5CLENGTH];
- /* allocate and set up ciphertext and to-be-derived keys */
-
hashsize = hash->hashsize;
blocksize = enc->block_size;
- keybytes = enc->keybytes;
keylength = enc->keylength;
if (hmacsize == 0)
enclen = input->length - hmacsize;
- 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);
- }
+ /* Allocate and set up ciphertext and to-be-derived keys. */
+ kedata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ kidata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ plaindata = k5alloc(enclen, &ret);
+ if (ret != 0)
+ goto cleanup;
+ cksum = k5alloc(hashsize, &ret);
+ if (ret != 0)
+ goto cleanup;
ke.contents = kedata;
ke.length = keylength;
ki.contents = kidata;
ki.length = keylength;
- /* derive the keys */
+ /* Derive the keys. */
d1.data = (char *) constantdata;
d1.length = K5CLENGTH;
d1.data[4] = (char) 0xAA;
- if ((ret = krb5_derive_key(enc, key, &ke, &d1)) != 0)
+ ret = krb5_derive_key(enc, key, &ke, &d1);
+ if (ret != 0)
goto cleanup;
d1.data[4] = 0x55;
- if ((ret = krb5_derive_key(enc, key, &ki, &d1)) != 0)
+ ret = krb5_derive_key(enc, key, &ki, &d1);
+ if (ret != 0)
goto cleanup;
/* decrypt the ciphertext */
d2.length = enclen;
d2.data = (char *) plaindata;
- if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0)
+ ret = (*enc->decrypt)(&ke, ivec, &d1, &d2);
+ if (ret != 0)
goto cleanup;
if (ivec != NULL && ivec->length == blocksize) {
cn = (unsigned char *) d1.data + d1.length - blocksize;
else if (ivec_mode == 1) {
int nblocks = (d1.length + blocksize - 1) / blocksize;
- cn = d1.data + blocksize * (nblocks - 2);
+ cn = (unsigned char *) d1.data + blocksize * (nblocks - 2);
} else
abort();
} else
cn = NULL;
- /* verify the hash */
+ /* Verify the hash. */
d1.length = hashsize;
d1.data = (char *) cksum;
- if ((ret = krb5_hmac(hash, &ki, 1, &d2, &d1)) != 0)
+ ret = krb5_hmac(hash, &ki, 1, &d2, &d1);
+ if (ret != 0)
goto cleanup;
if (memcmp(cksum, input->data+enclen, hmacsize) != 0) {
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. */
+ /*
+ * Because this encoding isn't self-describing wrt length, the
+ * best we can do here is to compute the length minus the
+ * confounder.
+ */
plainlen = enclen - blocksize;
if (output->length < plainlen)
- return(KRB5_BAD_MSIZE);
+ return KRB5_BAD_MSIZE;
output->length = plainlen;
if (cn != NULL)
memcpy(ivec->data, cn, blocksize);
- 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);
+ zapfree(kedata, keylength);
+ zapfree(kidata, keylength);
+ zapfree(plaindata, enclen);
+ zapfree(cksum, hashsize);
+ return ret;
}
-
#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
-/* the spec says that the confounder size and padding are specific to
- the encryption algorithm. This code (dk_encrypt_length and
- dk_encrypt) assume the confounder is always the blocksize, and the
- padding is always zero bytes up to the blocksize. If these
- assumptions ever fails, the keytype table should be extended to
- include these bits of info. */
+/*
+ * The spec says that the confounder size and padding are specific to
+ * the encryption algorithm. This code (dk_encrypt_length and
+ * dk_encrypt) assume the confounder is always the blocksize, and the
+ * padding is always zero bytes up to the blocksize. If these
+ * assumptions ever fails, the keytype table should be extended to
+ * include these bits of info.
+ */
void
krb5_dk_encrypt_length(const struct krb5_enc_provider *enc,
blocksize = enc->block_size;
hashsize = hash->hashsize;
- *length = krb5_roundup(blocksize+inputlen, blocksize) + hashsize;
+ *length = krb5_roundup(blocksize + inputlen, blocksize) + hashsize;
}
krb5_error_code
const krb5_data *ivec, const krb5_data *input,
krb5_data *output)
{
- size_t blocksize, keybytes, keylength, plainlen, enclen;
+ size_t blocksize, keylength, plainlen, enclen;
krb5_error_code ret;
unsigned char constantdata[K5CLENGTH];
krb5_data d1, d2;
- unsigned char *plaintext, *kedata, *kidata;
+ unsigned char *plaintext = NULL, *kedata = NULL, *kidata = NULL;
char *cn;
krb5_keyblock ke, ki;
- /* allocate and set up plaintext and to-be-derived keys */
-
blocksize = enc->block_size;
- keybytes = enc->keybytes;
keylength = enc->keylength;
- plainlen = krb5_roundup(blocksize+input->length, blocksize);
+ plainlen = krb5_roundup(blocksize + input->length, blocksize);
krb5_dk_encrypt_length(enc, hash, input->length, &enclen);
- /* key->length, ivec will be tested in enc->encrypt */
+ /* 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);
- }
+ /* Allocate and set up plaintext and to-be-derived keys. */
+
+ kedata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ kidata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ plaintext = k5alloc(plainlen, &ret);
+ if (ret != 0)
+ goto cleanup;
ke.contents = kedata;
ke.length = keylength;
ki.contents = kidata;
ki.length = keylength;
- /* derive the keys */
+ /* Derive the keys. */
d1.data = (char *) constantdata;
d1.length = K5CLENGTH;
d1.data[4] = (char) 0xAA;
- if ((ret = krb5_derive_key(enc, key, &ke, &d1)))
+ ret = krb5_derive_key(enc, key, &ke, &d1);
+ if (ret != 0)
goto cleanup;
d1.data[4] = 0x55;
- if ((ret = krb5_derive_key(enc, key, &ki, &d1)))
+ ret = krb5_derive_key(enc, key, &ki, &d1);
+ if (ret != 0)
goto cleanup;
- /* put together the plaintext */
+ /* Put together the plaintext. */
d1.length = blocksize;
d1.data = (char *) plaintext;
- if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &d1)))
+ ret = krb5_c_random_make_octets(/* XXX */ 0, &d1);
+ if (ret != 0)
goto cleanup;
- memcpy(plaintext+blocksize, input->data, input->length);
+ memcpy(plaintext + blocksize, input->data, input->length);
- memset(plaintext+blocksize+input->length, 0,
- plainlen - (blocksize+input->length));
+ memset(plaintext + blocksize + input->length, 0,
+ plainlen - (blocksize + input->length));
- /* encrypt the plaintext */
+ /* Encrypt the plaintext. */
d1.length = plainlen;
d1.data = (char *) plaintext;
d2.length = plainlen;
d2.data = output->data;
- if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2))))
+ ret = (*enc->encrypt)(&ke, ivec, &d1, &d2);
+ if (ret != 0)
goto cleanup;
if (ivec != NULL && ivec->length == blocksize)
else
cn = NULL;
- /* hash the plaintext */
+ /* Hash the plaintext. */
d2.length = enclen - plainlen;
d2.data = output->data+plainlen;
output->length = enclen;
- if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) {
+ ret = krb5_hmac(hash, &ki, 1, &d1, &d2);
+ if (ret != 0) {
memset(d2.data, 0, d2.length);
goto cleanup;
}
- /* update ivec */
+ /* Update ivec. */
if (cn != NULL)
memcpy(ivec->data, cn, blocksize);
- /* 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);
+ zapfree(kedata, keylength);
+ zapfree(kidata, keylength);
+ zapfree(plaintext, plainlen);
+ return ret;
}
/* Not necessarily "AES", per se, but "a CBC+CTS mode block cipher
krb5_error_code ret;
unsigned char constantdata[K5CLENGTH];
krb5_data d1, d2;
- unsigned char *plaintext, *kedata, *kidata;
+ unsigned char *plaintext = NULL, *kedata = NULL, *kidata = NULL;
char *cn;
krb5_keyblock ke, ki;
/* key->length, ivec will be tested in enc->encrypt */
if (output->length < enclen)
- return(KRB5_BAD_MSIZE);
+ 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);
- }
+ kedata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ kidata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+ plaintext = k5alloc(plainlen, &ret);
+ if (ret != 0)
+ goto cleanup;
ke.contents = kedata;
ke.length = keylength;
ki.contents = kidata;
ki.length = keylength;
- /* derive the keys */
+ /* Derive the keys. */
d1.data = (char *) constantdata;
d1.length = K5CLENGTH;
d1.data[4] = (char) 0xAA;
- if ((ret = krb5_derive_key(enc, key, &ke, &d1)))
+ ret = krb5_derive_key(enc, key, &ke, &d1);
+ if (ret != 0)
goto cleanup;
d1.data[4] = 0x55;
- if ((ret = krb5_derive_key(enc, key, &ki, &d1)))
+ ret = krb5_derive_key(enc, key, &ki, &d1);
+ if (ret != 0)
goto cleanup;
/* put together the plaintext */
d1.length = blocksize;
d1.data = (char *) plaintext;
- if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &d1)))
+ ret = krb5_c_random_make_octets(NULL, &d1);
+ if (ret != 0)
goto cleanup;
- memcpy(plaintext+blocksize, input->data, input->length);
+ memcpy(plaintext + blocksize, input->data, input->length);
/* Ciphertext stealing; there should be no more. */
if (plainlen != blocksize + input->length)
abort();
- /* encrypt the plaintext */
+ /* Encrypt the plaintext. */
d1.length = plainlen;
d1.data = (char *) plaintext;
d2.length = plainlen;
d2.data = output->data;
- if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2))))
+ ret = (*enc->encrypt)(&ke, ivec, &d1, &d2);
+ if (ret != 0)
goto cleanup;
if (ivec != NULL && ivec->length == blocksize) {
} else
cn = NULL;
- /* hash the plaintext */
+ /* Hash the plaintext. */
d2.length = enclen - plainlen;
d2.data = output->data+plainlen;
if (d2.length != 96 / 8)
abort();
- if ((ret = trunc_hmac(hash, &ki, 1, &d1, &d2))) {
+ ret = trunc_hmac(hash, &ki, 1, &d1, &d2);
+ if (ret != 0) {
memset(d2.data, 0, d2.length);
goto cleanup;
}
output->length = enclen;
- /* update ivec */
- if (cn != NULL) {
+ /* Update ivec. */
+ if (cn != NULL)
memcpy(ivec->data, cn, blocksize);
-#if 0
- {
- int i;
- printf("\n%s: output:", __func__);
- for (i = 0; i < output->length; i++) {
- if (i % 16 == 0)
- printf("\n%s: ", __func__);
- printf(" %02x", i[(unsigned char *)output->data]);
- }
- printf("\n%s: outputIV:", __func__);
- for (i = 0; i < ivec->length; i++) {
- if (i % 16 == 0)
- printf("\n%s: ", __func__);
- printf(" %02x", i[(unsigned char *)ivec->data]);
- }
- printf("\n"); fflush(stdout);
- }
-#endif
- }
-
- /* 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);
+ zapfree(kedata, keylength);
+ zapfree(kidata, keylength);
+ zapfree(plaintext, plainlen);
+ return ret;
}
{
krb5_error_code ret;
size_t keybytes, keylength, concatlen;
- unsigned char *concat, *foldstring, *foldkeydata;
+ unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL;
krb5_data indata;
krb5_keyblock foldkey;
- /* key->length is checked by krb5_derive_key */
+ /* key->length is checked by krb5_derive_key. */
keybytes = enc->keybytes;
keylength = enc->keylength;
- concatlen = string->length+(salt?salt->length:0);
+ concatlen = string->length + (salt ? salt->length : 0);
- if ((concat = (unsigned char *) malloc(concatlen)) == NULL)
- return(ENOMEM);
- if ((foldstring = (unsigned char *) malloc(keybytes)) == NULL) {
- free(concat);
- return(ENOMEM);
- }
- if ((foldkeydata = (unsigned char *) malloc(keylength)) == NULL) {
- free(foldstring);
- free(concat);
- return(ENOMEM);
- }
+ concat = k5alloc(concatlen, &ret);
+ if (ret != 0)
+ goto cleanup;
+ foldstring = k5alloc(keybytes, &ret);
+ if (ret != 0)
+ goto cleanup;
+ foldkeydata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
/* construct input string ( = string + salt), fold it, make_key it */
memcpy(concat, string->data, string->length);
if (salt)
- memcpy(concat+string->length, salt->data, salt->length);
+ memcpy(concat + string->length, salt->data, salt->length);
krb5_nfold(concatlen*8, concat, keybytes*8, foldstring);
foldkey.length = keylength;
foldkey.contents = foldkeydata;
- (*(enc->make_key))(&indata, &foldkey);
+ ret = (*enc->make_key)(&indata, &foldkey);
+ if (ret != 0)
+ goto cleanup;
/* now derive the key from this one */
indata.length = kerberos_len;
indata.data = (char *) kerberos;
- if ((ret = krb5_derive_key(enc, &foldkey, key, &indata)))
+ ret = krb5_derive_key(enc, &foldkey, key, &indata);
+ if (ret != 0)
memset(key->contents, 0, key->length);
- /* ret is set correctly by the prior call */
-
- memset(concat, 0, concatlen);
- memset(foldstring, 0, keybytes);
- memset(foldkeydata, 0, keylength);
-
- free(foldkeydata);
- free(foldstring);
- free(concat);
-
- return(ret);
+cleanup:
+ zapfree(concat, concatlen);
+ zapfree(foldstring, keybytes);
+ zapfree(foldkeydata, keylength);
+ return ret;
}