[1093] in Kerberos_V5_Development

home help back first fref pref prev next nref lref last post

Common random routines: for review

daemon@ATHENA.MIT.EDU (Richard Basch)
Thu May 2 19:20:24 1996

Date: Thu, 2 May 1996 19:19:18 -0400
To: krbdev@MIT.EDU
From: "Richard Basch" <basch@lehman.com>

The following patches don't fully indicate what I have done:
1. A new file, lib/crypto/u_rn_key.c was added.
2. lib/crypto/{d3_rndky.c,new_rn_key.c} were removed.

The patches also do not reflect the change in the API suggesting that we
change one parameter from a krb5_keyblock* to a krb5_data*.  This
version keeps API compatibility, but does do the n-fold operations, of
the key contents and ignores the key's enctype, altogether.

However, those will be relatively straight-forward compared to these,
and I am still awaiting responses regarding that API change...

The algorithms from the original routines were preserved, just extended
for the integration of des and 3des into a single set of routines.  The
3des random number generator previously there was merely a placeholder
that yielded random keys that were only as strong as des.

This should be integrated into the sources before beta 6 because of the
weak 3des case.  I just want to put this out there for a perusal, though
I am fairly confident in the implementation.  I do not particularly care
for the libdes425 case, where there is one memory block that will never
be freed, but it will not leak...  However, another set of eyes couldn't
hurt...

After this, I need to:
- cleanup the kdc/kdb5_edit/kdb5_create/*admin* routines that actually
	use the random number initialization routines to provide better seeds.
- fix the API to use krb5_data* instead of krb5_keyblock* if agreed upon.

Richard Basch                   
Sr. Developer/Analyst           URL: http://web.mit.edu/basch/www/home.html
Lehman Brothers, Inc.           Email: basch@lehman.com, basch@mit.edu
101 Hudson St., 33rd Floor      Fax:   +1-201-524-5828
Jersey City, NJ 07302-3988      Voice: +1-201-524-5049


--- 1.1	1996/05/02 22:48:28
+++ src/lib/crypto/ChangeLog	1996/05/02 22:50:10
@@ -1,3 +1,8 @@
+Thu May  2 18:48:35 1996  Richard Basch  <basch@lehman.com>
+
+	* des3_md5.c des3_raw.c: use the new common random routines for
+		des & des3 (the old des3 routines have been removed)
+
 Sat Mar 30 22:52:46 1996  Theodore Y. Ts'o  <tytso@dcl>
 
 	* cryptoconf.c: Fixed comments describing the various checksum
--- 1.1	1996/04/30 23:26:05
+++ src/lib/crypto/des3_md5.c	1996/04/30 23:26:38
@@ -44,7 +44,7 @@
     mit_des3_string_to_key,
     mit_des_init_random_key,
     mit_des_finish_random_key,
-    mit_des3_random_key,
+    mit_des_random_key,
     sizeof(mit_des_cblock),
     RSA_MD5_CKSUM_LENGTH+sizeof(mit_des_cblock),
     sizeof(mit_des3_cblock),
--- 1.1	1996/04/30 23:26:35
+++ src/lib/crypto/des3_raw.c	1996/04/30 23:26:38
@@ -41,7 +41,7 @@
     mit_des3_string_to_key,
     mit_des_init_random_key,
     mit_des_finish_random_key,
-    mit_des3_random_key,
+    mit_des_random_key,
     sizeof(mit_des_cblock),
     0,
     sizeof(mit_des3_cblock),
--- 1.1	1996/04/29 18:08:18
+++ src/lib/crypto/des/ChangeLog	1996/05/02 22:41:50
@@ -1,3 +1,28 @@
+Thu May  2 18:29:01 1996  Richard Basch  <basch@lehman.com>
+
+	* d3_rndky.c new_rn_key.c: Removed (obsolete).
+
+	* u_rn_key.c: New file
+		Support routines to set the seed/sequence number of the
+		random stream.
+
+	* Makefile.in: new/removed file changes
+
+	* des_int.h: Changed prototypes for all the random routines.
+
+	* fin_rndkey.c: rewrote mit_des_finish_random_key to use the new
+		random state structure and to accept an eblock as arg 1.
+
+	* init_rkey.c: rewritten to be a common DES, 3-DES random stream
+		initialization routine.  it uses the eblock to determine
+		the random key type to generate.
+		
+	* random_key.c: rewritten to be a common DES, 3-DES random stream
+		generator, using the former DES algorithm (encrypting an
+		incrementing sequence number with a unique key schedule)
+		[3-DES uses DES3-CBC-CRC to increment a 192 bit sequence
+		number, instead of being only as secure as DES.]
+
 Wed Apr 10 17:46:40 1996  Theodore Y. Ts'o  <tytso@dcl>
 
 	* Makefile.in (SRCS,OBJS): Added afsstring2key.c to the list of
--- 1.1	1996/04/30 20:05:52
+++ src/lib/crypto/des/des_int.h	1996/05/02 22:15:27
@@ -57,9 +57,9 @@
 #define MIT_DES_DECRYPT	0
 
 typedef struct mit_des_ran_key_seed {
-    krb5_octet sequence_number[8];
-    mit_des_key_schedule random_sequence_key;
-} mit_des_random_key_seed;
+    krb5_encrypt_block eblock;
+    krb5_data sequence;
+} mit_des_random_state;
 
 /* the first byte of the key is already in the keyblock */
 
