From 0d617fc8545f08c44c2a6aef482097fc7287a65f Mon Sep 17 00:00:00 2001 From: John Kohl Date: Thu, 14 Mar 1991 10:00:20 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1890 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/des425/cksum.c | 56 +++++++ src/lib/des425/des.c | 56 +++++++ src/lib/des425/des.h | 41 +++++ src/lib/des425/enc_dec.c | 63 ++++++++ src/lib/des425/key_parity.c | 51 +++++++ src/lib/des425/key_sched.c | 53 +++++++ src/lib/des425/new_rnd_key.c | 129 ++++++++++++++++ src/lib/des425/pcbc_encrypt.c | 252 +++++++++++++++++++++++++++++++ src/lib/des425/quad_cksum.c | 216 ++++++++++++++++++++++++++ src/lib/des425/random_key.c | 31 ++++ src/lib/des425/str_to_key.c | 131 ++++++++++++++++ src/lib/des425/string2key.c | 166 ++++++++++++++++++++ src/lib/des425/verify.c | 275 ++++++++++++++++++++++++++++++++++ src/lib/des425/weak_key.c | 37 +++++ 14 files changed, 1557 insertions(+) create mode 100644 src/lib/des425/cksum.c create mode 100644 src/lib/des425/des.c create mode 100644 src/lib/des425/des.h create mode 100644 src/lib/des425/enc_dec.c create mode 100644 src/lib/des425/key_parity.c create mode 100644 src/lib/des425/key_sched.c create mode 100644 src/lib/des425/new_rnd_key.c create mode 100644 src/lib/des425/pcbc_encrypt.c create mode 100644 src/lib/des425/quad_cksum.c create mode 100644 src/lib/des425/random_key.c create mode 100644 src/lib/des425/str_to_key.c create mode 100644 src/lib/des425/string2key.c create mode 100644 src/lib/des425/verify.c create mode 100644 src/lib/des425/weak_key.c diff --git a/src/lib/des425/cksum.c b/src/lib/des425/cksum.c new file mode 100644 index 000000000..4791236a3 --- /dev/null +++ b/src/lib/des425/cksum.c @@ -0,0 +1,56 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * 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 "des.h" +#include + +/* + * 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 */ + mit_des_key_schedule key; /* precomputed key schedule */ + krb5_octet *iv; /* 8 bytes of ivec */ +{ + mit_des_cbc_cksum(in, out, length, key, iv); +} diff --git a/src/lib/des425/des.c b/src/lib/des425/des.c new file mode 100644 index 000000000..5c1dfd5a4 --- /dev/null +++ b/src/lib/des425/des.c @@ -0,0 +1,56 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * 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[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include "des.h" +#include + +int +des_ecb_encrypt(clear, cipher, schedule, encrypt) + unsigned long *clear; + unsigned long *cipher; + int encrypt; /* 0 ==> decrypt, else encrypt */ + register mit_des_key_schedule schedule; /* r11 */ +{ + return (mit_des_ecb_encrypt(clear, cipher, schedule, encrypt)); +} + + diff --git a/src/lib/des425/des.h b/src/lib/des425/des.h new file mode 100644 index 000000000..2c00b6200 --- /dev/null +++ b/src/lib/des425/des.h @@ -0,0 +1,41 @@ +/* + * Include file for the Data Encryption Standard library. + */ + +/* only do the whole thing once */ +#ifndef DES_DEFS +#define DES_DEFS + +#include +#include + +typedef mit_des_cblock des_cblock; /* crypto-block size */ + +/* Key schedule */ +typedef mit_des_key_schedule des_key_schedule; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#ifndef NCOMPAT +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define key_sched des_key_sched +#define cbc_encrypt des_cbc_encrypt +#define cbc_cksum des_cbc_cksum +#define C_Block_print des_cblock_print +#define quad_cksum des_quad_cksum +typedef struct des_ks_struct bit_64; +#endif + +#define des_cblock_print(x) des_cblock_print_file(x, stdout) + +#endif /* DES_DEFS */ diff --git a/src/lib/des425/enc_dec.c b/src/lib/des425/enc_dec.c new file mode 100644 index 000000000..ae271ad68 --- /dev/null +++ b/src/lib/des425/enc_dec.c @@ -0,0 +1,63 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * 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 rcsid_enc_dec_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include "des.h" +#include + +/* + * 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. + */ + +int +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 */ + mit_des_key_schedule key; /* precomputed key schedule */ + krb5_octet *iv; /* 8 bytes of ivec */ + int encrypt; /* 0 ==> decrypt, else encrypt */ +{ + return(mit_des_cbc_encrypt(in,out,length,key,iv,encrypt)); +} + diff --git a/src/lib/des425/key_parity.c b/src/lib/des425/key_parity.c new file mode 100644 index 000000000..42420a641 --- /dev/null +++ b/src/lib/des425/key_parity.c @@ -0,0 +1,51 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1989, 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * 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 rcsid_key_parity_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include "des.h" + +/* + * des_fixup_key_parity: Forces odd parity per byte; parity is bits + * 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order. + */ +void +des_fixup_key_parity(key) + register mit_des_cblock key; +{ + mit_des_fixup_key_parity(key); +} + +/* + * des_check_key_parity: returns true iff key has the correct des parity. + * See des_fix_key_parity for the definition of + * correct des parity. + */ +int +des_check_key_parity(key) + register mit_des_cblock key; +{ + return(mit_des_check_key_parity(key)); +} + diff --git a/src/lib/des425/key_sched.c b/src/lib/des425/key_sched.c new file mode 100644 index 000000000..33a6fab71 --- /dev/null +++ b/src/lib/des425/key_sched.c @@ -0,0 +1,53 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * 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 rcsid_key_sched_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include "des.h" + +typedef char key[64]; + +/* the following are really void but cc86 doesnt allow it */ +static void make_key_sched PROTOTYPE((key, mit_des_key_schedule)); + +int +des_key_sched(k,schedule) + register mit_des_cblock k; /* r11 */ + mit_des_key_schedule schedule; +{ + return (mit_des_key_sched(k, schedule)); +} diff --git a/src/lib/des425/new_rnd_key.c b/src/lib/des425/new_rnd_key.c new file mode 100644 index 000000000..3b8519420 --- /dev/null +++ b/src/lib/des425/new_rnd_key.c @@ -0,0 +1,129 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988,1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + */ + +#ifndef lint +static char rcsid_new_rnd_key_c[] = +"$Id$"; +#endif /* lint */ + +#include "des.h" + +extern void mit_des_fixup_key_parity(); +extern int mit_des_is_weak_key(); +extern int mit_des_init_random_number_generator(); +extern void mit_des_set_random_generator_seed(); +extern void mit_des_set_sequence_number(); +extern void mit_des_generate_random_block(); +extern int mit_des_new_random_key(); +extern void mit_des_generate_random_block(); + + +void des_set_random_generator_seed(), des_set_sequence_number(); +void des_generate_random_block(); + +/* + * The secret des key schedule and sequence number for the current + * stream of random numbers + */ +static mit_des_random_key_seed random_sequence_state; + +/* + * 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) + mit_des_cblock key; +{ + return(mit_des_new_random_key(key, &random_sequence_state)); +} + +/* + * 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. + */ +void des_init_random_number_generator(key) + mit_des_cblock key; +{ + mit_des_init_random_number_generator(key, &random_sequence_state); +} + +/* + * 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) + mit_des_cblock key; +{ + mit_des_set_random_generator_seed(key, &random_sequence_state); +} + + +/* + * 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) + mit_des_cblock new_sequence_number; +{ + mit_des_set_sequence_number(new_sequence_number, &random_sequence_state); +} + +/* + * 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) + mit_des_cblock block; +{ + mit_des_generate_random_block(block, &random_sequence_state); +} + diff --git a/src/lib/des425/pcbc_encrypt.c b/src/lib/des425/pcbc_encrypt.c new file mode 100644 index 000000000..c382f20ca --- /dev/null +++ b/src/lib/des425/pcbc_encrypt.c @@ -0,0 +1,252 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988,1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * 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. The cleartext and ciphertext should be in host order. + * + * These routines form the library interface to the des facilities. + * + * spm 8/85 MIT project athena + */ + +#ifndef lint +static char rcsid_pcbc_encrypt_c[] = +"$Id$"; +#endif /* lint */ + +#include +#include "des.h" + +extern int mit_des_debug; +extern int mit_des_debug_print(); + +/* + * pcbc_encrypt is an "error propagation chaining" encrypt operation + * for DES, similar to CBC, but that, on encryption, "xor"s the + * plaintext of block N with the ciphertext resulting from block N, + * then "xor"s that result with the plaintext of block N+1 prior to + * encrypting block N+1. (decryption the appropriate inverse. This + * "pcbc" mode propagates a single bit error anywhere in either the + * cleartext or ciphertext chain all the way through to the end. In + * contrast, CBC mode limits a single bit error in the ciphertext to + * affect only the current (8byte) block and the subsequent block. + * + * performs pcbc error-propagation chaining operation by xor-ing block + * N+1 with both the plaintext (block N) and the ciphertext from block + * N. Either encrypts from cleartext to ciphertext, if encrypt != 0 + * or decrypts from ciphertext to cleartext, if encrypt == 0 + * + * 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. + * + * This is NOT a standard mode of operation. + * + */ + +int +des_pcbc_encrypt(in,out,length,key,iv,encrypt) + mit_des_cblock *in; /* >= length bytes of inputtext */ + mit_des_cblock *out; /* >= length bytes of outputtext */ + register long length; /* in bytes */ + int encrypt; /* 0 ==> decrypt, else encrypt */ + des_key_schedule key; /* precomputed key schedule */ + mit_des_cblock *iv; /* 8 bytes of ivec */ +{ + 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 *)&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+1),(char *)&t_input[1],sizeof(t_input[1])); + } + else +#endif + { + t_input[0] = *input; + t_input[1] = *(input+1); + } + + /* zero pad */ + if (length < 8) { + for (j = length; j <= 7; j++) + *(t_in_p+j)= 0; + } + +#ifdef DEBUG + if (mit_des_debug) + mit_des_debug_print("clear",length,t_input[0],t_input[1]); +#endif + /* do the xor for cbc into the temp */ + t_input[0] ^= xor_0 ; + t_input[1] ^= xor_1 ; + /* encrypt */ + (void) des_ecb_encrypt(t_input,t_output,key,encrypt); + + /* + * We want to XOR with both the plaintext and ciphertext + * of the previous block, before we write the output, in + * case both input and output are the same space. + */ +#ifdef MUSTALIGN + if ((long) input & 3) { + bcopy((char *)input++,(char *)&xor_0,sizeof(xor_0)); + xor_0 ^= t_output[0]; + bcopy((char *)input++,(char *)&xor_1,sizeof(xor_1)); + xor_1 ^= t_output[1]; + } + else +#endif + { + xor_0 = *input++ ^ t_output[0]; + xor_1 = *input++ ^ t_output[1]; + } + + + /* 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 (mit_des_debug) { + mit_des_debug_print("xor'ed",i,t_input[0],t_input[1]); + mit_des_debug_print("cipher",i,t_output[0],t_output[1]); + } +#endif + } + t_output[0] = 0; + t_output[1] = 0; + xor_0 = 0; + xor_1 = 0; + 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[1])); + } + else +#endif + { + t_input[0] = *input++; + t_input[1] = *input++; + } + + /* no padding for decrypt */ +#ifdef DEBUG + if (mit_des_debug) + mit_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 (mit_des_debug) + mit_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_output[0] ^ t_input[0]; + xor_1 = t_output[1] ^ t_input[1]; + +#ifdef DEBUG + if (mit_des_debug) + mit_des_debug_print("clear",i,t_output[0],t_output[1]); +#endif + } + return 0; + } +} diff --git a/src/lib/des425/quad_cksum.c b/src/lib/des425/quad_cksum.c new file mode 100644 index 000000000..896a9680f --- /dev/null +++ b/src/lib/des425/quad_cksum.c @@ -0,0 +1,216 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988,1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * Quadratic Congruential Manipulation Dectection Code + * + * ref: "Message Authentication" + * R.R. Jueneman, S. M. Matyas, C.H. Meyer + * IEEE Communications Magazine, + * Sept 1985 Vol 23 No 9 p 29-40 + * + * This routine, part of the Athena DES library built for the Kerberos + * authentication system, calculates a manipulation detection code for + * a message. It is a much faster alternative to the DES-checksum + * method. No guarantees are offered for its security. Refer to the + * paper noted above for more information + * + * Implementation for 4.2bsd + * by S.P. Miller Project Athena/MIT + */ + +/* + * Algorithm (per paper): + * define: + * message to be composed of n m-bit blocks X1,...,Xn + * optional secret seed S in block X1 + * MDC in block Xn+1 + * prime modulus N + * accumulator Z + * initial (secret) value of accumulator C + * N, C, and S are known at both ends + * C and , optionally, S, are hidden from the end users + * then + * (read array references as subscripts over time) + * Z[0] = c; + * for i = 1...n + * Z[i] = (Z[i+1] + X[i])**2 modulo N + * X[n+1] = Z[n] = MDC + * + * Then pick + * N = 2**31 -1 + * m = 16 + * iterate 4 times over plaintext, also use Zn + * from iteration j as seed for iteration j+1, + * total MDC is then a 128 bit array of the four + * Zn; + * + * return the last Zn and optionally, all + * four as output args. + * + * Modifications: + * To inhibit brute force searches of the seed space, this + * implementation is modified to have + * Z = 64 bit accumulator + * C = 64 bit C seed + * N = 2**63 - 1 + * S = S seed is not implemented here + * arithmetic is not quite real double integer precision, since we + * cant get at the carry or high order results from multiply, + * but nontheless is 64 bit arithmetic. + */ + +#ifndef lint +static char rcsid_quad_cksum_c[] = +"$Id$"; +#endif /* lint */ + +/* System include files */ +#include +#include + +/* Application include files */ +#include +#include +#include "des.h" +/* Definitions for byte swapping */ + +#ifdef LSBFIRST +#ifdef MUSTALIGN +static unsigned long vaxtohl(); +static unsigned short vaxtohs(); +#else /* ! MUSTALIGN */ +#define vaxtohl(x) *((unsigned long *)(x)) +#define vaxtohs(x) *((unsigned short *)(x)) +#endif /* MUSTALIGN */ +#else /* !LSBFIRST */ +static unsigned long four_bytes_vax_to_nets(); +#define vaxtohl(x) four_bytes_vax_to_nets((char *)(x)) +static unsigned short two_bytes_vax_to_nets(); +#define vaxtohs(x) two_bytes_vax_to_nets((char *)(x)) +#endif + +/* Externals */ +extern char *errmsg(); +extern int errno; +extern int des_debug; + +/*** Routines ***************************************************** */ + +unsigned long +des_quad_cksum(in,out,length,out_count,c_seed) + mit_des_cblock *c_seed; /* secret seed, 8 bytes */ + unsigned char *in; /* input block */ + unsigned long *out; /* optional longer output */ + int out_count; /* number of iterations */ + long length; /* original length in bytes */ +{ + + /* + * this routine both returns the low order of the final (last in + * time) 32bits of the checksum, and if "out" is not a null + * pointer, a longer version, up to entire 32 bytes of the + * checksum is written unto the address pointed to. + */ + + register unsigned long z; + register unsigned long z2; + register unsigned long x; + register unsigned long x2; + register unsigned char *p; + register long len; + register int i; + + /* use all 8 bytes of seed */ + + z = vaxtohl(c_seed); + z2 = vaxtohl((char *)c_seed+4); + if (out == NULL) + out_count = 1; /* default */ + + /* This is repeated n times!! */ + for (i = 1; i <=4 && i<= out_count; i++) { + len = length; + p = in; + while (len) { + if (len > 1) { + x = (z + vaxtohs(p)); + p += 2; + len -= 2; + } + else { + x = (z + *(unsigned char *)p++); + len = 0; + } + x2 = z2; + z = ((x * x) + (x2 * x2)) % 0x7fffffff; + z2 = (x * (x2+83653421)) % 0x7fffffff; /* modulo */ + if (des_debug & 8) + printf("%d %d\n",z,z2); + } + + if (out != NULL) { + *out++ = z; + *out++ = z2; + } + } + /* return final z value as 32 bit version of checksum */ + return z; +} +#ifdef MSBFIRST + +static unsigned short two_bytes_vax_to_nets(p) + char *p; +{ + union { + char pieces[2]; + unsigned short result; + } short_conv; + + short_conv.pieces[0] = p[1]; + short_conv.pieces[1] = p[0]; + return(short_conv.result); +} + +static unsigned long four_bytes_vax_to_nets(p) + char *p; +{ + static union { + char pieces[4]; + unsigned long result; + } long_conv; + + long_conv.pieces[0] = p[3]; + long_conv.pieces[1] = p[2]; + long_conv.pieces[2] = p[1]; + long_conv.pieces[3] = p[0]; + return(long_conv.result); +} + +#endif +#ifdef LSBFIRST +#ifdef MUSTALIGN +static unsigned long vaxtohl(x) +char *x; +{ + unsigned long val; + bcopy(x, (char *)&val, sizeof(val)); + return(val); +} + +static unsigned short vaxtohs(x) +char *x; +{ + unsigned short val; + bcopy(x, (char *)&val, sizeof(val)); + return(val); +} +#endif /* MUSTALIGN */ +#endif /* LSBFIRST */ diff --git a/src/lib/des425/random_key.c b/src/lib/des425/random_key.c new file mode 100644 index 000000000..d710b176a --- /dev/null +++ b/src/lib/des425/random_key.c @@ -0,0 +1,31 @@ +/* + * $Source$ + * $Author$ + */ + +#ifndef lint +static char rcsid_random_key_c[] = +"$Header$"; +#endif /* lint */ + +#include "des.h" + +/* random_key */ +int +des_random_key(key) + mit_des_cblock *key; +{ + mit_des_random_key_seed p_seed; + mit_des_cblock nullkey; + + bzero(nullkey, sizeof(mit_des_cblock)); + mit_des_fixup_key_parity(key); + mit_des_init_random_number_generator(nullkey,&p_seed); + do { + mit_des_generate_random_block(key, &p_seed); + mit_des_fixup_key_parity(key); + } while (mit_des_is_weak_key(key)); + + return(0); +} + diff --git a/src/lib/des425/str_to_key.c b/src/lib/des425/str_to_key.c new file mode 100644 index 000000000..71bfe8315 --- /dev/null +++ b/src/lib/des425/str_to_key.c @@ -0,0 +1,131 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988, 1989,1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * 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. The cleartext and ciphertext should be in host order. + * + * These routines form the library interface to the DES facilities. + * + * spm 8/85 MIT project athena + */ + +#ifndef lint +static char rcsid_string_to_key_c[] = +"$Id$"; +#endif /* lint */ + +#include +#include +#include "des.h" +/* #include "des_internal.h" */ + +extern int mit_des_debug; +extern int mit_des_debug_print(); +extern void mit_des_fixup_key_parity(); + +/* + * convert an arbitrary length string to a DES key + */ +int +des_string_to_key(str,key) + char *str; + register mit_des_cblock *key; +{ + register char *in_str; + 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 mit_des_key_schedule key_sked; + extern unsigned long des_cbc_cksum(); + + in_str = str; + forward = 1; + p_char = k_char; + length = strlen(str); + + /* init key array for bits */ + bzero(k_char,sizeof(k_char)); + +#ifdef DEBUG + if (mit_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 (mit_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((des_cblock *)in_str,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 (mit_des_debug) + fprintf(stdout, + "\nResulting string_to_key = 0x%x 0x%x\n", + *((unsigned long *) key), + *((unsigned long *) key+1)); +#endif /* DEBUG */ + return 0; /* Really should be returning void, */ + /* but the original spec was for it to */ + /* return an int, and ANSI compilers */ + /* can do dumb things sometimes */ +} diff --git a/src/lib/des425/string2key.c b/src/lib/des425/string2key.c new file mode 100644 index 000000000..d6a1598a1 --- /dev/null +++ b/src/lib/des425/string2key.c @@ -0,0 +1,166 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * 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 rcsid_string2key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include "des.h" +#include + +#include "des_int.h" + +#ifdef DEBUG +#include +extern int des_debug; +#endif + +/* + 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 mit_des_string_to_key (DECLARG(const krb5_keytype, keytype), + DECLARG(krb5_keyblock *,keyblock), + DECLARG(const krb5_data *,data), + DECLARG(krb5_const_principal, princ)) +OLDDECLARG(const krb5_keytype, keytype) +OLDDECLARG(krb5_keyblock *,keyblock) +OLDDECLARG(const krb5_data *,data) +OLDDECLARG(krb5_const_principal, princ) +{ + char copystr[512]; + + register char *str = copystr; + register krb5_octet *key; + + register unsigned temp,i; + register int j; + register long length; + unsigned char *k_p; + int forward; + register char *p_char; + char k_char[64]; + mit_des_key_schedule key_sked; + +#define min(A, B) ((A) < (B) ? (A): (B)) + + if ( keytype != KEYTYPE_DES ) + return (KRB5_PROG_KEYTYPE_NOSUPP); + + if ( !(keyblock->contents = (krb5_octet *)malloc(sizeof(mit_des_cblock))) ) + return(ENOMEM); + +#define cleanup() {memset(keyblock->contents, 0, sizeof(mit_des_cblock));\ + xfree(keyblock->contents);} + + keyblock->keytype = KEYTYPE_DES; + keyblock->length = sizeof(mit_des_cblock); + key = keyblock->contents; + + memset(copystr, 0, sizeof(copystr)); + j = min(data->length, 511); + (void) strncpy(copystr, data->data, j); + if ( princ != 0 ) + for (i=0; princ[i] != 0 && j < 511; i++) { + (void) strncpy(copystr+j, princ[i]->data, + min(princ[i]->length, 511-j)); + j += min(princ[i]->length, 511-j); + } + + /* convert copystr to des key */ + forward = 1; + p_char = k_char; + length = strlen(str); + + /* init key array for bits */ + memset(k_char,0,sizeof(k_char)); + +#ifdef DEBUG + if (mit_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 (mit_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; + } + + /* check and flip direction */ + if ((i%8) == 0) + forward = !forward; + } + + /* now stuff into the key mit_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 */ + mit_des_fixup_key_parity(key); + + /* Now one-way encrypt it with the folded key */ + (void) mit_des_key_sched(key, key_sked); + (void) mit_des_cbc_cksum((krb5_octet *)copystr, key, length, key_sked, key); + /* erase key_sked */ + memset((char *)key_sked, 0, sizeof(key_sked)); + + /* now fix up key parity again */ + mit_des_fixup_key_parity(key); + +#ifdef DEBUG + if (mit_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/des425/verify.c b/src/lib/des425/verify.c new file mode 100644 index 000000000..f1b910c50 --- /dev/null +++ b/src/lib/des425/verify.c @@ -0,0 +1,275 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988,1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * 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 "./des.h" + +extern char *errmsg(); +extern int errno; +extern int des_string_to_key(); +extern int des_key_sched(); +extern int des_ecb_encrypt(); +extern int des_cbc_encrypt(); +extern exit(); +char *progname; +int nflag = 2; +int vflag; +int mflag; +int zflag; +int pid; +int des_debug; +des_key_schedule KS; +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; + +/* + * Can also add : + * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) + */ + +main(argc,argv) + int argc; + char *argv[]; +{ + /* Local Declarations */ + long in_length; + + 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); + } + + /* use known input and key */ + + /* ECB zero text zero key */ + if (zflag) { + input = zero_text; + des_key_sched(zero_key,KS); + 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); + return(0); + } + + if (mflag) { + input = msb_text; + des_key_sched(key3,KS); + 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); + return(0); + } + + /* ECB mode Davies and Price */ + { + input = zero_text; + des_key_sched(key2,KS); + 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); + } + + /* ECB mode */ + { + des_key_sched(default_key,KS); + 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); + des_cbc_encrypt(input,cipher_text,(long) in_length,KS,ivec,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"); + } + des_cbc_encrypt(cipher_text,clear_text,(long) in_length,KS,ivec,0); + 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),KS,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"); + exit(0); +} + +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++; + } +} + +do_encrypt(in,out) + char *in; + char *out; +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(in,out,KS,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); + } + } +} + +do_decrypt(in,out) + char *out; + char *in; + /* try to invert it */ +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(out,in,KS,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/des425/weak_key.c b/src/lib/des425/weak_key.c new file mode 100644 index 000000000..74b0fc883 --- /dev/null +++ b/src/lib/des425/weak_key.c @@ -0,0 +1,37 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1989,1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * 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 rcsid_weak_key_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include "des.h" +#include + +/* + * mit_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) + mit_des_cblock key; +{ + return (mit_des_is_weak_key(key)); +} -- 2.26.2