Merge the camellia-ccm branch to trunk. Since there are no IANA
authorGreg Hudson <ghudson@mit.edu>
Tue, 7 Sep 2010 17:54:15 +0000 (17:54 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 7 Sep 2010 17:54:15 +0000 (17:54 +0000)
assignments for Camellia-CCM enctypes or cksumtypes yet, they are
disabled in a default build.  They can be made available by defining
(via CPPFLAGS) local-use enctype numbers for the enctypes and
cksumtypes.

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

63 files changed:
src/configure.in
src/include/k5-int.h
src/lib/crypto/Makefile.in
src/lib/crypto/builtin/Makefile.in
src/lib/crypto/builtin/camellia/Makefile.in [new file with mode: 0644]
src/lib/crypto/builtin/camellia/camellia-gen.c [new file with mode: 0644]
src/lib/crypto/builtin/camellia/camellia.c [new file with mode: 0644]
src/lib/crypto/builtin/camellia/camellia.h [new file with mode: 0644]
src/lib/crypto/builtin/camellia/deps [new file with mode: 0644]
src/lib/crypto/builtin/des/d3_aead.c
src/lib/crypto/builtin/des/f_aead.c
src/lib/crypto/builtin/enc_provider/Makefile.in
src/lib/crypto/builtin/enc_provider/aes.c
src/lib/crypto/builtin/enc_provider/camellia_ctr.c [new file with mode: 0644]
src/lib/crypto/builtin/enc_provider/enc_provider.h
src/lib/crypto/crypto_tests/Makefile.in
src/lib/crypto/crypto_tests/camellia-expect-vt.txt [new file with mode: 0644]
src/lib/crypto/crypto_tests/camellia-test.c [new file with mode: 0644]
src/lib/crypto/crypto_tests/t_camellia_ccm.c [new file with mode: 0644]
src/lib/crypto/crypto_tests/t_cmac.c [new file with mode: 0644]
src/lib/crypto/crypto_tests/t_encrypt.c
src/lib/crypto/crypto_tests/t_short.c
src/lib/crypto/crypto_tests/t_str2key.c [new file with mode: 0644]
src/lib/crypto/crypto_tests/vectors.c
src/lib/crypto/krb/Makefile.in
src/lib/crypto/krb/aead.c
src/lib/crypto/krb/aead.h
src/lib/crypto/krb/checksum/Makefile.in
src/lib/crypto/krb/checksum/cmac.c [new file with mode: 0644]
src/lib/crypto/krb/cksumtypes.c
src/lib/crypto/krb/cksumtypes.h
src/lib/crypto/krb/combine_keys.c
src/lib/crypto/krb/dk/Makefile.in
src/lib/crypto/krb/dk/checksum_cmac.c [new file with mode: 0644]
src/lib/crypto/krb/dk/checksum_hmac.c [moved from src/lib/crypto/krb/dk/checksum.c with 97% similarity]
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_ccm.c [new file with mode: 0644]
src/lib/crypto/krb/dk/stringtokey.c
src/lib/crypto/krb/etypes.c
src/lib/crypto/krb/etypes.h
src/lib/crypto/krb/prf/Makefile.in
src/lib/crypto/krb/prf/cmac_prf.c [new file with mode: 0644]
src/lib/crypto/krb/prf/dk_prf.c
src/lib/crypto/krb/prf/prf_int.h
src/lib/crypto/krb/rand2key/Makefile.in
src/lib/crypto/krb/rand2key/camellia_rand2key.c [new file with mode: 0644]
src/lib/crypto/krb/rand2key/rand2key.h
src/lib/crypto/krb/state.c
src/lib/crypto/libk5crypto.exports
src/lib/crypto/openssl/camellia/Makefile.in [new file with mode: 0644]
src/lib/crypto/openssl/camellia/deps [new file with mode: 0644]
src/lib/crypto/openssl/enc_provider/Makefile.in
src/lib/crypto/openssl/enc_provider/camellia_ctr.c [new file with mode: 0644]
src/lib/crypto/openssl/enc_provider/enc_provider.h
src/lib/krb5/krb/init_ctx.c
src/lib/krb5/krb/t_etypes.c
src/tests/dejagnu/config/default.exp
src/util/collected-client-lib/Makefile.in
src/util/k5test.py
src/windows/identity/plugins/krb5/datarep.c
src/windows/identity/plugins/krb5/lang/en_us/langres.rc

index 1d86f977059178aa856b99829b8a5ff0fa39c927..ec5672def7cf31c37be92f761ae4b8474e859e40 100644 (file)
@@ -1084,7 +1084,7 @@ V5_AC_OUTPUT_MAKEFILE(.
        lib/crypto/$CRYPTO_IMPL lib/crypto/$CRYPTO_IMPL/md4 lib/crypto/$CRYPTO_IMPL/md5
        lib/crypto/krb/old lib/crypto/krb/raw lib/crypto/$CRYPTO_IMPL/sha1
        lib/crypto/krb/arcfour lib/crypto/krb/yarrow lib/crypto/$CRYPTO_IMPL/aes
-       lib/crypto/crypto_tests
+       lib/crypto/$CRYPTO_IMPL/camellia lib/crypto/crypto_tests
 
        lib/krb5 lib/krb5/error_tables lib/krb5/asn.1 lib/krb5/ccache
 dnl    lib/krb5/ccache/ccapi
index 4b2fdd25dbf94bab749be202d27745ceda8f44f0..efffa3b5ee59e95400a3be9f9d36dc61de0f17b7 100644 (file)
@@ -2676,6 +2676,30 @@ krb5_error_code
 krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
                     size_t num_data);
 
+krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *iv,
+                         krb5_data *output);
+
+#if 0
+/*
+ * There are no IANA assignments for these enctypes or cksumtypes yet.  They
+ * must be defined to local-use negative numbers at build time for Camellia-CCM
+ * support to function at the moment.  If one is defined, they should all be
+ * defined.  When IANA assignments exist, these definitions should move to the
+ * appropriate places in krb5.hin and all CAMELLIA_CCM conditional code should
+ * be made unconditional.
+ */
+#define ENCTYPE_CAMELLIA128_CCM_128 -XXX /* Camellia CCM mode, 128-bit key */
+#define ENCTYPE_CAMELLIA256_CCM_128 -YYY /* Camellia CCM mode, 256-bit key */
+#define CKSUMTYPE_CMAC_128_CAMELLIA128  -XXX  /* CMAC, 128-bit Camellia key */
+#define CKSUMTYPE_CMAC_128_CAMELLIA256  -YYY  /* CMAC, 256-bit Camellia key */
+#endif
+
+#ifdef ENCTYPE_CAMELLIA128_CCM_128
+#define CAMELLIA_CCM
+#endif
+
 struct _krb5_kt {       /* should move into k5-int.h */
     krb5_magic magic;
     const struct _krb5_kt_ops *ops;
index fa12e19c723ba0a897dd1b8971bc19d112b813ce..a05f086e7fe0a830c460657a55a2f12f33d0777f 100644 (file)
@@ -27,7 +27,7 @@ STOBJLISTS=krb/crc32/OBJS.ST krb/dk/OBJS.ST                           \
        @CRYPTO_IMPL@/sha1/OBJS.ST                                      \
        krb/arcfour/OBJS.ST                                             \
        @CRYPTO_IMPL@/aes/OBJS.ST @CRYPTO_IMPL@/des/OBJS.ST             \
-       krb/OBJS.ST                                                     \
+       @CRYPTO_IMPL@/camellia/OBJS.ST krb/OBJS.ST                      \
        @CRYPTO_IMPL@/OBJS.ST
 
 SUBDIROBJLISTS=krb/crc32/OBJS.ST krb/dk/OBJS.ST                                \
@@ -39,7 +39,7 @@ SUBDIROBJLISTS=krb/crc32/OBJS.ST krb/dk/OBJS.ST                               \
        @CRYPTO_IMPL@/sha1/OBJS.ST                                      \
        krb/arcfour/OBJS.ST                                             \
        @CRYPTO_IMPL@/aes/OBJS.ST @CRYPTO_IMPL@/des/OBJS.ST             \
-       krb/OBJS.ST                                                     \
+       @CRYPTO_IMPL@/camellia/OBJS.ST krb/OBJS.ST                      \
        @CRYPTO_IMPL@/OBJS.ST
 
 # No dependencies.  Record places to find this shared object if the target
index a65f64df988504f0d06ad021c3bb528e6bdba439..4e7e0cd87b35442fb34fe0b02d0dac011d86f1f0 100644 (file)
@@ -1,10 +1,11 @@
 mydir=lib/crypto/builtin
 BUILDTOP=$(REL)..$(S)..$(S)..
-SUBDIRS=des aes         md4 md5  sha1 enc_provider hash_provider
+SUBDIRS=camellia des aes md4 md5 sha1 enc_provider hash_provider
 LOCALINCLUDES = -I$(srcdir)/../krb                     \
                -I$(srcdir)/../krb/hash_provider        \
                -I$(srcdir)/des         \
                -I$(srcdir)/aes         \
+               -I$(srcdir)/camellia    \
                -I$(srcdir)/sha1        \
                -I$(srcdir)/md4         \
                -I$(srcdir)/md5 \
@@ -21,8 +22,8 @@ EXTRADEPSRCS= $(srcdir)/t_cf2.c
 ##DOSBUILDTOP = ..\..\..
 ##DOSLIBNAME=$(OUTPRE)crypto.lib
 ##DOSOBJFILE=$(OUTPRE)crypto.lst
-##DOSOBJFILELIST=@$(OUTPRE)crypto.lst @$(OUTPRE)des.lst @$(OUTPRE)md4.lst @$(OUTPRE)md5.lst @$(OUTPRE)sha1.lst @$(OUTPRE)crc32.lst @$(OUTPRE)dk.lst @$(OUTPRE)old.lst @$(OUTPRE)raw.lst @$(OUTPRE)enc_prov.lst @$(OUTPRE)hash_pro.lst @$(OUTPRE)kh_pro.lst @$(OUTPRE)yarrow.lst @$(OUTPRE)aes.lst
-##DOSOBJFILEDEP =$(OUTPRE)crypto.lst $(OUTPRE)des.lst $(OUTPRE)md4.lst $(OUTPRE)md5.lst $(OUTPRE)sha1.lst $(OUTPRE)crc32.lst $(OUTPRE)dk.lst $(OUTPRE)old.lst $(OUTPRE)raw.lst $(OUTPRE)enc_prov.lst $(OUTPRE)hash_pro.lst $(OUTPRE)kh_pro.lst $(OUTPRE)aes.lst
+##DOSOBJFILELIST=@$(OUTPRE)crypto.lst @$(OUTPRE)des.lst @$(OUTPRE)md4.lst @$(OUTPRE)md5.lst @$(OUTPRE)sha1.lst @$(OUTPRE)crc32.lst @$(OUTPRE)dk.lst @$(OUTPRE)old.lst @$(OUTPRE)raw.lst @$(OUTPRE)enc_prov.lst @$(OUTPRE)hash_pro.lst @$(OUTPRE)kh_pro.lst @$(OUTPRE)yarrow.lst @$(OUTPRE)aes.lst $(OUTPRE)camellia.lst
+##DOSOBJFILEDEP =$(OUTPRE)crypto.lst $(OUTPRE)des.lst $(OUTPRE)md4.lst $(OUTPRE)md5.lst $(OUTPRE)sha1.lst $(OUTPRE)crc32.lst $(OUTPRE)dk.lst $(OUTPRE)old.lst $(OUTPRE)raw.lst $(OUTPRE)enc_prov.lst $(OUTPRE)hash_pro.lst $(OUTPRE)kh_pro.lst $(OUTPRE)aes.lst $(OUTPRE)camellia.lst
 
 STLIBOBJS=\
        hmac.o  \
@@ -41,13 +42,15 @@ STOBJLISTS= des/OBJS.ST md4/OBJS.ST         \
        enc_provider/OBJS.ST            \
        hash_provider/OBJS.ST           \
        aes/OBJS.ST                     \
+       camellia/OBJS.ST                \
        OBJS.ST
 
 SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST        \
                md5/OBJS.ST sha1/OBJS.ST        \
                enc_provider/OBJS.ST            \
                hash_provider/OBJS.ST           \
-               aes/OBJS.ST 
+               aes/OBJS.ST                     \
+               camellia/OBJS.ST 
 
 ##DOS##LIBOBJS = $(OBJS)
 
@@ -92,6 +95,9 @@ all-windows::
        cd ..\aes
        @echo Making in crypto\aes
        $(MAKE) -$(MFLAGS)
+       cd ..\camellia
+       @echo Making in crypto\camellia
+       $(MAKE) -$(MFLAGS)
        cd ..
 
 clean-windows::
@@ -116,6 +122,9 @@ clean-windows::
        cd ..\aes
        @echo Making clean in crypto\aes
        $(MAKE) -$(MFLAGS) clean
+       cd ..\camellia
+       @echo Making clean in crypto\camellia
+       $(MAKE) -$(MFLAGS) clean
        cd ..
 
 check-windows::
@@ -140,6 +149,9 @@ check-windows::
        cd ..\aes
        @echo Making check in crypto\aes
        $(MAKE) -$(MFLAGS) check
+       cd ..\camellia
+       @echo Making check in crypto\camellia
+       $(MAKE) -$(MFLAGS) check
        cd ..
 
 
diff --git a/src/lib/crypto/builtin/camellia/Makefile.in b/src/lib/crypto/builtin/camellia/Makefile.in
new file mode 100644 (file)
index 0000000..32cbd50
--- /dev/null
@@ -0,0 +1,50 @@
+thisconfigdir=../../../..
+myfulldir=lib/crypto/builtin/camellia
+mydir=lib/crypto/builtin/camellia
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb/dk \
+        -I$(srcdir)/../../../../include -I$(srcdir)/../aes
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR=camellia
+##DOS##OBJFILE=..\$(OUTPRE)camellia.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS=\
+       camellia.o
+
+OBJS=\
+       $(OUTPRE)camellia.$(OBJEXT)
+
+SRCS=\
+       $(srcdir)/camellia.c
+
+GEN_OBJS=\
+       $(OUTPRE)camellia.$(OBJEXT)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs # camellia-gen
+
+includes:: depend
+
+depend:: $(SRCS)
+
+camellia-gen: camellia-gen.o $(GEN_OBJS)
+       $(CC_LINK) -I../../../../include $(LOCALINCLUDES) -o camellia-gen camellia-gen.o $(GEN_OBJS)
+
+run-camellia-gen: camellia-gen
+       ./camellia-gen > kresults.out
+
+check:: run-camellia-gen
+
+
+clean-unix:: clean-libobjs
+
+clean::
+       -$(RM) camellia-gen camellia-gen.o kresults.out
+
+@libobj_frag@
diff --git a/src/lib/crypto/builtin/camellia/camellia-gen.c b/src/lib/crypto/builtin/camellia/camellia-gen.c
new file mode 100644 (file)
index 0000000..1446d77
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2009
+ * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "camellia.h"
+
+#define B 16U
+unsigned char key[16];
+unsigned char test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, };
+#define NTESTS (sizeof(test_case_len))
+struct {
+    unsigned char ivec[16];
+    unsigned char input[4*16];
+    unsigned char output[4*16];
+} test_case[NTESTS];
+camellia_ctx ctx, dctx;
+
+static void init ()
+{
+    int i, j, r;
+
+    srand(42);
+    for (i = 0; i < 16; i++)
+       key[i] = 0xff & rand();
+    memset(test_case, 0, sizeof(test_case));
+    for (i = 0; i < NTESTS; i++)
+       for (j = 0; j < test_case_len[i]; j++) {
+           test_case[i].input[j] = 0xff & rand();
+       }
+
+    r = camellia_enc_key (key, sizeof(key), &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = camellia_dec_key (key, sizeof(key), &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+}
+
+static void hexdump(const unsigned char *ptr, size_t len)
+{
+    int i;
+    for (i = 0; i < len; i++)
+       printf ("%s%02X", (i % 16 == 0) ? "\n    " : " ", ptr[i]);
+}
+
+static void fips_test ()
+{
+    static const unsigned char fipskey[16] = {
+       0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+       0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+    };
+    static const unsigned char input[16] = {
+       0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+       0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+    };
+    static const unsigned char expected[16] = {
+       0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73,
+       0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43
+    };
+    unsigned char output[16];
+    unsigned char tmp[16];
+    camellia_ctx fipsctx;
+    int r;
+
+    printf ("FIPS test:\nkey:");
+    hexdump (fipskey, 16);
+    printf ("\ninput:");
+    hexdump (input, 16);
+    r = camellia_enc_key (fipskey, sizeof(fipskey), &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = camellia_enc_blk (input, output, &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    printf ("\noutput:");
+    hexdump (output, 16);
+    printf ("\n");
+    if (memcmp(expected, output, 16))
+       fprintf(stderr, "wrong results!!!\n"), exit (1);
+    r = camellia_dec_key (fipskey, sizeof(fipskey), &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    r = camellia_dec_blk (output, tmp, &fipsctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    if (memcmp(input, tmp, 16))
+       fprintf(stderr, "decryption failed!!\n"), exit(1);
+    printf ("ok.\n\n");
+}
+
+static void
+xor (unsigned char *out, const unsigned char *a, const unsigned char *b)
+{
+    int i;
+    for (i = 0; i < B; i++)
+       out[i] = a[i] ^ b[i];
+}
+
+static void
+ecb_enc (unsigned char *out, unsigned char *in, unsigned int len)
+{
+    int i, r;
+    for (i = 0; i < len; i += 16) {
+       r = camellia_enc_blk (in + i, out + i, &ctx);
+       if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    }
+    if (i != len) abort ();
+}
+
+static void
+ecb_dec (unsigned char *out, unsigned char *in, unsigned int len)
+{
+    int i, r;
+    for (i = 0; i < len; i += 16) {
+       r = camellia_dec_blk (in + i, out + i, &dctx);
+       if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    }
+    if (i != len) abort ();
+}
+
+#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n"))
+
+#undef D
+#define D(X)
+
+static void
+cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+        unsigned int len)
+{
+    int i, r;
+    unsigned char tmp[B];
+    D(iv);
+    memcpy (tmp, iv, B);
+    for (i = 0; i < len; i += B) {
+       D(in+i);
+       xor (tmp, tmp, in + i);
+       D(tmp);
+       r = camellia_enc_blk (tmp, out + i, &ctx);
+       if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+       memcpy (tmp, out + i, B);
+       D(out+i);
+    }
+    if (i != len) abort ();
+}
+
+static void
+cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+        unsigned int len)
+{
+    int i, r;
+    unsigned char tmp[B];
+    memcpy (tmp, iv, B);
+    for (i = 0; i < len; i += B) {
+       r = camellia_dec_blk (in + i, tmp, &dctx);
+       if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+       xor (tmp, tmp, iv);
+       iv = in + i;
+       memcpy (out + i, tmp, B);
+    }
+    if (i != len) abort ();
+}
+
+static void
+cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+        unsigned int len)
+{
+    int r;
+    unsigned int len2;
+    unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+    if (len < B + 1) abort ();
+    len2 = (len - B - 1) & ~(B-1);
+    cbc_enc (out, in, iv, len2);
+    out += len2;
+    in += len2;
+    len -= len2;
+    if (len2)
+       iv = out - B;
+    if (len <= B || len > 2 * B)
+       abort ();
+    printf ("(did CBC mode for %d)\n", len2);
+
+    D(in);
+    xor (pn1, in, iv);
+    D(pn1);
+    r = camellia_enc_blk (pn1, cn, &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    D(cn);
+    memset (pn, 0, sizeof(pn));
+    memcpy (pn, in+B, len-B);
+    D(pn);
+    xor (pn, pn, cn);
+    D(pn);
+    r = camellia_enc_blk (pn, cn1, &ctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    D(cn1);
+    memcpy(out, cn1, B);
+    memcpy(out+B, cn, len-B);
+}
+
+static void
+cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+        unsigned int len)
+{
+    int r;
+    unsigned int len2;
+    unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+    if (len < B + 1) abort ();
+    len2 = (len - B - 1) & ~(B-1);
+    cbc_dec (out, in, iv, len2);
+    out += len2;
+    in += len2;
+    len -= len2;
+    if (len2)
+       iv = in - B;
+    if (len <= B || len > 2 * B)
+       abort ();
+
+    memcpy (cn1, in, B);
+    r = camellia_dec_blk (cn1, pn, &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    memset (cn, 0, sizeof(cn));
+    memcpy (cn, in+B, len-B);
+    xor (pn, pn, cn);
+    memcpy (cn+len-B, pn+len-B, 2*B-len);
+    r = camellia_dec_blk (cn, pn1, &dctx);
+    if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+    xor (pn1, pn1, iv);
+    memcpy(out, pn1, B);
+    memcpy(out+B, pn, len-B);
+}
+
+static void ecb_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("ECB tests:\n");
+    printf ("key:");
+    hexdump (key, sizeof(key));
+    for (testno = 0; testno < NTESTS; testno++) {
+       unsigned len = (test_case_len[testno] + 15) & ~15;
+       printf ("\ntest %d - %d bytes\n", testno, len);
+       printf ("input:");
+       hexdump (test_case[testno].input, len);
+       printf ("\n");
+       ecb_enc (test_case[testno].output, test_case[testno].input, len);
+       printf ("output:");
+       hexdump (test_case[testno].output, len);
+       printf ("\n");
+       ecb_dec (tmp, test_case[testno].output, len);
+       if (memcmp (tmp, test_case[testno].input, len)) {
+           printf ("ecb decrypt failed!!");
+           hexdump (tmp, len);
+           printf ("\n");
+           exit (1);
+       }
+    }
+    printf ("\n");
+}
+
+unsigned char ivec[16] = { 0 };
+
+static void cbc_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("CBC tests:\n");
+    printf ("initial vector:");
+    hexdump (ivec, sizeof(ivec));
+    for (testno = 0; testno < NTESTS; testno++) {
+       unsigned len = (test_case_len[testno] + 15) & ~15;
+       printf ("\ntest %d - %d bytes\n", testno, len);
+       printf ("input:");
+       hexdump (test_case[testno].input, len);
+       printf ("\n");
+       cbc_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+       printf ("output:");
+       hexdump (test_case[testno].output, len);
+       printf ("\n");
+       cbc_dec (tmp, test_case[testno].output, ivec, len);
+       if (memcmp (tmp, test_case[testno].input, len)) {
+           printf("cbc decrypt failed!!");
+           hexdump (tmp, len);
+           printf ("\n");
+           exit(1);
+       }
+    }
+    printf ("\n");
+}
+
+static void cts_test ()
+{
+    int testno;
+    unsigned char tmp[4*B];
+
+    printf ("CTS tests:\n");
+    printf ("initial vector:");
+    hexdump (ivec, sizeof(ivec));
+    for (testno = 0; testno < NTESTS; testno++) {
+       unsigned int len = test_case_len[testno];
+       printf ("\ntest %d - %d bytes\n", testno, len);
+       printf ("input:");
+       hexdump (test_case[testno].input, len);
+       printf ("\n");
+       cts_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+       printf ("output:");
+       hexdump (test_case[testno].output, len);
+       printf ("\n");
+       cts_dec (tmp, test_case[testno].output, ivec, len);
+       if (memcmp (tmp, test_case[testno].input, len))
+           fprintf (stderr, "cts decrypt failed!!\n"), exit(1);
+    }
+    printf ("\n");
+}
+
+int main ()
+{
+    init ();
+    fips_test ();
+
+    ecb_test();
+    cbc_test();
+    cts_test();
+
+    return 0;
+}
+
diff --git a/src/lib/crypto/builtin/camellia/camellia.c b/src/lib/crypto/builtin/camellia/camellia.c
new file mode 100644 (file)
index 0000000..57b2e36
--- /dev/null
@@ -0,0 +1,1539 @@
+/* camellia.c ver 1.2.0
+ *
+ * Copyright (c) 2006,2007,2009
+ * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer as
+ *   the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Algorithm Specification 
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "camellia.h"
+
+/* key constants */
+
+#define CAMELLIA_SIGMA1L (0xA09E667FL)
+#define CAMELLIA_SIGMA1R (0x3BCC908BL)
+#define CAMELLIA_SIGMA2L (0xB67AE858L)
+#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
+#define CAMELLIA_SIGMA3L (0xC6EF372FL)
+#define CAMELLIA_SIGMA3R (0xE94F82BEL)
+#define CAMELLIA_SIGMA4L (0x54FF53A5L)
+#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
+#define CAMELLIA_SIGMA5L (0x10E527FAL)
+#define CAMELLIA_SIGMA5R (0xDE682D1DL)
+#define CAMELLIA_SIGMA6L (0xB05688C2L)
+#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
+
+/*
+ *  macros
+ */
+
+
+#if defined(_MSC_VER)
+
+# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+# define GETU32(p) SWAP(*((u32 *)(p)))
+# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));}
+
+#else /* not MS-VC */
+
+# define GETU32(pt)                            \
+    (((u32)(pt)[0] << 24)                      \
+     ^ ((u32)(pt)[1] << 16)                    \
+     ^ ((u32)(pt)[2] <<  8)                    \
+     ^ ((u32)(pt)[3]))
+
+# define PUTU32(ct, st)  {                     \
+       (ct)[0] = (u8)((st) >> 24);             \
+       (ct)[1] = (u8)((st) >> 16);             \
+       (ct)[2] = (u8)((st) >>  8);             \
+       (ct)[3] = (u8)(st); }
+
+#endif
+
+#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2])
+#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1])
+
+/* rotation right shift 1byte */
+#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
+
+#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)   \
+    do {                                               \
+       w0 = ll;                                        \
+       ll = (ll << bits) + (lr >> (32 - bits));        \
+       lr = (lr << bits) + (rl >> (32 - bits));        \
+       rl = (rl << bits) + (rr >> (32 - bits));        \
+       rr = (rr << bits) + (w0 >> (32 - bits));        \
+    } while(0)
+
+#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)        \
+    do {                                               \
+       w0 = ll;                                        \
+       w1 = lr;                                        \
+       ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \
+       lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \
+       rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \
+       rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \
+    } while(0)
+
+#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
+#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
+#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
+#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
+
+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)     \
+    do {                                                       \
+       il = xl ^ kl;                                           \
+       ir = xr ^ kr;                                           \
+       t0 = il >> 16;                                          \
+       t1 = ir >> 16;                                          \
+       yl = CAMELLIA_SP1110(ir & 0xff)                         \
+           ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)                 \
+           ^ CAMELLIA_SP3033(t1 & 0xff)                        \
+           ^ CAMELLIA_SP4404((ir >> 8) & 0xff);                \
+       yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)                  \
+           ^ CAMELLIA_SP0222(t0 & 0xff)                        \
+           ^ CAMELLIA_SP3033((il >> 8) & 0xff)                 \
+           ^ CAMELLIA_SP4404(il & 0xff);                       \
+       yl ^= yr;                                               \
+       yr = CAMELLIA_RR8(yr);                                  \
+       yr ^= yl;                                               \
+    } while(0)
+
+
+/*
+ * for speed up
+ *
+ */
+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+    do {                                                               \
+       t0 = kll;                                                       \
+       t0 &= ll;                                                       \
+       lr ^= CAMELLIA_RL1(t0);                                         \
+       t1 = klr;                                                       \
+       t1 |= lr;                                                       \
+       ll ^= t1;                                                       \
+                                                                       \
+       t2 = krr;                                                       \
+       t2 |= rr;                                                       \
+       rl ^= t2;                                                       \
+       t3 = krl;                                                       \
+       t3 &= rl;                                                       \
+       rr ^= CAMELLIA_RL1(t3);                                         \
+    } while(0)
+
+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)       \
+    do {                                                               \
+       ir = CAMELLIA_SP1110(xr & 0xff)                                 \
+           ^ CAMELLIA_SP0222((xr >> 24) & 0xff)                        \
+           ^ CAMELLIA_SP3033((xr >> 16) & 0xff)                        \
+           ^ CAMELLIA_SP4404((xr >> 8) & 0xff);                        \
+       il = CAMELLIA_SP1110((xl >> 24) & 0xff)                         \
+           ^ CAMELLIA_SP0222((xl >> 16) & 0xff)                        \
+           ^ CAMELLIA_SP3033((xl >> 8) & 0xff)                         \
+           ^ CAMELLIA_SP4404(xl & 0xff);                               \
+       il ^= kl;                                                       \
+       ir ^= kr;                                                       \
+       ir ^= il;                                                       \
+       il = CAMELLIA_RR8(il);                                          \
+       il ^= ir;                                                       \
+       yl ^= ir;                                                       \
+       yr ^= il;                                                       \
+    } while(0)
+
+
+static const u32 camellia_sp1110[256] = {
+    0x70707000,0x82828200,0x2c2c2c00,0xececec00,
+    0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
+    0xe4e4e400,0x85858500,0x57575700,0x35353500,
+    0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
+    0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
+    0x45454500,0x19191900,0xa5a5a500,0x21212100,
+    0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
+    0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
+    0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
+    0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
+    0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
+    0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
+    0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
+    0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
+    0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
+    0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
+    0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
+    0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
+    0x74747400,0x12121200,0x2b2b2b00,0x20202000,
+    0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
+    0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
+    0x34343400,0x7e7e7e00,0x76767600,0x05050500,
+    0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
+    0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
+    0x14141400,0x58585800,0x3a3a3a00,0x61616100,
+    0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
+    0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
+    0x53535300,0x18181800,0xf2f2f200,0x22222200,
+    0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
+    0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
+    0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
+    0x60606000,0xfcfcfc00,0x69696900,0x50505000,
+    0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
+    0xa1a1a100,0x89898900,0x62626200,0x97979700,
+    0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
+    0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
+    0x10101000,0xc4c4c400,0x00000000,0x48484800,
+    0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
+    0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
+    0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
+    0x87878700,0x5c5c5c00,0x83838300,0x02020200,
+    0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
+    0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
+    0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
+    0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
+    0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
+    0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
+    0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
+    0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
+    0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
+    0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
+    0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
+    0x78787800,0x98989800,0x06060600,0x6a6a6a00,
+    0xe7e7e700,0x46464600,0x71717100,0xbababa00,
+    0xd4d4d400,0x25252500,0xababab00,0x42424200,
+    0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
+    0x72727200,0x07070700,0xb9b9b900,0x55555500,
+    0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
+    0x36363600,0x49494900,0x2a2a2a00,0x68686800,
+    0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
+    0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
+    0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
+    0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
+    0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
+};
+
+static const u32 camellia_sp0222[256] = {
+    0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
+    0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
+    0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
+    0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
+    0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
+    0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
+    0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
+    0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
+    0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
+    0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
+    0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
+    0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
+    0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
+    0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
+    0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
+    0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
+    0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
+    0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
+    0x00e8e8e8,0x00242424,0x00565656,0x00404040,
+    0x00e1e1e1,0x00636363,0x00090909,0x00333333,
+    0x00bfbfbf,0x00989898,0x00979797,0x00858585,
+    0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
+    0x00dadada,0x006f6f6f,0x00535353,0x00626262,
+    0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
+    0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
+    0x00bdbdbd,0x00363636,0x00222222,0x00383838,
+    0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
+    0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
+    0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
+    0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
+    0x00484848,0x00101010,0x00d1d1d1,0x00515151,
+    0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
+    0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
+    0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
+    0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
+    0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
+    0x00202020,0x00898989,0x00000000,0x00909090,
+    0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
+    0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
+    0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
+    0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
+    0x009b9b9b,0x00949494,0x00212121,0x00666666,
+    0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
+    0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
+    0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
+    0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
+    0x00030303,0x002d2d2d,0x00dedede,0x00969696,
+    0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
+    0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
+    0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
+    0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
+    0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
+    0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
+    0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
+    0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
+    0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
+    0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
+    0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
+    0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
+    0x00787878,0x00707070,0x00e3e3e3,0x00494949,
+    0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
+    0x00777777,0x00939393,0x00868686,0x00838383,
+    0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
+    0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
+};
+
+static const u32 camellia_sp3033[256] = {
+    0x38003838,0x41004141,0x16001616,0x76007676,
+    0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
+    0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
+    0x75007575,0x06000606,0x57005757,0xa000a0a0,
+    0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
+    0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
+    0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
+    0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
+    0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
+    0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
+    0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
+    0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
+    0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
+    0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
+    0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
+    0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
+    0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
+    0xfd00fdfd,0x66006666,0x58005858,0x96009696,
+    0x3a003a3a,0x09000909,0x95009595,0x10001010,
+    0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
+    0xef00efef,0x26002626,0xe500e5e5,0x61006161,
+    0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
+    0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
+    0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
+    0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
+    0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
+    0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
+    0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
+    0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
+    0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
+    0x12001212,0x04000404,0x74007474,0x54005454,
+    0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
+    0x55005555,0x68006868,0x50005050,0xbe00bebe,
+    0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
+    0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
+    0x70007070,0xff00ffff,0x32003232,0x69006969,
+    0x08000808,0x62006262,0x00000000,0x24002424,
+    0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
+    0x45004545,0x81008181,0x73007373,0x6d006d6d,
+    0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
+    0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
+    0xe600e6e6,0x25002525,0x48004848,0x99009999,
+    0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
+    0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
+    0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
+    0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
+    0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
+    0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
+    0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
+    0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
+    0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
+    0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
+    0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
+    0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
+    0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
+    0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
+    0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
+    0x7c007c7c,0x77007777,0x56005656,0x05000505,
+    0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
+    0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
+    0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
+    0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
+    0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
+    0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
+};
+
+static const u32 camellia_sp4404[256] = {
+    0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
+    0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
+    0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
+    0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
+    0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
+    0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
+    0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
+    0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
+    0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
+    0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
+    0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
+    0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
+    0x14140014,0x3a3a003a,0xdede00de,0x11110011,
+    0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
+    0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
+    0x24240024,0xe8e800e8,0x60600060,0x69690069,
+    0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
+    0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
+    0x10100010,0x00000000,0xa3a300a3,0x75750075,
+    0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
+    0x87870087,0x83830083,0xcdcd00cd,0x90900090,
+    0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
+    0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
+    0x81810081,0x6f6f006f,0x13130013,0x63630063,
+    0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
+    0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
+    0x78780078,0x06060006,0xe7e700e7,0x71710071,
+    0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
+    0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
+    0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
+    0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
+    0x15150015,0xadad00ad,0x77770077,0x80800080,
+    0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
+    0x85850085,0x35350035,0x0c0c000c,0x41410041,
+    0xefef00ef,0x93930093,0x19190019,0x21210021,
+    0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
+    0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
+    0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
+    0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
+    0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
+    0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
+    0x12120012,0x20200020,0xb1b100b1,0x99990099,
+    0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
+    0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
+    0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
+    0x0f0f000f,0x16160016,0x18180018,0x22220022,
+    0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
+    0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
+    0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
+    0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
+    0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
+    0x03030003,0xdada00da,0x3f3f003f,0x94940094,
+    0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
+    0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
+    0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
+    0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
+    0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
+    0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
+    0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
+    0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
+    0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
+    0x49490049,0x68680068,0x38380038,0xa4a400a4,
+    0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
+    0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
+};
+
+
+/**
+ * Stuff related to the Camellia key schedule
+ */
+#define subl(x) subL[(x)]
+#define subr(x) subR[(x)]
+
+void
+camellia_setup128(const unsigned char *key, u32 *subkey)
+{
+    u32 kll, klr, krl, krr;
+    u32 il, ir, t0, t1, w0, w1;
+    u32 kw4l, kw4r, dw, tl, tr;
+    u32 subL[26];
+    u32 subR[26];
+
+    /**
+     *  k == kll || klr || krl || krr (|| is concatination)
+     */
+    kll = GETU32(key     );
+    klr = GETU32(key +  4);
+    krl = GETU32(key +  8);
+    krr = GETU32(key + 12);
+    /**
+     * generate KL dependent subkeys
+     */
+    subl(0) = kll; subr(0) = klr;
+    subl(1) = krl; subr(1) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(4) = kll; subr(4) = klr;
+    subl(5) = krl; subr(5) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+    subl(10) = kll; subr(10) = klr;
+    subl(11) = krl; subr(11) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(13) = krl; subr(13) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(16) = kll; subr(16) = klr;
+    subl(17) = krl; subr(17) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(18) = kll; subr(18) = klr;
+    subl(19) = krl; subr(19) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(22) = kll; subr(22) = klr;
+    subl(23) = krl; subr(23) = krr;
+
+    /* generate KA */
+    kll = subl(0); klr = subr(0);
+    krl = subl(1); krr = subr(1);
+    CAMELLIA_F(kll, klr,
+              CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+              w0, w1, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+              CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+              kll, klr, il, ir, t0, t1);
+    CAMELLIA_F(kll, klr,
+              CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+              krl, krr, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+              CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+              w0, w1, il, ir, t0, t1);
+    kll ^= w0; klr ^= w1;
+
+    /* generate KA dependent subkeys */
+    subl(2) = kll; subr(2) = klr;
+    subl(3) = krl; subr(3) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(6) = kll; subr(6) = klr;
+    subl(7) = krl; subr(7) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(8) = kll; subr(8) = klr;
+    subl(9) = krl; subr(9) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(12) = kll; subr(12) = klr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(14) = kll; subr(14) = klr;
+    subl(15) = krl; subr(15) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+    subl(20) = kll; subr(20) = klr;
+    subl(21) = krl; subr(21) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(24) = kll; subr(24) = klr;
+    subl(25) = krl; subr(25) = krr;
+
+
+    /* absorb kw2 to other subkeys */
+    subl(3) ^= subl(1); subr(3) ^= subr(1);
+    subl(5) ^= subl(1); subr(5) ^= subr(1);
+    subl(7) ^= subl(1); subr(7) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(9);
+    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(11) ^= subl(1); subr(11) ^= subr(1);
+    subl(13) ^= subl(1); subr(13) ^= subr(1);
+    subl(15) ^= subl(1); subr(15) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(17);
+    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(19) ^= subl(1); subr(19) ^= subr(1);
+    subl(21) ^= subl(1); subr(21) ^= subr(1);
+    subl(23) ^= subl(1); subr(23) ^= subr(1);
+    subl(24) ^= subl(1); subr(24) ^= subr(1);
+
+    /* absorb kw4 to other subkeys */
+    kw4l = subl(25); kw4r = subr(25);
+    subl(22) ^= kw4l; subr(22) ^= kw4r;
+    subl(20) ^= kw4l; subr(20) ^= kw4r;
+    subl(18) ^= kw4l; subr(18) ^= kw4r;
+    kw4l ^= kw4r & ~subr(16);
+    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
+    subl(14) ^= kw4l; subr(14) ^= kw4r;
+    subl(12) ^= kw4l; subr(12) ^= kw4r;
+    subl(10) ^= kw4l; subr(10) ^= kw4r;
+    kw4l ^= kw4r & ~subr(8);
+    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
+    subl(6) ^= kw4l; subr(6) ^= kw4r;
+    subl(4) ^= kw4l; subr(4) ^= kw4r;
+    subl(2) ^= kw4l; subr(2) ^= kw4r;
+    subl(0) ^= kw4l; subr(0) ^= kw4r;
+
+    /* key XOR is end of F-function */
+    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
+    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
+    CamelliaSubkeyL(2) = subl(3);
+    CamelliaSubkeyR(2) = subr(3);
+    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
+    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
+    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
+    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
+    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
+    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
+    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
+    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
+    tl = subl(10) ^ (subr(10) & ~subr(8));
+    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(7) = subl(6) ^ tl;
+    CamelliaSubkeyR(7) = subr(6) ^ tr;
+    CamelliaSubkeyL(8) = subl(8);
+    CamelliaSubkeyR(8) = subr(8);
+    CamelliaSubkeyL(9) = subl(9);
+    CamelliaSubkeyR(9) = subr(9);
+    tl = subl(7) ^ (subr(7) & ~subr(9));
+    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(10) = tl ^ subl(11);
+    CamelliaSubkeyR(10) = tr ^ subr(11);
+    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
+    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
+    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
+    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
+    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
+    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
+    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
+    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
+    tl = subl(18) ^ (subr(18) & ~subr(16));
+    dw = tl & subl(16),        tr = subr(18) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(15) = subl(14) ^ tl;
+    CamelliaSubkeyR(15) = subr(14) ^ tr;
+    CamelliaSubkeyL(16) = subl(16);
+    CamelliaSubkeyR(16) = subr(16);
+    CamelliaSubkeyL(17) = subl(17);
+    CamelliaSubkeyR(17) = subr(17);
+    tl = subl(15) ^ (subr(15) & ~subr(17));
+    dw = tl & subl(17),        tr = subr(15) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(18) = tl ^ subl(19);
+    CamelliaSubkeyR(18) = tr ^ subr(19);
+    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
+    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
+    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
+    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
+    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
+    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
+    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
+    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
+    CamelliaSubkeyL(23) = subl(22);
+    CamelliaSubkeyR(23) = subr(22);
+    CamelliaSubkeyL(24) = subl(24) ^ subl(23);
+    CamelliaSubkeyR(24) = subr(24) ^ subr(23);
+
+    /* apply the inverse of the last half of P-function */
+    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
+    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
+    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
+    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
+    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
+    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
+    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
+    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
+    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
+    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
+    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
+    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
+    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
+    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
+    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
+    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
+    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
+    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
+
+    return;
+}
+
+void
+camellia_setup256(const unsigned char *key, u32 *subkey)
+{
+    u32 kll,klr,krl,krr;           /* left half of key */
+    u32 krll,krlr,krrl,krrr;       /* right half of key */
+    u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
+    u32 kw4l, kw4r, dw, tl, tr;
+    u32 subL[34];
+    u32 subR[34];
+
+    /**
+     *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
+     *  (|| is concatination)
+     */
+
+    kll  = GETU32(key     );
+    klr  = GETU32(key +  4);
+    krl  = GETU32(key +  8);
+    krr  = GETU32(key + 12);
+    krll = GETU32(key + 16);
+    krlr = GETU32(key + 20);
+    krrl = GETU32(key + 24);
+    krrr = GETU32(key + 28);
+
+    /* generate KL dependent subkeys */
+    subl(0) = kll; subr(0) = klr;
+    subl(1) = krl; subr(1) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+    subl(12) = kll; subr(12) = klr;
+    subl(13) = krl; subr(13) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(16) = kll; subr(16) = klr;
+    subl(17) = krl; subr(17) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+    subl(22) = kll; subr(22) = klr;
+    subl(23) = krl; subr(23) = krr;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+    subl(30) = kll; subr(30) = klr;
+    subl(31) = krl; subr(31) = krr;
+
+    /* generate KR dependent subkeys */
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+    subl(4) = krll; subr(4) = krlr;
+    subl(5) = krrl; subr(5) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+    subl(8) = krll; subr(8) = krlr;
+    subl(9) = krrl; subr(9) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(18) = krll; subr(18) = krlr;
+    subl(19) = krrl; subr(19) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+    subl(26) = krll; subr(26) = krlr;
+    subl(27) = krrl; subr(27) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+
+    /* generate KA */
+    kll = subl(0) ^ krll; klr = subr(0) ^ krlr;
+    krl = subl(1) ^ krrl; krr = subr(1) ^ krrr;
+    CAMELLIA_F(kll, klr,
+              CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+              w0, w1, il, ir, t0, t1);
+    krl ^= w0; krr ^= w1;
+    CAMELLIA_F(krl, krr,
+              CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+              kll, klr, il, ir, t0, t1);
+    kll ^= krll; klr ^= krlr;
+    CAMELLIA_F(kll, klr,
+              CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+              krl, krr, il, ir, t0, t1);
+    krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
+    CAMELLIA_F(krl, krr,
+              CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+              w0, w1, il, ir, t0, t1);
+    kll ^= w0; klr ^= w1;
+
+    /* generate KB */
+    krll ^= kll; krlr ^= klr;
+    krrl ^= krl; krrr ^= krr;
+    CAMELLIA_F(krll, krlr,
+              CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
+              w0, w1, il, ir, t0, t1);
+    krrl ^= w0; krrr ^= w1;
+    CAMELLIA_F(krrl, krrr,
+              CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
+              w0, w1, il, ir, t0, t1);
+    krll ^= w0; krlr ^= w1;
+
+    /* generate KA dependent subkeys */
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+    subl(6) = kll; subr(6) = klr;
+    subl(7) = krl; subr(7) = krr;
+    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+    subl(14) = kll; subr(14) = klr;
+    subl(15) = krl; subr(15) = krr;
+    subl(24) = klr; subr(24) = krl;
+    subl(25) = krr; subr(25) = kll;
+    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+    subl(28) = kll; subr(28) = klr;
+    subl(29) = krl; subr(29) = krr;
+
+    /* generate KB dependent subkeys */
+    subl(2) = krll; subr(2) = krlr;
+    subl(3) = krrl; subr(3) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(10) = krll; subr(10) = krlr;
+    subl(11) = krrl; subr(11) = krrr;
+    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+    subl(20) = krll; subr(20) = krlr;
+    subl(21) = krrl; subr(21) = krrr;
+    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+    subl(32) = krll; subr(32) = krlr;
+    subl(33) = krrl; subr(33) = krrr;
+
+    /* absorb kw2 to other subkeys */
+    subl(3) ^= subl(1); subr(3) ^= subr(1);
+    subl(5) ^= subl(1); subr(5) ^= subr(1);
+    subl(7) ^= subl(1); subr(7) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(9);
+    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(11) ^= subl(1); subr(11) ^= subr(1);
+    subl(13) ^= subl(1); subr(13) ^= subr(1);
+    subl(15) ^= subl(1); subr(15) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(17);
+    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(19) ^= subl(1); subr(19) ^= subr(1);
+    subl(21) ^= subl(1); subr(21) ^= subr(1);
+    subl(23) ^= subl(1); subr(23) ^= subr(1);
+    subl(1) ^= subr(1) & ~subr(25);
+    dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw);
+    subl(27) ^= subl(1); subr(27) ^= subr(1);
+    subl(29) ^= subl(1); subr(29) ^= subr(1);
+    subl(31) ^= subl(1); subr(31) ^= subr(1);
+    subl(32) ^= subl(1); subr(32) ^= subr(1);
+
+    /* absorb kw4 to other subkeys */
+    kw4l = subl(33); kw4r = subr(33);
+    subl(30) ^= kw4l; subr(30) ^= kw4r;
+    subl(28) ^= kw4l; subr(28) ^= kw4r;
+    subl(26) ^= kw4l; subr(26) ^= kw4r;
+    kw4l ^= kw4r & ~subr(24);
+    dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw);
+    subl(22) ^= kw4l; subr(22) ^= kw4r;
+    subl(20) ^= kw4l; subr(20) ^= kw4r;
+    subl(18) ^= kw4l; subr(18) ^= kw4r;
+    kw4l ^= kw4r & ~subr(16);
+    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
+    subl(14) ^= kw4l; subr(14) ^= kw4r;
+    subl(12) ^= kw4l; subr(12) ^= kw4r;
+    subl(10) ^= kw4l; subr(10) ^= kw4r;
+    kw4l ^= kw4r & ~subr(8);
+    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
+    subl(6) ^= kw4l; subr(6) ^= kw4r;
+    subl(4) ^= kw4l; subr(4) ^= kw4r;
+    subl(2) ^= kw4l; subr(2) ^= kw4r;
+    subl(0) ^= kw4l; subr(0) ^= kw4r;
+
+    /* key XOR is end of F-function */
+    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
+    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
+    CamelliaSubkeyL(2) = subl(3);
+    CamelliaSubkeyR(2) = subr(3);
+    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
+    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
+    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
+    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
+    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
+    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
+    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
+    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
+    tl = subl(10) ^ (subr(10) & ~subr(8));
+    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(7) = subl(6) ^ tl;
+    CamelliaSubkeyR(7) = subr(6) ^ tr;
+    CamelliaSubkeyL(8) = subl(8);
+    CamelliaSubkeyR(8) = subr(8);
+    CamelliaSubkeyL(9) = subl(9);
+    CamelliaSubkeyR(9) = subr(9);
+    tl = subl(7) ^ (subr(7) & ~subr(9));
+    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(10) = tl ^ subl(11);
+    CamelliaSubkeyR(10) = tr ^ subr(11);
+    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
+    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
+    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
+    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
+    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
+    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
+    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
+    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
+    tl = subl(18) ^ (subr(18) & ~subr(16));
+    dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(15) = subl(14) ^ tl;
+    CamelliaSubkeyR(15) = subr(14) ^ tr;
+    CamelliaSubkeyL(16) = subl(16);
+    CamelliaSubkeyR(16) = subr(16);
+    CamelliaSubkeyL(17) = subl(17);
+    CamelliaSubkeyR(17) = subr(17);
+    tl = subl(15) ^ (subr(15) & ~subr(17));
+    dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(18) = tl ^ subl(19);
+    CamelliaSubkeyR(18) = tr ^ subr(19);
+    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
+    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
+    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
+    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
+    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
+    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
+    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
+    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
+    tl = subl(26) ^ (subr(26) & ~subr(24));
+    dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(23) = subl(22) ^ tl;
+    CamelliaSubkeyR(23) = subr(22) ^ tr;
+    CamelliaSubkeyL(24) = subl(24);
+    CamelliaSubkeyR(24) = subr(24);
+    CamelliaSubkeyL(25) = subl(25);
+    CamelliaSubkeyR(25) = subr(25);
+    tl = subl(23) ^ (subr(23) &  ~subr(25));
+    dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw);
+    CamelliaSubkeyL(26) = tl ^ subl(27);
+    CamelliaSubkeyR(26) = tr ^ subr(27);
+    CamelliaSubkeyL(27) = subl(26) ^ subl(28);
+    CamelliaSubkeyR(27) = subr(26) ^ subr(28);
+    CamelliaSubkeyL(28) = subl(27) ^ subl(29);
+    CamelliaSubkeyR(28) = subr(27) ^ subr(29);
+    CamelliaSubkeyL(29) = subl(28) ^ subl(30);
+    CamelliaSubkeyR(29) = subr(28) ^ subr(30);
+    CamelliaSubkeyL(30) = subl(29) ^ subl(31);
+    CamelliaSubkeyR(30) = subr(29) ^ subr(31);
+    CamelliaSubkeyL(31) = subl(30);
+    CamelliaSubkeyR(31) = subr(30);
+    CamelliaSubkeyL(32) = subl(32) ^ subl(31);
+    CamelliaSubkeyR(32) = subr(32) ^ subr(31);
+
+    /* apply the inverse of the last half of P-function */
+    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
+    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
+    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
+    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
+    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
+    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
+    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
+    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
+    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
+    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
+    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
+    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
+    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
+    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
+    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
+    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
+    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
+    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
+    dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw;
+    dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw;
+    dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw;
+    dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw;
+    dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw;
+    dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw);
+    CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw;
+    
+    return;
+}
+
+void
+camellia_setup192(const unsigned char *key, u32 *subkey)
+{
+    unsigned char kk[32];
+    u32 krll, krlr, krrl,krrr;
+
+    memcpy(kk, key, 24);
+    memcpy((unsigned char *)&krll, key+16,4);
+    memcpy((unsigned char *)&krlr, key+20,4);
+    krrl = ~krll;
+    krrr = ~krlr;
+    memcpy(kk+24, (unsigned char *)&krrl, 4);
+    memcpy(kk+28, (unsigned char *)&krrr, 4);
+    camellia_setup256(kk, subkey);
+    return;
+}
+
+
+/**
+ * Stuff related to camellia encryption/decryption
+ *
+ * "io" must be 4byte aligned and big-endian data.
+ */
+void
+camellia_encrypt128(const u32 *subkey, u32 *io)
+{
+    u32 il, ir, t0, t1;
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(0);
+    io[1] ^= CamelliaSubkeyR(0);
+    /* main iteration */
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+                CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+                CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+                    io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(24);
+    io[3] ^= CamelliaSubkeyR(24);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+       
+    return;
+}
+
+void
+camellia_decrypt128(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;               /* temporary valiables */
+    
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(24);
+    io[1] ^= CamelliaSubkeyR(24);
+
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+                CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+                CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+                    io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(0);
+    io[3] ^= CamelliaSubkeyR(0);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+/**
+ * stuff for 192 and 256bit encryption/decryption
+ */
+void
+camellia_encrypt256(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;           /* temporary valiables */
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(0);
+    io[1] ^= CamelliaSubkeyR(0);
+
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+                CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+                CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(24),CamelliaSubkeyR(24),
+                CamelliaSubkeyL(25),CamelliaSubkeyR(25),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(26),CamelliaSubkeyR(26),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(27),CamelliaSubkeyR(27),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(28),CamelliaSubkeyR(28),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(29),CamelliaSubkeyR(29),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(30),CamelliaSubkeyR(30),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(31),CamelliaSubkeyR(31),
+                    io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(32);
+    io[3] ^= CamelliaSubkeyR(32);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+void
+camellia_decrypt256(const u32 *subkey, u32 *io)
+{
+    u32 il,ir,t0,t1;           /* temporary valiables */
+
+    /* pre whitening but absorb kw2*/
+    io[0] ^= CamelliaSubkeyL(32);
+    io[1] ^= CamelliaSubkeyR(32);
+       
+    /* main iteration */
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(31),CamelliaSubkeyR(31),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(30),CamelliaSubkeyR(30),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(29),CamelliaSubkeyR(29),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(28),CamelliaSubkeyR(28),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(27),CamelliaSubkeyR(27),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(26),CamelliaSubkeyR(26),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(25),CamelliaSubkeyR(25),
+                CamelliaSubkeyL(24),CamelliaSubkeyR(24),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(23),CamelliaSubkeyR(23),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(22),CamelliaSubkeyR(22),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(21),CamelliaSubkeyR(21),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(20),CamelliaSubkeyR(20),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(19),CamelliaSubkeyR(19),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(18),CamelliaSubkeyR(18),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(17),CamelliaSubkeyR(17),
+                CamelliaSubkeyL(16),CamelliaSubkeyR(16),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(15),CamelliaSubkeyR(15),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(14),CamelliaSubkeyR(14),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(13),CamelliaSubkeyR(13),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(12),CamelliaSubkeyR(12),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(11),CamelliaSubkeyR(11),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(10),CamelliaSubkeyR(10),
+                    io[0],io[1],il,ir,t0,t1);
+
+    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+                CamelliaSubkeyL(9),CamelliaSubkeyR(9),
+                CamelliaSubkeyL(8),CamelliaSubkeyR(8),
+                t0,t1,il,ir);
+
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+                    io[0],io[1],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[0],io[1],
+                    CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+                    io[2],io[3],il,ir,t0,t1);
+    CAMELLIA_ROUNDSM(io[2],io[3],
+                    CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+                    io[0],io[1],il,ir,t0,t1);
+
+    /* post whitening but kw4 */
+    io[2] ^= CamelliaSubkeyL(0);
+    io[3] ^= CamelliaSubkeyR(0);
+
+    t0 = io[0];
+    t1 = io[1];
+    io[0] = io[2];
+    io[1] = io[3];
+    io[2] = t0;
+    io[3] = t1;
+
+    return;
+}
+
+/***
+ *
+ * API for compatibility
+ */
+
+void
+Camellia_Ekeygen(const int keyBitLength, 
+                const unsigned char *rawKey, 
+                KEY_TABLE_TYPE keyTable)
+{
+    switch(keyBitLength) {
+    case 128:
+       camellia_setup128(rawKey, keyTable);
+       break;
+    case 192:
+       camellia_setup192(rawKey, keyTable);
+       break;
+    case 256:
+       camellia_setup256(rawKey, keyTable);
+       break;
+    default:
+       break;
+    }
+}
+
+
+void
+Camellia_EncryptBlock(const int keyBitLength, 
+                     const unsigned char *plaintext, 
+                     const KEY_TABLE_TYPE keyTable, 
+                     unsigned char *ciphertext)
+{
+    u32 tmp[4];
+
+    tmp[0] = GETU32(plaintext);
+    tmp[1] = GETU32(plaintext + 4);
+    tmp[2] = GETU32(plaintext + 8);
+    tmp[3] = GETU32(plaintext + 12);
+
+    switch (keyBitLength) {
+    case 128:
+       camellia_encrypt128(keyTable, tmp);
+       break;
+    case 192:
+       /* fall through */
+    case 256:
+       camellia_encrypt256(keyTable, tmp);
+       break;
+    default:
+       break;
+    }
+
+    PUTU32(ciphertext, tmp[0]);
+    PUTU32(ciphertext + 4, tmp[1]);
+    PUTU32(ciphertext + 8, tmp[2]);
+    PUTU32(ciphertext + 12, tmp[3]);
+}
+
+void
+Camellia_DecryptBlock(const int keyBitLength, 
+                     const unsigned char *ciphertext, 
+                     const KEY_TABLE_TYPE keyTable, 
+                     unsigned char *plaintext)
+{
+    u32 tmp[4];
+
+    tmp[0] = GETU32(ciphertext);
+    tmp[1] = GETU32(ciphertext + 4);
+    tmp[2] = GETU32(ciphertext + 8);
+    tmp[3] = GETU32(ciphertext + 12);
+
+    switch (keyBitLength) {
+    case 128:
+       camellia_decrypt128(keyTable, tmp);
+       break;
+    case 192:
+       /* fall through */
+    case 256:
+       camellia_decrypt256(keyTable, tmp);
+       break;
+    default:
+       break;
+    }
+    PUTU32(plaintext, tmp[0]);
+    PUTU32(plaintext + 4, tmp[1]);
+    PUTU32(plaintext + 8, tmp[2]);
+    PUTU32(plaintext + 12, tmp[3]);
+}
+
+cam_rval
+camellia_blk_len(unsigned int blen, camellia_ctx cx[1]){
+    if(blen != 16) return camellia_bad;
+    return camellia_good;
+}
+
+cam_rval
+camellia_enc_key(const unsigned char in_key[], unsigned int klen,
+                camellia_ctx cx[1]){
+    switch(klen){
+    case 16:
+       camellia_setup128(in_key, cx->k_sch);
+       cx->keybitlen = 128;
+       break;
+    case 24:
+       camellia_setup192(in_key, cx->k_sch);
+       cx->keybitlen = 192;
+       break;
+    case 32:
+       camellia_setup256(in_key, cx->k_sch);
+       cx->keybitlen = 256;
+       break;
+    default:
+       return camellia_bad;
+    }
+    return camellia_good;
+}
+
+cam_rval
+camellia_enc_blk(const unsigned char in_blk[],  unsigned char out_blk[],
+                const camellia_ctx cx[1]){
+    Camellia_EncryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk);
+    return camellia_good;
+}
+
+cam_rval
+camellia_dec_key(const unsigned char in_key[],  unsigned int klen,
+                camellia_ctx cx[1]){
+    switch(klen){
+    case 16:
+       camellia_setup128(in_key, cx->k_sch);
+       cx->keybitlen = 128;
+       break;
+    case 24:
+       camellia_setup192(in_key, cx->k_sch);
+       cx->keybitlen = 192;
+       break;
+    case 32:
+       camellia_setup256(in_key, cx->k_sch);
+       cx->keybitlen = 256;
+       break;
+    default:
+       return camellia_bad;
+    }
+    return camellia_good;
+}
+
+cam_rval
+camellia_dec_blk(const unsigned char in_blk[],  unsigned char out_blk[],
+                const camellia_ctx cx[1]){
+    Camellia_DecryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk);
+    return camellia_good;
+}
diff --git a/src/lib/crypto/builtin/camellia/camellia.h b/src/lib/crypto/builtin/camellia/camellia.h
new file mode 100644 (file)
index 0000000..a2afc62
--- /dev/null
@@ -0,0 +1,113 @@
+/* camellia.h ver 1.2.0
+ *
+ * Copyright (c) 2006,2007,2009
+ * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer as
+ *   the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HEADER_CAMELLIA_H
+#define HEADER_CAMELLIA_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include "uitypes.h" /* ../aes/ui_types.h */
+
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+
+#ifndef BLOCK_SIZE
+#define BLOCK_SIZE CAMELLIA_BLOCK_SIZE
+#endif
+
+typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
+
+/* u32 must be 32bit word */
+typedef uint32_t u32;
+typedef uint8_t u8;
+
+void camellia_setup128(const unsigned char *key, u32 *subkey);
+void camellia_setup192(const unsigned char *key, u32 *subkey);
+void camellia_setup256(const unsigned char *key, u32 *subkey);
+void camellia_encrypt128(const u32 *subkey, u32 *io);
+void camellia_decrypt128(const u32 *subkey, u32 *io);
+void camellia_encrypt256(const u32 *subkey, u32 *io);
+void camellia_decrypt256(const u32 *subkey, u32 *io);
+
+void Camellia_Ekeygen(const int keyBitLength,
+                     const unsigned char *rawKey, 
+                     KEY_TABLE_TYPE keyTable);
+
+void Camellia_EncryptBlock(const int keyBitLength,
+                          const unsigned char *plaintext, 
+                          const KEY_TABLE_TYPE keyTable, 
+                          unsigned char *cipherText);
+
+void Camellia_DecryptBlock(const int keyBitLength, 
+                          const unsigned char *cipherText, 
+                          const KEY_TABLE_TYPE keyTable, 
+                          unsigned char *plaintext);
+
+
+typedef uint16_t    cam_fret;   /* type for function return value       */
+#define camellia_good 1
+#define camellia_bad 1
+#ifndef CAMELLIA_DLL                 /* implement normal or DLL functions    */
+#define cam_rval    cam_fret
+#else
+#define cam_rval    cam_fret __declspec(dllexport) _stdcall
+#endif
+
+typedef struct                      /* the Camellia context for encryption */
+{
+    uint32_t k_sch[CAMELLIA_TABLE_WORD_LEN]; /* the encryption key schedule */
+    int keybitlen;                     /* bitlength of key */
+} camellia_ctx;
+
+
+/* for Kerberos 5 tree -- hide names!  */
+#define camellia_blk_len       krb5int_camellia_blk_len
+#define camellia_enc_key       krb5int_camellia_enc_key
+#define camellia_enc_blk       krb5int_camellia_enc_blk
+#define camellia_dec_key       krb5int_camellia_dec_key
+#define camellia_dec_blk       krb5int_camellia_dec_blk
+
+cam_rval camellia_blk_len(unsigned int blen, camellia_ctx cx[1]);
+cam_rval camellia_enc_key(const unsigned char in_key[], unsigned int klen,
+                         camellia_ctx cx[1]);
+cam_rval camellia_enc_blk(const unsigned char in_blk[],
+                         unsigned char out_blk[],
+                         const camellia_ctx cx[1]);
+cam_rval camellia_dec_key(const unsigned char in_key[], unsigned int klen,
+                         camellia_ctx cx[1]);
+cam_rval camellia_dec_blk(const unsigned char in_blk[],
+                         unsigned char out_blk[],
+                         const camellia_ctx cx[1]);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* HEADER_CAMELLIA_H */
diff --git a/src/lib/crypto/builtin/camellia/deps b/src/lib/crypto/builtin/camellia/deps
new file mode 100644 (file)
index 0000000..4c8d393
--- /dev/null
@@ -0,0 +1,17 @@
+# 
+# Generated makefile dependencies follow.
+#
+camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h camellia.h camellia.c
+camellia_s2k.so camellia_s2k.po $(OUTPRE)camellia_s2k.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h camellia.h camellia_s2k.c camellia_s2k.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h \
+  $(srcdir)/../../krb/dk/dk.h
index 4052a4058317a2f5b0f56dc4a452284924ba7dfd..182f631e545a9833c676fa17c00ce965f3d200a1 100644 (file)
@@ -56,9 +56,8 @@ krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
     for (;;) {
         unsigned DES_INT32 temp;
 
-        ptr = iov_next_block(storage, MIT_DES_BLOCK_LENGTH, data, num_data,
-                             &input_pos);
-        if (ptr == NULL)
+        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
+                                            data, num_data, &input_pos, &ptr))
             break;
         block = ptr;
 