@@ -118,7 +118,8 @@
     
 /* fin_rndkey.c */
 extern krb5_error_code mit_des_finish_random_key
-    PROTOTYPE(( krb5_pointer FAR *));
+    PROTOTYPE(( const krb5_encrypt_block FAR *,
+		krb5_pointer FAR *));
 
 /* finish_key.c */
 extern krb5_error_code mit_des_finish_key
@@ -126,7 +127,9 @@
 
 /* init_rkey.c */
 extern krb5_error_code mit_des_init_random_key
-    PROTOTYPE(( const krb5_keyblock FAR *,  krb5_pointer FAR *));
+    PROTOTYPE(( const krb5_encrypt_block FAR *,
+		const krb5_keyblock FAR *,
+		krb5_pointer FAR *));
 
 /* key_parity.c */
 extern void mit_des_fixup_key_parity PROTOTYPE((mit_des_cblock ));
@@ -136,18 +139,6 @@
 extern int mit_des_key_sched
     PROTOTYPE((mit_des_cblock , mit_des_key_schedule ));
 
-/* new_rnd_key.c */
-extern int mit_des_new_random_key
-    PROTOTYPE((mit_des_cblock , mit_des_random_key_seed FAR *));
-extern void mit_des_init_random_number_generator
-    PROTOTYPE((mit_des_cblock, mit_des_random_key_seed FAR *));
-extern void mit_des_set_random_generator_seed
-    PROTOTYPE((mit_des_cblock , mit_des_random_key_seed FAR *));
-extern void mit_des_set_sequence_number
-    PROTOTYPE((mit_des_cblock , mit_des_random_key_seed FAR *));
-extern void mit_des_generate_random_block
-    PROTOTYPE((mit_des_cblock , mit_des_random_key_seed FAR *));
-
 /* process_ky.c */
 extern krb5_error_code mit_des_process_key
     PROTOTYPE(( krb5_encrypt_block FAR *,  const krb5_keyblock FAR *));
@@ -218,12 +209,6 @@
 	PROTOTYPE((krb5_encrypt_block * eblock,
 		   const krb5_keyblock * keyblock));
 
-/* d3_rndkey.c */
-extern krb5_error_code mit_des3_random_key
-	PROTOTYPE((const krb5_encrypt_block * eblock,
-		   krb5_pointer seed,
-		   krb5_keyblock ** keyblock));
-
 /* d3_kysched.c */
 extern int mit_des3_key_sched
 	PROTOTYPE((mit_des3_cblock key,
@@ -242,5 +227,14 @@
 		   const size_t in_len,
 		   krb5_octet * output,
 		   const size_t out_len));
+
+/* u_rn_key.c */
+extern krb5_error_code mit_des_set_random_generator_seed
+	PROTOTYPE((const krb5_data * seed,
+		   krb5_pointer random_state));
+
+extern krb5_error_code mit_des_set_random_sequence_number
+	PROTOTYPE((const krb5_data * sequence,
+		   krb5_pointer random_state));
 
 #endif	/*DES_INTERNAL_DEFS*/
