diff options
author | Luke Howard <lukeh@padl.com> | 2010-05-13 23:12:26 +0000 |
---|---|---|
committer | Luke Howard <lukeh@padl.com> | 2010-05-13 23:12:26 +0000 |
commit | 2a03253b1d561cdd1d1c58d5a4cb110955bc2805 (patch) | |
tree | 67ff99835d5036c3ea10ced28ee3ed41d3c119d5 | |
parent | 90ce6ad65aa7af3db6c8b298e0c295c51be85698 (diff) | |
download | krb5-2a03253b1d561cdd1d1c58d5a4cb110955bc2805.zip krb5-2a03253b1d561cdd1d1c58d5a4cb110955bc2805.tar.gz krb5-2a03253b1d561cdd1d1c58d5a4cb110955bc2805.tar.bz2 |
CCM PRF is now CMAC (similar to RFC 4615)
git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/camellia-ccm@24024 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/lib/crypto/krb/checksum/Makefile.in | 10 | ||||
-rw-r--r-- | src/lib/crypto/krb/checksum/cmac.c | 243 | ||||
-rw-r--r-- | src/lib/crypto/krb/cksumtypes.c | 16 | ||||
-rw-r--r-- | src/lib/crypto/krb/cksumtypes.h | 6 | ||||
-rw-r--r-- | src/lib/crypto/krb/dk/checksum_cmac.c | 219 | ||||
-rw-r--r-- | src/lib/crypto/krb/dk/dk.h | 8 | ||||
-rw-r--r-- | src/lib/crypto/krb/prf/ccm_prf.c | 10 |
7 files changed, 283 insertions, 229 deletions
diff --git a/src/lib/crypto/krb/checksum/Makefile.in b/src/lib/crypto/krb/checksum/Makefile.in index 61b41f2..826afd1 100644 --- a/src/lib/crypto/krb/checksum/Makefile.in +++ b/src/lib/crypto/krb/checksum/Makefile.in @@ -10,12 +10,14 @@ DEFS= PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -STLIBOBJS= cbc.o confounder.o hmac_md5.o unkeyed.o +STLIBOBJS= cbc.o cmac.o confounder.o hmac_md5.o unkeyed.o -OBJS= $(OUTPRE)cbc.$(OBJEXT) $(OUTPRE)confounder.$(OBJEXT) \ - $(OUTPRE)hmac_md5.$(OBJEXT) $(OUTPRE)unkeyed.$(OBJEXT) +OBJS= $(OUTPRE)cbc.$(OBJEXT) $(OUTPRE)cmac.$(OBJECT) \ + $(OUTPRE)confounder.$(OBJEXT) $(OUTPRE)hmac_md5.$(OBJEXT) \ + $(OUTPRE)unkeyed.$(OBJEXT) -SRCS= $(srcdir)/cbc.c $(srcdir)/confounder.c $(srcdir)/hmac_md5.c \ +SRCS= $(srcdir)/cbc.c $(srcdir)/cmac.c \ + $(srcdir)/confounder.c $(srcdir)/hmac_md5.c \ $(srcdir)/unkeyed.c ##DOS##LIBOBJS = $(OBJS) diff --git a/src/lib/crypto/krb/checksum/cmac.c b/src/lib/crypto/krb/checksum/cmac.c new file mode 100644 index 0000000..2356198 --- /dev/null +++ b/src/lib/crypto/krb/checksum/cmac.c @@ -0,0 +1,243 @@ +/* + * lib/crypto/krb/checksum/cmac.c + * + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * 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 + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Portions Copyright (C) The Internet Society (2006). + * + * This document is subject to the rights, licenses and restrictions + * contained in BCP 78, and except as set forth therein, the authors + * retain all their rights. + * + * This document and the information contained herein are provided on an + * "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + * OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET + * ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + * INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "etypes.h" +#include "aead.h" +#include "etypes.h" +#include "cksumtypes.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +#define BLOCK_SIZE 16 + +static unsigned char const_Rb[BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 +}; + +static unsigned char const_Zero[BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void +xor_128(unsigned char *a, unsigned char *b, unsigned char *out) +{ + int z; + + for (z = 0; z < BLOCK_SIZE / 4; z++) { + unsigned char *aptr = &a[z * 4]; + unsigned char *bptr = &b[z * 4]; + unsigned char *outptr = &out[z * 4]; + + store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr); + } +} + +static void +leftshift_onebit(unsigned char *input, unsigned char *output) +{ + int i; + unsigned char overflow = 0; + + for (i = BLOCK_SIZE - 1; i >= 0; i--) { + output[i] = input[i] << 1; + output[i] |= overflow; + overflow = (input[i] & 0x80) ? 1 : 0; + } +} + +static krb5_error_code +generate_subkey(const struct krb5_enc_provider *enc, + krb5_key key, + unsigned char *K1, + unsigned char *K2) +{ + unsigned char Z[BLOCK_SIZE]; + unsigned char L[BLOCK_SIZE]; + unsigned char tmp[BLOCK_SIZE]; + krb5_crypto_iov iov[1]; + krb5_data d; + krb5_error_code ret; + + memset(Z, 0, sizeof(Z)); + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data((char *)Z, sizeof(Z)); + + d = make_data((char *)L, BLOCK_SIZE); + + /* + * CBC in terms of CBC-MAC; at the cost of an additional XOR, + * this avoids needing to extend the SPI interface (because we + * need both the CBC-MAC function from the CCM provider and + * the CBC function from the CTS provider). + */ + ret = enc->cbc_mac(key, iov, 1, NULL, &d); + if (ret != 0) + return ret; + + xor_128(const_Zero, L, L); + + if ((L[0] & 0x80) == 0) { + leftshift_onebit(L, K1); + } else { + leftshift_onebit(L, tmp); + xor_128(tmp, const_Rb, K1); + } + + if ((K1[0] & 0x80) == 0) { + leftshift_onebit(K1, K2); + } else { + leftshift_onebit(K1, tmp); + xor_128(tmp, const_Rb, K2); + } + + return 0; +} + +static void +padding(unsigned char *lastb, unsigned char *pad, int length) +{ + int j; + + /* original last block */ + for (j = 0; j < BLOCK_SIZE; j++) { + if (j < length) { + pad[j] = lastb[j]; + } else if (j == length) { + pad[j] = 0x80; + } else { + pad[j] = 0x00; + } + } +} + +/* + * Implementation of CMAC algorithm. When used with AES, this function + * is compatible with RFC 4493. + */ +krb5_error_code +krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = ctp->enc; + unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE]; + unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE]; + unsigned char input[BLOCK_SIZE]; + unsigned int n, i, flag; + krb5_error_code ret; + struct iov_block_state iov_state; + unsigned int length; + krb5_data ivec; + krb5_crypto_iov iov[1]; + krb5_data d; + + assert(enc->cbc_mac != NULL); + + if (enc->block_size != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + for (i = 0, length = 0; i < num_data; i++) { + const krb5_crypto_iov *piov = &data[i]; + + if (SIGN_IOV(piov)) + length += piov->data.length; + } + + ret = generate_subkey(enc, key, K1, K2); + if (ret != 0) + return ret; + + n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; + + if (n == 0) { + n = 1; + flag = 0; + } else { + flag = ((length % BLOCK_SIZE) == 0); + } + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data((char *)input, BLOCK_SIZE); + + memset(Y, 0, BLOCK_SIZE); + + ivec = make_data((char *)Y, BLOCK_SIZE); + d = make_data((char *)Y, BLOCK_SIZE); + + IOV_BLOCK_STATE_INIT(&iov_state); + iov_state.include_sign_only = 1; + + for (i = 0; i < n - 1; i++) { + krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state); + + ret = enc->cbc_mac(key, iov, 1, &ivec, &d); + if (ret != 0) + return ret; + } + + krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state); + + if (flag) { + /* last block is complete block */ + xor_128(input, K1, M_last); + } else { + padding(input, padded, length % BLOCK_SIZE); + xor_128(padded, K2, M_last); + } + + iov[0].data = make_data((char *)M_last, BLOCK_SIZE); + + ret = enc->cbc_mac(key, iov, 1, &ivec, &d); + if (ret != 0) + return ret; + + assert(output->length >= d.length); + + output->length = d.length; + memcpy(output->data, d.data, d.length); + + return ret; +} + diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c index f0f4076..d757889 100644 --- a/src/lib/crypto/krb/cksumtypes.c +++ b/src/lib/crypto/krb/cksumtypes.c @@ -103,14 +103,14 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { { CKSUMTYPE_CMAC_128_AES128, "cmac-128-aes128", { 0 }, "CMAC AES128 key", &krb5int_enc_aes128_ctr, NULL, - krb5int_cmac_checksum, NULL, - 16, 16, 0, &krb5int_enc_aes128 }, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, { CKSUMTYPE_CMAC_128_AES256, "cmac-128-aes256", { 0 }, "CMAC AES256 key", &krb5int_enc_aes256_ctr, NULL, - krb5int_cmac_checksum, NULL, - 16, 16, 0, &krb5int_enc_aes256 }, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, #endif /* AES_CCM */ { CKSUMTYPE_MD5_HMAC_ARCFOUR, @@ -134,14 +134,14 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { { CKSUMTYPE_CMAC_128_CAMELLIA128, "cmac-128-camellia128", { 0 }, "CMAC Camellia128 key", &krb5int_enc_camellia128_ctr, NULL, - krb5int_cmac_checksum, NULL, - 16, 16, 0, &krb5int_enc_camellia128 }, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, { CKSUMTYPE_CMAC_128_CAMELLIA256, "cmac-128-camellia256", { 0 }, "CMAC Camellia256 key", &krb5int_enc_camellia256_ctr, NULL, - krb5int_cmac_checksum, NULL, - 16, 16, 0, &krb5int_enc_camellia256 }, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, }; const size_t krb5int_cksumtypes_length = diff --git a/src/lib/crypto/krb/cksumtypes.h b/src/lib/crypto/krb/cksumtypes.h index 8c32f66..ebc4e87 100644 --- a/src/lib/crypto/krb/cksumtypes.h +++ b/src/lib/crypto/krb/cksumtypes.h @@ -97,6 +97,12 @@ krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, size_t num_data, krb5_data *output); +krb5_error_code krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); + krb5_error_code krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp, krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, diff --git a/src/lib/crypto/krb/dk/checksum_cmac.c b/src/lib/crypto/krb/dk/checksum_cmac.c index d520920..a38f05f 100644 --- a/src/lib/crypto/krb/dk/checksum_cmac.c +++ b/src/lib/crypto/krb/dk/checksum_cmac.c @@ -23,21 +23,6 @@ * this software for any purpose. It is provided "as is" without express * or implied warranty. */ -/* - * Portions Copyright (C) The Internet Society (2006). - * - * This document is subject to the rights, licenses and restrictions - * contained in BCP 78, and except as set forth therein, the authors - * retain all their rights. - * - * This document and the information contained herein are provided on an - * "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS - * OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET - * ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE - * INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED - * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - */ #include "k5-int.h" #include "etypes.h" @@ -47,200 +32,11 @@ #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ -#define BLOCK_SIZE 16 - -static unsigned char const_Rb[BLOCK_SIZE] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 -}; - -static unsigned char const_Zero[BLOCK_SIZE] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void -xor_128(unsigned char *a, unsigned char *b, unsigned char *out) -{ - int z; - - for (z = 0; z < BLOCK_SIZE / 4; z++) { - unsigned char *aptr = &a[z * 4]; - unsigned char *bptr = &b[z * 4]; - unsigned char *outptr = &out[z * 4]; - - store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr); - } -} - -static void -leftshift_onebit(unsigned char *input, unsigned char *output) -{ - int i; - unsigned char overflow = 0; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - output[i] = input[i] << 1; - output[i] |= overflow; - overflow = (input[i] & 0x80) ? 1 : 0; - } -} - -static krb5_error_code -generate_subkey(const struct krb5_cksumtypes *ctp, - krb5_key key, - unsigned char *K1, - unsigned char *K2) -{ - unsigned char Z[BLOCK_SIZE]; - unsigned char L[BLOCK_SIZE]; - unsigned char tmp[BLOCK_SIZE]; - krb5_crypto_iov iov[1]; - krb5_data d; - krb5_error_code ret; - - memset(Z, 0, sizeof(Z)); - iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data = make_data((char *)Z, sizeof(Z)); - - d = make_data((char *)L, BLOCK_SIZE); - - /* - * CBC in terms of CBC-MAC; at the cost of an additional XOR, - * this avoids needing to extend the SPI interface (because we - * need both the CBC-MAC function from the CCM provider and - * the CBC function from the CTS provider). - */ - ret = ctp->enc->cbc_mac(key, iov, 1, NULL, &d); - if (ret != 0) - return ret; - - xor_128(const_Zero, L, L); - - if ((L[0] & 0x80) == 0) { - leftshift_onebit(L, K1); - } else { - leftshift_onebit(L, tmp); - xor_128(tmp, const_Rb, K1); - } - - if ((K1[0] & 0x80) == 0) { - leftshift_onebit(K1, K2); - } else { - leftshift_onebit(K1, tmp); - xor_128(tmp, const_Rb, K2); - } - - return 0; -} - -static void -padding(unsigned char *lastb, unsigned char *pad, int length) -{ - int j; - - /* original last block */ - for (j = 0; j < BLOCK_SIZE; j++) { - if (j < length) { - pad[j] = lastb[j]; - } else if (j == length) { - pad[j] = 0x80; - } else { - pad[j] = 0x00; - } - } -} - -/* - * Implementation of CMAC algorithm. When used with AES, this function - * is compatible with RFC 4493. - */ -static krb5_error_code -cmac128_checksum(const struct krb5_cksumtypes *ctp, krb5_key key, - const krb5_crypto_iov *data, size_t num_data, - krb5_data *output) -{ - unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE]; - unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE]; - unsigned char input[BLOCK_SIZE]; - unsigned int n, i, flag; - krb5_error_code ret; - struct iov_block_state iov_state; - unsigned int length; - krb5_data ivec; - krb5_crypto_iov iov[1]; - krb5_data d; - - assert(ctp->enc->cbc_mac != NULL); - - for (i = 0, length = 0; i < num_data; i++) { - const krb5_crypto_iov *piov = &data[i]; - - if (SIGN_IOV(piov)) - length += piov->data.length; - } - - ret = generate_subkey(ctp, key, K1, K2); - if (ret != 0) - return ret; - - n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; - - if (n == 0) { - n = 1; - flag = 0; - } else { - flag = ((length % BLOCK_SIZE) == 0); - } - - iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data = make_data((char *)input, BLOCK_SIZE); - - memset(Y, 0, BLOCK_SIZE); - - ivec = make_data((char *)Y, BLOCK_SIZE); - d = make_data((char *)Y, BLOCK_SIZE); - - IOV_BLOCK_STATE_INIT(&iov_state); - iov_state.include_sign_only = 1; - - for (i = 0; i < n - 1; i++) { - krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state); - - ret = ctp->enc->cbc_mac(key, iov, 1, &ivec, &d); - if (ret != 0) - return ret; - } - - krb5int_c_iov_get_block(input, BLOCK_SIZE, data, num_data, &iov_state); - - if (flag) { - /* last block is complete block */ - xor_128(input, K1, M_last); - } else { - padding(input, padded, length % BLOCK_SIZE); - xor_128(padded, K2, M_last); - } - - iov[0].data = make_data((char *)M_last, BLOCK_SIZE); - - ret = ctp->enc->cbc_mac(key, iov, 1, &ivec, &d); - if (ret != 0) - return ret; - - assert(output->length >= d.length); - - output->length = d.length; - memcpy(output->data, d.data, d.length); - - return ret; -} - krb5_error_code -krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, - krb5_key key, krb5_keyusage usage, - const krb5_crypto_iov *data, size_t num_data, - krb5_data *output) +krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) { const struct krb5_keytypes *ktp; const struct krb5_enc_provider *enc; @@ -249,9 +45,6 @@ krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, krb5_data datain; krb5_key kc; - if (ctp->compute_size != BLOCK_SIZE) - return KRB5_BAD_MSIZE; - /* Use the key's enctype (more flexible than setting an enctype in ctp). */ ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL) @@ -259,6 +52,8 @@ krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, enc = ktp->enc; if (key->keyblock.length != enc->keylength) return KRB5_BAD_KEYSIZE; + if (ctp->compute_size != enc->block_size) + return KRB5_BAD_MSIZE; /* Derive the key. */ datain = make_data(constantdata, K5CLENGTH); @@ -269,7 +64,7 @@ krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, return ret; /* Hash the data. */ - ret = cmac128_checksum(ctp, kc, data, num_data, output); + ret = krb5int_cmac_checksum(ctp, kc, usage, data, num_data, output); if (ret != 0) memset(output->data, 0, output->length); diff --git a/src/lib/crypto/krb/dk/dk.h b/src/lib/crypto/krb/dk/dk.h index 360492b..04223e6 100644 --- a/src/lib/crypto/krb/dk/dk.h +++ b/src/lib/crypto/krb/dk/dk.h @@ -107,7 +107,7 @@ krb5int_ccm_decrypt(const struct krb5_keytypes *ktp, size_t num_data); krb5_error_code -krb5int_cmac_checksum(const struct krb5_cksumtypes *ctp, - krb5_key key, krb5_keyusage usage, - const krb5_crypto_iov *data, size_t num_data, - krb5_data *output); +krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output); diff --git a/src/lib/crypto/krb/prf/ccm_prf.c b/src/lib/crypto/krb/prf/ccm_prf.c index b384e07..aeef7a5 100644 --- a/src/lib/crypto/krb/prf/ccm_prf.c +++ b/src/lib/crypto/krb/prf/ccm_prf.c @@ -37,11 +37,15 @@ krb5_error_code krb5int_ccm_prf(const struct krb5_keytypes *ktp, krb5_key key, const krb5_data *in, krb5_data *out) { + struct krb5_cksumtypes ctp; krb5_crypto_iov iov; krb5_data prfconst = make_data("prf", 3); krb5_key kp = NULL; krb5_error_code ret; + if (ktp->prf_length != ktp->enc->block_size) + return KRB5_BAD_MSIZE; + iov.flags = KRB5_CRYPTO_TYPE_DATA; iov.data = *in; @@ -50,7 +54,11 @@ krb5int_ccm_prf(const struct krb5_keytypes *ktp, krb5_key key, if (ret != 0) goto cleanup; - ret = ktp->enc->cbc_mac(kp, &iov, 1, NULL, out); + memset(&ctp, 0, sizeof(ctp)); + ctp.enc = ktp->enc; + + /* Similar to RFC 4615, PRF is CMAC of input */ + ret = krb5int_cmac_checksum(&ctp, kp, 0, &iov, 1, out); if (ret != 0) goto cleanup; |