svn rev #24679: trunk/src/ lib/crypto/ lib/crypto/crypto_tests/ lib/crypto/krb/

ghudson@MIT.EDU ghudson at MIT.EDU
Sat Mar 5 08:31:02 EST 2011


http://src.mit.edu/fisheye/changelog/krb5/?cs=24679
Commit By: ghudson
Log Message:
Flatten lib/crypto/krb, as its seven subdirectories only contained a
few source file each (often only 1-2).



Changed Files:
U   trunk/src/configure.in
U   trunk/src/lib/crypto/Makefile.in
A   trunk/src/lib/crypto/crypto_tests/CRC.pm
A   trunk/src/lib/crypto/crypto_tests/Poly.pm
A   trunk/src/lib/crypto/crypto_tests/crc.pl
U   trunk/src/lib/crypto/krb/Makefile.in
D   trunk/src/lib/crypto/krb/arcfour/
D   trunk/src/lib/crypto/krb/checksum/
A   trunk/src/lib/crypto/krb/checksum_cbc.c
A   trunk/src/lib/crypto/krb/checksum_confounder.c
A   trunk/src/lib/crypto/krb/checksum_dk_cmac.c
A   trunk/src/lib/crypto/krb/checksum_dk_hmac.c
A   trunk/src/lib/crypto/krb/checksum_hmac_md5.c
A   trunk/src/lib/crypto/krb/checksum_unkeyed.c
A   trunk/src/lib/crypto/krb/cmac.c
D   trunk/src/lib/crypto/krb/crc32/
A   trunk/src/lib/crypto/krb/crc32.c
U   trunk/src/lib/crypto/krb/deps
A   trunk/src/lib/crypto/krb/derive.c
D   trunk/src/lib/crypto/krb/dk/
A   trunk/src/lib/crypto/krb/enc_dk_cmac.c
A   trunk/src/lib/crypto/krb/enc_dk_hmac.c
A   trunk/src/lib/crypto/krb/enc_old.c
A   trunk/src/lib/crypto/krb/enc_raw.c
A   trunk/src/lib/crypto/krb/enc_rc4.c
D   trunk/src/lib/crypto/krb/hash_provider/
D   trunk/src/lib/crypto/krb/old/
D   trunk/src/lib/crypto/krb/prf/
A   trunk/src/lib/crypto/krb/prf_cmac.c
A   trunk/src/lib/crypto/krb/prf_des.c
A   trunk/src/lib/crypto/krb/prf_dk.c
A   trunk/src/lib/crypto/krb/prf_rc4.c
D   trunk/src/lib/crypto/krb/raw/
A   trunk/src/lib/crypto/krb/s2k_des.c
A   trunk/src/lib/crypto/krb/s2k_pbkdf2.c
A   trunk/src/lib/crypto/krb/s2k_rc4.c
Modified: trunk/src/configure.in
===================================================================
--- trunk/src/configure.in	2011-03-03 15:21:11 UTC (rev 24678)
+++ trunk/src/configure.in	2011-03-05 13:31:02 UTC (rev 24679)
@@ -1115,17 +1115,14 @@
 
 	lib lib/kdb
 
-	lib/crypto lib/crypto/krb lib/crypto/krb/crc32 lib/crypto/$CRYPTO_IMPL/des
-	lib/crypto/krb/dk lib/crypto/$CRYPTO_IMPL/enc_provider
-	lib/crypto/$CRYPTO_IMPL/hash_provider lib/crypto/krb/checksum
-	lib/crypto/krb/prf lib/crypto/$CRYPTO_IMPL
+	lib/crypto lib/crypto/krb lib/crypto/$CRYPTO_IMPL
+	lib/crypto/$CRYPTO_IMPL/enc_provider
+	lib/crypto/$CRYPTO_IMPL/hash_provider
+	lib/crypto/$CRYPTO_IMPL/des
 	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/$CRYPTO_IMPL/sha2
-	lib/crypto/krb/arcfour
-	lib/crypto/$CRYPTO_IMPL/aes
-	lib/crypto/$CRYPTO_IMPL/camellia lib/crypto/crypto_tests
+        lib/crypto/$CRYPTO_IMPL/sha1 lib/crypto/$CRYPTO_IMPL/sha2
+	lib/crypto/$CRYPTO_IMPL/aes 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

Modified: trunk/src/lib/crypto/Makefile.in
===================================================================
--- trunk/src/lib/crypto/Makefile.in	2011-03-03 15:21:11 UTC (rev 24678)
+++ trunk/src/lib/crypto/Makefile.in	2011-03-05 13:31:02 UTC (rev 24679)
@@ -18,28 +18,18 @@
 LIBFINIFUNC=cryptoint_cleanup_library
 RELDIR=crypto
 
-STOBJLISTS=krb/crc32/OBJS.ST krb/dk/OBJS.ST				\
-	$(CRYPTO_IMPL)/enc_provider/OBJS.ST				\
+STOBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST				\
 	$(CRYPTO_IMPL)/hash_provider/OBJS.ST				\
