From: Greg Hudson Date: Tue, 7 Sep 2010 17:54:15 +0000 (+0000) Subject: Merge the camellia-ccm branch to trunk. Since there are no IANA X-Git-Tag: krb5-1.9-beta1~105 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=140e24e9149eabe8793d439a7d386c78ecb00fab;p=krb5.git Merge the camellia-ccm branch to trunk. Since there are no IANA 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 --- diff --git a/src/configure.in b/src/configure.in index 1d86f9770..ec5672def 100644 --- a/src/configure.in +++ b/src/configure.in @@ -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 diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 4b2fdd25d..efffa3b5e 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -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; diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in index fa12e19c7..a05f086e7 100644 --- a/src/lib/crypto/Makefile.in +++ b/src/lib/crypto/Makefile.in @@ -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 diff --git a/src/lib/crypto/builtin/Makefile.in b/src/lib/crypto/builtin/Makefile.in index a65f64df9..4e7e0cd87 100644 --- a/src/lib/crypto/builtin/Makefile.in +++ b/src/lib/crypto/builtin/Makefile.in @@ -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 index 000000000..32cbd5026 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/Makefile.in @@ -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 index 000000000..1446d779e --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia-gen.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + */ +#include +#include +#include +#include +#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 index 000000000..57b2e3642 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia.c @@ -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 +#include + +#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 index 000000000..a2afc62ea --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia.h @@ -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 index 000000000..4c8d393a5 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/deps @@ -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 diff --git a/src/lib/crypto/builtin/des/d3_aead.c b/src/lib/crypto/builtin/des/d3_aead.c index 4052a4058..182f631e5 100644 --- a/src/lib/crypto/builtin/des/d3_aead.c +++ b/src/lib/crypto/builtin/des/d3_aead.c @@ -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) { diff --git a/src/lib/crypto/builtin/des/f_aead.c b/src/lib/crypto/builtin/des/f_aead.c index bb3982d1b..34eee2cbd 100644 --- a/src/lib/crypto/builtin/des/f_aead.c +++ b/src/lib/crypto/builtin/des/f_aead.c @@ -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; diff --git a/src/lib/crypto/builtin/enc_provider/Makefile.in b/src/lib/crypto/builtin/enc_provider/Makefile.in index 40e42ef6e..f3d4a0b2c 100644 --- a/src/lib/crypto/builtin/enc_provider/Makefile.in +++ b/src/lib/crypto/builtin/enc_provider/Makefile.in @@ -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) diff --git a/src/lib/crypto/builtin/enc_provider/aes.c b/src/lib/crypto/builtin/enc_provider/aes.c index 9d2c5d4ff..682a0ee22 100644 --- a/src/lib/crypto/builtin/enc_provider/aes.c +++ b/src/lib/crypto/builtin/enc_provider/aes.c @@ -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 index 000000000..8171ab651 --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/camellia_ctr.c @@ -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 +#include + +#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 */ diff --git a/src/lib/crypto/builtin/enc_provider/enc_provider.h b/src/lib/crypto/builtin/enc_provider/enc_provider.h index 8144b6533..39175d1b9 100644 --- a/src/lib/crypto/builtin/enc_provider/enc_provider.h +++ b/src/lib/crypto/builtin/enc_provider/enc_provider.h @@ -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 diff --git a/src/lib/crypto/crypto_tests/Makefile.in b/src/lib/crypto/crypto_tests/Makefile.in index c92cc7e8d..a0cbb1d1b 100644 --- a/src/lib/crypto/crypto_tests/Makefile.in +++ b/src/lib/crypto/crypto_tests/Makefile.in @@ -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 index 000000000..e6ebe8a81 --- /dev/null +++ b/src/lib/crypto/crypto_tests/camellia-expect-vt.txt @@ -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 index 000000000..8ea8c4660 --- /dev/null +++ b/src/lib/crypto/crypto_tests/camellia-test.c @@ -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 +#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 index 000000000..e3827ec52 --- /dev/null +++ b/src/lib/crypto/crypto_tests/t_camellia_ccm.c @@ -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 + * ./t_camellia_ccm -gc + * ./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 index 000000000..139372c1c --- /dev/null +++ b/src/lib/crypto/crypto_tests/t_cmac.c @@ -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; +} diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c index aa6c4af2d..c2d2be869 100644 --- a/src/lib/crypto/crypto_tests/t_encrypt.c +++ b/src/lib/crypto/crypto_tests/t_encrypt.c @@ -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 }; diff --git a/src/lib/crypto/crypto_tests/t_short.c b/src/lib/crypto/crypto_tests/t_short.c index 90f15b8a8..9b1b630fc 100644 --- a/src/lib/crypto/crypto_tests/t_short.c +++ b/src/lib/crypto/crypto_tests/t_short.c @@ -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 index 000000000..d441e66f3 --- /dev/null +++ b/src/lib/crypto/crypto_tests/t_str2key.c @@ -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; +} diff --git a/src/lib/crypto/crypto_tests/vectors.c b/src/lib/crypto/crypto_tests/vectors.c index a6f1bbe78..f984a1788 100644 --- a/src/lib/crypto/crypto_tests/vectors.c +++ b/src/lib/crypto/crypto_tests/vectors.c @@ -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; } diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in index 9e019115f..119441aab 100644 --- a/src/lib/crypto/krb/Makefile.in +++ b/src/lib/crypto/krb/Makefile.in @@ -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) diff --git a/src/lib/crypto/krb/aead.c b/src/lib/crypto/krb/aead.c index c1f8ccd9e..3d9111abb 100644 --- a/src/lib/crypto/krb/aead.c +++ b/src/lib/crypto/krb/aead.c @@ -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, diff --git a/src/lib/crypto/krb/aead.h b/src/lib/crypto/krb/aead.h index df54a05d3..5cc94f449 100644 --- a/src/lib/crypto/krb/aead.h +++ b/src/lib/crypto/krb/aead.h @@ -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); } diff --git a/src/lib/crypto/krb/checksum/Makefile.in b/src/lib/crypto/krb/checksum/Makefile.in index 61b41f252..826afd189 100644 --- a/src/lib/crypto/krb/checksum/Makefile.in +++ b/src/lib/crypto/krb/checksum/Makefile.in @@ -10,12 +10,14 @@ DEFS= PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -STLIBOBJS= cbc.o confounder.o hmac_md5.o unkeyed.o +STLIBOBJS= cbc.o cmac.o confounder.o hmac_md5.o unkeyed.o -OBJS= $(OUTPRE)cbc.$(OBJEXT) $(OUTPRE)confounder.$(OBJEXT) \ - $(OUTPRE)hmac_md5.$(OBJEXT) $(OUTPRE)unkeyed.$(OBJEXT) +OBJS= $(OUTPRE)cbc.$(OBJEXT) $(OUTPRE)cmac.$(OBJECT) \ + $(OUTPRE)confounder.$(OBJEXT) $(OUTPRE)hmac_md5.$(OBJEXT) \ + $(OUTPRE)unkeyed.$(OBJEXT) -SRCS= $(srcdir)/cbc.c $(srcdir)/confounder.c $(srcdir)/hmac_md5.c \ +SRCS= $(srcdir)/cbc.c $(srcdir)/cmac.c \ + $(srcdir)/confounder.c $(srcdir)/hmac_md5.c \ $(srcdir)/unkeyed.c ##DOS##LIBOBJS = $(OBJS) diff --git a/src/lib/crypto/krb/checksum/cmac.c b/src/lib/crypto/krb/checksum/cmac.c new file mode 100644 index 000000000..a0e249ffd --- /dev/null +++ b/src/lib/crypto/krb/checksum/cmac.c @@ -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 */ diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c index 6e16b4ea8..6744775bc 100644 --- a/src/lib/crypto/krb/cksumtypes.c +++ b/src/lib/crypto/krb/cksumtypes.c @@ -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 = diff --git a/src/lib/crypto/krb/cksumtypes.h b/src/lib/crypto/krb/cksumtypes.h index 8c32f662a..c5eb493f2 100644 --- a/src/lib/crypto/krb/cksumtypes.h +++ b/src/lib/crypto/krb/cksumtypes.h @@ -97,6 +97,12 @@ krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, size_t num_data, krb5_data *output); +krb5_error_code krb5int_cmac_checksum(const struct krb5_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, diff --git a/src/lib/crypto/krb/combine_keys.c b/src/lib/crypto/krb/combine_keys.c index b7435383b..a6cea2eed 100644 --- a/src/lib/crypto/krb/combine_keys.c +++ b/src/lib/crypto/krb/combine_keys.c @@ -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; } diff --git a/src/lib/crypto/krb/dk/Makefile.in b/src/lib/crypto/krb/dk/Makefile.in index 8d658573d..09df6c38d 100644 --- a/src/lib/crypto/krb/dk/Makefile.in +++ b/src/lib/crypto/krb/dk/Makefile.in @@ -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 index 000000000..c2309b7cd --- /dev/null +++ b/src/lib/crypto/krb/dk/checksum_cmac.c @@ -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 */ diff --git a/src/lib/crypto/krb/dk/checksum.c b/src/lib/crypto/krb/dk/checksum_hmac.c similarity index 97% rename from src/lib/crypto/krb/dk/checksum.c rename to src/lib/crypto/krb/dk/checksum_hmac.c index 3dbde1014..ae51aa38f 100644 --- a/src/lib/crypto/krb/dk/checksum.c +++ b/src/lib/crypto/krb/dk/checksum_hmac.c @@ -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; diff --git a/src/lib/crypto/krb/dk/derive.c b/src/lib/crypto/krb/dk/derive.c index 5fd887647..a7ad2e344 100644 --- a/src/lib/crypto/krb/dk/derive.c +++ b/src/lib/crypto/krb/dk/derive.c @@ -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; diff --git a/src/lib/crypto/krb/dk/dk.h b/src/lib/crypto/krb/dk/dk.h index 0fdd98492..fb6df88fa 100644 --- a/src/lib/crypto/krb/dk/dk.h +++ b/src/lib/crypto/krb/dk/dk.h @@ -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); diff --git a/src/lib/crypto/krb/dk/dk_aead.c b/src/lib/crypto/krb/dk/dk_aead.c index f44ae84ad..4e9a7c4cf 100644 --- a/src/lib/crypto/krb/dk/dk_aead.c +++ b/src/lib/crypto/krb/dk/dk_aead.c @@ -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 index 000000000..284e36215 --- /dev/null +++ b/src/lib/crypto/krb/dk/dk_ccm.c @@ -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 */ diff --git a/src/lib/crypto/krb/dk/stringtokey.c b/src/lib/crypto/krb/dk/stringtokey.c index 4c7206c2a..12ef67a01 100644 --- a/src/lib/crypto/krb/dk/stringtokey.c +++ b/src/lib/crypto/krb/dk/stringtokey.c @@ -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 diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c index bd0e8964d..7a8d6f198 100644 --- a/src/lib/crypto/krb/etypes.c +++ b/src/lib/crypto/krb/etypes.c @@ -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 = diff --git a/src/lib/crypto/krb/etypes.h b/src/lib/crypto/krb/etypes.h index a45a6c771..70cb7bcae 100644 --- a/src/lib/crypto/krb/etypes.h +++ b/src/lib/crypto/krb/etypes.h @@ -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 diff --git a/src/lib/crypto/krb/prf/Makefile.in b/src/lib/crypto/krb/prf/Makefile.in index 4bcb8678d..a0e1ad6b1 100644 --- a/src/lib/crypto/krb/prf/Makefile.in +++ b/src/lib/crypto/krb/prf/Makefile.in @@ -14,13 +14,13 @@ DEFS= PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -STLIBOBJS= des_prf.o dk_prf.o rc4_prf.o +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 index 000000000..a9ad09ab2 --- /dev/null +++ b/src/lib/crypto/krb/prf/cmac_prf.c @@ -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 + +#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 */ diff --git a/src/lib/crypto/krb/prf/dk_prf.c b/src/lib/crypto/krb/prf/dk_prf.c index 9851ce774..a824e2b57 100644 --- a/src/lib/crypto/krb/prf/dk_prf.c +++ b/src/lib/crypto/krb/prf/dk_prf.c @@ -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; diff --git a/src/lib/crypto/krb/prf/prf_int.h b/src/lib/crypto/krb/prf/prf_int.h index 865f62ba2..1c9872047 100644 --- a/src/lib/crypto/krb/prf/prf_int.h +++ b/src/lib/crypto/krb/prf/prf_int.h @@ -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*/ diff --git a/src/lib/crypto/krb/rand2key/Makefile.in b/src/lib/crypto/krb/rand2key/Makefile.in index 72f14feaa..adde89b94 100644 --- a/src/lib/crypto/krb/rand2key/Makefile.in +++ b/src/lib/crypto/krb/rand2key/Makefile.in @@ -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 index 000000000..50e7ef015 --- /dev/null +++ b/src/lib/crypto/krb/rand2key/camellia_rand2key.c @@ -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); +} diff --git a/src/lib/crypto/krb/rand2key/rand2key.h b/src/lib/crypto/krb/rand2key/rand2key.h index 321c45230..262d83daf 100644 --- a/src/lib/crypto/krb/rand2key/rand2key.h +++ b/src/lib/crypto/krb/rand2key/rand2key.h @@ -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); diff --git a/src/lib/crypto/krb/state.c b/src/lib/crypto/krb/state.c index ef0b2b63f..4a0bafd8b 100644 --- a/src/lib/crypto/krb/state.c +++ b/src/lib/crypto/krb/state.c @@ -36,6 +36,22 @@ #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; } diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports index ffc824818..114b6c988 100644 --- a/src/lib/crypto/libk5crypto.exports +++ b/src/lib/crypto/libk5crypto.exports @@ -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 index 000000000..5e36d5070 --- /dev/null +++ b/src/lib/crypto/openssl/camellia/Makefile.in @@ -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 index 000000000..2feac3c9d --- /dev/null +++ b/src/lib/crypto/openssl/camellia/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/src/lib/crypto/openssl/enc_provider/Makefile.in b/src/lib/crypto/openssl/enc_provider/Makefile.in index 0ed82cb0e..d9c1cdc3c 100644 --- a/src/lib/crypto/openssl/enc_provider/Makefile.in +++ b/src/lib/crypto/openssl/enc_provider/Makefile.in @@ -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 index 000000000..0b6eee721 --- /dev/null +++ b/src/lib/crypto/openssl/enc_provider/camellia_ctr.c @@ -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 +#include +#include + +#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 */ diff --git a/src/lib/crypto/openssl/enc_provider/enc_provider.h b/src/lib/crypto/openssl/enc_provider/enc_provider.h index 8144b6533..e8b552e41 100644 --- a/src/lib/crypto/openssl/enc_provider/enc_provider.h +++ b/src/lib/crypto/openssl/enc_provider/enc_provider.h @@ -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 + diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index c5975f19a..30ae2efc0 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -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); diff --git a/src/lib/krb5/krb/t_etypes.c b/src/lib/krb5/krb/t_etypes.c index f84ffee4f..5d4ae0e3d 100644 --- a/src/lib/krb5/krb/t_etypes.c +++ b/src/lib/krb5/krb/t_etypes.c @@ -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 }, diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp index f0276b59a..1ae02ea10 100644 --- a/src/tests/dejagnu/config/default.exp +++ b/src/tests/dejagnu/config/default.exp @@ -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. diff --git a/src/util/collected-client-lib/Makefile.in b/src/util/collected-client-lib/Makefile.in index 0776b1030..d11d77b77 100644 --- a/src/util/collected-client-lib/Makefile.in +++ b/src/util/collected-client-lib/Makefile.in @@ -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 \ diff --git a/src/util/k5test.py b/src/util/k5test.py index d88086274..dbac71781 100644 --- a/src/util/k5test.py +++ b/src/util/k5test.py @@ -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'}}}, diff --git a/src/windows/identity/plugins/krb5/datarep.c b/src/windows/identity/plugins/krb5/datarep.c index d0478a070..f260eceea 100644 --- a/src/windows/identity/plugins/krb5/datarep.c +++ b/src/windows/identity/plugins/krb5/datarep.c @@ -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; diff --git a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc index bcf837587..a98064e43 100644 --- a/src/windows/identity/plugins/krb5/lang/en_us/langres.rc +++ b/src/windows/identity/plugins/krb5/lang/en_us/langres.rc @@ -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)"