Update the crypto derived key support code to conform to most of the
authorGreg Hudson <ghudson@mit.edu>
Sat, 3 Oct 2009 18:07:44 +0000 (18:07 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sat, 3 Oct 2009 18:07:44 +0000 (18:07 +0000)
current coding practices (except lack of tabs).  Use the helper
functions k5alloc, zapfree, and find_enctype to reduce code size.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22840 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/krb/dk/checksum.c
src/lib/crypto/krb/dk/derive.c
src/lib/crypto/krb/dk/dk.h
src/lib/crypto/krb/dk/dk_aead.c
src/lib/crypto/krb/dk/dk_decrypt.c
src/lib/crypto/krb/dk/dk_encrypt.c
src/lib/crypto/krb/dk/stringtokey.c

index f4b18bf0c4f80a9bfc342bcc804275c959c9d3d0..fb5622a7355a5c09ae44dd4c84a5dad1940a3739 100644 (file)
@@ -36,41 +36,35 @@ krb5_dk_make_checksum(const struct krb5_hash_provider *hash,
                      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;
@@ -79,24 +73,21 @@ krb5_dk_make_checksum(const struct krb5_hash_provider *hash,
 
     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
@@ -105,41 +96,36 @@ krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
                          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;
@@ -148,20 +134,18 @@ krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
 
     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);
 }
index 77b05fa1abcdf3c5e550110dcaf2e982dbd7d7e6..8c8214c125ad05722b95623e3b4f27c211b75fe3 100644 (file)
@@ -32,33 +32,27 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
                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;
@@ -66,7 +60,7 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
     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);
@@ -75,14 +69,16 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
                   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;
        }
 
@@ -96,19 +92,15 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
     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;
 }
 
 
@@ -117,33 +109,28 @@ krb5_derive_random(const struct krb5_enc_provider *enc,
                   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;
@@ -151,8 +138,7 @@ krb5_derive_random(const struct krb5_enc_provider *enc,
     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 {
@@ -160,14 +146,15 @@ krb5_derive_random(const struct krb5_enc_provider *enc,
                   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;
        }
 
@@ -176,42 +163,12 @@ krb5_derive_random(const struct krb5_enc_provider *enc,
        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
index 54d1076c8bec244a22733f56da1996411a3acc16..9ddeb408c897206828ff08ef1abc7f36d4eda562 100644 (file)
 
 #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,
@@ -94,26 +94,3 @@ 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);
index e995f9ae69ab22f0602b46a72271fd6b64eae811..13eb007cdbf3dd05ffdb6d74dd9b5f4df3d41ab9 100644 (file)
@@ -8,7 +8,7 @@
  *   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
@@ -84,11 +84,13 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
 
     /* 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;
 
@@ -110,7 +112,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
        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);
     }
@@ -125,24 +127,18 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
     }
 
     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;
@@ -161,7 +157,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
     if (ret != 0)
        goto cleanup;
 
-    /* generate confounder */
+    /* Generate confounder. */
 
     header->data.length = enc->block_size;
 
@@ -169,7 +165,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
     if (ret != 0)
        goto cleanup;
 
-    /* hash the plaintext */
+    /* Hash the plaintext. */
     d2.length = hash->hashsize;
     d2.data = (char *)cksum;
 
@@ -177,32 +173,23 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
     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;
 }
 
@@ -222,12 +209,13 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
     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);
     }
@@ -237,11 +225,13 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
 
     /* 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;
 
@@ -273,24 +263,18 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
        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;
@@ -309,14 +293,14 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
     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;
 
@@ -324,24 +308,16 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
     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;
 }
@@ -383,4 +359,3 @@ const struct krb5_aead_provider krb5int_aead_aes = {
     krb5int_dk_encrypt_iov,
     krb5int_dk_decrypt_iov
 };
-
index c38c4d5bf3cc688d449fcaa319abb72fdb6cf5d5..1c0358a2d353ada7a79c1ce4f7238ef6aa45c8da 100644 (file)
@@ -71,17 +71,15 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
                                 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)
@@ -91,30 +89,26 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
 
     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;
@@ -123,12 +117,14 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
 
     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 */
@@ -139,7 +135,8 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
     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) {
@@ -147,18 +144,19 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
            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) {
@@ -166,14 +164,16 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
        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;
 
@@ -182,19 +182,10 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc,
     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;
 }
-
index 6596e53ce842f1b4653a679fc2acc0042d5bb78d..b06079c6368ef7ac9980c22a0a39afbdc255168e 100644 (file)
 
 #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,
@@ -45,7 +47,7 @@ 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
@@ -55,46 +57,43 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc,
                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;
@@ -103,28 +102,31 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc,
 
     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;
@@ -132,7 +134,8 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc,
     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)
@@ -140,34 +143,28 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc,
     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
@@ -222,7 +219,7 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
     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;
 
@@ -238,26 +235,24 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
     /* 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;
@@ -266,12 +261,14 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
 
     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 */
@@ -279,16 +276,17 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
     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;
@@ -296,7 +294,8 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
     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) {
@@ -305,54 +304,29 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc,
     } 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;
 }
 
index 0e54b849fff147df410a8345dad68e0859a1d7a0..326565758355a12ed368bb0b21c681900be29618 100644 (file)
@@ -36,34 +36,32 @@ krb5int_dk_string_to_key(const struct krb5_enc_provider *enc,
 {
     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);
 
@@ -72,25 +70,22 @@ krb5int_dk_string_to_key(const struct krb5_enc_provider *enc,
     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;
 }