@@ -76,8 +75,9 @@ krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
         PUT_HALF_BLOCK(left, ptr);
         PUT_HALF_BLOCK(right, ptr);
 
-        iov_store_block(data, num_data, block, storage, MIT_DES_BLOCK_LENGTH,
-                        &output_pos);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
+                                       MIT_DES_BLOCK_LENGTH, &output_pos,
+                                       block);
     }
 
     if (ivec != NULL && block != NULL) {
@@ -123,9 +123,8 @@ krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
 
     /* Work the length down 8 bytes at a time. */
     for (;;) {
-        ptr = iov_next_block(storage, MIT_DES_BLOCK_LENGTH, data, num_data,
-                             &input_pos);
-        if (ptr == NULL)
+        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
+                                            data, num_data, &input_pos, &ptr))
             break;
         block = ptr;
 
@@ -151,8 +150,9 @@ krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
         ocipherl = cipherl;
         ocipherr = cipherr;
 
-        iov_store_block(data, num_data, block, storage, MIT_DES_BLOCK_LENGTH,
-                        &output_pos);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
+                                       MIT_DES_BLOCK_LENGTH, &output_pos,
+                                       block);
     }
 
     if (ivec != NULL && block != NULL) {
index bb3982d1b4022c2f7062e55eacbe6cb9d5512a44..34eee2cbde159488cb901afc45ac24735ee7d919 100644 (file)
@@ -54,9 +54,8 @@ krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
     for (;;) {
         unsigned DES_INT32 temp;
 
-        ptr = iov_next_block(storage, MIT_DES_BLOCK_LENGTH, data, num_data,
-                             &input_pos);
-        if (ptr == NULL)
+        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
+                                            data, num_data, &input_pos, &ptr))
             break;
         block = ptr;
 
