svn rev #24221: branches/camellia-ccm/src/lib/crypto/ crypto_tests/ krb/checksum/

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Jul 30 16:13:21 EDT 2010


http://src.mit.edu/fisheye/changelog/krb5/?cs=24221
Commit By: ghudson
Log Message:
Add comments to the CMAC implementation relating it to specific steps
in the RFC 4493 algorithm description, and adjust the code to make it
clearer what we're doing with the ivecs we're passing to the enc
provider cbc_mac method.  Add a test program for CMAC with
Camellia-128, using the RFC 4493 test vector inputs.



Changed Files:
U   branches/camellia-ccm/src/lib/crypto/crypto_tests/Makefile.in
A   branches/camellia-ccm/src/lib/crypto/crypto_tests/t_cmac.c
U   branches/camellia-ccm/src/lib/crypto/krb/checksum/cmac.c
U   branches/camellia-ccm/src/lib/crypto/libk5crypto.exports
Modified: branches/camellia-ccm/src/lib/crypto/crypto_tests/Makefile.in
===================================================================
--- branches/camellia-ccm/src/lib/crypto/crypto_tests/Makefile.in	2010-07-30 18:27:29 UTC (rev 24220)
+++ branches/camellia-ccm/src/lib/crypto/crypto_tests/Makefile.in	2010-07-30 20:13:20 UTC (rev 24221)
@@ -19,6 +19,7 @@
 	$(srcdir)/t_encrypt.c	\
 	$(srcdir)/t_prf.c 	\
 	$(srcdir)/t_prng.c	\
+	$(srcdir)/t_cmac.c	\
 	$(srcdir)/t_hmac.c	\
 	$(srcdir)/t_pkcs5.c	\
 	$(srcdir)/t_cts.c	\
@@ -43,7 +44,7 @@
 # NOTE: The t_cksum known checksum values are primarily for regression
 # testing.  They are not derived a priori, but are known to produce
 # checksums that interoperate.
-check-unix:: t_nfold t_encrypt t_prf t_prng t_hmac \
+check-unix:: t_nfold t_encrypt t_prf t_prng t_cmac t_hmac \
 		t_cksum4 t_cksum5 \
 		aes-test  \
 		camellia-test  \
@@ -53,6 +54,7 @@
 	$(RUN_SETUP) $(VALGRIND) ./t_encrypt
 	$(RUN_SETUP) $(VALGRIND) ./t_prng <$(srcdir)/t_prng.seed >t_prng.output && \
 	diff t_prng.output $(srcdir)/t_prng.expected
+	$(RUN_SETUP) $(VALGRIND) ./t_cmac
 	$(RUN_SETUP) $(VALGRIND) ./t_hmac
 	$(RUN_SETUP) $(VALGRIND) ./t_prf <$(srcdir)/t_prf.in >t_prf.output
 	diff t_prf.output $(srcdir)/t_prf.expected
@@ -90,6 +92,9 @@
 t_prng$(EXEEXT): t_prng.$(OBJEXT) $(SUPPORT_DEPLIB)
 	$(CC_LINK) -o $@ t_prng.$(OBJEXT)  -lk5crypto -lcom_err $(SUPPORT_LIB)
 
+t_cmac$(EXEEXT): t_cmac.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
+	$(CC_LINK) -o $@ t_cmac.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
 t_hmac$(EXEEXT): t_hmac.$(OBJEXT) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
 	$(CC_LINK) -o $@ t_hmac.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
 
@@ -147,8 +152,8 @@
 
 clean::
 	$(RM) t_nfold.o t_nfold nfold.$(OBJEXT) t_encrypt t_encrypt.o \
-		t_prng.o t_prng t_hmac.o t_hmac t_pkcs5.o t_pkcs5 pbkdf2.o \
-		t_prf t_prf.o \
+		t_prng.o t_prng t_cmac.o t_cmac t_hmac.o t_hmac \
+		t_pkcs5.o t_pkcs5 pbkdf2.o t_prf t_prf.o \
 		aes-test.o aes-test vt.txt vk.txt kresults.out \
 		t_cksum.o t_cksum \
 		t_crc.o t_crc t_cts.o t_cts \

