From 60931c5c21144dd4437fcb47caf8e63ed9b0d40b Mon Sep 17 00:00:00 2001 From: edg Date: Thu, 10 May 1990 13:27:14 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@822 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/des/Imakefile | 82 ++++++ src/lib/crypto/des/cbc_cksum.c | 99 +++++++ src/lib/crypto/des/cksum.c | 138 ++++++++++ src/lib/crypto/des/cs_entry.c | 79 ++++++ src/lib/crypto/des/des.c | 457 ++++++++++++++++++++++++++++++++ src/lib/crypto/des/des_int.h | 95 +++++++ src/lib/crypto/des/enc_dec.c | 305 +++++++++++++++++++++ src/lib/crypto/des/fin_rndkey.c | 36 +++ src/lib/crypto/des/finish_key.c | 41 +++ src/lib/crypto/des/init_rkey.c | 51 ++++ src/lib/crypto/des/key_parity.c | 65 +++++ src/lib/crypto/des/key_sched.c | 251 ++++++++++++++++++ src/lib/crypto/des/make_e.c | 42 +++ src/lib/crypto/des/make_fp.c | 72 +++++ src/lib/crypto/des/make_ip.c | 61 +++++ src/lib/crypto/des/make_kp.c | 217 +++++++++++++++ src/lib/crypto/des/make_odd.c | 47 ++++ src/lib/crypto/des/make_p.c | 51 ++++ src/lib/crypto/des/make_pt.c | 68 +++++ src/lib/crypto/des/make_s.c | 33 +++ src/lib/crypto/des/make_st.c | 71 +++++ src/lib/crypto/des/misc.c | 354 +++++++++++++++++++++++++ src/lib/crypto/des/new_rn_key.c | 210 +++++++++++++++ src/lib/crypto/des/process_ky.c | 69 +++++ src/lib/crypto/des/random_key.c | 50 ++++ src/lib/crypto/des/string2key.c | 167 ++++++++++++ src/lib/crypto/des/tables.h | 109 ++++++++ src/lib/crypto/des/verify.c | 340 ++++++++++++++++++++++++ src/lib/crypto/des/weak_key.c | 76 ++++++ 29 files changed, 3736 insertions(+) create mode 100644 src/lib/crypto/des/Imakefile create mode 100644 src/lib/crypto/des/cbc_cksum.c create mode 100644 src/lib/crypto/des/cksum.c create mode 100644 src/lib/crypto/des/cs_entry.c create mode 100644 src/lib/crypto/des/des.c create mode 100644 src/lib/crypto/des/des_int.h create mode 100644 src/lib/crypto/des/enc_dec.c create mode 100644 src/lib/crypto/des/fin_rndkey.c create mode 100644 src/lib/crypto/des/finish_key.c create mode 100644 src/lib/crypto/des/init_rkey.c create mode 100644 src/lib/crypto/des/key_parity.c create mode 100644 src/lib/crypto/des/key_sched.c create mode 100644 src/lib/crypto/des/make_e.c create mode 100644 src/lib/crypto/des/make_fp.c create mode 100644 src/lib/crypto/des/make_ip.c create mode 100644 src/lib/crypto/des/make_kp.c create mode 100644 src/lib/crypto/des/make_odd.c create mode 100644 src/lib/crypto/des/make_p.c create mode 100644 src/lib/crypto/des/make_pt.c create mode 100644 src/lib/crypto/des/make_s.c create mode 100644 src/lib/crypto/des/make_st.c create mode 100644 src/lib/crypto/des/misc.c create mode 100644 src/lib/crypto/des/new_rn_key.c create mode 100644 src/lib/crypto/des/process_ky.c create mode 100644 src/lib/crypto/des/random_key.c create mode 100644 src/lib/crypto/des/string2key.c create mode 100644 src/lib/crypto/des/tables.h create mode 100644 src/lib/crypto/des/verify.c create mode 100644 src/lib/crypto/des/weak_key.c diff --git a/src/lib/crypto/des/Imakefile b/src/lib/crypto/des/Imakefile new file mode 100644 index 000000000..ac49efa25 --- /dev/null +++ b/src/lib/crypto/des/Imakefile @@ -0,0 +1,82 @@ +NormalLibraryObjectRule() + +OBJS= cksum.o \ + des.o \ + des_cbc_cksum.o \ + des_cs_ent.o \ + des_enc_dec.o \ + des_fin_key.o \ + des_fnr_key.o \ + des_inr_key.o \ + des_prc_key.o \ + des_ran_key.o \ + des_st2_key.o \ + key_parity.o \ + key_sched.o \ + new_rnd_key.o \ + weak_key.o + +SRCS= cksum.c \ + des.c \ + des_cs_ent.c \ + des_cbc_cksum.c \ + des_enc_dec.c \ + des_fin_key.c \ + des_fnr_key.c \ + des_inr_key.c \ + des_prc_key.c \ + des_ran_key.c \ + des_st2_key.c \ + key_parity.c \ + key_sched.c \ + new_rnd_key.c \ + weak_key.c + +VERIFYOBJ = verify.o + +NormalLibraryTarget(des,$(OBJS)) + +EXTRA_LIBRARIES = $(TOP)/error_tables/libkrberrs.a + +NormalProgramTarget(verify, $(VERIFYOBJ), libdes.a, libdes.a, -lcom_err) + +NormalProgramTarget(make_e, make_e.o, misc.o, misc.o, ) + +NormalProgramTarget(make_fp, make_fp.o, misc.o, misc.o, ) + +fp.c: make_fp + ./make_fp fp.c + +NormalProgramTarget(make_ip, make_ip.o, misc.o, misc.o, ) + +ip.c: make_ip + ./make_ip ip.c + +NormalProgramTarget(make_key_perm, make_key_perm.o, misc.o, misc.o, ) + +key_perm.h: make_key_perm + ./make_key_perm key_perm.h + +NormalProgramTarget(make_odd, make_odd.o, misc.o, misc.o, ) + +odd.h: make_odd + ./make_odd odd.h + +NormalProgramTarget(make_p, make_p.o, misc.o, misc.o, ) + +p.c: make_p + ./make_p p.c + +NormalProgramTarget(make_p_table, make_p_table.o, misc.o, misc.o, ) + +p_table.h: make_p_table + ./make_p_table p_table.h + +NormalProgramTarget(make_s, make_s.o, misc.o, misc.o, ) + +NormalProgramTarget(make_s_table, make_s_table.o, misc.o, misc.o, ) + +s_table.h: make_s_table + ./make_s_table s_table.h + +NormalLintTarget($(SRCS)) diff --git a/src/lib/crypto/des/cbc_cksum.c b/src/lib/crypto/des/cbc_cksum.c new file mode 100644 index 000000000..206a9f6e2 --- /dev/null +++ b/src/lib/crypto/des/cbc_cksum.c @@ -0,0 +1,99 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_cbc_checksum_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include + +#include + +extern void des_cbc_cksum(); +extern int des_key_sched(); + +/* + produces cbc cheksum of sequence "in" of the length "in_length" + with the help of key "key" of size "key_size" (which should be 8); + fills out krb5_checksum structure. + + caller is responsible for freeing "contents" element in + krb5_checksum structure. + + returns: errors +*/ +krb5_error_code des_cbc_checksum(DECLARG(krb5_pointer, in), + DECLARG(size_t, in_length), + DECLARG(krb5_pointer, key), + DECLARG(size_t, key_size), + DECLARG(krb5_checksum *, cksum)) +OLDDECLARG(krb5_pointer, in) +OLDDECLARG(size_t, in_length) +OLDDECLARG(krb5_pointer, key) +OLDDECLARG(size_t, key_size) +OLDDECLARG(krb5_checksum *, cksum) +{ + struct des_ks_struct *schedule; /* pointer to key schedules */ + krb5_octet *contents; + + if (key_size != sizeof(des_cblock)) + return -1; + + if (!(schedule = (struct des_ks_struct *) malloc(sizeof(des_key_schedule)))) + return ENOMEM; + +#define cleanup() { bzero((char *)schedule, sizeof(des_key_schedule));\ + free( (char *) schedule); } + + switch (des_key_sched ((krb5_octet *)key, schedule)) { + case -1: + cleanup(); + return KRB5DES_BAD_KEYPAR; /* XXX error code-bad key parity */ + + case -2: + cleanup(); + return KRB5DES_WEAK_KEY; /* XXX error code-weak key */ + + default: + ; + } + + if (!(contents = (krb5_octet *) malloc(sizeof(des_cblock)))) + return ENOMEM; + +#define cleanup2() { free( (char *) schedule); } + + des_cbc_cksum((krb5_octet *)in, contents, in_length, + schedule, (krb5_octet *)key); + + cksum->checksum_type = CKSUMTYPE_DESCBC; + cksum->length = sizeof(des_cblock); + cksum->contents = contents; + cleanup(); + + return 0; +} + diff --git a/src/lib/crypto/des/cksum.c b/src/lib/crypto/des/cksum.c new file mode 100644 index 000000000..a22494463 --- /dev/null +++ b/src/lib/crypto/des/cksum.c @@ -0,0 +1,138 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * . + * + * These routines perform encryption and decryption using the DES + * private key algorithm, or else a subset of it-- fewer inner loops. + * (AUTH_DES_ITER defaults to 16, may be less.) + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * spm 8/85 MIT project athena + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_cksum_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include + +#include +#include +#include "des_internal.h" + +extern int des_debug; +extern int des_debug_print(); +extern int des_ecb_encrypt(); + +/* + * This routine performs DES cipher-block-chaining checksum operation, + * a.k.a. Message Authentication Code. It ALWAYS encrypts from input + * to a single 64 bit output MAC checksum. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was + * provided, your program will get trashed. + * + * The input is null padded, at the end (highest addr), to an integral + * multiple of eight bytes. + */ + +void +des_cbc_cksum(in,out,length,key,iv) + krb5_octet *in; /* >= length bytes of inputtext */ + krb5_octet *out; /* >= length bytes of outputtext */ + register long length; /* in bytes */ + des_key_schedule key; /* precomputed key schedule */ + krb5_octet *iv; /* 8 bytes of ivec */ +{ + register unsigned long *input = (unsigned long *) in; + register unsigned long *output = (unsigned long *) out; + unsigned long *ivec = (unsigned long *) iv; + + unsigned long i,j; + static unsigned long t_input[2]; + static unsigned long t_output[8]; + static unsigned char *t_in_p; + + t_in_p = (unsigned char *) t_input; +#ifdef MUSTALIGN + if ((long) ivec & 3) { + bcopy((char *)ivec++,(char *)&t_output[0],sizeof(t_output[0])); + bcopy((char *)ivec,(char *)&t_output[1],sizeof(t_output[1])); + } + else +#endif + { + t_output[0] = *ivec++; + t_output[1] = *ivec; + } + + for (i = 0; length > 0; i++, length -= 8) { + /* get input */ +#ifdef MUSTALIGN + if ((long) input & 3) { + bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0])); + bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[1])); + } + else +#endif + { + t_input[0] = *input++; + t_input[1] = *input++; + } + + /* zero pad */ + if (length < 8) + for (j = length; j <= 7; j++) + *(t_in_p+j)= 0; + +#ifdef DEBUG + if (des_debug) + des_debug_print("clear",length,t_input[0],t_input[1]); +#endif + /* do the xor for cbc into the temp */ + t_input[0] ^= t_output[0] ; + t_input[1] ^= t_output[1] ; + /* encrypt */ + (void) des_ecb_encrypt(t_input,t_output,key,1); +#ifdef DEBUG + if (des_debug) { + des_debug_print("xor'ed",i,t_input[0],t_input[1]); + des_debug_print("cipher",i,t_output[0],t_output[1]); + } +#else +#ifdef lint + i = i; +#endif +#endif + } + /* copy temp output and save it for checksum */ +#ifdef MUSTALIGN + if ((long) output & 3) { + bcopy((char *)&t_output[0],(char *)output++,sizeof(t_output[0])); + bcopy((char *)&t_output[1],(char *)output,sizeof(t_output[1])); + } + else +#endif + { + *output++ = t_output[0]; + *output = t_output[1]; + } + + return; +} diff --git a/src/lib/crypto/des/cs_entry.c b/src/lib/crypto/des/cs_entry.c new file mode 100644 index 000000000..a6862f586 --- /dev/null +++ b/src/lib/crypto/des/cs_entry.c @@ -0,0 +1,79 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Wrapper for the V4 libdes for use with kerberos V5. + */ + +#if !defined(lint) && !defined(SABER) +static char des_cs_ent_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include + +extern krb5_error_code encrypt_func PROTOTYPE((const krb5_pointer, + krb5_pointer, + const size_t, + krb5_encrypt_block *, + krb5_pointer)); +extern krb5_error_code decrypt_func PROTOTYPE((const krb5_pointer, + krb5_pointer, + const size_t, + krb5_encrypt_block *, + krb5_pointer)); +extern krb5_error_code process_key PROTOTYPE((krb5_encrypt_block *, + const krb5_keyblock *)); +extern krb5_error_code finish_key PROTOTYPE((krb5_encrypt_block *)); +extern krb5_error_code string_to_key PROTOTYPE((const krb5_keytype, + krb5_keyblock *, + const krb5_data *, + const krb5_principal)); +extern krb5_error_code init_random_key PROTOTYPE((const krb5_keyblock *, + krb5_pointer *)); +extern krb5_error_code finish_random_key PROTOTYPE((krb5_pointer *)); +extern krb5_error_code random_key PROTOTYPE((krb5_pointer, + krb5_keyblock **)); + +krb5_cryptosystem_entry mit_des_cryptosystem_entry = { + encrypt_func, + decrypt_func, + process_key, + finish_key, + string_to_key, + init_random_key, + finish_random_key , + random_key, + sizeof(des_cblock), + 0, + sizeof(des_cblock), + ETYPE_DES_CBC_CRC, + KEYTYPE_DES + }; + +krb5_cs_table_entry krb5_des_cst_entry = { + &mit_des_cryptosystem_entry, + 0 + }; +extern krb5_error_code des_cbc_checksum PROTOTYPE ((krb5_pointer , + size_t , + krb5_pointer , + size_t , + krb5_checksum * )); + + +krb5_checksum_entry des_cbc_cksumtable_entry = { + des_cbc_checksum, + sizeof(des_cblock) + }; diff --git a/src/lib/crypto/des/des.c b/src/lib/crypto/des/des.c new file mode 100644 index 000000000..73e529ddf --- /dev/null +++ b/src/lib/crypto/des/des.c @@ -0,0 +1,457 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * . + * + * These routines perform encryption and decryption using the DES + * private key algorithm, or else a subset of it-- fewer inner loops. + * (AUTH_DES_ITER defaults to 16, may be less.) + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. + * + * All registers labeled imply Vax using the Ultrix or 4.2bsd + * compiler. + * + * + * NOTE: bit and byte numbering: + * DES algorithm is defined in terms of bits of L + * followed by bits of R. + * bit 0 ==> lsb of L + * bit 63 ==> msb of R + * + * Always work in register pairs, FROM L1,R1 TO L2,R2 to make + * bookkeeping easier. + * + * originally written by Steve Miller, MIT Project Athena + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_des_c[] = +"$Header$"; +#endif /* !lint & !SABER */ + +#include + +#include +#include +#include +#include "des_internal.h" +#include "s_table.h" +#include "p_table.h" + +#ifdef DEBUG +#define DBG_PRINT(s) if (des_debug & 2) \ + des_debug_print(s,i,L1&0xffff,(L1>>16)&0xffff, \ + R1&0xffff,(R1>>16)&0xffff) +#else +#define DBG_PRINT(s) +#endif + +extern int des_debug; +extern des_cblock_print_file (); +extern des_debug_print (); + +int +des_ecb_encrypt(clear, cipher, schedule, encrypt) + unsigned long *clear; + unsigned long *cipher; + int encrypt; /* 0 ==> decrypt, else encrypt */ + register des_key_schedule schedule; /* r11 */ +{ + + /* better pass 8 bytes, length not checked here */ + + register unsigned long R1, L1; /* R1 = r10, L1 = r9 */ + register unsigned long R2, L2; /* R2 = r8, L2 = r7 */ + long i; + /* one more registers left on VAX, see below P_temp_p */ +#ifdef BITS16 + sbox_in_16_a S_in_16_a; + sbox_in_16_b S_in_16_b; + sbox_in_16_c S_in_16_c; + unsigned int *S_in_a_16_p = (unsigned int *) &S_in_16_a; + unsigned int *S_in_b_16_p = (unsigned int *) &S_in_16_b; + unsigned int *S_in_c_16_p = (unsigned int *) &S_in_16_c; +#endif +#ifndef BITS32 +#ifndef BITS16 + dunno how to do this machine type, you lose; +#endif +#endif + unsigned long P_temp; + register unsigned char *P_temp_p = (unsigned char *) & P_temp; +#ifdef BITS16 + sbox_out S_out; + unsigned long *S_out_p = (unsigned long *) &S_out; +#endif + unsigned long R_save, L_save; +#ifdef DEBUG + unsigned long dbg_tmp[2]; +#endif + + /* + * Use L1,R1 and L2,R2 as two sets of "64-bit" registers always + * work from L1,R1 input to L2,R2 output; initialize the cleartext + * into registers. + */ +#ifdef MUSTALIGN +#ifdef DEBUG + /* + * If the alignment is wrong, the programmer really screwed up -- + * we aren't even getting the right data type. His problem. Keep + * this code for debugging. + */ + /* Make sure schedule is ok */ + if ((long) schedule & 3) { + fprintf(stderr,"des.c schedule arg pointer not aligned\n"); + abort(); + } +#endif + if ((long) clear & 3) { + bcopy((char *)clear++,(char *)&L_save,sizeof(L_save)); + bcopy((char *)clear,(char *)&R_save,sizeof(R_save)); + L1 = L_save; + R1 = R_save; + } + else +#endif + { + if (clear) L1 = *clear++; + else L1 = NULL; + if (clear) R1 = *clear; + else R1 = NULL; + } + +#ifdef DEBUG + if (des_debug & 2) { + printf("All values printed from low byte (bit 0)"); + printf(" --> high byte (bit 63)\n"); + i = 0; + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + printf("iter = %2d before IP\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } + + DBG_PRINT("before IP"); +#endif + +/* IP_start:*/ + + /* all the Initial Permutation code is in the include file */ +#include "ip.c" + /* reset input to L1,R1 */ + L1 = L2; + R1 = R2; + + /* iterate through the inner loop */ + for (i = 0; i <= (AUTH_DES_ITER-1); i++) { + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + printf("iter = %2d start loop\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + DBG_PRINT("start loop"); + } + +#endif + + R_save = R1; + L_save = L1; + +/* E_start:*/ + /* apply the E permutation from R1 to L2, R2 */ +#ifndef VAXASM +#ifdef SLOW_E +#include "e.c" +#else /* Bill's fast E */ + L2 = (R1 << 1); + if (R1 & (1<<31)) + L2 |= 1<<0; + L2 &= 077; + L2 |= (R1 <<3) & 07700; + L2 |= (R1 <<5) & 0770000; + L2 |= (R1 <<7) & 077000000; + L2 |= (R1 <<9) & 07700000000; + L2 |= (R1 <<11) & 030000000000; + + /* now from right to right */ + + R2 = ((R1 >> 17) & 0176000); + if (R1 & (1<<0)) R2 |= 1<<15; + + R2 |= ((R1 >> 21) & 017); + R2 |= ((R1 >> 19) & 01760); +#endif /* SLOW_E */ +#else /* VAXASM */ + /* E operations */ + /* right to left */ + asm(" rotl $1,r10,r7"); + L2 &= 077; + L2 |= (R1 <<3) & 07700; + L2 |= (R1 <<5) & 0770000; + L2 |= (R1 <<7) & 077000000; + L2 |= (R1 <<9) & 07700000000; + L2 |= (R1 <<11) & 030000000000; + + asm(" rotl $-17,r10,r8"); + R2 &= 0176000; + asm(" rotl $-21,r10,r0"); + asm(" bicl2 $-16,r0"); + asm(" bisl2 r0,r8"); + asm(" rotl $-19,r10,r0"); + asm(" bicl2 $-1009,r0"); + asm(" bisl2 r0,r8"); + +#endif + + /* reset input to L1,R1 */ + L1 = L2; + R1 = R2; + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("after e"); + printf("iter = %2d after e\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } +#endif + +/* XOR_start:*/ + /* + * XOR with the key schedule, "schedule" + * + * If this is an encryption operation, use schedule[i], + * otherwise use schedule [AUTH_DES_ITER-i-1] + * + * First XOR left half. + */ + if (encrypt) { + L1 ^= *(((unsigned long *) &schedule[i] )+0); + /* now right half */ + R1 ^= *(((unsigned long *) &schedule[i] )+1); + } + else { + L1 ^= *(((unsigned long *) &schedule[AUTH_DES_ITER-i-1] )+0); + /* now right half */ + R1 ^= *(((unsigned long *) &schedule[AUTH_DES_ITER-i-1] )+1); + } + + /* dont have to reset input to L1, R1 */ + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("after xor"); + printf("iter = %2d after xor\n\t\tL1 R1 =",i); + des_cblock_print_file (dbg_tmp, stdout); + } +#endif + +/* S_start:*/ + /* apply the S selection from L1, R1 to R2 */ + +#ifdef notdef +#include "s.c" +#endif + + /* S operations , cant use registers for bit field stuff */ + /* from S_in to S_out */ + +#ifdef BITS16 + *S_in_a_16_p = L1&0xffff; + *S_in_b_16_p = (L1>>16)&0xffff; + *S_in_c_16_p = R1&0xffff; + (*(unsigned long *) &S_out) = + (unsigned) S_adj[0][S_in_16_a.b0]; + S_out.b1 = (unsigned) S_adj[1][S_in_16_a.b1]; + /* b2 spans two words */ + S_out.b2 = (unsigned) + S_adj[2][(unsigned) S_in_16_a.b2 + + (((unsigned) S_in_16_b.b2) << 4)]; + S_out.b3 = (unsigned) S_adj[3][S_in_16_b.b3]; + S_out.b4 = (unsigned) S_adj[4][S_in_16_b.b4]; + /* b5 spans both parts */ + S_out.b5 = (unsigned) + S_adj[5][(unsigned) S_in_16_b.b5 + + (((unsigned) S_in_16_c.b5) << 2)]; + S_out.b6 = (unsigned) S_adj[6][S_in_16_c.b6]; + S_out.b7 = (unsigned) S_adj[7][S_in_16_c.b7]; + R1 = *S_out_p; +#else + /* is a 32 bit sys */ +#ifndef VAXASM + R2 = (unsigned) S_adj[0][L1 & 077]; + L2 = (unsigned) S_adj[1][(L1 >> 6) & 077]; + R2 |= (L2 <<4 ); + L2 = (unsigned) S_adj[2][(L1 >> 12) & 077]; + R2 |= (L2 <<8); + L2 = (unsigned) S_adj[3][(L1 >> 18) & 077]; + R2 |= (L2 <<12); + L2 = (unsigned) S_adj[4][(L1 >> 24) & 077]; + R2 |= (L2 <<16); + /* b5 spans both parts */ + L2 = (unsigned) + S_adj[5][(unsigned) ((L1 >>30) & 03) + ((R1 & 017) << 2)]; + R2 |= (L2 << 20); + L2 = (unsigned) S_adj[6][(R1 >> 4) & 077]; + R2 |= (L2 <<24); + L2 = (unsigned) S_adj[7][(R1 >> 10) & 077]; + R1 = R2 | (L2 <<28); + /* reset input to L1, R1 */ +#else /* vaxasm */ + /* + * this is the c code produced above, with + * extzv replaced by rotl + */ + asm("bicl3 $-64,r9,r0"); + asm("movzbl _S_adj[r0],r8"); + asm("rotl $-6,r9,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+64[r0],r7"); + asm("ashl $4,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-12,r9,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+128[r0],r7"); + asm("ashl $8,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-18,r9,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+192[r0],r7"); + asm("ashl $12,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-24,r9,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+256[r0],r7"); + asm("ashl $16,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-30,r9,r0"); + asm("bicl2 $-4,r0"); + asm("bicl3 $-16,r10,r1"); + asm("ashl $2,r1,r1"); + asm("addl2 r1,r0"); + asm("movzbl _S_adj+320[r0],r7"); + asm("ashl $20,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-4,r10,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+384[r0],r7"); + asm("ashl $24,r7,r0"); + asm("bisl2 r0,r8"); + asm("rotl $-10,r10,r0"); + asm("bicl2 $-64,r0"); + asm("movzbl _S_adj+448[r0],r7"); + asm("ashl $28,r7,r0"); + asm("bisl2 r8,r0"); + asm("movl r0,r10"); + +#endif /* vaxasm */ +#endif + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("after s"); + printf("iter = %2d after s\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } +#endif + +/* P_start:*/ + /* and then the p permutation from R1 into R2 */ +#include "p.c" + /* reset the input to L1, R1 */ + R1 = R2; + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("after p"); + printf("iter = %2d after p\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } +#endif + + /* R1 is the output value from the f() */ + /* move R[iter] to L[iter+1] */ +/* XOR_2_start:*/ + L1 = R_save; + /* xor with left */ + R1 = L_save ^ R1; + /* reset the input */ + } + + /* flip left and right before final permutation */ + L2 = R1; /* flip */ + R2 = L1; + /* reset the input */ + L1 = L2; + R1 = R2; + +#ifdef DEBUG + if (des_debug & 2) { + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("before FP"); + printf("iter = %2d before FP\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } + +#endif + +/*FP_start:*/ + /* do the final permutation from L1R1 to L2R2 */ + /* all the fp code is in the include file */ +#include "fp.c" + + /* copy the output to the ciphertext string; + * can be same as cleartext + */ + +#ifdef MUSTALIGN + if ((long) cipher & 3) { + L_save = L2; /* cant bcopy a reg */ + R_save = R2; + bcopy((char *)&L_save,(char *)cipher++,sizeof(L_save)); + bcopy((char *)&R_save,(char *)cipher,sizeof(R_save)); + } + else +#endif + { + *cipher++ = L2; + *cipher = R2; + } + +#ifdef DEBUG + if (des_debug & 2) { + L1 = L2; + R1 = R2; + dbg_tmp[0] = L1; + dbg_tmp[1] = R1; + DBG_PRINT("done"); + printf("iter = %2d done\n\t\tL1 R1 = ",i); + des_cblock_print_file (dbg_tmp, stdout); + } +#endif + + /* that's it, no errors can be returned */ + return 0; +} + diff --git a/src/lib/crypto/des/des_int.h b/src/lib/crypto/des/des_int.h new file mode 100644 index 000000000..feea0d0c5 --- /dev/null +++ b/src/lib/crypto/des/des_int.h @@ -0,0 +1,95 @@ +/* + * $Source$ + * $Author$ + * $Header$ + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Private include file for the Data Encryption Standard library. + */ + +/* only do the whole thing once */ +#ifndef DES_INTERNAL_DEFS +#define DES_INTERNAL_DEFS + +#include +#include + +/* + * number of iterations of the inner + * loop of the DES algorithm. The + * standard is 16, but in case that is + * too slow, we might do less. Of + * course, less also means less + * security. + */ +#define AUTH_DES_ITER 16 + +#ifdef BITS32 +/* these are for 32 bit machines */ + +typedef struct { + unsigned b0:6; + unsigned b1:6; + unsigned b2:6; + unsigned b3:6; + unsigned b4:6; + unsigned b5:2; +} sbox_in_a; + +typedef struct { + unsigned b5:4; + unsigned b6:6; + unsigned b7:6; +} sbox_in_b; + +typedef struct { + unsigned b0:4; + unsigned b1:4; + unsigned b2:4; + unsigned b3:4; + unsigned b4:4; + unsigned b5:4; + unsigned b6:4; + unsigned b7:4; +} sbox_out; + +#else /*BITS32*/ +/* for sixteen bit machines */ + +typedef struct { + unsigned b0:6; + unsigned b1:6; + unsigned b2:4; +} sbox_in_16_a; + +typedef struct { + unsigned b2:2; + unsigned b3:6; + unsigned b4:6; + unsigned b5:2; +} sbox_in_16_b; + +typedef struct { + unsigned b5:4; + unsigned b6:6; + unsigned b7:6; +} sbox_in_16_c; + +typedef struct { + unsigned b0:4; + unsigned b1:4; + unsigned b2:4; + unsigned b3:4; + unsigned b4:4; + unsigned b5:4; + unsigned b6:4; + unsigned b7:4; +} sbox_out; +#endif /*BITS32*/ + + +#endif /*DES_INTERNAL_DEFS*/ diff --git a/src/lib/crypto/des/enc_dec.c b/src/lib/crypto/des/enc_dec.c new file mode 100644 index 000000000..b7fa7722c --- /dev/null +++ b/src/lib/crypto/des/enc_dec.c @@ -0,0 +1,305 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * These routines perform encryption and decryption using the DES + * private key algorithm, or else a subset of it -- fewer inner loops. + * (AUTH_DES_ITER defaults to 16, may be less.) + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_enc_dec_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include + +#include + +#ifdef DEBUG +#include + +extern int des_debug; +extern int des_debug_print(); +#endif + + +/* + encrypts "size" bytes at "in", storing result in "out". + "eblock" points to an encrypt block which has been initialized + by process_key(). + + "out" must be preallocated by the caller to contain sufficient + storage to hold the output; the macro krb5_encrypt_size() can + be used to compute this size. + + returns: errors +*/ +krb5_error_code encrypt_func(DECLARG(krb5_pointer, in), + DECLARG(krb5_pointer, out), + DECLARG(size_t, size), + DECLARG(krb5_encrypt_block *, key), + DECLARG(krb5_pointer, ivec)) +OLDDECLARG(krb5_pointer, in) +OLDDECLARG(krb5_pointer, out) +OLDDECLARG(size_t, size) +OLDDECLARG(krb5_encrypt_block *, key) +OLDDECLARG(krb5_pointer, ivec) +{ + krb5_error_code des_cbc_encrypt(); + krb5_octet *iv; + + if ( ivec == 0 ) + iv = key->key->contents; + else + iv = (krb5_octet *)ivec; + + /* XXX should check that key sched is valid here? */ + return (des_cbc_encrypt((krb5_octet *)in, + (krb5_octet *)out, + size, + (struct des_ks_struct *)key->priv, + iv, + DES_ENCRYPT)); +} + +/* + + decrypts "size" bytes at "in", storing result in "out". + "eblock" points to an encrypt block which has been initialized + by process_key(). + + "out" must be preallocated by the caller to contain sufficient + storage to hold the output; this is guaranteed to be no more than + the input size. + + returns: errors + + */ +krb5_error_code decrypt_func(DECLARG(krb5_pointer, in), + DECLARG(krb5_pointer, out), + DECLARG(size_t, size), + DECLARG(krb5_encrypt_block *, key), + DECLARG(krb5_pointer, ivec)) +OLDDECLARG(krb5_pointer, in) +OLDDECLARG(krb5_pointer, out) +OLDDECLARG(size_t, size) +OLDDECLARG(krb5_encrypt_block *, key) +OLDDECLARG(krb5_pointer, ivec) +{ + krb5_error_code des_cbc_encrypt(); + krb5_octet *iv; + + if ( ivec == 0 ) + iv = key->key->contents; + else + iv = (krb5_octet *)ivec; + + /* XXX should check that key sched is valid here? */ + return (des_cbc_encrypt ((krb5_octet *)in, + (krb5_octet *)out, + size, + (struct des_ks_struct *)key->priv, + iv, + DES_DECRYPT)); +} +/* + * This routine performs DES cipher-block-chaining operation, either + * encrypting from cleartext to ciphertext, if encrypt != 0 or + * decrypting from ciphertext to cleartext, if encrypt == 0. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not + * enough space was provided, your program will get trashed. + * + * For encryption, the cleartext string is null padded, at the end, to + * an integral multiple of eight bytes. + * + * For decryption, the ciphertext will be used in integral multiples + * of 8 bytes, but only the first "length" bytes returned into the + * cleartext. + */ + +krb5_error_code +des_cbc_encrypt(in,out,length,key,iv,encrypt) + krb5_octet *in; /* >= length bytes of input text */ + krb5_octet *out; /* >= length bytes of output text */ + register long length; /* in bytes */ + int encrypt; /* 0 ==> decrypt, else encrypt */ + des_key_schedule key; /* precomputed key schedule */ + krb5_octet *iv; /* 8 bytes of ivec */ +{ + int des_ecb_encrypt(); + + register unsigned long *input = (unsigned long *) in; + register unsigned long *output = (unsigned long *) out; + register unsigned long *ivec = (unsigned long *) iv; + + unsigned long i,j; + static unsigned long t_input[2]; + static unsigned long t_output[2]; + static unsigned char *t_in_p; + static unsigned long xor_0, xor_1; + + t_in_p = (unsigned char *) t_input; + if (encrypt) { +#ifdef MUSTALIGN + if ((long) ivec & 3) { + bcopy((char *)ivec++, (char *)&t_output[0], sizeof(t_output[0])); + bcopy((char *)ivec, (char *)&t_output[1], sizeof(t_output[1])); + } + else +#endif + { + t_output[0] = *ivec++; + t_output[1] = *ivec; + } + + for (i = 0; length > 0; i++, length -= 8) { + /* get input */ +#ifdef MUSTALIGN + if ((long) input & 3) { + bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0])); + bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[1])); + } + else +#endif + { + t_input[0] = *input++; + t_input[1] = *input++; + } + + /* zero pad */ + if (length < 8) + for (j = length; j <= 7; j++) + *(t_in_p+j)= 0; + +#ifdef DEBUG + if (des_debug) + des_debug_print("clear",length,t_input[0],t_input[1]); +#endif + /* do the xor for cbc into the temp */ + t_input[0] ^= t_output[0]; + t_input[1] ^= t_output[1]; + /* encrypt */ + (void) des_ecb_encrypt(t_input,t_output,key,encrypt); + /* copy temp output and save it for cbc */ +#ifdef MUSTALIGN + if ((long) output & 3) { + bcopy((char *)&t_output[0],(char *)output++, + sizeof(t_output[0])); + bcopy((char *)&t_output[1],(char *)output++, + sizeof(t_output[1])); + } + else +#endif + { + *output++ = t_output[0]; + *output++ = t_output[1]; + } + +#ifdef DEBUG + if (des_debug) { + des_debug_print("xor'ed",i,t_input[0],t_input[1]); + des_debug_print("cipher",i,t_output[0],t_output[1]); + } +#endif + } + return 0; + } + + else { + /* decrypt */ +#ifdef MUSTALIGN + if ((long) ivec & 3) { + bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0)); + bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1)); + } + else +#endif + { + xor_0 = *ivec++; + xor_1 = *ivec; + } + + for (i = 0; length > 0; i++, length -= 8) { + /* get input */ +#ifdef MUSTALIGN + if ((long) input & 3) { + bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0])); + bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[0])); + } + else +#endif + { + t_input[0] = *input++; + t_input[1] = *input++; + } + + /* no padding for decrypt */ +#ifdef DEBUG + if (des_debug) + des_debug_print("cipher",i,t_input[0],t_input[1]); +#else +#ifdef lint + i = i; +#endif +#endif + /* encrypt */ + (void) des_ecb_encrypt(t_input,t_output,key,encrypt); +#ifdef DEBUG + if (des_debug) + des_debug_print("out pre xor",i,t_output[0],t_output[1]); +#endif + /* do the xor for cbc into the output */ + t_output[0] ^= xor_0; + t_output[1] ^= xor_1; + /* copy temp output */ +#ifdef MUSTALIGN + if ((long) output & 3) { + bcopy((char *)&t_output[0],(char *)output++, + sizeof(t_output[0])); + bcopy((char *)&t_output[1],(char *)output++, + sizeof(t_output[1])); + } + else +#endif + { + *output++ = t_output[0]; + *output++ = t_output[1]; + } + + /* save xor value for next round */ + xor_0 = t_input[0]; + xor_1 = t_input[1]; +#ifdef DEBUG + if (des_debug) + des_debug_print("clear",i,t_output[0],t_output[1]); +#endif + } + return 0; + } +} diff --git a/src/lib/crypto/des/fin_rndkey.c b/src/lib/crypto/des/fin_rndkey.c new file mode 100644 index 000000000..1c21884a3 --- /dev/null +++ b/src/lib/crypto/des/fin_rndkey.c @@ -0,0 +1,36 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_fnr_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include + +/* + free any resources held by "seed" and assigned by init_random_key() + */ + +krb5_error_code finish_random_key (DECLARG(krb5_pointer *, seed)) +OLDDECLARG(krb5_pointer *, seed) +{ + bzero( (char *)*seed, sizeof(des_random_key_seed) ); + free((char *)*seed); + *seed = 0; + return 0; /* XXX init_random_key */ +} diff --git a/src/lib/crypto/des/finish_key.c b/src/lib/crypto/des/finish_key.c new file mode 100644 index 000000000..7a5ec8135 --- /dev/null +++ b/src/lib/crypto/des/finish_key.c @@ -0,0 +1,41 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_fin_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include + +#include + +/* + does any necessary clean-up on the eblock (such as releasing + resources held by eblock->priv). + + returns: errors + */ + +krb5_error_code finish_key (DECLARG(krb5_encrypt_block *,eblock)) +OLDDECLARG(krb5_encrypt_block *,eblock) +{ + bzero((char *)eblock->priv, sizeof(des_key_schedule)); + free(eblock->priv); + eblock->priv = 0; + /* free/clear other stuff here? */ + return 0; +} diff --git a/src/lib/crypto/des/init_rkey.c b/src/lib/crypto/des/init_rkey.c new file mode 100644 index 000000000..c311cbd98 --- /dev/null +++ b/src/lib/crypto/des/init_rkey.c @@ -0,0 +1,51 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_inr_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include +#include + +extern void des_init_random_number_generator(); + +/* + initialize the random key generator using the encryption key, + "seedblock", and allocating private sequence information, filling + in "seed" with the address of such information. + "seed" is later passed to the random_key() function to provide + sequence information. + */ + +krb5_error_code init_random_key (DECLARG(krb5_keyblock *,seedblock), + DECLARG(krb5_pointer *,seed)) +OLDDECLARG(krb5_keyblock *,seedblock) +OLDDECLARG(krb5_pointer *,seed) +{ + des_random_key_seed * p_seed; + if (seedblock->keytype != KEYTYPE_DES) + return KRB5_BAD_KEYTYPE; /* XXX error code bad keytype */ + if ( !(p_seed = (des_random_key_seed *) + malloc(sizeof(des_random_key_seed))) ) + return ENOMEM; + bzero( (char *)p_seed, sizeof(des_random_key_seed) ); + des_init_random_number_generator(seedblock->contents, p_seed); + *seed = (krb5_pointer) p_seed; + return 0; +} diff --git a/src/lib/crypto/des/key_parity.c b/src/lib/crypto/des/key_parity.c new file mode 100644 index 000000000..a6db13b10 --- /dev/null +++ b/src/lib/crypto/des/key_parity.c @@ -0,0 +1,65 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * These routines check and fix parity of encryption keys for the DES + * algorithm. + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + */ + +#if !defined(lint) && !defined(SABER) +static char key_parity_c[] = +"$Header$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include "des_internal.h" + +#include "odd.h" /* Load compile-time generated odd_parity table */ + +/* + * des_fixup_key_parity: Forces odd parity per byte; parity is bits + * 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order. + */ +void +des_fixup_key_parity(key) + register des_cblock key; +{ + int i; + + for (i=0; i. + * + * This routine computes the DES key schedule given a key. The + * permutations and shifts have been done at compile time, resulting + * in a direct one-step mapping from the input key to the key + * schedule. + * + * Also checks parity and weak keys. + * + * Watch out for the subscripts -- most effectively start at 1 instead + * of at zero. Maybe some bugs in that area. + * + * DON'T change the data types for arrays and such, or it will either + * break or run slower. This was optimized for Uvax2. + * + * In case the user wants to cache the computed key schedule, it is + * passed as an arg. Also implies that caller has explicit control + * over zeroing both the key schedule and the key. + * + * All registers labeled imply Vax using the Ultrix or 4.2bsd compiler. + * + * Originally written 6/85 by Steve Miller, MIT Project Athena. + */ + +#if !defined(lint) && !defined(SABER) +static char key_sched_c[] = +"$Header$"; +#endif /* !lint & !SABER */ + +#include +#include "des_internal.h" +#include + +#include +#include +#include "key_perm.h" + +extern int des_debug; +extern rev_swap_bit_pos_0(); +extern int des_check_key_parity(); +extern int des_is_weak_key(); + +typedef char key[64]; +/* the following are really void but cc86 doesnt allow it */ +void make_key_sched(); + + +int +des_key_sched(k,schedule) + register des_cblock k; /* r11 */ + des_key_schedule schedule; +{ + /* better pass 8 bytes, length not checked here */ + + register i, j, n; /* i = r10, j = r9, n = r8 */ + register unsigned int temp; /* r7 */ + register char *p_char; /* r6 */ + static key k_char; + i = 8; + n = 0; + p_char = k_char; + +#if defined(lint) || defined(SABER) + n = n; /* fool it in case of VAXASM */ +#endif +#ifdef DEBUG + if (des_debug) + fprintf(stderr,"\n\ninput key, left to right = "); +#endif + + if (!des_check_key_parity(k)) /* bad parity --> return -1 */ + return(-1); + + do { + /* get next input key byte */ +#ifdef DEBUG + if (des_debug) + fprintf(stderr,"%02x ",*k & 0xff); +#endif + temp = (unsigned int) ((unsigned char) *k++); + j = 8; + + do { +#ifndef VAXASM + *p_char++ = (int) temp & 01; + temp = temp >> 1; +#else + asm("bicb3 $-2,r7,(r8)+[r6]"); + asm("rotl $-1,r7,r7"); +#endif + } while (--j > 0); + } while (--i > 0); + +#ifdef DEBUG + if (des_debug) { + p_char = k_char; + fprintf(stderr,"\nKey bits, from zero to 63"); + for (i = 0; i <= 7; i++) { + fprintf(stderr,"\n\t"); + for (j = 0; j <=7; j++) + fprintf(stderr,"%d ",*p_char++); + } + } +#else +#ifdef lint + p_char = p_char; +#endif +#endif + + /* check against weak keys */ + k -= sizeof(des_cblock); + + if (des_is_weak_key(k)) + return(-2); + + make_key_sched(k_char,schedule); + + /* if key was good, return 0 */ + return 0; +} + +static void +make_key_sched(Key,Schedule) + register key Key; /* r11 */ + des_key_schedule Schedule; +{ + /* + * The key has been converted to an array to make this run faster; + * on a microvax 2, this routine takes about 3.5ms. The code and + * size of the arrays has been played with to get it as fast as + * possible. + * + * Don't change the order of the declarations below without + * checking the assembler code to make sure that things are still + * where it expects them. + */ + + /* r10, unroll by AUTH_DES_ITER */ + register int iter = AUTH_DES_ITER ; + register unsigned long *k; /* r9 */ + register int *kp; /* r8 */ + register unsigned long temp; /* r7 */ + + kp = (int *) key_perm; + k = (unsigned long *) Schedule; + + do { + /* + * create the Key schedule + * + * put into lsb first order (lsb is bit 0) + */ + + /* + * On the uvax2, this C code below is as fast as straight + * assembler, so just use C code below. + */ + temp = 0; +#ifdef LSBFIRST +#define BIT(x) x +#else +#ifdef notdef +#define BIT(x) rev_swap_bit_pos_0(x) +#else +#define BIT(x) x +#endif +#endif + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(0)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(1)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(2)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(3)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(4)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(5)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(6)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(7)); + + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(8)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(9)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(10)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(11)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(12)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(13)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(14)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(15)); + + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(16)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(17)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(18)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(19)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(20)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(21)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(22)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(23)); + + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(24)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(25)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(26)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(27)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(28)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(29)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(30)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(31)); + + *k++ = temp; + temp = 0; + + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(0)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(1)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(2)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(3)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(4)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(5)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(6)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(7)); + + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(8)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(9)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(10)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(11)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(12)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(13)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(14)); + if ((unsigned) Key[(int) *kp++]) temp |= (1<< BIT(15)); + + *k++ = temp; + + } while (--iter > 0); + +#ifdef DEBUG + if (des_debug) { + char *n; + int q; + fprintf(stderr,"\nKey Schedule, left to right"); + for (i = 0; i < AUTH_DES_ITER; i++) { + n = (char *) &Schedule[i]; + fprintf(stderr,"\n"); + for (q = 0; q <= 7; q++) + fprintf(stderr,"%02x ",*n++ & 0xff); + } + fprintf(stderr,"\n"); + } +#endif +} diff --git a/src/lib/crypto/des/make_e.c b/src/lib/crypto/des/make_e.c new file mode 100644 index 000000000..5db85ee13 --- /dev/null +++ b/src/lib/crypto/des/make_e.c @@ -0,0 +1,42 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file . + * + * This routine generates source code that implements the "E" + * operations of the DES. + */ + +#include +#include "des_internal.h" +#include "tables.h" + +void gen(stream) + FILE *stream; +{ + register i; + + /* clear the output */ + fprintf(stream, " L2 = 0; R2 = 0;\n"); + + /* only take bits from R1, put into either L2 or R2 */ + /* first setup E */ + fprintf(stream, "/* E operations */\n/* right to left */\n"); + /* first list mapping from left to left */ + + for (i = 0; i <= 31; i++) + if (E[i] < 32) + fprintf(stream, + " if (R1 & (1<<%2d)) L2 |= 1<<%2d;\n", E[i], i); + + fprintf(stream, "\n/* now from right to right */\n"); + /* list mapping from left to right */ + for (i = 32; i <= 47; i++) + if (E[i] <32) + fprintf(stream, " if (R1 & (1<<%2d)) R2 |= 1<<%2d;\n", + E[i], i-32); +} diff --git a/src/lib/crypto/des/make_fp.c b/src/lib/crypto/des/make_fp.c new file mode 100644 index 000000000..7e19bd081 --- /dev/null +++ b/src/lib/crypto/des/make_fp.c @@ -0,0 +1,72 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file . + * + * This file contains a generation routine for source code + * implementing the final permutation of the DES. + */ + +#include +#include +#include +#include +#include "des_internal.h" +#include "tables.h" + +extern unsigned int swap_bit_pos_0_to_ansi PROTOTYPE((unsigned int)); +extern long swap_long_bytes(); +extern unsigned long swap_long_bytes_bit_number(); +extern void test_set PROTOTYPE((FILE *, char const *, int, + char const *, int)); + +void gen (stream) + FILE * stream; +{ + register i; + + /* clear the output */ + fprintf(stream," L2 = 0; R2 = 0;\n"); + + /* + * NOTE: As part of the final permutation, we also have to adjust + * for host bit order via "swap_bit_pos_0()". Since L2,R2 are + * the output from this, we adjust the bit positions written into + * L2,R2. + */ + +#define SWAP(i,j) \ + swap_long_bytes_bit_number(swap_bit_pos_0_to_ansi((unsigned)i)-j) + + /* first setup FP */ + fprintf(stream, + "/* FP operations */\n/* first left to left */\n"); + + /* first list mapping from left to left */ + for (i = 0; i <= 31; i++) + if (FP[i] < 32) + test_set(stream, "L1", FP[i], "L2", SWAP(i,0)); + + /* now mapping from right to left */ + fprintf(stream,"\n\n/* now from right to left */\n"); + for (i = 0; i <= 31; i++) + if (FP[i] >= 32) + test_set(stream, "R1", FP[i]-32, "L2", SWAP(i,0)); + + fprintf(stream,"\n/* now from left to right */\n"); + + /* list mapping from left to right */ + for (i = 32; i <= 63; i++) + if (FP[i] <32) + test_set(stream, "L1", FP[i], "R2", SWAP(i,32)); + + /* now mapping from right to right */ + fprintf(stream,"\n/* last from right to right */\n"); + for (i = 32; i <= 63; i++) + if (FP[i] >= 32) + test_set(stream, "R1", FP[i]-32, "R2", SWAP(i,32)); +} diff --git a/src/lib/crypto/des/make_ip.c b/src/lib/crypto/des/make_ip.c new file mode 100644 index 000000000..54e927c50 --- /dev/null +++ b/src/lib/crypto/des/make_ip.c @@ -0,0 +1,61 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * This routine generates source code implementing the initial + * permutation of the DES. + */ + +#include +#include +#include "des_internal.h" +#include "tables.h" + +extern long swap_bit_pos_0(); +extern long rev_swap_bit_pos_0(); +extern void test_set(); +extern unsigned long swap_long_bytes_bit_number(); +unsigned long swap_bit_pos_0_to_ansi(); + +#define SWAP(x) swap_long_bytes_bit_number(swap_bit_pos_0_to_ansi(x)) + +void gen(stream) + FILE *stream; +{ + register i; + + /* clear the output */ + fprintf(stream," L2 = 0; R2 = 0;\n"); + + /* first setup IP */ + fprintf(stream,"/* IP operations */\n/* first left to left */\n"); + + /* first list mapping from left to left */ + for (i = 0; i <= 31; i++) + if (IP[i] < 32) + test_set(stream, "L1", SWAP(IP[i]), "L2", i); + + /* now mapping from right to left */ + fprintf(stream,"\n/* now from right to left */\n"); + for (i = 0; i <= 31; i++) + if (IP[i] >= 32) + test_set(stream, "R1", SWAP(IP[i]-32), "L2", i); + + fprintf(stream,"\n/* now from left to right */\n"); + /* list mapping from left to right */ + for (i = 32; i <= 63; i++) + if (IP[i] <32) + test_set(stream, "L1", SWAP(IP[i]), "R2", i-32); + + /* now mapping from right to right */ + fprintf(stream,"\n/* last from right to right */\n"); + for (i = 32; i <= 63; i++) + if (IP[i] >= 32) + test_set(stream, "R1", SWAP(IP[i]-32), "R2", i-32); + exit(0); +} diff --git a/src/lib/crypto/des/make_kp.c b/src/lib/crypto/des/make_kp.c new file mode 100644 index 000000000..18c334215 --- /dev/null +++ b/src/lib/crypto/des/make_kp.c @@ -0,0 +1,217 @@ +/* + * $Source$ + * $Author$ + * $Locker$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * This routine calculates an effective Key schedule set of + * permutations for des. Beginning with the pre-defined key schedule + * algorithm, it reduces it to a set of 16 permutations upon the + * initial key. Only needs to execute once to produce a header file. + * Note that we subtract one from the values ouput to fix up for C + * subscripts starting at 0. + */ + +#include +#include +#include +#include "des_internal.h" + +#ifndef lint +static char rcsid[]= + "$Header$"; +#endif /* lint */ + +char *progname; +extern char *errmsg(); +extern int errno; +extern long swap_bit_pos_1(); +extern long swap_bit_pos_0(); +int sflag; +int vflag; +int dflag; +int pid; +int child_status; + +int key_position[64+1]; +int C[28+1]; +int D[28+1]; +int C_temp, D_temp; + +/* + * CONVENTIONS for numbering the bits + * bit 0 ==> lsb + * L starts at bit 0 + * R starts at bit 64 + * + * BEWARE-- some stuff starts at 0, some at 1; perhaps some bugs still? + */ + +/* + * Sequence of shifts used for the key schedule. + */ +int shift[16+1] = { 0, + 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, +}; + +int pc_1[64+1] = { 0, + + 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, + + 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, +}; + + +/* + * Permuted-choice 2, to pick out the bits from + * the CD array that generate the key schedule. + */ +int pc_2[48+1] = { 0, + + 14,17,11,24, 1, 5, + 3,28,15, 6,21,10, + 23,19,12, 4,26, 8, + 16, 7,27,20,13, 2, + + 41,52,31,37,47,55, + 30,40,51,45,33,48, + 44,49,39,56,34,53, + 46,42,50,36,29,32, +}; + +int ks_perm[16+1][48+1]; + +int des_debug; + +void gen(stream) + FILE *stream; +{ + /* Local Declarations */ + register i, j, iter; + + /* + * initialize the key_position array s.t. key_position[i] = i; + * that is, each element is equal to its starting position. + * + * Also adjust for the bit order within bytes. + */ + + for (i=0; i<65; i++) + key_position[i]= swap_bit_pos_1(i); + + fprintf(stream,"static int const key_perm[16][48] = {\n"); + + /* + * apply pc_1 to initial key_position to create C[0] and D[0] + * Start at pc_1[1], not pc_1[0] + */ + for (i=1; i<=28; i++) { + C[i] = key_position[pc_1[i]]; + D[i] = key_position[pc_1[i+28]]; + } + + /* + * major loop over the 16 iterations + * start at iter = 1, not zero. + */ + for (iter = 1; iter <= 16; iter++) { + if (des_debug) { + /* for debugging */ + printf( + "/* DEBUG-- start iteration = %d shifts = %d", + iter, shift[iter]); + printf("\nC array"); + for (i = 1; i <=4 ; i++) { + printf("\n"); + for (j = 1; j<=7; j++) + printf("%d, ",C[(i-1)*7+j]); + } + printf("\n\nD array"); + for (i = 1; i <=4 ; i++) { + printf("\n"); + for (j = 1; j<=7; j++) + printf("%d, ",D[(i-1)*7+j]); + } + printf("\n */"); + fflush(stdout); + } + + /* apply the appropriate left shifts */ + for (i = 1; i <= shift[iter]; i++) { + C_temp = C[1]; + D_temp = D[1]; + for (j =1; j<=27; j++) { + C[j] = C[j+1]; + D[j] = D[j+1]; + } + C[j] = C_temp; + D[j] = D_temp; + } + + + if (des_debug) { + /* for debugging */ + printf("/* DEBUG:\n"); + printf(" * after shifts, iteration = %d shifts = %d", + iter, shift[iter]); + printf("\nC array"); + for (i = 1; i <=4 ; i++) { + printf("\n"); + for (j = 1; j<=7; j++) + printf("%d, ",C[(i-1)*7+j]); + } + printf("\n\nD array"); + for (i = 1; i <=4 ; i++) { + printf("\n"); + for (j = 1; j<=7; j++) + printf("%d, ",D[(i-1)*7+j]); + } + printf("\n */"); + fflush(stdout); + } + + /* + * apply pc_2 + * Start at pc_2[1], not pc_2[0] + * + * Start stuffing ks_perm[1][1], not ks_perm[0][0] + * + * Adjust ks_perm for bit order if needed. + */ + for (i = 1; i <= 48; i++) { + if (pc_2[i] <= 28) + ks_perm[iter][(i)] = C[pc_2[i]]; + else + ks_perm[iter][(i)] = D[pc_2[i]-28]; + } + + /* now output the resulting key permutation */ + fprintf(stream, " /* ks permutation iteration = %2d */", + iter); + for (i = 1; i <= 6; i++) { + fprintf(stream, "\n "); + for (j = 1; j <= 8; j++) { + /* + * IMPORTANT -- subtract one from value to adjust to a + * zero-based subscript for key + */ + fprintf(stream, "%d", ks_perm[iter][(i-1)*8+j]-1); + /* omit last comma */ + if ((j != 8) || (i != 6) || (iter != 16)) { + fprintf(stream,", "); + } + } + } + } + fprintf(stream,"\n};\n"); +} diff --git a/src/lib/crypto/des/make_odd.c b/src/lib/crypto/des/make_odd.c new file mode 100644 index 000000000..d44159523 --- /dev/null +++ b/src/lib/crypto/des/make_odd.c @@ -0,0 +1,47 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see + * the file . + * + * This routine generates an odd-parity table for use in key generation. + */ + +#include +#include + +void gen(stream) + FILE *stream; +{ + /* + * map a byte into its equivalent with odd parity, where odd + * parity is in the least significant bit + */ + register i, j, k, odd; + + fprintf(stream, + "static unsigned char const odd_parity[256] = {\n"); + + for (i = 0; i < 256; i++) { + odd = 0; + /* shift out the lsb parity bit */ + k = i >> 1; + /* then count the other bits */ + for (j = 0; j < 7; j++) { + odd ^= (k&1); + k = k >> 1; + } + k = i&~1; + if (!odd) + k |= 1; + fprintf(stream, "%3d", k); + if (i < 255) + fprintf(stream, ", "); + if (i%8 == 0) + fprintf(stream, "\n"); + } + fprintf(stream, "};\n"); +} diff --git a/src/lib/crypto/des/make_p.c b/src/lib/crypto/des/make_p.c new file mode 100644 index 000000000..becac62f3 --- /dev/null +++ b/src/lib/crypto/des/make_p.c @@ -0,0 +1,51 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please + * see the file . + * + * This routine generates the P permutation code for the DES. + */ + +#include +#include +#include "des_internal.h" +#include "tables.h" + +void gen(stream) + FILE *stream; +{ + /* P permutes 32 bit input R1 into 32 bit output R2 */ + + /* clear the output */ + fprintf(stream," L2 = 0;\n"); +#ifndef BIG + fprintf(stream," R2 = 0;\n"); + fprintf(stream, + "/* P operations */\n/* from right to right */\n"); + /* first list mapping from left to left */ + for (i = 0; i <=31; i++) + if (P[i] < 32) + fprintf(stream, + " if (R1 & (1<<%d)) R2 |= 1<<%d;\n",P[i],i); +#else /* BIG */ + /* flip p into p_temp */ + fprintf(stream," P_temp = R1;\n"); + fprintf(stream," P_temp_p = (unsigned char *) &P_temp;\n"); + +#ifdef LSBFIRST + fprintf(stream," R2 = P_prime[0][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[1][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[2][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[3][*P_temp_p];\n"); +#else /* MSBFIRST */ + fprintf(stream," R2 = P_prime[3][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[2][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[1][*P_temp_p++];\n"); + fprintf(stream," R2 |= P_prime[0][*P_temp_p];\n"); +#endif /* MSBFIRST */ +#endif /* BIG */ +} diff --git a/src/lib/crypto/des/make_pt.c b/src/lib/crypto/des/make_pt.c new file mode 100644 index 000000000..2d8787b76 --- /dev/null +++ b/src/lib/crypto/des/make_pt.c @@ -0,0 +1,68 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please + * see the file . + * + */ + +#include +#include +#include "des_internal.h" +#include "tables.h" + +extern unsigned long swap_byte_bits(); +extern unsigned long rev_swap_bit_pos_0(); +static unsigned char P_temp[32]; +static unsigned long P_prime[4][256]; + +void gen(stream) + FILE *stream; +{ + register i,j,k,m; + /* P permutes 32 bit input R1 into 32 bit output R2 */ + +#ifdef BIG + /* flip p into p_temp */ + for (i = 0; i<32; i++) + P_temp[P[rev_swap_bit_pos_0(i)]] = rev_swap_bit_pos_0(i); + + /* + * now for each byte of input, figure out all possible combinations + */ + for (i = 0; i <4 ; i ++) { /* each input byte */ + for (j = 0; j<256; j++) { /* each possible byte value */ + /* flip bit order */ + k = j; + /* swap_byte_bits(j); */ + for (m = 0; m < 8; m++) { /* each bit */ + if (k & (1 << m)) { + /* set output values */ + P_prime[i][j] |= 1 << P_temp[(i*8)+m]; + } + } + } + } + + fprintf(stream, + "\n\tstatic unsigned long const P_prime[4][256] = {\n\t"); + for (i = 0; i < 4; i++) { + fprintf(stream,"\n"); + for (j = 0; j < 64; j++) { + fprintf(stream,"\n"); + for (k = 0; k < 4; k++) { + fprintf(stream,"0x%08X",P_prime[i][j*4+k]); + if ((i == 3) && (j == 63) && (k == 3)) + fprintf(stream,"\n};"); + else + fprintf(stream,", "); + } + } + } + +#endif + fprintf(stream,"\n"); +} diff --git a/src/lib/crypto/des/make_s.c b/src/lib/crypto/des/make_s.c new file mode 100644 index 000000000..1e1781702 --- /dev/null +++ b/src/lib/crypto/des/make_s.c @@ -0,0 +1,33 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please + * see the file . + */ + +#include +#include +#include "des_internal.h" +#include "s_table.h" + +void gen(stream) + FILE *stream; +{ + /* clear the output */ + fprintf(stream,"\n\tL2 = 0; R2 = 0;"); + +#ifdef notdef + /* P permutes 32 bit input R1 into 32 bit output R2 */ + + fprintf(stream,"\n/* P operations */\n/* first left to left */\n"); + /* first list mapping from left to left */ + for (i = 0; i <=31; i++) + if (S[i] < 32) + fprintf(stream, + "\n\tif (R1 & (1<<%d)) R2 |= 1<<%d;",S[i],i); +#endif + fprintf(stream,"\n"); +} diff --git a/src/lib/crypto/des/make_st.c b/src/lib/crypto/des/make_st.c new file mode 100644 index 000000000..78601e03d --- /dev/null +++ b/src/lib/crypto/des/make_st.c @@ -0,0 +1,71 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please + * see the file . + */ + +#include +#include +#include "des_internal.h" +#include "tables.h" + +extern unsigned long swap_bit_pos_0(); +extern unsigned long swap_six_bits_to_ansi(); +extern unsigned long swap_four_bits_to_ansi(); +char temp[8][64]; +int des_debug; + +void gen(stream) + FILE *stream; +{ + register unsigned long i,j,k,l,m,n; + + /* rearrange the S table entries, and adjust for host bit order */ + + fprintf(stream, "static unsigned char const S_adj[8][64] = {"); + fprintf(stream, " /* adjusted */\n"); + + for (i = 0; i<=7 ; i++) { + for (j = 0; j <= 63; j++) { + /* + * figure out which one to put in the new S[i][j] + * + * start by assuming the value of the input bits is "j" in + * host order, then figure out what it means in standard + * form. + */ + k = swap_six_bits_to_ansi(j); + /* figure out the index for k */ + l = (((k >> 5) & 01) << 5) + + ((k & 01) <<4) + ((k >> 1) & 0xf); + m = S[i][l]; + /* restore in host order */ + n = swap_four_bits_to_ansi(m); + if (des_debug) + fprintf(stderr, + "i = %d, j = %d, k = %d, l = %d, m = %d, n = %d\n", + i,j,k,l,m,n); + temp[i][j] = n; + } + } + + for (i = 0; i<=7; i++) { + fprintf(stream,"\n"); + k =0; + for (j = 0; j<= 3; j++) { + fprintf(stream,"\n"); + for (m = 0; m <= 15; m++) { + fprintf(stream,"%2d",temp[i][k]); + if ((k++ != 63) || (i !=7)) { + fprintf(stream,", "); + } + } + } + } + + fprintf(stream,"\n};\n"); +} diff --git a/src/lib/crypto/des/misc.c b/src/lib/crypto/des/misc.c new file mode 100644 index 000000000..a7add4c66 --- /dev/null +++ b/src/lib/crypto/des/misc.c @@ -0,0 +1,354 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please seethe file . + * + * This file contains most of the routines needed by the various + * make_foo programs, to account for bit- and byte-ordering on + * different machine types. It also contains other routines useful in + * generating the intermediate source files. + */ + +#include +#include +#include +#include +#include + +#include +#include "des_internal.h" + +/* + * The DES algorithm is defined in terms of MSBFIRST, so sometimes, + * e.g. VAXes, we need to fix it up. ANSI order means the DES + * MSBFIRST order. + */ + +#if 0 /* These don't seem to get used anywhere.... */ +void swap_bits(array) + char *array; +{ +#ifdef MSBFIRST + /* just return */ + return; +#else /* LSBFIRST */ + register old,new,i,j; + + /* for an eight byte block-- */ + /* flips the bit order within each byte from 0 lsb to 0 msb */ + for (i = 0; i<=7; i++) { + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + new |= old & 01; /* copy a bit */ + if (j < 7) { + /* rotate in opposite directions */ + old = old >> 1; + new = new << 1; + } + } + *array++ = new; + } +#endif /* MSBFIRST */ +} + +unsigned long long_swap_bits(x) + unsigned long x; +{ +#ifdef MSBFIRST + return x; +#else + char *array = (char *) &x; + register old,new,i,j; + + /* flips the bit order within each byte from 0 lsb to 0 msb */ + for (i = 0; i <= (sizeof(long)-1); i++) { + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + if (old & 01) + new = new | 01; + if (j < 7) { + old = old >> 1; + new = new << 1; + } + } + *array++ = new; + } + return x; +#endif /* LSBFIRST */ +} +#endif /* 0 */ + +unsigned long swap_six_bits_to_ansi(old) + unsigned long old; +{ + register unsigned long new, j; + + /* flips the bit order within each byte from 0 lsb to 0 msb */ + new = 0; + for (j = 0; j<=5; j++) { + new |= old & 01; /* copy a bit */ + if (j < 5) { + /* rotate in opposite directions */ + old = old >> 1; + new = new << 1; + } + } + return new; +} + +unsigned long swap_four_bits_to_ansi(old) + unsigned long old; +{ + register unsigned long new,j; + + /* flips the bit order within each byte from 0 lsb to 0 msb */ + new = 0; + for (j = 0; j<=3; j++) { + new |= (old & 01); /* copy a bit */ + if (j < 3) { + old = old >> 1; + new = new << 1; + } + } + return new; +} + +unsigned long swap_bit_pos_1(x) + unsigned long x; +{ + /* + * This corrects for the bit ordering of the algorithm, e.g. + * bit 0 ==> msb, bit 7 lsb. + * + * given the number of a bit position, >=1, flips the bit order + * each byte. e.g. bit 3 --> bit 6, bit 13 --> bit 12 + */ + register y,z; + + /* always do it, only used by des_make_key_perm.c so far */ + y = (x-1)/8; + z = (x-1)%8; + + x = (8-z) + (y*8); + + return x; +} + +unsigned long swap_bit_pos_0(x) + unsigned long x; +{ + /* zero based version */ + + /* + * This corrects for the bit ordering of the algorithm, e.g. + * bit 0 ==> msb, bit 7 lsb. + */ + +#ifdef MSBFIRST + return x; +#else /* LSBFIRST */ + register y,z; + + /* + * given the number of a bit position, >=0, flips the bit order + * each byte. e.g. bit 3 --> bit 6, bit 13 --> bit 12 + */ + y = x/8; + z = x%8; + + x = (7-z) + (y*8); + + return x; +#endif /* LSBFIRST */ +} + +unsigned long swap_bit_pos_0_to_ansi(x) + unsigned long x; +{ + /* zero based version */ + + /* + * This corrects for the bit ordering of the algorithm, e.g. + * bit 0 ==> msb, bit 7 lsb. + */ + + register y,z; + /* + * given the number of a bit position, >=0, flips the bit order each + * byte. e.g. bit 3 --> bit 6, bit 13 --> bit 12 + */ + y = x/8; + z = x%8; + + x = (7-z) + (y*8); + + return x; +} + +unsigned long rev_swap_bit_pos_0(x) + unsigned long x; +{ + /* zero based version */ + + /* + * This corrects for the bit ordering of the algorithm, e.g. + * bit 0 ==> msb, bit 7 lsb. + * + * Role of LSB and MSB flipped from the swap_bit_pos_0() + */ + +#ifdef LSBFIRST + return x; +#else /* MSBFIRST */ + + register y,z; + + /* + * given the number of a bit position, >=0, flips the bit order each + * byte. e.g. bit 3 --> bit 6, bit 13 --> bit 12 + */ + y = x/8; + z = x%8; + + x = (7-z) + (y*8); + + return x; +#endif /* MSBFIRST */ +} + +unsigned long swap_byte_bits(x) + unsigned long x; +{ +#ifdef MSBFIRST + return x; +#else /* LSBFIRST */ + + char *array = (char *) &x; + register unsigned long old,new,j; + + /* flips the bit order within each byte from 0 lsb to 0 msb */ + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + new |= (old & 01); /* copy a bit */ + if (j < 7) { + old = old >> 1; + new = new << 1; + } + } + return new; +#endif /* LSBFIRST */ +} + +unsigned long +swap_long_bytes_bit_number(x) + unsigned long x; +{ + /* + * given a bit number (0-31) from a vax, swap the byte part of the + * bit number to change the byte ordering to mSBFIRST type + */ +#ifdef LSBFIRST + return x; +#else /* MSBFIRST */ + unsigned long y,z; + + y = x/8; /* initial byte component */ + z = x%8; /* bit within byte */ + + x = (3-y)*8 +z; + return x; +#endif /* MSBFIRST */ +} + +void test_set(stream, src, testbit, dest, setbit) + FILE *stream; + const char *src; + int testbit; + const char *dest; + int setbit; +{ +#ifdef DES_SHIFT_SHIFT + if (testbit == setbit) + fprintf(stream, " %s |= %s & (1<<%2d);\n", + dest, src, testbit); + else + fprintf(stream, " %s |= (%s & (1<<%2d)) %s %2d;\n", + dest, src, testbit, + (testbit < setbit) ? "<<" : ">>", + abs(testbit - setbit)); +#else + fprintf(stream, + " if (%s & (1<<%2d)) %s |= 1<<%2d;\n", + src, testbit, dest, setbit); +#endif +} + +extern void gen PROTOTYPE((FILE *)); +int des_debug; +char const *whoami; + +void +main(argc, argv) + int argc; + char *argv[]; +{ + char *filename; + char *arg; + FILE *stream = 0; + + whoami = argv[0]; + filename = (char *)NULL; + + while (argc--, *++argv) { + arg = *argv; + if (*arg == '-') { + if (!strcmp(arg, "-d") && !strcmp(arg, "-debug")) + des_debug++; + else { + fprintf(stderr, "%s: unknown control argument %s\n", + whoami, arg); + goto usage; + } + } + else if (filename) { + fprintf(stderr, + "%s: multiple file names provided: %s, %s\n", + whoami, filename, arg); + goto usage; + } + else + filename = arg; + } + + if (!filename) { + fprintf(stderr, "%s: no file name provided\n", whoami); + goto usage; + } + + stream = fopen(filename, "w"); + if (!stream) { + perror(filename); + usage: + fprintf(stderr, "usage: %s [-debug] filename\n", whoami); + exit(1); + } + + fputs( + "/* This file is automatically generated. Do not edit it. */\n", + stream); + + /* This routine will generate the contents of the file. */ + gen(stream); + if (fclose(stream) == EOF) { + perror(filename); + exit(1); + } + exit(0); +} diff --git a/src/lib/crypto/des/new_rn_key.c b/src/lib/crypto/des/new_rn_key.c new file mode 100644 index 000000000..437e88c9a --- /dev/null +++ b/src/lib/crypto/des/new_rn_key.c @@ -0,0 +1,210 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * New pseudo-random key generator, using DES encryption to make the + * pseudo-random cycle as hard to break as DES. + * + * Written by Mark Lillibridge, MIT Project Athena + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + */ + +#if !defined(lint) && !defined(SABER) +static char new_rnd_key_c[] = +"$Header$"; +#endif /* !lint & !SABER */ + +#include + +#include +#include +#include "des_internal.h" + +extern void des_fixup_key_parity(); +extern int des_is_weak_key(); +extern int des_ecb_encrypt(); +extern int des_key_sched(); +void des_set_random_generator_seed(), des_set_sequence_number(); +void des_generate_random_block(); + +/* + * des_new_random_key: create a random des key + * + * Requires: des_set_random_number_generater_seed must be at called least + * once before this routine is called. + * + * Notes: the returned key has correct parity and is guarenteed not + * to be a weak des key. Des_generate_random_block is used to + * provide the random bits. + */ +int +des_new_random_key(key, p_seed) + des_cblock key; + des_random_key_seed *p_seed; +{ + do { + des_generate_random_block(key, p_seed); + des_fixup_key_parity(key); + } while (des_is_weak_key(key)); + + return(0); +} + +/* + * des_init_random_number_generator: + * + * This routine takes a secret key possibly shared by a number + * of servers and uses it to generate a random number stream that is + * not shared by any of the other servers. It does this by using the current + * process id, host id, and the current time to the nearest second. The + * resulting stream seed is not useful information for cracking the secret + * key. Moreover, this routine keeps no copy of the secret key. + * This routine is used for example, by the kerberos server(s) with the + * key in question being the kerberos master key. + * + * Note: this routine calls des_set_random_generator_seed. + */ +#ifndef BSDUNIX + you lose... (aka, you get to implement an analog of this for your + system...) +#else + +#include +#include +extern long gethostid(); + +void des_init_random_number_generator(key,p_seed) + des_cblock key; + des_random_key_seed *p_seed; +{ + struct { /* This must be 64 bits exactly */ + long process_id; + long host_id; + } seed; + struct timeval time; /* this must also be 64 bits exactly */ + des_cblock new_key; + + /* + * use a host id and process id in generating the seed to ensure + * that different servers have different streams: + */ + seed.host_id = gethostid(); + seed.process_id = (long) getpid(); + + /* + * Generate a tempory value that depends on the key, host_id, and + * process_id such that it gives no useful information about the key: + */ + des_set_random_generator_seed(key, p_seed); + des_set_sequence_number((unsigned char *)&seed, p_seed); + des_new_random_key(new_key, p_seed); + + /* + * use it to select a random stream: + */ + des_set_random_generator_seed(new_key, p_seed); + + /* + * use a time stamp to ensure that a server started later does not reuse + * an old stream: + */ + gettimeofday(&time, (struct timezone *)0); + des_set_sequence_number((unsigned char *)&time, p_seed); + + /* + * use the time stamp finally to select the final seed using the + * current random number stream: + */ + des_new_random_key(new_key, p_seed); + des_set_random_generator_seed(new_key, p_seed); +} + +#endif /* ifdef BSDUNIX */ + +/* + * This module implements a random number generator faculty such that the next + * number in any random number stream is very hard to predict without knowing + * the seed for that stream even given the preceeding random numbers. + */ + +/* + * des_set_random_generator_seed: this routine is used to select a random + * number stream. The stream that results is + * totally determined by the passed in key. + * (I.e., calling this routine again with the + * same key allows repeating a sequence of + * random numbers) + * + * Requires: key is a valid des key. I.e., has correct parity and is not a + * weak des key. + */ +void +des_set_random_generator_seed(key, p_seed) + des_cblock key; + des_random_key_seed *p_seed; +{ + register int i; + + /* select the new stream: (note errors are not possible here...) */ + des_key_sched(key, p_seed->random_sequence_key); + + /* "seek" to the start of the stream: */ + for (i=0; i<8; i++) + p_seed->sequence_number[i] = 0; +} + +/* + * des_set_sequence_number: this routine is used to set the sequence number + * of the current random number stream. This routine + * may be used to "seek" within the current random + * number stream. + * + * Note that des_set_random_generator_seed resets the sequence number to 0. + */ +void +des_set_sequence_number(new_sequence_number, p_seed) + des_cblock new_sequence_number; + des_random_key_seed *p_seed; +{ + bcopy((char *)new_sequence_number, (char *)p_seed->sequence_number, + sizeof(p_seed->sequence_number)); +} + +/* + * des_generate_random_block: routine to return the next random number + * from the current random number stream. + * The returned number is 64 bits long. + * + * Requires: des_set_random_generator_seed must have been called at least once + * before this routine is called. + */ +void des_generate_random_block(block, p_seed) + des_cblock block; + des_random_key_seed *p_seed; +{ + int i; + + /* + * Encrypt the sequence number to get the new random block: + */ + des_ecb_encrypt((unsigned long *)p_seed->sequence_number, + (unsigned long *)block, + p_seed->random_sequence_key, 1); + + /* + * Increment the sequence number as an 8 byte unsigned number with wrap: + * (using LSB here) + */ + for (i=0; i<8; i++) { + p_seed->sequence_number[i] = (p_seed->sequence_number[i] + 1) & 0xff; + if (p_seed->sequence_number[i]) + break; + } +} diff --git a/src/lib/crypto/des/process_ky.c b/src/lib/crypto/des/process_ky.c new file mode 100644 index 000000000..be62bebec --- /dev/null +++ b/src/lib/crypto/des/process_ky.c @@ -0,0 +1,69 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_prc_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include +#include + +extern int des_key_sched(); +/* + does any necessary key preprocessing (such as computing key + schedules for DES). + eblock->crypto_entry must be set by the caller; the other elements + of eblock are to be assigned by this function. + [in particular, eblock->key must be set by this function if the key + is needed in raw form by the encryption routine] + + The caller may not move or reallocate "keyblock" before calling + finish_key on "eblock" + + returns: errors + */ + +krb5_error_code process_key (DECLARG(krb5_encrypt_block *, eblock), + DECLARG(krb5_keyblock *,keyblock)) +OLDDECLARG(krb5_encrypt_block *, eblock) +OLDDECLARG(krb5_keyblock *,keyblock) +{ + struct des_ks_struct *schedule; /* pointer to key schedules */ + + if (keyblock->length != sizeof (des_cblock)) + return KRB5_BAD_KEYSIZE; /* XXX error code-bad key size */ + + if ( !(schedule = (struct des_ks_struct *) malloc(sizeof(des_key_schedule))) ) + return ENOMEM; +#define cleanup() { free( (char *) schedule); } + + switch (des_key_sched (keyblock->contents, schedule)) { + case -1: + cleanup(); + return KRB5DES_BAD_KEYPAR; /* XXX error code-bad key parity */ + + case -2: + cleanup(); + return KRB5DES_WEAK_KEY; /* XXX error code-weak key */ + + default: + eblock->key = keyblock; + eblock->priv = (krb5_pointer) schedule; + return 0; + } +} diff --git a/src/lib/crypto/des/random_key.c b/src/lib/crypto/des/random_key.c new file mode 100644 index 000000000..5fd407514 --- /dev/null +++ b/src/lib/crypto/des/random_key.c @@ -0,0 +1,50 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + */ + +#if !defined(lint) && !defined(SABER) +static char des_ran_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include + +extern int des_new_random_key(); + +/* + generate a random encryption key, allocating storage for it and + filling in the keyblock address in *keyblock + */ + +krb5_error_code random_key (DECLARG(krb5_pointer, seed), + DECLARG(krb5_keyblock **, keyblock)) +OLDDECLARG(krb5_pointer, seed) +OLDDECLARG(krb5_keyblock **, keyblock) +{ + krb5_keyblock *randkey; + + if (!(randkey = (krb5_keyblock *)malloc(sizeof(*randkey)))) + return ENOMEM; + if (!(randkey->contents = (krb5_octet *)malloc(sizeof(des_cblock)))) { + free((char *)randkey); + return ENOMEM; + } + randkey->length = sizeof(des_cblock); + randkey->keytype = KEYTYPE_DES; + des_new_random_key(randkey->contents, (des_random_key_seed *) seed); + *keyblock = randkey; + return 0; +} diff --git a/src/lib/crypto/des/string2key.c b/src/lib/crypto/des/string2key.c new file mode 100644 index 000000000..729c5d475 --- /dev/null +++ b/src/lib/crypto/des/string2key.c @@ -0,0 +1,167 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Wrapper for the V4 libdes for use with kerberos V5. + */ + +#if !defined(lint) && !defined(SABER) +static char des_st2_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include + +#include + +#include +#include +#include +#include + +#include "des_internal.h" + +#ifdef DEBUG +#include +extern int des_debug; +extern int des_debug_print(); +#endif + +extern void des_fixup_key_parity(); +extern int des_key_sched(); +extern void des_cbc_cksum(); +/* + converts the string pointed to by "data" into an encryption key + of type "keytype". *keyblock is filled in with the key info; + in particular, keyblock->contents is to be set to allocated storage. + It is the responsibility of the caller to release this storage + when the generated key no longer needed. + + The routine may use "princ" to seed or alter the conversion + algorithm. + + If the particular function called does not know how to make a + key of type "keytype", an error may be returned. + + returns: errors + */ + +krb5_error_code string_to_key (DECLARG(krb5_keytype, keytype), + DECLARG(krb5_keyblock *,keyblock), + DECLARG(krb5_data *,data), + DECLARG(krb5_principal, princ)) +OLDDECLARG(krb5_keytype, keytype) +OLDDECLARG(krb5_keyblock *,keyblock) +OLDDECLARG(krb5_data *,data) +OLDDECLARG(krb5_principal, princ) +{ + char copystr[512]; + + register char *str = copystr; + register krb5_octet *key; + + register unsigned temp,i; + register int j; + register long length; + static unsigned char *k_p; + static int forward; + register char *p_char; + static char k_char[64]; + static des_key_schedule key_sked; + +#define min(A, B) ((A) < (B) ? (A): (B)) + +#if defined(lint) || defined(SABER) + princ = princ; +#endif + + if ( keytype != KEYTYPE_DES ) + return (KRB5_PROG_KEYTYPE_NOSUPP); + + if ( !(keyblock->contents = (krb5_octet *)malloc(sizeof(des_cblock))) ) + return(ENOMEM); + +#define cleanup() {memset(keyblock->contents, sizeof(des_cblock), 0);\ + (void) free((char *) keyblock->contents);} + + keyblock->keytype = KEYTYPE_DES; + keyblock->length = sizeof(des_cblock); + key = keyblock->contents; + bzero(copystr, sizeof(copystr)); + (void) strncpy(copystr, data->data, min(data->length,511)); + + /* convert copystr to des key */ + forward = 1; + p_char = k_char; + length = strlen(str); + + /* init key array for bits */ + bzero(k_char,sizeof(k_char)); + +#ifdef DEBUG + if (des_debug) + fprintf(stdout, + "\n\ninput str length = %d string = %s\nstring = 0x ", + length,str); +#endif + + /* get next 8 bytes, strip parity, xor */ + for (i = 1; i <= length; i++) { + /* get next input key byte */ + temp = (unsigned int) *str++; +#ifdef DEBUG + if (des_debug) + fprintf(stdout,"%02x ",temp & 0xff); +#endif + /* loop through bits within byte, ignore parity */ + for (j = 0; j <= 6; j++) { + if (forward) + *p_char++ ^= (int) temp & 01; + else + *--p_char ^= (int) temp & 01; + temp = temp >> 1; + } while (--j > 0); + + /* check and flip direction */ + if ((i%8) == 0) + forward = !forward; + } + + /* now stuff into the key des_cblock, and force odd parity */ + p_char = k_char; + k_p = (unsigned char *) key; + + for (i = 0; i <= 7; i++) { + temp = 0; + for (j = 0; j <= 6; j++) + temp |= *p_char++ << (1+j); + *k_p++ = (unsigned char) temp; + } + + /* fix key parity */ + des_fixup_key_parity(key); + + /* Now one-way encrypt it with the folded key */ + (void) des_key_sched(key, key_sked); + (void) des_cbc_cksum((krb5_octet *)copystr, key, length, key_sked, key); + /* erase key_sked */ + bzero((char *)key_sked, sizeof(key_sked)); + + /* now fix up key parity again */ + des_fixup_key_parity(key); + +#ifdef DEBUG + if (des_debug) + fprintf(stdout, + "\nResulting string_to_key = 0x%x 0x%x\n", + *((unsigned long *) key), + *((unsigned long *) key+1)); +#endif + + return 0; +} diff --git a/src/lib/crypto/des/tables.h b/src/lib/crypto/des/tables.h new file mode 100644 index 000000000..1367338a4 --- /dev/null +++ b/src/lib/crypto/des/tables.h @@ -0,0 +1,109 @@ +/* + * $Source$ + * $Author$ + * $Header$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * part of the Athena Kerberos encryption system + * + * spm 8/85 + */ + +/* + * Initial permutation, adjust to zero based subscript + */ +static char IP[] = { + 58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1, 2-1, + 60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1, 4-1, + 62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1, 6-1, + 64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1, 8-1, + 57-1, 49-1, 41-1, 33-1, 25-1, 17-1, 9-1, 1-1, + 59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1, 3-1, + 61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1, 5-1, + 63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1, 7-1, +}; + +/* + * Final permutation, FP = IP^(-1) adjust to zero based subscript + */ +static char FP[] = { + 40-1, 8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1, + 39-1, 7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1, + 38-1, 6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1, + 37-1, 5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1, + 36-1, 4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1, + 35-1, 3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1, + 34-1, 2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1, + 33-1, 1-1, 41-1, 9-1, 49-1, 17-1, 57-1, 25-1, +}; + +/* the E selection function, adjusted to zero based subscripts */ +static char E[] = { + 32-1, 1-1, 2-1, 3-1, 4-1, 5-1, + 4-1, 5-1, 6-1, 7-1, 8-1, 9-1, + 8-1, 9-1, 10-1, 11-1, 12-1, 13-1, + 12-1, 13-1, 14-1, 15-1, 16-1, 17-1, + 16-1, 17-1, 18-1, 19-1, 20-1, 21-1, + 20-1, 21-1, 22-1, 23-1, 24-1, 25-1, + 24-1, 25-1, 26-1, 27-1, 28-1, 29-1, + 28-1, 29-1, 30-1, 31-1, 32-1, 1-1, +}; + +/* the P permutation, adjusted to zero based subscripts */ +static char P[] = { + 16-1, 7-1, 20-1, 21-1, + 29-1, 12-1, 28-1, 17-1, + 1-1, 15-1, 23-1, 26-1, + 5-1, 18-1, 31-1, 10-1, + 2-1, 8-1, 24-1, 14-1, + 32-1, 27-1, 3-1, 9-1, + 19-1, 13-1, 30-1, 6-1, + 22-1, 11-1, 4-1, 25-1, +}; + +/* S tables, original form */ +static 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, +}; diff --git a/src/lib/crypto/des/verify.c b/src/lib/crypto/des/verify.c new file mode 100644 index 000000000..54ac58e61 --- /dev/null +++ b/src/lib/crypto/des/verify.c @@ -0,0 +1,340 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Program to test the correctness of the DES library + * implementation. + * + * exit returns 0 ==> success + * -1 ==> error + */ + +#ifndef lint +static char rcsid_verify_c[] = +"$Id$"; +#endif /*lint*/ + +#include +#include +#include +#include +#include +#include +#include + +extern void com_err(); +extern int errno; +extern krb5_cryptosystem_entry mit_des_cryptosystem_entry; +extern des_cbc_cksum(); +extern des_ecb_encrypt(); +extern exit(); +char *progname; +int nflag = 2; +int vflag; +int mflag; +int zflag; +int pid; +int des_debug; + +krb5_encrypt_block eblock; +krb5_keyblock keyblock; + +unsigned char cipher_text[64]; +unsigned char clear_text[64] = "Now is the time for all " ; +unsigned char clear_text2[64] = "7654321 Now is the time for "; +unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0}; +unsigned char output[64]; +unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0}; +unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */ +unsigned char *input; + +/* 0x0123456789abcdef */ +unsigned char default_key[8] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef +}; +unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f }; +unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 }; +des_cblock s_key; +unsigned char default_ivec[8] = { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef +}; +unsigned char *ivec; +unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */ +int i,j; +krb5_error_code retval; + +/* + * Can also add : + * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) + */ + +void +main(argc,argv) + int argc; + char *argv[]; +{ + /* Local Declarations */ + long in_length; + void do_encrypt(); + void do_decrypt(); + + progname=argv[0]; /* salt away invoking program */ + + /* Assume a long is four bytes */ + if (sizeof(long) != 4) { + printf("\nERROR, size of long is %d",sizeof(long)); + exit(-1); + } + + while (--argc > 0 && (*++argv)[0] == '-') + for (i=1; argv[0][i] != '\0'; i++) { + switch (argv[0][i]) { + + /* debug flag */ + case 'd': + des_debug=3; + continue; + + case 'z': + zflag = 1; + continue; + + case 'm': + mflag = 1; + continue; + + default: + printf("%s: illegal flag \"%c\" ", + progname,argv[0][i]); + exit(1); + } + }; + + if (argc) { + fprintf(stderr, "Usage: %s [-dmz]\n", progname); + exit(1); + } + + /* do some initialisation */ + initialize_krb5_error_table(); + + eblock.crypto_entry = &mit_des_cryptosystem_entry; + keyblock.keytype = KEYTYPE_DES; + keyblock.length = sizeof (des_cblock); + + /* use known input and key */ + + /* ECB zero text zero key */ + if (zflag) { + input = zero_text; + keyblock.contents = (krb5_octet *)zero_key; + if (retval = (*eblock.crypto_entry->process_key)(&eblock,&keyblock)) { + com_err("des verify", retval, "can't process zero key"); + exit(-1); + } + printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n"); + do_decrypt(output,cipher_text); + if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) { + com_err("des verify", retval, "can't finish zero key"); + exit(-1); + } + exit(0); + } + + if (mflag) { + input = msb_text; + keyblock.contents = (krb5_octet *)key3; + if (retval = (*eblock.crypto_entry->process_key)(&eblock,&keyblock)) { + com_err("des verify", retval, "can't process key3"); + exit(-1); + } + printf("plaintext = 0x00 00 00 00 00 00 00 40, "); + printf("key = 0, cipher = 0x??\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n"); + do_decrypt(output,cipher_text); + if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) { + com_err("des verify", retval, "can't finish key3"); + exit(-1); + } + exit(0); + } + + /* ECB mode Davies and Price */ + { + input = zero_text; + keyblock.contents = (krb5_octet *)key2; + if (retval = (*eblock.crypto_entry->process_key)(&eblock,&keyblock)) { + com_err("des verify", retval, "can't process key2"); + exit(-1); + } + printf("Examples per FIPS publication 81, keys ivs and cipher\n"); + printf("in hex. These are the correct answers, see below for\n"); + printf("the actual answers.\n\n"); + printf("Examples per Davies and Price.\n\n"); + printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n"); + printf("\tclear = 0\n"); + printf("\tcipher = 25 dd ac 3e 96 17 64 67\n"); + printf("ACTUAL ECB\n"); + printf("\tclear \"%s\"\n", input); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + do_decrypt(output,cipher_text); + if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) { + com_err("des verify", retval, "can't finish key2"); + exit(-1); + } + } + + /* ECB mode */ + { + keyblock.contents = (krb5_octet *)default_key; + if (retval = (*eblock.crypto_entry->process_key)(&eblock,&keyblock)) { + com_err("des verify", retval, "can't process key2"); + exit(-1); + } + input = clear_text; + ivec = default_ivec; + printf("EXAMPLE ECB\tkey = 0123456789abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n"); + printf("ACTUAL ECB\n\tclear \"%s\"",input); + do_encrypt(input,cipher_text); + printf("\n\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n\n"); + do_decrypt(output,cipher_text); + } + + /* CBC mode */ + printf("EXAMPLE CBC\tkey = 0123456789abcdef"); + printf("\tiv = 1234567890abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n"); + printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n"); + printf("\t\t\t68 37 88 49 9a 7c 05 f6\n"); + + printf("ACTUAL CBC\n\tclear \"%s\"\n",input); + in_length = strlen(input); + if (retval = + (*eblock.crypto_entry->encrypt_func)((krb5_pointer) input, + (krb5_pointer) cipher_text, + (size_t) in_length, + &eblock, (krb5_pointer) ivec)) { + com_err("des verify", retval, "can't encrypt"); + exit(-1); + } + printf("\tciphertext = (low to high bytes)\n"); + for (i = 0; i <= 7; i++) { + printf("\t\t"); + for (j = 0; j <= 7; j++) { + printf("%02x ",cipher_text[i*8+j]); + } + printf("\n"); + } + if (retval = + (*eblock.crypto_entry->decrypt_func)((krb5_pointer) cipher_text, + (krb5_pointer) clear_text, + (size_t) in_length, + &eblock, (krb5_pointer) ivec)) { + com_err("des verify", retval, "can't decrypt"); + exit(-1); + } + printf("\tdecrypted clear_text = \"%s\"\n",clear_text); + + printf("EXAMPLE CBC checksum"); + printf("\tkey = 0123456789abcdef\tiv = 1234567890abcdef\n"); + printf("\tclear =\t\t\"7654321 Now is the time for \"\n"); + printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, "); + printf("or some part thereof\n"); + input = clear_text2; + des_cbc_cksum(input,cipher_text,(long) strlen(input),eblock.priv,ivec,1); + printf("ACTUAL CBC checksum\n"); + printf("\t\tencrypted cksum = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) { + com_err("des verify", retval, "can't finish key2"); + exit(-1); + } + exit(0); +} + +void +flip(array) + char *array; +{ + register old,new,i,j; + /* flips the bit order within each byte from 0 lsb to 0 msb */ + for (i = 0; i<=7; i++) { + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + if (old & 01) + new = new | 01; + if (j < 7) { + old = old >> 1; + new = new << 1; + } + } + *array = new; + array++; + } +} + +void +do_encrypt(in,out) + char *in; + char *out; +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(in,out,(struct des_ks_struct *)eblock.priv,1); + if (des_debug) { + printf("\nclear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02 X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +void +do_decrypt(in,out) + char *out; + char *in; + /* try to invert it */ +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(out,in,(struct des_ks_struct *)eblock.priv,0); + if (des_debug) { + printf("clear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} diff --git a/src/lib/crypto/des/weak_key.c b/src/lib/crypto/des/weak_key.c new file mode 100644 index 000000000..ffb9c64e4 --- /dev/null +++ b/src/lib/crypto/des/weak_key.c @@ -0,0 +1,76 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + */ + +#if !defined(lint) && !defined(SABER) +static char weak_key_c[] = +"$Header$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include "des_internal.h" + +/* + * The following are the weak DES keys: + */ +static des_cblock weak[16] = { + /* 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} +}; + +/* + * des_is_weak_key: returns true iff key is a [semi-]weak des key. + * + * Requires: key has correct odd parity. + */ +int +des_is_weak_key(key) + des_cblock key; +{ + int i; + des_cblock *weak_p = weak; + + for (i = 0; i < (sizeof(weak)/sizeof(des_cblock)); i++) { + if (!bcmp((char *)weak_p++,(char *)key,sizeof(des_cblock))) + return 1; + } + + return 0; +} -- 2.26.2