@@ -66,14 +65,15 @@ krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data,
         GET_HALF_BLOCK(temp, ptr);
         right ^= temp;
 
-        /* Encrypt what we have and store back into block. */
+        /* Encrypt what we have and put back into block. */
         DES_DO_ENCRYPT(left, right, kp);
         ptr = block;
         PUT_HALF_BLOCK(left, ptr);
         PUT_HALF_BLOCK(right, ptr);
 
-        iov_store_block(data, num_data, block, storage, MIT_DES_BLOCK_LENGTH,
-                        &output_pos);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
+                                       MIT_DES_BLOCK_LENGTH, &output_pos,
+                                       block);
     }
 
     if (ivec != NULL && block != NULL) {
@@ -115,9 +115,8 @@ krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
 
     /* Work the length down 8 bytes at a time. */
     for (;;) {
-        ptr = iov_next_block(storage, MIT_DES_BLOCK_LENGTH, data, num_data,
-                             &input_pos);
-        if (ptr == NULL)
+        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
+                                            data, num_data, &input_pos, &ptr))
             break;
         block = ptr;
 
@@ -141,8 +140,9 @@ krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data,
         ocipherl = cipherl;
         ocipherr = cipherr;
 
-        iov_store_block(data, num_data, block, storage, MIT_DES_BLOCK_LENGTH,
-                        &output_pos);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
+                                       MIT_DES_BLOCK_LENGTH, &output_pos,
+                                       block);
     }
 
     if (ivec != NULL && block != NULL) {
@@ -178,9 +178,8 @@ krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data,
     for (;;) {
         unsigned DES_INT32 temp;
 
-        ptr = iov_next_block(storage, MIT_DES_BLOCK_LENGTH, data, num_data,
-                             &input_pos);
-        if (ptr == NULL)
+        if (!krb5int_c_iov_get_block_nocopy(storage, MIT_DES_BLOCK_LENGTH,
+                                            data, num_data, &input_pos, &ptr))
             break;
         block = ptr;
 
index 40e42ef6e6e5e66c928434d28d274df6b6a2d557..f3d4a0b2c354b2c8c70f85544ad83c9ceae864da 100644 (file)
@@ -3,6 +3,7 @@ BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
 LOCALINCLUDES = -I$(srcdir)/../des     \
                -I$(srcdir)/../arcfour \
                -I$(srcdir)/../aes      \
+               -I$(srcdir)/../camellia         \
                -I$(srcdir)/../../krb                   \
                -I$(srcdir)/../../krb/rand2key          \
                -I$(srcdir)/.. -I$(srcdir)/. 
@@ -19,18 +20,21 @@ STLIBOBJS= \
        des.o   \
        des3.o  \
        rc4.o   \
-       aes.o 
+       aes.o   \
+       camellia_ctr.o
 
 OBJS= \
        $(OUTPRE)des.$(OBJEXT)  \
        $(OUTPRE)des3.$(OBJEXT)         \
        $(OUTPRE)aes.$(OBJEXT)  \
+       $(OUTPRE)camellia_ctr.$(OBJEXT) \
        $(OUTPRE)rc4.$(OBJEXT)
 
 SRCS= \
        $(srcdir)/des.c         \
        $(srcdir)/des3.c        \
        $(srcdir)/aes.c         \
+       $(srcdir)/camellia_ctr.c\
        $(srcdir)/rc4.c
 
 ##DOS##LIBOBJS = $(OBJS)
index 9d2c5d4ffed6af65473801d1e8b64fa25e10c940..682a0ee22d5560456b7c4a774bd94152151b2006 100644 (file)
@@ -132,12 +132,12 @@ krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
         for (blockno = 0; blockno < nblocks - 2; blockno++) {
             unsigned char blockN[BLOCK_SIZE], *block;
 
-            block = iov_next_block(blockN, BLOCK_SIZE, data, num_data,
-                                   &input_pos);
+            krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
+                                           data, num_data, &input_pos, &block);
             xorblock(tmp, block);
             enc(block, tmp, &CACHE(key)->enc_ctx);
-            iov_store_block(data, num_data, block, blockN, BLOCK_SIZE,
-                            &output_pos);
+            krb5int_c_iov_put_block_nocopy(data, num_data, blockN, BLOCK_SIZE,
+                                           &output_pos, block);
 
             /* Set up for next block.  */
             memcpy(tmp, block, BLOCK_SIZE);
@@ -228,14 +228,14 @@ krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
         for (blockno = 0; blockno < nblocks - 2; blockno++) {
             unsigned char blockN[BLOCK_SIZE], *block;
 
-            block = iov_next_block(blockN, BLOCK_SIZE, data, num_data,
-                                   &input_pos);
+            krb5int_c_iov_get_block_nocopy(blockN, BLOCK_SIZE,
+                                           data, num_data, &input_pos, &block);
             memcpy(tmp2, block, BLOCK_SIZE);
             dec(block, block, &CACHE(key)->dec_ctx);
             xorblock(block, tmp);
             memcpy(tmp, tmp2, BLOCK_SIZE);
-            iov_store_block(data, num_data, block, blockN, BLOCK_SIZE,
-                            &output_pos);
+            krb5int_c_iov_put_block_nocopy(data, num_data, blockN, BLOCK_SIZE,
+                                           &output_pos, block);
         }
 
         /* Do last two blocks, the second of which (next-to-last block
diff --git a/src/lib/crypto/builtin/enc_provider/camellia_ctr.c b/src/lib/crypto/builtin/enc_provider/camellia_ctr.c
new file mode 100644 (file)
index 0000000..8171ab6
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * lib/crypto/builtin/enc_provider/camellia_ctr.c
+ *
+ * Copyright (C) 2003, 2007-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 "enc_provider.h"
+#include "camellia.h"
+#include <aead.h>
+#include <rand2key.h>
+
+#ifdef CAMELLIA_CCM
+
+static void
+xorblock(unsigned char *out, const unsigned char *in)
+{
+    int z;
+    for (z = 0; z < BLOCK_SIZE / 4; z++) {
+        unsigned char *outptr = &out[z * 4];
+        unsigned char *inptr = (unsigned char *)&in[z * 4];
+        /*
+         * Use unaligned accesses.  On x86, this will probably still be faster
+         * than multiple byte accesses for unaligned data, and for aligned data
+         * should be far better.  (One test indicated about 2.4% faster
+         * encryption for 1024-byte messages.)
+         *
+         * If some other CPU has really slow unaligned-word or byte accesses,
+         * perhaps this function (or the load/store helpers?) should test for
+         * alignment first.
+         *
+         * If byte accesses are faster than unaligned words, we may need to
+         * conditionalize on CPU type, as that may be hard to determine
+         * automatically.
+         */
+        store_32_n(load_32_n(outptr) ^ load_32_n(inptr), outptr);
+    }
+}
+
+/* Get the current counter block number from the IV */
+static inline void getctrblockno(krb5_ui_8 *pblockno,
+                                const unsigned char ctr[BLOCK_SIZE])
+{
+    *pblockno = load_64_be(&ctr[BLOCK_SIZE - 8]);
+}
+
+/* Store the current counter block number in the IV */
+static inline void putctrblockno(krb5_ui_8 blockno,
+                                unsigned char ctr[BLOCK_SIZE])
+{
+    store_64_be(blockno, &ctr[BLOCK_SIZE - 8]);
+}
+
+/*
+ * ivec must be a correctly formatted counter block per NIST SP800-38C A.3.
+ */
+static krb5_error_code
+krb5int_camellia_encrypt_ctr(krb5_key key, const krb5_data *ivec,
+                             krb5_crypto_iov *data, size_t num_data)
+{
+    camellia_ctx ctx;
+    unsigned char ctr[BLOCK_SIZE];
+    krb5_ui_8 blockno;
+    struct iov_block_state input_pos, output_pos;
+
+    if (camellia_enc_key(key->keyblock.contents,
+                         key->keyblock.length, &ctx) != camellia_good)
+        abort();
+
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    /* Don't encrypt the header (B0), and use zero instead of IOV padding. */
+    input_pos.ignore_header = output_pos.ignore_header = 1;
+    input_pos.pad_to_boundary = output_pos.pad_to_boundary = 1;
+
+    if (ivec == NULL)
+       return EINVAL;
+    if (ivec->length != BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    memcpy(ctr, ivec->data, BLOCK_SIZE);
+
+    getctrblockno(&blockno, ctr);
+
+    for (;;) {
+        unsigned char storage[BLOCK_SIZE], *block;
+        unsigned char ectr[BLOCK_SIZE];
+
+        if (!krb5int_c_iov_get_block_nocopy(storage, BLOCK_SIZE, data,
+                                           num_data, &input_pos, &block))
+            break;
+
+        if (camellia_enc_blk(ctr, ectr, &ctx) != camellia_good)
+            abort();
+
+        xorblock(block, ectr);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage, BLOCK_SIZE,
+                                       &output_pos, block);
+        putctrblockno(++blockno, ctr);
+    }
+
+    if (ivec != NULL)
+        memcpy(ivec->data, ctr, sizeof(ctr));
+
+    return 0;
+}
+
+krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *iv,
+                        krb5_data *output)
+{
+    camellia_ctx ctx;
+    unsigned char blockY[BLOCK_SIZE];
+    struct iov_block_state iov_state;
+
+    if (output->length < BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    if (camellia_enc_key(key->keyblock.contents,
+                         key->keyblock.length, &ctx) != camellia_good)
+        abort();
+
+    if (iv != NULL)
+        memcpy(blockY, iv->data, BLOCK_SIZE);
+    else
+        memset(blockY, 0, BLOCK_SIZE);
+
+    IOV_BLOCK_STATE_INIT(&iov_state);
+
+    /*
+     * The CCM header may not fit in a block, because it includes a variable
+     * length encoding of the associated data length.  This encoding plus the
+     * associated data itself is padded to the block size.
+     */
+    iov_state.include_sign_only = 1;
+    iov_state.pad_to_boundary = 1;
+
+    for (;;) {
+        unsigned char blockB[BLOCK_SIZE];
+
+        if (!krb5int_c_iov_get_block(blockB, BLOCK_SIZE, data, num_data,
+                                    &iov_state))
+            break;
+
+        xorblock(blockB, blockY);
+
+        if (camellia_enc_blk(blockB, blockY, &ctx) != camellia_good)
+            abort();
+    }
+
+    output->length = BLOCK_SIZE;
+    memcpy(output->data, blockY, BLOCK_SIZE);
+
+    return 0;
+}
+
+static krb5_error_code
+krb5int_camellia_init_state_ctr(const krb5_keyblock *key, krb5_keyusage usage,
+                               krb5_data *state)
+{
+    return alloc_data(state, 16);
+}
+
+const struct krb5_enc_provider krb5int_enc_camellia128_ctr = {
+    16,
+    16, 16,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_make_key,
+    krb5int_camellia_init_state_ctr,
+    krb5int_default_free_state,
+    NULL
+};
+
+const struct krb5_enc_provider krb5int_enc_camellia256_ctr = {
+    16,
+    32, 32,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_make_key,
+    krb5int_camellia_init_state_ctr,
+    krb5int_default_free_state,
+    NULL
+};
+
+#else /* CAMELLIA_CCM */
+
+/* These won't be used, but is still in the export table. */
+
+krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *iv,
+                        krb5_data *output)
+{
+    return EINVAL;
+}
+
+const struct krb5_enc_provider krb5int_enc_camellia128_ctr = {
+};
+
+#endif /* CAMELLIA_CCM */
index 8144b6533e3351bed5b54d1226fd6ee21a65d621..39175d1b912ae5657ee973937a25e95769482e65 100644 (file)
@@ -32,5 +32,7 @@ extern const struct krb5_enc_provider krb5int_enc_des3;
 extern const struct krb5_enc_provider krb5int_enc_arcfour;
 extern const struct krb5_enc_provider krb5int_enc_aes128;
 extern const struct krb5_enc_provider krb5int_enc_aes256;
-extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
-extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
+#ifdef CAMELLIA_CCM
+extern const struct krb5_enc_provider krb5int_enc_camellia128_ctr;
+extern const struct krb5_enc_provider krb5int_enc_camellia256_ctr;
+#endif
index c92cc7e8d4bbfaebcfb88ebf6fe00607df6851d4..a0cbb1d1b848fa2d64e363fb4dcb4fb0b5e8d47f 100644 (file)
@@ -7,7 +7,8 @@ LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir)/../@CRYPTO_IMPL@/enc_provider            \
        -I$(srcdir)/../krb/crc32 -I$(srcdir)/../krb/old -I$(srcdir)/../krb/raw  \
        -I$(srcdir)/../@CRYPTO_IMPL@/aes -I$(srcdir)/../@CRYPTO_IMPL@/des       \
        -I$(srcdir)/../@CRYPTO_IMPL@/arcfour -I$(srcdir)/../@CRYPTO_IMPL@/sha1  \
-       -I$(srcdir)/../@CRYPTO_IMPL@/md5 -I$(srcdir)/../@CRYPTO_IMPL@/md4 
+       -I$(srcdir)/../@CRYPTO_IMPL@/md5 -I$(srcdir)/../@CRYPTO_IMPL@/md4 \
+       -I$(srcdir)/../@CRYPTO_IMPL@/camellia
 RUN_SETUP = @KRB5_RUN_ENV@
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
@@ -18,16 +19,19 @@ EXTRADEPSRCS=\
        $(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       \
        $(srcdir)/vectors.c     \
        $(srcdir)/aes-test.c    \
+       $(srcdir)/camellia-test.c       \
        $(srcdir)/t_cksum.c     \
        $(srcdir)/t_crc.c       \
        $(srcdir)/t_mddriver.c  \
        $(srcdir)/t_kperf.c     \
        $(srcdir)/t_short.c     \
+       $(srcdir)/t_str2key.c   \
        $(srcdir)/ytest.c       
 
 ##DOSBUILDTOP = ..\..\..
@@ -41,15 +45,17 @@ EXTRADEPSRCS=\
 # 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  \
                t_mddriver4 t_mddriver \
-               t_crc t_cts t_short
+               t_crc t_cts t_short t_str2key t_camellia_ccm
        $(RUN_SETUP) $(VALGRIND) ./t_nfold
        $(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
@@ -61,9 +67,14 @@ check-unix:: t_nfold t_encrypt t_prf t_prng t_hmac \
        cmp vk.txt $(srcdir)/expect-vk.txt
        $(RUN_SETUP) $(VALGRIND) ./aes-test > vt.txt
        cmp vt.txt $(srcdir)/expect-vt.txt
+       $(RUN_SETUP) $(VALGRIND) ./camellia-test > camellia-vt.txt
+# Enable this when Camellia-CCM becomes unconditional.
+#      cmp camellia-vt.txt $(srcdir)/camellia-expect-vt.txt
        $(RUN_SETUP) $(VALGRIND) $(C)t_mddriver4 -x
        $(RUN_SETUP) $(VALGRIND) $(C)t_mddriver -x
        $(RUN_SETUP) $(VALGRIND) ./t_short
+       $(RUN_SETUP) $(VALGRIND) ./t_str2key
+       $(RUN_SETUP) $(VALGRIND) ./t_camellia_ccm
 
 
 
@@ -85,6 +96,9 @@ t_prf$(EXEEXT): t_prf.$(OBJEXT) $(SUPPORT_DEPLIB)
 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)
 
@@ -120,6 +134,9 @@ t_crc: t_crc.o $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB)
 aes-test: aes-test.$(OBJEXT) $(CRYPTO_DEPLIB)
        $(CC_LINK) -o aes-test aes-test.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
 
+camellia-test: camellia-test.$(OBJEXT) $(CRYPTO_DEPLIB)
+       $(CC_LINK) -o camellia-test camellia-test.$(OBJEXT) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB)
+
 t_mddriver4.o: $(srcdir)/t_mddriver.c
        $(CC) -DMD=4 $(ALL_CFLAGS) -o t_mddriver4.o -c $(srcdir)/t_mddriver.c
 
@@ -132,6 +149,12 @@ t_mddriver: t_mddriver.o  $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB)
 t_kperf: t_kperf.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB)
        $(CC_LINK) -o t_kperf t_kperf.o  $(SUPPORT_LIB) $(CRYPTO_DEPLIB)
 
+t_str2key$(EXEEXT): t_str2key.$(OBJEXT) $(SUPPORT_DEPLIB)
+       $(CC_LINK) -o $@ t_str2key.$(OBJEXT)  -lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB)
+
+t_camellia_ccm$(EXEEXT): t_camellia_ccm.$(OBJEXT) $(SUPPORT_DEPLIB)
+       $(CC_LINK) -o $@ t_camellia_ccm.$(OBJEXT)  -lkrb5 -lk5crypto -lcom_err $(SUPPORT_LIB)
+
 ytest: ytest.o shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB)
        $(CC_LINK) -o ytest ytest.o  $(SUPPORT_LIB)  $(CRYPTO_DEPLIB)
 
@@ -139,14 +162,15 @@ ytest: ytest.o shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB)
 
 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 \
                t_mddriver4.o t_mddriver4 t_mddriver.o t_mddriver \
                t_cksum4 t_cksum4.o t_cksum5 t_cksum5.o \
-               t_kperf.o t_kperf t_short t_short.o \
+               t_kperf.o t_kperf t_short t_short.o t_str2key t_str2key.o \
+               t_camellia_ccm t_camellia_ccm.o \
                t_mddriver$(EXEEXT) $(OUTPRE)t_mddriver.$(OBJEXT)
 
        -$(RM) t_prng.output