Added: branches/camellia-ccm/src/lib/crypto/crypto_tests/t_cmac.c
===================================================================
--- branches/camellia-ccm/src/lib/crypto/crypto_tests/t_cmac.c	                        (rev 0)
+++ branches/camellia-ccm/src/lib/crypto/crypto_tests/t_cmac.c	2010-07-30 20:13:20 UTC (rev 24221)
@@ -0,0 +1,142 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/t_hmac.c
+ *
+ * Copyright 2001,2002 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.
+ *
+ *
+ * Test vectors for CMAC.  Inputs are taken from RFC 4493 section 4.  Outputs
+ * are changed for the use of Camellia-128 in place of AES-128.
+ *
+ * Ideally we would double-check subkey values, but we have no easy way to see
+ * them.
+ *
+ * Ideally we would test AES-CMAC against the expected results in RFC 4493,
+ * instead of results we generated ourselves.  This was done manually, but is
+ * not convenient to do automatically since the AES-128 enc provider has no
+ * cbc_mac method and therefore cannot be used with krb5int_cmac_checksum.
+ */
+
+#include "k5-int.h"
+#include "enc_provider.h"
+#include "cksumtypes.h"
+
+/* All examples use the following Camellia-128 key. */
+static unsigned char keybytes[] = {
+    0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+    0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+
+/* Example inputs are this message truncated to 0, 16, 40, and 64 bytes. */
+unsigned char input[] = {
+    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+/* Expected result of CMAC on empty input. */
+static unsigned char cmac1[] = {
+    0xba, 0x92, 0x57, 0x82, 0xaa, 0xa1, 0xf5, 0xd9,
+    0xa0, 0x0f, 0x89, 0x64, 0x80, 0x94, 0xfc, 0x71
+};
+
+/* Expected result of CMAC on first 16 bytes of input. */
+static unsigned char cmac2[] = {
+    0x6d, 0x96, 0x28, 0x54, 0xa3, 0xb9, 0xfd, 0xa5,
+    0x6d, 0x7d, 0x45, 0xa9, 0x5e, 0xe1, 0x79, 0x93
+};
+
+/* Expected result of CMAC on first 40 bytes of input. */
+static unsigned char cmac3[] = {
+    0x5c, 0x18, 0xd1, 0x19, 0xcc, 0xd6, 0x76, 0x61,
+    0x44, 0xac, 0x18, 0x66, 0x13, 0x1d, 0x9f, 0x22
+};
+
+/* Expected result of CMAC on all 64 bytes of input. */
+static unsigned char cmac4[] = {
+    0xc2, 0x69, 0x9a, 0x6e, 0xba, 0x55, 0xce, 0x9d,
+    0x93, 0x9a, 0x8a, 0x4e, 0x19, 0x46, 0x6e, 0xe9
+};
+
+static void
+check_result(const char *name, const unsigned char *result,
+	     const unsigned char *expected)
+{
+    int i;
+
+    for (i = 0; i < 16; i++) {
+	if (result[i] != expected[i]) {
+	    fprintf(stderr, "CMAC test vector failure: %s\n", name);
+	    exit(1);
+	}
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context = NULL;
+    krb5_keyblock keyblock;
+    krb5_key key;
+    const struct krb5_enc_provider *enc = &krb5int_enc_camellia128_ctr;
+    krb5_crypto_iov iov;
+    unsigned char resultbuf[16];
+    krb5_data result = make_data(resultbuf, 16);
+
+    /* Create the example key. */
+    keyblock.magic = KV5M_KEYBLOCK;
+    keyblock.enctype = ENCTYPE_CAMELLIA128_CCM_128;
+    keyblock.length = 16;
+    keyblock.contents = keybytes;
+    assert(krb5_k_create_key(context, &keyblock, &key) == 0);
+
+    /* Example 1. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = make_data(input, 0);
+    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
+    check_result("example 1", resultbuf, cmac1);
+
+    /* Example 2. */
+    iov.data.length = 16;
+    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
+    check_result("example 2", resultbuf, cmac2);
+
+    /* Example 1. */
+    iov.data.length = 40;
+    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
+    check_result("example 3", resultbuf, cmac3);
+
+    /* Example 1. */
+    iov.data.length = 64;
+    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
+    check_result("example 4", resultbuf, cmac4);
+
+    printf("All CMAC tests passed.\n");
+    krb5_k_free_key(context, key);
+    return 0;
+}

Modified: branches/camellia-ccm/src/lib/crypto/krb/checksum/cmac.c
===================================================================
--- branches/camellia-ccm/src/lib/crypto/krb/checksum/cmac.c	2010-07-30 18:27:29 UTC (rev 24220)
+++ branches/camellia-ccm/src/lib/crypto/krb/checksum/cmac.c	2010-07-30 20:13:20 UTC (rev 24221)
@@ -79,6 +79,7 @@
     }
 }
 
+/* Generate subkeys K1 and K2 as described in RFC 4493 figure 2.2. */
 static krb5_error_code
 generate_subkey(const struct krb5_enc_provider *enc,
                 krb5_key key,
@@ -92,16 +93,17 @@
     krb5_data d;
     krb5_error_code ret;
 
+    /* L := encrypt(K, const_Zero) */
     memset(Z, 0, sizeof(Z));
     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     iov[0].data = make_data(Z, sizeof(Z));
-
     d = make_data(L, BLOCK_SIZE);
-
+    /* cbc-mac is the same as block encrypt if invoked on a single block. */
     ret = enc->cbc_mac(key, iov, 1, NULL, &d);
     if (ret != 0)
         return ret;
 
+    /* K1 := (MSB(L) == 0) ? L << 1 : (L << 1) XOR const_Rb */
     if ((L[0] & 0x80) == 0) {
         leftshift_onebit(L, K1);
     } else {
@@ -109,6 +111,7 @@
         xor_128(tmp, const_Rb, K1);
     }
 
+    /* K2 := (MSB(K1) == 0) ? K1 << 1 : (K1 << 1) XOR const_Rb */
     if ((K1[0] & 0x80) == 0) {
         leftshift_onebit(K1, K2);
     } else {
@@ -119,6 +122,7 @@
     return 0;
 }
 
+/* Pad out lastb with a 1 bit followed by 0 bits, placing the result in pad. */
 static void
 padding(unsigned char *lastb, unsigned char *pad, int length)
 {
@@ -138,7 +142,7 @@
 
 /*
  * Implementation of CMAC algorithm. When used with AES, this function
- * is compatible with RFC 4493.
+ * is compatible with RFC 4493 figure 2.3.
  */
 krb5_error_code
 krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
@@ -152,7 +156,6 @@
     krb5_error_code ret;
     struct iov_block_state iov_state;
     unsigned int length;
-    krb5_data ivec;
     krb5_crypto_iov iov[1];
     krb5_data d;
 
@@ -168,12 +171,15 @@
             length += piov->data.length;
     }
 
+    /* Step 1. */
     ret = generate_subkey(enc, key, K1, K2);
     if (ret != 0)
         return ret;
 
+    /* Step 2. */
     n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
 
+    /* Step 3. */
     if (n == 0) {
         n = 1;
         flag = 0;
@@ -184,24 +190,23 @@
     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     iov[0].data = make_data(input, BLOCK_SIZE);
 
+    /* Step 5 (we'll do step 4 in a bit). */
     memset(Y, 0, BLOCK_SIZE);
-
-    ivec = make_data(Y, BLOCK_SIZE);
     d = make_data(Y, BLOCK_SIZE);
 
+    /* Step 6 (all but last block). */
     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);
+        ret = enc->cbc_mac(key, iov, 1, &d, &d);
         if (ret != 0)
             return ret;
     }
 
+    /* Step 4. */
     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);
@@ -210,9 +215,9 @@
         xor_128(padded, K2, M_last);
     }
 
+    /* Step 6 (last block). */
     iov[0].data = make_data(M_last, BLOCK_SIZE);
-
-    ret = enc->cbc_mac(key, iov, 1, &ivec, &d);
+    ret = enc->cbc_mac(key, iov, 1, &d, &d);
     if (ret != 0)
         return ret;
 

Modified: branches/camellia-ccm/src/lib/crypto/libk5crypto.exports
===================================================================
--- branches/camellia-ccm/src/lib/crypto/libk5crypto.exports	2010-07-30 18:27:29 UTC (rev 24220)
+++ branches/camellia-ccm/src/lib/crypto/libk5crypto.exports	2010-07-30 20:13:20 UTC (rev 24221)
@@ -96,3 +96,5 @@
 krb5int_enc_des3
 krb5int_arcfour_gsscrypt
 krb5int_camellia_cbc_mac
+krb5int_cmac_checksum
+krb5int_enc_camellia128_ctr




More information about the cvs-krb5 mailing list