-	krb/checksum/OBJS.ST krb/prf/OBJS.ST				\
-	krb/old/OBJS.ST krb/raw/OBJS.ST					\
 	$(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST		\
-	$(CRYPTO_IMPL)/sha1/OBJS.ST					\
-	$(CRYPTO_IMPL)/sha2/OBJS.ST					\
-	krb/arcfour/OBJS.ST						\
+	$(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST		\
 	$(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST		\
 	$(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST			\
 	$(CRYPTO_IMPL)/OBJS.ST
 
-SUBDIROBJLISTS=krb/crc32/OBJS.ST krb/dk/OBJS.ST				\
-	$(CRYPTO_IMPL)/enc_provider/OBJS.ST				\
+SUBDIROBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST			\
 	$(CRYPTO_IMPL)/hash_provider/OBJS.ST				\
-	krb/checksum/OBJS.ST krb/prf/OBJS.ST				\
-	krb/old/OBJS.ST krb/raw/OBJS.ST 				\
 	$(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST		\
-	$(CRYPTO_IMPL)/sha1/OBJS.ST					\
-	$(CRYPTO_IMPL)/sha2/OBJS.ST					\
-	krb/arcfour/OBJS.ST						\
+	$(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST		\
 	$(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST		\
 	$(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST			\
 	$(CRYPTO_IMPL)/OBJS.ST
@@ -57,8 +47,8 @@
 SHLIB_RDIRS=$(KRB5_LIBDIR)
 
 ##DOS##LIBNAME=$(OUTPRE)crypto.lib
-##DOS##OBJFILEDEP=$(OUTPRE)crc32.lst $(OUTPRE)prf.lst $(OUTPRE)checksum.lst $(OUTPRE)krb.lst $(OUTPRE)old.lst $(OUTPRE)raw.lst $(OUTPRE)arcfour.lst $(OUTPRE)dk.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst
-##DOS##OBJFILELIST=@$(OUTPRE)crc32.lst @$(OUTPRE)prf.lst @$(OUTPRE)checksum.lst @$(OUTPRE)krb.lst @$(OUTPRE)old.lst @$(OUTPRE)raw.lst @$(OUTPRE)arcfour.lst @$(OUTPRE)dk.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst
+##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst
+##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst
 
 all-unix:: all-liblinks
 install-unix:: install-libs

Copied: trunk/src/lib/crypto/crypto_tests/CRC.pm (from rev 24673, trunk/src/lib/crypto/krb/crc32/CRC.pm)
===================================================================
--- trunk/src/lib/crypto/crypto_tests/CRC.pm	                        (rev 0)
+++ trunk/src/lib/crypto/crypto_tests/CRC.pm	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,156 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+package CRC;
+
+# CRC: implement a CRC using the Poly package (yes this is slow)
+#
+# message M(x) = m_0 * x^0 + m_1 * x^1 + ... + m_(k-1) * x^(k-1)
+# generator P(x) = p_0 * x^0 + p_1 * x^1 + ... + p_n * x^n
+# remainder R(x) = r_0 * x^0 + r_1 * x^1 + ... + r_(n-1) * x^(n-1)
+#
+# R(x) = (x^n * M(x)) % P(x)
+#
+# Note that if F(x) = x^n * M(x) + R(x), then F(x) = 0 mod P(x) .
+#
+# In MIT Kerberos 5, R(x) is taken as the CRC, as opposed to what
+# ISO 3309 does.
+#
+# ISO 3309 adds a precomplement and a postcomplement.
+#
+# The ISO 3309 postcomplement is of the form
+#
+# A(x) = x^0 + x^1 + ... + x^(n-1) .
+#
+# The ISO 3309 precomplement is of the form
+#
+# B(x) = x^k * A(x) .
+#
+# The ISO 3309 FCS is then
+#
+# (x^n * M(x)) % P(x) + B(x) % P(x) + A(x) ,
+#
+# which is equivalent to
+#
+# (x^n * M(x) + B(x)) % P(x) + A(x) .
+#
+# In ISO 3309, the transmitted frame is
+#
+# F'(x) = x^n * M(x) + R(x) + R'(x) + A(x) ,
+#
+# where
+#
+# R'(x) = B(x) % P(x) .
+#
+# Note that this means that if a new remainder is computed over the
+# frame F'(x) (treating F'(x) as the new M(x)), it will be equal to a
+# constant.
+#
+# F'(x) = 0 + R'(x) + A(x) mod P(x) ,
+#
+# then
+#
+# (F'(x) + x^k * A(x)) * x^n
+#
+# = ((R'(x) + A(x)) + x^k * A(x)) * x^n mod P(x)
+#
+# = (x^k * A(x) + A(x) + x^k * A(x)) * x^n mod P(x)
+#
+# = (0 + A(x)) * x^n mod P(x)
+#
+# Note that (A(x) * x^n) % P(x) is a constant, and that this result
+# depends on B(x) being x^k * A(x).
+
+use Carp;
+use Poly;
+
+sub new {
+    my $self = shift;
+    my $class = ref($self) || $self;
+    my %args = @_;
+    $self = {bitsendian => "little"};
+    bless $self, $class;
+    $self->setpoly($args{"Poly"}) if exists $args{"Poly"};
+    $self->bitsendian($args{"bitsendian"})
+	if exists $args{"bitsendian"};
+    $self->{precomp} = $args{precomp} if exists $args{precomp};
+    $self->{postcomp} = $args{postcomp} if exists $args{postcomp};
+    return $self;
+}
+
+sub setpoly {
+    my $self = shift;
+    my($arg) = @_;
+    croak "need a polynomial" if !$arg->isa("Poly");
+    $self->{Poly} = $arg;
+    return $self;
+}
+
+sub crc {
+    my $self = shift;
+    my $msg = Poly->new(@_);
+    my($order, $r, $precomp);
+    $order = $self->{Poly}->order;
+    # B(x) = x^k * precomp
+    $precomp = $self->{precomp} ?
+	$self->{precomp} * Poly->powers2poly(scalar(@_)) : Poly->new;
+    # R(x) = (x^n * M(x)) % P(x)
+    $r = ($msg * Poly->powers2poly($order)) % $self->{Poly};
+    # B(x) % P(x)
+    $r += $precomp % $self->{Poly};
+    $r += $self->{postcomp} if exists $self->{postcomp};
+    return $r;
+}
+
+# endianness of bits of each octet
+#
+# Note that the message is always treated as being sent in big-endian
+# octet order.
+#
+# Usually, the message will be treated as bits being little-endian,
+# since that is the common case for serial implementations that
+# present data in octets; e.g., most UARTs shift octets onto the line
+# in little-endian order, and protocols such as ISO 3309, V.42,
+# etc. treat individual octets as being sent LSB-first.
+
+sub bitsendian {
+    my $self = shift;
+    my($arg) = @_;
+    croak "bad bit endianness" if $arg !~ /big|little/;
+    $self->{bitsendian} = $arg;
+    return $self;
+}
+
+sub crcstring {
+    my $self = shift;
+    my($arg) = @_;
+    my($packstr, @m);
+    {
+	$packstr = "B*", last if $self->{bitsendian} =~ /big/;
+	$packstr = "b*", last if $self->{bitsendian} =~ /little/;
+	croak "bad bit endianness";
+    };
+    @m = split //, unpack $packstr, $arg;
+    return $self->crc(@m);
+}
+
+1;

Copied: trunk/src/lib/crypto/crypto_tests/Poly.pm (from rev 24673, trunk/src/lib/crypto/krb/crc32/Poly.pm)
===================================================================
--- trunk/src/lib/crypto/crypto_tests/Poly.pm	                        (rev 0)
+++ trunk/src/lib/crypto/crypto_tests/Poly.pm	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,182 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+package Poly;
+
+# Poly: implements some basic operations on polynomials in the field
+# of integers (mod 2).
+#
+# The rep is an array of coefficients, highest order term first.
+#
+# This is rather slow at the moment.
+
+use overload
+    '+' => \&add,
+    '-' => \&add,
+    '*' => \&mul,
+    '%' => sub {$_[2] ? mod($_[1], $_[0]) : mod($_[0], $_[1])},
+    '/' => sub { $_[2] ? scalar(div($_[1], $_[0]))
+		     : scalar(div($_[0], $_[1])) },
+    '<=>' => sub {$_[2] ? pcmp($_[1], $_[0]) : pcmp($_[0], $_[1])},
+    '""' => \&str
+;
+
+use Carp;
+
+# doesn't do much beyond normalize and bless
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my(@x) = @_;
+    return bless [norm(@x)], $class;
+}
+
+# stringified P(x)
+sub pretty {
+    my(@x) = @{+shift};
+    my $n = @x;
+    local $_;
+    return "0" if !@x;
+    return join " + ", map {$n--; $_ ? ("x^$n") : ()} @x;
+}
+
+sub print {
+    my $self = shift;
+    print $self->pretty, "\n";
+}
+
+# This assumes normalization.
+sub order {
+    my $self = shift;
+    return $#{$self};
+}
+
+sub str {
+    return overload::StrVal($_[0]);
+}
+
+# strip leading zero coefficients
+sub norm {
+    my(@x) = @_;
+    shift @x while @x && !$x[0];
+    return @x;
+}
+
+# multiply $self by the single term of power $n
+sub multerm {
+    my($self, $n) = @_;
+    return $self->new(@$self, (0) x $n);
+}
+
+# This is really an order comparison; different polys of same order
+# compare equal.  It also assumes prior normalization.
+sub pcmp {
+    my @x = @{+shift};
+    my @y = @{+shift};
+    return @x <=> @y;
+}
+
+# convenience constructor; takes list of non-zero terms
+sub powers2poly
+{
+    my $self = shift;
+    my $poly = $self->new;
+    my $n;
+    foreach $n (@_) {
+	$poly += $one->multerm($n);
+    }
+    return $poly;
+}
+
+sub add {
+    my $self = shift;
+    my @x = @$self;
+    my @y = @{+shift};
+    my @r;
+    unshift @r, (pop @x || 0) ^ (pop @y || 0)
+	while @x || @y;
+    return $self->new(@r);
+}
+
+sub mul {
+    my($self) = shift;
+    my @y = @{+shift};
+    my $r = $self->new;
+    my $power = 0;
+    while (@y) {
+	$r += $self->multerm($power) if pop @y;
+	$power++;
+    }
+    return $r;
+}
+
+sub oldmod {
+    my($self, $div) = @_;
+    my @num = @$self;
+    my @div = @$div;
+    my $r = $self->new(splice @num, 0, @div);
+    do {
+	push @$r, shift @num while @num && $r < $div;
+	$r += $div if $r >= $div;
+    } while @num;
+    return $r;
+}
+
+sub div {
+    my($self, $div) = @_;
+    my $q = $self->new;
+    my $r = $self->new(@$self);
+    my $one = $self->new(1);
+    my ($tp, $power);
+    croak "divide by zero" if !@$div;
+    while ($div <= $r) {
+	$power = 0;
+	$power++ while ($tp = $div->multerm($power)) < $r;
+	$q += $one->multerm($power);
+	$r -= $tp;
+    }
+    return wantarray ? ($q, $r) : $q;
+}
+
+sub mod {
+    (&div)[1];
+}
+
+# bits and octets both big-endian
+sub hex {
+    my @x = @{+shift};
+    my $minwidth = shift || 32;
+    unshift @x, 0 while @x % 8 || @x < $minwidth;
+    return unpack "H*", pack "B*", join "", @x;
+}
+
+# bit-reversal of above
+sub revhex {
+    my @x = @{+shift};
+    my $minwidth = shift || 32;
+    unshift @x, 0 while @x % 8 || @x < $minwidth;
+    return unpack "H*", pack "B*", join "", reverse @x;
+}
+
+$one = Poly->new(1);
+
+1;

Copied: trunk/src/lib/crypto/crypto_tests/crc.pl (from rev 24673, trunk/src/lib/crypto/krb/crc32/crc.pl)
===================================================================
--- trunk/src/lib/crypto/crypto_tests/crc.pl	                        (rev 0)
+++ trunk/src/lib/crypto/crypto_tests/crc.pl	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,111 @@
+# Copyright 2002 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+#   require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+
+use CRC;
+
+print "*** crudely testing polynomial functions ***\n";
+
+$x = Poly->new(1,1,1,1);
+$y = Poly->new(1,1);
+print "x = @{[$x->pretty]}\ny = @{[$y->pretty]}\n";
+$q = $x / $y;
+$r = $x % $y;
+print $x->pretty, " = (", $y->pretty , ") * (", $q->pretty,
+    ") + ", $r->pretty, "\n";
+$q = $y / $x;
+$r = $y % $x;
+print "y / x = @{[$q->pretty]}\ny % x = @{[$r->pretty]}\n";
+
+# ISO 3309 32-bit FCS polynomial
+$fcs32 = Poly->powers2poly(32,26,23,22,16,12,11,10,8,7,5,4,2,1,0);
+print "fcs32 = ", $fcs32->pretty, "\n";
+
+$crc = CRC->new(Poly => $fcs32, bitsendian => "little");
+
+print "\n";
+
+print "*** little endian, no complementation ***\n";
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->revhex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+print "\n";
+
+print "*** little endian, 4 bits, no complementation ***\n";
+for ($i = 0; $i < 16; $i++) {
+    @m = (split //, unpack "b*", pack "C", $i)[0..3];
+    $r = $crc->crc(@m);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->revhex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+print "\n";
+
+print "*** test vectors for t_crc.c, little endian ***\n";
+for ($i = 1; $i <= 4; $i *=2) {
+    for ($j = 0; $j < $i * 8; $j++) {
+	@m = split //, unpack "b*", pack "V", 1 << $j;
+	splice @m, $i * 8;
+	$r = $crc->crc(@m);
+	$m = unpack "H*", pack "b*", join("", @m);
+	print "{HEX, \"$m\", 0x", $r->revhex, "},\n";
+    }
+}
+ at m = ("foo", "test0123456789",
+      "MASSACHVSETTS INSTITVTE OF TECHNOLOGY");
+foreach $m (@m) {
+    $r = $crc->crcstring($m);
+    print "{STR, \"$m\", 0x", $r->revhex, "},\n";
+}
+__END__
+
+print "*** big endian, no complementation ***\n";
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    printf ("%02x: ", $i) if !($i % 8);
+    print ($r->hex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+# all ones polynomial of order 31
+$ones = Poly->new((1) x 32);
+
+print "*** big endian, ISO-3309 style\n";
+$crc = CRC->new(Poly => $fcs32,
+		bitsendian => "little",
+		precomp => $ones,
+		postcomp => $ones);
+for ($i = 0; $i < 256; $i++) {
+    $r = $crc->crcstring(pack "C", $i);
+    print ($r->hex, ($i % 8 == 7) ? "\n" : " ");
+}
+
+for ($i = 0; $i < 0; $i++) {
+    $x = Poly->new((1) x 32, (0) x $i);
+    $y = Poly->new((1) x 32);
+    $f = ($x % $fcs32) + $y;
+    $r = (($f + $x) * Poly->powers2poly(32)) % $fcs32;
+    @out = @$r;
+    unshift @out, 0 while @out < 32;
+    print @out, "\n";
+}

Modified: trunk/src/lib/crypto/krb/Makefile.in
===================================================================
--- trunk/src/lib/crypto/krb/Makefile.in	2011-03-03 15:21:11 UTC (rev 24678)
+++ trunk/src/lib/crypto/krb/Makefile.in	2011-03-05 13:31:02 UTC (rev 24679)
@@ -1,6 +1,5 @@
 mydir=lib$(S)crypto$(S)krb
 BUILDTOP=$(REL)..$(S)..$(S)..
-SUBDIRS= arcfour checksum crc32 dk prf old raw 
 LOCALINCLUDES = -I$(srcdir) -I$(srcdir)/../$(CRYPTO_IMPL)
 RUN_SETUP = @KRB5_RUN_ENV@
 PROG_LIBPATH=-L$(TOPLIBD)
@@ -18,20 +17,34 @@
 	aead.o		 	\
 	block_size.o		\
 	cf2.o 			\
+	checksum_cbc.o		\
+	checksum_confounder.o	\
+	checksum_dk_cmac.o	\
+	checksum_dk_hmac.o	\
+	checksum_hmac_md5.o	\
+	checksum_unkeyed.o	\
 	checksum_length.o	\
 	cksumtype_to_string.o	\
 	cksumtypes.o		\
+	cmac.o			\
 	coll_proof_cksum.o	\
 	combine_keys.o		\
+	crc32.o			\
 	crypto_length.o		\
 	crypto_libinit.o	\
 	default_state.o 	\
 	decrypt.o		\
 	decrypt_iov.o		\
+	derive.o		\
 	encrypt.o		\
 	encrypt_iov.o		\
 	encrypt_length.o	\
 	enctype_util.o		\
+	enc_dk_cmac.o		\
+	enc_dk_hmac.o		\
+	enc_old.o		\
+	enc_raw.o		\
+	enc_rc4.o		\
 	etypes.o		\
 	key.o			\
 	keyblocks.o 		\
@@ -45,9 +58,16 @@
 	nfold.o			\
 	old_api_glue.o		\
 	prf.o			\
+	prf_cmac.o		\
+	prf_des.o		\
+	prf_dk.o		\
+	prf_rc4.o		\
 	prng.o			\
 	prng_$(PRNG_ALG).o	\
 	random_to_key.o		\
+	s2k_des.o		\
+	s2k_pbkdf2.o		\
+	s2k_rc4.o		\
 	state.o 		\
 	string_to_cksumtype.o	\
 	string_to_key.o		\
@@ -64,6 +84,7 @@
 	$(OUTPRE)cksumtypes.$(OBJEXT)		\
 	$(OUTPRE)coll_proof_cksum.$(OBJEXT)	\
 	$(OUTPRE)combine_keys.$(OBJEXT)		\
+	$(OUTPRE)crc_32.$(OBJEXT)		\
 	$(OUTPRE)crypto_length.$(OBJEXT)	\
 	$(OUTPRE)crypto_libinit.$(OBJEXT)	\
 	$(OUTPRE)default_state.$(OBJEXT) 	\
@@ -72,7 +93,12 @@
 	$(OUTPRE)encrypt.$(OBJEXT)		\
 	$(OUTPRE)encrypt_iov.$(OBJEXT)		\
 	$(OUTPRE)encrypt_length.$(OBJEXT)	\
-	$(OUTPRE)enctype_util.$(OBJEXT)	\
+	$(OUTPRE)enctype_util.$(OBJEXT)		\
+	$(OUTPRE)enc_dk_cmac.$(OBJEXT)		\
+	$(OUTPRE)enc_dk_hmac.$(OBJEXT)		\
+	$(OUTPRE)enc_old.$(OBJEXT)		\
+	$(OUTPRE)enc_raw.$(OBJEXT)		\
+	$(OUTPRE)enc_rc4.$(OBJEXT)		\
 	$(OUTPRE)etypes.$(OBJEXT)		\
 	$(OUTPRE)key.$(OBJEXT)			\
 	$(OUTPRE)keyblocks.$(OBJEXT) 		\
@@ -85,10 +111,17 @@
 	$(OUTPRE)mandatory_sumtype.$(OBJEXT)	\
 	$(OUTPRE)nfold.$(OBJEXT)		\
 	$(OUTPRE)old_api_glue.$(OBJEXT)		\
-	$(OUTPRE)prf.$(OBJEXT) 			\
+	$(OUTPRE)prf.$(OBJEXT)			\
+	$(OUTPRE)prf_cmac.$(OBJEXT)		\
+	$(OUTPRE)prf_des.$(OBJEXT)		\
+	$(OUTPRE)prf_dk.$(OBJEXT)		\
+	$(OUTPRE)prf_rc4.$(OBJEXT)		\
 	$(OUTPRE)prng.$(OBJEXT)			\
 	$(OUTPRE)prng_$(PRNG_ALG).$(OBJEXT)	\
 	$(OUTPRE)random_to_key.$(OBJEXT)	\
+	$(OUTPRE)s2k_des.$(OBJEXT)		\
+	$(OUTPRE)s2k_pbkdf2.$(OBJEXT)		\
+	$(OUTPRE)s2k_rc4.$(OBJEXT)		\
 	$(OUTPRE)state.$(OBJEXT) 		\
 	$(OUTPRE)string_to_cksumtype.$(OBJEXT)	\
 	$(OUTPRE)string_to_key.$(OBJEXT)	\
@@ -104,6 +137,7 @@
 	$(srcdir)/cksumtypes.c		\
 	$(srcdir)/coll_proof_cksum.c	\
 	$(srcdir)/combine_keys.c	\
+	$(srcdir)/crc32.c		\
 	$(srcdir)/crypto_length.c	\
 	$(srcdir)/crypto_libinit.c	\
 	$(srcdir)/default_state.c 	\
@@ -113,6 +147,11 @@
 	$(srcdir)/encrypt_iov.c		\
 	$(srcdir)/encrypt_length.c	\
 	$(srcdir)/enctype_util.c	\
+	$(srcdir)/enc_dk_cmac.c		\
+	$(srcdir)/enc_dk_hmac.c		\
+	$(srcdir)/enc_old.c		\
+	$(srcdir)/enc_raw.c		\
+	$(srcdir)/enc_rc4.c		\
 	$(srcdir)/etypes.c		\
 	$(srcdir)/key.c			\
 	$(srcdir)/keyblocks.c 		\
@@ -125,11 +164,18 @@
 	$(srcdir)/mandatory_sumtype.c	\
 	$(srcdir)/nfold.c		\
 	$(srcdir)/old_api_glue.c	\
-	$(srcdir)/prf.c 		\
+	$(srcdir)/prf.c			\
+	$(srcdir)/prf_cmac.c		\
+	$(srcdir)/prf_des.c		\
+	$(srcdir)/prf_dk.c		\
+	$(srcdir)/prf_rc4.c		\
 	$(srcdir)/prng.c 		\
 	$(srcdir)/prng_$(PRNG_ALG).c	\
 	$(srcdir)/cf2.c 		\
 	$(srcdir)/random_to_key.c	\
+	$(srcdir)/s2k_des.c		\
+	$(srcdir)/s2k_pbkdf2.c		\
+	$(srcdir)/s2k_rc4.c		\
 	$(srcdir)/state.c 		\
 	$(srcdir)/string_to_cksumtype.c	\
 	$(srcdir)/string_to_key.c	\
@@ -138,12 +184,6 @@
 	$(srcdir)/verify_checksum.c	\
 	$(srcdir)/verify_checksum_iov.c
 
-STOBJLISTS=arcfour/OBJS.ST checksum/OBJS.ST crc32/OBJS.ST	\
-	dk/OBJS.ST prf/OBJS.ST old/OBJS.ST raw/OBJS.ST OBJS.ST
-
-SUBDIROBJLISTS=arcfour/OBJS.ST checksum/OBJS.ST crc32/OBJS.ST	\
-	dk/OBJS.ST prf/OBJS.ST old/OBJS.ST raw/OBJS.ST
-
 ##DOS##LIBOBJS = $(OBJS)
 
 all-unix:: all-libobjs

Copied: trunk/src/lib/crypto/krb/checksum_cbc.c (from rev 24677, trunk/src/lib/crypto/krb/checksum/cbc.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_cbc.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_cbc.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/checksum/cbc.c
+ *
+ * Copyright (C) 2009 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.
+ *
+ * CBC checksum, which computes the ivec resulting from CBC encryption of the
+ * input.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_cbc_checksum(const struct krb5_cksumtypes *ctp,
+                     krb5_key key, krb5_keyusage usage,
+                     const krb5_crypto_iov *data, size_t num_data,
+                     krb5_data *output)
+{
+    if (ctp->enc->cbc_mac == NULL)
+        return KRB5_CRYPTO_INTERNAL;
+    return ctp->enc->cbc_mac(key, data, num_data, NULL, output);
+}

Copied: trunk/src/lib/crypto/krb/checksum_confounder.c (from rev 24677, trunk/src/lib/crypto/krb/checksum/confounder.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_confounder.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_confounder.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,159 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/checksum/confounder.c
+ *
+ * Copyright (C) 2009 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.
+ *
+ * Confounder checksum implementation, using tokens of the form:
+ *   enc(xorkey, confounder | hash(confounder | data))
+ * where xorkey is the key XOR'd with 0xf0 bytes.
+ */
+
+#include "crypto_int.h"
+
+/* Derive a key by XOR with 0xF0 bytes. */
+static krb5_error_code
+mk_xorkey(krb5_key origkey, krb5_key *xorkey)
+{
+    krb5_error_code retval = 0;
+    unsigned char *xorbytes;
+    krb5_keyblock xorkeyblock;
+    size_t i = 0;
+
+    xorbytes = malloc(origkey->keyblock.length);
+    if (xorbytes == NULL)
+	return ENOMEM;
+    memcpy(xorbytes, origkey->keyblock.contents, origkey->keyblock.length);
+    for (i = 0; i < origkey->keyblock.length; i++)
+        xorbytes[i] ^= 0xf0;
+
+    /* Do a shallow copy here. */
+    xorkeyblock = origkey->keyblock;
+    xorkeyblock.contents = xorbytes;
+
+    retval = krb5_k_create_key(0, &xorkeyblock, xorkey);
+    zapfree(xorbytes, sizeof(xorbytes));
+    return retval;
+}
+
+krb5_error_code
+krb5int_confounder_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 ret;
+    krb5_data conf, hashval;
+    krb5_key xorkey = NULL;
+    krb5_crypto_iov *hash_iov, iov;
+    size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
+
+    /* Partition the output buffer into confounder and hash. */
+    conf = make_data(output->data, blocksize);
+    hashval = make_data(output->data + blocksize, hashsize);
+
+    /* Create the confounder. */
+    ret = krb5_c_random_make_octets(NULL, &conf);
+    if (ret != 0)
+        return ret;
+
+    ret = mk_xorkey(key, &xorkey);
+    if (ret)
+        return ret;
+
+    /* Hash the confounder, then the input data. */
+    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+    if (hash_iov == NULL)
+	goto cleanup;
+    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    hash_iov[0].data = conf;
+    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+    ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
+    if (ret != 0)
+	goto cleanup;
+
+    /* Confounder and hash are in output buffer; encrypt them in place. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *output;
+    ret = ctp->enc->encrypt(xorkey, NULL, &iov, 1);
+
+cleanup:
+    free(hash_iov);
+    krb5_k_free_key(NULL, xorkey);
+    return ret;
+}
+
+krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp,
+                                          krb5_key key, krb5_keyusage usage,
+                                          const krb5_crypto_iov *data,
+                                          size_t num_data,
+                                          const krb5_data *input,
+                                          krb5_boolean *valid)
+{
+    krb5_error_code ret;
+    unsigned char *plaintext = NULL;
+    krb5_key xorkey = NULL;
+    krb5_data computed = empty_data();
+    krb5_crypto_iov *hash_iov = NULL, iov;
+    size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
+
+    plaintext = k5alloc(input->length, &ret);
+    if (plaintext == NULL)
+	return ret;
+
+    ret = mk_xorkey(key, &xorkey);
+    if (ret != 0)
+	goto cleanup;
+
+    /* Decrypt the input checksum. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = make_data(plaintext, input->length);
+    memcpy(plaintext, input->data, input->length);
+    ret = ctp->enc->decrypt(xorkey, NULL, &iov, 1);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Hash the confounder, then the input data. */
+    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+    if (hash_iov == NULL)
+	goto cleanup;
+    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    hash_iov[0].data = make_data(plaintext, blocksize);
+    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+    ret = alloc_data(&computed, hashsize);
+    if (ret != 0)
+	goto cleanup;
+    ret = ctp->hash->hash(hash_iov, num_data + 1, &computed);
+    if (ret != 0)
+	goto cleanup;
+
+    /* Compare the decrypted hash to the computed one. */
+    *valid = (memcmp(plaintext + blocksize, computed.data, hashsize) == 0);
+
+cleanup:
+    zapfree(plaintext, input->length);
+    zapfree(computed.data, hashsize);
+    free(hash_iov);
+    krb5_k_free_key(NULL, xorkey);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/checksum_dk_cmac.c (from rev 24677, trunk/src/lib/crypto/krb/dk/checksum_cmac.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_dk_cmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_dk_cmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,62 @@
+/*
+ * 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 "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+#ifdef CAMELLIA
+
+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 */

Copied: trunk/src/lib/crypto/krb/checksum_dk_hmac.c (from rev 24677, trunk/src/lib/crypto/krb/dk/checksum_hmac.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_dk_hmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_dk_hmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,59 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+krb5_error_code
+krb5int_dk_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_RFC3961);
+    if (ret)
+        return ret;
+
+    /* Hash the data. */
+    ret = krb5int_hmac(ctp->hash, kc, data, num_data, output);
+    if (ret)
+        memset(output->data, 0, output->length);
+
+    krb5_k_free_key(NULL, kc);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/checksum_hmac_md5.c (from rev 24677, trunk/src/lib/crypto/krb/checksum/hmac_md5.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_hmac_md5.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_hmac_md5.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,93 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/checksum/hmac_md5.c
+ *
+ * Copyright (C) 2009 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.
+ *
+ * Microsoft HMAC-MD5 and MD5-HMAC checksums (see RFC 4757):
+ *   HMAC(KS, hash(msusage || input))
+ * KS is HMAC(key, "signaturekey\0") for HMAC-MD5, or just the key for
+ * MD5-HMAC.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code krb5int_hmacmd5_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_keyusage ms_usage;
+    krb5_error_code ret;
+    krb5_keyblock ks, *keyblock;
+    krb5_crypto_iov *hash_iov = NULL, iov;
+    krb5_data ds = empty_data(), hashval = empty_data();
+    char t[4];
+
+    if (key == NULL || key->keyblock.length > ctp->hash->blocksize)
+        return KRB5_BAD_ENCTYPE;
+    if (ctp->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) {
+	/* Compute HMAC(key, "signaturekey\0") to get the signing key ks. */
+        ret = alloc_data(&ds, ctp->hash->hashsize);
+	if (ret != 0)
+	    goto cleanup;
+
+	iov.flags = KRB5_CRYPTO_TYPE_DATA;
+	iov.data = make_data("signaturekey", 13);
+	ret = krb5int_hmac(ctp->hash, key, &iov, 1, &ds);
+	if (ret)
+	    goto cleanup;
+	ks.length = key->keyblock.length;
+	ks.contents = (krb5_octet *) ds.data;
+	keyblock = &ks;
+    } else  /* For md5-hmac, just use the key. */
+	keyblock = &key->keyblock;
+
+    /* Compute the MD5 value of the input. */
+    ms_usage = krb5int_arcfour_translate_usage(usage);
+    store_32_le(ms_usage, t);
+    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
+    if (hash_iov == NULL)
+	goto cleanup;
+    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    hash_iov[0].data = make_data(t, 4);
+    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+    ret = alloc_data(&hashval, ctp->hash->hashsize);
+    if (ret != 0)
+	goto cleanup;
+    ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
+    if (ret != 0)
+	goto cleanup;
+
+    /* Compute HMAC(ks, md5value). */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = hashval;
+    ret = krb5int_hmac_keyblock(ctp->hash, keyblock, &iov, 1, output);
+
+cleanup:
+    zapfree(ds.data, ds.length);
+    zapfree(hashval.data, hashval.length);
+    free(hash_iov);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/checksum_unkeyed.c (from rev 24677, trunk/src/lib/crypto/krb/checksum/unkeyed.c)
===================================================================
--- trunk/src/lib/crypto/krb/checksum_unkeyed.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/checksum_unkeyed.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/checksum/unkeyed.c
+ *
+ * Copyright (C) 2009 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.
+ *
+ * Unkeyed hash checksum implementation.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp,
+                         krb5_key key, krb5_keyusage usage,
+                         const krb5_crypto_iov *data, size_t num_data,
+                         krb5_data *output)
+{
+    return ctp->hash->hash(data, num_data, output);
+}

Copied: trunk/src/lib/crypto/krb/cmac.c (from rev 24677, trunk/src/lib/crypto/krb/checksum/cmac.c)
===================================================================
--- trunk/src/lib/crypto/krb/cmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/cmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,237 @@
+/*
+ * 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 "crypto_int.h"
+
+#ifdef CAMELLIA
+
+#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 */
+
+/* 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 */

Copied: trunk/src/lib/crypto/krb/crc32.c (from rev 24677, trunk/src/lib/crypto/krb/crc32/crc32.c)
===================================================================
--- trunk/src/lib/crypto/krb/crc32.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/crc32.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,166 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/crc32/crc.c
+ *
+ * Copyright 1990, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * CRC-32/AUTODIN-II routines
+ */
+
+#include "crypto_int.h"
+
+/* This table and block of comments are taken from code labeled: */
+/*
+ * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/* First, the polynomial itself and its table of feedback terms.  The  */
+/* polynomial is                                                       */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in  */
+/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
+/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
+/* the MSB being 1.                                                    */
+
+/* Note that the usual hardware shift register implementation, which   */
+/* is what we're using (we're merely optimizing it by doing eight-bit  */
+/* chunks at a time) shifts bits into the lowest-order term.  In our   */
+/* implementation, that means shifting towards the right.  Why do we   */
+/* do it this way?  Because the calculated CRC must be transmitted in  */
+/* order from highest-order term to lowest-order term.  UARTs transmit */
+/* characters in order from LSB to MSB.  By storing the CRC this way,  */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part.  Reception works similarly.                  */
+
+/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
+/*                                                                     */
+/*  1. The table can be generated at runtime if desired; code to do so */
+/*     is shown later.  It might not be obvious, but the feedback      */
+/*     terms simply represent the results of eight shift/xor opera-    */
+/*     tions for all combinations of data and CRC register values.     */
+/*                                                                     */
+/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
+/*     be they sixteen or thirty-two bits wide.  You simply choose the */
+/*     appropriate table.  Alternatively, because the table can be     */
+/*     generated at runtime, you can start by generating the table for */
+/*     the polynomial in question and use exactly the same "updcrc",   */
+/*     if your application needn't simultaneously handle two CRC       */
+/*     polynomials.  (Note, however, that XMODEM is strange.)          */
+/*                                                                     */
+/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
+/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
+/*                                                                     */
+/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
+/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
+/*     hardware you could probably optimize the shift in assembler by  */
+/*     using byte-swap instructions.                                   */
+
+static u_long const crc_table[256] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+void
+mit_crc32(krb5_pointer in, size_t in_length, unsigned long *cksum)
+{
+    register u_char *data;
+    register u_long c = *cksum;
+    register int idx;
+    size_t i;
+
+    data = (u_char *)in;
+    for (i = 0; i < in_length; i++) {
+        idx = (int) (data[i] ^ c);
+        idx &= 0xff;
+        c >>= 8;
+        c ^= crc_table[idx];
+    }
+
+    *cksum = c;
+}

Modified: trunk/src/lib/crypto/krb/deps
===================================================================
--- trunk/src/lib/crypto/krb/deps	2011-03-03 15:21:11 UTC (rev 24678)
+++ trunk/src/lib/crypto/krb/deps	2011-03-05 13:31:02 UTC (rev 24679)
@@ -96,6 +96,19 @@
   $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
   $(top_srcdir)/include/socket-utils.h combine_keys.c \
   crypto_int.h
+crc32.so crc32.po $(OUTPRE)crc32.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+  $(srcdir)/../builtin/aes/uitypes.h $(srcdir)/../builtin/crypto_mod.h \
+  $(srcdir)/../builtin/sha2/sha2.h $(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/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crc32.c crypto_int.h
 crypto_length.so crypto_length.po $(OUTPRE)crypto_length.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
@@ -382,6 +395,58 @@
   $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
   crypto_int.h prf.c
+prf_cmac.so prf_cmac.po $(OUTPRE)prf_cmac.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/aes/uitypes.h \
+  $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+  $(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/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
+  $(top_srcdir)/include/socket-utils.h crypto_int.h prf_cmac.c
+prf_des.so prf_des.po $(OUTPRE)prf_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+  $(srcdir)/../builtin/aes/uitypes.h $(srcdir)/../builtin/crypto_mod.h \
+  $(srcdir)/../builtin/sha2/sha2.h $(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/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_int.h prf_des.c
+prf_dk.so prf_dk.po $(OUTPRE)prf_dk.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+  $(srcdir)/../builtin/aes/uitypes.h $(srcdir)/../builtin/crypto_mod.h \
+  $(srcdir)/../builtin/sha2/sha2.h $(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/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_int.h prf_dk.c
+prf_rc4.so prf_rc4.po $(OUTPRE)prf_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+  $(srcdir)/../builtin/aes/uitypes.h $(srcdir)/../builtin/crypto_mod.h \
+  $(srcdir)/../builtin/sha2/sha2.h $(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/k5-trace.h \
+  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  crypto_int.h prf_rc4.c
 prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \

Copied: trunk/src/lib/crypto/krb/derive.c (from rev 24677, trunk/src/lib/crypto/krb/dk/derive.c)
===================================================================
--- trunk/src/lib/crypto/krb/derive.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/derive.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,299 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+static krb5_key
+find_cached_dkey(struct derived_key *list, const krb5_data *constant)
+{
+    for (; list; list = list->next) {
+        if (data_eq(list->constant, *constant)) {
+            krb5_k_reference_key(NULL, list->dkey);
+            return list->dkey;
+        }
+    }
+    return NULL;
+}
+
+static krb5_error_code
+add_cached_dkey(krb5_key key, const krb5_data *constant,
+                const krb5_keyblock *dkeyblock, krb5_key *cached_dkey)
+{
+    krb5_key dkey;
+    krb5_error_code ret;
+    struct derived_key *dkent = NULL;
+    char *data = NULL;
+
+    /* Allocate fields for the new entry. */
+    dkent = malloc(sizeof(*dkent));
+    if (dkent == NULL)
+        goto cleanup;
+    data = malloc(constant->length);
+    if (data == NULL)
+        goto cleanup;
+    ret = krb5_k_create_key(NULL, dkeyblock, &dkey);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Add the new entry to the list. */
+    memcpy(data, constant->data, constant->length);
+    dkent->dkey = dkey;
+    dkent->constant.data = data;
+    dkent->constant.length = constant->length;
+    dkent->next = key->derived;
+    key->derived = dkent;
+
+    /* Return a "copy" of the cached key. */
+    krb5_k_reference_key(NULL, dkey);
+    *cached_dkey = dkey;
+    return 0;
+
+cleanup:
+    free(dkent);
+    free(data);
+    return ENOMEM;
+}
+
+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_error_code ret;
+    krb5_data block = empty_data();
+
+    blocksize = enc->block_size;
+    keybytes = enc->keybytes;
+
+    if (blocksize == 1)
+        return KRB5_BAD_ENCTYPE;
+    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+        return KRB5_CRYPTO_INTERNAL;
+
+    /* Allocate encryption data buffer. */
+    ret = alloc_data(&block, blocksize);
+    if (ret)
+        return ret;
+
+    /* Initialize the input block. */
+    if (in_constant->length == blocksize) {
+        memcpy(block.data, in_constant->data, blocksize);
+    } else {
+        krb5int_nfold(in_constant->length * 8,
+                      (unsigned char *) in_constant->data,
+                      blocksize * 8, (unsigned char *) block.data);
+    }
+
+    /* Loop encrypting the blocks until enough key bytes are generated. */
+    n = 0;
+    while (n < keybytes) {
+        ret = encrypt_block(enc, inkey, &block);
+        if (ret)
+            goto cleanup;
+
+        if ((keybytes - n) <= blocksize) {
+            memcpy(outrnd->data + n, block.data, (keybytes - n));
+            break;
+        }
+
+        memcpy(outrnd->data + n, block.data, blocksize);
+        n += blocksize;
+    }
+
+cleanup:
+    zapfree(block.data, blocksize);
+    return ret;
+}
+
+#ifdef CAMELLIA
+
+/*
+ * 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 * 8, 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 */
+
+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
+    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
+ * directly in situations which are not expected to be repeated with
+ * the same inkey and constant.
+ */
+krb5_error_code
+krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
+                        krb5_key inkey, krb5_keyblock *outkey,
+                        const krb5_data *in_constant, enum deriv_alg alg)
+{
+    krb5_error_code ret;
+    krb5_data rawkey = empty_data();
+
+    /* Allocate a buffer for the raw key bytes. */
+    ret = alloc_data(&rawkey, enc->keybytes);
+    if (ret)
+        goto cleanup;
+
+    /* Derive pseudo-random data for the key bytes. */
+    ret = krb5int_derive_random(enc, inkey, &rawkey, in_constant, alg);
+    if (ret)
+        goto cleanup;
+
+    /* Postprocess the key. */
+    ret = krb5_c_random_to_key(NULL, inkey->keyblock.enctype, &rawkey, outkey);
+
+cleanup:
+    zapfree(rawkey.data, enc->keybytes);
+    return ret;
+}
+
+krb5_error_code
+krb5int_derive_key(const struct krb5_enc_provider *enc,
+                   krb5_key inkey, krb5_key *outkey,
+                   const krb5_data *in_constant, enum deriv_alg alg)
+{
+    krb5_keyblock keyblock;
+    krb5_error_code ret;
+    krb5_key dkey;
+
+    *outkey = NULL;
+
+    /* Check for a cached result. */
+    dkey = find_cached_dkey(inkey->derived, in_constant);
+    if (dkey != NULL) {
+        *outkey = dkey;
+        return 0;
+    }
+
+    /* Derive into a temporary keyblock. */
+    keyblock.length = enc->keylength;
+    keyblock.contents = malloc(keyblock.length);
+    keyblock.enctype = inkey->keyblock.enctype;
+    if (keyblock.contents == NULL)
+        return ENOMEM;
+    ret = krb5int_derive_keyblock(enc, inkey, &keyblock, in_constant, alg);
+    if (ret)
+        goto cleanup;
+
+    /* Cache the derived key. */
+    ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey);
+    if (ret != 0)
+        goto cleanup;
+
+    *outkey = dkey;
+
+cleanup:
+    zapfree(keyblock.contents, keyblock.length);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/enc_dk_cmac.c (from rev 24677, trunk/src/lib/crypto/krb/dk/dk_cmac.c)
===================================================================
--- trunk/src/lib/crypto/krb/enc_dk_cmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/enc_dk_cmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,186 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/dk/dk_cmac.c - Derived-key enctype functions using CMAC */
+/*
+ * Copyright 2008, 2009, 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 "crypto_int.h"
+
+#ifdef CAMELLIA
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+/* AEAD */
+
+unsigned int
+krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp,
+			       krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_HEADER:
+        return ktp->enc->block_size;
+    case KRB5_CRYPTO_TYPE_PADDING:
+        return 0;
+    case KRB5_CRYPTO_TYPE_TRAILER:
+    case KRB5_CRYPTO_TYPE_CHECKSUM:
+        return ktp->enc->block_size;
+    default:
+        assert(0 && "bad type passed to krb5int_camellia_crypto_length");
+        return 0;
+    }
+}
+
+/* Derive encryption and integrity keys for CMAC-using enctypes. */
+static krb5_error_code
+derive_keys(const struct krb5_enc_provider *enc, krb5_key key,
+	    krb5_keyusage usage, krb5_key *ke_out, krb5_key *ki_out)
+{
+    krb5_error_code ret;
+    unsigned char buf[K5CLENGTH];
+    krb5_data constant = make_data(buf, K5CLENGTH);
+    krb5_key ke, ki;
+
+    *ke_out = *ki_out = NULL;
+
+    /* Derive the encryption key. */
+    store_32_be(usage, buf);
+    buf[4] = 0xAA;
+    ret = krb5int_derive_key(enc, key, &ke, &constant, DERIVE_SP800_108_CMAC);
+    if (ret != 0)
+	return ret;
+
+    /* Derive the integrity key. */
+    buf[4] = 0x55;
+    ret = krb5int_derive_key(enc, key, &ki, &constant, DERIVE_SP800_108_CMAC);
+    if (ret != 0) {
+	krb5_k_free_key(NULL, ke);
+	return ret;
+    }
+
+    *ke_out = ke;
+    *ki_out = ki;
+    return 0;
+}
+
+krb5_error_code
+krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+			krb5_keyusage usage, const krb5_data *ivec,
+			krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer, *padding;
+    krb5_data cksum = empty_data();
+    krb5_key ke = NULL, ki = NULL;
+
+    /* E(Confounder | Plaintext | Pad) | Checksum */
+
+    /* Validate header and trailer lengths, and zero out padding length. */
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL || header->data.length < enc->block_size)
+        return KRB5_BAD_MSIZE;
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer == NULL || trailer->data.length < enc->block_size)
+        return KRB5_BAD_MSIZE;
+    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+    if (padding != NULL)
+	padding->data.length = 0;
+
+    /* Derive the encryption and integrity keys. */
+    ret = derive_keys(enc, key, usage, &ke, &ki);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Generate confounder. */
+    header->data.length = enc->block_size;
+    ret = krb5_c_random_make_octets(NULL, &header->data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Checksum the plaintext. */
+    ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Encrypt the plaintext (header | data | padding) */
+    ret = enc->encrypt(ke, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+cleanup:
+    krb5_k_free_key(NULL, ke);
+    krb5_k_free_key(NULL, ki);
+    zapfree(cksum.data, cksum.length);
+    return ret;
+}
+
+krb5_error_code
+krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                        krb5_keyusage usage, const krb5_data *ivec,
+                        krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer;
+    krb5_data cksum;
+    krb5_key ke = NULL, ki = NULL;
+
+    /* E(Confounder | Plaintext | Pad) | Checksum */
+
+    /* Validate header and trailer lengths. */
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL || header->data.length != enc->block_size)
+        return KRB5_BAD_MSIZE;
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer == NULL || trailer->data.length != enc->block_size)
+        return KRB5_BAD_MSIZE;
+
+    /* Derive the encryption and integrity keys. */
+    ret = derive_keys(enc, key, usage, &ke, &ki);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Decrypt the plaintext (header | data | padding). */
+    ret = enc->decrypt(ke, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Verify the hash. */
+    ret = alloc_data(&cksum, enc->block_size);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_cmac_checksum(enc, ki, data, num_data, &cksum);
+    if (ret != 0)
+        goto cleanup;
+    if (!data_eq(cksum, trailer->data))
+        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+cleanup:
+    krb5_k_free_key(NULL, ke);
+    krb5_k_free_key(NULL, ki);
+    zapfree(cksum.data, cksum.length);
+    return ret;
+}
+
+#endif /* CAMELLIA */

Copied: trunk/src/lib/crypto/krb/enc_dk_hmac.c (from rev 24677, trunk/src/lib/crypto/krb/dk/dk_aead.c)
===================================================================
--- trunk/src/lib/crypto/krb/enc_dk_hmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/enc_dk_hmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,270 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/dk/dk_aead.c
+ *
+ * Copyright 2008, 2009 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 "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+/* AEAD */
+
+unsigned int
+krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_HEADER:
+    case KRB5_CRYPTO_TYPE_PADDING:
+        return ktp->enc->block_size;
+    case KRB5_CRYPTO_TYPE_TRAILER:
+    case KRB5_CRYPTO_TYPE_CHECKSUM:
+        return ktp->hash->hashsize;
+    default:
+        assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length");
+        return 0;
+    }
+}
+
+unsigned int
+krb5int_aes_crypto_length(const struct krb5_keytypes *ktp,
+                          krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_HEADER:
+        return ktp->enc->block_size;
+    case KRB5_CRYPTO_TYPE_PADDING:
+        return 0;
+    case KRB5_CRYPTO_TYPE_TRAILER:
+    case KRB5_CRYPTO_TYPE_CHECKSUM:
+        return 96 / 8;
+    default:
+        assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length");
+        return 0;
+    }
+}
+
+krb5_error_code
+krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                   krb5_keyusage usage, const krb5_data *ivec,
+                   krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data d1, d2;
+    krb5_crypto_iov *header, *trailer, *padding;
+    krb5_key ke = NULL, ki = NULL;
+    size_t i;
+    unsigned int blocksize, hmacsize, plainlen = 0, padsize = 0;
+    unsigned char *cksum = NULL;
+
+    /* E(Confounder | Plaintext | Pad) | Checksum */
+
+    blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+    hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+    for (i = 0; i < num_data; i++) {
+        krb5_crypto_iov *iov = &data[i];
+
+        if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+            plainlen += iov->data.length;
+    }
+
+    /* Validate header and trailer lengths. */
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL || header->data.length < enc->block_size)
+        return KRB5_BAD_MSIZE;
+
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer == NULL || trailer->data.length < hmacsize)
+        return KRB5_BAD_MSIZE;
+
+    if (blocksize != 0) {
+        /* Check that the input data is correctly padded. */
+        if (plainlen % blocksize)
+            padsize = blocksize - (plainlen % blocksize);
+    }
+
+    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+    if (padsize && (padding == NULL || padding->data.length < padsize))
+        return KRB5_BAD_MSIZE;
+
+    if (padding != NULL) {
+        memset(padding->data.data, 0, padsize);
+        padding->data.length = padsize;
+    }
+
+    cksum = k5alloc(hash->hashsize, &ret);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive the keys. */
+
+    d1.data = (char *)constantdata;
+    d1.length = K5CLENGTH;
+
+    store_32_be(usage, constantdata);
+
+    d1.data[4] = 0xAA;
+
+    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, DERIVE_RFC3961);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Generate confounder. */
+
+    header->data.length = enc->block_size;
+
+    ret = krb5_c_random_make_octets(/* XXX */ NULL, &header->data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Hash the plaintext. */
+    d2.length = hash->hashsize;
+    d2.data = (char *)cksum;
+
+    ret = krb5int_hmac(hash, ki, data, num_data, &d2);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Encrypt the plaintext (header | data | padding) */
+    ret = enc->encrypt(ke, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Possibly truncate the hash */
+    assert(hmacsize <= d2.length);
+
+    memcpy(trailer->data.data, cksum, hmacsize);
+    trailer->data.length = hmacsize;
+
+cleanup:
+    krb5_k_free_key(NULL, ke);
+    krb5_k_free_key(NULL, ki);
+    free(cksum);
+    return ret;
+}
+
+krb5_error_code
+krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                   krb5_keyusage usage, const krb5_data *ivec,
+                   krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    unsigned char constantdata[K5CLENGTH];
+    krb5_data d1;
+    krb5_crypto_iov *header, *trailer;
+    krb5_key ke = NULL, ki = NULL;
+    size_t i;
+    unsigned int blocksize; /* enc block size, not confounder len */
+    unsigned int hmacsize, cipherlen = 0;
+    unsigned char *cksum = NULL;
+
+    /* E(Confounder | Plaintext | Pad) | Checksum */
+
+    blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+    hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+    if (blocksize != 0) {
+        /* Check that the input data is correctly padded. */
+        for (i = 0; i < num_data; i++) {
+            const krb5_crypto_iov *iov = &data[i];
+
+            if (ENCRYPT_DATA_IOV(iov))
+                cipherlen += iov->data.length;
+        }
+        if (cipherlen % blocksize != 0)
+            return KRB5_BAD_MSIZE;
+    }
+
+    /* Validate header and trailer lengths */
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL || header->data.length != enc->block_size)
+        return KRB5_BAD_MSIZE;
+
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer == NULL || trailer->data.length != hmacsize)
+        return KRB5_BAD_MSIZE;
+
+    cksum = k5alloc(hash->hashsize, &ret);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive the keys. */
+
+    d1.data = (char *)constantdata;
+    d1.length = K5CLENGTH;
+
+    store_32_be(usage, constantdata);
+
+    d1.data[4] = 0xAA;
+
+    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, DERIVE_RFC3961);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Decrypt the plaintext (header | data | padding). */
+    ret = enc->decrypt(ke, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Verify the hash. */
+    d1.length = hash->hashsize; /* non-truncated length */
+    d1.data = (char *)cksum;
+
+    ret = krb5int_hmac(hash, ki, data, num_data, &d1);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Compare only the possibly truncated length. */
+    if (memcmp(cksum, trailer->data.data, hmacsize) != 0) {
+        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+        goto cleanup;
+    }
+
+cleanup:
+    krb5_k_free_key(NULL, ke);
+    krb5_k_free_key(NULL, ki);
+    free(cksum);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/enc_old.c (from rev 24677, trunk/src/lib/crypto/krb/old/old_aead.c)
===================================================================
--- trunk/src/lib/crypto/krb/enc_old.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/enc_old.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,189 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/old/old_aead.c
+ *
+ * Copyright 2008 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 "crypto_int.h"
+
+unsigned int
+krb5int_old_crypto_length(const struct krb5_keytypes *ktp,
+                          krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_HEADER:
+        return ktp->enc->block_size + ktp->hash->hashsize;
+    case KRB5_CRYPTO_TYPE_PADDING:
+        return ktp->enc->block_size;
+    case KRB5_CRYPTO_TYPE_TRAILER:
+        return 0;
+    case KRB5_CRYPTO_TYPE_CHECKSUM:
+        return ktp->hash->hashsize;
+    default:
+        assert(0 && "invalid cryptotype passed to krb5int_old_crypto_length");
+        return 0;
+    }
+}
+
+krb5_error_code
+krb5int_old_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                    krb5_keyusage usage, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer, *padding;
+    krb5_data checksum, confounder, crcivec = empty_data();
+    unsigned int plainlen, padsize;
+    size_t i;
+
+    /* E(Confounder | Checksum | Plaintext | Pad) */
+
+    plainlen = enc->block_size + hash->hashsize;
+    for (i = 0; i < num_data; i++) {
+        krb5_crypto_iov *iov = &data[i];
+
+        if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+            plainlen += iov->data.length;
+    }
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL ||
+        header->data.length < enc->block_size + hash->hashsize)
+        return KRB5_BAD_MSIZE;
+
+    /* Trailer may be absent. */
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer != NULL)
+        trailer->data.length = 0;
+
+    /* Check that the input data is correctly padded. */
+    padsize = krb5_roundup(plainlen, enc->block_size) - plainlen;
+    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+    if (padsize > 0 && (padding == NULL || padding->data.length < padsize))
+        return KRB5_BAD_MSIZE;
+    if (padding) {
+        padding->data.length = padsize;
+        memset(padding->data.data, 0, padsize);
+    }
+
+    /* Generate a confounder in the header block. */
+    confounder = make_data(header->data.data, enc->block_size);
+    ret = krb5_c_random_make_octets(0, &confounder);
+    if (ret != 0)
+        goto cleanup;
+    checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
+    memset(checksum.data, 0, hash->hashsize);
+
+    /* Checksum the plaintext with zeroed checksum and padding. */
+    ret = hash->hash(data, num_data, &checksum);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Use the key as the ivec for des-cbc-crc if none was provided. */
+    if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
+        ret = alloc_data(&crcivec, key->keyblock.length);
+        memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
+        ivec = &crcivec;
+    }
+
+    ret = enc->encrypt(key, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+cleanup:
+    zapfree(crcivec.data, crcivec.length);
+    return ret;
+}
+
+krb5_error_code
+krb5int_old_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                    krb5_keyusage usage, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer;
+    krb5_data checksum, crcivec = empty_data();
+    char *saved_checksum = NULL;
+    size_t i;
+    unsigned int cipherlen = 0;
+
+    /* Check that the input data is correctly padded. */
+    for (i = 0; i < num_data; i++) {
+        const krb5_crypto_iov *iov = &data[i];
+
+        if (ENCRYPT_IOV(iov))
+            cipherlen += iov->data.length;
+    }
+    if (cipherlen % enc->block_size != 0)
+        return KRB5_BAD_MSIZE;
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL ||
+        header->data.length != enc->block_size + hash->hashsize)
+        return KRB5_BAD_MSIZE;
+
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer != NULL && trailer->data.length != 0)
+        return KRB5_BAD_MSIZE;
+
+    /* Use the key as the ivec for des-cbc-crc if none was provided. */
+    if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
+        ret = alloc_data(&crcivec, key->keyblock.length);
+        memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
+        ivec = &crcivec;
+    }
+
+    /* Decrypt the ciphertext. */
+    ret = enc->decrypt(key, ivec, data, num_data);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Save the checksum, then zero it out in the plaintext. */
+    checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
+    saved_checksum = k5alloc(hash->hashsize, &ret);
+    if (saved_checksum == NULL)
+        goto cleanup;
+    memcpy(saved_checksum, checksum.data, checksum.length);
+    memset(checksum.data, 0, checksum.length);
+
+    /*
+     * Checksum the plaintext (with zeroed checksum field), storing the result
+     * back into the plaintext field we just zeroed out.  Then compare it to
+     * the saved checksum.
+     */
+    ret = hash->hash(data, num_data, &checksum);
+    if (memcmp(checksum.data, saved_checksum, checksum.length) != 0) {
+        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+        goto cleanup;
+    }
+
+cleanup:
+    zapfree(crcivec.data, crcivec.length);
+    zapfree(saved_checksum, hash->hashsize);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/enc_raw.c (from rev 24677, trunk/src/lib/crypto/krb/raw/raw_aead.c)
===================================================================
--- trunk/src/lib/crypto/krb/enc_raw.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/enc_raw.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/raw/raw_aead.c
+ *
+ * Copyright 2008 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 "crypto_int.h"
+
+unsigned int
+krb5int_raw_crypto_length(const struct krb5_keytypes *ktp,
+                          krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_PADDING:
+        return ktp->enc->block_size;
+    default:
+        return 0;
+    }
+}
+
+krb5_error_code
+krb5int_raw_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_crypto_iov *padding;
+    size_t i;
+    unsigned int blocksize, plainlen = 0, padsize = 0;
+
+    blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+
+    for (i = 0; i < num_data; i++) {
+        krb5_crypto_iov *iov = &data[i];
+
+        if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+            plainlen += iov->data.length;
+    }
+
+    if (blocksize != 0) {
+        /* Check that the input data is correctly padded */
+        if (plainlen % blocksize)
+            padsize = blocksize - (plainlen % blocksize);
+    }
+
+    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+    if (padsize && (padding == NULL || padding->data.length < padsize))
+        return KRB5_BAD_MSIZE;
+
+    if (padding != NULL) {
+        memset(padding->data.data, 0, padsize);
+        padding->data.length = padsize;
+    }
+
+    return ktp->enc->encrypt(key, ivec, data, num_data);
+}
+
+krb5_error_code
+krb5int_raw_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                    krb5_keyusage usage, const krb5_data *ivec,
+                    krb5_crypto_iov *data, size_t num_data)
+{
+    size_t i;
+    unsigned int blocksize = 0; /* enc block size, not confounder len */
+    unsigned int cipherlen = 0;
+
+    /* E(Confounder | Plaintext | Pad) | Checksum */
+
+    blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+
+    for (i = 0; i < num_data; i++) {
+        const krb5_crypto_iov *iov = &data[i];
+
+        if (ENCRYPT_DATA_IOV(iov))
+            cipherlen += iov->data.length;
+    }
+
+    if (blocksize == 0) {
+        /* Check for correct input length in CTS mode */
+        if (ktp->enc->block_size != 0 && cipherlen < ktp->enc->block_size)
+            return KRB5_BAD_MSIZE;
+    } else {
+        /* Check that the input data is correctly padded */
+        if (cipherlen % blocksize != 0)
+            return KRB5_BAD_MSIZE;
+    }
+
+    return ktp->enc->decrypt(key, ivec, data, num_data);
+}