diff --git a/src/lib/crypto/crypto_tests/camellia-expect-vt.txt b/src/lib/crypto/crypto_tests/camellia-expect-vt.txt
new file mode 100644 (file)
index 0000000..e6ebe8a
--- /dev/null
@@ -0,0 +1,1036 @@
+
+KEYSIZE=128
+
+KEY=00000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=07923A39EB0A817D1C4D87BDB82D1F1C
+
+I=2
+PT=40000000000000000000000000000000
+CT=48CD6419809672D2349260D89A08D3D3
+
+I=3
+PT=20000000000000000000000000000000
+CT=D07493CCB2E95CE0B4945A05ACC97D82
+
+I=4
+PT=10000000000000000000000000000000
+CT=5DBE1EAC9F7080A88DBED7F6DA101448
+
+I=5
+PT=08000000000000000000000000000000
+CT=F01EE477D199DF2701027034B229622F
+
+I=6
+PT=04000000000000000000000000000000
+CT=C841587ABD9A912E563774CB569D051E
+
+I=7
+PT=02000000000000000000000000000000
+CT=1D9BC0C04546F0915C8CCD11391A455C
+
+I=8
+PT=01000000000000000000000000000000
+CT=05E6EBB4BA167F5C479CEFF3152F943B
+
+I=9
+PT=00800000000000000000000000000000
+CT=93211E0F788845B9FC0E4551FFE92AC9
+
+I=10
+PT=00400000000000000000000000000000
+CT=B6D35701CD8FADDE383BBE8E6B70BAF7
+
+I=11
+PT=00200000000000000000000000000000
+CT=8358F9F4EBCFEE348CB30551ACB151A0
+
+I=12
+PT=00100000000000000000000000000000
+CT=D57516EB5AD93C523E40521BF447AFCE
+
+I=13
+PT=00080000000000000000000000000000
+CT=66B2534C279C439133F52E5AD8B439A9
+
+I=14
+PT=00040000000000000000000000000000
+CT=A71C69184A9F63C2992A5F18F77C1FE9
+
+I=15
+PT=00020000000000000000000000000000
+CT=1ADCBE49AEACB9ECEBBD492B10E82C7B
+
+I=16
+PT=00010000000000000000000000000000
+CT=27E3BCFB227C5561DB6CF7FC30387036
+
+I=17
+PT=00008000000000000000000000000000
+CT=F4AE20365CC9D06B0CAE6B695ED2CEC1
+
+I=18
+PT=00004000000000000000000000000000
+CT=3DD682F0B641ED32AD3D43EA2A0456E4
+
+I=19
+PT=00002000000000000000000000000000
+CT=6E5D14A95ECC290B509EA6B673652E3A
+
+I=20
+PT=00001000000000000000000000000000
+CT=F1CDF0F8D7B3FFD95422D7CC0CF40B7B
+
+I=21
+PT=00000800000000000000000000000000
+CT=A9253D459A34C385A1F1B2CFFA3935C5
+
+I=22
+PT=00000400000000000000000000000000
+CT=291024D99FF09A47A1DEE45BA700AE52
+
+I=23
+PT=00000200000000000000000000000000
+CT=49241D9459B277187BB10081C60361C0
+
+I=24
+PT=00000100000000000000000000000000
+CT=AD9BA365CC4DD5553D2D9FE303841D88
+
+I=25
+PT=00000080000000000000000000000000
+CT=C2ECA616664A249DC622CC11196B4AE1
+
+I=26
+PT=00000040000000000000000000000000
+CT=6E1A2D4794BB0DC08777A0BC7523E70E
+
+I=27
+PT=00000020000000000000000000000000
+CT=6DB1F0CF59656BDD235E82B8CEF0BE8E
+
+I=28
+PT=00000010000000000000000000000000
+CT=52F239C5EAF401EBDC54D2F011FF4B6A
+
+I=29
+PT=00000008000000000000000000000000
+CT=6B58A08F648414B67FD6847D2AA51CBF
+
+I=30
+PT=00000004000000000000000000000000
+CT=2959DD5367885A75EB48053CF3251A36
+
+I=31
+PT=00000002000000000000000000000000
+CT=630B292E3B88EF641CDFD531E206605E
+
+I=32
+PT=00000001000000000000000000000000
+CT=4BBB88EF82B70593FCC56AFD91540FDB
+
+I=33
+PT=00000000800000000000000000000000
+CT=0A13055B118A45C606999257BD191426
+
+I=34
+PT=00000000400000000000000000000000
+CT=5CF8E5C9F15D7E4F865020224853EB77
+
+I=35
+PT=00000000200000000000000000000000
+CT=3898805042C7A4315C5EE51AF2DE47E2
+
+I=36
+PT=00000000100000000000000000000000
+CT=8D3F96372E87CBB0B375425B3A10B9E7
+
+I=37
+PT=00000000080000000000000000000000
+CT=4D9510A378BD784A70A66BCC75B7D3C8
+
+I=38
+PT=00000000040000000000000000000000
+CT=70DB1902D37CFBDFB98F7C516F79D416
+
+I=39
+PT=00000000020000000000000000000000
+CT=383C6C2AABEF7FDE25CD470BF774A331
+
+I=40
+PT=00000000010000000000000000000000
+CT=47CBCB5288349B1A15DC9F81FBEE6B8F
+
+I=41
+PT=00000000008000000000000000000000
+CT=21DA34D4468EEB13AED95DAE0FF48310
+
+I=42
+PT=00000000004000000000000000000000
+CT=021C9A8E6BD36FBD036411E5D852A80F
+
+I=43
+PT=00000000002000000000000000000000
+CT=6A459E2F839AF60ACDE83774D0BB5574
+
+I=44
+PT=00000000001000000000000000000000
+CT=C19255121F1B933CAE09E58AEC0E9977
+
+I=45
+PT=00000000000800000000000000000000
+CT=7BA949E27B2BE148A6B801F9305F43D5
+
+I=46
+PT=00000000000400000000000000000000
+CT=E8CEB1026BCF7BCEA32E8A380EA76DB7
+
+I=47
+PT=00000000000200000000000000000000
+CT=63F97747ED56A8F521B20CC65F6F9465
+
+I=48
+PT=00000000000100000000000000000000
+CT=2091CFDC629819106188424AC694F75B
+
+I=49
+PT=00000000000080000000000000000000
+CT=A91BDF8E8B88407942423CCE000527C4
+
+I=50
+PT=00000000000040000000000000000000
+CT=73F9B44B9635A3FD683DBF8D49E9825B
+
+I=51
+PT=00000000000020000000000000000000
+CT=9DC64B2133FAD5069FD9A7CC2FFFD1CC
+
+I=52
+PT=00000000000010000000000000000000
+CT=28240F81FEC36B71E13F1FEA7A7641E3
+
+I=53
+PT=00000000000008000000000000000000
+CT=20DD39FEE96CD2EFF972872A692B28FD
+
+I=54
+PT=00000000000004000000000000000000
+CT=47A9E40483EC1925B635E47E964E8E93
+
+I=55
+PT=00000000000002000000000000000000
+CT=9C0EBD822C49FB3D853DF5B315A87BA0
+
+I=56
+PT=00000000000001000000000000000000
+CT=C18D813FDB45A594C6DC24E5A1F6CE32
+
+I=57
+PT=00000000000000800000000000000000
+CT=7E5467FF245ECF80CB55C2D8E91F0711
+
+I=58
+PT=00000000000000400000000000000000
+CT=394D4365B77954FDEA4145FCF7A7A041
+
+I=59
+PT=00000000000000200000000000000000
+CT=B1D8311A492ED11F11E57B29221610C4
+
+I=60
+PT=00000000000000100000000000000000
+CT=E5FBB947A63AEA90163AF04AD6951EF8
+
+I=61
+PT=00000000000000080000000000000000
+CT=CA0627DDF580F0E7D59562825C9D0492
+
+I=62
+PT=00000000000000040000000000000000
+CT=EF98FFD1AED295AAE1860F0274C8F555
+
+I=63
+PT=00000000000000020000000000000000
+CT=8C698E5CFFF08FACE10C2DC5FF1E2A81
+
+I=64
+PT=00000000000000010000000000000000
+CT=35A7767E02032C35B5CE1A6F49C57C28
+
+I=65
+PT=00000000000000008000000000000000
+CT=AB36F8734E76EBA306CF00D6763D90B0
+
+I=66
+PT=00000000000000004000000000000000
+CT=E854EB66D4EC66889B5E6CD4F44A5806
+
+I=67
+PT=00000000000000002000000000000000
+CT=15B66DF1455ACD640B8716BCF5DB2D69
+
+I=68
+PT=00000000000000001000000000000000
+CT=4C57AB5333E5C2D4B7E30A007E449F48
+
+I=69
+PT=00000000000000000800000000000000
+CT=BA3E7FF28EB38EA09D8DB1440A9A3552
+
+I=70
+PT=00000000000000000400000000000000
+CT=64E60227AFD80C40C70186CC94804C1A
+
+I=71
+PT=00000000000000000200000000000000
+CT=CEB4423C20B4C91C2551F6FC227C9514
+
+I=72
+PT=00000000000000000100000000000000
+CT=F736894B843EF32DA28576DE500D448C
+
+I=73
+PT=00000000000000000080000000000000
+CT=58FDA98B678D15053D4B6C060368108C
+
+I=74
+PT=00000000000000000040000000000000
+CT=E28CAE384E578F47657755EBCD97996C
+
+I=75
+PT=00000000000000000020000000000000
+CT=0A64617BD4B5B166668240D105B7B6A2
+
+I=76
+PT=00000000000000000010000000000000
+CT=4BD090C7E3D365B5EA80F19B4798881E
+
+I=77
+PT=00000000000000000008000000000000
+CT=BC7B6CB9BFF4F72973BB2CD20A512C06
+
+I=78
+PT=00000000000000000004000000000000
+CT=4C7ADDC5C867594E9EE75F0AA6AB9C23
+
+I=79
+PT=00000000000000000002000000000000
+CT=1FBD05C71A36691AC6566A5298101D53
+
+I=80
+PT=00000000000000000001000000000000
+CT=42D7D6B1F499D412F8793972BD968DA2
+
+I=81
+PT=00000000000000000000800000000000
+CT=260EC86E2786FC68824576B934F32814
+
+I=82
+PT=00000000000000000000400000000000
+CT=576C26DFD7046F9357F34BEA7DFB26A0
+
+I=83
+PT=00000000000000000000200000000000
+CT=6D55E54BFB6F927174A02294C95E0F8F
+
+I=84
+PT=00000000000000000000100000000000
+CT=1A6CE91DD458229C7675A34950D10E23
+
+I=85
+PT=00000000000000000000080000000000
+CT=DAD0D5E7E000652825AA34D228EA8D8F
+
+I=86
+PT=00000000000000000000040000000000
+CT=E68013F48D75EAD2BBC0B0BDA5E690BF
+
+I=87
+PT=00000000000000000000020000000000
+CT=A07D92312FBAE37BFE8A834210AE4F9C
+
+I=88
+PT=00000000000000000000010000000000
+CT=6EEE5F8544CD7D456366EB448813989A
+
+I=89
+PT=00000000000000000000008000000000
+CT=F8E5C7FF4B79D7ABE8BFA2DD148820A8
+
+I=90
+PT=00000000000000000000004000000000
+CT=C6349D75C7472BBD66F95B3A07C79C91
+
+I=91
+PT=00000000000000000000002000000000
+CT=B85713C12D8658951CD1AD21C74D2CD2
+
+I=92
+PT=00000000000000000000001000000000
+CT=907AA00B9F7D47A97623FB55BA911F29
+
+I=93
+PT=00000000000000000000000800000000
+CT=DC3CD0ED23D11776FAB43A2A6A8F3557
+
+I=94
+PT=00000000000000000000000400000000
+CT=4BFE58A8FD69179C14765B09AB70B705
+
+I=95
+PT=00000000000000000000000200000000
+CT=A23996E0EA67EC280356E5F77130A551
+
+I=96
+PT=00000000000000000000000100000000
+CT=CDEADE859B3AACD273CCA85A3E2E45F2
+
+I=97
+PT=00000000000000000000000080000000
+CT=E0FC78489857D84DA03F40CE97147174
+
+I=98
+PT=00000000000000000000000040000000
+CT=7615EA6351F6BB12855E8579C6995D8E
+
+I=99
+PT=00000000000000000000000020000000
+CT=13E184344FE28C2E70ED0E4D0A8037F9
+
+I=100
+PT=00000000000000000000000010000000
+CT=A5FE395F568482B87BC3EB208C81C942
+
+I=101
+PT=00000000000000000000000008000000
+CT=B3103E11AF06C85565823F8CAA3159F6
+
+I=102
+PT=00000000000000000000000004000000
+CT=7EBC2234D271B89C519C396985300030
+
+I=103
+PT=00000000000000000000000002000000
+CT=0661D338F2E0C939BA1687820A768467
+
+I=104
+PT=00000000000000000000000001000000
+CT=EC2B42667C0195A90715499617884DA5
+
+I=105
+PT=00000000000000000000000000800000
+CT=AE077BA19D24E7188DDD3682FF196892
+
+I=106
+PT=00000000000000000000000000400000
+CT=98823C24B9C65A66073C7952DC2B4B5E
+
+I=107
+PT=00000000000000000000000000200000
+CT=6AB58432CBB3C2F503DA2D16796CC297
+
+I=108
+PT=00000000000000000000000000100000
+CT=EEB5EBB3A53E4196C2F22BC1A4DDF5E8
+
+I=109
+PT=00000000000000000000000000080000
+CT=33DC40AC5FDC126D38878416AF6C0FA6
+
+I=110
+PT=00000000000000000000000000040000
+CT=38EDDC08E18B4AD982CEA921D2765A9A
+
+I=111
+PT=00000000000000000000000000020000
+CT=7D6BEA038E9347C642E18631660A9558
+
+I=112
+PT=00000000000000000000000000010000
+CT=FDA57921A473B5EE3700AD5ADF035019
+
+I=113
+PT=00000000000000000000000000008000
+CT=699B4812E200337E9C1D2C397F0DFE4E
+
+I=114
+PT=00000000000000000000000000004000
+CT=7A1EADF68B0807145D6C414852DECFC8
+
+I=115
+PT=00000000000000000000000000002000
+CT=1645FFAA8AD76689C01DA8C40882781F
+
+I=116
+PT=00000000000000000000000000001000
+CT=BA0C053BE702FA62FC66D8FEB12FC97E
+
+I=117
+PT=00000000000000000000000000000800
+CT=841FD8AF69CF2C31F7D4D7B6959662B5
+
+I=118
+PT=00000000000000000000000000000400
+CT=F675D59BDB33231861268F539829DA0B
+
+I=119
+PT=00000000000000000000000000000200
+CT=A4967F45ABB4E8C7DC5E3806680F35E0
+
+I=120
+PT=00000000000000000000000000000100
+CT=4D7E08081CC82F92ABA7C58C99F8343F
+
+I=121
+PT=00000000000000000000000000000080
+CT=9AEFDB287C119B82353612B60ECCBFD8
+
+I=122
+PT=00000000000000000000000000000040
+CT=979BB6A1553A17592A86E78DF144A699
+
+I=123
+PT=00000000000000000000000000000020
+CT=A6FA8CAB06FD2E5BF3A858983C01757A
+
+I=124
+PT=00000000000000000000000000000010
+CT=BE8511254C31E25420B91D6FEF1710ED
+
+I=125
+PT=00000000000000000000000000000008
+CT=F589A908D18A21894971C0433581E1A5
+
+I=126
+PT=00000000000000000000000000000004
+CT=4237585130E7C9F715235EB1D8C94DE7
+
+I=127
+PT=00000000000000000000000000000002
+CT=DEFE3E0B5C54C94B4F2A0F5A46F6210D
+
+I=128
+PT=00000000000000000000000000000001
+CT=F5574ACC3148DFCB9015200631024DF9
+
+==========
+
+KEYSIZE=256
+
+KEY=0000000000000000000000000000000000000000000000000000000000000000
+
+I=1
+PT=80000000000000000000000000000000
+CT=B0C6B88AEA518AB09E847248E91B1B9D
+
+I=2
+PT=40000000000000000000000000000000
+CT=B8D7684E35FA1DB15BDCEE7A48659858
+
+I=3
+PT=20000000000000000000000000000000
+CT=F0CAD59AF92FBB79F36951E697492750
+
+I=4
+PT=10000000000000000000000000000000
+CT=117100F6635389560DC4A2DA24EBA70F
+
+I=5
+PT=08000000000000000000000000000000
+CT=DBDD62355553019ED84C35886421E532
+
+I=6
+PT=04000000000000000000000000000000
+CT=9CB8D04FA506F19848F7B9110518BFC8
+
+I=7
+PT=02000000000000000000000000000000
+CT=E4308E253BC3444D293500701BA82C6A
+
+I=8
+PT=01000000000000000000000000000000
+CT=EA2FAE53F7F30C0170A20E95A068503E
+
+I=9
+PT=00800000000000000000000000000000
+CT=14B14839EA221880B2C64D1FE000B93D
+
+I=10
+PT=00400000000000000000000000000000
+CT=A5CFC075B342D5101AACC334E73058BB
+
+I=11
+PT=00200000000000000000000000000000
+CT=477EA56B2EBAD0F8AC5E1936866560FF
+
+I=12
+PT=00100000000000000000000000000000
+CT=107E8598418404196EC59F63E45B7F6D
+
+I=13
+PT=00080000000000000000000000000000
+CT=FF6A891E7C1C074A68FEC291928FDD8D
+
+I=14
+PT=00040000000000000000000000000000
+CT=F64C250A13F45D377ADB7545B2B157A9
+
+I=15
+PT=00020000000000000000000000000000
+CT=FAD0F252086F11C830C65B63197CBC38
+
+I=16
+PT=00010000000000000000000000000000
+CT=9DCB89B209441F02AD0D25C6AB826629
+
+I=17
+PT=00008000000000000000000000000000
+CT=E62E4ED4E4F34EDC563710D960E09D4C
+
+I=18
+PT=00004000000000000000000000000000
+CT=98A1B926BA06895C3F2E84CCBACBC356
+
+I=19
+PT=00002000000000000000000000000000
+CT=29BE0BE4DB7F4D196718AEA38F3B0BFD
+
+I=20
+PT=00001000000000000000000000000000
+CT=F670C4EBECBA0B43E71F6D752BFD4854
+
+I=21
+PT=00000800000000000000000000000000
+CT=7D7666B4484CDB7E3605468E093A787C
+
+I=22
+PT=00000400000000000000000000000000
+CT=562D06B181C091DA6C43642AE99460C6
+
+I=23
+PT=00000200000000000000000000000000
+CT=AB0EFB5975E6186B7D76BC9672453488
+
+I=24
+PT=00000100000000000000000000000000
+CT=10C0756538E7BFF88D19AE2B1F7B859A
+
+I=25
+PT=00000080000000000000000000000000
+CT=AF7FCD5248F8C72F1695AA05DD1CADE0
+
+I=26
+PT=00000040000000000000000000000000
+CT=9841E555655609A75D7BE20B8A90EF1E
+
+I=27
+PT=00000020000000000000000000000000
+CT=27F9546E6A1B7464780000561783569C
+
+I=28
+PT=00000010000000000000000000000000
+CT=8671D935D7A8354EECB7288803D42D7A
+
+I=29
+PT=00000008000000000000000000000000
+CT=0DA44F508DEBC6F044394624FCEB8EBE
+
+I=30
+PT=00000004000000000000000000000000
+CT=AB137369BE6D93FBB18006BDB236EC09
+
+I=31
+PT=00000002000000000000000000000000
+CT=EB90C4E597A7E1779FFA260886E26F75
+
+I=32
+PT=00000001000000000000000000000000
+CT=618CF3588D5C128EAF252616230E08F7
+
+I=33
+PT=00000000800000000000000000000000
+CT=98DC4DB49D197AB9152D12B9DE2D73CA
+
+I=34
+PT=00000000400000000000000000000000
+CT=5BDDE24B15702A35E1F140C57D206443
+
+I=35
+PT=00000000200000000000000000000000
+CT=CF755809882BED8BA2F9F1A4ED296A2B
+
+I=36
+PT=00000000100000000000000000000000
+CT=F1A8DBB999538AE89D16F92A7F4D1DF1
+
+I=37
+PT=00000000080000000000000000000000
+CT=775222FDDAAECB81CF675C4E0B98179E
+
+I=38
+PT=00000000040000000000000000000000
+CT=12A648CADCD153C760A965826683119A
+
+I=39
+PT=00000000020000000000000000000000
+CT=0503FB10AB241E7CF45D8CDEEE474335
+
+I=40
+PT=00000000010000000000000000000000
+CT=3D299C0070CBBD831B802690B8E7CA24
+
+I=41
+PT=00000000008000000000000000000000
+CT=33105BD4D11D66753DC34D128BEFE3F4
+
+I=42
+PT=00000000004000000000000000000000
+CT=5EFCE2B4B987C0F77D27B44836881682
+
+I=43
+PT=00000000002000000000000000000000
+CT=7835449454128035D7F0EA99E327577B
+
+I=44
+PT=00000000001000000000000000000000
+CT=27BEDDA0601BE35122FB1D272D73AB3E
+
+I=45
+PT=00000000000800000000000000000000
+CT=54C3F99FF48E318CC515EDE75800C4B3
+
+I=46
+PT=00000000000400000000000000000000
+CT=C627C329F8E48299F6FDB23B9DBEA0BB
+
+I=47
+PT=00000000000200000000000000000000
+CT=1B6578F9E23BD8C1845A02431C5F9AA3
+
+I=48
+PT=00000000000100000000000000000000
+CT=6DB2FB8C0B9344D0547C0FF1292020C6
+
+I=49
+PT=00000000000080000000000000000000
+CT=4FAD9B2C37C131493FBEF53581FA4F83
+
+I=50
+PT=00000000000040000000000000000000
+CT=47502A01E93D2C87BD5584F6AFD3D99D
+
+I=51
+PT=00000000000020000000000000000000
+CT=056E1C6F651BFE50271B3B7A18E76D84
+
+I=52
+PT=00000000000010000000000000000000
+CT=5632BAF6627B3D96AD4E06FA6A561F55
+
+I=53
+PT=00000000000008000000000000000000
+CT=E29807CAACDFA2D41A7D9E91FA7FD8EB
+
+I=54
+PT=00000000000004000000000000000000
+CT=81DD44BB5D1822DEE605F9E6FF01D7B3
+
+I=55
+PT=00000000000002000000000000000000
+CT=5C3649925E47D7FF96482A8FBD9666FD
+
+I=56
+PT=00000000000001000000000000000000
+CT=695415A836E66E737887845EC08A1ADB
+
+I=57
+PT=00000000000000800000000000000000
+CT=F5416BCE292D9E2CEA5D1CC70BBAEED1
+
+I=58
+PT=00000000000000400000000000000000
+CT=7AEC4F1388FC29C47F7FED74ADDE8485
+
+I=59
+PT=00000000000000200000000000000000
+CT=82A9F1A6CE08BC4876E649D8A8EA7EB6
+
+I=60
+PT=00000000000000100000000000000000
+CT=B6296C88ADF1A792908B065EEB04BFC2
+
+I=61
+PT=00000000000000080000000000000000
+CT=E766A39AECCA40BDBFBE6FF3FA292913
+
+I=62
+PT=00000000000000040000000000000000
+CT=C6D081454EA00D83C23B5A62C84359E1
+
+I=63
+PT=00000000000000020000000000000000
+CT=85D259A79CCA80484504D1603F7A8F53
+
+I=64
+PT=00000000000000010000000000000000
+CT=D8291FA1C6DC250078824B2D0A20883F
+
+I=65
+PT=00000000000000008000000000000000
+CT=95387CB74C48FFBD1F8D64A6CC45E074
+
+I=66
+PT=00000000000000004000000000000000
+CT=A17F975F538F56CDF629B516011DE837
+
+I=67
+PT=00000000000000002000000000000000
+CT=B50B615A1654C6E1CB6AB33716C097FE
+
+I=68
+PT=00000000000000001000000000000000
+CT=7BBB2CBB874DF6C8B821DA7FB0F9011B
+
+I=69
+PT=00000000000000000800000000000000
+CT=E9EFE074D096A275E47CD2E6206DF6A1
+
+I=70
+PT=00000000000000000400000000000000
+CT=88F2F8D5A836406AE8BBB98C65BBDA55
+
+I=71
+PT=00000000000000000200000000000000
+CT=F64620D8D87585A3EF038B9AD58F5EA0
+
+I=72
+PT=00000000000000000100000000000000
+CT=694438EC141C8ED5F2F898B4554A298F
+
+I=73
+PT=00000000000000000080000000000000
+CT=3E6226EC7726A1EE5F5FA9B18CCE8C44
+
+I=74
+PT=00000000000000000040000000000000
+CT=8AB6949E79911647800B9E87362AB97A
+
+I=75
+PT=00000000000000000020000000000000
+CT=093C5CF24EDAF7F9F1C8A80DE4FF50A9
+
+I=76
+PT=00000000000000000010000000000000
+CT=28A36E50061F19E240351ED0E378CBF4
+
+I=77
+PT=00000000000000000008000000000000
+CT=B93BB36CB88BF26EA79198652AA51D3C
+
+I=78
+PT=00000000000000000004000000000000
+CT=DE4948083D044FAC9BCA6DA8CD67B8A6
+
+I=79
+PT=00000000000000000002000000000000
+CT=6E778B5BDA6CA118117E47470D080D3C
+
+I=80
+PT=00000000000000000001000000000000
+CT=0A9107324DA32B4281D032A3487EF875
+
+I=81
+PT=00000000000000000000800000000000
+CT=18ED5635312D71ABD123CCE779D4D68A
+
+I=82
+PT=00000000000000000000400000000000
+CT=2E3C63F95C4BC1F944BAB06DEDC9AA8E
+
+I=83
+PT=00000000000000000000200000000000
+CT=ACCC869EF07004C8C3C709083BE7BA2F
+
+I=84
+PT=00000000000000000000100000000000
+CT=DF60B34FB1A59147CC1FB049C1578206
+
+I=85
+PT=00000000000000000000080000000000
+CT=4228DC636C08E41021054AA0E1E2227A
+
+I=86
+PT=00000000000000000000040000000000
+CT=7CE27F66EFD735FFD6B3E1738C50495B
+
+I=87
+PT=00000000000000000000020000000000
+CT=F8E74B33A9CDE351DA0BBC06D69093D7
+
+I=88
+PT=00000000000000000000010000000000
+CT=AE0D22A5B37B8DC5D81CC641EED334D0
+
+I=89
+PT=00000000000000000000008000000000
+CT=C181C6CA5E163743458B9167A0B6A16A
+
+I=90
+PT=00000000000000000000004000000000
+CT=5171F4F6095E4B276CFBA1F07223FBE6
+
+I=91
+PT=00000000000000000000002000000000
+CT=2732F4D3A8C9D1D8D493840D6E0B864F
+
+I=92
+PT=00000000000000000000001000000000
+CT=3EF04E0059A061D973532CA5C1DFBE7B
+
+I=93
+PT=00000000000000000000000800000000
+CT=6D9A8F23579E4978EBAA87B5ADEB77E5
+
+I=94
+PT=00000000000000000000000400000000
+CT=BBD08873CC44BA4253C0C41FEEB7F124
+
+I=95
+PT=00000000000000000000000200000000
+CT=72E4B2437CBD283F3809CE686F6A591E
+
+I=96
+PT=00000000000000000000000100000000
+CT=6E5580514B92512B1BF4B1B987B9AA1B
+
+I=97
+PT=00000000000000000000000080000000
+CT=5EF5D0C5BCBDCB604D3A083B68CE0FA3
+
+I=98
+PT=00000000000000000000000040000000
+CT=9D991FDD723AD2182777A15CA0E0F665
+
+I=99
+PT=00000000000000000000000020000000
+CT=24440626EFC8F86BEA7DE78085AB8A22
+
+I=100
+PT=00000000000000000000000010000000
+CT=17C3630D62D13C1E826C0FCCBD74A864
+
+I=101
+PT=00000000000000000000000008000000
+CT=4CF5AB86A56AB134A7FE46CCE3F9FCE9
+
+I=102
+PT=00000000000000000000000004000000
+CT=3E6B9C0388F6D9B8F458F30221907607
+
+I=103
+PT=00000000000000000000000002000000
+CT=AD9C926B8A5CD98EEE88200617E59958
+
+I=104
+PT=00000000000000000000000001000000
+CT=AFF8AED5E075E02AF720CA4BF0028B3B
+
+I=105
+PT=00000000000000000000000000800000
+CT=D90EAFF909202BB209BB3BB8C7F9A954
+
+I=106
+PT=00000000000000000000000000400000
+CT=2C709B00E6A22F00F64A7D8EE341853F
+
+I=107
+PT=00000000000000000000000000200000
+CT=CCEC598F0D9F0BF201B2F487136D54A4
+
+I=108
+PT=00000000000000000000000000100000
+CT=73B2883A0A166AAE1BF14E60A5195FA3
+
+I=109
+PT=00000000000000000000000000080000
+CT=E676867BD9AD5EF915143388496779D7
+
+I=110
+PT=00000000000000000000000000040000
+CT=CDCB73D1BFCFD4BE7F1DAA9B1C6A4055
+
+I=111
+PT=00000000000000000000000000020000
+CT=02A3A5C89DAA24CD2C517F7A73286A89
+
+I=112
+PT=00000000000000000000000000010000
+CT=C0FA2AC9E92EE58C2DD12D6D43AB7035
+
+I=113
+PT=00000000000000000000000000008000
+CT=EDC2CB1F7291353BDBF2385519E6AE16
+
+I=114
+PT=00000000000000000000000000004000
+CT=B4B62D16D197A98CD3B978812B9D9884
+
+I=115
+PT=00000000000000000000000000002000
+CT=5CDFC95A529A905101CEA26BC1B891ED
+
+I=116
+PT=00000000000000000000000000001000
+CT=CC7150CD3650B98363296C7C4ED368D1
+
+I=117
+PT=00000000000000000000000000000800
+CT=CC57706B0C6526B8E25A5DBD32EACBDB
+
+I=118
+PT=00000000000000000000000000000400
+CT=30D30456AD98B182D64C649648F6AEC9
+
+I=119
+PT=00000000000000000000000000000200
+CT=D7E9DA7F631938EB649A08AF82FBD75F
+
+I=120
+PT=00000000000000000000000000000100
+CT=B8DA2AF6600B07895B5D0FFAF4991469
+
+I=121
+PT=00000000000000000000000000000080
+CT=0F6F64F930BA6C178943322B98114599
+
+I=122
+PT=00000000000000000000000000000040
+CT=8B1F247802E47C91BEE2AA34ECFD7A01
+
+I=123
+PT=00000000000000000000000000000020
+CT=7A6985778D3A66E97F23E01F0D0E45E7
+
+I=124
+PT=00000000000000000000000000000010
+CT=BA664AC39855518DFDEE10D1B3111FAE
+
+I=125
+PT=00000000000000000000000000000008
+CT=7C92854D801A1648F65CA81813DDBF83
+
+I=126
+PT=00000000000000000000000000000004
+CT=6A3F25AAB7E92D9CF378E5D9C040F26B
+
+I=127
+PT=00000000000000000000000000000002
+CT=3D4B2CDE666761BA5DFB305178E667FB
+
+I=128
+PT=00000000000000000000000000000001
+CT=9CDB269B5D293BC5DB9C55B057D9B591
+
+==========
diff --git a/src/lib/crypto/crypto_tests/camellia-test.c b/src/lib/crypto/crypto_tests/camellia-test.c
new file mode 100644 (file)
index 0000000..8ea8c46
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * lib/crypto/camellia/camellia-test.c
+ *
+ * Copyright (c) 2009
+ * NTT (Nippon Telegraph and Telephone Corporation) . 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.
+ * 
+ *
+ * Subset of NIST tests for AES as applied to Camellia; specifically, the
+ * variable-key and variable-text tests for 128- and 256-bit keys.
+ */
+
+#include <stdio.h>
+#include "k5-int.h"
+
+#ifdef CAMELLIA_CCM
+
+static char key[32];
+static char plain[16], cipher[16], zero[16];
+
+static krb5_keyblock enc_key;
+static krb5_data ivec;
+static void init()
+{
+    enc_key.contents = (unsigned char *)key;
+    enc_key.length = 16;
+    ivec.data = zero;
+    ivec.length = 16;
+}
+static void enc()
+{
+    krb5_key k;
+    krb5_crypto_iov iov;
+    krb5_data cdata = make_data(cipher, 16);
+
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = make_data(plain, 16);
+    krb5_k_create_key(NULL, &enc_key, &k);
+    /* cbc-mac is the same as block encryption for a single block. */
+    krb5int_camellia_cbc_mac(k, &iov, 1, &ivec, &cdata);
+    krb5_k_free_key(NULL, k);
+}
+
+static void hexdump(const char *label, const char *cp, int len)
+{
+    printf("%s=", label);
+    while (len--) printf("%02X", 0xff & *cp++);
+    printf("\n");
+}
+
+static void set_bit(char *ptr, int bitnum)
+{
+    int bytenum;
+    bytenum = bitnum / 8;
+    bitnum %= 8;
+    /* First bit is the high bit! */
+    ptr[bytenum] = 1 << (7 - bitnum);
+}
+
+/* Variable-Key tests */
+static void vk_test_1(int len)
+{
+    int i;
+
+    enc_key.length = len;
+    printf("\nKEYSIZE=%d\n\n", len * 8);
+    memset(plain, 0, sizeof(plain));
+    hexdump("PT", plain, 16);
+    for (i = 0; i < len * 8; i++) {
+       memset(key, 0, len);
+       set_bit(key, i);
+       printf("\nI=%d\n", i+1);
+       hexdump("KEY", key, len);
+       enc();
+       hexdump("CT", cipher, 16);
+    }
+    printf("\n==========\n");
+}
+static void vk_test()
+{
+    vk_test_1(16);
+    vk_test_1(32);
+}
+
+/* Variable-Text tests */
+static void vt_test_1(int len)
+{
+    int i;
+
+    enc_key.length = len;
+    printf("\nKEYSIZE=%d\n\n", len * 8);
+    memset(key, 0, len);
+    hexdump("KEY", key, len);
+    for (i = 0; i < 16 * 8; i++) {
+       memset(plain, 0, sizeof(plain));
+       set_bit(plain, i);
+       printf("\nI=%d\n", i+1);
+       hexdump("PT", plain, 16);
+       enc();
+       hexdump("CT", cipher, 16);
+    }
+    printf("\n==========\n");
+}
+static void vt_test()
+{
+    vt_test_1(16);
+    vt_test_1(32);
+}
+
+#endif /* CAMELLIA_CCM */
+
+int main (int argc, char *argv[])
+{
+#ifdef CAMELLIA_CCM
+    if (argc > 2 || (argc == 2 && strcmp(argv[1], "-k"))) {
+       fprintf(stderr,
+               "usage:\t%s -k\tfor variable-key tests\n"
+               "   or:\t%s   \tfor variable-plaintext tests\n",
+               argv[0], argv[0]);
+       return 1;
+    }
+    init();
+    if (argc == 2)
+       vk_test();
+    else
+       vt_test();
+#endif /* CAMELLIA_CCM */
+    return 0;
+}
diff --git a/src/lib/crypto/crypto_tests/t_camellia_ccm.c b/src/lib/crypto/crypto_tests/t_camellia_ccm.c
new file mode 100644 (file)
index 0000000..e3827ec
--- /dev/null
@@ -0,0 +1,273 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/crypto_tests/t_camellia_ccm.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.
+ *
+ *
+ * Test vectors for camellia-ccm enctypes.
+ *
+ * Currently we have no way of controlling the random generated during
+ * encryption.  This test program can be used to generate test vectors with
+ * random nonces, and to verify existing test vectors via decryption.
+ *
+ * Usage:
+ *   ./t_camellia_ccm -ge <usage> <text> <additional>
+ *   ./t_camellia_ccm -gc <usage> <text>
+ *   ./t_camellia_ccm
+ */
+
+#include "k5-int.h"
+
+#ifdef CAMELLIA_CCM
+
+static krb5_keyblock key_128 = {
+    KV5M_KEYBLOCK,
+    ENCTYPE_CAMELLIA128_CCM_128,
+    16, (unsigned char *)
+    "\xF0\x10\x02\xD2\xB1\xF9\xA1\xAD\xE2\x57\xEE\xF7\x52\x9C\x2A\x16"
+};
+
+static krb5_keyblock key_256 = {
+    KV5M_KEYBLOCK,
+    ENCTYPE_CAMELLIA256_CCM_128,
+    32, (unsigned char *)
+    "\xD7\xEF\x37\xE2\xD1\x05\x5E\xB7\xD7\x6B\x06\x39\x6E\xF7\x00\x52"
+    "\x3D\xA4\xB0\xB7\xA0\x53\xF5\xCC\x5F\xAE\x4A\x39\xCF\xC5\x75\x0F"
+};
+
+static struct enc_test {
+    krb5_keyusage usage;
+    char *input;
+    char *addl;
+    krb5_data cipher_128;
+    krb5_data cipher_256;
+} enc_tests[] = {
+    {
+        0, "", "",
+        { KV5M_DATA, 28,
+          "\x44\xE7\x08\x7D\xDF\x12\x8F\x02\x56\x10\xF5\x34"
+          "\xA1\x0C\x14\x58\x97\x38\xDD\x6B\x0D\x44\x12\x87\xAC\x2C\xC8\xD8" },
+        { KV5M_DATA, 28,
+          "\xE1\x8C\x74\x93\xA7\x15\x58\x11\x58\x6A\xB4\x0E"
+          "\x82\xC1\xFD\xB6\xA7\x05\x5B\x78\xD3\x1D\xE2\x34\xBA\xC3\xC0\x5A" }
+    },
+    {
+        1, "input", "additional",
+        { KV5M_DATA, 33,
+          "\x44\xE7\x08\x7D\xDF\x12\x8F\x02\x56\x10\xF5\x34"
+          "\x32\x69\x98\x26\xE4"
+          "\xE4\x4E\x85\x75\xA0\x37\x60\xDF\x0A\x96\xEC\x24\xB2\xBE\x4A\xA4" },
+        { KV5M_DATA, 33,
+          "\xE1\x8C\x74\x93\xA7\x15\x58\x11\x58\x6A\xB4\x0E"
+          "\x55\x9E\xB8\xB8\x22"
+          "\x7C\xD0\x38\x61\xC6\x81\x3C\x64\xB1\x72\xE3\x3D\x38\x36\x42\x72" }
+    },
+    {
+        100,
+        "this input spans multiple blocks",
+        "the additional data also spans multiple blocks",
+        { KV5M_DATA, 60,
+          "\x44\xE7\x08\x7D\xDF\x12\x8F\x02\x56\x10\xF5\x34"
+          "\x29\x1B\xAF\x6E\x2E\x31\xC6\xDD\xB2\xC9\xE1\xDD\xB4\x82\xAD\x5E"
+          "\x87\xE2\x9A\x65\xF5\x53\x28\x75\x84\x40\x96\x1B\x56\x02\xAD\x31"
+          "\xDD\x15\x22\x61\xB6\x10\xAD\x80\x42\x44\x32\x85\xFD\xFA\x82\x1A" },
+        { KV5M_DATA, 60,
+          "\xE1\x8C\x74\x93\xA7\x15\x58\x11\x58\x6A\xB4\x0E"
+          "\xD0\x9E\x5A\xFB\xFB\x56\x13\x5F\xB6\x29\x07\x0A\x54\x80\xAE\xB9"
+          "\x37\xC5\x25\x6E\xA3\x65\xD4\x2D\x92\x0A\x15\xF9\xED\x6B\x07\xC3"
+          "\x3D\x6B\x68\x9C\x2D\xC9\x7C\x69\x86\xAA\x7C\xCC\x37\x75\x33\x1C" }
+    }
+};
+
+static struct cksum_test {
+    krb5_keyusage usage;
+    char *input;
+    unsigned char expected_128[16];
+    unsigned char expected_256[16];
+} cksum_tests[] = {
+    {
+        0, "",
+        "\xEE\x29\xC4\x6D\xA1\x37\x1D\x27\xD7\x32\x12\xFA\x14\xE8\x25\xB3",
+        "\x19\x7A\xD0\x4B\x76\x82\x99\xA8\xD7\xBD\x51\x2C\xA8\x65\x65\x5D"
+    },
+    {
+        5, "input",
+        "\xA4\x40\x3B\x18\xC2\xAE\xFF\x04\xEA\x9E\xE2\x8F\xB0\x1F\x1C\x26",
+        "\xC2\x11\x53\x9B\x99\xC2\x76\xDB\xC4\x55\x4F\x73\xFE\xD9\x76\x38"
+    },
+    {
+        99, "a somewhat longer input spanning multiple blocks",
+        "\x4A\x29\x54\x12\x9D\xF8\x0D\x04\x33\x2C\xD2\xA6\xC4\x14\x10\xDA",
+        "\x0F\xAD\xE4\x38\xEA\xB4\xCB\x3C\x29\x5F\xBE\x69\x6F\xA4\x9F\x52"
+    }
+};
+
+static void
+print_hex(const char *heading, unsigned char *data, size_t len)
+{
+    size_t i;
+
+    printf("  %s:\n    ", heading);
+    for (i = 0; i < len; i++) {
+        printf("%02X", data[i]);
+        if (i + 1 < len)
+            printf("%s", (i % 16) == 15 ? "\n    " : " ");
+    }
+    printf("\n");
+}
+
+static void
+generate_enc1(krb5_context context, krb5_keyusage usage, char *text,
+              char *addl, krb5_keyblock *keyblock)
+{
+    krb5_crypto_iov iov[4];
+    unsigned char nonce[12], tag[16];
+    char *ciphertext = strdup(text);
+
+    iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
+    iov[0].data = make_data(nonce, sizeof(nonce));
+    iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+    iov[1].data = string2data(addl);
+    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[2].data = string2data(ciphertext);
+    iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER;
+    iov[3].data = make_data(tag, sizeof(tag));
+    assert(krb5_c_encrypt_iov(context, keyblock, usage, NULL, iov, 4) == 0);
+    print_hex("Nonce", nonce, sizeof(nonce));
+    print_hex("Ciphertext", (unsigned char *)ciphertext, strlen(ciphertext));
+    print_hex("Tag", tag, sizeof(tag));
+}
+
+static void
+generate_enc(krb5_context context, krb5_keyusage usage, char *text, char *addl)
+{
+    printf("camellia128-ccm-128 ciphertext:\n");
+    generate_enc1(context, usage, text, addl, &key_128);
+    printf("camellia256-ccm-128 ciphertext:\n");
+    generate_enc1(context, usage, text, addl, &key_256);
+}
+
+static void
+generate_cksum1(krb5_context context, krb5_keyusage usage, char *text,
+                krb5_keyblock *keyblock)
+{
+    krb5_checksum sum;
+    krb5_data input = string2data(text);
+
+    assert(krb5_c_make_checksum(context, 0, keyblock, usage, &input,
+                                &sum) == 0);
+    print_hex("Checksum", sum.contents, sum.length);
+    krb5_free_checksum_contents(context, &sum);
+}
+
+static void
+generate_cksum(krb5_context context, krb5_keyusage usage, char *text)
+{
+    printf("cmac-128-camellia128 checksum:\n");
+    generate_cksum1(context, usage, text, &key_128);
+    printf("cmac-128-camellia256 checksum:\n");
+    generate_cksum1(context, usage, text, &key_256);
+}
+
+static void
+verify_enc1(krb5_context context, krb5_keyblock *keyblock, krb5_keyusage usage,
+            krb5_data *cipher, char *input, char *addl)
+{
+    krb5_crypto_iov iov[3];
+
+    iov[0].flags = KRB5_CRYPTO_TYPE_STREAM;
+    assert(alloc_data(&iov[0].data, cipher->length) == 0);
+    memcpy(iov[0].data.data, cipher->data, cipher->length);
+    iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+    iov[1].data = string2data(addl);
+    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+    assert(krb5_c_decrypt_iov(context, keyblock, usage, NULL, iov, 3) == 0);
+    assert(data_eq_string(iov[2].data, input));
+}
+
+static void
+verify_enc(krb5_context context)
+{
+    size_t i;
+    struct enc_test *test;
+
+    for (i = 0; i < sizeof(enc_tests) / sizeof(*enc_tests); i++) {
+        test = &enc_tests[i];
+        verify_enc1(context, &key_128, test->usage, &test->cipher_128,
+                    test->input, test->addl);
+        verify_enc1(context, &key_256, test->usage, &test->cipher_256,
+                    test->input, test->addl);
+    }
+}
+
+static void
+verify_cksum1(krb5_context context, krb5_keyblock *keyblock,
+              krb5_keyusage usage, char *text, unsigned char *expected)
+{
+    krb5_checksum sum;
+    krb5_data input = string2data(text);
+
+    assert(krb5_c_make_checksum(context, 0, keyblock, usage, &input,
+                                &sum) == 0);
+    assert(sum.length == 16);
+    assert(memcmp(sum.contents, expected, 16) == 0);
+    krb5_free_checksum_contents(context, &sum);
+}
+
+static void
+verify_cksum(krb5_context context)
+{
+    size_t i;
+    struct cksum_test *test;
+
+    for (i = 0; i < sizeof(cksum_tests) / sizeof(*cksum_tests); i++) {
+        test = &cksum_tests[i];
+        verify_cksum1(context, &key_128, test->usage, test->input,
+                      test->expected_128);
+        verify_cksum1(context, &key_256, test->usage, test->input,
+                      test->expected_256);
+    }
+}
+
+#endif /* CAMELLIA_CCM */
+
+int
+main(int argc, char **argv)
+{
+#ifdef CAMELLIA_CCM
+    krb5_context context = NULL;
+    krb5_data seed = string2data("seed");
+
+    assert(krb5_c_random_seed(context, &seed) == 0);
+    if (argc >= 5 && strcmp(argv[1], "-ge") == 0) {
+        generate_enc(context, atoi(argv[2]), argv[3], argv[4]);
+    } else if (argc >= 4 && strcmp(argv[1], "-gc") == 0) {
+        generate_cksum(context, atoi(argv[2]), argv[3]);
+    } else {
+        verify_enc(context);
+        verify_cksum(context);
+    }
+#endif /* CAMELLIA_CCM */
+    return 0;
+}
diff --git a/src/lib/crypto/crypto_tests/t_cmac.c b/src/lib/crypto/crypto_tests/t_cmac.c
new file mode 100644 (file)
index 0000000..139372c
--- /dev/null
@@ -0,0 +1,149 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/t_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.
+ *
+ *
+ * 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 Camellia-CMAC against results we generated ourselves.  This has
+ * been 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"
+
+#ifdef CAMELLIA_CCM
+
+/* 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);
+        }
+    }
+}
+
+#endif /* CAMELLIA_CCM */
+
+int
+main(int argc, char **argv)
+{
+#ifdef CAMELLIA_CCM
+    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 3. */
+    iov.data.length = 40;
+    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
+    check_result("example 3", resultbuf, cmac3);
+
+    /* Example 4. */
+    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);
+#endif /* CAMELLIA_CCM */
+    return 0;
+}
index aa6c4af2d49ebb5923422f6219b3f0d3d91914a3..c2d2be86978c1d6895ef8f52be9bc4b8de9e48e7 100644 (file)
@@ -45,6 +45,10 @@ krb5_enctype interesting_enctypes[] = {
     ENCTYPE_ARCFOUR_HMAC_EXP,
     ENCTYPE_AES256_CTS_HMAC_SHA1_96,
     ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+#ifdef CAMELLIA_CCM
+    ENCTYPE_CAMELLIA128_CCM_128,
+    ENCTYPE_CAMELLIA256_CCM_128,
+#endif
     0
 };
 
