svn rev #24699: trunk/src/lib/crypto/ builtin/des/ crypto_tests/ krb/ nss/des/ ...

ghudson@MIT.EDU ghudson at MIT.EDU
Thu Mar 10 23:20:17 EST 2011


http://src.mit.edu/fisheye/changelog/krb5/?cs=24699
Commit By: ghudson
Log Message:
Move the des and AFS string-to-key implementations into lib/crypto/krb,
since they aren't standard crypto primitives.  Revise the module SPI
accordingly.  Add tests for AFS string-to-key to t_str2key.c to replace
the ones in the (now defunct) t_afss2k.c.



Changed Files:
U   trunk/src/lib/crypto/builtin/des/Makefile.in
D   trunk/src/lib/crypto/builtin/des/afsstring2key.c
U   trunk/src/lib/crypto/builtin/des/des_int.h
A   trunk/src/lib/crypto/builtin/des/des_keys.c
U   trunk/src/lib/crypto/builtin/des/f_parity.c
D   trunk/src/lib/crypto/builtin/des/string2key.c
D   trunk/src/lib/crypto/builtin/des/t_afss2k.c
U   trunk/src/lib/crypto/crypto_tests/t_str2key.c
U   trunk/src/lib/crypto/krb/crypto_int.h
U   trunk/src/lib/crypto/krb/random_to_key.c
U   trunk/src/lib/crypto/krb/s2k_des.c
U   trunk/src/lib/crypto/nss/des/Makefile.in
A   trunk/src/lib/crypto/nss/des/des_keys.c
D   trunk/src/lib/crypto/nss/des/des_oldapis.c
D   trunk/src/lib/crypto/nss/des/f_parity.c
D   trunk/src/lib/crypto/nss/des/string2key.c
U   trunk/src/lib/crypto/nss/enc_provider/des.c
U   trunk/src/lib/crypto/nss/enc_provider/enc_gen.c
U   trunk/src/lib/crypto/openssl/des/Makefile.in
A   trunk/src/lib/crypto/openssl/des/des_keys.c
D   trunk/src/lib/crypto/openssl/des/des_oldapis.c
D   trunk/src/lib/crypto/openssl/des/f_parity.c
D   trunk/src/lib/crypto/openssl/des/string2key.c
U   trunk/src/lib/crypto/openssl/enc_provider/des.c
Modified: trunk/src/lib/crypto/builtin/des/Makefile.in
===================================================================
--- trunk/src/lib/crypto/builtin/des/Makefile.in	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/builtin/des/Makefile.in	2011-03-11 04:20:17 UTC (rev 24699)
@@ -13,41 +13,38 @@
 
 
 STLIBOBJS=\
-	afsstring2key.o	\
 	d3_aead.o	\
 	d3_kysched.o	\
+	des_keys.o	\
 	f_aead.o 	\
 	f_cksum.o	\
 	f_parity.o 	\
 	f_sched.o 	\
 	f_tables.o	\
 	key_sched.o	\
-	string2key.o	\
 	weak_key.o
 
-OBJS=	$(OUTPRE)afsstring2key.$(OBJEXT)	\
-	$(OUTPRE)d3_aead.$(OBJEXT)	\
+OBJS=	$(OUTPRE)d3_aead.$(OBJEXT)	\
 	$(OUTPRE)d3_kysched.$(OBJEXT)	\
+	$(OUTPRE)des_keys.c.$(OBJEXT)	\
 	$(OUTPRE)f_aead.$(OBJEXT) 	\
 	$(OUTPRE)f_cksum.$(OBJEXT)	\
 	$(OUTPRE)f_parity.$(OBJEXT) 	\
 	$(OUTPRE)f_sched.$(OBJEXT) 	\
 	$(OUTPRE)f_tables.$(OBJEXT)	\
 	$(OUTPRE)key_sched.$(OBJEXT)	\
-	$(OUTPRE)string2key.$(OBJEXT)	\
 	$(OUTPRE)weak_key.$(OBJEXT)
 
-SRCS=	$(srcdir)/afsstring2key.c	\
-	$(srcdir)/d3_aead.c	\
+SRCS=	$(srcdir)/d3_aead.c	\
 	$(srcdir)/d3_kysched.c	\
+	$(srcdir)/des_keys.c	\
 	$(srcdir)/f_aead.c	\
 	$(srcdir)/f_cksum.c	\
 	$(srcdir)/f_parity.c	\
 	$(srcdir)/f_sched.c	\
 	$(srcdir)/f_tables.c	\
 	$(srcdir)/key_sched.c	\
-	$(srcdir)/weak_key.c	\
-	$(srcdir)/string2key.c
+	$(srcdir)/weak_key.c
 
 EXTRADEPSRCS = $(srcdir)/destest.c $(srcdir)/f_cbc.c $(srcdir)/t_verify.c
 
@@ -67,19 +64,11 @@
 
 all-unix:: all-libobjs
 
-TAFSS2KOBJS =							   \
-	t_afss2k.$(OBJEXT) $(TOBJS)				     \
-	afsstring2key.$(OBJEXT) f_parity.$(OBJEXT) weak_key.$(OBJEXT)
-
-t_afss2k$(EXEEXT): $(TAFSS2KOBJS) $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
-	$(CC_LINK) -o $@ $(TAFSS2KOBJS) -lcom_err $(SUPPORT_LIB)
-
-check-unix:: verify destest t_afss2k
+check-unix:: verify destest
 	$(RUN_SETUP) $(VALGRIND) ./verify -z
 	$(RUN_SETUP) $(VALGRIND) ./verify -m
 	$(RUN_SETUP) $(VALGRIND) ./verify
 	$(RUN_SETUP) $(VALGRIND) ./destest < $(srcdir)/keytest.data
-	$(RUN_SETUP) $(VALGRIND) ./t_afss2k
 
 includes:: depend
 