Copied: trunk/src/lib/crypto/krb/enc_rc4.c (from rev 24677, trunk/src/lib/crypto/krb/arcfour/arcfour.c)
===================================================================
--- trunk/src/lib/crypto/krb/enc_rc4.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/enc_rc4.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,347 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+
+  ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95).
+  This cipher is widely believed and has been tested to be equivalent
+  with the RC4 cipher from RSA Data Security, Inc.  (RC4 is a trademark
+  of RSA Data Security)
+
+*/
+#include "crypto_int.h"
+
+#define CONFOUNDERLENGTH 8
+
+const char l40[] = "fortybits";
+
+krb5_keyusage
+krb5int_arcfour_translate_usage(krb5_keyusage usage)
+{
+    switch (usage) {
+    case 1:  return 1;   /* AS-REQ PA-ENC-TIMESTAMP padata timestamp,  */
+    case 2:  return 2;   /* ticket from kdc */
+    case 3:  return 8;   /* as-rep encrypted part */
+    case 4:  return 4;   /* tgs-req authz data */
+    case 5:  return 5;   /* tgs-req authz data in subkey */
+    case 6:  return 6;   /* tgs-req authenticator cksum */
+    case 7:  return 7;   /* tgs-req authenticator */
+    case 8:  return 8;
+    case 9:  return 9;   /* tgs-rep encrypted with subkey */
+    case 10: return 10;  /* ap-rep authentication cksum (never used by MS) */
+    case 11: return 11;  /* app-req authenticator */
+    case 12: return 12;  /* app-rep encrypted part */
+    case 23: return 13;  /* sign wrap token*/
+    default: return usage;
+    }
+}
+
+/* Derive a usage key from a session key and krb5 usage constant. */
+static krb5_error_code
+usage_key(const struct krb5_enc_provider *enc,
+          const struct krb5_hash_provider *hash,
+          const krb5_keyblock *session_keyblock, krb5_keyusage usage,
+          krb5_keyblock *out)
+{
+    char salt_buf[14];
+    unsigned int salt_len;
+    krb5_data out_data = make_data(out->contents, out->length);
+    krb5_crypto_iov iov;
+    krb5_keyusage ms_usage;
+
+    /* Generate the salt. */
+    ms_usage = krb5int_arcfour_translate_usage(usage);
+    if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+        memcpy(salt_buf, l40, 10);
+        store_32_le(ms_usage, salt_buf + 10);
+        salt_len = 14;
+    } else {
+        store_32_le(ms_usage, salt_buf);
+        salt_len = 4;
+    }
+
+    /* Compute HMAC(key, salt) to produce the usage key. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = make_data(salt_buf, salt_len);
+    return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data);
+}
+
+/* Derive an encryption key from a usage key and (typically) checksum. */
+static krb5_error_code
+enc_key(const struct krb5_enc_provider *enc,
+        const struct krb5_hash_provider *hash,
+        const krb5_keyblock *usage_keyblock, const krb5_data *checksum,
+        krb5_keyblock *out)
+{
+    krb5_keyblock *trunc_keyblock = NULL;
+    krb5_data out_data = make_data(out->contents, out->length);
+    krb5_crypto_iov iov;
+    krb5_error_code ret;
+
+    /* Copy usage_keyblock to trunc_keyblock and truncate if exportable. */
+    ret = krb5int_c_copy_keyblock(NULL, usage_keyblock, &trunc_keyblock);
+    if (ret != 0)
+        return ret;
+    if (trunc_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+        memset(trunc_keyblock->contents + 7, 0xab, 9);
+
+    /* Compute HMAC(trunc_key, checksum) to produce the encryption key. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *checksum;
+    ret = krb5int_hmac_keyblock(hash, trunc_keyblock, &iov, 1, &out_data);
+    krb5int_c_free_keyblock(NULL, trunc_keyblock);
+    return ret;
+}
+
+unsigned int
+krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp,
+                              krb5_cryptotype type)
+{
+    switch (type) {
+    case KRB5_CRYPTO_TYPE_HEADER:
+        return ktp->hash->hashsize + CONFOUNDERLENGTH;
+    case KRB5_CRYPTO_TYPE_PADDING:
+    case KRB5_CRYPTO_TYPE_TRAILER:
+        return 0;
+    case KRB5_CRYPTO_TYPE_CHECKSUM:
+        return ktp->hash->hashsize;
+    default:
+        assert(0 &&
+               "invalid cryptotype passed to krb5int_arcfour_crypto_length");
+        return 0;
+    }
+}
+
+/* Encrypt or decrypt using a keyblock. */
+static krb5_error_code
+keyblock_crypt(const struct krb5_enc_provider *enc, krb5_keyblock *keyblock,
+               const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data)
+{
+    krb5_error_code ret;
+    krb5_key key;
+
+    ret = krb5_k_create_key(NULL, keyblock, &key);
+    if (ret != 0)
+        return ret;
+    /* Works for encryption or decryption since arcfour is a stream cipher. */
+    ret = enc->encrypt(key, ivec, data, num_data);
+    krb5_k_free_key(NULL, key);
+    return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                        krb5_keyusage usage, const krb5_data *ivec,
+                        krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer;
+    krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+    krb5_data checksum, confounder, header_data;
+    size_t i;
+
+    /*
+     * Caller must have provided space for the header, padding
+     * and trailer; per RFC 4757 we will arrange it as:
+     *
+     *      Checksum | E(Confounder | Plaintext)
+     */
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL ||
+        header->data.length < hash->hashsize + CONFOUNDERLENGTH)
+        return KRB5_BAD_MSIZE;
+
+    header_data = header->data;
+
+    /* Trailer may be absent. */
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer != NULL)
+        trailer->data.length = 0;
+
+    /* Ensure that there is no padding. */
+    for (i = 0; i < num_data; i++) {
+        if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING)
+            data[i].data.length = 0;
+    }
+
+    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+                                  &usage_keyblock);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+                                  &enc_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive a usage key from the session key and usage. */
+    ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Generate a confounder in the header block, after the checksum. */
+    header->data.length = hash->hashsize + CONFOUNDERLENGTH;
+    confounder = make_data(header->data.data + hash->hashsize,
+                           CONFOUNDERLENGTH);
+    ret = krb5_c_random_make_octets(0, &confounder);
+    if (ret != 0)
+        goto cleanup;
+    checksum = make_data(header->data.data, hash->hashsize);
+
+    /* Adjust pointers so confounder is at start of header. */
+    header->data.length -= hash->hashsize;
+    header->data.data += hash->hashsize;
+
+    /* Compute the checksum using the usage key. */
+    ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
+                                &checksum);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive the encryption key from the usage key and checksum. */
+    ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
+    if (ret)
+        goto cleanup;
+
+    ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
+
+cleanup:
+    header->data = header_data; /* Restore header pointers. */
+    krb5int_c_free_keyblock(NULL, usage_keyblock);
+    krb5int_c_free_keyblock(NULL, enc_keyblock);
+    return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+                        krb5_keyusage usage, const krb5_data *ivec,
+                        krb5_crypto_iov *data, size_t num_data)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_error_code ret;
+    krb5_crypto_iov *header, *trailer;
+    krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+    krb5_data checksum, header_data, comp_checksum = empty_data();
+
+    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+    if (header == NULL ||
+        header->data.length != hash->hashsize + CONFOUNDERLENGTH)
+        return KRB5_BAD_MSIZE;
+
+    header_data = header->data;
+
+    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+    if (trailer != NULL && trailer->data.length != 0)
+        return KRB5_BAD_MSIZE;
+
+    /* Allocate buffers. */
+    ret = alloc_data(&comp_checksum, hash->hashsize);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+                                  &usage_keyblock);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+                                  &enc_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    checksum = make_data(header->data.data, hash->hashsize);
+
+    /* Adjust pointers so confounder is at start of header. */
+    header->data.length -= hash->hashsize;
+    header->data.data += hash->hashsize;
+
+    /* We may have to try two usage values; see below. */
+    do {
+        /* Derive a usage key from the session key and usage. */
+        ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
+        if (ret != 0)
+            goto cleanup;
+
+        /* Derive the encryption key from the usage key and checksum. */
+        ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
+        if (ret)
+            goto cleanup;
+
+        /* Decrypt the ciphertext. */
+        ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
+        if (ret != 0)
+            goto cleanup;
+
+        /* Compute HMAC(usage key, plaintext) to get the checksum. */
+        ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
+                                    &comp_checksum);
+        if (ret != 0)
+            goto cleanup;
+
+        if (memcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) {
+            if (usage == 9) {
+                /*
+                 * RFC 4757 specifies usage 8 for TGS-REP encrypted parts
+                 * encrypted in a subkey, but the value used by MS is actually
+                 * 9.  We now use 9 to start with, but fall back to 8 on
+                 * failure in case we are communicating with a KDC using the
+                 * value from the RFC.  ivec is always NULL in this case.
+                 * We need to re-encrypt the data in the wrong key first.
+                 */
+                ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data);
+                if (ret != 0)
+                    goto cleanup;
+                usage = 8;
+                continue;
+            }
+            ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+            goto cleanup;
+        }
+
+        break;
+    } while (1);
+
+cleanup:
+    header->data = header_data; /* Restore header pointers. */
+    krb5int_c_free_keyblock(NULL, usage_keyblock);
+    krb5int_c_free_keyblock(NULL, enc_keyblock);
+    zapfree(comp_checksum.data, comp_checksum.length);
+    return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
+                         const krb5_data *kd_data, krb5_crypto_iov *data,
+                         size_t num_data)
+{
+    const struct krb5_enc_provider *enc = &krb5int_enc_arcfour;
+    const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+    krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+    krb5_error_code ret;
+
+    ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
+                                  &usage_keyblock);
+    if (ret != 0)
+        goto cleanup;
+    ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
+                                  &enc_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive a usage key from the session key and usage. */
+    ret = usage_key(enc, hash, keyblock, usage, usage_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive the encryption key from the usage key and kd_data. */
+    ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Encrypt or decrypt (encrypt_iov works for both) the input. */
+    ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data);
+
+cleanup:
+    krb5int_c_free_keyblock(NULL, usage_keyblock);
+    krb5int_c_free_keyblock(NULL, enc_keyblock);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/prf_cmac.c (from rev 24677, trunk/src/lib/crypto/krb/prf/cmac_prf.c)
===================================================================
--- trunk/src/lib/crypto/krb/prf_cmac.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/prf_cmac.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,68 @@
+/* -*- 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 "crypto_int.h"
+
+#ifdef CAMELLIA
+
+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 */