index 90f15b8a88aff5ea318b64f78317e40fd831ac6e..9b1b630fc9a0f00ad1398933d53ca3208bf36644 100644 (file)
@@ -41,6 +41,10 @@ krb5_enctype interesting_enctypes[] = {
     ENCTYPE_ARCFOUR_HMAC_EXP,
     ENCTYPE_AES256_CTS_HMAC_SHA1_96,
     ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+#ifdef CAMELLIA_CCM
+    ENCTYPE_CAMELLIA128_CCM_128,
+    ENCTYPE_CAMELLIA256_CCM_128,
+#endif
     0
 };
 
diff --git a/src/lib/crypto/crypto_tests/t_str2key.c b/src/lib/crypto/crypto_tests/t_str2key.c
new file mode 100644 (file)
index 0000000..d441e66
--- /dev/null
@@ -0,0 +1,336 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/crypto_tests/t_str2key.c
+ *
+ * Copyright (C) 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.
+ *
+ *
+ * String-to-key test vectors
+ */
+
+#include "k5-int.h"
+
+struct test {
+    krb5_enctype enctype;
+    char *string;
+    char *salt;
+    krb5_data params;
+    krb5_data expected_key;
+} test_cases[] = {
+    /* Test vectors from RFC 3962 appendix B. */
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\1" },
+        { KV5M_DATA, 16,
+          "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\1" },
+        { KV5M_DATA, 32,
+          "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B"
+          "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\2" },
+        { KV5M_DATA, 16,
+          "\xC6\x51\xBF\x29\xE2\x30\x0A\xC2\x7F\xA4\x69\xD6\x93\xBD\xDA\x13" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\2" },
+        { KV5M_DATA, 32,
+          "\xA2\xE1\x6D\x16\xB3\x60\x69\xC1\x35\xD5\xE9\xD2\xE2\x5F\x89\x61"
+          "\x02\x68\x56\x18\xB9\x59\x14\xB4\x67\xC6\x76\x22\x22\x58\x24\xFF" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\x4C\x01\xCD\x46\xD6\x32\xD0\x1E\x6D\xBE\x23\x0A\x01\xED\x64\x2A" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\x55\xA6\xAC\x74\x0A\xD1\x7B\x48\x46\x94\x10\x51\xE1\xE8\xB0\xA7"
+          "\x54\x8D\x93\xB0\xAB\x30\xA8\xBC\x3F\xF1\x62\x80\x38\x2B\x8C\x2A" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "password",
+        "\x12\x34\x56\x78\x78\x56\x34\x12",
+        { KV5M_DATA, 4, "\0\0\0\5" },
+        { KV5M_DATA, 16,
+          "\xE9\xB2\x3D\x52\x27\x37\x47\xDD\x5C\x35\xCB\x55\xBE\x61\x9D\x8E" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "password",
+        "\x12\x34\x56\x78\x78\x56\x34\x12",
+        { KV5M_DATA, 4, "\0\0\0\5" },
+        { KV5M_DATA, 32,
+          "\x97\xA4\xE7\x86\xBE\x20\xD8\x1A\x38\x2D\x5E\xBC\x96\xD5\x90\x9C"
+          "\xAB\xCD\xAD\xC8\x7C\xA4\x8F\x57\x45\x04\x15\x9F\x16\xC3\x6E\x31" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase equals block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\x59\xD1\xBB\x78\x9A\x82\x8B\x1A\xA5\x4E\xF9\xC2\x88\x3F\x69\xED" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase equals block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\x89\xAD\xEE\x36\x08\xDB\x8B\xC7\x1F\x1B\xFB\xFE\x45\x94\x86\xB0"
+          "\x56\x18\xB7\x0C\xBA\xE2\x20\x92\x53\x4E\x56\xC5\x53\xBA\x4B\x34" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\xCB\x80\x05\xDC\x5F\x90\x17\x9A\x7F\x02\x10\x4C\x00\x18\x75\x1D" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\xD7\x8C\x5C\x9C\xB8\x72\xA8\xC9\xDA\xD4\x69\x7F\x0B\xB5\xB2\xD2"
+          "\x14\x96\xC8\x2B\xEB\x2C\xAE\xDA\x21\x12\xFC\xEE\xA0\x57\x40\x1B" }
+    },
+    { 
+        ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+        "\xF0\x9D\x84\x9E",
+        "EXAMPLE.COMpianist",
+        { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */
+        { KV5M_DATA, 16,
+          "\xF1\x49\xC1\xF2\xE1\x54\xA7\x34\x52\xD4\x3E\x7F\xE6\x2A\x56\xE5" }
+    },
+    { 
+        ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+        "\xF0\x9D\x84\x9E",
+        "EXAMPLE.COMpianist",
+        { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */
+        { KV5M_DATA, 32,
+          "\x4B\x6D\x98\x39\xF8\x44\x06\xDF\x1F\x09\xCC\x16\x6D\xB4\xB8\x3C"
+          "\x57\x18\x48\xB7\x84\xA3\xD6\xBD\xC3\x46\x58\x9A\x3E\x39\x3F\x9E" }
+    },
+
+#ifdef CAMELLIA_CCM
+    /* The same inputs applied to camellia-ccm enctypes. */
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\1" },
+        { KV5M_DATA, 16,
+          "\xF0\x10\x02\xD2\xB1\xF9\xA1\xAD\xE2\x57\xEE\xF7\x52\x9C\x2A\x16" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\1" },
+        { KV5M_DATA, 32,
+          "\xD7\xEF\x37\xE2\xD1\x05\x5E\xB7\xD7\x6B\x06\x39\x6E\xF7\x00\x52"
+          "\x3D\xA4\xB0\xB7\xA0\x53\xF5\xCC\x5F\xAE\x4A\x39\xCF\xC5\x75\x0F" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\2" },
+        { KV5M_DATA, 16,
+          "\xDD\x74\x90\xC0\x57\x4A\x44\x6B\x10\x3A\xB3\x1B\x6D\xE4\x77\x4F" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\0\2" },
+        { KV5M_DATA, 32,
+          "\x68\xC1\x64\x74\x09\x42\x8F\x59\x47\x9B\x26\xC3\x98\x6D\x5B\xB8"
+          "\x66\x1C\xDE\x3C\x66\x79\xA0\xF5\x2C\x89\x01\xBD\x78\xDC\xEB\xA2" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\x1A\xA9\x0A\xA6\x1E\x0B\x3C\xB8\x6A\xA5\xA7\x7E\xD8\x44\x9D\x3B" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "password",
+        "ATHENA.MIT.EDUraeburn",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\xF8\x29\xBC\xE4\xBB\xB1\xA2\x4B\x01\xA0\xE8\xB1\xA7\x09\x52\x0A"
+          "\x61\x38\xE9\xAF\xE5\x13\x84\x59\xB2\x0B\xAC\xCA\xB2\x4D\x5F\xAA" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "password",
+        "\x12\x34\x56\x78\x78\x56\x34\x12",
+        { KV5M_DATA, 4, "\0\0\0\5" },
+        { KV5M_DATA, 16,
+          "\x35\x70\xC6\x68\x0D\xC6\xE9\xB0\x2E\x01\x28\x8B\xD0\xD2\xB6\x9B" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "password",
+        "\x12\x34\x56\x78\x78\x56\x34\x12",
+        { KV5M_DATA, 4, "\0\0\0\5" },
+        { KV5M_DATA, 32,
+          "\x40\xB3\xB7\xC8\xF9\xC3\xB8\x65\x18\x10\xDC\x28\x42\x2D\x5F\x6D"
+          "\x10\xA6\xB3\xE9\xE1\x2A\x71\xFF\xA6\x35\x41\x08\x4A\xFA\x2C\xA2" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase equals block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\xFF\x99\x18\x52\x84\x8E\x67\x50\x4C\x09\x4F\x94\x68\xC9\xD6\x05" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase equals block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\x56\x5C\x0A\x29\xC0\x58\xCD\xDC\x3C\xD8\xA9\xF3\x0A\x92\xAA\xD7"
+          "\xFE\x30\xEA\xD4\x16\xC1\x51\xAA\x9B\x54\x75\x56\x62\xF0\x95\xDD" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 16,
+          "\xAC\x83\x28\x64\x10\xA2\x8C\x76\x64\x79\x60\xF6\xA0\x37\x88\x03" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+        "pass phrase exceeds block size",
+        { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */
+        { KV5M_DATA, 32,
+          "\xD3\x25\x4A\x5B\x45\x1F\x27\x9C\x1A\xD6\x29\x3E\x72\xF0\x69\x55"
+          "\xEB\xFF\x36\xB6\x47\xDF\x97\x48\x97\x18\xD7\x5C\xF0\x6C\x40\x7C" }
+    },
+    { 
+        ENCTYPE_CAMELLIA128_CCM_128,
+        "\xf0\x9d\x84\x9e",
+        "EXAMPLE.COMpianist",
+        { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */
+        { KV5M_DATA, 16,
+          "\x5D\xBD\x71\x57\x09\x38\x59\x81\xDA\xAB\xA2\x8A\x43\x10\xD7\x20" }
+    },
+    { 
+        ENCTYPE_CAMELLIA256_CCM_128,
+        "\xf0\x9d\x84\x9e",
+        "EXAMPLE.COMpianist",
+        { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */
+        { KV5M_DATA, 32,
+          "\x6A\x1F\x10\xE5\x74\x4E\x32\xDD\x33\x49\x03\xA8\xEB\xD1\x42\x7E"
+          "\x4C\x8D\x3D\x6D\xA5\x76\x77\x50\x4C\x38\x4C\x24\x33\x0B\x60\x3D" }
+    }
+#endif /* CAMELLIA_CCM */
+};
+
+static void
+printkey(krb5_keyblock *keyblock)
+{
+    unsigned int i;
+
+    for (i = 0; i < keyblock->length; i++) {
+        printf("%02X", keyblock->contents[i]);
+        if (i + 1 < keyblock->length)
+            printf(" ");
+    }
+    printf("\n");
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context = NULL;
+    krb5_data string, salt;
+    krb5_error_code ret;
+    krb5_keyblock *keyblock;
+    size_t i;
+    struct test *test;
+    krb5_boolean verbose = FALSE;
+
+    if (argc >= 2 && strcmp(argv[1], "-v") == 0)
+        verbose = TRUE;
+    for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) {
+        test = &test_cases[i];
+        string = string2data(test->string);
+        salt = string2data(test->salt);
+        assert(krb5_init_keyblock(context, test->enctype, 0, &keyblock) == 0);
+        ret = krb5_c_string_to_key_with_params(context, test->enctype,
+                                               &string, &salt, &test->params,
+                                               keyblock);
+        if (ret != 0) {
+            com_err(argv[0], ret, "in krb5_c_string_to_key_with_params");
+            exit(1);
+        }
+        if (verbose) {
+            printf("Test %02d: ", (int)i);
+            printkey(keyblock);
+        }
+        assert(keyblock->length == test->expected_key.length);
+        if (memcmp(keyblock->contents, test->expected_key.data,
+                   keyblock->length) != 0) {
+            printf("str2key test %d failed\n", (int)i);
+            exit(1);
+        }
+        krb5_free_keyblock(context, keyblock);
+    }
+    return 0;
+}
index a6f1bbe78c8f153d174871eceb91fc51c1ea80ce..f984a1788fcc06ab0986afceca217f59264d8041 100644 (file)
@@ -213,13 +213,13 @@ extern struct krb5_enc_provider krb5int_enc_aes128, krb5int_enc_aes256;
 
 void DK (krb5_keyblock *out, krb5_keyblock *in, const krb5_data *usage) {
     krb5_error_code r;
-    r = krb5int_derive_key (enc, in, out, usage);
+    r = krb5int_derive_key (enc, in, out, usage, DERIVE_RFC3961);
     CHECK;
 }
 
 void DR (krb5_data *out, krb5_keyblock *in, const krb5_data *usage) {
     krb5_error_code r;
-    r = krb5int_derive_random (enc, in, out, usage);
+    r = krb5int_derive_random (enc, in, out, usage, DERIVE_RFC3961);
     CHECK;
 }
 
index 9e019115fe5559344adb9cc40ae7729a7e881eab..119441aabf97e28ef33aae489e1b68b335e16199 100644 (file)
@@ -8,6 +8,7 @@ LOCALINCLUDES = -I$(srcdir) -I$(srcdir)/../@CRYPTO_IMPL@/enc_provider -I$(srcdir
                -I$(srcdir)/old -I$(srcdir)/raw -I$(srcdir)/yarrow                      \
                -I$(srcdir)/../@CRYPTO_IMPL@/ -I$(srcdir)/../@CRYPTO_IMPL@/des          \
                -I$(srcdir)/../@CRYPTO_IMPL@/aes -I$(srcdir)/arcfour    \
+               -I$(srcdir)/../@CRYPTO_IMPL@/camellia \
                -I$(srcdir)/../@CRYPTO_IMPL@/sha1 -I$(srcdir)/../@CRYPTO_IMPL@
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
index c1f8ccd9e6f01eef8fb1202b871db064c25c7cf9..3d9111abb48aa578b46fdaee78190a54ff2773fe 100644 (file)
@@ -53,184 +53,6 @@ krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data,
     return iov;
 }
 
-#ifdef DEBUG_IOV
-static void
-dump_block(const char *tag,
-           size_t i,
-           size_t j,
-           unsigned char *block,
-           size_t block_size)
-{
-    size_t k;
-
-    printf("[%s: %d.%d] ", tag, i, j);
-
-    for (k = 0; k < block_size; k++)
-        printf("%02x ", block[k] & 0xFF);
-
-    printf("\n");
-}
-#endif
-
-static int
-process_block_p(const krb5_crypto_iov *data,
-                size_t num_data,
-                struct iov_block_state *iov_state,
-                size_t i)
-{
-    const krb5_crypto_iov *iov = &data[i];
-    int process_block;
-
-    switch (iov->flags) {
-    case KRB5_CRYPTO_TYPE_SIGN_ONLY:
-        process_block = iov_state->include_sign_only;
-        break;
-    case KRB5_CRYPTO_TYPE_PADDING:
-        process_block = (iov_state->pad_to_boundary == 0);
-        break;
-    case KRB5_CRYPTO_TYPE_HEADER:
-        process_block = (iov_state->ignore_header == 0);
-        break;
-    case KRB5_CRYPTO_TYPE_DATA:
-        process_block = 1;
-        break;
-    default:
-        process_block = 0;
-        break;
-    }
-
-    return process_block;
-}
-
-/*
- * Returns TRUE if, having reached the end of the current buffer,
- * we should pad the rest of the block with zeros.
- */
-static int
-pad_to_boundary_p(const krb5_crypto_iov *data,
-                  size_t num_data,
-                  struct iov_block_state *iov_state,
-                  size_t i,
-                  size_t j)
-{
-    /* If the pad_to_boundary flag is unset, return FALSE */
-    if (iov_state->pad_to_boundary == 0)
-        return 0;
-
-    /* If we haven't got any data, we need to get some */
-    if (j == 0)
-        return 0;
-
-    /* No boundary between adjacent buffers marked for processing */
-    if (data[iov_state->iov_pos].flags == data[i].flags)
-        return 0;
-
-    return 1;
-}
-
-krb5_boolean
-krb5int_c_iov_get_block(unsigned char *block,
-                        size_t block_size,
-                        const krb5_crypto_iov *data,
-                        size_t num_data,
-                        struct iov_block_state *iov_state)
-{
-    size_t i, j = 0;
-
-    for (i = iov_state->iov_pos; i < num_data; i++) {
-        const krb5_crypto_iov *iov = &data[i];
-        size_t nbytes;
-
-        if (!process_block_p(data, num_data, iov_state, i))
-            continue;
-
-        if (pad_to_boundary_p(data, num_data, iov_state, i, j))
-            break;
-
-        iov_state->iov_pos = i;
-
-        nbytes = iov->data.length - iov_state->data_pos;
-        if (nbytes > block_size - j)
-            nbytes = block_size - j;
-
-        memcpy(block + j, iov->data.data + iov_state->data_pos, nbytes);
-
-        iov_state->data_pos += nbytes;
-        j += nbytes;
-
-        assert(j <= block_size);
-
-        if (j == block_size)
-            break;
-
-        assert(iov_state->data_pos == iov->data.length);
-
-        iov_state->data_pos = 0;
-    }
-
-    iov_state->iov_pos = i;
-    if (i == num_data)
-        return FALSE;
-
-    if (j != block_size)
-        memset(block + j, 0, block_size - j);
-
-#ifdef DEBUG_IOV
-    dump_block("get_block", i, j, block, block_size);
-#endif
-
-    return TRUE;
-}
-
-krb5_boolean
-krb5int_c_iov_put_block(const krb5_crypto_iov *data,
-                        size_t num_data,
-                        unsigned char *block,
-                        size_t block_size,
-                        struct iov_block_state *iov_state)
-{
-    size_t i, j = 0;
-
-    for (i = iov_state->iov_pos; i < num_data; i++) {
-        const krb5_crypto_iov *iov = &data[i];
-        size_t nbytes;
-
-        if (!process_block_p(data, num_data, iov_state, i))
-            continue;
-
-        if (pad_to_boundary_p(data, num_data, iov_state, i, j))
-            break;
-
-        iov_state->iov_pos = i;
-
-        nbytes = iov->data.length - iov_state->data_pos;
-        if (nbytes > block_size - j)
-            nbytes = block_size - j;
-
-        memcpy(iov->data.data + iov_state->data_pos, block + j, nbytes);
-
-        iov_state->data_pos += nbytes;
-        j += nbytes;
-
-        assert(j <= block_size);
-
-        if (j == block_size)
-            break;
-
-        assert(iov_state->data_pos == iov->data.length);
-
-        iov_state->data_pos = 0;
-    }
-
-    iov_state->iov_pos = i;
-
-#ifdef DEBUG_IOV
-    dump_block("put_block", i, j, block, block_size);
-#endif
-
-    return (iov_state->iov_pos < num_data);
-}
-
 krb5_error_code
 krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key,
                              krb5_keyusage keyusage, const krb5_data *ivec,
index df54a05d377fc4e96e110fbf933e6495fbd76b4e..5cc94f4498092c6824cbc95ffdb469b065fecb68 100644 (file)
@@ -60,20 +60,6 @@ struct iov_block_state {
                                          (_state)->include_sign_only =  \
                                          (_state)->pad_to_boundary = 0)
 
-krb5_boolean
-krb5int_c_iov_get_block(unsigned char *block,
-                        size_t block_size,
-                        const krb5_crypto_iov *data,
-                        size_t num_data,
-                        struct iov_block_state *iov_state);
-
-krb5_boolean
-krb5int_c_iov_put_block(const krb5_crypto_iov *data,
-                        size_t num_data,
-                        unsigned char *block,
-                        size_t block_size,
-                        struct iov_block_state *iov_state);
-
 krb5_error_code
 krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key,
                              krb5_keyusage keyusage, const krb5_data *ivec,
@@ -82,48 +68,247 @@ krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key,
 unsigned int
 krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length);
 
+#ifdef DEBUG_IOV
+static inline void
+dump_block(const char *tag,
+           size_t i,
+           size_t j,
+           unsigned char *block,
+           size_t block_size)
+{
+    size_t k;
+
+    printf("[%s: %lu.%lu] ", tag, i, j);
+
+    for (k = 0; k < block_size; k++)
+        printf("%02x ", block[k] & 0xFF);
+
+    printf("\n");
+}
+#endif
+
+static inline int
+process_block_p(const krb5_crypto_iov *data,
+                size_t num_data,
+                struct iov_block_state *iov_state,
+                size_t i)
+{
+    const krb5_crypto_iov *iov = &data[i];
+    int process_block;
+
+    switch (iov->flags) {
+    case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+        process_block = iov_state->include_sign_only;
+        break;
+    case KRB5_CRYPTO_TYPE_PADDING:
+        process_block = (iov_state->pad_to_boundary == 0);
+        break;
+    case KRB5_CRYPTO_TYPE_HEADER:
+        process_block = (iov_state->ignore_header == 0);
+        break;
+    case KRB5_CRYPTO_TYPE_DATA:
+        process_block = 1;
+        break;
+    default:
+        process_block = 0;
+        break;
+    }
+
+    return process_block;
+}
+
+/*
+ * Returns TRUE if, having reached the end of the current buffer,
+ * we should pad the rest of the block with zeros.
+ */
+static inline int
+pad_to_boundary_p(const krb5_crypto_iov *data,
+                  size_t num_data,
+                  struct iov_block_state *iov_state,
+                  size_t i,
+                  size_t j)
+{
+    /* If the pad_to_boundary flag is unset, return FALSE */
+    if (iov_state->pad_to_boundary == 0)
+        return 0;
+
+    /* If we haven't got any data, we need to get some */
+    if (j == 0)
+        return 0;
+
+    /* No boundary between adjacent buffers marked for processing */
+    if (data[iov_state->iov_pos].flags == data[i].flags)
+        return 0;
+
+    return 1;
+}
+
 /*
- * Returns an alias into the current buffer if the next block is fully
- * contained within; otherwise makes a copy of the next block and returns an
- * alias to storage.  After calling this function, encrypt the returned block
- * in place and then call iov_store_block (with a separate output cursor) to
- * store the result back into the iov if necessary.  Returns NULL if there
- * is no next block.
+ * Retrieve a block from the IOV. If p is non-NULL and the next block is
+ * completely contained within the current buffer, then *p will contain an
+ * alias into the buffer; otherwise, a copy will be made into storage.
+ *
+ * After calling this function, encrypt the returned block and then call
+ * krb5int_c_iov_put_block_nocopy() (with a separate output cursor). If
+ * p was non-NULL on the call to get_block(), then pass that pointer in.
  */
-static inline unsigned char *
-iov_next_block(unsigned char *storage, size_t len,
-               const krb5_crypto_iov *data, size_t num_data,
-               struct iov_block_state *pos)
+static inline krb5_boolean
+krb5int_c_iov_get_block_nocopy(unsigned char *storage,
+                               size_t block_size,
+                               const krb5_crypto_iov *data,
+                               size_t num_data,
+                               struct iov_block_state *iov_state,
+                               unsigned char **p)
 {
-    const krb5_crypto_iov *iov = &data[pos->iov_pos];
-    unsigned char *block;
-
-    if (pos->iov_pos < num_data && iov->data.length - pos->data_pos >= len) {
-        /* Return an alias to memory inside the current iov. */
-        block = (unsigned char *) iov->data.data + pos->data_pos;
-        pos->data_pos += len;
-        return block;
+    size_t i, j = 0;
+
+    if (p != NULL)
+        *p = storage;
+
+    for (i = iov_state->iov_pos; i < num_data; i++) {
+        const krb5_crypto_iov *iov = &data[i];
+        size_t nbytes;
+
+        if (!process_block_p(data, num_data, iov_state, i))
+            continue;
+
+        if (pad_to_boundary_p(data, num_data, iov_state, i, j))
+            break;
+
+        iov_state->iov_pos = i;
+
+        nbytes = iov->data.length - iov_state->data_pos;
+        if (nbytes > block_size - j)
+            nbytes = block_size - j;
+
+        /*
+         * If we can return a pointer into a complete block, then do so.
+         */
+        if (p != NULL && j == 0 && nbytes == block_size) {
+            *p = (unsigned char *)iov->data.data + iov_state->data_pos;
+        } else {
+            memcpy(storage + j, iov->data.data + iov_state->data_pos, nbytes);
+        }
+
+        iov_state->data_pos += nbytes;
+        j += nbytes;
+
+        assert(j <= block_size);
+
+        if (j == block_size)
+            break;
+
+        assert(iov_state->data_pos == iov->data.length);
+
+        iov_state->data_pos = 0;
     }
-    /* Do it the slow way and return a copy into storage. */
-    if (krb5int_c_iov_get_block(storage, len, data, num_data, pos))
-        return storage;
-    return NULL;
+
+    iov_state->iov_pos = i;
+
+    if (j == 0)
+        return FALSE;
+    else if (j != block_size)
+        memset(storage + j, 0, block_size - j);
+
+#ifdef DEBUG_IOV
+    dump_block("get_block", i, j, (p && *p) ? *p : storage, block_size);
+#endif
+
+    return TRUE;
 }
 
 /*
- * Store a block retrieved with iov_next_block if necessary, and advance the
- * output cursor.
+ * Store a block retrieved with krb5int_c_iov_get_block_no_copy if
+ * necessary, and advance the output cursor.
  */
-static inline void
-iov_store_block(const krb5_crypto_iov *data, size_t num_data,
-                unsigned char *block, unsigned char *storage, size_t len,
-                struct iov_block_state *pos)
+static inline krb5_boolean
+krb5int_c_iov_put_block_nocopy(const krb5_crypto_iov *data,
+                               size_t num_data,
+                               unsigned char *storage,
+                               size_t block_size,
+                               struct iov_block_state *iov_state,
+                               unsigned char *p)
 {
-    if (block == storage) {
-        /* We got the block the slow way; put it back that way too. */
-        krb5int_c_iov_put_block(data, num_data, storage, len, pos);
-    } else {
-        /* It's already stored; we just have to advance the output cursor. */
-        pos->data_pos += len;
+    size_t i, j = 0;
+
+    assert(p != NULL);
+
+    for (i = iov_state->iov_pos; i < num_data; i++) {
+        const krb5_crypto_iov *iov = &data[i];
+        size_t nbytes;
+
+        if (!process_block_p(data, num_data, iov_state, i))
+            continue;
+
+        if (pad_to_boundary_p(data, num_data, iov_state, i, j))
+            break;
+
+        iov_state->iov_pos = i;
+
+        nbytes = iov->data.length - iov_state->data_pos;
+        if (nbytes > block_size - j)
+            nbytes = block_size - j;
+
+        /*
+         * If we had previously returned a pointer into a complete block,
+         * then no action is required.
+         */
+        if (p == storage) {
+            memcpy(iov->data.data + iov_state->data_pos, storage + j, nbytes);
+        } else {
+            /* Ensure correctly paired with a call to get_block_nocopy(). */
+            assert(j == 0);
+            assert(nbytes == 0 || nbytes == block_size);
+        }
+
+        iov_state->data_pos += nbytes;
+        j += nbytes;
+
+        assert(j <= block_size);
+
+        if (j == block_size)
+            break;
+
+        assert(iov_state->data_pos == iov->data.length);
+
+        iov_state->data_pos = 0;
     }
+
+    iov_state->iov_pos = i;
+
+#ifdef DEBUG_IOV
+    dump_block("put_block", i, j, p, block_size);
+#endif
+
+    return (iov_state->iov_pos < num_data);
+}
+
+/*
+ * A wrapper for krb5int_c_iov_get_block_nocopy() that always makes
+ * a copy.
+ */
+static inline krb5_boolean
+krb5int_c_iov_get_block(unsigned char *block,
+                        size_t block_size,
+                        const krb5_crypto_iov *data,
+                        size_t num_data,
+                        struct iov_block_state *iov_state)
+{
+    return krb5int_c_iov_get_block_nocopy(block, block_size, data, num_data,
+                                          iov_state, NULL);
+}
+
+/*
+ * A wrapper for krb5int_c_iov_put_block_nocopy() that always copies
+ * the block.
+ */
+static inline krb5_boolean
+krb5int_c_iov_put_block(const krb5_crypto_iov *data,
+                        size_t num_data,
+                        unsigned char *block,
+                        size_t block_size,
+                        struct iov_block_state *iov_state)
+{
+    return krb5int_c_iov_put_block_nocopy(data, num_data, block, block_size,
+                                          iov_state, block);
 }
index 61b41f252d1bc656ab8ea9e867ca6f90d3a41820..826afd189d760b7dee5ccc3b36f424922fc1d95e 100644 (file)
@@ -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 (file)
index 0000000..a0e249f
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * 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"
+
+#ifdef CAMELLIA_CCM
+
+#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 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;
+    }
+}
+
+/* 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,
+                unsigned char *K1,
+                unsigned char *K2)
+{
+    unsigned char L[BLOCK_SIZE];
+    unsigned char tmp[BLOCK_SIZE];
+    krb5_data d;
+    krb5_error_code ret;
+
+    /* L := encrypt(K, const_Zero) */
+    memset(L, 0, sizeof(L));
+    d = make_data(L, BLOCK_SIZE);
+    ret = encrypt_block(enc, key, &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 {
+        leftshift_onebit(L, tmp);
+        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 {
+        leftshift_onebit(K1, tmp);
+        xor_128(tmp, const_Rb, K2);
+    }
+
+    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)
+{
+    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 figure 2.3.
+ */
+krb5_error_code
+krb5int_cmac_checksum(const struct krb5_enc_provider *enc, 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_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;
+    }
+
+    /* 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;
+    } else {
+        flag = ((length % BLOCK_SIZE) == 0);
+    }
+
+    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);
+    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, &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);
+    } else {
+        padding(input, padded, length % BLOCK_SIZE);
+        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, &d, &d);
+    if (ret != 0)
+        return ret;
+
+    assert(output->length >= d.length);
+
+    output->length = d.length;
+    memcpy(output->data, d.data, d.length);
+
+    return 0;
+}
+
+#else /* CAMELLIA_CCM */
+
+/* This won't be used, but is still in the export table. */
+
+krb5_error_code
+krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
+                      const krb5_crypto_iov *data, size_t num_data,
+                      krb5_data *output)
+{
+    return EINVAL;
+}
+
+#endif /* CAMELLIA_CCM */
index 6e16b4ea89e803f06d5acc912e1d5dd291a5c01a..6744775bcb27b883181061201dab4c86985c23dc 100644 (file)
@@ -104,6 +104,20 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
       NULL, &krb5int_hash_md5,
       krb5int_hmacmd5_checksum, NULL,
       16, 16, 0 },
+
+#ifdef CAMELLIA_CCM
+    { CKSUMTYPE_CMAC_128_CAMELLIA128,
+      "cmac-128-camellia128", { 0 }, "CMAC Camellia128 key",
+      &krb5int_enc_camellia128_ctr, NULL,
+      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_dk_cmac_checksum, NULL,
+      16, 16, 0 },
+#endif /* CAMELLIA_CCM */
 };
 
 const size_t krb5int_cksumtypes_length =
index 8c32f662a4bea46b3cccf6fa261fd86ed6c50672..c5eb493f28269c2580e1e959a27739b7a3e5905b 100644 (file)
@@ -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_enc_provider *enc,
+                                      krb5_key key,
+                                      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,
index b7435383bbcb60360674c3999b7ee8e66c7f113f..a6cea2eed7f35de8f1ac9e691729b9f0491b0076 100644 (file)
@@ -191,7 +191,7 @@ krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1,
         myalloc = TRUE;
     }
 
-    ret = krb5int_derive_keyblock(enc, tkey, outkey, &input);
+    ret = krb5int_derive_keyblock(enc, tkey, outkey, &input, DERIVE_RFC3961);
     if (ret) {
         if (myalloc) {
             free(outkey->contents);
@@ -222,7 +222,8 @@ dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey,
     ret = krb5_k_create_key(NULL, inkey, &key);
     if (ret != 0)
         return ret;
-    ret = krb5int_derive_random(enc, key, &outdata, in_constant);
+    ret = krb5int_derive_random(enc, key, &outdata, in_constant,
+                                DERIVE_RFC3961);
     krb5_k_free_key(NULL, key);
     return ret;
 }
index 8d658573d575be3a2d48afd2d4e283bef5d36c34..09df6c38d5fa093af18ab4347ba247ec714bd2f4 100644 (file)
@@ -11,20 +11,26 @@ PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
 STLIBOBJS=\
-       checksum.o      \
+       checksum_hmac.o \
+       checksum_cmac.o \
        dk_aead.o       \
+       dk_ccm.o        \
        derive.o        \
        stringtokey.o
 
 OBJS=\
-       $(OUTPRE)checksum.$(OBJEXT)     \
+       $(OUTPRE)checksum_hmac.$(OBJEXT)\
+       $(OUTPRE)checksum_cmac.$(OBJEXT)\
        $(OUTPRE)dk_aead.$(OBJEXT)      \
+       $(OUTPRE)dk_ccm.$(OBJEXT)       \
        $(OUTPRE)derive.$(OBJEXT)       \
        $(OUTPRE)stringtokey.$(OBJEXT)
 
 SRCS=\
-       $(srcdir)/checksum.c    \
+       $(srcdir)/checksum_hmac.c       \
+       $(srcdir)/checksum_cmac.c       \
        $(srcdir)/dk_aead.c     \
+       $(srcdir)/dk_ccm.c      \
        $(srcdir)/derive.c      \
        $(srcdir)/stringtokey.c
 
diff --git a/src/lib/crypto/krb/dk/checksum_cmac.c b/src/lib/crypto/krb/dk/checksum_cmac.c
new file mode 100644 (file)
index 0000000..c2309b7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * lib/crypto/krb/dk/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.
+ */
+
+#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 */
+
+#ifdef CAMELLIA_CCM
+
+krb5_error_code
+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_enc_provider *enc = ctp->enc;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data datain;
+    krb5_key kc;
+
+    /* 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, DERIVE_SP800_108_CMAC);
+    if (ret != 0)
+        return ret;
+
+    /* Hash the data. */
+    ret = krb5int_cmac_checksum(enc, kc, data, num_data, output);
+    if (ret != 0)
+        memset(output->data, 0, output->length);
+
+    krb5_k_free_key(NULL, kc);
+    return ret;
+}
+
+#endif /* CAMELLIA_CCM */
similarity index 97%
rename from src/lib/crypto/krb/dk/checksum.c
rename to src/lib/crypto/krb/dk/checksum_hmac.c
index 3dbde1014b866fa94ee61e4ef974f9400475f643..ae51aa38f49df235c294620cddf058e879dbec50 100644 (file)
@@ -57,7 +57,7 @@ krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
     datain = make_data(constantdata, K5CLENGTH);
     store_32_be(usage, constantdata);
     constantdata[4] = (char) 0x99;
-    ret = krb5int_derive_key(enc, key, &kc, &datain);
+    ret = krb5int_derive_key(enc, key, &kc, &datain, DERIVE_RFC3961);
     if (ret)
         return ret;
 
index 5fd8876479982078caf79ca6a7e4f00f87f15067..a7ad2e344596897cd11040903fff7bf40579b270 100644 (file)
@@ -79,14 +79,14 @@ cleanup:
     return ENOMEM;
 }
 
-krb5_error_code
-krb5int_derive_random(const struct krb5_enc_provider *enc,
+static krb5_error_code
+derive_random_rfc3961(const struct krb5_enc_provider *enc,
                       krb5_key inkey, krb5_data *outrnd,
                       const krb5_data *in_constant)
 {
     size_t blocksize, keybytes, n;
-    krb5_crypto_iov iov;
     krb5_error_code ret;
+    krb5_data block = empty_data();
 
     blocksize = enc->block_size;
     keybytes = enc->keybytes;
@@ -95,41 +95,136 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
         return KRB5_CRYPTO_INTERNAL;
 
     /* Allocate encryption data buffer. */
-    iov.flags = KRB5_CRYPTO_TYPE_DATA;
-    ret = alloc_data(&iov.data, blocksize);
+    ret = alloc_data(&block, blocksize);
     if (ret)
         return ret;
 
     /* Initialize the input block. */
     if (in_constant->length == blocksize) {
-        memcpy(iov.data.data, in_constant->data, blocksize);
+        memcpy(block.data, in_constant->data, blocksize);
     } else {
         krb5int_nfold(in_constant->length * 8,
                       (unsigned char *) in_constant->data,
-                      blocksize * 8, (unsigned char *) iov.data.data);
+                      blocksize * 8, (unsigned char *) block.data);
     }
 
     /* Loop encrypting the blocks until enough key bytes are generated. */
     n = 0;
     while (n < keybytes) {
-        ret = enc->encrypt(inkey, 0, &iov, 1);
+        ret = encrypt_block(enc, inkey, &block);
         if (ret)
             goto cleanup;
 
         if ((keybytes - n) <= blocksize) {
-            memcpy(outrnd->data + n, iov.data.data, (keybytes - n));
+            memcpy(outrnd->data + n, block.data, (keybytes - n));
             break;
         }
 
-        memcpy(outrnd->data + n, iov.data.data, blocksize);
+        memcpy(outrnd->data + n, block.data, blocksize);
         n += blocksize;
     }
 
 cleanup:
-    zapfree(iov.data.data, blocksize);
+    zapfree(block.data, blocksize);
     return ret;
 }
 
+#ifdef CAMELLIA_CCM
+
+/*
+ * NIST SP800-108 KDF in feedback mode (section 5.2).
+ * Parameters:
+ *   - CMAC (with enc as the enc provider) is the PRF.
+ *   - A block counter of four bytes is used.
+ *   - Label is the key derivation constant.
+ *   - Context is empty.
+ *   - Four bytes are used to encode the output length in the PRF input.
+ */
+static krb5_error_code
+derive_random_sp800_108_cmac(const struct krb5_enc_provider *enc,
+                             krb5_key inkey, krb5_data *outrnd,
+                             const krb5_data *in_constant)
+{
+    size_t blocksize, keybytes, n;
+    krb5_crypto_iov iov[6];
+    krb5_error_code ret;
+    krb5_data prf;
+    unsigned int i;
+    unsigned char ibuf[4], Lbuf[4];
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+
+    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+        return KRB5_CRYPTO_INTERNAL;
+
+    /* Allocate encryption data buffer. */
+    ret = alloc_data(&prf, blocksize);
+    if (ret)
+        return ret;
+
+    /* K(i-1): the previous block of PRF output, initially all-zeros. */
+    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[0].data = prf;
+    /* [i]2: four-byte big-endian binary string giving the block counter */
+    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[1].data = make_data(ibuf, sizeof(ibuf));
+    /* Label: the fixed derived-key input */
+    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[2].data = *in_constant;
+    /* 0x00: separator byte */
+    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[3].data = make_data("", 1);
+    /* Context: (unused) */
+    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[4].data = empty_data();
+    /* [L]2: four-byte big-endian binary string giving the output length */
+    iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[5].data = make_data(Lbuf, sizeof(Lbuf));
+    store_32_be(outrnd->length, Lbuf);
+
+    for (i = 1, n = 0; n < keybytes; i++) {
+        /* Update the block counter. */
+        store_32_be(i, ibuf);
+
+        /* Compute a CMAC checksum, storing the result into K(i-1). */
+        ret = krb5int_cmac_checksum(enc, inkey, iov, 6, &prf);
+        if (ret)
+            goto cleanup;
+
+        /* Copy the result into the appropriate part of the output buffer. */
+        if (keybytes - n <= blocksize) {
+            memcpy(outrnd->data + n, prf.data, keybytes - n);
+            break;
+        }
+        memcpy(outrnd->data + n, prf.data, blocksize);
+        n += blocksize;
+    }
+
+cleanup:
+    zapfree(prf.data, blocksize);
+    return ret;
+}
+
+#endif /* CAMELLIA_CCM */
+
+krb5_error_code
+krb5int_derive_random(const struct krb5_enc_provider *enc,
+                      krb5_key inkey, krb5_data *outrnd,
+                      const krb5_data *in_constant, enum deriv_alg alg)
+{
+    switch (alg) {
+    case DERIVE_RFC3961:
+        return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+#ifdef CAMELLIA_CCM
+    case DERIVE_SP800_108_CMAC:
+        return derive_random_sp800_108_cmac(enc, inkey, outrnd, in_constant);
+#endif
+    default:
+        return EINVAL;
+    }
+}
+
 /*
  * Compute a derived key into the keyblock outkey.  This variation on
  * krb5int_derive_key does not cache the result, as it is only used
@@ -139,7 +234,7 @@ cleanup:
 krb5_error_code
 krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
                         krb5_key inkey, krb5_keyblock *outkey,
-                        const krb5_data *in_constant)
+                        const krb5_data *in_constant, enum deriv_alg alg)
 {
     krb5_error_code ret;
     krb5_data rawkey = empty_data();
@@ -150,7 +245,7 @@ krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
         goto cleanup;
 
     /* Derive pseudo-random data for the key bytes. */
-    ret = krb5int_derive_random(enc, inkey, &rawkey, in_constant);
+    ret = krb5int_derive_random(enc, inkey, &rawkey, in_constant, alg);
     if (ret)
         goto cleanup;
 
@@ -165,7 +260,7 @@ cleanup:
 krb5_error_code
 krb5int_derive_key(const struct krb5_enc_provider *enc,
                    krb5_key inkey, krb5_key *outkey,
-                   const krb5_data *in_constant)
+                   const krb5_data *in_constant, enum deriv_alg alg)
 {
     krb5_keyblock keyblock;
     krb5_error_code ret;
@@ -183,13 +278,10 @@ krb5int_derive_key(const struct krb5_enc_provider *enc,
     /* Derive into a temporary keyblock. */
     keyblock.length = enc->keylength;
     keyblock.contents = malloc(keyblock.length);
-    /* Set the enctype as the krb5_k_free_key will iterate over list
-       or derived keys and invoke krb5_k_free_key which will lookup
-       the enctype for key_cleanup handler */
     keyblock.enctype = inkey->keyblock.enctype;
     if (keyblock.contents == NULL)
         return ENOMEM;
-    ret = krb5int_derive_keyblock(enc, inkey, &keyblock, in_constant);
+    ret = krb5int_derive_keyblock(enc, inkey, &keyblock, in_constant, alg);
     if (ret)
         goto cleanup;
 
index 0fdd984928fba45a8ef35c10d93a12eb013e734c..fb6df88fa81ff212cf45c311c80177adfa4c7093 100644 (file)
@@ -57,17 +57,29 @@ krb5int_aes_string_to_key(const struct krb5_keytypes *enc,
                           const krb5_data *string, const krb5_data *salt,
                           const krb5_data *params, krb5_keyblock *key);
 
+krb5_error_code
+krb5int_camellia_ccm_string_to_key(const struct krb5_keytypes *enc,
+                                   const krb5_data *string,
+                                   const krb5_data *salt,
+                                   const krb5_data *params,
+                                   krb5_keyblock *key);
+
+enum deriv_alg {
+    DERIVE_RFC3961,             /* RFC 3961 section 5.1 */
+#ifdef CAMELLIA_CCM
+    DERIVE_SP800_108_CMAC       /* NIST SP 800-108 with CMAC as PRF */
+#endif
+};
+
 krb5_error_code
 krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
-                        krb5_key inkey,
-                        krb5_keyblock *outkey,
-                        const krb5_data *in_constant);
+                        krb5_key inkey, krb5_keyblock *outkey,
+                        const krb5_data *in_constant, enum deriv_alg alg);
 
 krb5_error_code
 krb5int_derive_key(const struct krb5_enc_provider *enc,
-                   krb5_key inkey,
-                   krb5_key *outkey,
-                   const krb5_data *in_constant);
+                   krb5_key inkey, krb5_key *outkey,
+                   const krb5_data *in_constant, enum deriv_alg alg);
 
 krb5_error_code
 krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
@@ -78,4 +90,38 @@ krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
 krb5_error_code
 krb5int_derive_random(const struct krb5_enc_provider *enc,
                       krb5_key inkey, krb5_data *outrnd,
-                      const krb5_data *in_constant);
+                      const krb5_data *in_constant, enum deriv_alg alg);
+
+unsigned int
+krb5int_dk_ccm_crypto_length(const struct krb5_keytypes *ktp,
+                             krb5_cryptotype type);
+
+krb5_error_code
+krb5int_dk_ccm_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_ccm_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_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_dk_ccm_init_state(const struct krb5_keytypes *ktp,
+                          const krb5_keyblock *key, krb5_keyusage usage,
+                          krb5_data *out_state);
+
+void
+krb5int_dk_ccm_free_state(const struct krb5_keytypes *ktp, krb5_data *state);
index f44ae84ad0e9cf972af3edf032fbe2bc4569e2f1..4e9a7c4cf3db552d372188963f11595d99f16c6d 100644 (file)
@@ -134,13 +134,13 @@ krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
 
     d1.data[4] = 0xAA;
 
-    ret = krb5int_derive_key(enc, key, &ke, &d1);
+    ret = krb5int_derive_key(enc, key, &ke, &d1, DERIVE_RFC3961);
     if (ret != 0)
         goto cleanup;
 
     d1.data[4] = 0x55;
 
-    ret = krb5int_derive_key(enc, key, &ki, &d1);
+    ret = krb5int_derive_key(enc, key, &ki, &d1, DERIVE_RFC3961);
     if (ret != 0)
         goto cleanup;
 
@@ -235,13 +235,13 @@ krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
 
     d1.data[4] = 0xAA;
 
-    ret = krb5int_derive_key(enc, key, &ke, &d1);
+    ret = krb5int_derive_key(enc, key, &ke, &d1, DERIVE_RFC3961);
     if (ret != 0)
         goto cleanup;
 
     d1.data[4] = 0x55;
 
-    ret = krb5int_derive_key(enc, key, &ki, &d1);
+    ret = krb5int_derive_key(enc, key, &ki, &d1, DERIVE_RFC3961);
     if (ret != 0)
         goto cleanup;
 
diff --git a/src/lib/crypto/krb/dk/dk_ccm.c b/src/lib/crypto/krb/dk/dk_ccm.c
new file mode 100644 (file)
index 0000000..284e362
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * lib/crypto/krb/dk/dk_ccm.c
+ *
+ * Copyright 2008-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"
+
+#ifdef CAMELLIA_CCM
+
+/*
+ * Implement CCM-mode AEAD as described in section 5.3 and 5.4 of RFC 5116.
+ * This is the CCM mode as described in NIST SP800-38C, with a 12 byte nonce
+ * and 16 byte checksum.  Multiple buffers of the same type are logically
+ * concatenated.  The underlying enc provider must have a 16-byte block size,
+ * must have a counter-mode encrypt method, and must have a cbc_mac method.
+ *
+ * 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 | 0xCC)
+ *
+ * Again as required by the CCM specification, SIGN_DATA is processed before
+ * DATA for the purpose of checksumming.
+ */
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+unsigned int
+krb5int_dk_ccm_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.3 */
+        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;
+        break;
+    default:
+        assert(0 && "invalid cryptotype passed to ccm_crypto_length");
+        length = ~0;
+        break;
+    }
+
+    return length;
+}
+
+/*
+ * Encode the length of the additional data according to NIST SP800-38C section
+ * A.2.2.  The size of the encoding will be 0, 2, 6, or 10 bytes depending on
+ * the length value.
+ */
+static krb5_error_code
+encode_a_len(krb5_data *a, krb5_ui_8 adata_len)
+{
+    size_t len;
+    unsigned char *p;
+
+    if (adata_len > (1LL << 32))
+        len = 10;
+    else if (adata_len > (1LL << 16) - (1LL << 8))
+        len = 6;
+    else if (adata_len)
+        len = 2;
+    else
+        len = 0;
+
+    if (a->length < len)
+        return KRB5_BAD_MSIZE;
+
+    p = (unsigned char *)a->data;
+
+    switch (len) {
+    case 2:
+       /* Two raw bytes; first byte will not be 0xFF. */
+        p[0] = (adata_len >> 8) & 0xFF;
+        p[1] = (adata_len     ) & 0xFF;
+        break;
+    case 6:
+       /* FF FE followed by four bytes. */
+        p[0] = 0xFF;
+        p[1] = 0xFE;
+        p[2] = (adata_len >> 24) & 0xFF;
+        p[3] = (adata_len >> 16) & 0xFF;
+        p[4] = (adata_len >> 8 ) & 0xFF;
+        p[5] = (adata_len      ) & 0xFF;
+        break;
+    case 10:
+       /* FF FF followed by eight bytes. */
+        p[0] = 0xFF;
+        p[1] = 0xFF;
+        p[2] = (adata_len >> 56) & 0xFF;
+        p[3] = (adata_len >> 48) & 0xFF;
+        p[4] = (adata_len >> 40) & 0xFF;
+        p[5] = (adata_len >> 32) & 0xFF;
+        p[6] = (adata_len >> 24) & 0xFF;
+        p[7] = (adata_len >> 16) & 0xFF;
+        p[8] = (adata_len >> 8 ) & 0xFF;
+        p[9] = (adata_len      ) & 0xFF;
+        break;
+    }
+
+    a->length = len;
+
+    return 0;
+}
+
+/*
+ * Encode the first 16-byte block of CBC-MAC input according to NIST SP800-38C
+ * section A.2.1.  n (the nonce length) is given by nonce->length.
+ */
+static krb5_error_code
+format_B0(krb5_data *B0,            /* B0 */
+          krb5_data *nonce,         /* N */
+          size_t trailer_len,       /* t */
+          krb5_ui_8 adata_len,      /* a */
+          krb5_ui_8 payload_len)    /* Q */
+{
+    unsigned char flags;
+    unsigned char *p;
+    krb5_octet q, i = 0;
+
+    if (B0->length != 16)
+        return KRB5_BAD_MSIZE;
+
+    /* Section A.1: Length Requirements */
+
+    /* t is an element of {4, 6, 8, 10, 12, 14, 16}. */
+    if (trailer_len % 2 ||
+        (trailer_len < 4 || trailer_len > 16))
+        return KRB5_BAD_MSIZE;
+
+    /* n is an element of {7, 8, 9, 10, 11, 12, 13}. */
+    if (nonce->length < 7 || nonce->length > 13)
+        return KRB5_BAD_MSIZE;
+
+    q = 15 - nonce->length;
+
+    /* P consists of fewer than 2^(8q) octets. */
+    if (payload_len >= (1UL << (8 * q)))
+        return KRB5_BAD_MSIZE;
+
+    /* Encode the flags octet. */
+    flags = q - 1;
+    flags |= (((trailer_len - 2) / 2) << 3);
+    if (adata_len != 0)
+        flags |= (1 << 6);
+
+    p = (unsigned char *)B0->data;
+    p[i++] = flags;
+
+    /* Next comes the nonce (n bytes). */
+    memcpy(&p[i], nonce->data, nonce->length);
+    i += nonce->length;
+
+    /* The final q bytes are the payload length. */
+    for (; i < B0->length; i++) {
+        register krb5_octet s;
+
+        s = (q - (i - nonce->length)) * 8;
+
+        p[i] = (payload_len >> s) & 0xFF;
+    }
+
+    return 0;
+}
+
+/*
+ * Encode the initial counter block according to NIST SP800-38C section A.3.
+ * The counter value may be chained across krb5_k_encrypt invocations via the
+ * cipher_state parameter; otherwise it begins at 0.
+ */
+static krb5_error_code
+format_Ctr0(krb5_data *counter, const krb5_data *nonce, const krb5_data *state,
+            unsigned int n)
+{
+    krb5_octet q; /* counter length */
+
+    assert(n >= 7 && n <= 13);
+
+    /* First byte is q-1 in the lowest three bits. */
+    q = 15 - n;
+    counter->data[0] = q - 1;
+    /* Next comes the nonce (n bytes). */
+    memcpy(&counter->data[1], nonce->data, n);
+
+    /* Finally, the counter value. */
+    if (state != NULL)
+        memcpy(&counter->data[1 + n], state->data, q);
+    else
+        memset(&counter->data[1 + n], 0, q);
+
+    return 0;
+}
+
+/* Return true if the payload length is valid given the nonce length n. */
+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 int nblocks, maxblocks;
+    krb5_octet q;
+
+    assert(n >= 7 && n <= 13);
+
+    q = 15 - n;
+
+    maxblocks = (1U << (8 * q)) - 1 /* tag */;
+
+    nblocks = (payload_len + block_size - 1) / block_size;
+
+    return (nblocks <= maxblocks);
+}
+
+/* Encrypt and authenticate data according to NIST SP800-38C section 6.1. */
+static krb5_error_code
+ccm_encrypt(const struct krb5_keytypes *ktp, krb5_key kc,
+           const krb5_data *state, krb5_crypto_iov *data, size_t num_data)
+{
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer, *sign_data = NULL, cksum;
+    size_t i, num_sign_data = 0;
+    unsigned int header_len;
+    unsigned int trailer_len;
+    size_t payload_len = 0;
+    size_t adata_len = 0;
+    char adata_len_buf[6];
+    unsigned char B0[16], Ctr[16];
+    krb5_data counter = make_data(Ctr, sizeof(Ctr));
+
+    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:
+            payload_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, payload_len)) {
+        ret = KRB5_BAD_MSIZE;
+        goto cleanup;
+    }
+
+    header->data.length = header_len;
+    trailer->data.length = trailer_len;
+
+    /* Choose a random nonce. */
+    ret = krb5_c_random_make_octets(NULL, &header->data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Encode the first counter block. */
+    ret = format_Ctr0(&counter, &header->data, state, header_len);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Create a list of CBC-MAC input blocks. */
+    sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+    if (sign_data == NULL)
+        goto cleanup;
+
+    /* Format the initial control/nonce block. */
+    sign_data[0].flags = KRB5_CRYPTO_TYPE_HEADER;
+    sign_data[0].data = make_data(B0, sizeof(B0));
+    ret = format_B0(&sign_data[0].data, &header->data, trailer_len,
+                    (krb5_ui_8)adata_len, (krb5_ui_8)payload_len);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Format the length of associated data. */
+    sign_data[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+    sign_data[1].data = make_data(adata_len_buf, sizeof(adata_len_buf));
+    ret = encode_a_len(&sign_data[1].data, (krb5_ui_8)adata_len);
+    if (ret != 0)
+        goto cleanup;
+    num_sign_data = 2;
+
+    /* 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];
+    }
+
+    assert(ktp->enc->encrypt != NULL);
+    assert(ktp->enc->cbc_mac != NULL);
+
+    /* Make checksum and place in trailer. */
+    ret = ktp->enc->cbc_mac(kc, sign_data, num_sign_data, NULL,
+                           &trailer->data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Encrypt checksum in trailer using the first counter block. */
+    cksum.flags = KRB5_CRYPTO_TYPE_DATA;
+    cksum.data = trailer->data;
+    ret = ktp->enc->encrypt(kc, &counter, &cksum, 1);
+    if (ret != 0)
+       goto cleanup;
+
+    /* Encrypt everything but B0 (header) in subsequent counter blocks. */
+    ret = ktp->enc->encrypt(kc, &counter, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Store the counter value as cipher state.  Subsequent encryptions will
+     * generate a fresh nonce. */
+    if (state != NULL)
+        memcpy(state->data, counter.data + 1 + header_len, 15 - header_len);
+
+cleanup:
+    free(sign_data);
+    return ret;
+}
+
+/* Derive an encryption key based on usage and CCM-encrypt data. */
+krb5_error_code
+krb5int_dk_ccm_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] = 0xCC;
+
+    ret = krb5int_derive_key(ktp->enc, key, &kc, &d1, DERIVE_SP800_108_CMAC);
+    if (ret != 0)
+        return ret;
+
+    ret = ccm_encrypt(ktp, kc, state, data, num_data);
+
+    krb5_k_free_key(NULL, kc);
+
+    return ret;
+}
+
+/* Decrypt and verify data according to NIST SP800-38C section 6.2. */
+static krb5_error_code
+ccm_decrypt(const struct krb5_keytypes *ktp, krb5_key kc,
+           const krb5_data *state, krb5_crypto_iov *data, size_t num_data)
+{
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer, *sign_data = NULL, got_cksum;
+    size_t i, num_sign_data = 0;
+    unsigned int header_len;
+    unsigned int trailer_len;
+    size_t adata_len = 0;
+    size_t payload_len = 0;
+    char adata_len_buf[6];
+    unsigned char B0[16], Ctr[16];
+    krb5_data made_cksum = empty_data();
+    krb5_data counter = make_data(Ctr, sizeof(Ctr));
+
+    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:
+            payload_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, payload_len)) {
+        ret = KRB5_BAD_MSIZE;
+        goto cleanup;
+    }
+
+    /* Encode the first counter block. */
+    ret = format_Ctr0(&counter, &header->data, state, header_len);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Create a list of CBC-MAC input blocks. */
+    sign_data = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+    if (sign_data == NULL)
+        goto cleanup;
+
+    /* Format the initial control/nonce block. */
+    sign_data[0].flags = KRB5_CRYPTO_TYPE_HEADER;
+    sign_data[0].data = make_data(B0, sizeof(B0));
+    ret = format_B0(&sign_data[0].data, &header->data, trailer_len,
+                    (krb5_ui_8)adata_len, (krb5_ui_8)payload_len);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Format the length of associated data. */
+    sign_data[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+    sign_data[1].data = make_data(adata_len_buf, sizeof(adata_len_buf));
+    ret = encode_a_len(&sign_data[1].data, (krb5_ui_8)adata_len);
+    if (ret != 0)
+        goto cleanup;
+    num_sign_data = 2;
+
+    assert(ktp->enc->decrypt != NULL);
+    assert(ktp->enc->cbc_mac != NULL);
+
+    made_cksum.data = k5alloc(trailer_len, &ret);
+    if (made_cksum.data == NULL)
+        goto cleanup;
+    made_cksum.length = trailer_len;
+
+    /* Decrypt checksum from trailer using the first counter block. */
+    got_cksum.flags = KRB5_CRYPTO_TYPE_DATA;
+    got_cksum.data = trailer->data;
+    ret = ktp->enc->decrypt(kc, &counter, &got_cksum, 1);
+    if (ret != 0)
+       goto cleanup;
+
+    /* Decrypt everything but B0 (header) in subsequent counter blocks. */
+    ret = ktp->enc->decrypt(kc, &counter, data, num_data);
+    if (ret != 0)
+        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];
+    }
+
+    /* Calculate CBC-MAC for comparison (including B0). */
+    ret = ktp->enc->cbc_mac(kc, sign_data, num_sign_data, NULL, &made_cksum);
+    if (ret != 0)
+        goto cleanup;
+
+    if (made_cksum.length != trailer->data.length ||
+        memcmp(made_cksum.data, trailer->data.data,
+              trailer->data.length) != 0) {
+        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+        goto cleanup;
+    }
+
+    /* Store the counter value as cipher state.  Subsequent encryptions will
+     * generate a fresh nonce. */
+    if (state != NULL)
+        memcpy(state->data, counter.data + 1 + header_len, 15 - header_len);
+
+cleanup:
+    free(made_cksum.data);
+    free(sign_data);
+
+    return ret;
+}
+
+/* Derive an encryption key based on usage and CCM-decrypt data. */
+krb5_error_code
+krb5int_dk_ccm_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] = 0xCC;
+
+    ret = krb5int_derive_key(ktp->enc, key, &kc, &d1, DERIVE_SP800_108_CMAC);
+    if (ret != 0)
+        return ret;
+
+    ret = ccm_decrypt(ktp, kc, state, data, num_data);
+
+    krb5_k_free_key(NULL, kc);
+
+    return ret;
+}
+
+krb5_error_code
+krb5int_dk_ccm_init_state(const struct krb5_keytypes *ktp,
+                          const krb5_keyblock *key, krb5_keyusage usage,
+                          krb5_data *out_state)
+{
+    unsigned int header_len;
+
+    /* The cipher state is the q-byte block counter value. */
+    header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+    return alloc_data(out_state, 15 - header_len);
+}
+
+void
+krb5int_dk_ccm_free_state(const struct krb5_keytypes *ktp,
+                          krb5_data *state)
+{
+    free(state->data);
+    state->data = NULL;
+    state->length = 0;
+}
+
+#endif /* CAMELLIA_CCM */
index 4c7206c2a20961398e0093f8658ff48b6df797bf..12ef67a01700796ac54454afc94f32403c78d24a 100644 (file)
@@ -87,7 +87,8 @@ krb5int_dk_string_to_key(const struct krb5_keytypes *ktp,
     indata.length = kerberos_len;
     indata.data = (char *) kerberos;
 
-    ret = krb5int_derive_keyblock(enc, foldkey, keyblock, &indata);
+    ret = krb5int_derive_keyblock(enc, foldkey, keyblock, &indata,
+                                  DERIVE_RFC3961);
     if (ret != 0)
         memset(keyblock->contents, 0, keyblock->length);
 
@@ -103,18 +104,18 @@ cleanup:
 #define DEFAULT_ITERATION_COUNT         4096 /* was 0xb000L in earlier drafts */
 #define MAX_ITERATION_COUNT             0x1000000L
 
-krb5_error_code
-krb5int_aes_string_to_key(const struct krb5_keytypes *ktp,
-                          const krb5_data *string,
-                          const krb5_data *salt,
-                          const krb5_data *params,
-                          krb5_keyblock *key)
+static krb5_error_code
+pbkdf2_string_to_key(const struct krb5_keytypes *ktp, const krb5_data *string,
+                     const krb5_data *salt, const krb5_data *pepper,
+                     const krb5_data *params, krb5_keyblock *key,
+                     enum deriv_alg deriv_alg)
 {
     unsigned long iter_count;
     krb5_data out;
     static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
     krb5_key tempkey = NULL;
     krb5_error_code err;
+    krb5_data sandp = empty_data();
 
     if (params) {
         unsigned char *p = (unsigned char *) params->data;
@@ -142,6 +143,18 @@ krb5int_aes_string_to_key(const struct krb5_keytypes *ktp,
     if (out.length != 16 && out.length != 32)
         return KRB5_CRYPTO_INTERNAL;
 
+    if (pepper != NULL) {
+        err = alloc_data(&sandp, pepper->length + 1 + salt->length);
+        if (err)
+            return err;
+
+        memcpy(sandp.data, pepper->data, pepper->length);
+        sandp.data[pepper->length] = '\0';
+        memcpy(&sandp.data[pepper->length + 1], salt->data, salt->length);
+
+        salt = &sandp;
+    }
+
     err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt);
     if (err)
         goto cleanup;
@@ -150,11 +163,39 @@ krb5int_aes_string_to_key(const struct krb5_keytypes *ktp,
     if (err)
         goto cleanup;
 
-    err = krb5int_derive_keyblock(ktp->enc, tempkey, key, &usage);
+    err = krb5int_derive_keyblock(ktp->enc, tempkey, key, &usage, deriv_alg);
 
 cleanup:
+    if (sandp.data)
+        free(sandp.data);
     if (err)
         memset (out.data, 0, out.length);
     krb5_k_free_key (NULL, tempkey);
     return err;
 }
+
+krb5_error_code
+krb5int_aes_string_to_key(const struct krb5_keytypes *ktp,
+                          const krb5_data *string,
+                          const krb5_data *salt,
+                          const krb5_data *params,
+                          krb5_keyblock *key)
+{
+    return pbkdf2_string_to_key(ktp, string, salt, NULL, params, key,
+                                DERIVE_RFC3961);
+}
+
+#ifdef CAMELLIA_CCM
+krb5_error_code
+krb5int_camellia_ccm_string_to_key(const struct krb5_keytypes *ktp,
+                                   const krb5_data *string,
+                                   const krb5_data *salt,
+                                   const krb5_data *params,
+                                   krb5_keyblock *key)
+{
+    krb5_data pepper = string2data(ktp->name);
+
+    return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key,
+                                DERIVE_SP800_108_CMAC);
+}
+#endif
index bd0e8964d3ee47c47ae9bd637c895cc5d385dfde..7a8d6f198c079d8b5a70623f0204574fb05c2b36 100644 (file)
@@ -50,6 +50,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
       krb5int_des_string_to_key,
       krb5int_des_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_RSA_MD5,
       ETYPE_WEAK },
     { ENCTYPE_DES_CBC_MD4,
@@ -59,6 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
       krb5int_des_string_to_key,
       krb5int_des_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_RSA_MD4,
       ETYPE_WEAK },
     { ENCTYPE_DES_CBC_MD5,
@@ -68,6 +70,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
       krb5int_des_string_to_key,
       krb5int_des_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_RSA_MD5,
       ETYPE_WEAK },
     { ENCTYPE_DES_CBC_RAW,
@@ -77,6 +80,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt,
       krb5int_des_string_to_key,
       krb5int_des_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       0,
       ETYPE_WEAK },
     { ENCTYPE_DES3_CBC_RAW,
@@ -86,6 +90,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt,
       krb5int_dk_string_to_key,
       NULL, /*PRF*/
+      krb5int_init_state_enc, krb5int_free_state_enc,
       0,
       ETYPE_WEAK },
 
@@ -97,6 +102,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
       krb5int_dk_string_to_key,
       krb5int_dk_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_HMAC_SHA1_DES3,
       0 /*flags*/ },
 
