aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Howard <lukeh@padl.com>2010-05-22 19:11:24 +0000
committerLuke Howard <lukeh@padl.com>2010-05-22 19:11:24 +0000
commitf1dd1977c775b63f92af88bd60c3c92e2a8fb43a (patch)
treeb4ee78c91fd3d759b1a0e4cfce50977e7cad42c5
parent16e37d18f13cfe3ab850a662fe5d1f630f752319 (diff)
downloadkrb5-f1dd1977c775b63f92af88bd60c3c92e2a8fb43a.zip
krb5-f1dd1977c775b63f92af88bd60c3c92e2a8fb43a.tar.gz
krb5-f1dd1977c775b63f92af88bd60c3c92e2a8fb43a.tar.bz2
Initial implementation of GCM
git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/camellia-ccm@24087 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/crypto/crypto_tests/t_encrypt.c6
-rw-r--r--src/lib/crypto/crypto_tests/t_short.c4
-rw-r--r--src/lib/crypto/krb/cksumtypes.c24
-rw-r--r--src/lib/crypto/krb/dk/Makefile.in6
-rw-r--r--src/lib/crypto/krb/dk/checksum_gmac.c194
-rw-r--r--src/lib/crypto/krb/dk/dk.h51
-rw-r--r--src/lib/crypto/krb/dk/dk_ccm.c12
-rw-r--r--src/lib/crypto/krb/dk/dk_gcm.c618
-rw-r--r--src/lib/crypto/krb/etypes.c48
-rw-r--r--src/lib/crypto/krb/prf/Makefile.in6
-rw-r--r--src/lib/crypto/krb/prf/cmac_prf.c (renamed from src/lib/crypto/krb/prf/ccm_prf.c)6
-rw-r--r--src/lib/crypto/krb/prf/prf_int.h4
-rw-r--r--src/util/k5test.py10
13 files changed, 967 insertions, 22 deletions
diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c
index b0b8233..bb3af2d 100644
--- a/src/lib/crypto/crypto_tests/t_encrypt.c
+++ b/src/lib/crypto/crypto_tests/t_encrypt.c
@@ -48,11 +48,13 @@ krb5_enctype interesting_enctypes[] = {
#ifdef AES_CCM
ENCTYPE_AES128_CCM_128,
ENCTYPE_AES256_CCM_128,
+ ENCTYPE_AES128_GCM_128,
+ ENCTYPE_AES256_GCM_128,
#endif
ENCTYPE_CAMELLIA128_CTS_HMAC_SHA1_96,
ENCTYPE_CAMELLIA256_CTS_HMAC_SHA1_96,
- ENCTYPE_CAMELLIA128_CCM_128,
- ENCTYPE_CAMELLIA256_CCM_128,
+ ENCTYPE_CAMELLIA128_GCM_128,
+ ENCTYPE_CAMELLIA256_GCM_128,
0
};
diff --git a/src/lib/crypto/crypto_tests/t_short.c b/src/lib/crypto/crypto_tests/t_short.c
index a149da7..68cde6e 100644
--- a/src/lib/crypto/crypto_tests/t_short.c
+++ b/src/lib/crypto/crypto_tests/t_short.c
@@ -44,11 +44,15 @@ krb5_enctype interesting_enctypes[] = {
#ifdef AES_CCM
ENCTYPE_AES128_CCM_128,
ENCTYPE_AES256_CCM_128,
+ ENCTYPE_AES128_GCM_128,
+ ENCTYPE_AES256_GCM_128,
#endif
ENCTYPE_CAMELLIA128_CTS_HMAC_SHA1_96,
ENCTYPE_CAMELLIA256_CTS_HMAC_SHA1_96,
ENCTYPE_CAMELLIA128_CCM_128,
ENCTYPE_CAMELLIA256_CCM_128,
+ ENCTYPE_CAMELLIA128_GCM_128,
+ ENCTYPE_CAMELLIA256_GCM_128,
0
};
diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c
index d757889..d501689 100644
--- a/src/lib/crypto/krb/cksumtypes.c
+++ b/src/lib/crypto/krb/cksumtypes.c
@@ -111,6 +111,18 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
&krb5int_enc_aes256_ctr, NULL,
krb5int_dk_cmac_checksum, NULL,
16, 16, 0 },
+
+ { CKSUMTYPE_GMAC_128_AES128,
+ "gmac-128-aes128", { 0 }, "GMAC AES128 key",
+ &krb5int_enc_aes128_ctr, NULL,
+ krb5int_dk_gmac_checksum, krb5int_dk_gmac_verify,
+ 28, 28, 0 },
+
+ { CKSUMTYPE_GMAC_128_AES256,
+ "gmac-128-aes256", { 0 }, "GMAC AES256 key",
+ &krb5int_enc_aes256_ctr, NULL,
+ krb5int_dk_gmac_checksum, krb5int_dk_gmac_verify,
+ 28, 28, 0 },
#endif /* AES_CCM */
{ CKSUMTYPE_MD5_HMAC_ARCFOUR,
@@ -142,6 +154,18 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
&krb5int_enc_camellia256_ctr, NULL,
krb5int_dk_cmac_checksum, NULL,
16, 16, 0 },
+
+ { CKSUMTYPE_GMAC_128_CAMELLIA128,
+ "gmac-128-camellia128", { 0 }, "GMAC Camellia128 key",
+ &krb5int_enc_camellia128_ctr, NULL,
+ krb5int_dk_gmac_checksum, krb5int_dk_gmac_verify,
+ 28, 28, 0 },
+
+ { CKSUMTYPE_GMAC_128_CAMELLIA256,
+ "gmac-128-camellia256", { 0 }, "GMAC Camellia256 key",
+ &krb5int_enc_camellia256_ctr, NULL,
+ krb5int_dk_gmac_checksum, krb5int_dk_gmac_verify,
+ 28, 28, 0 },
};
const size_t krb5int_cksumtypes_length =
diff --git a/src/lib/crypto/krb/dk/Makefile.in b/src/lib/crypto/krb/dk/Makefile.in
index 5c54601..4a2d2f7 100644
--- a/src/lib/crypto/krb/dk/Makefile.in
+++ b/src/lib/crypto/krb/dk/Makefile.in
@@ -13,24 +13,30 @@ PROG_RPATH=$(KRB5_LIBDIR)
STLIBOBJS=\
checksum.o \
checksum_cmac.o \
+ checksum_gmac.o \
dk_aead.o \
dk_ccm.o \
+ dk_gcm.o \
derive.o \
stringtokey.o
OBJS=\
$(OUTPRE)checksum.$(OBJEXT) \
$(OUTPRE)checksum_cmac.$(OBJEXT)\
+ $(OUTPRE)checksum_gmac.$(OBJEXT)\
$(OUTPRE)dk_aead.$(OBJEXT) \
$(OUTPRE)dk_ccm.$(OBJEXT) \
+ $(OUTPRE)dk_gcm.$(OBJEXT) \
$(OUTPRE)derive.$(OBJEXT) \
$(OUTPRE)stringtokey.$(OBJEXT)
SRCS=\
$(srcdir)/checksum.c \
$(srcdir)/checksum_cmac.c \
+ $(srcdir)/checksum_gmac.c \
$(srcdir)/dk_aead.c \
$(srcdir)/dk_ccm.c \
+ $(srcdir)/dk_gcm.c \
$(srcdir)/derive.c \
$(srcdir)/stringtokey.c
diff --git a/src/lib/crypto/krb/dk/checksum_gmac.c b/src/lib/crypto/krb/dk/checksum_gmac.c
new file mode 100644
index 0000000..1fa162a
--- /dev/null
+++ b/src/lib/crypto/krb/dk/checksum_gmac.c
@@ -0,0 +1,194 @@
+/*
+ * lib/crypto/krb/dk/checksum_gmac.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.
+ */
+
+#include "k5-int.h"
+#include "etypes.h"
+#include "dk.h"
+#include "aead.h"
+#include "cksumtypes.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+krb5_error_code
+krb5int_dk_gmac_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;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data datain;
+ krb5_key kc;
+ unsigned int header_len;
+ unsigned int trailer_len;
+ krb5_crypto_iov *sign_data;
+ size_t i;
+
+ /* Use the key's enctype (more flexible than setting an enctype in ctp). */
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
+ if (key->keyblock.length != enc->keylength)
+ return KRB5_BAD_KEYSIZE;
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ if (ctp->compute_size != header_len + trailer_len)
+ return KRB5_BAD_MSIZE;
+
+ if (output->length < ctp->compute_size)
+ return KRB5_BAD_MSIZE;
+
+ sign_data = k5alloc((num_data + 2) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
+ return ret;
+
+ for (i = 0; i < num_data; i++) {
+ sign_data[i].data = data[i].data;
+
+ if (SIGN_IOV(&data[i])) {
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ } else {
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+ }
+ }
+
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+ sign_data[i].data = make_data(output->data, header_len);
+ i++;
+
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ sign_data[i].data = make_data(&output->data[header_len], trailer_len);
+ i++;
+
+ /* Derive the key. */
+ datain = make_data(constantdata, K5CLENGTH);
+ store_32_be(usage, constantdata);
+ constantdata[4] = (char) 0x99;
+ ret = krb5int_derive_key(enc, key, &kc, &datain);
+ if (ret != 0) {
+ free(sign_data);
+ return ret;
+ }
+
+ /* Hash the data. */
+ ret = krb5int_gcm_encrypt(ktp, kc, usage, NULL, sign_data, i);
+ if (ret != 0)
+ memset(output->data, 0, output->length);
+
+ output->length = header_len + trailer_len;
+
+ krb5_k_free_key(NULL, kc);
+ free(sign_data);
+ return ret;
+}
+
+krb5_error_code
+krb5int_dk_gmac_verify(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ const krb5_data *input, krb5_boolean *valid)
+{
+ const struct krb5_keytypes *ktp;
+ const struct krb5_enc_provider *enc;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data datain;
+ krb5_key kc;
+ unsigned int header_len;
+ unsigned int trailer_len;
+ krb5_crypto_iov *sign_data;
+ size_t i;
+
+ *valid = FALSE;
+
+ /* Use the key's enctype (more flexible than setting an enctype in ctp). */
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
+ if (key->keyblock.length != enc->keylength)
+ return KRB5_BAD_KEYSIZE;
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ if (ctp->compute_size != header_len + trailer_len)
+ return KRB5_BAD_MSIZE;
+
+ if (input->length != ctp->compute_size)
+ return KRB5_BAD_MSIZE;
+
+ sign_data = k5alloc((num_data + 2) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
+ return ret;
+
+ for (i = 0; i < num_data; i++) {
+ sign_data[i].data = data[i].data;
+
+ if (SIGN_IOV(&data[i])) {
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ } else {
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+ }
+ }
+
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+ sign_data[i].data = make_data(input->data, header_len);
+ i++;
+
+ sign_data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ sign_data[i].data = make_data(&input->data[header_len], trailer_len);
+ i++;
+
+ /* Derive the key. */
+ datain = make_data(constantdata, K5CLENGTH);
+ store_32_be(usage, constantdata);
+ constantdata[4] = (char) 0x99;
+ ret = krb5int_derive_key(enc, key, &kc, &datain);
+ if (ret != 0) {
+ free(sign_data);
+ return ret;
+ }
+
+ /* Verify the data. */
+ ret = krb5int_gcm_decrypt(ktp, kc, usage, NULL, sign_data, i);
+ if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+ ret = 0;
+ } else if (ret == 0) {
+ *valid = TRUE;
+ }
+
+ krb5_k_free_key(NULL, kc);
+ free(sign_data);
+
+ return ret;
+}
+
diff --git a/src/lib/crypto/krb/dk/dk.h b/src/lib/crypto/krb/dk/dk.h
index 5d07332..9b5f898 100644
--- a/src/lib/crypto/krb/dk/dk.h
+++ b/src/lib/crypto/krb/dk/dk.h
@@ -67,8 +67,11 @@ krb5int_peppered_string_to_key(const struct krb5_keytypes *enc,
const krb5_data *params, krb5_keyblock *key);
#define krb5int_aes_ccm_string_to_key krb5int_peppered_string_to_key
+#define krb5int_aes_gcm_string_to_key krb5int_peppered_string_to_key
+
#define krb5int_camellia_string_to_key krb5int_peppered_string_to_key
#define krb5int_camellia_ccm_string_to_key krb5int_peppered_string_to_key
+#define krb5int_camellia_gcm_string_to_key krb5int_peppered_string_to_key
krb5_error_code
krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
@@ -118,3 +121,51 @@ 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);
+
+unsigned int
+krb5int_dk_gcm_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+
+krb5_error_code
+krb5int_gcm_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+
+krb5_error_code
+krb5int_dk_gcm_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+
+krb5_error_code
+krb5int_gcm_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+
+krb5_error_code
+krb5int_dk_gcm_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+
+krb5_error_code
+krb5int_dk_gmac_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_dk_gmac_verify(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ const krb5_data *input, krb5_boolean *valid);
diff --git a/src/lib/crypto/krb/dk/dk_ccm.c b/src/lib/crypto/krb/dk/dk_ccm.c
index 5209bba..75a9cd5 100644
--- a/src/lib/crypto/krb/dk/dk_ccm.c
+++ b/src/lib/crypto/krb/dk/dk_ccm.c
@@ -323,11 +323,9 @@ ccm_encrypt(const struct krb5_keytypes *ktp,
if (ret != 0)
goto cleanup;
- sign_data = (krb5_crypto_iov *)calloc(num_data + 1, sizeof(krb5_crypto_iov));
- if (sign_data == NULL) {
- ret = ENOMEM;
+ sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
goto cleanup;
- }
sign_data[num_sign_data].flags = KRB5_CRYPTO_TYPE_HEADER;
sign_data[num_sign_data].data = make_data((char *)B0, sizeof(B0));
@@ -490,11 +488,9 @@ ccm_decrypt(const struct krb5_keytypes *ktp,
if (ret != 0)
goto cleanup;
- sign_data = (krb5_crypto_iov *)calloc(num_data + 1, sizeof(krb5_crypto_iov));
- if (sign_data == NULL) {
- ret = ENOMEM;
+ sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
goto cleanup;
- }
sign_data[num_sign_data].flags = KRB5_CRYPTO_TYPE_HEADER;
sign_data[num_sign_data].data = make_data((char *)B0, sizeof(B0));
diff --git a/src/lib/crypto/krb/dk/dk_gcm.c b/src/lib/crypto/krb/dk/dk_gcm.c
new file mode 100644
index 0000000..4c79841
--- /dev/null
+++ b/src/lib/crypto/krb/dk/dk_gcm.c
@@ -0,0 +1,618 @@
+/*
+ * lib/crypto/krb/dk/dk_gcm.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.
+ */
+
+#include "k5-int.h"
+#include "dk.h"
+#include "aead.h"
+
+/*
+ * Implement AEAD_AES_{128,256}_GCM as described in section 5.1 of RFC 5116.
+ *
+ * This is the GCM mode as described in NIST 800-38D, with a 12 byte IV
+ * and 16 byte checksum. Multiple buffers of the same type are logically
+ * concatenated.
+ *
+ * The IOV should be laid out as follows:
+ *
+ * HEADER | SIGN_DATA | DATA | PADDING | TRAILER
+ *
+ * SIGN_DATA and PADDING may be absent.
+ *
+ * Upon decryption, one can pass in explicit buffers as for encryption, or
+ * one can pass in STREAM, being the concatenation of HEADER | DATA | TRAILER.
+ *
+ * STREAM | SIGN_DATA | DATA
+ *
+ * Upon output, DATA will contain a pointer into the STREAM buffer with the
+ * decrypted payload. SIGN_DATA should be ordered relative to the output DATA
+ * buffer as it was upon encryption.
+ *
+ * For compatibility with RFC 5116, a single key is used both for encryption
+ * and checksumming. The key derivation function is as follows:
+ *
+ * Kc = DK(base-key, usage | 0x6C)
+ *
+ * Again as required by the GCM specification, SIGN_DATA is processed before
+ * DATA for the purpose of checksumming.
+ *
+ * Because the base keys are compatible with RFC 3962, the two encryption
+ * types defined here (ENCTYPE_AES128_GCM_128 and ENCTYPE_AES256_GCM_128)
+ * are most useful in conjunction with RFC 4537.
+ */
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+#define BLOCK_SIZE 16
+
+static char zeros[BLOCK_SIZE];
+
+unsigned int
+krb5int_dk_gcm_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ unsigned int length;
+
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ length = 12; /* RFC 5116 5.1 */
+ break;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ length = 0; /* CTR mode requires no padding */
+ break;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ length = ktp->enc->block_size;
+ assert(length == BLOCK_SIZE); /* SP-800-38D requires this */
+ break;
+ default:
+ assert(0 && "invalid cryptotype passed to gcm_crypto_length");
+ length = ~0;
+ break;
+ }
+
+ return length;
+}
+
+static krb5_boolean
+valid_payload_length_p(const struct krb5_keytypes *ktp,
+ unsigned int n,
+ unsigned int payload_len)
+{
+ unsigned int block_size = ktp->enc->block_size;
+ unsigned long nblocks, maxblocks;
+
+ maxblocks = (1UL << 32);
+
+ nblocks = 1; /* tag */
+ nblocks += (payload_len + block_size - 1) / block_size;
+
+ return (nblocks <= maxblocks);
+}
+
+static void
+xor_128(unsigned char a[BLOCK_SIZE],
+ unsigned char b[BLOCK_SIZE],
+ unsigned char out[BLOCK_SIZE])
+{
+ unsigned char z;
+
+ for (z = 0; z < 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
+rightshift_onebit(unsigned char input[BLOCK_SIZE],
+ unsigned char output[BLOCK_SIZE])
+{
+ unsigned char last_overflow = 0, overflow;
+ unsigned char i;
+
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ overflow = (input[i] & 1) ? 0x80 : 0;
+ output[i] = (input[i] >> 1) & 0x7F;
+ output[i] |= last_overflow;
+ last_overflow = overflow;
+ }
+}
+
+static void
+block_product(unsigned char X[BLOCK_SIZE],
+ unsigned char Y[BLOCK_SIZE],
+ unsigned char out[BLOCK_SIZE])
+{
+ unsigned char V[BLOCK_SIZE];
+ unsigned char Z[BLOCK_SIZE];
+ unsigned char i;
+
+ memset(Z, 0, BLOCK_SIZE);
+ memcpy(V, X, BLOCK_SIZE);
+
+ for (i = 0; i < 128; i++) {
+ unsigned char j = 7 - (i % 8);
+
+ if (Y[i / 8] & (1 << j))
+ xor_128(Z, V, Z);
+
+ if (V[15] & 1) {
+ rightshift_onebit(V, V);
+ V[0] ^= 0xE1; /* R */
+ } else
+ rightshift_onebit(V, V);
+ }
+
+ memcpy(out, Z, BLOCK_SIZE);
+}
+
+static krb5_error_code
+GHASH(unsigned char H[BLOCK_SIZE],
+ krb5_crypto_iov *data,
+ size_t num_data,
+ unsigned char Y[BLOCK_SIZE])
+{
+ struct iov_block_state iov_state;
+ unsigned char X[BLOCK_SIZE];
+
+ memset(Y, 0, BLOCK_SIZE);
+
+ IOV_BLOCK_STATE_INIT(&iov_state);
+ iov_state.include_sign_only = 1;
+ iov_state.pad_to_boundary = 1;
+
+ while (krb5int_c_iov_get_block(X, sizeof(X), data, num_data, &iov_state)) {
+ xor_128(Y, X, Y);
+ block_product(Y, H, Y);
+ }
+
+ return 0;
+}
+
+/*
+ * Format initial counter block. Counter may be chained
+ * across invocations.
+ */
+static krb5_error_code
+format_J0(unsigned char H[BLOCK_SIZE],
+ unsigned char J0[BLOCK_SIZE],
+ const krb5_data *iv,
+ const krb5_data *state)
+{
+ if (iv->length != 12) {
+ /*
+ * SP800-38D 7.1.2: if a non-96-bit nonce is specified,
+ * then the initial counter block is:
+ *
+ * GHASH(H, IV || pad || [0]64 || [len(IV)]64)
+ *
+ * Note that len(IV) is the bit length of the IV.
+ */
+ krb5_crypto_iov ivdata[2];
+ unsigned char ivlength[BLOCK_SIZE];
+
+ store_64_be((krb5_ui_8)0, &ivlength[0]);
+ store_64_be((krb5_ui_8)iv->length * 8, &ivlength[8]);
+
+ ivdata[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ ivdata[0].data = *iv;
+ ivdata[1].flags = KRB5_CRYPTO_TYPE_HEADER;
+ ivdata[1].data = make_data(ivlength, BLOCK_SIZE);
+
+ GHASH(H, ivdata, 2, J0);
+ } else {
+ /* Otherwise J0 is IV || [1]32 */
+ memcpy(J0, iv->data, iv->length);
+ store_32_be(1, &J0[12]);
+ }
+
+ /*
+ * If non-initial cipher state, propagate counter value
+ * to support chaining.
+ */
+ if (state != NULL) {
+ krb5_ui_4 i;
+
+ if (state->length < 4)
+ return KRB5_BAD_MSIZE;
+
+ i = load_32_be(&state->data[state->length - 4]);
+ if (i != 0)
+ store_32_be(i, &J0[12]);
+ }
+
+ return 0;
+}
+
+static void
+format_ICB(unsigned char J0[BLOCK_SIZE],
+ unsigned char ICB[BLOCK_SIZE])
+{
+ krb5_ui_4 i;
+
+ i = load_32_be(&J0[12]);
+ memcpy(ICB, J0, 12);
+ store_32_be(i + 1, &ICB[12]);
+}
+
+static krb5_error_code
+derive_H(const struct krb5_keytypes *ktp,
+ krb5_key kg,
+ unsigned char H[BLOCK_SIZE])
+{
+ krb5_crypto_iov data[1];
+ krb5_data H_data;
+
+ data[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ data[0].data = make_data(zeros, sizeof(zeros));
+
+ H_data = make_data(H, BLOCK_SIZE);
+
+ assert(ktp->enc->cbc_mac != NULL);
+
+ return ktp->enc->cbc_mac(kg, data, 1, NULL, &H_data);
+}
+
+krb5_error_code
+krb5int_gcm_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key kg,
+ krb5_keyusage usage,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer, *sign_data = NULL;
+ size_t i, num_sign_data = 0;
+ unsigned int header_len, trailer_len;
+ size_t plain_len = 0, adata_len = 0;
+ char len_buf[BLOCK_SIZE];
+ unsigned char H[BLOCK_SIZE], J0[BLOCK_SIZE];
+ unsigned char ICB[BLOCK_SIZE];
+ krb5_data counter;
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length != header_len) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length != trailer_len) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ switch (iov->flags) {
+ case KRB5_CRYPTO_TYPE_DATA:
+ plain_len += iov->data.length;
+ break;
+ case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+ adata_len += iov->data.length;
+ break;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ if (iov->data.length != 0) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!valid_payload_length_p(ktp, header_len, plain_len)) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ header->data.length = header_len;
+
+ /* Initialize IV */
+ ret = krb5_c_random_make_octets(NULL, &header->data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive H subkey */
+ ret = derive_H(ktp, kg, H);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Initialize counter block */
+ ret = format_J0(H, J0, &header->data, state);
+ if (ret != 0)
+ goto cleanup;
+
+ format_ICB(J0, ICB);
+ counter = make_data((char *)ICB, sizeof(ICB));
+
+ if (plain_len != 0) {
+ /* Encrypt plaintext */
+ ret = ktp->enc->encrypt(kg, &counter, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+ }
+
+ sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
+ goto cleanup;
+
+ /* Reorder input IOV so SIGN_ONLY data is before DATA */
+ for (i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
+ sign_data[num_sign_data++] = data[i];
+ }
+ for (i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
+ sign_data[num_sign_data++] = data[i];
+ }
+
+ /* Append bit length of SIGN_ONLY and DATA */
+ store_64_be((krb5_ui_8)adata_len * 8, &len_buf[0]);
+ store_64_be((krb5_ui_8)plain_len * 8, &len_buf[8]);
+
+ sign_data[num_sign_data].flags = KRB5_CRYPTO_TYPE_HEADER;
+ sign_data[num_sign_data].data = make_data(len_buf, sizeof(len_buf));
+ num_sign_data++;
+
+ /* Make checksum */
+ ret = GHASH(H, sign_data, num_sign_data,
+ (unsigned char *)trailer->data.data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Encrypt checksum in trailer */
+ {
+ krb5_data J0_data = make_data((char *)J0, sizeof(J0));
+ krb5_crypto_iov cksum[1];
+
+ cksum[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ cksum[0].data = trailer->data;
+
+ ret = ktp->enc->encrypt(kg, &J0_data, cksum, 1);
+ if (ret != 0)
+ goto cleanup;
+ }
+
+ if (state != NULL)
+ memcpy(state->data, counter.data, counter.length);
+
+cleanup:
+ free(sign_data);
+ zap(ICB, sizeof(ICB));
+ zap(J0, sizeof(J0));
+ zap(H, sizeof(H));
+
+ return ret;
+}
+
+krb5_error_code
+krb5int_dk_gcm_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ unsigned char constantdata[K5CLENGTH];
+ krb5_error_code ret;
+ krb5_key kc;
+ krb5_data d1;
+
+ d1.data = (char *)constantdata;
+ d1.length = K5CLENGTH;
+
+ d1.data[0] = (usage >> 24) & 0xFF;
+ d1.data[1] = (usage >> 16) & 0xFF;
+ d1.data[2] = (usage >> 8 ) & 0xFF;
+ d1.data[3] = (usage ) & 0xFF;
+
+ d1.data[4] = 0x6C;
+
+ ret = krb5int_derive_key(ktp->enc, key, &kc, &d1);
+ if (ret != 0)
+ return ret;
+
+ ret = krb5int_gcm_encrypt(ktp, kc, usage, state, data, num_data);
+
+ krb5_k_free_key(NULL, kc);
+
+ return ret;
+}
+
+krb5_error_code
+krb5int_gcm_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key kg,
+ krb5_keyusage usage,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer, *sign_data = NULL;
+ size_t i, num_sign_data = 0;
+ unsigned int header_len, trailer_len;
+ size_t plain_len = 0, adata_len = 0;
+ char len_buf[BLOCK_SIZE];
+ unsigned char H[BLOCK_SIZE], J0[BLOCK_SIZE];
+ krb5_data counter;
+ unsigned char made_cksum[BLOCK_SIZE];
+ krb5_crypto_iov made_cksum_data[1];
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length < header_len) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+ assert(trailer_len <= sizeof(made_cksum));
+
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length < trailer_len) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ switch (iov->flags) {
+ case KRB5_CRYPTO_TYPE_DATA:
+ plain_len += iov->data.length;
+ break;
+ case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+ adata_len += iov->data.length;
+ break;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ iov->data.length = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!valid_payload_length_p(ktp, header_len, plain_len)) {
+ ret = KRB5_BAD_MSIZE;
+ goto cleanup;
+ }
+
+ /* Derive H subkey */
+ ret = derive_H(ktp, kg, H);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Initialize counter block */
+ ret = format_J0(H, J0, &header->data, state);
+ if (ret != 0)
+ goto cleanup;
+
+ counter = make_data((char *)J0, sizeof(J0));
+
+ sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+ if (sign_data == NULL)
+ goto cleanup;
+
+ /* Reorder input IOV so SIGN_ONLY data is before DATA */
+ for (i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
+ sign_data[num_sign_data++] = data[i];
+ }
+ for (i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
+ sign_data[num_sign_data++] = data[i];
+ }
+
+ /* Append bit length of SIGN_ONLY and DATA */
+ store_64_be((krb5_ui_8)adata_len * 8, &len_buf[0]);
+ store_64_be((krb5_ui_8)plain_len * 8, &len_buf[8]);
+
+ sign_data[num_sign_data].flags = KRB5_CRYPTO_TYPE_HEADER;
+ sign_data[num_sign_data].data = make_data(len_buf, sizeof(len_buf));
+ num_sign_data++;
+
+ /* Calculate hash for comparison */
+ ret = GHASH(H, sign_data, num_sign_data, made_cksum);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Encrypt checksum for comparison */
+ made_cksum_data[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ made_cksum_data[0].data = make_data(made_cksum, sizeof(made_cksum));
+
+ ret = ktp->enc->encrypt(kg, &counter, made_cksum_data, 1);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Compare (possibly truncated) checksum */
+ if (memcmp(made_cksum, trailer->data.data, trailer_len) != 0) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+ /* Decrypt plaintext */
+ if (plain_len != 0) {
+ ret = ktp->enc->decrypt(kg, &counter, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+ }
+
+ if (state != NULL)
+ memcpy(state->data, counter.data, counter.length);
+
+cleanup:
+ free(sign_data);
+ zap(J0, sizeof(J0));
+ zap(H, sizeof(H));
+ zap(made_cksum, sizeof(made_cksum));
+
+ return ret;
+}
+
+krb5_error_code
+krb5int_dk_gcm_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ unsigned char constantdata[K5CLENGTH];
+ krb5_error_code ret;
+ krb5_key kc;
+ krb5_data d1;
+
+ d1.data = (char *)constantdata;
+ d1.length = K5CLENGTH;
+
+ d1.data[0] = (usage >> 24) & 0xFF;
+ d1.data[1] = (usage >> 16) & 0xFF;
+ d1.data[2] = (usage >> 8 ) & 0xFF;
+ d1.data[3] = (usage ) & 0xFF;
+
+ d1.data[4] = 0x6C;
+
+ ret = krb5int_derive_key(ktp->enc, key, &kc, &d1);
+ if (ret != 0)
+ return ret;
+
+ ret = krb5int_gcm_decrypt(ktp, kc, usage, state, data, num_data);
+
+ krb5_k_free_key(NULL, kc);
+
+ return ret;
+}
diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
index aa14dc6..0e6c2ac 100644
--- a/src/lib/crypto/krb/etypes.c
+++ b/src/lib/crypto/krb/etypes.c
@@ -161,7 +161,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
16,
krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
krb5int_aes_ccm_string_to_key,
- krb5int_dk_ccm_prf,
+ krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_128_AES128,
0 /*flags*/ },
{ ENCTYPE_AES256_CCM_128,
@@ -171,9 +171,29 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
16,
krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
krb5int_aes_ccm_string_to_key,
- krb5int_dk_ccm_prf,
+ krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_128_AES256,
0 /*flags */ },
+ { ENCTYPE_AES128_GCM_128,
+ "aes128-gcm-128", { "aes128-gcm" },
+ "AES-128 GCM mode with 128-bit MAC",
+ &krb5int_enc_aes128_ctr, NULL,
+ 16,
+ krb5int_dk_gcm_crypto_length, krb5int_dk_gcm_encrypt, krb5int_dk_gcm_decrypt,
+ krb5int_aes_gcm_string_to_key,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_GMAC_128_AES128,
+ 0 /*flags*/ },
+ { ENCTYPE_AES256_GCM_128,
+ "aes256-gcm-128", { "aes256-gcm" },
+ "AES-256 GCM mode with 128-bit MAC",
+ &krb5int_enc_aes256_ctr, NULL,
+ 16,
+ krb5int_dk_gcm_crypto_length, krb5int_dk_gcm_encrypt, krb5int_dk_gcm_decrypt,
+ krb5int_aes_gcm_string_to_key,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_GMAC_128_AES256,
+ 0 /*flags */ },
#endif /* AES_CCM */
{ ENCTYPE_CAMELLIA128_CTS_HMAC_SHA1_96,
"camellia128-cts-hmac-sha1-96", { "camellia128-cts" },
@@ -202,7 +222,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
16,
krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
krb5int_camellia_ccm_string_to_key,
- krb5int_dk_ccm_prf,
+ krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_128_CAMELLIA128,
0 /*flags*/ },
{ ENCTYPE_CAMELLIA256_CCM_128,
@@ -212,9 +232,29 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
16,
krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
krb5int_camellia_ccm_string_to_key,
- krb5int_dk_ccm_prf,
+ krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_128_CAMELLIA256,
0 /*flags */ },
+ { ENCTYPE_CAMELLIA128_GCM_128,
+ "camellia128-gcm-128", { "camellia128-gcm" },
+ "Camellia-128 GCM mode with 128-bit MAC",
+ &krb5int_enc_camellia128_ctr, NULL,
+ 16,
+ krb5int_dk_gcm_crypto_length, krb5int_dk_gcm_encrypt, krb5int_dk_gcm_decrypt,
+ krb5int_camellia_gcm_string_to_key,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_GMAC_128_CAMELLIA128,
+ 0 /*flags*/ },
+ { ENCTYPE_CAMELLIA256_GCM_128,
+ "camellia256-gcm-128", { "camellia256-gcm" },
+ "Camellia-256 GCM mode with 128-bit MAC",
+ &krb5int_enc_camellia256_ctr, NULL,
+ 16,
+ krb5int_dk_gcm_crypto_length, krb5int_dk_gcm_encrypt, krb5int_dk_gcm_decrypt,
+ krb5int_camellia_gcm_string_to_key,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_GMAC_128_CAMELLIA256,
+ 0 /*flags */ },
};
const int krb5int_enctypes_length =
diff --git a/src/lib/crypto/krb/prf/Makefile.in b/src/lib/crypto/krb/prf/Makefile.in
index 74a8979..a0e1ad6 100644
--- a/src/lib/crypto/krb/prf/Makefile.in
+++ b/src/lib/crypto/krb/prf/Makefile.in
@@ -14,13 +14,13 @@ DEFS=
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
-STLIBOBJS= des_prf.o dk_prf.o rc4_prf.o ccm_prf.o
+STLIBOBJS= des_prf.o dk_prf.o rc4_prf.o cmac_prf.o
OBJS= $(OUTPRE)des_prf.$(OBJEXT) $(OUTPRE)dk_prf.$(OBJEXT) \
- $(OUTPRE)rc4_prf.$(OBJEXT) $(OUTPRE)ccm_prf.$(OBJEXT)
+ $(OUTPRE)rc4_prf.$(OBJEXT) $(OUTPRE)cmac_prf.$(OBJEXT)
SRCS= $(srcdir)/des_prf.c $(srcdir)/dk_prf.c \
- $(srcdir)/rc4_prf.c $(srcdir)/ccm_prf.c
+ $(srcdir)/rc4_prf.c $(srcdir)/cmac_prf.c
##DOS##LIBOBJS = $(OBJS)
diff --git a/src/lib/crypto/krb/prf/ccm_prf.c b/src/lib/crypto/krb/prf/cmac_prf.c
index ba23be7..5b14a86 100644
--- a/src/lib/crypto/krb/prf/ccm_prf.c
+++ b/src/lib/crypto/krb/prf/cmac_prf.c
@@ -1,6 +1,6 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
- * lib/crypto/krb/prf/ccm_prf.c
+ * lib/crypto/krb/prf/cmac_prf.c
*
* Copyright (C) 2010 by the Massachusetts Institute of Technology.
* All rights reserved.
@@ -34,8 +34,8 @@
#include <dk.h>
krb5_error_code
-krb5int_dk_ccm_prf(const struct krb5_keytypes *ktp, krb5_key key,
- const krb5_data *in, krb5_data *out)
+krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
{
krb5_crypto_iov iov;
krb5_data prfconst = make_data("prf", 3);
diff --git a/src/lib/crypto/krb/prf/prf_int.h b/src/lib/crypto/krb/prf/prf_int.h
index 25c4da6..1c98720 100644
--- a/src/lib/crypto/krb/prf/prf_int.h
+++ b/src/lib/crypto/krb/prf/prf_int.h
@@ -44,7 +44,7 @@ krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
const krb5_data *in, krb5_data *out);
krb5_error_code
-krb5int_dk_ccm_prf(const struct krb5_keytypes *ktp, krb5_key key,
- const krb5_data *in, krb5_data *out);
+krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out);
#endif /*PRF_INTERNAL_DEFS*/
diff --git a/src/util/k5test.py b/src/util/k5test.py
index 3e2f7a8..97269ac 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -1023,6 +1023,16 @@ _passes = [
'supported_enctypes' : 'camellia256-ccm:normal',
'master_key_type' : 'camellia256-ccm'}}}}),
+ # Exercise the camellia256-gcm enctype.
+ ('camellia256', None,
+ {'all' : {'libdefaults' : {
+ 'default_tgs_enctypes' : 'camellia256-gcm',
+ 'default_tkt_enctypes' : 'camellia256-gcm',
+ 'permitted_enctypes' : 'camellia256-gcm'}}},
+ {'master' : {'realms' : {'$realm' : {
+ 'supported_enctypes' : 'camellia256-gcm:normal',
+ 'master_key_type' : 'camellia256-gcm'}}}}),
+
# Test a setup with modern principal keys but an old TGT key.
('aes256.destgt', 'des-cbc-crc:normal',
{'all' : {'libdefaults' : {'allow_weak_crypto' : 'true'}}},