Move the des and AFS string-to-key implementations into lib/crypto/krb,
authorGreg Hudson <ghudson@mit.edu>
Fri, 11 Mar 2011 04:20:17 +0000 (04:20 +0000)
committerGreg Hudson <ghudson@mit.edu>
Fri, 11 Mar 2011 04:20:17 +0000 (04:20 +0000)
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.

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

22 files changed:
src/lib/crypto/builtin/des/Makefile.in
src/lib/crypto/builtin/des/afsstring2key.c [deleted file]
src/lib/crypto/builtin/des/des_int.h
src/lib/crypto/builtin/des/des_keys.c [moved from src/lib/crypto/openssl/des/des_oldapis.c with 77% similarity]
src/lib/crypto/builtin/des/f_parity.c
src/lib/crypto/builtin/des/string2key.c [deleted file]
src/lib/crypto/builtin/des/t_afss2k.c [deleted file]
src/lib/crypto/crypto_tests/t_str2key.c
src/lib/crypto/krb/crypto_int.h
src/lib/crypto/krb/random_to_key.c
src/lib/crypto/krb/s2k_des.c
src/lib/crypto/nss/des/Makefile.in
src/lib/crypto/nss/des/des_keys.c [new file with mode: 0644]
src/lib/crypto/nss/des/des_oldapis.c [deleted file]
src/lib/crypto/nss/des/f_parity.c [deleted file]
src/lib/crypto/nss/des/string2key.c [deleted file]
src/lib/crypto/nss/enc_provider/des.c
src/lib/crypto/nss/enc_provider/enc_gen.c
src/lib/crypto/openssl/des/Makefile.in
src/lib/crypto/openssl/des/des_keys.c [moved from src/lib/crypto/openssl/des/f_parity.c with 78% similarity]
src/lib/crypto/openssl/des/string2key.c [deleted file]
src/lib/crypto/openssl/enc_provider/des.c

index 9ac2f6cc6c3feb1ea59e4e4bde55da513a1fc50d..f63f9182eff46d45d5c7ff5bdb7f5dbf6ddb7f3a 100644 (file)
@@ -13,41 +13,38 @@ PROG_RPATH=$(KRB5_LIBDIR)
 
 
 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 @@ destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB)
 
 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 @@ check-windows::
 
 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
 