@@ -107,6 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
       krb5int_dk_string_to_key,
       NULL, /*PRF*/
+      krb5int_init_state_enc, krb5int_free_state_enc,
       0,
       ETYPE_WEAK },
     { ENCTYPE_ARCFOUR_HMAC,
@@ -118,6 +125,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt,
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
       krb5int_arcfour_prf, /*PRF*/
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
       0 /*flags*/ },
     { ENCTYPE_ARCFOUR_HMAC_EXP,
@@ -129,6 +137,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt,
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
       krb5int_arcfour_prf, /*PRF*/
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
       ETYPE_WEAK
     },
@@ -141,6 +150,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
       krb5int_aes_string_to_key,
       krb5int_dk_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_HMAC_SHA1_96_AES128,
       0 /*flags*/ },
     { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
@@ -151,8 +161,33 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
       krb5int_aes_string_to_key,
       krb5int_dk_prf,
+      krb5int_init_state_enc, krb5int_free_state_enc,
       CKSUMTYPE_HMAC_SHA1_96_AES256,
       0 /*flags*/ },
+#ifdef CAMELLIA_CCM
+    { ENCTYPE_CAMELLIA128_CCM_128,
+      "camellia128-ccm-128", { "camellia128-ccm" },
+      "Camellia-128 CCM mode with 128-bit MAC",
+      &krb5int_enc_camellia128_ctr, NULL,
+      16,
+      krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
+      krb5int_camellia_ccm_string_to_key,
+      krb5int_dk_cmac_prf,
+      krb5int_dk_ccm_init_state, krb5int_dk_ccm_free_state,
+      CKSUMTYPE_CMAC_128_CAMELLIA128,
+      0 /*flags*/ },
+    { ENCTYPE_CAMELLIA256_CCM_128,
+      "camellia256-ccm-128", { "camellia256-ccm" },
+      "Camellia-256 CCM mode with 128-bit MAC",
+      &krb5int_enc_camellia256_ctr, NULL,
+      16,
+      krb5int_dk_ccm_crypto_length, krb5int_dk_ccm_encrypt, krb5int_dk_ccm_decrypt,
+      krb5int_camellia_ccm_string_to_key,
+      krb5int_dk_cmac_prf,
+      krb5int_dk_ccm_init_state, krb5int_dk_ccm_free_state,
+      CKSUMTYPE_CMAC_128_CAMELLIA256,
+      0 /*flags */ },
+#endif /* CAMELLIA_CCM */
 };
 
 const int krb5int_enctypes_length =