Copied: trunk/src/lib/crypto/krb/prf_des.c (from rev 24677, trunk/src/lib/crypto/krb/prf/des_prf.c)
===================================================================
--- trunk/src/lib/crypto/krb/prf_des.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/prf_des.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,53 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prf//des_prf.c
+ *
+ * Copyright (C) 2004, 2009  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
+ * des-cbc-crc, des-cbc-md4, and des-cbc-md5 enctypes.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key,
+                const krb5_data *in, krb5_data *out)
+{
+    const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+    krb5_crypto_iov iov;
+    krb5_error_code ret;
+
+    /* Compute a hash of the input, storing into the output buffer. */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *in;
+    ret = hash->hash(&iov, 1, out);
+    if (ret != 0)
+        return ret;
+
+    /* Encrypt the hash in place. */
+    iov.data = *out;
+    return ktp->enc->encrypt(key, NULL, &iov, 1);
+}

Copied: trunk/src/lib/crypto/krb/prf_dk.c (from rev 24677, trunk/src/lib/crypto/krb/prf/dk_prf.c)
===================================================================
--- trunk/src/lib/crypto/krb/prf_dk.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/prf_dk.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,75 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prf/dk_prf.c
+ *
+ * Copyright (C) 2004 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 "crypto_int.h"
+
+krb5_error_code
+krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
+               const krb5_data *in, krb5_data *out)
+{
+    const struct krb5_enc_provider *enc = ktp->enc;
+    const struct krb5_hash_provider *hash = ktp->hash;
+    krb5_crypto_iov iov;
+    krb5_data cksum = empty_data(), prfconst = make_data("prf", 3);
+    krb5_key kp = NULL;
+    krb5_error_code ret;
+
+    /* Hash the input data into an allocated buffer. */
+    ret = alloc_data(&cksum, hash->hashsize);
+    if (ret != 0)
+        goto cleanup;
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *in;
+    ret = hash->hash(&iov, 1, &cksum);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Derive a key using the PRF constant. */
+    ret = krb5int_derive_key(ktp->enc, key, &kp, &prfconst, DERIVE_RFC3961);
+    if (ret != 0)
+        goto cleanup;
+
+    /* Truncate the hash to the closest multiple of the block size. */
+    iov.data.data = cksum.data;
+    iov.data.length = (hash->hashsize / enc->block_size) * enc->block_size;
+
+    /* Encrypt the truncated hash in the derived key to get the output. */
+    ret = ktp->enc->encrypt(kp, NULL, &iov, 1);
+    if (ret != 0)
+        goto cleanup;
+    memcpy(out->data, iov.data.data, out->length);
+
+cleanup:
+    zapfree(cksum.data, hash->hashsize);
+    krb5_k_free_key(NULL, kp);
+    return ret;
+}

