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;
}