index a45a6c7712ebc169da606f8f47098d0f8ebe8f97..70cb7bcae9d9ebd3efc23ac2991e2bee293356d6 100644 (file)
@@ -52,6 +52,14 @@ typedef krb5_error_code (*prf_func)(const struct krb5_keytypes *ktp,
                                     krb5_key key,
                                     const krb5_data *in, krb5_data *out);
 
+typedef krb5_error_code (*init_state_func)(const struct krb5_keytypes *ktp,
+                                           const krb5_keyblock *key,
+                                           krb5_keyusage keyusage,
+                                           krb5_data *out_state);
+
+typedef void (*free_state_func)(const struct krb5_keytypes *ktp,
+                                krb5_data *state);
+
 struct krb5_keytypes {
     krb5_enctype etype;
     char *name;
@@ -65,6 +73,8 @@ struct krb5_keytypes {
     crypt_func decrypt;
     str2key_func str2key;
     prf_func prf;
+    init_state_func init_state;
+    free_state_func free_state;
     krb5_cksumtype required_ctype;
     krb5_flags flags;
 };
@@ -89,4 +99,32 @@ find_enctype(krb5_enctype enctype)
     return &krb5int_enctypes_list[i];
 }
 
+/* This belongs with the declaration of struct krb5_enc_provider... but not
+ * while that's still in k5-int.h. */
+/* Encrypt one block of plaintext in place. */
+static inline krb5_error_code
+encrypt_block(const struct krb5_enc_provider *enc, krb5_key key,
+              krb5_data *block)
+{
+    krb5_crypto_iov iov;
+
+    /* Verify that block is the right length. */
+    if (block->length != enc->block_size)
+        return EINVAL;
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *block;
+    if (enc->cbc_mac != NULL)   /* One-block cbc-mac with no ivec. */
+        return enc->cbc_mac(key, &iov, 1, NULL, block);
+    else                        /* Assume cbc-mode encrypt. */
+        return enc->encrypt(key, 0, &iov, 1);
+}
+
+krb5_error_code
+krb5int_init_state_enc(const struct krb5_keytypes *ktp,
+                       const krb5_keyblock *key, krb5_keyusage keyusage,
+                       krb5_data *out_state);
+
+void
+krb5int_free_state_enc(const struct krb5_keytypes *ktp, krb5_data *state);
+
 #endif
