From cd7f0a235df010bd0c23c69765f2eca1596c2ff2 Mon Sep 17 00:00:00 2001 From: Richard Basch Date: Wed, 15 May 1996 01:01:41 +0000 Subject: [PATCH] * .Sanitize: reflect current files * Makefile.in: added hmac-sha * hmac_sha.c: implement HMAC-SHA * sha_crypto.c: use hmac-sha * sha_glue.c: sanity check the passed in checksum length * shs.h: replaced sha-des3 with hmac-sha git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@8026 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/sha/.Sanitize | 5 +- src/lib/crypto/sha/ChangeLog | 9 ++ src/lib/crypto/sha/Makefile.in | 11 +- src/lib/crypto/sha/hmac_sha.c | 77 ++++++++++++++ src/lib/crypto/sha/sha_crypto.c | 176 ++++---------------------------- src/lib/crypto/sha/sha_glue.c | 3 + src/lib/crypto/sha/shs.h | 18 +++- 7 files changed, 135 insertions(+), 164 deletions(-) create mode 100644 src/lib/crypto/sha/hmac_sha.c diff --git a/src/lib/crypto/sha/.Sanitize b/src/lib/crypto/sha/.Sanitize index c9f08bb77..886bb2b0a 100644 --- a/src/lib/crypto/sha/.Sanitize +++ b/src/lib/crypto/sha/.Sanitize @@ -28,10 +28,11 @@ ChangeLog Makefile.in configure configure.in -shs.c -shs.h sha_crypto.c sha_glue.c +shs.c +shs.h +hmac_sha.c t_shs.c Things-to-lose: diff --git a/src/lib/crypto/sha/ChangeLog b/src/lib/crypto/sha/ChangeLog index d7331b49f..9e3c0011d 100644 --- a/src/lib/crypto/sha/ChangeLog +++ b/src/lib/crypto/sha/ChangeLog @@ -1,3 +1,12 @@ +Tue May 14 17:09:36 1996 Richard Basch + + * .Sanitize: reflect current files + * Makefile.in: added hmac-sha + * hmac_sha.c: implement HMAC-SHA + * sha_crypto.c: use hmac-sha + * sha_glue.c: sanity check the passed in checksum length + * shs.h: replaced sha-des3 with hmac-sha + Fri May 10 11:19:53 1996 Ezra Peisach * shs.c (longReverse): Remove extraneous \. diff --git a/src/lib/crypto/sha/Makefile.in b/src/lib/crypto/sha/Makefile.in index 288e72ca7..4f529fdfa 100644 --- a/src/lib/crypto/sha/Makefile.in +++ b/src/lib/crypto/sha/Makefile.in @@ -7,9 +7,16 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)/../des $(CC) $(CFLAGS) -c $(srcdir)/$*.c @SHARED_RULE@ -OBJS= shs.$(OBJEXT) sha_glue.$(OBJEXT) sha_crypto.$(OBJEXT) +OBJS= shs.$(OBJEXT) \ + hmac_sha.$(OBJEXT) \ + sha_crypto.$(OBJEXT) \ + sha_glue.$(OBJEXT) + +SRCS= $(srcdir)/shs.c \ + $(srcdir)/hmac_sha.c \ + $(srcdir)/sha_crypto.c \ + $(srcdir)/sha_glue.c -SRCS= $(srcdir)/shs.c $(srcdir)/sha_glue.c $(srcdir)/sha_crypto.c all-unix:: shared $(OBJS) all-mac:: shared $(OBJS) diff --git a/src/lib/crypto/sha/hmac_sha.c b/src/lib/crypto/sha/hmac_sha.c new file mode 100644 index 000000000..6813ea70c --- /dev/null +++ b/src/lib/crypto/sha/hmac_sha.c @@ -0,0 +1,77 @@ +#include "shs.h" + +#define PAD_SZ 64 + + +krb5_error_code +hmac_sha(text, text_len, key, key_len, digest) + krb5_octet * text; /* pointer to data stream */ + int text_len; /* length of data stream */ + krb5_octet * key; /* pointer to authentication key */ + int key_len; /* length of authentication key */ + krb5_octet * digest; /* caller digest to be filled in */ +{ + SHS_INFO context; + krb5_octet k_ipad[PAD_SZ]; /* inner padding - key XORd with ipad */ + krb5_octet k_opad[PAD_SZ]; /* outer padding - key XORd with opad */ + int i; + + /* sanity check parameters */ + if (!text || !key || !digest) + /* most heinous, probably should log something */ + return EINVAL; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > sizeof(k_ipad)) { + shsInit(&context); + shsUpdate(&context, key, key_len); + shsFinal(&context); + + memcpy(digest, context.digest, SHS_DIGESTSIZE); + key = digest; + key_len = SHS_DIGESTSIZE; + } + + /* + * the HMAC_SHA transform looks like: + * + * SHA(K XOR opad, SHA(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset(k_ipad, 0x36, sizeof(k_ipad)); + memset(k_opad, 0x5c, sizeof(k_opad)); + + /* XOR key with ipad and opad values */ + for (i = 0; i < key_len; i++) { + k_ipad[i] ^= key[i]; + k_opad[i] ^= key[i]; + } + + /* + * perform inner SHA + */ + shsInit(&context); + shsUpdate(&context, k_ipad, sizeof(k_ipad)); + shsUpdate(&context, text, text_len); + shsFinal(&context); + + memcpy(digest, context.digest, SHS_DIGESTSIZE); + + /* + * perform outer SHA + */ + shsInit(&context); + shsUpdate(&context, k_opad, sizeof(k_opad)); + shsUpdate(&context, digest, SHS_DIGESTSIZE); + shsFinal(&context); + + memcpy(digest, context.digest, SHS_DIGESTSIZE); + + return 0; +} diff --git a/src/lib/crypto/sha/sha_crypto.c b/src/lib/crypto/sha/sha_crypto.c index f554a49e2..af1aee225 100644 --- a/src/lib/crypto/sha/sha_crypto.c +++ b/src/lib/crypto/sha/sha_crypto.c @@ -4,7 +4,7 @@ /* Windows needs to these prototypes for the assignment below */ -krb5_error_code +static krb5_error_code krb5_sha_crypto_sum_func PROTOTYPE((krb5_pointer in, size_t in_length, @@ -12,7 +12,7 @@ krb5_sha_crypto_sum_func size_t seed_length, krb5_checksum FAR *outcksum)); -krb5_error_code +static krb5_error_code krb5_sha_crypto_verify_func PROTOTYPE((krb5_checksum FAR *cksum, krb5_pointer in, @@ -20,21 +20,6 @@ krb5_sha_crypto_verify_func krb5_pointer seed, size_t seed_length)); -static void -krb5_sha_calculate_cksum(ctx, in, in_length, confound, confound_length) - SHS_INFO *ctx; - krb5_pointer in; - size_t in_length; - krb5_pointer confound; - size_t confound_length; -{ - shsInit(ctx); - if (confound && confound_length) - shsUpdate(ctx, confound, confound_length); - shsUpdate(ctx, in, in_length); - shsFinal(ctx); -} - static krb5_error_code shs_crypto_sum_func(in, in_length, seed, seed_length, outcksum) krb5_pointer in; @@ -43,73 +28,15 @@ shs_crypto_sum_func(in, in_length, seed, seed_length, outcksum) size_t seed_length; krb5_checksum FAR *outcksum; { - krb5_octet outtmp[NIST_SHA_DES3_CKSUM_LENGTH+ - NIST_SHA_DES3_CONFOUND_LENGTH]; - krb5_octet *input = (krb5_octet *)in; - krb5_encrypt_block eblock; - krb5_keyblock keyblock; krb5_error_code retval; - mit_des3_cblock tmpkey; - size_t i; - - SHS_INFO working; - - /* Generate the confounder in place */ - if (retval = krb5_random_confounder(NIST_SHA_DES3_CONFOUND_LENGTH, - outtmp)) - return(retval); - - /* Calculate the checksum */ - krb5_sha_calculate_cksum(&working, - in, - in_length, - (krb5_pointer) outtmp, - (size_t) NIST_SHA_DES3_CONFOUND_LENGTH); - - outcksum->checksum_type = CKSUMTYPE_NIST_SHA_DES3; - outcksum->length = - NIST_SHA_DES3_CKSUM_LENGTH + NIST_SHA_DES3_CONFOUND_LENGTH; - - /* Now blast in the digest */ - memset((char *)&outtmp[NIST_SHA_DES3_CONFOUND_LENGTH], 0, - NIST_SHA_DES3_CKSUM_LENGTH); - memcpy((char *)&outtmp[NIST_SHA_DES3_CONFOUND_LENGTH], - (char *)&working.digest[0], NIST_SHA_CKSUM_LENGTH); - - /* Clean up the droppings */ - memset((char *)&working, 0, sizeof(working)); - /* Set up the temporary copy of the key (see RFC 1510 section 6.4.5) */ - memset((char *) tmpkey, 0, sizeof(tmpkey)); - for (i=0; (ilength < HMAC_SHA_CKSUM_LENGTH) + return KRB5_BAD_MSIZE; - keyblock.length = sizeof(tmpkey); - keyblock.contents = (krb5_octet *) tmpkey; - keyblock.enctype = ENCTYPE_DES3_CBC_SHA; - - if ((retval = mit_des3_process_key(&eblock, &keyblock))) - return retval; - - /* now that we have computed the key schedules, zero the key as the IV */ - memset((char *) tmpkey, 0, sizeof(tmpkey)); - - /* now encrypt it */ - retval = mit_des3_cbc_encrypt((mit_des_cblock *)&outtmp[0], - (mit_des_cblock *)outcksum->contents, - NIST_SHA_DES3_CKSUM_LENGTH + - NIST_SHA_DES3_CONFOUND_LENGTH, - (struct mit_des_ks_struct *)eblock.priv, - ((struct mit_des_ks_struct *)eblock.priv)+1, - ((struct mit_des_ks_struct *)eblock.priv)+2, - keyblock.contents, - MIT_DES_ENCRYPT); - - if (retval) - (void) mit_des_finish_key(&eblock); - else - retval = mit_des_finish_key(&eblock); + outcksum->checksum_type = CKSUMTYPE_HMAC_SHA; + outcksum->length = HMAC_SHA_CKSUM_LENGTH; + retval = hmac_sha(in, in_length, seed, seed_length, outcksum->contents); return retval; } @@ -121,92 +48,31 @@ shs_crypto_verify_func(cksum, in, in_length, seed, seed_length) krb5_pointer seed; size_t seed_length; { - krb5_octet outtmp[NIST_SHA_DES3_CKSUM_LENGTH + - NIST_SHA_DES3_CONFOUND_LENGTH]; - krb5_octet *input = (krb5_octet *)in; - krb5_encrypt_block eblock; - krb5_keyblock keyblock; + krb5_octet digest[HMAC_SHA_CKSUM_LENGTH]; krb5_error_code retval; - mit_des3_cblock tmpkey; - size_t i; - - SHS_INFO working; - - retval = 0; - if (cksum->checksum_type == CKSUMTYPE_NIST_SHA_DES3) { - if (cksum->length == (NIST_SHA_DES3_CKSUM_LENGTH + - NIST_SHA_DES3_CONFOUND_LENGTH)) { - /* - * If we're verifying the correct implementation, then we have - * to do a little more work because we must decrypt the checksum - * because it contains the confounder in it. So, figure out - * what our key variant is and then do it! - */ - /* Set up the variant of the key (see RFC 1510 section 6.4.5) */ - memset((char *) tmpkey, 0, sizeof(tmpkey)); - for (i=0; (ichecksum_type != CKSUMTYPE_HMAC_SHA) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + if (cksum->length != HMAC_SHA_CKSUM_LENGTH) + return KRB5KRB_AP_ERR_BAD_INTEGRITY; - keyblock.length = sizeof(tmpkey); - keyblock.contents = (krb5_octet *) tmpkey; - keyblock.enctype = ENCTYPE_DES3_CBC_SHA; + retval = hmac_sha(in, in_length, seed, seed_length, digest); + if (retval) goto cleanup; - if ((retval = mit_des3_process_key(&eblock, &keyblock))) - return retval; + if (memcmp((char *)digest, (char *)cksum->contents, cksum->length)) + retval = KRB5KRB_AP_ERR_BAD_INTEGRITY; - /* now zero the key for use as the IV */ - memset((char *) tmpkey, 0, sizeof(tmpkey)); - - /* now decrypt it */ - retval = mit_des3_cbc_encrypt((mit_des_cblock *)cksum->contents, - (mit_des_cblock *)&outtmp[0], - NIST_SHA_DES3_CKSUM_LENGTH + - NIST_SHA_DES3_CONFOUND_LENGTH, - (struct mit_des_ks_struct *) - eblock.priv, - ((struct mit_des_ks_struct *) - eblock.priv) + 1, - ((struct mit_des_ks_struct *) - eblock.priv) + 2, - keyblock.contents, - MIT_DES_DECRYPT); - if (retval) - (void) mit_des_finish_key(&eblock); - else - retval = mit_des_finish_key(&eblock); - if (retval) return retval; - - /* Now that we have the decrypted checksum, try to regenerate it */ - krb5_sha_calculate_cksum(&working, - in, - in_length, - (krb5_pointer) outtmp, - (size_t) NIST_SHA_DES3_CONFOUND_LENGTH); - - /* Compare the checksums */ - if (memcmp((char *) &outtmp[NIST_SHA_DES3_CONFOUND_LENGTH], - (char *) &working.digest[0], - NIST_SHA_CKSUM_LENGTH)) - retval = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - else - retval = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - else - retval = KRB5KRB_AP_ERR_INAPP_CKSUM; - - /* Clean up droppings */ - memset((char *)&working, 0, sizeof(working)); - return(retval); +cleanup: + memset((char *)digest, 0, sizeof(digest)); + return retval; } -krb5_checksum_entry nist_sha_des3_cksumtable_entry = +krb5_checksum_entry hmac_sha_cksumtable_entry = { 0, shs_crypto_sum_func, shs_crypto_verify_func, - NIST_SHA_DES3_CKSUM_LENGTH + NIST_SHA_DES3_CONFOUND_LENGTH, + HMAC_SHA_CKSUM_LENGTH, 1, /* is collision proof */ 1, /* uses key */ }; diff --git a/src/lib/crypto/sha/sha_glue.c b/src/lib/crypto/sha/sha_glue.c index 3028c1147..28416fc08 100644 --- a/src/lib/crypto/sha/sha_glue.c +++ b/src/lib/crypto/sha/sha_glue.c @@ -28,6 +28,9 @@ krb5_sha_sum_func(in, in_length, seed, seed_length, outcksum) krb5_octet *input = (krb5_octet *)in; SHS_INFO working; + if (outcksum->length < SHS_DIGESTSIZE) + return KRB5_BAD_MSIZE; + shsInit(&working); shsUpdate(&working, input, in_length); shsFinal(&working); diff --git a/src/lib/crypto/sha/shs.h b/src/lib/crypto/sha/shs.h index 4c846bf66..77b4ff250 100644 --- a/src/lib/crypto/sha/shs.h +++ b/src/lib/crypto/sha/shs.h @@ -31,8 +31,7 @@ typedef struct { LONG data[ 16 ]; /* SHS data buffer */ } SHS_INFO; -/* Message digest functions */ - +/* Message digest functions (shs.c) */ void shsInit KRB5_PROTOTYPE((SHS_INFO *shsInfo)); void shsUpdate @@ -41,12 +40,21 @@ void shsFinal KRB5_PROTOTYPE((SHS_INFO *shsInfo)); +/* Keyed Message digest functions (hmac_sha.c) */ +krb5_error_code hmac_sha + KRB5_PROTOTYPE((krb5_octet *text, + int text_len, + krb5_octet *key, + int key_len, + krb5_octet *digest)); + + #define NIST_SHA_CKSUM_LENGTH SHS_DIGESTSIZE -#define NIST_SHA_DES3_CKSUM_LENGTH 24 -#define NIST_SHA_DES3_CONFOUND_LENGTH 8 +#define HMAC_SHA_CKSUM_LENGTH SHS_DIGESTSIZE + extern krb5_checksum_entry nist_sha_cksumtable_entry, - nist_sha_des3_cksumtable_entry; + hmac_sha_cksumtable_entry; #endif /* _SHS_DEFINED */ -- 2.26.2