--- 1.1	1996/05/02 22:47:05
+++ src/lib/crypto/des/u_rn_key.c	1996/05/02 22:25:16
@@ -0,0 +1,138 @@
+/*
+ * Copyright 1996 by Richard P. Basch.  All Rights Reserved.
+ * Copyright 1996 by Lehman Brothers, Inc.  All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  Richard P. Basch,
+ * Lehman Brothers and M.I.T. make no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
+ *
+ *
+ * Based on the version 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.
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+
+int
+mit_des_is_weak_keyblock(keyblock)
+    krb5_keyblock * keyblock;
+{
+    int i;
+    
+    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
+	if (mit_des_is_weak_key(*((mit_des_cblock *)keyblock->contents + i)))
+	    return 1;
+    return 0;
+}
+
+void
+mit_des_fixup_keyblock_parity(keyblock)
+    krb5_keyblock * keyblock;
+{
+    int i;
+    
+    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
+	mit_des_fixup_key_parity(*((mit_des_cblock *)keyblock->contents + i));
+}
+
+/*
+ * mit_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)
+ */
+krb5_error_code
+mit_des_set_random_generator_seed(seed, p_state)
+    const krb5_data * seed;
+    krb5_pointer p_state;
+{
+    krb5_error_code kret;
+    register int i;
+    mit_des_cblock *new_key;
+    mit_des_random_state *state = p_state;
+
+    if (state->eblock.key) {
+	if (state->eblock.key->contents) {
+	    memset(state->eblock.key->contents, 0, state->eblock.key->length);
+	    krb5_xfree(state->eblock.key->contents);
+	}
+    }
+
+    state->eblock.key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock));
+    if (! state->eblock.key)
+	return ENOMEM;
+
+    state->eblock.key->length = state->eblock.crypto_entry->keysize;
+    state->eblock.key->contents = (krb5_octet *)malloc(state->eblock.key->length);
+    if (! state->eblock.key->contents) {
+	krb5_xfree(state->eblock.key);
+	state->eblock.key = 0;
+	return ENOMEM;
+    }
+
+    kret = mit_des_n_fold(seed->data, seed->length,
+		state->eblock.key->contents, state->eblock.key->length);
+    if (kret) return kret;
+
+    mit_des_fixup_keyblock_parity(state->eblock.key);
+
+    for (i = 0; i < state->eblock.key->length/sizeof(mit_des_cblock); i++) {
+	new_key = (mit_des_cblock *)state->eblock.key->contents + i;
+	if (mit_des_is_weak_key(*new_key)) {
+	    (*new_key)[0] ^= 0xF0;
+	    mit_des_fixup_key_parity(*new_key);
+	}
+    }
+
+    /* destroy any old key schedule */
+    mit_des_finish_key(&state->eblock);
+    
+    /* compute the key schedule */
+    (* state->eblock.crypto_entry->process_key)
+	(&state->eblock, state->eblock.key);
+
+    /* now we can destroy the key... */
+    memset(state->eblock.key->contents, 0, state->eblock.key->length);
+    krb5_xfree(state->eblock.key->contents);
+    krb5_xfree(state->eblock.key);
+    state->eblock.key = (krb5_keyblock *) 0;
+
+    /* "seek" to the start of the stream: */
+    memset(state->sequence.data, 0, state->sequence.length);
+
+    return 0;
+}
+
+krb5_error_code
+mit_des_set_random_sequence_number(sequence, p_state)
+    const krb5_data *sequence;
+    krb5_pointer p_state;
+{
+    mit_des_random_state *state = p_state;
+    int length = state->eblock.crypto_entry->keysize;
+
+    if (length > sequence->length)
+	length = sequence->length;
+
+    memcpy(state->sequence.data, sequence->data, length);
+    
+    return 0;
+}
--- 1.1	1996/04/30 20:04:09
+++ src/lib/crypto/des/init_rkey.c	1996/05/02 22:21:56
@@ -32,24 +32,130 @@
         sequence information.
  */
 
+#ifndef min
+#define min(a,b) (((a) > (b)) ? (b) : (a))
+#endif
+
 krb5_error_code
-mit_des_init_random_key (seedblock, seed)
+mit_des_init_random_key (eblock, seedblock, state)
+    const krb5_encrypt_block * eblock;
     const krb5_keyblock * seedblock;
-    krb5_pointer * seed;
+    krb5_pointer * state;
 {
-    mit_des_random_key_seed * p_seed;
-    if ((seedblock->enctype != ENCTYPE_DES_CBC_CRC) &&
-	(seedblock->enctype != ENCTYPE_DES_CBC_MD4) && 
-	(seedblock->enctype != ENCTYPE_DES_CBC_MD5) && 
-	(seedblock->enctype != ENCTYPE_DES_CBC_RAW) &&
-	(seedblock->enctype != ENCTYPE_DES3_CBC_MD5) && 
-	(seedblock->enctype != ENCTYPE_DES3_CBC_RAW))
+    mit_des_random_state * p_state = 0;
+    krb5_keyblock *new_key;
+    krb5_enctype enctype = eblock->crypto_entry->proto_enctype;
+    krb5_error_code kret = 0;
+    krb5_address **addrs = 0;
+    krb5_data seed;
+    struct tval {
+	krb5_int32 seconds;
+	krb5_int32 microseconds;
+    } timenow;
+
+    switch (enctype)
+    {
+    case ENCTYPE_DES_CBC_CRC:
+    case ENCTYPE_DES_CBC_MD4:
+    case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_DES_CBC_RAW:
+	enctype = ENCTYPE_DES_CBC_RAW;
+	break;
+
+    case ENCTYPE_DES3_CBC_MD5:
+    case ENCTYPE_DES3_CBC_RAW:
+	enctype = ENCTYPE_DES3_CBC_RAW;
+	break;
+
+    default:
 	return KRB5_BAD_ENCTYPE;
-    if ( !(p_seed = (mit_des_random_key_seed *) 
-	   malloc(sizeof(mit_des_random_key_seed))) ) 
-	return ENOMEM;
-    memset((char *)p_seed, 0, sizeof(mit_des_random_key_seed) );
-    mit_des_init_random_number_generator(seedblock->contents, p_seed);
-    *seed = (krb5_pointer) p_seed;
+    }
+
+    p_state = (mit_des_random_state *) malloc(sizeof(mit_des_random_state));
+    *state = (krb5_pointer) p_state;
+
+    if (! p_state) {
+	kret = ENOMEM;
+	goto cleanup;
+    }
+
+    memset(p_state, 0, sizeof(*p_state));
+    p_state->eblock.crypto_entry = krb5_enctype_array[enctype]->system;
+    p_state->sequence.length = p_state->eblock.crypto_entry->keysize;
+    p_state->sequence.data = (krb5_pointer) malloc(p_state->sequence.length);
+
+    if (! p_state->sequence.data) {
+	kret = ENOMEM;
+	goto cleanup;
+    }
+
+    /*
+     * Generate a temporary value that is based on the
+     * input seed and the hostid (sequence number)
+     * such that it gives no useful information about the input.
+     *
+     * Then use the temporary value as the new seed and the current
+     * time as a sequence number to give us a stream that was not
+     * previously used.
+     *
+     * This result will be the seed for the random number stream
+     * (the sequence number will start at zero).
+     */
+
+    /* seed = input */
+    seed.data = seedblock->contents;
+    seed.length = seedblock->length;
+    kret = mit_des_set_random_generator_seed(&seed, p_state);
+    if (kret) goto cleanup;
+
+    /* sequence = hostid */
+    if (!krb5_crypto_os_localaddr(&addrs) && addrs && *addrs) {
+	memcpy((char *)p_state->sequence.data, (char *)addrs[0]->contents,
+	      min(p_state->sequence.length, addrs[0]->length));
+	/* XXX may not do all of the sequence number. */
+    }
+    if (addrs) {
+	/* can't use krb5_free_addresses due to circular dependencies in
+	   libraries */
+	register krb5_address **addr2;
+	for (addr2 = addrs; *addr2; addr2++) {
+	    krb5_xfree((*addr2)->contents);
+	    krb5_xfree(*addr2);
+	}
+	krb5_xfree(addrs);
+    }
+
+    /* tmp.seed = random(input,hostid) */
+    kret = mit_des_random_key(NULL, p_state, &new_key);
+    if (kret) goto cleanup;
+    seed.data = new_key->contents;
+    seed.length = new_key->length;
+    kret = mit_des_set_random_generator_seed(&seed, p_state);
+    (void) memset(new_key->contents, 0, new_key->length);
+    krb5_xfree(new_key->contents);
+    krb5_xfree(new_key);
+    if (kret) goto cleanup;
+
+    /* sequence = time */
+    (void) krb5_crypto_us_timeofday(&timenow.seconds,
+				    &timenow.microseconds);
+    memcpy((char *)p_state->sequence.data, (char *)&timenow, sizeof(timenow));
+
+    /* seed = random(tmp.seed, time) */
+    kret = mit_des_random_key(NULL, p_state, &new_key);
+    if (kret) goto cleanup;
+    seed.data = new_key->contents;
+    seed.length = new_key->length;
+    kret = mit_des_set_random_generator_seed(&seed, p_state);
+    (void) memset(new_key->contents, 0, new_key->length);
+    krb5_xfree(new_key->contents);
+    krb5_xfree(new_key);
+    if (kret) goto cleanup;
+    
     return 0;
+
+cleanup:
+    if (kret)
+	mit_des_finish_random_key(eblock, state);
+    return kret;
 }