diff --git a/src/lib/crypto/builtin/des/afsstring2key.c b/src/lib/crypto/builtin/des/afsstring2key.c
deleted file mode 100644 (file)
index 03fbaba..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/builtin/des/afsstring2key.c */
-/*
- * Copyright 1989, 2001 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.
- */
-/*
- * 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.
- */
-/*
- * Copyright (c) 1990 Regents of The University of Michigan.
- * All Rights Reserved.
- *
- * 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 appears in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation, and that the name of
- * The University of Michigan not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission. This software is supplied as
- * is without expressed or implied warranties of any kind.
- *
- *      ITD Research Systems
- *      University of Michigan
- *      535 W. William Street
- *      Ann Arbor, Michigan
- *      +1-313-936-2652
- *      netatalk@terminator.cc.umich.edu
- */
-
-/*
- * based on lib/crypto/des/string2key.c from MIT V5
- * and on lib/des/afs_string_to_key.c from UMD.
- * constructed by Mark Eichin, Cygnus Support, 1995.
- * made thread-safe by Ken Raeburn, MIT, 2001.
- */
-
-#include "crypto_int.h"
-#include "des_int.h"
-#include <ctype.h>
-
-#define afs_crypt mit_afs_crypt
-char *afs_crypt (const char *, const char *, char *);
-
-#undef min
-#define min(a,b) ((a)>(b)?(b):(a))
-
-krb5_error_code
-mit_afs_string_to_key(krb5_keyblock *keyblock, const krb5_data *data,
-                      const krb5_data *salt)
-{
-    /* totally different approach from MIT string2key. */
-    /* much of the work has already been done by the only caller
-       which is mit_des_string_to_key; in particular, *keyblock is already
-       set up. */
-
-    char *realm = salt->data;
-    unsigned int i, j;
-    krb5_octet *key = keyblock->contents;
-
-    if (data->length <= 8) {
-        /* One block only.  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.  */
-        unsigned char password[9]; /* trailing nul for crypt() */
-        char afs_crypt_buf[16];
-
-        memset (password, 0, sizeof (password));
-        memcpy (password, realm, 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,
-                (char *) afs_crypt((char *) password, "#~", afs_crypt_buf) + 2,
-                8);
-        for (i=0; i<8; i++)
-            key[i] <<= 1;
-        /* now fix up key parity again */
-        mit_des_fixup_key_parity(key);
-        /* clean & free the input string */
-        memset(password, 0, (size_t) sizeof(password));
-    } else {
-        /* Multiple blocks.  Do a CBC checksum, twice, and use the
-           result as the new key.  */
-        mit_des_cblock ikey, tkey;
-        mit_des_key_schedule key_sked;
-        unsigned int pw_len = salt->length+data->length;
-        unsigned char *password = malloc(pw_len+1);
-        if (!password) return ENOMEM;
-
-        /* Some bound checks from the original code are elided here as
-           the malloc above makes sure we have enough storage. */
-        memcpy (password, data->data, data->length);
-        for (i=data->length, j = 0; j < salt->length; i++, j++) {
-            password[i] = realm[j];
-            if (isupper(password[i]))
-                password[i] = tolower(password[i]);
-        }
-
-        memcpy (ikey, "kerberos", sizeof(ikey));
-        memcpy (tkey, ikey, sizeof(tkey));
-        mit_des_fixup_key_parity (tkey);
-        (void) mit_des_key_sched (tkey, key_sked);
-        (void) mit_des_cbc_cksum (password, tkey, i, key_sked, ikey);
-
-        memcpy (ikey, tkey, sizeof(ikey));
-        mit_des_fixup_key_parity (tkey);
-        (void) mit_des_key_sched (tkey, key_sked);
-        (void) mit_des_cbc_cksum (password, key, i, key_sked, ikey);
-
-        /* erase key_sked */
-        memset(key_sked, 0,sizeof(key_sked));
-
-        /* now fix up key parity again */
-        mit_des_fixup_key_parity(key);
-
-        /* clean & free the input string */
-        memset(password, 0, (size_t) pw_len);
-        free(password);
-    }
-#if 0
-    /* must free here because it was copied for this special case */
-    free(salt->data);
-#endif
-    return 0;
-}
-
-static void krb5_afs_crypt_setkey (char*, char*, char(*)[48]);
-static void krb5_afs_encrypt (char*,char*,char (*)[48]);
-
-/*
- * 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},
-};
-
-
-char *afs_crypt(const char *pw, const char *salt,
-                /* must be at least 16 bytes */
-                char *iobuf)
-{
-    int i, j, c;
-    int temp;
-    char block[66];
-    char E[48];
-    /*
-     * The key schedule.
-     * Generated from the key.
-     */
-    char KS[16][48];
-
-    for(i=0; i<66; i++)
-        block[i] = 0;
-    for(i=0; (c= *pw) && i<64; pw++){
-        for(j=0; j<7; j++, i++)
-            block[i] = (c>>(6-j)) & 01;
-        i++;
-    }
-
-    krb5_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++)
-        krb5_afs_encrypt(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);
-}
-
-/*
- * Set up the key schedule from the key.
- */
-
-static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48])
-{
-    register int i, j, k;
-    int t;
-    /*
-     * The C and D arrays used to calculate the key schedule.
-     */
-    char C[28], D[28];
-
-    /*
-     * 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];
-        }
-    }
-
-#if 0
-    for(i=0;i<48;i++) {
-        E[i] = e[i];
-    }
-#else
-    memcpy(E, e, 48);
-#endif
-}
-
-/*
- * The payoff: encrypt a block.
- */
-
-static void krb5_afs_encrypt(char *block, char *E, char (*KS)[48])
-{
-    const long edflag = 0;
-    int i, ii;
-    int t, j, k;
-    char tempL[32];
-    char f[32];
-    /*
-     * The current block, divided into 2 halves.
-     */
-    char L[64];
-    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
-         */
-        if (edflag)
-            i = 15-ii;
-        else
-            i = ii;
-        /*
-         * Save the R array,
-         * which will be the new L.
-         */
-#if 0
-        for (j=0; j<32; j++)
-            tempL[j] = R[j];
-#else
-        memcpy(tempL, R, 32);
-#endif
-        /*
-         * 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)&01;
-            f[t+1] = (k>>2)&01;
-            f[t+2] = (k>>1)&01;
-            f[t+3] = (k>>0)&01;
-        }
-        /*
-         * 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.
-         */
-#if 0
-        for (j=0; j<32; j++)
-            L[j] = tempL[j];
-#else
-        memcpy(L, tempL, 32);
-#endif
-    }
-    /*
-     * 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];
-}
index 8519ad1a0b204f709c34e38f98f553c4ddb3deca..2338a9cf52cd995ce02a6c8dffaa8d6001b95e2d 100644 (file)
@@ -184,6 +184,7 @@ krb5_error_code mit_des_init_random_key(const krb5_encrypt_block *,
                                         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 */
similarity index 77%
rename from src/lib/crypto/openssl/des/des_oldapis.c
rename to src/lib/crypto/builtin/des/des_keys.c
index 584140f2cbf2a594fd089a463988f2d4059d2290..32b119aade70cd3e4b4baa40f2933a832ff72ff7 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/openssl/des/des_oldapis.c */
+/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */
 /*
- * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
  * All rights reserved.
  *
  * Export of this software from the United States of America may
  */
 
 #include "crypto_int.h"
+#include "des_int.h"
 
-krb5_error_code
-mit_afs_string_to_key(krb5_keyblock *keyblock, const krb5_data *data,
-                      const krb5_data *salt)
+void
+k5_des_fixup_key_parity(unsigned char *keybits)
 {
-    return KRB5_CRYPTO_INTERNAL;
+    mit_des_fixup_key_parity(keybits);
+}
+
+krb5_boolean
+k5_des_is_weak_key(unsigned char *keybits)
+{
+    return mit_des_is_weak_key(keybits);
 }
index 501a1b35b7fd6f4751b9cff87598e2f0359abc70..460b5061b5bc2313ba2da944c5f4246717e3f6f4 100644 (file)
@@ -9,7 +9,7 @@
  * Mark Eichin -- Cygnus Support
  */
 
-#include "crypto_int.h"
+
 #include "des_int.h"
 
 /*
 #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]);
diff --git a/src/lib/crypto/builtin/des/string2key.c b/src/lib/crypto/builtin/des/string2key.c
deleted file mode 100644 (file)
index a937d6f..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/builtin/des/string2key.c */
-/*
- * Copyright 2004, 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.
- */
-
-/* Compute encryption key from salt and pass phrase. */
-
-#include "crypto_int.h"
-#include "des_int.h"
-
-krb5_error_code
-mit_des_string_to_key_int (krb5_keyblock *key,
-                           const krb5_data *pw, const krb5_data *salt)
-{
-    union {
-        /* 8 "forward" bytes, 8 "reverse" bytes */
-        unsigned char uc[16];
-        krb5_ui_4 ui[4];
-        mit_des_cblock cb;
-    } temp;
-    unsigned int i;
-    krb5_ui_4 x, y, z;
-    unsigned char *p;
-    des_key_schedule sched;
-    char *copy;
-    size_t copylen;
-
-    /* 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
-
-    if (salt
-        && (salt->length == SALT_TYPE_AFS_LENGTH
-            /* XXX  Yuck!  Aren't we done with this yet?  */
-            || salt->length == (unsigned) -1)) {
-        krb5_data afssalt;
-        char *at;
-
-        afssalt.data = salt->data;
-        at = strchr(afssalt.data, '@');
-        if (at) {
-            *at = 0;
-            afssalt.length = at - afssalt.data;
-        } else
-            afssalt.length = strlen(afssalt.data);
-        return mit_afs_string_to_key(key, pw, &afssalt);
-    }
-
-    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
-#if 0
-    /* Algorithm described in Dr. Dobbs Journal 1983, reported in "bit
-       twiddling hacks" web page collected by Sean Eron Anderson; see
-       http://graphics.stanford.edu/~seander/bithacks.html for
-       details.
-
-       Avoids loops, uses 7*lg(N)=35 ops instead of 4*N=128 for the
-       obvious mask, ior, shift, shift sequence of each 32-bit
-       quantity.
-
-       If we could rely on 64-bit math, another 7 ops would save us
-       from having to do double the work.  */
-#define REVERSE_STEP(VAR, SHIFT, MASK)                                  \
-    VAR = ((VAR >> SHIFT) & MASK) | ((VAR << SHIFT) & (0xFFFFFFFFUL & ~MASK))
-#define REVERSE(VAR)                                                    \
-    REVERSE_STEP (VAR, 1, 0x55555555UL); /* swap odd/even bits */       \
-    REVERSE_STEP (VAR, 2, 0x33333333UL); /* swap bitpairs */            \
-    REVERSE_STEP (VAR, 4, 0x0F0F0F0FUL); /* swap nibbles, etc */        \
-    REVERSE_STEP (VAR, 8, 0x00FF00FFUL);                                \
-    REVERSE_STEP (VAR, 16, 0x0000FFFFUL);
-#else /* shorter */
-#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;                            \
-    }
-#endif
-
-    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)                                        \
-    (mit_des_fixup_key_parity(K),                       \
-     mit_des_is_weak_key(K) ? (K[7] ^= 0xF0) : 0)
-
-    /* Now temp.cb is the temporary key, with invalid parity.  */
-    FIXUP(temp.cb);
-
-#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
-
-    mit_des_key_sched(temp.cb, sched);
-    mit_des_cbc_cksum(copy, temp.cb, copylen, sched, temp.cb);
-
-    memset(copy, 0, copylen);
-    free(copy);
-
-#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
-
-    memset(sched, 0, sizeof(sched));
-    FIXUP (temp.cb);
-
-#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->contents, temp.cb, 8);
-    memset(&temp, 0, sizeof(temp));
-
-    return 0;
-}
diff --git a/src/lib/crypto/builtin/des/t_afss2k.c b/src/lib/crypto/builtin/des/t_afss2k.c
deleted file mode 100644 (file)
index 5a0f960..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#include "des_int.h"
-
-static const char *me;
-
-struct test_case {
-    char *saltstr;
-    int saltlen;
-    unsigned char keys[12][8];
-};
-
-struct test_case test_cases[] = {
-    {
-        "Sodium Chloride", -1,
-        {
-            { 0xa4, 0xd0, 0xd0, 0x9b, 0x86, 0x92, 0xb0, 0xc2, },
-            { 0xf1, 0xf2, 0x9e, 0xab, 0xd0, 0xef, 0xdf, 0x73, },
-            { 0xd6, 0x85, 0x61, 0xc4, 0xf2, 0x94, 0xf4, 0xa1, },
-            { 0xd0, 0xe3, 0xa7, 0x83, 0x94, 0x61, 0xe0, 0xd0, },
-            { 0xd5, 0x62, 0xcd, 0x94, 0x61, 0xcb, 0x97, 0xdf, },
-            { 0x9e, 0xa2, 0xa2, 0xec, 0xa8, 0x8c, 0x6b, 0x8f, },
-            { 0xe3, 0x91, 0x6d, 0xd3, 0x85, 0xf1, 0x67, 0xc4, },
-            { 0xf4, 0xc4, 0x73, 0xc8, 0x8a, 0xe9, 0x94, 0x6d, },
-            { 0xa1, 0x9e, 0xb3, 0xad, 0x6b, 0xe3, 0xab, 0xd9, },
-            { 0xad, 0xa1, 0xce, 0x10, 0x37, 0x83, 0xa7, 0x8c, },
-            { 0xd3, 0x01, 0xd0, 0xf7, 0x3e, 0x7a, 0x49, 0x0b, },
-            { 0xb6, 0x2a, 0x4a, 0xec, 0x9d, 0x4c, 0x68, 0xdf, },
-        }
-    },
-    {
-        "NaCl", 4,
-        {
-            { 0x61, 0xef, 0xe6, 0x83, 0xe5, 0x8a, 0x6b, 0x98 },
-            { 0x68, 0xcd, 0x68, 0xad, 0xc4, 0x86, 0xcd, 0xe5 },
-            { 0x83, 0xa1, 0xc8, 0x86, 0x8f, 0x67, 0xd0, 0x62 },
-            { 0x9e, 0xc7, 0x8f, 0xa4, 0xa4, 0xb3, 0xe0, 0xd5 },
-            { 0xd9, 0x92, 0x86, 0x8f, 0x9d, 0x8c, 0x85, 0xe6 },
-            { 0xda, 0xf2, 0x92, 0x83, 0xf4, 0x9b, 0xa7, 0xad },
-            { 0x91, 0xcd, 0xad, 0xef, 0x86, 0xdf, 0xd3, 0xa2 },
-            { 0x73, 0xd3, 0x67, 0x68, 0x8f, 0x6e, 0xe3, 0x73 },
-            { 0xc4, 0x61, 0x85, 0x9d, 0xad, 0xf4, 0xdc, 0xb0 },
-            { 0xe9, 0x02, 0x83, 0x16, 0x2c, 0xec, 0xe0, 0x08 },
-            { 0x61, 0xc8, 0x26, 0x29, 0xd9, 0x73, 0x6e, 0xb6 },
-            { 0x8c, 0xa8, 0x9e, 0xc4, 0xa8, 0xdc, 0x31, 0x73 },
-        }
-    },
-    {
-        /* This one intentionally supplies a length shorter
-           than the string.  The point of this is to ensure
-           that s[len] is not zero, so that anything actually
-           relying on that value (i.e., reading out of bounds)
-           should generate incorrect results.  */
-        "NaCl2", 4,
-        {
-            { 0x61, 0xef, 0xe6, 0x83, 0xe5, 0x8a, 0x6b, 0x98 },
-            { 0x68, 0xcd, 0x68, 0xad, 0xc4, 0x86, 0xcd, 0xe5 },
-            { 0x83, 0xa1, 0xc8, 0x86, 0x8f, 0x67, 0xd0, 0x62 },
-            { 0x9e, 0xc7, 0x8f, 0xa4, 0xa4, 0xb3, 0xe0, 0xd5 },
-            { 0xd9, 0x92, 0x86, 0x8f, 0x9d, 0x8c, 0x85, 0xe6 },
-            { 0xda, 0xf2, 0x92, 0x83, 0xf4, 0x9b, 0xa7, 0xad },
-            { 0x91, 0xcd, 0xad, 0xef, 0x86, 0xdf, 0xd3, 0xa2 },
-            { 0x73, 0xd3, 0x67, 0x68, 0x8f, 0x6e, 0xe3, 0x73 },
-            { 0xc4, 0x61, 0x85, 0x9d, 0xad, 0xf4, 0xdc, 0xb0 },
-            { 0xe9, 0x02, 0x83, 0x16, 0x2c, 0xec, 0xe0, 0x08 },
-            { 0x61, 0xc8, 0x26, 0x29, 0xd9, 0x73, 0x6e, 0xb6 },
-            { 0x8c, 0xa8, 0x9e, 0xc4, 0xa8, 0xdc, 0x31, 0x73 },
-        }
-    },
-};
-
-static void do_it (struct test_case *tcase);
-
-int
-main (int argc, char *argv[])
-{
-    int i;
-
-    me = argv[0];
-    for (i = 0; i < sizeof (test_cases) / sizeof (struct test_case); i++)
-        do_it (&test_cases[i]);
-    return 0;
-}
-
-static void
-do_it (struct test_case *tcase)
-{
-    unsigned char keydata[8];
-    krb5_data salt, passwd;
-    krb5_keyblock key;
-    krb5_error_code err;
-    int i;
-    unsigned char longpass[2048];
-
-    key.contents = keydata;
-    key.length = sizeof (keydata);
-
-    salt.data = tcase->saltstr;
-    if (tcase->saltlen == -1)
-        salt.length = strlen (tcase->saltstr);
-    else
-        salt.length = tcase->saltlen;
-
-    /*
-     * Try passwords with lengths equal to, greater than, and less
-     * than 8 characters, since the AFS s2k algorithm does
-     * interesting stuff depending on the length.
-     */
-    passwd.data = "My Password";
-    for (i = 0; i < 12; i++) {
-        passwd.length = i;
-        err = mit_afs_string_to_key (&key, &passwd, &salt);
-        if (err != 0) {
-            com_err (me, err, "");
-            exit (1);
-        }
-        if (memcmp (tcase->keys[i], keydata, 8) != 0)
-            abort ();
-    }
-
-    /* Run another pass to make sure the characters after the
-       password in the buffer aren't influencing the output.  The
-       password is *not* required to be null-terminated.  */
-    memset (longpass, '!', sizeof (longpass));
-    longpass[sizeof (longpass)-1] = '\0';
-    memcpy (longpass, "My Password", strlen ("My Password"));
-    passwd.data = (char *) longpass;
-    for (i = 0; i < 12; i++) {
-        passwd.length = i;
-        err = mit_afs_string_to_key (&key, &passwd, &salt);
-        if (err != 0) {
-            com_err (me, err, "");
-            exit (1);
-        }
-        if (memcmp (tcase->keys[i], keydata, 8) != 0)
-            abort ();
-    }
-}
index 85a7a9f25e14cac52ae31fbaf7b9b5fd316c882c..ff7c9b4066273eedf6e33e313fa51b72aaa85f19 100644 (file)
@@ -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.
  * or implied warranty.
  */
 