Copied: trunk/src/lib/crypto/krb/prf_rc4.c (from rev 24677, trunk/src/lib/crypto/krb/prf/rc4_prf.c)
===================================================================
--- trunk/src/lib/crypto/krb/prf_rc4.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/prf_rc4.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,41 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * lib/crypto/krb/prf/rc4_prf.c
+ *
+ * Copyright (C) 2009 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 "crypto_int.h"
+
+krb5_error_code
+krb5int_arcfour_prf(const struct krb5_keytypes *ktp, krb5_key key,
+                    const krb5_data *in, krb5_data *out)
+{
+    krb5_crypto_iov iov;
+
+    assert(out->length == 20);
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = *in;
+    return krb5int_hmac(&krb5int_hash_sha1, key, &iov, 1, out);
+}

Copied: trunk/src/lib/crypto/krb/s2k_des.c (from rev 24677, trunk/src/lib/crypto/krb/old/des_stringtokey.c)
===================================================================
--- trunk/src/lib/crypto/krb/s2k_des.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/s2k_des.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,50 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_des_string_to_key(const struct krb5_keytypes *ktp,
+                          const krb5_data *string, const krb5_data *salt,
+                          const krb5_data *parm, krb5_keyblock *key)
+{
+    int type;
+    if (parm) {
+        if (parm->length != 1)
+            return KRB5_ERR_BAD_S2K_PARAMS;
+        type = parm->data[0];
+    }
+    else type = 0;
+    switch(type) {
+    case 0:
+        return(mit_des_string_to_key_int(key, string, salt));
+    case 1:
+        return mit_afs_string_to_key(key, string, salt);
+    default:
+        return KRB5_ERR_BAD_S2K_PARAMS;
+    }
+}