--- 1.1	1996/04/30 20:50:56
+++ src/lib/crypto/des/fin_rndkey.c	1996/05/02 22:13:38
@@ -2,6 +2,7 @@
  * lib/crypto/des/fin_rndkey.c
  *
  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1996 by Lehman Brothers, Inc.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -14,13 +15,12 @@
  * without fee is hereby granted, provided that the above copyright
  * notice appear in all copies and that both that copyright notice and
  * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- *
+ * the name of M.I.T. or Lehman Brothers not be used in advertising or
+ * publicity pertaining to distribution of the software without
+ * specific, written prior permission.  M.I.T. and Lehman Brothers
+ * make no representations about the suitability of this software for
+ * any purpose.  It is provided "as is" without express or implied
+ * warranty.
  */
 
 #include "k5-int.h"
@@ -30,11 +30,22 @@
         free any resources held by "seed" and assigned by init_random_key()
  */
 
-krb5_error_code mit_des_finish_random_key (seed)
-    krb5_pointer * seed;
+krb5_error_code mit_des_finish_random_key (eblock, p_state)
+    const krb5_encrypt_block * eblock;
+    krb5_pointer * p_state;
 {
-    memset((char *)*seed, 0, sizeof(mit_des_random_key_seed) );
-    krb5_xfree(*seed);
-    *seed = 0;
+    mit_des_random_state * state = *p_state;
+
+    if (! state) return 0;
+
+    if (state->sequence.data) {
+	memset((char *)state->sequence.data, 0, state->sequence.length);
+	krb5_xfree(state->sequence.data);
+    }
+
+    mit_des_finish_key(&state->eblock);
+
+    krb5_xfree(state);
+    *p_state = 0;
     return 0;
 }
--- 1.1	1996/04/30 21:45:59
+++ src/lib/crypto/des/random_key.c	1996/05/02 22:06:13
@@ -2,6 +2,7 @@
  * lib/crypto/des/random_key.c
  *
  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1996 by Lehman Brothers, Inc.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -14,39 +15,76 @@
  * without fee is hereby granted, provided that the above copyright
  * notice appear in all copies and that both that copyright notice and
  * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
+ * the name of M.I.T. or Lehman Brothers not be used in advertising or
+ * publicity pertaining to distribution of the software without
+ * specific, written prior permission.  M.I.T. and Lehman Brothers
+ * make no representations about the suitability of this software for
+ * any purpose.  It is provided "as is" without express or implied
+ * warranty.
  */
 
 #include "k5-int.h"
 #include "des_int.h"
 