@@ -89,7 +78,7 @@
 
 clean::
 	$(RM) destest.$(OBJEXT) destest$(EXEEXT) verify$(EXEEXT) \
-	t_verify.$(OBJEXT) t_afss2k.$(OBJEXT) t_afss2k$(EXEEXT) $(TOBJS)
+	t_verify.$(OBJEXT) $(TOBJS)
 
 clean-unix:: clean-libobjs
 

Modified: trunk/src/lib/crypto/builtin/des/des_int.h
===================================================================
--- trunk/src/lib/crypto/builtin/des/des_int.h	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/builtin/des/des_int.h	2011-03-11 04:20:17 UTC (rev 24699)
@@ -184,6 +184,7 @@
                                         krb5_pointer *);
 
 /* key_parity.c */
+void mit_des_fixup_key_parity(mit_des_cblock);
 int mit_des_check_key_parity(mit_des_cblock);
 
 /* key_sched.c */

Added: trunk/src/lib/crypto/builtin/des/des_keys.c
===================================================================
--- trunk/src/lib/crypto/builtin/des/des_keys.c	                        (rev 0)
+++ trunk/src/lib/crypto/builtin/des/des_keys.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -0,0 +1,40 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */
+/*
+ * Copyright (C) 2011 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"
+#include "des_int.h"
+
+void
+k5_des_fixup_key_parity(unsigned char *keybits)
+{
+    mit_des_fixup_key_parity(keybits);
+}
+
+krb5_boolean
+k5_des_is_weak_key(unsigned char *keybits)
+{
+    return mit_des_is_weak_key(keybits);
+}

Modified: trunk/src/lib/crypto/builtin/des/f_parity.c
===================================================================
--- trunk/src/lib/crypto/builtin/des/f_parity.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/builtin/des/f_parity.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -9,7 +9,7 @@
  * Mark Eichin -- Cygnus Support
  */
 
-#include "crypto_int.h"
+
 #include "des_int.h"
 
 /*
@@ -22,10 +22,10 @@
 #define parity_char(x) pstep(pstep(pstep((x),4),2),1)
 
 void
-mit_des_fixup_key_parity(unsigned char *key)
+mit_des_fixup_key_parity(mit_des_cblock key)
 {
     unsigned int i;
-    for (i=0; i<8; i++)
+    for (i=0; i<sizeof(mit_des_cblock); i++)
     {
         key[i] &= 0xfe;
         key[i] |= 1^parity_char(key[i]);

Modified: trunk/src/lib/crypto/crypto_tests/t_str2key.c
===================================================================
--- trunk/src/lib/crypto/crypto_tests/t_str2key.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/crypto_tests/t_str2key.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -1,5 +1,5 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/crypto_tests/t_str2key.c */
+/* lib/crypto/crypto_tests/t_str2key.c - String-to-key test vectors */
 /*
  * Copyright (C) 2010 by the Massachusetts Institute of Technology.
  * All rights reserved.
@@ -24,11 +24,6 @@
  * or implied warranty.
  */
 
-/*
- *
- * String-to-key test vectors
- */
-
 #include "k5-int.h"
 
 struct test {
@@ -38,6 +33,176 @@
     krb5_data params;
     krb5_data expected_key;
 } test_cases[] = {
+    /* AFS string-to-key tests from old t_afss2k.c. */
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xA4\xD0\xD0\x9B\x86\x92\xB0\xC2" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "M",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xF1\xF2\x9E\xAB\xD0\xEF\xDF\x73" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xD6\x85\x61\xC4\xF2\x94\xF4\xA1" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My ",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xD0\xE3\xA7\x83\x94\x61\xE0\xD0" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My P",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xD5\x62\xCD\x94\x61\xCB\x97\xDF" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pa",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x9E\xA2\xA2\xEC\xA8\x8C\x6B\x8F" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pas",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xE3\x91\x6D\xD3\x85\xF1\x67\xC4" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pass",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xF4\xC4\x73\xC8\x8A\xE9\x94\x6D" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passw",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xA1\x9E\xB3\xAD\x6B\xE3\xAB\xD9" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passwo",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xAD\xA1\xCE\x10\x37\x83\xA7\x8C" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passwor",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xD3\x01\xD0\xF7\x3E\x7A\x49\x0B" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Password",
+        "Sodium Chloride",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xB6\x2A\x4A\xEC\x9D\x4C\x68\xDF" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x61\xEF\xE6\x83\xE5\x8A\x6B\x98" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "M",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x68\xCD\x68\xAD\xC4\x86\xCD\xE5" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x83\xA1\xC8\x86\x8F\x67\xD0\x62" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My ",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x9E\xC7\x8F\xA4\xA4\xB3\xE0\xD5" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My P",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xD9\x92\x86\x8F\x9D\x8C\x85\xE6" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pa",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xDA\xF2\x92\x83\xF4\x9B\xA7\xAD" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pas",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x91\xCD\xAD\xEF\x86\xDF\xD3\xA2" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Pass",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x73\xD3\x67\x68\x8F\x6E\xE3\x73" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passw",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xC4\x61\x85\x9D\xAD\xF4\xDC\xB0" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passwo",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\xE9\x02\x83\x16\x2C\xEC\xE0\x08" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Passwor",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x61\xC8\x26\x29\xD9\x73\x6E\xB6" }
+    },
+    {
+        ENCTYPE_DES_CBC_CRC,
+        "My Password",
+        "NaCl",
+        { KV5M_DATA, 1, "\1" },
+        { KV5M_DATA, 8, "\x8C\xA8\x9E\xC4\xA8\xDC\x31\x73" }
+    },
+
     /* Test vectors from RFC 3961 appendix A.2. */
     {
         ENCTYPE_DES_CBC_CRC,

Modified: trunk/src/lib/crypto/krb/crypto_int.h
===================================================================
--- trunk/src/lib/crypto/krb/crypto_int.h	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/krb/crypto_int.h	2011-03-11 04:20:17 UTC (rev 24699)
@@ -432,16 +432,11 @@
 
 /* Modules must implement the following functions. */
 
-/* Set the parity bits in a DES key. */
-void mit_des_fixup_key_parity(unsigned char *key);
+/* Set the parity bits to the correct values in keybits. */
+void k5_des_fixup_key_parity(unsigned char *keybits);
 
-/* Convert a password to a DES key (see RFC 3961). */
-krb5_error_code mit_afs_string_to_key(krb5_keyblock *keyblock,
-                                      const krb5_data *password,
-                                      const krb5_data *salt);
-krb5_error_code mit_des_string_to_key_int(krb5_keyblock *key,
-                                          const krb5_data *password,
-                                          const krb5_data *salt);
+/* Return true if keybits is a weak or semi-weak DES key. */
+krb5_boolean k5_des_is_weak_key(unsigned char *keybits);
 
 /* Compute an HMAC using the provided hash function, key, and data, storing the
  * result into output (caller-allocated). */

Modified: trunk/src/lib/crypto/krb/random_to_key.c
===================================================================
--- trunk/src/lib/crypto/krb/random_to_key.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/krb/random_to_key.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -92,7 +92,7 @@
      * 8 key bytes, then compute the parity bits. */
     memcpy(keyblock->contents, randombits->data, randombits->length);
     eighth_byte(keyblock->contents);
-    mit_des_fixup_key_parity(keyblock->contents);
+    k5_des_fixup_key_parity(keyblock->contents);
 
     return 0;
 }