index 4bcb8678d95f8168a507f5355434917d541e6280..a0e1ad6b10c061f4e5f5614901a630d60796cdca 100644 (file)
@@ -14,13 +14,13 @@ DEFS=
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
-STLIBOBJS= des_prf.o dk_prf.o rc4_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)rc4_prf.$(OBJEXT) $(OUTPRE)cmac_prf.$(OBJEXT)
 
 SRCS= $(srcdir)/des_prf.c $(srcdir)/dk_prf.c \
-       $(srcdir)/rc4_prf.c 
+       $(srcdir)/rc4_prf.c  $(srcdir)/cmac_prf.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
diff --git a/src/lib/crypto/krb/prf/cmac_prf.c b/src/lib/crypto/krb/prf/cmac_prf.c
new file mode 100644 (file)
index 0000000..a9ad09a
--- /dev/null
@@ -0,0 +1,69 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prf/cmac_prf.c
+ *
+ * Copyright (C) 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.
+ *
+ *
+ *
+ * This file contains an implementation of the RFC 3961 PRF for
+ *simplified profile enctypes.
+ */
+
+#include "prf_int.h"
+#include <dk.h>
+
+#ifdef CAMELLIA_CCM
+
+krb5_error_code
+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);
+    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;
+
+    /* Derive a key using the PRF constant. */
+    ret = krb5int_derive_key(ktp->enc, key, &kp, &prfconst,
+                             DERIVE_SP800_108_CMAC);
+    if (ret != 0)
+        goto cleanup;
+
+    /* PRF is CMAC of input */
+    ret = krb5int_cmac_checksum(ktp->enc, kp, &iov, 1, out);
+    if (ret != 0)
+        goto cleanup;
+
+cleanup:
+    krb5_k_free_key(NULL, kp);
+    return ret;
+}
+
+#endif /* CAMELLIA_CCM */
index 9851ce774d8fde31ca5d3e3bfbead8adcba088e8..a824e2b572d98d11c584af13d3427ae0c30cf1f4 100644 (file)
@@ -55,7 +55,7 @@ krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
         goto cleanup;
 
     /* Derive a key using the PRF constant. */
-    ret = krb5int_derive_key(ktp->enc, key, &kp, &prfconst);
+    ret = krb5int_derive_key(ktp->enc, key, &kp, &prfconst, DERIVE_RFC3961);
     if (ret != 0)
         goto cleanup;
 
index 865f62ba22cc6756707b61aeb4c9cf53b4e70170..1c98720476df823f245e2c2620cb0c5a830e3e8d 100644 (file)
@@ -43,4 +43,8 @@ krb5_error_code
 krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
                const krb5_data *in, krb5_data *out);
 
+krb5_error_code
+krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key,
+                    const krb5_data *in, krb5_data *out);
+
 #endif  /*PRF_INTERNAL_DEFS*/
index 72f14feaac16ce213829b80b8370a7b27929fe05..adde89b94ec3242e1dffb0e6bc6b9412d08ef9a4 100644 (file)
@@ -10,13 +10,15 @@ DEFS=
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
-STLIBOBJS= aes_rand2key.o des_rand2key.o des3_rand2key.o rc4_rand2key.o
+STLIBOBJS= aes_rand2key.o des_rand2key.o des3_rand2key.o rc4_rand2key.o camellia_rand2key.o
 
 OBJS=   $(OUTPRE)aes_rand2key.$(OBJEXT) $(OUTPRE)des_rand2key.$(OBJEXT) \
-       $(OUTPRE)des3_rand2key.$(OBJEXT) $(OUTPRE)rc4_rand2key.$(OBJEXT)
+       $(OUTPRE)des3_rand2key.$(OBJEXT) $(OUTPRE)rc4_rand2key.$(OBJEXT) \
+       $(OUTPRE)camellia_rand2key.$(OBJEXT)
 
 SRCS= $(srcdir)/aes_rand2key.c $(srcdir)/des_rand2key.c \
-       $(srcdir)/des3_rand2key.c $(srcdir)/rc4_rand2key.c
+       $(srcdir)/des3_rand2key.c $(srcdir)/rc4_rand2key.c \
+       $(srcdir)/camellia_rand2key.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
diff --git a/src/lib/crypto/krb/rand2key/camellia_rand2key.c b/src/lib/crypto/krb/rand2key/camellia_rand2key.c
new file mode 100644 (file)
index 0000000..50e7ef0
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * lib/crypto/krb/rand2key/camellia_rand2key.c
+ *
+ * Copyright (c) 2009
+ * NTT (Nippon Telegraph and Telephone Corporation) . 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 "rand2key.h"
+
+krb5_error_code
+krb5int_camellia_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+    if (key->length != 16 && key->length != 32)
+        return(KRB5_BAD_KEYSIZE);
+    if (randombits->length != key->length)
+        return(KRB5_CRYPTO_INTERNAL);
+
+    key->magic = KV5M_KEYBLOCK;
+
+    memcpy(key->contents, randombits->data, randombits->length);
+
+    return(0);
+}
index 321c45230e4aae92199620876a7b808e620debb2..262d83daf7491cf67e1a99f1770d72752b610c1b 100644 (file)
@@ -14,3 +14,6 @@ krb5int_des3_make_key(const krb5_data *randombits, krb5_keyblock *key);
 
 krb5_error_code
 krb5int_aes_make_key(const krb5_data *randombits, krb5_keyblock *key);
+
+krb5_error_code
+krb5int_camellia_make_key(const krb5_data *randombits, krb5_keyblock *key);
index ef0b2b63ff0e46bb3ea4855c2aa1d081b6b2b38d..4a0bafd8b0fc043e195cde596e84324d8d1adda1 100644 (file)
 #include "k5-int.h"
 #include "etypes.h"
 
+/* Most enctypes delegate cipher state handling to the enc provider by using
+ * this function as their init_state methods. */
+krb5_error_code
+krb5int_init_state_enc(const struct krb5_keytypes *ktp,
+                       const krb5_keyblock *key, krb5_keyusage keyusage,
+                       krb5_data *out_state)
+{
+    return ktp->enc->init_state(key, keyusage, out_state);
+}
+
+void
+krb5int_free_state_enc(const struct krb5_keytypes *ktp, krb5_data *state)
+{
+    (void)ktp->enc->free_state(state);
+}
+
 krb5_error_code KRB5_CALLCONV
 krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
                    krb5_keyusage keyusage, krb5_data *new_state)
@@ -45,7 +61,7 @@ krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
     ktp = find_enctype(key->enctype);
     if (ktp == NULL)
         return KRB5_BAD_ENCTYPE;
-    return ktp->enc->init_state(key, keyusage, new_state);
+    return ktp->init_state(ktp, key, keyusage, new_state);
 }
 
 krb5_error_code KRB5_CALLCONV
@@ -57,5 +73,6 @@ krb5_c_free_state(krb5_context context, const krb5_keyblock *key,
     ktp = find_enctype(key->enctype);
     if (ktp == NULL)
         return KRB5_BAD_ENCTYPE;
-    return ktp->enc->free_state(state);
+    ktp->free_state(ktp, state);
+    return 0;
 }
index ffc824818e20a7fb568086fde078e26fa9229461..114b6c988060041a7a8666550cbec30e680901b0 100644 (file)
@@ -95,3 +95,6 @@ krb5int_MD5Final
 krb5int_aes_decrypt
 krb5int_enc_des3
 krb5int_arcfour_gsscrypt
+krb5int_camellia_cbc_mac
+krb5int_cmac_checksum
+krb5int_enc_camellia128_ctr
diff --git a/src/lib/crypto/openssl/camellia/Makefile.in b/src/lib/crypto/openssl/camellia/Makefile.in
new file mode 100644 (file)
index 0000000..5e36d50
--- /dev/null
@@ -0,0 +1,40 @@
+# Nothing here!  But we can't remove this directory as the build
+# system currently assumes that all modules have the same directory
+# structure.
+
+mydir=lib/crypto/openssl/camellia
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb/dk  -I$(srcdir)/../../../../include
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR=camellia
+##DOS##OBJFILE=..\$(OUTPRE)camellia.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS=
+
+OBJS=
+
+SRCS=
+
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs 
+
+includes:: depend
+
+depend:: $(SRCS)
+
+check:: 
+
+
+clean-unix:: clean-libobjs
+
+clean::
+
+@libobj_frag@
+
diff --git a/src/lib/crypto/openssl/camellia/deps b/src/lib/crypto/openssl/camellia/deps
new file mode 100644 (file)
index 0000000..2feac3c
--- /dev/null
@@ -0,0 +1 @@
+# No dependencies here.
index 0ed82cb0e30b094c6358937ab1f47ae813a1df89..d9c1cdc3c17ab251804eeb7acdf6b17b22f67fca 100644 (file)
@@ -3,6 +3,7 @@ BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
 LOCALINCLUDES = -I$(srcdir)/../des     \
                -I$(srcdir)/../arcfour \
                -I$(srcdir)/../aes      \
+               -I$(srcdir)/../camellia         \
                -I$(srcdir)/../../krb                   \
                -I$(srcdir)/../../krb/rand2key          \
                -I$(srcdir)/.. -I$(srcdir)/.
@@ -19,18 +20,25 @@ STLIBOBJS= \
        des.o   \
        des3.o  \
        rc4.o   \
-       aes.o 
+       aes.o   \
+       camellia_ctr.o
 
 OBJS= \
        $(OUTPRE)des.$(OBJEXT)  \
        $(OUTPRE)des3.$(OBJEXT)         \
        $(OUTPRE)aes.$(OBJEXT)  \
+       $(OUTPRE)aes_ctr.$(OBJEXT)      \
+       $(OUTPRE)camellia.$(OBJEXT)     \
+       $(OUTPRE)camellia_ctr.$(OBJEXT)         \
        $(OUTPRE)rc4.$(OBJEXT)
 
 SRCS= \
        $(srcdir)/des.c         \
        $(srcdir)/des3.c        \
        $(srcdir)/aes.c         \
+       $(srcdir)/aes_ctr.c     \
+       $(srcdir)/camellia.c    \
+       $(srcdir)/camellia_ctr.c\
        $(srcdir)/rc4.c
 
 ##DOS##LIBOBJS = $(OBJS)
diff --git a/src/lib/crypto/openssl/enc_provider/camellia_ctr.c b/src/lib/crypto/openssl/enc_provider/camellia_ctr.c
new file mode 100644 (file)
index 0000000..0b6eee7
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * lib/crypto/openssl/enc_provider/camellia_ctr.c
+ *
+ * Copyright (C) 2003, 2007-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 "enc_provider.h"
+#include "rand2key.h"
+#include "aead.h"
+#include "hash_provider/hash_provider.h"
+#include <openssl/evp.h>
+#include <openssl/camellia.h>
+#include <openssl/modes.h>
+
+#ifdef CAMELLIA_CCM
+#define NUM_BITS 8
+
+static void
+xorblock(unsigned char *out, const unsigned char *in)
+{
+    int z;
+    for (z = 0; z < CAMELLIA_BLOCK_SIZE / 4; z++) {
+        unsigned char *outptr = &out[z * 4];
+        unsigned char *inptr = (unsigned char *)&in[z * 4];
+        /*
+         * Use unaligned accesses.  On x86, this will probably still be faster
+         * than multiple byte accesses for unaligned data, and for aligned data
+         * should be far better.  (One test indicated about 2.4% faster
+         * encryption for 1024-byte messages.)
+         *
+         * If some other CPU has really slow unaligned-word or byte accesses,
+         * perhaps this function (or the load/store helpers?) should test for
+         * alignment first.
+         *
+         * If byte accesses are faster than unaligned words, we may need to
+         * conditionalize on CPU type, as that may be hard to determine
+         * automatically.
+         */
+        store_32_n(load_32_n(outptr) ^ load_32_n(inptr), outptr);
+    }
+}
+
+/*
+ * ivec must be a correctly formatted counter block per SP800-38C A.3
+ */
+static krb5_error_code
+krb5int_camellia_encrypt_ctr(krb5_key key, const krb5_data *ivec,
+                             krb5_crypto_iov *data, size_t num_data)
+{
+    CAMELLIA_KEY enck;
+    unsigned char ctr[CAMELLIA_BLOCK_SIZE];
+    krb5_ui_8 blockno;
+    struct iov_block_state input_pos, output_pos;
+
+    Camellia_set_key(key->keyblock.contents,
+                     NUM_BITS * key->keyblock.length, &enck);
+
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    /* Don't encrypt the header (B0), and use zero instead of IOV padding */
+    input_pos.ignore_header = output_pos.ignore_header = 1;
+    input_pos.pad_to_boundary = output_pos.pad_to_boundary = 1;
+
+    assert(ivec != NULL);
+
+    if (ivec->length != CAMELLIA_BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    memcpy(ctr, ivec->data, CAMELLIA_BLOCK_SIZE);
+
+    for (blockno = 0; ; blockno++) {
+        unsigned char storage[CAMELLIA_BLOCK_SIZE], *block;
+        unsigned char ectr[CAMELLIA_BLOCK_SIZE];
+        unsigned int num = 0;
+
+        if (!krb5int_c_iov_get_block_nocopy(storage, CAMELLIA_BLOCK_SIZE,
+                                            data, num_data, &input_pos,
+                                           &block))
+            break;
+
+        /* We should not need to initialise ectr because we're on a block
+        * boundary. */
+        Camellia_ctr128_encrypt(block, block, CAMELLIA_BLOCK_SIZE, &enck, ctr,
+                               ectr, &num);
+        assert(num == 0);
+        krb5int_c_iov_put_block_nocopy(data, num_data, storage,
+                                      CAMELLIA_BLOCK_SIZE, &output_pos,
+                                      block);
+    }
+
+    if (ivec != NULL)
+        memcpy(ivec->data, ctr, sizeof(ctr));
+
+    return 0;
+}
+
+static krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *iv,
+                        krb5_data *output)
+{
+    CAMELLIA_KEY enck;
+    unsigned char blockY[CAMELLIA_BLOCK_SIZE];
+    struct iov_block_state iov_state;
+
+    if (output->length < CAMELLIA_BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    Camellia_set_key(key->keyblock.contents,
+                     NUM_BITS * key->keyblock.length, &enck);
+
+    if (iv != NULL)
+        memcpy(blockY, iv->data, CAMELLIA_BLOCK_SIZE);
+    else
+        memset(blockY, 0, CAMELLIA_BLOCK_SIZE);
+
+    IOV_BLOCK_STATE_INIT(&iov_state);
+
+    /*
+     * The CCM header may not fit in a block, because it includes a variable
+     * length encoding of the associated data length. This encoding plus the
+     * associated data itself is padded to the block size.
+     */
+    iov_state.include_sign_only = 1;
+    iov_state.pad_to_boundary = 1;
+
+    for (;;) {
+        unsigned char blockB[CAMELLIA_BLOCK_SIZE];
+
+        if (!krb5int_c_iov_get_block(blockB, CAMELLIA_BLOCK_SIZE, data,
+                                    num_data, &iov_state))
+            break;
+
+        xorblock(blockB, blockY);
+
+        Camellia_ecb_encrypt(blockB, blockY, &enck, 1);
+    }
+
+    output->length = CAMELLIA_BLOCK_SIZE;
+    memcpy(output->data, blockY, CAMELLIA_BLOCK_SIZE);
+
+    return 0;
+}
+
+static krb5_error_code
+krb5int_camellia_init_state_ctr (const krb5_keyblock *key, krb5_keyusage usage,
+                                 krb5_data *state)
+{
+    return alloc_data(state, 16);
+}
+
+const struct krb5_enc_provider krb5int_enc_camellia128_ctr = {
+    16,
+    16, 16,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_make_key,
+    krb5int_camellia_init_state_ctr,
+    krb5int_default_free_state,
+    NULL
+};
+
+const struct krb5_enc_provider krb5int_enc_camellia256_ctr = {
+    16,
+    32, 32,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_encrypt_ctr,
+    krb5int_camellia_cbc_mac,
+    krb5int_camellia_make_key,
+    krb5int_camellia_init_state_ctr,
+    krb5int_default_free_state,
+    NULL
+};
+
+#else /* CAMELLIA_CCM */
+
+/* These won't be used, but is still in the export table. */
+
+krb5_error_code
+krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
+                         size_t num_data, const krb5_data *iv,
+                        krb5_data *output)
+{
+    return EINVAL;
+}
+
+const struct krb5_enc_provider krb5int_enc_camellia128_ctr = {
+};
+
+#endif /* CAMELLIA_CCM */
index 8144b6533e3351bed5b54d1226fd6ee21a65d621..e8b552e4116b13ef32a1404ee43200ad43e86219 100644 (file)
@@ -34,3 +34,8 @@ extern const struct krb5_enc_provider krb5int_enc_aes128;
 extern const struct krb5_enc_provider krb5int_enc_aes256;
 extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
 extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
+#ifdef CAMELLIA_CCM
+extern const struct krb5_enc_provider krb5int_enc_camellia128_ctr;
+extern const struct krb5_enc_provider krb5int_enc_camellia256_ctr;
+#endif
+
index c5975f19a6e5904fe0ed4e004757370335104ddd..30ae2efc0764fe85acb6fa82df3a6a7b1b55cfe8 100644 (file)
@@ -432,6 +432,11 @@ krb5int_parse_enctype_list(krb5_context context, char *profstr,
             mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
         } else if (strcasecmp(token, "rc4") == 0) {
             mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list);
+#ifdef CAMELLIA_CCM
+        } else if (strcasecmp(token, "camellia") == 0) {
+            mod_list(ENCTYPE_CAMELLIA256_CCM_128, sel, weak, &list);
+            mod_list(ENCTYPE_CAMELLIA128_CCM_128, sel, weak, &list);
+#endif
         } else if (krb5_string_to_enctype(token, &etype) == 0) {
             /* Set a specific enctype. */
             mod_list(etype, sel, weak, &list);
index f84ffee4fbeabea42e312232585eaa278a88ec6e..5d4ae0e3d95473968220c25d41b80970547deb9d 100644 (file)
@@ -98,6 +98,14 @@ static struct {
         ENCTYPE_DES3_CBC_SHA1, 0 },
       0, 0
     },
+#ifdef CAMELLIA_CCM
+    /* Family with enctype removed */
+    { "camellia -camellia256-ccm-128",
+      { 0 },
+      { ENCTYPE_CAMELLIA128_CCM_128, 0 },
+      { ENCTYPE_CAMELLIA128_CCM_128, 0 }
+    },
+#endif
     /* Enctype followed by two families */
     { "+rc4-hmAC des3 +des",
       { 0 },
index f0276b59aad2c407e7b7e1b457b55d40b948e6ee..1ae02ea10f5d6dcb35506fa13f9ad7b81267f63e 100644 (file)
@@ -263,6 +263,32 @@ set passes {
     }
 }
 
+# Add to above when Camellia-CCM support becomes unconditional.
+#    {
+#      camellia-only
+#      mode=udp
+#      des3_krbtgt=0
+#      {supported_enctypes=camellia256-ccm:normal}
+#      {permitted_enctypes(kdc)=camellia256-ccm}
+#      {permitted_enctypes(slave)=camellia256-ccm}
+#      {permitted_enctypes(client)=camellia256-ccm}
+#      {permitted_enctypes(server)=camellia256-ccm}
+#      {default_tgs_enctypes(kdc)=camellia256-ccm}
+#      {default_tgs_enctypes(slave)=camellia256-ccm}
+#      {default_tgs_enctypes(client)=camellia256-ccm}
+#      {default_tgs_enctypes(server)=camellia256-ccm}
+#      {default_tkt_enctypes(kdc)=camellia256-ccm}
+#      {default_tkt_enctypes(slave)=camellia256-ccm}
+#      {default_tkt_enctypes(client)=camellia256-ccm}
+#      {default_tkt_enctypes(server)=camellia256-ccm}
+#      {allow_weak_crypto(kdc)=false}
+#      {allow_weak_crypto(slave)=false}
+#      {allow_weak_crypto(client)=false}
+#      {allow_weak_crypto(server)=false}
+#      {master_key_type=camellia256-ccm}
+#      {dummy=[verbose -log "Camellia-256 enctype"]}
+#    }
+
 # des.md5-tgt is set as unused, since it won't trigger the error case
 # if SUPPORT_DESMD5 isn't honored.
 
index 0776b1030e4bcc908a6af432a57141d03dd29d82..d11d77b77bb83bd2fccf8794f45aeebf94d7a3c3 100644 (file)
@@ -51,6 +51,7 @@ STOBJLISTS= \
        ../../lib/crypto/@CRYPTO_IMPL@/sha1/OBJS.ST \
        ../../lib/crypto/@CRYPTO_IMPL@/arcfour/OBJS.ST \
        ../../lib/crypto/@CRYPTO_IMPL@/aes/OBJS.ST \
+       ../../lib/crypto/@CRYPTO_IMPL@/camellia/OBJS.ST \
        ../../lib/crypto/krb/yarrow/OBJS.ST \
        ../../lib/crypto/krb/OBJS.ST \
        ../../lib/crypto/@CRYPTO_IMPL@/OBJS.ST \
index d88086274bf4aa3dfae6d8c022e9cb746271acff..dbac7178138d900b05b631277e52c3ad5147c0e3 100644 (file)
@@ -1013,6 +1013,17 @@ _passes = [
                         'supported_enctypes' : 'aes128-cts:normal',
                         'master_key_type' : 'aes128-cts'}}}}),
 
+    # Exercise the camellia256-ccm enctype.
+# Enable when Camellia-CCM support becomes unconditional.
+#    ('camellia256', None,
+#      {'all' : {'libdefaults' : {
+#                    'default_tgs_enctypes' : 'camellia256-ccm',
+#                    'default_tkt_enctypes' : 'camellia256-ccm',
+#                    'permitted_enctypes' : 'camellia256-ccm'}}},
+#      {'master' : {'realms' : {'$realm' : {
+#                        'supported_enctypes' : 'camellia256-ccm:normal',
+#                        'master_key_type' : 'camellia256-ccm'}}}}),
+
     # Test a setup with modern principal keys but an old TGT key.
     ('aes256.destgt', 'des-cbc-crc:normal',
      {'all' : {'libdefaults' : {'allow_weak_crypto' : 'true'}}},
index d0478a070c67f33592e58db665501a32852dd702..f260eceeab57e546eea4481cfdac63f4abc6f8cb 100644 (file)
@@ -93,6 +93,14 @@ enctype_toString(const void * data, khm_size cbdata,
         resid = IDS_ETYPE_AES256_CTS_HMAC_SHA1_96;
         break;
 
+    case ENCTYPE_CAMELLIA128_CCM_128:
+        resid = IDS_ETYPE_CAMELLIA128_CCM_128;
+        break;
+
+    case ENCTYPE_CAMELLIA256_CCM_128:
+        resid = IDS_ETYPE_CAMELLIA256_CCM_128;
+        break;
+
     case ENCTYPE_ARCFOUR_HMAC:
         resid = IDS_ETYPE_ARCFOUR_HMAC;
         break;
index bcf837587fbada53f12f9af9ea6378cb4ba7d71d..a98064e43aedb54f65700ac7abb76fc9aa2a32d2 100644 (file)
@@ -364,6 +364,8 @@ BEGIN
     IDS_ETYPE_DES3_CBC_SHA1 "DES3-CBC-SHA1"
     IDS_ETYPE_AES128_CTS_HMAC_SHA1_96 "AES128_CTS-HMAC-SHA1_96"
     IDS_ETYPE_AES256_CTS_HMAC_SHA1_96 "AES256_CTS-HMAC-SHA1_96"
+    IDS_ETYPE_CAMELLIA128_CCM_128 "CAMELLIA128_CCM-128"
+    IDS_ETYPE_CAMELLIA256_CCM_128 "CAMELLIA256_CCM-128"
     IDS_ETYPE_ARCFOUR_HMAC  "RC4-HMAC-NT"
     IDS_ETYPE_ARCFOUR_HMAC_EXP "RC4-HMAC-NT-EXP"
     IDS_ETYPE_UNKNOWN       "(Unknown)"