-/*
- *
- * String-to-key test vectors
- */
-
 #include "k5-int.h"
 
 struct test {
@@ -38,6 +33,176 @@ struct test {
     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,
index 3b46fc6279b0a821026a431c1c2a725d2778ea7b..fa20cc526e6712d9bb967d82213a3543d08d41f1 100644 (file)
@@ -432,16 +432,11 @@ extern const struct krb5_hash_provider krb5int_hash_sha1;
 
 /* Modules must implement the following functions. */
 
-/* Set the parity bits in a DES key. */
-void mit_des_fixup_key_parity(unsigned char *key);
-
-/* 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);
+/* Set the parity bits to the correct values in keybits. */
+void k5_des_fixup_key_parity(unsigned char *keybits);
+
+/* 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). */
index 93d033eb7108b7e2b070ee326c7055a9d85efc22..1574625268c9f7706e2a95aaf117e705acca04b4 100644 (file)
@@ -92,7 +92,7 @@ k5_rand2key_des(const krb5_data *randombits, krb5_keyblock *keyblock)
      * 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 @@ k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock)
     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;
 }
index 751aa72da2280e1677a4266af8e66a66b7dc6346..fd2143054b9ba1db1928cc684a7ce7fe03e8e32b 100644 (file)
  * 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);
 }