Copied: trunk/src/lib/crypto/krb/s2k_pbkdf2.c (from rev 24677, trunk/src/lib/crypto/krb/dk/stringtokey.c)
===================================================================
--- trunk/src/lib/crypto/krb/s2k_pbkdf2.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/s2k_pbkdf2.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,199 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+static const unsigned char kerberos[] = "kerberos";
+#define kerberos_len (sizeof(kerberos)-1)
+
+krb5_error_code
+krb5int_dk_string_to_key(const struct krb5_keytypes *ktp,
+                         const krb5_data *string, const krb5_data *salt,
+                         const krb5_data *parms, krb5_keyblock *keyblock)
+{
+    krb5_error_code ret;
+    size_t keybytes, keylength, concatlen;
+    unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL;
+    krb5_data indata;
+    krb5_keyblock foldkeyblock;
+    krb5_key foldkey = NULL;
+
+    /* keyblock->length is checked by krb5int_derive_key. */
+
+    keybytes = ktp->enc->keybytes;
+    keylength = ktp->enc->keylength;
+
+    concatlen = string->length + (salt ? salt->length : 0);
+
+    concat = k5alloc(concatlen, &ret);
+    if (ret != 0)
+        goto cleanup;
+    foldstring = k5alloc(keybytes, &ret);
+    if (ret != 0)
+        goto cleanup;
+    foldkeydata = k5alloc(keylength, &ret);
+    if (ret != 0)
+        goto cleanup;
+
+    /* construct input string ( = string + salt), fold it, make_key it */
+
+    memcpy(concat, string->data, string->length);
+    if (salt)
+        memcpy(concat + string->length, salt->data, salt->length);
+
+    krb5int_nfold(concatlen*8, concat, keybytes*8, foldstring);
+
+    indata.length = keybytes;
+    indata.data = (char *) foldstring;
+    foldkeyblock.length = keylength;
+    foldkeyblock.contents = foldkeydata;
+    foldkeyblock.enctype = ktp->etype;
+
+    ret = ktp->rand2key(&indata, &foldkeyblock);
+    if (ret != 0)
+        goto cleanup;
+
+    ret = krb5_k_create_key(NULL, &foldkeyblock, &foldkey);
+    if (ret != 0)
+        goto cleanup;
+
+    /* now derive the key from this one */
+
+    indata.length = kerberos_len;
+    indata.data = (char *) kerberos;
+
+    ret = krb5int_derive_keyblock(ktp->enc, foldkey, keyblock, &indata,
+                                  DERIVE_RFC3961);
+    if (ret != 0)
+        memset(keyblock->contents, 0, keyblock->length);
+
+cleanup:
+    zapfree(concat, concatlen);
+    zapfree(foldstring, keybytes);
+    zapfree(foldkeydata, keylength);
+    krb5_k_free_key(NULL, foldkey);
+    return ret;
+}
+
+
+#define MAX_ITERATION_COUNT             0x1000000L
+
+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 def_iter_count)
+{
+    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;
+        if (params->length != 4)
+            return KRB5_ERR_BAD_S2K_PARAMS;
+        /* The first two need casts in case 'int' is 16 bits.  */
+        iter_count = load_32_be(p);
+        if (iter_count == 0) {
+            iter_count = (1UL << 16) << 16;
+            if (((iter_count >> 16) >> 16) != 1)
+                return KRB5_ERR_BAD_S2K_PARAMS;
+        }
+    } else
+        iter_count = def_iter_count;
+
+    /* This is not a protocol specification constraint; this is an
+       implementation limit, which should eventually be controlled by
+       a config file.  */
+    if (iter_count >= MAX_ITERATION_COUNT)
+        return KRB5_ERR_BAD_S2K_PARAMS;
+
+    /* Use the output keyblock contents for temporary space. */
+    out.data = (char *) key->contents;
+    out.length = key->length;
+    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;
+
+    err = krb5_k_create_key (NULL, key, &tempkey);
+    if (err)
+        goto cleanup;
+
+    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, 4096);
+}
+
+#ifdef CAMELLIA
+krb5_error_code
+krb5int_camellia_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, 32768);
+}
+#endif

