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
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
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
+++ /dev/null
-/* -*- 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];
-}
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 */
/* -*- 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);
}
* 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]);
+++ /dev/null
-/* -*- 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;
-}
+++ /dev/null
-/* -*- 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 ();
- }
-}
/* -*- 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 {
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,
/* 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). */
* 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;
}
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;
}
* 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);
}
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
--- /dev/null
+/* -*- 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;
+}
+++ /dev/null
-/* -*- 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;
-}
+++ /dev/null
-/* -*- 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]);
- }
-}
+++ /dev/null
-/* -*- 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, ¶msItem, &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;
-}
{
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
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;
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;
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) {
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
/* -*- 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);
}
+++ /dev/null
-/* -*- 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;
-}
#include "crypto_int.h"
#include <openssl/evp.h>
+#include <openssl/des.h>
#define DES_BLOCK_SIZE 8
#define DES_KEY_SIZE 8
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
};