+static void mit_des_generate_random_key
+	PROTOTYPE((mit_des_random_state * state, krb5_keyblock * randkey));
+
+
 /*
         generate a random encryption key, allocating storage for it and
         filling in the keyblock address in *keyblock
  */
 
 krb5_error_code
-mit_des_random_key (eblock, seed, keyblock)
+mit_des_random_key (eblock, state, keyblock)
     const krb5_encrypt_block * eblock;
-    krb5_pointer seed;
+    krb5_pointer state;
     krb5_keyblock ** keyblock;
 {
     krb5_keyblock *randkey;
+    int keysize = ((mit_des_random_state *)state)->eblock.crypto_entry->keysize;
+
+    if (eblock == NULL)
+	/* We are being called from the random number initialization routine */
+	eblock = &((mit_des_random_state *)state)->eblock;
 
     if (!(randkey = (krb5_keyblock *)malloc(sizeof(*randkey))))
 	return ENOMEM;
-    if (!(randkey->contents = (krb5_octet *)malloc(sizeof(mit_des_cblock)))) {
+    if (!(randkey->contents = (krb5_octet *)malloc(keysize))) {
 	krb5_xfree(randkey);
 	return ENOMEM;
     }
     randkey->magic = KV5M_KEYBLOCK;
-    randkey->length = sizeof(mit_des_cblock);
+    randkey->length = keysize;
     randkey->enctype = eblock->crypto_entry->proto_enctype;
-    mit_des_new_random_key(randkey->contents, (mit_des_random_key_seed *) seed);
+
+    do {
+	mit_des_generate_random_key(state, randkey);
+	mit_des_fixup_keyblock_parity(randkey);
+    } while (mit_des_is_weak_keyblock(randkey));
+
     *keyblock = randkey;
     return 0;
+}
+
+static mit_des_cblock zero_ivec = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static void
+mit_des_generate_random_key(state, randkey)
+    mit_des_random_state * state;
+    krb5_keyblock * randkey;
+{
+    krb5_encrypt_block *eblock = &state->eblock;
+    int i;
+
+    (* state->eblock.crypto_entry->encrypt_func)
+	(state->sequence.data /*in*/, randkey->contents /*out*/,
+	 state->sequence.length, eblock, zero_ivec);
+
+    /* Increment the sequence number, with wraparound (LSB) */
+    for (i = 0; i < state->sequence.length; i++) {
+	state->sequence.data[i] = (state->sequence.data[i] + 1) & 0xff;
+	if (state->sequence.data[i])
+	    break;
+    }
 }
--- 1.1	1996/04/30 23:18:20
+++ src/lib/crypto/des/new_rn_key.c	1996/04/30 23:20:23
@@ -1,8 +1,6 @@
 /*
- * lib/crypto/des/new_rn_key.c
- *
- * Copyright 1988,1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
+ * Copyright 1996 by Richard P. Basch.  All Rights Reserved.
+ * Copyright 1996 by Lehman Brothers, Inc.  All Rights Reserved.
  *
  * Export of this software from the United States of America may
  *   require a specific license from the United States Government.
@@ -14,17 +12,15 @@
  * without fee is hereby granted, provided that the above copyright
  * notice appear in all copies and that both that copyright notice and
  * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
+ * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  Richard P. Basch,
+ * Lehman Brothers and M.I.T. make no representations about the suitability
+ * of this software for any purpose.  It is provided "as is" without
+ * express or implied warranty.
  *
- * 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
+ * Based on the version 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.
@@ -33,203 +29,115 @@
 #include "k5-int.h"
 #include "des_int.h"
 
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-/*
- * mit_des_new_random_key: create a random des key
- *
- * Requires: mit_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.  Mit_Des_generate_random_block is used to
- *        provide the random bits.
- */
 int
-mit_des_new_random_key(key, p_seed)
-    mit_des_cblock key;
-    mit_des_random_key_seed	*p_seed;
+mit_des_is_weak_keyblock(keyblock)
+    krb5_keyblock * keyblock;
 {
-    do {
-	mit_des_generate_random_block(key, p_seed);
-	mit_des_fixup_key_parity(key);
-    } while (mit_des_is_weak_key(key));
+    int i;
+    
+    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
+	if (mit_des_is_weak_key(*((mit_des_cblock *)keyblock->contents + i));
+	    return 1;
+    return 0;
+}
 
-    return(0);
+void
+mit_des_fixup_keyblock_parity(keyblock)
+    krb5_keyblock * keyblock;
+{
+    int i;
+    
+    for (i = 0; i < keyblock->length/sizeof(mit_des_cblock); i++)
+	mit_des_fixup_key_parity(*((mit_des_cblock *)keyblock->contents + i));
 }
 
-/*
- * mit_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 mit_des_set_random_generator_seed.
- */
 
-void
-mit_des_init_random_number_generator(key,p_seed)
-    mit_des_cblock key;
-    mit_des_random_key_seed	*p_seed;
+static mit_des_cblock zero_ivec = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static
+mit_des_generate_random_key(seed, randkey)
+    mit_des_random_seed * seed;
+    krb5_keyblock * randkey;
 {
-    mit_des_cblock seed; /* This must be 64 bits exactly */
-    struct tval {
-	krb5_int32 seconds;
-	krb5_int32 microseconds;
-    } timenow;
-    mit_des_cblock new_key;
-
-    krb5_address **addrs = 0;
-
-    /*
-     * use a host id in generating the seed to ensure
-     * that different servers have different streams:
-     */
-    memset((char *)seed, 0, sizeof(seed));
-    if (!krb5_crypto_os_localaddr(&addrs) && addrs && *addrs) {
-	memcpy((char *)seed, (char *)addrs[0]->contents,
-	      min(sizeof(seed), addrs[0]->length));
-	/* XXX may not do all of the seed. */
-    }
-    if (addrs) {
-	/* can't use krb5_free_addresses due to circular dependencies in
-	   libraries */
-	register krb5_address **addr2;
-	for (addr2 = addrs; *addr2; addr2++) {
-	    krb5_xfree((*addr2)->contents);
-	    krb5_xfree(*addr2);
-	}
-	krb5_xfree(addrs);
+    krb5_encrypt_block *eblock = seed->eblock;
+    int i;
+
+    (* seed->eblock.crypto_entry->encrypt_func)
+	(seed->sequence->data /*in*/, randkey->contents /*out*/,
+	 seed->sequence->length, eblock, zero_ivec);
+
+    /* Increment the sequence number, with wraparound (LSB) */
+    for (i = 0; i < seed->sequence.length; i++) {
+	seed->sequence.data[i] = (seed->sequence.data[i] + 1) & 0xff;
+	if (seed->sequence.data[i])
+	    break;
     }
-    /*
-     * Generate a temporary value that depends on the key and host_id
-     * such that it gives no useful information about the key:
-     */
-    mit_des_set_random_generator_seed(key, p_seed);
-    mit_des_set_sequence_number(seed, p_seed);
-    mit_des_new_random_key(new_key, p_seed);
-
-    /*
-     * use it to select a random stream:
-     */      
-    mit_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:
-     */
-    /* XXX return value */
-    (void) krb5_crypto_us_timeofday(&timenow.seconds,
-				    &timenow.microseconds);
-    mit_des_set_sequence_number((unsigned char *)&timenow, p_seed);
-
-    /*
-     * use the time stamp finally to select the final seed using the
-     * current random number stream:
-     */
-    mit_des_new_random_key(new_key, p_seed);
-    mit_des_set_random_generator_seed(new_key, p_seed);
 }
 
 /*
- * 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.
- */
-
-/*
  * mit_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.
- * 	[Note: I have changed this so that even if it is not a valid
- * 	DES key, this function will do something rational --- that is,
- * 	we fix up the key parity and make it a non-weak key.  This
- * 	still won't help us if the input value is guessable, but at
- * 	least we won't get screwed if the key-parity is wrong... --- TYT]
  */
-void
-mit_des_set_random_generator_seed(key, p_seed)
-    mit_des_cblock key;
-    mit_des_random_key_seed	*p_seed;
+krb5_error_code
+mit_des_set_random_generator_seed(key, seed)
+    krb5_keyblock *key;
+    mit_des_random_seed	*seed;
 {
     register int i;
-    mit_des_cblock fixed_key;
+    mit_des_cblock *new_key;
 
-    memcpy(fixed_key, key, sizeof(mit_des_cblock));
-    mit_des_fixup_key_parity(fixed_key);
-    if (mit_des_is_weak_key(fixed_key)) {
-	    fixed_key[0] ^= 0xF0;
-	    mit_des_fixup_key_parity(fixed_key);
+    if (seed->eblock.key) {
+	if (seed->eblock.key->contents) {
+	    memset(seed->eblock.key->contents, 0, seed->eblock.key->length);
+	    krb5_xfree(seed->eblock.key->contents);
+	}
     }
 
-    /* select the new stream: (note errors are not possible here...) */
-    mit_des_key_sched(fixed_key, p_seed->random_sequence_key);
+    seed->eblock.key = (krb5_keyblock *)malloc(sizeof(keyblock));
+    if (! seed->eblock.key)
+	return ENOMEM;
+
+    seed->eblock.key->length = seed->eblock.crypto_entry->keysize;
+    seed->eblock.key->contents = (krb5_octet *)malloc(seed->eblock.key->length);
+    if (! seed->eblock.key->contents) {
+	krb5_xfree(seed->eblock.key);
+	seed->eblock.key = 0
+	return ENOMEM;
+    }
 
-    /* "seek" to the start of the stream: */
-    for (i=0; i<8; i++)
-      p_seed->sequence_number[i] = 0;
-}
+    kret = mit_des_n_fold((krb5_octet *)key->contents, key->length,
+	(krb5_octet *)seed->eblock.key->contents, seed->eblock.key->length);
+    if (kret) return kret;
+
+    mit_des_fixup_keyblock_parity(seed->eblock.key);
+
+    for (i = 0; i < seed->eblock.key->length/sizeof(mit_des_cblock)) {
+	new_key = (mit_des_cblock *)seed->eblock.key->contents + i;
+	if (mit_des_is_weak_key(new_key)) {
+	    new_key[0] ^= 0xF0;
+	    mit_des_fixup_key_parity(new_key);
+	}
+    }
 
-/*
- * mit_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 mit_des_set_random_generator_seed resets the sequence number to 0.
- */
-void
-mit_des_set_sequence_number(new_sequence_number, p_seed)
-    mit_des_cblock new_sequence_number;
-    mit_des_random_key_seed	*p_seed;
-{
-    memcpy((char *)p_seed->sequence_number, (char *)new_sequence_number,
-	  sizeof(p_seed->sequence_number));
-}
+    /* destroy any old key schedule */
+    mit_des_finish_key(&seed->eblock);
+    
+    /* compute the key schedule */
+    (* seed->eblock.crypto_entry->process_key)
+	(&seed->eblock, seed->eblock.key);
+
+    /* now we can destroy the key... */
+    memset(seed->eblock.key->contents, 0, seed->eblock.key->length);
+    krb5_xfree(seed->eblock.key->contents);
+    krb5_xfree(seed->eblock.key);
+    seed->eblock.key = (krb5_keyblock *) 0;
 
-/*
- * mit_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: mit_des_set_random_generator_seed must have been called at least once
- *           before this routine is called.
- */
-void
-mit_des_generate_random_block(block, p_seed)
-    mit_des_cblock block;
-    mit_des_random_key_seed	*p_seed;
-{
-    int i;
+    /* "seek" to the start of the stream: */
+    memset(seed->sequence.data, 0, seed->sequence.length);
 
-    /*
-     * Encrypt the sequence number to get the new random block:
-     */
-    mit_des_ecb_encrypt((const mit_des_cblock *)p_seed->sequence_number, 
-		    (mit_des_cblock *)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;
-    }
+    return 0;
 }
--- 1.1	1996/04/30 23:23:35
+++ src/lib/crypto/des/Makefile.in	1996/04/30 23:24:43
@@ -21,7 +21,6 @@
 	process_ky.$(OBJEXT)	\
 	random_key.$(OBJEXT)	\
 	string2key.$(OBJEXT)	\
-	new_rn_key.$(OBJEXT)	\
 	key_sched.$(OBJEXT)	\
 	weak_key.$(OBJEXT)	\
 	f_cbc.$(OBJEXT) 	\
@@ -34,9 +33,9 @@
 	d3_ecb.$(OBJEXT)	\
 	d3_kysched.$(OBJEXT)	\
 	d3_procky.$(OBJEXT) 	\
-	d3_rndky.$(OBJEXT)	\
-	d3_str2ky.$(OBJEXT) \
-	u_nfold.$(OBJEXT)
+	d3_str2ky.$(OBJEXT)	\
+	u_nfold.$(OBJEXT)	\
+	u_rn_key.$(OBJEXT)
 
 SRCS=	$(srcdir)/afsstring2key.c \
 	$(srcdir)/cs_entry.c	\
@@ -47,7 +46,6 @@
 	$(srcdir)/process_ky.c	\
 	$(srcdir)/random_key.c	\
 	$(srcdir)/string2key.c	\
-	$(srcdir)/new_rn_key.c	\
 	$(srcdir)/key_sched.c	\
 	$(srcdir)/weak_key.c	\
 	$(srcdir)/f_cbc.c \
@@ -60,9 +58,9 @@
 	$(srcdir)/d3_ecb.c \
 	$(srcdir)/d3_kysched.c \
 	$(srcdir)/d3_procky.c \
-	$(srcdir)/d3_rndky.c \
 	$(srcdir)/d3_str2ky.c \
-	$(srcdir)/u_nfold.c
+	$(srcdir)/u_nfold.c \
+	$(srcdir)/u_rn_key.c
 
 
 all:: $(OBJS)
--- 1.1	1996/05/02 22:43:54
+++ src/lib/des425/ChangeLog	1996/05/02 22:44:15
@@ -1,3 +1,7 @@
+Thu May  2 18:44:02 1996  Richard Basch  <basch@lehman.com>
+
+	* new_rnd_key.c: Use the rewritten random number routines of libcrypto
+
 Fri Oct  6 22:01:18 1995  Theodore Y. Ts'o  <tytso@dcl>
 
 	* Makefile.in: Remove ##DOS!include of config/windows.in.
--- 1.1	1996/05/01 00:01:57
+++ src/lib/des425/new_rnd_key.c	1996/05/02 22:24:02
@@ -26,11 +26,7 @@
 
 #include "des.h"
 
-/*
- * The secret des key schedule and sequence number for the current
- * stream of random numbers
- */
-static mit_des_random_key_seed random_sequence_state;
+static krb5_pointer random_sequence_state = 0;
 
 /*
  * des_new_random_key: create a random des key
@@ -46,7 +42,19 @@
 des_new_random_key(key)
     mit_des_cblock key;
 {
-    return(mit_des_new_random_key(key, &random_sequence_state));
+    krb5_keyblock * keyblock;
+    krb5_error_code kret;
+
+    kret = mit_des_random_key(NULL, random_sequence_state, &keyblock);
+    if (kret) return kret;
+    
+    memcpy(key, keyblock->contents, sizeof(key));
+
+    memset(keyblock->contents, 0, keyblock->length);
+    krb5_xfree(keyblock->contents);
+    krb5_xfree(keyblock);
+
+    return 0;
 }
 
 /*
@@ -65,9 +73,20 @@
  */
 void
 des_init_random_number_generator(key)
-     mit_des_cblock key;
+    mit_des_cblock key;
 {
-     mit_des_init_random_number_generator(key, &random_sequence_state);
+    krb5_keyblock keyblock;
+    krb5_encrypt_block eblock;
+
+    krb5_use_enctype(NULL, &eblock, ENCTYPE_DES_CBC_CRC);
+
+    keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+    keyblock.length = sizeof(mit_des_cblock);
+    keyblock.contents = (krb5_octet *)key;
+
+    if (random_sequence_state)
+	mit_des_finish_random_key(&eblock, &random_sequence_state);
+    mit_des_init_random_key(&eblock, &keyblock, &random_sequence_state);
 }
 
 /*
@@ -89,9 +108,16 @@
  */
 void
 des_set_random_generator_seed(key)
-     mit_des_cblock key;
+    mit_des_cblock key;
 {
-     mit_des_set_random_generator_seed(key, &random_sequence_state);
+    krb5_data seed;
+
+    seed.length = sizeof(mit_des_cblock);
+    seed.data = (krb5_pointer) key;
+
+    if (!random_sequence_state)
+	des_init_random_number_generator(key);
+    mit_des_set_random_generator_seed(&seed, random_sequence_state);
 }
 
 
@@ -105,23 +131,11 @@
  */
 void
 des_set_sequence_number(new_sequence_number)
-     mit_des_cblock new_sequence_number;
+    mit_des_cblock new_sequence_number;
 {
-     mit_des_set_sequence_number(new_sequence_number, &random_sequence_state);
-}
+    krb5_data sequence;
 
-/*
- * 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);
+    sequence.length = sizeof(new_sequence_number);
+    sequence.data = (krb5_octet *)new_sequence_number;
+    mit_des_set_random_sequence_number(&sequence, random_sequence_state);
 }
-
--- 1.1	1996/05/02 21:52:55
+++ src/include/ChangeLog	1996/05/02 22:41:50
@@ -1,3 +1,8 @@
+Thu May  2 18:41:00 1996  Richard Basch  <basch@lehman.com>
+
+	* krb5.hin: krb5_init_random_key & krb5_finish_random_key now
+		pass the eblock to the underlying crypto routine.
+
 Wed Apr 17 20:56:51 1996  Marc Horowitz  <marc@mit.edu>
 
 	* k5-int.h, port-sockets.h: moved socket stuff into a separate
--- 1.1	1996/05/02 21:52:55
+++ src/include/krb5.hin	1996/05/02 22:59:32
@@ -359,9 +359,11 @@
 						krb5_keyblock FAR *,
 						krb5_const krb5_data FAR *,
  	                                        krb5_const krb5_data FAR *));
-    krb5_error_code  (*init_random_key) KRB5_NPROTOTYPE((krb5_const krb5_keyblock FAR *,
-						   krb5_pointer FAR *));
-    krb5_error_code  (*finish_random_key) KRB5_NPROTOTYPE(( krb5_pointer FAR *));
+    krb5_error_code (*init_random_key) KRB5_NPROTOTYPE(( krb5_const krb5_encrypt_block FAR *,
+						krb5_const krb5_keyblock FAR *,
+						krb5_pointer FAR *));
+    krb5_error_code (*finish_random_key) KRB5_NPROTOTYPE(( krb5_const krb5_encrypt_block FAR *,
+						krb5_pointer FAR *));
     krb5_error_code (*random_key) KRB5_NPROTOTYPE(( krb5_const krb5_encrypt_block FAR *,
 					      krb5_pointer,
 					      krb5_keyblock FAR * FAR *));
@@ -468,8 +470,8 @@
 #define krb5_process_key(context, eblock, key) krb5_x((eblock)->crypto_entry->process_key,(eblock, key))
 #define krb5_finish_key(context, eblock) krb5_x((eblock)->crypto_entry->finish_key,(eblock))
 #define krb5_string_to_key(context, eblock, keyblock, data, princ) krb5_x((eblock)->crypto_entry->string_to_key,(eblock, keyblock, data, princ))
-#define krb5_init_random_key(context, eblock, keyblock, ptr) krb5_x((eblock)->crypto_entry->init_random_key,(keyblock, ptr))
-#define krb5_finish_random_key(context, eblock, ptr) krb5_x((eblock)->crypto_entry->finish_random_key,(ptr))
+#define krb5_init_random_key(context, eblock, keyblock, ptr) krb5_x((eblock)->crypto_entry->init_random_key,(eblock, keyblock, ptr))
+#define krb5_finish_random_key(context, eblock, ptr) krb5_x((eblock)->crypto_entry->finish_random_key,(eblock, ptr))
 #define krb5_random_key(context, eblock, ptr, keyblock) krb5_x((eblock)->crypto_entry->random_key,(eblock, ptr, keyblock))
 
 #define krb5_eblock_enctype(context, eblockp) ((eblockp)->crypto_entry->proto_enctype)

home help back first fref pref prev next nref lref last post