Copied: trunk/src/lib/crypto/krb/s2k_rc4.c (from rev 24677, trunk/src/lib/crypto/krb/arcfour/arcfour_s2k.c)
===================================================================
--- trunk/src/lib/crypto/krb/s2k_rc4.c	                        (rev 0)
+++ trunk/src/lib/crypto/krb/s2k_rc4.c	2011-03-05 13:31:02 UTC (rev 24679)
@@ -0,0 +1,37 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include "crypto_int.h"
+#include "k5-utf8.h"
+
+krb5_error_code
+krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp,
+                              const krb5_data *string, const krb5_data *salt,
+                              const krb5_data *params, krb5_keyblock *key)
+{
+    krb5_error_code err = 0;
+    krb5_crypto_iov iov;
+    krb5_data hash_out;
+    unsigned char *copystr;
+    size_t copystrlen;
+
+    if (params != NULL)
+        return KRB5_ERR_BAD_S2K_PARAMS;
+
+    if (key->length != 16)
+        return (KRB5_BAD_MSIZE);
+
+    /* We ignore salt per the Microsoft spec. */
+    err = krb5int_utf8cs_to_ucs2les(string->data, string->length, &copystr,
+                                    &copystrlen);
+    if (err)
+        return err;
+
+    /* the actual MD4 hash of the data */
+    iov.flags = KRB5_CRYPTO_TYPE_DATA;
+    iov.data = make_data(copystr, copystrlen);
+    hash_out = make_data(key->contents, key->length);
+    err = krb5int_hash_md4.hash(&iov, 1, &hash_out);
+
+    /* Zero out the data behind us */
+    zapfree(copystr, copystrlen);
+    return err;
+}




More information about the cvs-krb5 mailing list