diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/krb5/krb/gen_seqnum.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/lib/krb5/krb/gen_seqnum.c b/src/lib/krb5/krb/gen_seqnum.c new file mode 100644 index 000000000..1a1e4b929 --- /dev/null +++ b/src/lib/krb5/krb/gen_seqnum.c @@ -0,0 +1,110 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * <krb5/copyright.h>. + * + * Routine to automatically generate a starting sequence number. + * We do this by getting a random key and encrypting something with it, + * then taking the output and slicing it up. + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_gen_seqnum_c[] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include <krb5/krb5.h> +#include <krb5/ext-proto.h> + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +krb5_error_code +krb5_generate_seq_number(key, seqno) +const krb5_keyblock *key; +krb5_int32 *seqno; +{ + krb5_pointer random_state; + krb5_encrypt_block eblock; + krb5_keyblock *subkey; + krb5_error_code retval; + struct tval { + krb5_int32 seconds; + krb5_int32 microseconds; + } timenow; + krb5_octet *intmp, *outtmp; + int esize; + char *outseqno; + + if (!valid_keytype(key->keytype)) + return KRB5_PROG_KEYTYPE_NOSUPP; + + krb5_use_keytype(&eblock, key->keytype); + + if (retval = krb5_init_random_key(&eblock, key, &random_state)) + return(retval); + + if (retval = krb5_random_key(&eblock, random_state, &subkey)) { + (void) krb5_finish_random_key(&eblock, random_state); + return retval; + } + /* ignore the error if any, since we've already gotten the key out */ + if (retval = krb5_finish_random_key(&eblock, &random_state)) { + krb5_free_keyblock(subkey); + return retval; + } + + esize = krb5_encrypt_size(sizeof(timenow), eblock.crypto_entry); + intmp = (krb5_octet *)malloc(esize); + if (!intmp) { + krb5_free_keyblock(subkey); + return ENOMEM; + } + outtmp = (krb5_octet *)malloc(esize); + if (!outtmp) { + xfree(intmp); + krb5_free_keyblock(subkey); + return ENOMEM; + } + if (retval = krb5_process_key(&eblock, subkey)) { + goto cleanup; + } + outseqno = (char *)seqno; + + if (retval = krb5_us_timeofday(&timenow.seconds, + &timenow.microseconds)) { + goto cleanup; + } + memcpy((char *)intmp, (char *)&timenow, sizeof(timenow)); + + while (outseqno < (char *)(seqno+1)) { + memset((char *)intmp, 0, esize); + + if (retval = krb5_encrypt((krb5_pointer)intmp, + (krb5_pointer)outtmp, + sizeof(timenow), + &eblock, + 0)) { + (void) krb5_finish_key(&eblock); + goto cleanup; + } + memcpy(outseqno, (char *)outtmp, MIN((char *)(seqno+1)-outseqno, + esize)); + outseqno += MIN((char *)(seqno+1)-outseqno, esize); + /* chain along */ + memcpy(intmp,outtmp,esize); + } + (void) krb5_finish_key(&eblock); + cleanup: + krb5_free_keyblock(subkey); + xfree(intmp); + xfree(outtmp); + return retval; +} + |