index b751e6e65a4896298b7c359412aa79b99a4946f3..cdef2818af178b78f972abf8d7fe980c4cf7145d 100644 (file)
@@ -9,17 +9,11 @@ RUN_SETUP = @KRB5_RUN_ENV@
 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
 
diff --git a/src/lib/crypto/nss/des/des_keys.c b/src/lib/crypto/nss/des/des_keys.c
new file mode 100644 (file)
index 0000000..4ff0e84
--- /dev/null
@@ -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;
+}
diff --git a/src/lib/crypto/nss/des/des_oldapis.c b/src/lib/crypto/nss/des/des_oldapis.c
deleted file mode 100644 (file)
index c26439f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/nss/des/des_oldapis.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
-mit_afs_string_to_key(krb5_keyblock *keyblock, const krb5_data *data,
-                      const krb5_data *salt)
-{
-    return KRB5_CRYPTO_INTERNAL;
-}
diff --git a/src/lib/crypto/nss/des/f_parity.c b/src/lib/crypto/nss/des/f_parity.c
deleted file mode 100644 (file)
index ca1de3e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * These routines check and fix parity of encryption keys for the DES
- * algorithm.
- *
- * They are a replacement for routines in key_parity.c, that don't require
- * the table building that they do.
- *
- * Mark Eichin -- Cygnus Support
- */
-
-#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
-mit_des_fixup_key_parity(unsigned char *key)
-{
-    unsigned int i;
-    for (i = 0; i < 8; i++) {
-        key[i] &= 0xfe;
-        key[i] |= 1^parity_char(key[i]);
-    }
-}
diff --git a/src/lib/crypto/nss/des/string2key.c b/src/lib/crypto/nss/des/string2key.c
deleted file mode 100644 (file)
index 8474c40..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/nss/des/string2key.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"
-#include "pk11pub.h"
-#include "nss_gen.h"
-
-krb5_error_code
-mit_des_string_to_key_int(krb5_keyblock *key, const krb5_data *pw,
-                          const krb5_data *salt)
-{
-    PK11SlotInfo *slot = NULL;
-    PK11SymKey *symKey = NULL;
-    SECItem pwItem;
-    SECItem paramsItem;
-    CK_PBE_PARAMS pbe_params;
-    CK_MECHANISM_TYPE pbeMech = CKM_NETSCAPE_PBE_SHA1_DES_CBC;
-    krb5_error_code ret;
-    SECItem *keyData;
-
-    ret = k5_nss_init();
-    if (ret)
-        return ret;
-
-    slot = PK11_GetBestSlot(pbeMech, NULL);
-    if (slot == NULL) {
-        ret = k5_nss_map_last_error();
-        goto loser;
-    }
-
-    pwItem.data = (unsigned char *)pw->data;
-    pwItem.len = pw->length;
-    memset(&pbe_params, 0, sizeof(pbe_params));
-    pbe_params.pSalt = (unsigned char *)salt->data;
-    pbe_params.ulSaltLen = salt->length;
-    pbe_params.ulIteration = 1;
-    paramsItem.data = (unsigned char *)&pbe_params;
-    paramsItem.len = sizeof(pbe_params);
-
-    symKey = PK11_RawPBEKeyGen(slot, pbeMech, &paramsItem, &pwItem,
-                               PR_FALSE, NULL);
-    if (symKey == NULL) {
-        ret = k5_nss_map_last_error();
-        goto loser;
-    }
-    PK11_ExtractKeyValue(symKey);
-    keyData = PK11_GetKeyData(symKey);
-    if (!keyData) {
-        ret = k5_nss_map_last_error();
-        goto loser;
-    }
-    key->length = keyData->len;
-    memcpy(key->contents, keyData->data, key->length);
-    ret = 0;
-
-loser:
-    if (symKey)
-        PK11_FreeSymKey(symKey);
-    if (slot)
-        PK11_FreeSlot(slot);
-    return ret;
-}
index 46a3e0fc17a650f2c752e5f2861717e995671d04..2d9387f19fbf6626fff0893f5ad4af8f5e14f0ea 100644 (file)
@@ -57,19 +57,32 @@ k5_des_decrypt_iov(krb5_key key,
 {
     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
index 943726352bcec7804cfc1c6562e983dc9d46e35c..ed016635e939f06d3b52db16c7428cb5f4bb003a 100644 (file)
@@ -545,9 +545,8 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
     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 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
     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 @@ k5_nss_gen_cbcmac_iov(krb5_key krb_key, CK_MECHANISM_TYPE mech,
         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) {
index 4907bc89d94e2f6424db8575688a3b035ebf1b51..ac113f7c87f99e239aab764ede38d6408f2a5532 100644 (file)
@@ -7,18 +7,11 @@ RUN_SETUP = @KRB5_RUN_ENV@
 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)/f_parity.c    \
-       $(srcdir)/des_oldapis.c \
-       $(srcdir)/string2key.c
+SRCS= $(srcdir)/des_keys.c
 
 all-unix:: all-libobjs
 
similarity index 78%
rename from src/lib/crypto/openssl/des/f_parity.c
rename to src/lib/crypto/openssl/des/des_keys.c
index f5744726aba9010f43dfbd399dc78d85247e86d6..51d9db216c6b98dec63d0807fd6fe6e2c4e77c96 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/openssl/des/f_parity.c */
+/* lib/crypto/openssl/des/des_keys.c - Key functions used by Kerberos code */
 /*
- * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
  * All rights reserved.
  *
  * Export of this software from the United States of America may
 #include <openssl/des.h>
 
 void
-mit_des_fixup_key_parity(unsigned char *key)
+k5_des_fixup_key_parity(unsigned char *keybits)
 {
-    DES_set_odd_parity((DES_cblock *)key);
+    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);
 }
diff --git a/src/lib/crypto/openssl/des/string2key.c b/src/lib/crypto/openssl/des/string2key.c
deleted file mode 100644 (file)
index cd3e759..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/crypto/openssl/des/string2key.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"
-#include <openssl/des.h>
-
-krb5_error_code
-mit_des_string_to_key_int(krb5_keyblock *key, const krb5_data *pw,
-                          const krb5_data *salt)
-{
-    DES_cblock outkey;
-    char *str;
-    krb5_data s = (salt == NULL) ? empty_data() : *salt;
-
-    /* AFS string-to-key isn't implemented. */
-    if (s.length == SALT_TYPE_AFS_LENGTH)
-        return KRB5_CRYPTO_INTERNAL;
-
-    /* Concatenate password and salt. */
-    if (asprintf(&str, "%.*s%.*s", pw->length, pw->data, s.length, s.data) < 0)
-        return ENOMEM;
-    DES_string_to_key(str, &outkey);
-    free(str);
-    if (key->length < sizeof(outkey))
-        return KRB5_CRYPTO_INTERNAL;
-    key->length = sizeof(outkey);
-    memcpy(key->contents, outkey, key->length);
-    return 0;
-}
index 591e13b8045c38f92a970f0454f5fbd84683148b..644e26633e28252be3168c6516ec28c6e864ad24 100644 (file)
@@ -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 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     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
 };