@@ -112,7 +112,7 @@
     for (i = 0; i < 3; i++) {
         memcpy(&keyblock->contents[i * 8], &randombits->data[i * 7], 7);
         eighth_byte(&keyblock->contents[i * 8]);
-        mit_des_fixup_key_parity(&keyblock->contents[i * 8]);
+        k5_des_fixup_key_parity(&keyblock->contents[i * 8]);
     }
     return 0;
 }

Modified: trunk/src/lib/crypto/krb/s2k_des.c
===================================================================
--- trunk/src/lib/crypto/krb/s2k_des.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/krb/s2k_des.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -25,26 +25,672 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * RFC 3961 and AFS string to key.  These are not standard crypto primitives
+ * (RFC 3961 string-to-key is implemented in OpenSSL for historical reasons but
+ * it doesn't get weak keys right), so we have to implement them here.
+ */
+
+#include <ctype.h>
 #include "crypto_int.h"
 
+#undef min
+#define min(a,b) ((a)>(b)?(b):(a))
+
+/* Compute a CBC checksum of in (with length len) using the specified key and
+ * ivec.  The result is written into out. */
+static krb5_error_code
+des_cbc_mac(const unsigned char *keybits, const unsigned char *ivec,
+            const unsigned char *in, size_t len, unsigned char *out)
+{
+    krb5_error_code ret;
+    krb5_keyblock kb;
+    krb5_key key;
+    krb5_crypto_iov iov[2];
+    unsigned char zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    krb5_data outd, ivecd;
+
+    /* Make a key from keybits. */
+    kb.magic = KV5M_KEYBLOCK;
+    kb.enctype = ENCTYPE_DES_CBC_CRC;
+    kb.length = 8;
+    kb.contents = (unsigned char *)keybits;
+    ret = krb5_k_create_key(NULL, &kb, &key);
+    if (ret)
+        return ret;
+
+    /* Make iovs for the input data, padding it out to the block size. */
+    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[0].data = make_data((unsigned char *)in, len);
+    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+    iov[1].data = make_data(zero, krb5_roundup(len, 8) - len);
+
+    /* Make krb5_data structures for the ivec and output. */
+    ivecd = make_data((unsigned char *)ivec, 8);
+    outd = make_data(out, 8);
+
+    /* Call the cbc_mac operation of the module's DES enc-provider. */
+    ret = krb5int_enc_des.cbc_mac(key, iov, 2, &ivecd, &outd);
+    krb5_k_free_key(NULL, key);
+    return ret;
+}
+
+/*** AFS string-to-key constants ***/
+
+/* Initial permutation */
+static const char IP[] = {
+    58,50,42,34,26,18,10, 2,
+    60,52,44,36,28,20,12, 4,
+    62,54,46,38,30,22,14, 6,
+    64,56,48,40,32,24,16, 8,
+    57,49,41,33,25,17, 9, 1,
+    59,51,43,35,27,19,11, 3,
+    61,53,45,37,29,21,13, 5,
+    63,55,47,39,31,23,15, 7,
+};
+
+/* Final permutation, FP = IP^(-1) */
+static const char FP[] = {
+    40, 8,48,16,56,24,64,32,
+    39, 7,47,15,55,23,63,31,
+    38, 6,46,14,54,22,62,30,
+    37, 5,45,13,53,21,61,29,
+    36, 4,44,12,52,20,60,28,
+    35, 3,43,11,51,19,59,27,
+    34, 2,42,10,50,18,58,26,
+    33, 1,41, 9,49,17,57,25,
+};
+
+/*
+ * Permuted-choice 1 from the key bits to yield C and D.
+ * Note that bits 8,16... are left out: They are intended for a parity check.
+ */
+static const char PC1_C[] = {
+    57,49,41,33,25,17, 9,
+    1,58,50,42,34,26,18,
+    10, 2,59,51,43,35,27,
+    19,11, 3,60,52,44,36,
+};
+
+static const char PC1_D[] = {
+    63,55,47,39,31,23,15,
+    7,62,54,46,38,30,22,
+    14, 6,61,53,45,37,29,
+    21,13, 5,28,20,12, 4,
+};
+
+/* Sequence of shifts used for the key schedule */
+static const char shifts[] = {
+    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
+};
+
+/* Permuted-choice 2, to pick out the bits from the CD array that generate the
+ * key schedule */
+static const char PC2_C[] = {
+    14,17,11,24, 1, 5,
+    3,28,15, 6,21,10,
+    23,19,12, 4,26, 8,
+    16, 7,27,20,13, 2,
+};
+
+static const char PC2_D[] = {
+    41,52,31,37,47,55,
+    30,40,51,45,33,48,
+    44,49,39,56,34,53,
+    46,42,50,36,29,32,
+};
+
+/* The E bit-selection table */
+static const char e[] = {
+    32, 1, 2, 3, 4, 5,
+    4, 5, 6, 7, 8, 9,
+    8, 9,10,11,12,13,
+    12,13,14,15,16,17,
+    16,17,18,19,20,21,
+    20,21,22,23,24,25,
+    24,25,26,27,28,29,
+    28,29,30,31,32, 1,
+};
+
+/* P is a permutation on the selected combination of the current L and key. */
+static const char P[] = {
+    16, 7,20,21,
+    29,12,28,17,
+    1,15,23,26,
+    5,18,31,10,
+    2, 8,24,14,
+    32,27, 3, 9,
+    19,13,30, 6,
+    22,11, 4,25,
+};
+
+/*
+ * The 8 selection functions.
+ * For some reason, they give a 0-origin
+ * index, unlike everything else.
+ */
+static const char S[8][64] = {
+    {14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
+     0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
+     4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
+     15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13},
+
+    {15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
+     3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
+     0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
+     13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9},
+
+    {10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
+     13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
+     13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
+     1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12},
+
+    { 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
+      13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
+      10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
+      3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14},
+
+    { 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
+      14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
+      4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
+      11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3},
+
+    {12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
+     10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
+     9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
+     4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13},
+
+    { 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
+      13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
+      1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
+      6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12},
+
+    {13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
+     1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
+     7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
+     2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11},
+};
+
+
+/* Set up the key schedule from the key. */
+static void
+afs_crypt_setkey(char *key, char *E, char (*KS)[48])
+{
+    int i, j, k, t;
+    char C[28], D[28];          /* Used to calculate key schedule. */
+
+    /*
+     * First, generate C and D by permuting
+     * the key.  The low order bit of each
+     * 8-bit char is not used, so C and D are only 28
+     * bits apiece.
+     */
+    for (i = 0; i < 28; i++) {
+        C[i] = key[PC1_C[i] - 1];
+        D[i] = key[PC1_D[i] - 1];
+    }
+    /*
+     * To generate Ki, rotate C and D according
+     * to schedule and pick up a permutation
+     * using PC2.
+     */
+    for (i = 0; i < 16; i++) {
+        /* Rotate. */
+        for (k = 0; k < shifts[i]; k++) {
+            t = C[0];
+            for (j = 0; j < 28 - 1; j++)
+                C[j] = C[j + 1];
+            C[27] = t;
+            t = D[0];
+            for (j = 0; j < 28 - 1; j++)
+                D[j] = D[j + 1];
+            D[27] = t;
+        }
+        /* Get Ki.  Note C and D are concatenated. */
+        for (j = 0; j < 24; j++) {
+            KS[i][j] = C[PC2_C[j]-1];
+            KS[i][j+24] = D[PC2_D[j]-28-1];
+        }
+    }
+
+    memcpy(E, e, 48);
+}
+
+/*
+ * The payoff: encrypt a block.
+ */
+
+static void
+afs_encrypt_block(char *block, char *E, char (*KS)[48])
+{
+    const long edflag = 0;
+    int i, ii;
+    int t, j, k;
+    char tempL[32];
+    char f[32];
+    char L[64];                 /* Current block divided into two halves */
+    char *const R = &L[32];
+    /* The combination of the key and the input, before selection. */
+    char preS[48];
+
+    /* First, permute the bits in the input. */
+    for (j = 0; j < 64; j++)
+        L[j] = block[IP[j] - 1];
+    /* Perform an encryption operation 16 times. */
+    for (ii = 0; ii < 16; ii++) {
+        /* Set direction. */
+        i = (edflag) ? 15 - ii : ii;
+        /* Save the R array, which will be the new L. */
+        memcpy(tempL, R, 32);
+        /* Expand R to 48 bits using the E selector; exclusive-or with the
+         * current key bits. */
+        for (j = 0; j < 48; j++)
+            preS[j] = R[E[j] - 1] ^ KS[i][j];
+        /*
+         * The pre-select bits are now considered in 8 groups of 6 bits each.
+         * The 8 selection functions map these 6-bit quantities into 4-bit
+         * quantities and the results permuted to make an f(R, K).  The
+         * indexing into the selection functions is peculiar; it could be
+         * simplified by rewriting the tables.
+         */
+        for (j = 0; j < 8; j++) {
+            t = 6 * j;
+            k = S[j][(preS[t + 0] << 5) +
+                     (preS[t + 1] << 3) +
+                     (preS[t + 2] << 2) +
+                     (preS[t + 3] << 1) +
+                     (preS[t + 4] << 0) +
+                     (preS[t + 5] << 4)];
+            t = 4 * j;
+            f[t + 0] = (k >> 3) & 1;
+            f[t + 1] = (k >> 2) & 1;
+            f[t + 2] = (k >> 1) & 1;
+            f[t + 3] = (k >> 0) & 1;
+        }
+        /* The new R is L ^ f(R, K).  The f here has to be permuted first,
+         * though. */
+        for (j = 0; j < 32; j++)
+            R[j] = L[j] ^ f[P[j] - 1];
+        /* Finally, the new L (the original R) is copied back. */
+        memcpy(L, tempL, 32);
+    }
+    /* The output L and R are reversed. */
+    for (j = 0; j < 32; j++) {
+        t = L[j];
+        L[j] = R[j];
+        R[j] = t;
+    }
+    /* The final output gets the inverse permutation of the very original. */
+    for (j = 0; j < 64; j++)
+        block[j] = L[FP[j] - 1];
+}
+
+/* iobuf must be at least 16 bytes */
+static char *
+afs_crypt(const char *pw, const char *salt, char *iobuf)
+{
+    int i, j, c;
+    int temp;
+    char block[66];
+    char E[48];
+    char KS[16][48];            /* Key schedule, generated from key */
+
+    for (i = 0; i < 66; i++)
+        block[i] = 0;
+    for (i = 0; (c = *pw) != '\0' && i < 64; pw++){
+        for(j = 0; j < 7; j++, i++)
+            block[i] = (c >> (6 - j)) & 01;
+        i++;
+    }
+
+    afs_crypt_setkey(block, E, KS);
+
+    for (i = 0; i < 66; i++)
+        block[i] = 0;
+
+    for (i = 0; i < 2; i++) {
+        c = *salt++;
+        iobuf[i] = c;
+        if (c > 'Z')
+            c -= 6;
+        if (c > '9')
+            c -= 7;
+        c -= '.';
+        for (j = 0; j < 6; j++) {
+            if ((c >> j) & 01) {
+                temp = E[6 * i + j];
+                E[6 * i + j] = E[6 * i + j + 24];
+                E[6 * i + j + 24] = temp;
+            }
+        }
+    }
+
+    for (i = 0; i < 25; i++)
+        afs_encrypt_block(block, E, KS);
+
+    for (i = 0; i < 11; i++) {
+        c = 0;
+        for (j = 0; j < 6; j++) {
+            c <<= 1;
+            c |= block[6 * i + j];
+        }
+        c += '.';
+        if (c > '9')
+            c += 7;
+        if (c > 'Z')
+            c += 6;
+        iobuf[i + 2] = c;
+    }
+    iobuf[i + 2] = 0;
+    if (iobuf[1] == 0)
+        iobuf[1] = iobuf[0];
+    return iobuf;
+}
+
+static krb5_error_code
+afs_s2k_oneblock(const krb5_data *data, const krb5_data *salt,
+                 unsigned char *key_out)
+{
+    unsigned int i;
+    unsigned char password[9]; /* trailing nul for crypt() */
+    char afs_crypt_buf[16];
+
+    /*
+     * Run afs_crypt and use the first eight returned bytes after the copy of
+     * the (fixed) salt.
+     *
+     * Since the returned bytes are alphanumeric, the output is limited to
+     * 2**48 possibilities; for each byte, only 64 possible values can be used.
+     */
+
+    memset(password, 0, sizeof(password));
+    memcpy(password, salt->data, min(salt->length, 8));
+    for (i = 0; i < 8; i++) {
+        if (isupper(password[i]))
+            password[i] = tolower(password[i]);
+    }
+    for (i = 0; i < data->length; i++)
+        password[i] ^= data->data[i];
+    for (i = 0; i < 8; i++) {
+        if (password[i] == '\0')
+            password[i] = 'X';
+    }
+    password[8] = '\0';
+    /* Out-of-bounds salt characters are equivalent to a salt string
+     * of "p1". */
+    strncpy((char *)key_out,
+            (char *)afs_crypt((char *)password, "#~", afs_crypt_buf) + 2, 8);
+    for (i = 0; i < 8; i++)
+        key_out[i] <<= 1;
+    /* Fix up key parity again. */
+    k5_des_fixup_key_parity(key_out);
+    zap(password, sizeof(password));
+    return 0;
+}
+
+static krb5_error_code
+afs_s2k_multiblock(const krb5_data *data, const krb5_data *salt,
+                   unsigned char *key_out)
+{
+    krb5_error_code ret;
+    unsigned char ivec[8], tkey[8], *password;
+    size_t pw_len = salt->length + data->length;
+    unsigned int i, j;
+
+    /* Do a CBC checksum, twice, and use the result as the new key.  */
+
+    password = malloc(pw_len);
+    if (!password)
+        return ENOMEM;
+
+    memcpy(password, data->data, data->length);
+    for (i = data->length, j = 0; j < salt->length; i++, j++) {
+        password[i] = salt->data[j];
+        if (isupper(password[i]))
+            password[i] = tolower(password[i]);
+    }
+
+    memcpy(ivec, "kerberos", sizeof(ivec));
+    memcpy(tkey, ivec, sizeof(tkey));
+    k5_des_fixup_key_parity(tkey);
+    ret = des_cbc_mac(tkey, ivec, password, pw_len, tkey);
+    if (ret)
+        goto cleanup;
+
+    memcpy(ivec, tkey, sizeof(ivec));
+    k5_des_fixup_key_parity(tkey);
+    ret = des_cbc_mac(tkey, ivec, password, pw_len, key_out);
+    if (ret)
+        goto cleanup;
+    k5_des_fixup_key_parity(key_out);
+
+cleanup:
+    zapfree(password, pw_len);
+    return ret;
+}
+
+static krb5_error_code
+afs_s2k(const krb5_data *data, const krb5_data *salt, unsigned char *key_out)
+{
+    if (data->length <= 8)
+        return afs_s2k_oneblock(data, salt, key_out);
+    else
+        return afs_s2k_multiblock(data, salt, key_out);
+}
+
+static krb5_error_code
+des_s2k(const krb5_data *pw, const krb5_data *salt, unsigned char *key_out)
+{
+    union {
+        /* 8 "forward" bytes, 8 "reverse" bytes */
+        unsigned char uc[16];
+        krb5_ui_4 ui[4];
+    } temp;
+    unsigned int i;
+    krb5_ui_4 x, y, z;
+    unsigned char *p, *copy;
+    size_t copylen;
+    krb5_error_code ret;
+
+    /* As long as the architecture is big-endian or little-endian, it
+       doesn't matter which it is.  Think of it as reversing the
+       bytes, and also reversing the bits within each byte.  But this
+       current algorithm is dependent on having four 8-bit char values
+       exactly overlay a 32-bit integral type.  */
+    if (sizeof(temp.uc) != sizeof(temp.ui)
+        || (unsigned char)~0 != 0xFF
+        || (krb5_ui_4)~(krb5_ui_4)0 != 0xFFFFFFFF
+        || (temp.uc[0] = 1, temp.uc[1] = 2, temp.uc[2] = 3, temp.uc[3] = 4,
+            !(temp.ui[0] == 0x01020304
+              || temp.ui[0] == 0x04030201)))
+        abort();
+#define FETCH4(VAR, IDX)        VAR = temp.ui[IDX/4]
+#define PUT4(VAR, IDX)          temp.ui[IDX/4] = VAR
+
+    copylen = pw->length + (salt ? salt->length : 0);
+    /* Don't need NUL termination, at this point we're treating it as
+       a byte array, not a string.  */
+    copy = malloc(copylen);
+    if (copy == NULL)
+        return ENOMEM;
+    memcpy(copy, pw->data, pw->length);
+    if (salt)
+        memcpy(copy + pw->length, salt->data, salt->length);
+
+    memset(&temp, 0, sizeof(temp));
+    p = temp.uc;
+    /* Handle the fan-fold xor operation by splitting the data into
+       forward and reverse sections, and combine them later, rather
+       than having to do the reversal over and over again.  */
+    for (i = 0; i < copylen; i++) {
+        *p++ ^= copy[i];
+        if (p == temp.uc+16) {
+            p = temp.uc;
+#ifdef PRINT_TEST_VECTORS
+            {
+                int j;
+                printf("after %d input bytes:\nforward block:\t", i+1);
+                for (j = 0; j < 8; j++)
+                    printf(" %02x", temp.uc[j] & 0xff);
+                printf("\nreverse block:\t");
+                for (j = 8; j < 16; j++)
+                    printf(" %02x", temp.uc[j] & 0xff);
+                printf("\n");
+            }
+#endif
+        }
+    }
+
+#ifdef PRINT_TEST_VECTORS
+    if (p != temp.uc) {
+        int j;
+        printf("at end, after %d input bytes:\nforward block:\t", i);
+        for (j = 0; j < 8; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\nreverse block:\t");
+        for (j = 8; j < 16; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+#define REVERSE(VAR)                            \
+    {                                           \
+        krb5_ui_4 old = VAR, temp1 = 0;         \
+        int j;                                  \
+        for (j = 0; j < 32; j++) {              \
+            temp1 = (temp1 << 1) | (old & 1);   \
+            old >>= 1;                          \
+        }                                       \
+        VAR = temp1;                            \
+    }
+
+    FETCH4 (x, 8);
+    FETCH4 (y, 12);
+    /* Ignore high bits of each input byte.  */
+    x &= 0x7F7F7F7F;
+    y &= 0x7F7F7F7F;
+    /* Reverse the bit strings -- after this, y is "before" x.  */
+    REVERSE (x);
+    REVERSE (y);
+#ifdef PRINT_TEST_VECTORS
+    {
+        int j;
+        union { unsigned char uc[4]; krb5_ui_4 ui; } t2;
+        printf("after reversal, reversed block:\n\t\t");
+        t2.ui = y;
+        for (j = 0; j < 4; j++)
+            printf(" %02x", t2.uc[j] & 0xff);
+        t2.ui = x;
+        for (j = 0; j < 4; j++)
+            printf(" %02x", t2.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+    /* Ignored bits are now at the bottom of each byte, where we'll
+     * put the parity bits.  Good.  */
+    FETCH4 (z, 0);
+    z &= 0x7F7F7F7F;
+    /* Ignored bits for z are at the top of each byte; fix that.  */
+    z <<= 1;
+    /* Finish the fan-fold xor for these four bytes.  */
+    z ^= y;
+    PUT4 (z, 0);
+    /* Now do the second four bytes.  */
+    FETCH4 (z, 4);
+    z &= 0x7F7F7F7F;
+    /* Ignored bits for z are at the top of each byte; fix that.  */
+    z <<= 1;
+    /* Finish the fan-fold xor for these four bytes.  */
+    z ^= x;
+    PUT4 (z, 4);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+        int j;
+        printf("after reversal, combined block:\n\t\t");
+        for (j = 0; j < 8; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+
+#define FIXUP(k) (k5_des_fixup_key_parity(k),                   \
+                  k5_des_is_weak_key(k) ? (k[7] ^= 0xF0) : 0)
+
+    /* Now temp.cb is the temporary key, with invalid parity.  */
+    FIXUP(temp.uc);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+        int j;
+        printf("after fixing parity and weak keys:\n\t\t");
+        for (j = 0; j < 8; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+
+    ret = des_cbc_mac(temp.uc, temp.uc, copy, copylen, temp.uc);
+    if (ret)
+        goto cleanup;
+
+#ifdef PRINT_TEST_VECTORS
+    {
+        int j;
+        printf("cbc checksum:\n\t\t");
+        for (j = 0; j < 8; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+
+    FIXUP(temp.uc);
+
+#ifdef PRINT_TEST_VECTORS
+    {
+        int j;
+        printf("after fixing parity and weak keys:\n\t\t");
+        for (j = 0; j < 8; j++)
+            printf(" %02x", temp.uc[j] & 0xff);
+        printf("\n");
+    }
+#endif
+
+    memcpy(key_out, temp.uc, 8);
+
+cleanup:
+    zap(&temp, sizeof(temp));
+    zapfree(copy, copylen);
+    return ret;
+}
+
 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)
+                          const krb5_data *parm, krb5_keyblock *keyblock)
 {
     int type;
-    if (parm) {
+    krb5_data afssalt;
+
+    if (parm != NULL) {
         if (parm->length != 1)
             return KRB5_ERR_BAD_S2K_PARAMS;
         type = parm->data[0];
+        if (type != 0 && type != 1)
+            return KRB5_ERR_BAD_S2K_PARAMS;
+    } else
+        type = 0;
+
+    /* Use AFS string to key if we were told to. */
+    if (type == 1)
+        return afs_s2k(string, salt, keyblock->contents);
+
+    /* Also use AFS string to key if the salt indicates it. */
+    if (salt != NULL && (salt->length == SALT_TYPE_AFS_LENGTH
+                         || salt->length == (unsigned)-1)) {
+        afssalt = make_data(salt->data, strcspn(salt->data, "@"));
+        return afs_s2k(string, &afssalt, keyblock->contents);
     }
-    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;
-    }
+
+    return des_s2k(string, salt, keyblock->contents);
 }

Modified: trunk/src/lib/crypto/nss/des/Makefile.in
===================================================================
--- trunk/src/lib/crypto/nss/des/Makefile.in	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/nss/des/Makefile.in	2011-03-11 04:20:17 UTC (rev 24699)
@@ -9,17 +9,11 @@
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
-STLIBOBJS= des_oldapis.o \
-	f_parity.o 	\
-	string2key.o
+STLIBOBJS= des_keys.o
 
-OBJS=	$(OUTPRE)f_parity.$(OBJEXT) 	\
-	$(OUTPRE)des_oldapis.$(OBJEXT) 	\
-	$(OUTPRE)string2key.$(OBJEXT)
+OBJS= $(OUTPRE)des_keys.$(OBJEXT)
 
-SRCS=	$(srcdir)/f_parity.c	\
-	$(srcdir)/des_oldapis.c	\
-	$(srcdir)/string2key.c
+SRCS= $(srcdir)/des_keys.c
 
 all-unix:: all-libobjs
 

Added: trunk/src/lib/crypto/nss/des/des_keys.c
===================================================================
--- trunk/src/lib/crypto/nss/des/des_keys.c	                        (rev 0)
+++ trunk/src/lib/crypto/nss/des/des_keys.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -0,0 +1,87 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/nss/des/des_keys.c - Key functions used by Kerberos code */
+/*
+ * Copyright (C) 2011 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"
+
+/*
+ * des_fixup_key_parity: Forces odd parity per byte; parity is bits
+ *                       8,16,...64 in des order, implies 0, 8, 16, ...
+ *                       vax order.
+ */
+#define smask(step) ((1<<step)-1)
+#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+#define parity_char(x) pstep(pstep(pstep((x),4),2),1)
+
+void
+k5_des_fixup_key_parity(unsigned char *keybits)
+{
+    unsigned int i;
+
+    for (i = 0; i < 8; i++) {
+        keybits[i] &= 0xfe;
+        keybits[i] |= 1^parity_char(keybits[i]);
+    }
+}
+
+/* The following are the weak DES keys: */
+static const unsigned char weak[16][8] = {
+    /* Weak keys */
+    {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+    {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
+    {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
+    {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
+
+    /* Semi-weak */
+    {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe},
+    {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01},
+
+    {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1},
+    {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e},
+
+    {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1},
+    {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01},
+
+    {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe},
+    {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e},
+
+    {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e},
+    {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01},
+
+    {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe},
+    {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1}
+};
+
+krb5_boolean
+k5_des_is_weak_key(unsigned char *keybits)
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(weak) / 8; i++) {
+        if (memcmp(weak[i], keybits, 8) == 0)
+            return TRUE;
+    }
+    return FALSE;
+}

Modified: trunk/src/lib/crypto/nss/enc_provider/des.c
===================================================================
--- trunk/src/lib/crypto/nss/enc_provider/des.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/nss/enc_provider/des.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -57,19 +57,32 @@
 {
     krb5_error_code ret;
 
-    ret = k5_nss_gen_import(key, CKM_DES_CBC, CKA_ENCRYPT);
+    ret = k5_nss_gen_import(key, CKM_DES_CBC, CKA_DECRYPT);
     if (ret != 0)
         return ret;
     return k5_nss_gen_block_iov(key, CKM_DES_CBC, CKA_DECRYPT,
                                 ivec, data, num_data);
 }
 
+static krb5_error_code
+k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
+               const krb5_data *ivec, krb5_data *output)
+{
+    krb5_error_code ret;
+
+    ret = k5_nss_gen_import(key, CKM_DES_CBC, CKA_ENCRYPT);
+    if (ret != 0)
+        return ret;
+    return k5_nss_gen_cbcmac_iov(key, CKM_DES_CBC, ivec, data, num_data,
+                                 output);
+}
+
 const struct krb5_enc_provider krb5int_enc_des = {
     8,
     7, KRB5_MIT_DES_KEYSIZE,
     k5_des_encrypt_iov,
     k5_des_decrypt_iov,
-    NULL,
+    k5_des_cbc_mac,
     krb5int_des_init_state,
     krb5int_default_free_state,
     k5_nss_gen_cleanup

Modified: trunk/src/lib/crypto/nss/enc_provider/enc_gen.c
===================================================================
--- trunk/src/lib/crypto/nss/enc_provider/enc_gen.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/nss/enc_provider/enc_gen.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -545,9 +545,8 @@
     SECStatus rv;
     SECItem *param = NULL;
     struct iov_block_state input_pos, output_pos;
-    unsigned char storage[MAX_BLOCK_SIZE];
+    unsigned char block[MAX_BLOCK_SIZE], *lastblock;
     unsigned char iv0[MAX_BLOCK_SIZE];
-    unsigned char *ptr = NULL, *lastptr = NULL;
     SECItem iv;
     size_t blocksize;
     int length = 0;
@@ -557,7 +556,7 @@
     IOV_BLOCK_STATE_INIT(&output_pos);
 
     blocksize = PK11_GetBlockSize(mech, NULL);
-    assert(blocksize <= sizeof(storage));
+    assert(blocksize <= sizeof(block));
     if (output->length < blocksize)
         return KRB5_BAD_MSIZE;
 
@@ -577,23 +576,19 @@
         goto done;
     }
 
-    lastptr = iv.data;
+    lastblock = iv.data;
     for (currentblock = 0;;currentblock++) {
-        if (!krb5int_c_iov_get_block_nocopy(storage, blocksize, data, num_data,
-                                            &input_pos, &ptr))
+        if (!krb5int_c_iov_get_block(block, blocksize, data, num_data,
+                                     &input_pos))
             break;
-
-        lastptr = NULL;
-
-        rv = PK11_CipherOp(ctx, ptr, &length, blocksize, ptr, blocksize);
+        rv = PK11_CipherOp(ctx, block, &length, blocksize, block, blocksize);
         if (rv != SECSuccess) {
             ret = k5_nss_map_last_error();
             goto done;
         }
-
-        lastptr = ptr;
+        lastblock = block;
     }
-    memcpy(output->data, lastptr, blocksize);
+    memcpy(output->data, lastblock, blocksize);
 
 done:
     if (ctx) {

Modified: trunk/src/lib/crypto/openssl/des/Makefile.in
===================================================================
--- trunk/src/lib/crypto/openssl/des/Makefile.in	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/openssl/des/Makefile.in	2011-03-11 04:20:17 UTC (rev 24699)
@@ -7,19 +7,12 @@
 PROG_LIBPATH=-L$(TOPLIBD)
 PROG_RPATH=$(KRB5_LIBDIR)
 
+STLIBOBJS= des_keys.o
 
-STLIBOBJS= des_oldapis.o \
-	f_parity.o 	\
-	string2key.o
+OBJS= $(OUTPRE)des_keys.$(OBJEXT)
 
-OBJS=	$(OUTPRE)f_parity.$(OBJEXT) 	\
-	$(OUTPRE)des_oldapis.$(OBJEXT) 	\
-	$(OUTPRE)string2key.$(OBJEXT)
+SRCS= $(srcdir)/des_keys.c
 
-SRCS=	$(srcdir)/f_parity.c	\
-	$(srcdir)/des_oldapis.c	\
-	$(srcdir)/string2key.c
-
 all-unix:: all-libobjs
 
 includes:: depend

Added: trunk/src/lib/crypto/openssl/des/des_keys.c
===================================================================
--- trunk/src/lib/crypto/openssl/des/des_keys.c	                        (rev 0)
+++ trunk/src/lib/crypto/openssl/des/des_keys.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -0,0 +1,40 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/openssl/des/des_keys.c - Key functions used by Kerberos code */
+/*
+ * Copyright (C) 2011 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"
+#include <openssl/des.h>
+
+void
+k5_des_fixup_key_parity(unsigned char *keybits)
+{
+    DES_set_odd_parity((DES_cblock *)keybits);
+}
+
+krb5_boolean
+k5_des_is_weak_key(unsigned char *keybits)
+{
+    return DES_is_weak_key((DES_cblock *)keybits);
+}

Modified: trunk/src/lib/crypto/openssl/enc_provider/des.c
===================================================================
--- trunk/src/lib/crypto/openssl/enc_provider/des.c	2011-03-11 04:17:42 UTC (rev 24698)
+++ trunk/src/lib/crypto/openssl/enc_provider/des.c	2011-03-11 04:20:17 UTC (rev 24699)
@@ -52,6 +52,7 @@
 
 #include "crypto_int.h"
 #include <openssl/evp.h>
+#include <openssl/des.h>
 
 #define DES_BLOCK_SIZE 8
 #define DES_KEY_SIZE 8
@@ -188,12 +189,50 @@
     return 0;
 }
 
+static krb5_error_code
+k5_des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data,
+               const krb5_data *ivec, krb5_data *output)
+{
+    int ret;
+    struct iov_block_state iov_state;
+    DES_cblock blockY, blockB;
+    DES_key_schedule sched;
+    krb5_boolean empty;
+
+    ret = validate(key, ivec, data, num_data, &empty);
+    if (ret != 0)
+        return ret;
+
+    if (output->length != DES_BLOCK_SIZE)
+        return KRB5_BAD_MSIZE;
+
+    if (DES_set_key((DES_cblock *)key->keyblock.contents, &sched) != 0)
+        return KRB5_CRYPTO_INTERNAL;
+
+    if (ivec != NULL)
+        memcpy(blockY, ivec->data, DES_BLOCK_SIZE);
+    else
+        memset(blockY, 0, DES_BLOCK_SIZE);
+
+    IOV_BLOCK_STATE_INIT(&iov_state);
+    for (;;) {
+        if (!krb5int_c_iov_get_block(blockB, DES_BLOCK_SIZE, data, num_data,
+                                     &iov_state))
+            break;
+        store_64_n(load_64_n(blockB) ^ load_64_n(blockY), blockB);
+        DES_ecb_encrypt(&blockB, &blockY, &sched, 1);
+    }
+
+    memcpy(output->data, blockY, DES_BLOCK_SIZE);
+    return 0;
+}
+
 const struct krb5_enc_provider krb5int_enc_des = {
     DES_BLOCK_SIZE,
     DES_KEY_BYTES, DES_KEY_SIZE,
     k5_des_encrypt,
     k5_des_decrypt,
-    NULL,
+    k5_des_cbc_mac,
     krb5int_des_init_state,
     krb5int_default_free_state
 };




More information about the cvs-krb5 mailing list