summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2001-10-26 05:50:25 +0000
committerSam Hartman <hartmans@mit.edu>2001-10-26 05:50:25 +0000
commit4f979233c32b6d7a937e4b139c131935695d2d3e (patch)
treea514bc6eb82b67b2064b4fe06c22d370791bf3bc /src
parent0af03dd9ced634438709a5706e38828162170bac (diff)
downloadkrb5-4f979233c32b6d7a937e4b139c131935695d2d3e.tar.gz
krb5-4f979233c32b6d7a937e4b139c131935695d2d3e.tar.xz
krb5-4f979233c32b6d7a937e4b139c131935695d2d3e.zip
* Expose some rc4 crypto routines through the accessor mechanism; cleaner than raw enctype
* Deal with GSSAPI key usage in microsoft translation * Add rc4 gssapi mechanism; works with itself, not tested against * Windows yet * Refactor large chunks of k5seal.c to make code more readable for debugging git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13859 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/include/ChangeLog8
-rw-r--r--src/include/k5-int.h18
-rw-r--r--src/lib/crypto/arcfour/ChangeLog4
-rw-r--r--src/lib/crypto/arcfour/arcfour.c2
-rw-r--r--src/lib/gssapi/krb5/ChangeLog40
-rw-r--r--src/lib/gssapi/krb5/accept_sec_context.c14
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h9
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c15
-rw-r--r--src/lib/gssapi/krb5/k5seal.c326
-rw-r--r--src/lib/gssapi/krb5/k5unseal.c73
-rw-r--r--src/lib/gssapi/krb5/util_crypt.c67
-rw-r--r--src/lib/gssapi/krb5/util_seqnum.c40
-rw-r--r--src/lib/krb5/os/ChangeLog4
-rw-r--r--src/lib/krb5/os/accessor.c3
14 files changed, 425 insertions, 198 deletions
diff --git a/src/include/ChangeLog b/src/include/ChangeLog
index 8d18c2c414..958dc2ab54 100644
--- a/src/include/ChangeLog
+++ b/src/include/ChangeLog
@@ -1,3 +1,11 @@
+2001-10-24 Sam Hartman <hartmans@mit.edu>
+
+ * k5-int.h: Add declaration for arcfour enc_provider and md5
+ hash_provider so we can get to these indirectly from libgssapi.
+ Ick. This is an evil hack but somewhat less evil than having raw
+ enctypes.
+ Add above to krb5int_access along with krb5_hmac function
+
2001-10-24 Ezra Peisach <epeisach@mit.edu>
* configure.in: Use of AC_DEFINE modified to include third
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 9f7a78ebae..34fe737955 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -623,6 +623,14 @@ krb5_error_code krb5_hmac
krb5_const krb5_keyblock *key, unsigned int icount,
krb5_const krb5_data *input, krb5_data *output);
+/*
+ * These declarations are here, so both krb5 and k5crypto
+ * can get to them.
+ * krb5 needs to get to them so it can make them available to libgssapi.
+ */
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_hash_provider krb5int_hash_md5;
+
#ifdef KRB5_OLD_CRYPTO
/* old provider api */
@@ -1512,7 +1520,7 @@ void krb5int_set_prompt_types
/* To keep happy libraries which are (for now) accessing internal stuff */
/* Make sure to increment by one when changing the struct */
-#define KRB5INT_ACCESS_STRUCT_VERSION 3
+#define KRB5INT_ACCESS_STRUCT_VERSION 4
typedef struct _krb5int_access {
krb5_error_code (*krb5_locate_kdc) (krb5_context, const krb5_data *,
@@ -1526,7 +1534,13 @@ typedef struct _krb5int_access {
unsigned int krb5_skdc_timeout_shift;
unsigned int krb5_skdc_timeout_1;
unsigned int krb5_max_dgram_size;
-} krb5int_access;
+ const struct krb5_hash_provider *md5_hash_provider;
+ const struct krb5_enc_provider *arcfour_enc_provider;
+ krb5_error_code (* krb5_hmac)
+ (krb5_const struct krb5_hash_provider *hash,
+ krb5_const krb5_keyblock *key, unsigned int icount,
+ krb5_const krb5_data *input, krb5_data *output);
+ } krb5int_access;
#define KRB5INT_ACCESS_VERSION \
(((krb5_int32)((sizeof(krb5int_access) & 0xFFFF) | \
diff --git a/src/lib/crypto/arcfour/ChangeLog b/src/lib/crypto/arcfour/ChangeLog
index 335304a933..9f9cbc76a2 100644
--- a/src/lib/crypto/arcfour/ChangeLog
+++ b/src/lib/crypto/arcfour/ChangeLog
@@ -1,3 +1,7 @@
+2001-10-25 Sam Hartman <hartmans@mit.edu>
+
+ * arcfour.c: GSSAPI usage translations
+
2001-10-24 Ezra Peisach <epeisach@mit.edu>
* arcfour.h: Declare krb5int_enc_arcfour extern so that multiple
diff --git a/src/lib/crypto/arcfour/arcfour.c b/src/lib/crypto/arcfour/arcfour.c
index cc1857770b..66c0bd3355 100644
--- a/src/lib/crypto/arcfour/arcfour.c
+++ b/src/lib/crypto/arcfour/arcfour.c
@@ -55,6 +55,8 @@ case 7: /* tgs-req authenticator */
return 11;
case 12: /* app-rep encrypted part */
return 12;
+ case 23: /* sign wrap token*/
+ return 13;
default:
return usage;
}
diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog
index e40b3fc1f4..d5aa402f7f 100644
--- a/src/lib/gssapi/krb5/ChangeLog
+++ b/src/lib/gssapi/krb5/ChangeLog
@@ -1,3 +1,39 @@
+2001-10-25 Sam Hartman <hartmans@mit.edu>
+
+ * k5unseal.c (kg_unseal_v1): same here.
+
+ * k5seal.c (make_seal_token_v1): Factor out usage type we claim
+ for signatures so we can do something different for hmac-md5.
+ Microsoft uses a different usage number for mic tokens and wrap tokens.
+
+ * k5unseal.c (kg_unseal_v1): Add arcfour checksum and decrypt support
+
+ * util_seqnum.c (kg_get_seq_num): support arcfour_hmac
+
+ * k5unseal.c (kg_unseal_v1): Get the sequence number before
+ decrypting the token so we can use it to decrypt arcfour
+
+ * gssapiP_krb5.h util_crypt.c: New function kg_arcfour_docrypt
+
+ * util_seqnum.c (kg_make_seq_num): Add rc4 support
+
+ * k5seal.c (make_seal_token_v1): Simplify logic significantly.
+ Don't worry so much about only allocating memory we use; allocate
+ a full token all the time and only decide not to copy in data at
+ the last moment. This significantly simplifies the control flow,
+ giving better testing coverage and allowing better reasoning about
+ the code. Add arcfour-hmac support
+
+ * util_crypt.c (kg_confounder_size): Special case arcfour to return 8
+
+2001-10-24 Sam Hartman <hartmans@mit.edu>
+
+ * accept_sec_context.c (krb5_gss_accept_sec_context): Support rc4 enctype
+
+ * init_sec_context.c (krb5_gss_init_sec_context): Support rc4 enctype
+
+ * gssapiP_krb5.h: Remove claim we don't support Microsoft sign alg
+
2001-10-09 Ken Raeburn <raeburn@mit.edu>
* gssapiP_krb5.h, gssapi_krb5.h, k5mech.c: Make prototypes
@@ -1487,3 +1523,7 @@ Wed Aug 17 15:47:26 1994 Theodore Y. Ts'o (tytso at tsx-11)
* gssapi_krb5.c: Fixed OID for the krb5 mechanism. (Transcription
error.)
+
+
+
+
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index a3d4a73374..3cc291d80e 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -628,6 +628,20 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
}
break;
+ case ENCTYPE_ARCFOUR_HMAC:
+ ctx->signalg = SGN_ALG_HMAC_MD5 ;
+ ctx->cksum_size = 8;
+ ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+
+ code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
+ if (code)
+ goto fail;
+ code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
+ if (code) {
+ krb5_free_keyblock (context, ctx->enc);
+ goto fail;
+ }
+ break;
default:
code = KRB5_BAD_ENCTYPE;
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 634b9e6b8b..238ce2507c 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -108,14 +108,14 @@ enum sgn_alg {
SGN_ALG_MD2_5 = 0x0001,
SGN_ALG_DES_MAC = 0x0002,
SGN_ALG_3 = 0x0003, /* not published */
- SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */
+ SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; */
SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004
};
enum seal_alg {
SEAL_ALG_NONE = 0xffff,
SEAL_ALG_DES = 0x0000,
SEAL_ALG_1 = 0x0001, /* not published */
- SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; no support */
+ SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
SEAL_ALG_DES3KD = 0x0002
};
@@ -248,6 +248,11 @@ krb5_error_code kg_encrypt (krb5_context context,
krb5_pointer in,
krb5_pointer out,
int length);
+krb5_error_code
+kg_arcfour_docrypt (const krb5_keyblock *longterm_key , int ms_usage,
+ const unsigned char *kd_data, size_t kd_data_len,
+ const unsigned char *input_buf, size_t input_len,
+ unsigned char *output_buf);
krb5_error_code kg_decrypt (krb5_context context,
krb5_keyblock *key, int usage,
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index a39372ff0d..6a88a4ebcf 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -353,6 +353,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
#if 1
ENCTYPE_DES3_CBC_SHA1,
#endif
+ ENCTYPE_ARCFOUR_HMAC,
ENCTYPE_DES_CBC_CRC,
ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4,
0
@@ -565,6 +566,20 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
goto fail;
}
break;
+ case ENCTYPE_ARCFOUR_HMAC:
+ ctx->signalg = SGN_ALG_HMAC_MD5 ;
+ ctx->cksum_size = 8;
+ ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+
+ code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
+ if (code)
+ goto fail;
+ code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
+ if (code) {
+ krb5_free_keyblock (context, ctx->enc);
+ goto fail;
+ }
+ break;
#if 0
case ENCTYPE_DES3_CBC_MD5:
enctype = ENCTYPE_DES3_CBC_RAW;
diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
index 9c718f0731..a8b10f6a5a 100644
--- a/src/lib/gssapi/krb5/k5seal.c
+++ b/src/lib/gssapi/krb5/k5seal.c
@@ -48,6 +48,8 @@
#include "gssapiP_krb5.h"
+#include <assert.h>
+
static krb5_error_code
make_seal_token_v1 (krb5_context context,
krb5_keyblock *enc,
@@ -70,82 +72,67 @@ make_seal_token_v1 (krb5_context context,
krb5_data plaind;
krb5_checksum md5cksum;
krb5_checksum cksum;
- int conflen=0, tmsglen, tlen;
+ /* msglen contains the message length
+ * we are signing/encrypting. tmsglen
+ * contains the length of the message
+ * we plan to write out to the token.
+ * tlen is the length of the token
+ * including header. */
+ unsigned conflen=0, tmsglen, tlen, msglen;
unsigned char *t, *ptr;
+ unsigned char *plain;
+ unsigned char pad;
+ krb5_keyusage sign_usage = KG_USAGE_SIGN;
- int encblksize, sumblksize;
-
- switch (signalg) {
- case SGN_ALG_DES_MAC_MD5:
- case SGN_ALG_MD2_5:
- case SGN_ALG_HMAC_MD5:
- sumblksize = 1;
- break;
- case SGN_ALG_DES_MAC:
- sumblksize = 8;
- break;
- case SGN_ALG_HMAC_SHA1_DES3_KD:
- sumblksize = 1;
- break;
- default:
- abort ();
- return 123; /* find error code */
- }
-
- switch (sealalg) {
- case SEAL_ALG_NONE:
- case SEAL_ALG_DES:
- case SEAL_ALG_DES3KD:
- encblksize = 8;
- break;
- default:
- abort ();
- return 12345654;
- }
+ assert((!encrypt) || (toktype == KG_TOK_SEAL_MSG));
/* create the token buffer */
-
+ /* Do we need confounder? */
+ if (encrypt || (!bigend && (toktype == KG_TOK_SEAL_MSG)))
+ conflen = kg_confounder_size(context, enc);
+ else conflen = 0;
if (toktype == KG_TOK_SEAL_MSG) {
- if (bigend && !encrypt) {
- tmsglen = text->length;
- } else {
- conflen = kg_confounder_size(context, enc);
- /* XXX knows that des block size is 8 */
- tmsglen = (conflen+text->length+8)&(~7);
- }
+ switch (sealalg) {
+ case SEAL_ALG_MICROSOFT_RC4:
+ msglen = conflen + text->length+1;
+ pad = 1;
+ break;
+ default:
+ /* XXX knows that des block size is 8 */
+ msglen = (conflen+text->length+8)&(~7);
+ pad = 8-(text->length%8);
+ }
+ tmsglen = msglen;
} else {
- tmsglen = 0;
+ tmsglen = 0;
+ msglen = text->length;
+ pad = 0;
}
-
tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
- return(ENOMEM);
+ return(ENOMEM);
/*** fill in the token */
ptr = t;
-
g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype);
/* 0..1 SIGN_ALG */
-
ptr[0] = signalg & 0xff;
ptr[1] = (signalg >> 8) & 0xff;
/* 2..3 SEAL_ALG or Filler */
-
if ((toktype == KG_TOK_SEAL_MSG) && encrypt) {
- ptr[2] = sealalg & 0xff;
- ptr[3] = (sealalg >> 8) & 0xff;
+ ptr[2] = sealalg & 0xff;
+ ptr[3] = (sealalg >> 8) & 0xff;
} else {
- /* No seal */
- ptr[2] = 0xff;
- ptr[3] = 0xff;
+ /* No seal */
+ ptr[2] = 0xff;
+ ptr[3] = 0xff;
}
/* 4..5 Filler */
-
ptr[4] = 0xff;
ptr[5] = 0xff;
@@ -155,145 +142,100 @@ make_seal_token_v1 (krb5_context context,
switch (signalg) {
case SGN_ALG_DES_MAC_MD5:
case SGN_ALG_MD2_5:
- case SGN_ALG_HMAC_MD5:
- md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
- break;
+ md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
+ break;
case SGN_ALG_HMAC_SHA1_DES3_KD:
- md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
- break;
+ md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
+ break;
+ case SGN_ALG_HMAC_MD5:
+ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+ if (!encrypt)
+ sign_usage = 15;
+ break;
default:
case SGN_ALG_DES_MAC:
- abort ();
+ abort ();
}
code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
if (code)
- return(code);
+ return(code);
md5cksum.length = sumlen;
- if (toktype == KG_TOK_SEAL_MSG) {
- unsigned char *plain;
- unsigned char pad;
-
- if (!bigend || encrypt) {
- if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
- xfree(t);
- return(ENOMEM);
- }
-
- if ((code = kg_make_confounder(context, enc, plain))) {
- xfree(plain);
- xfree(t);
- return(code);
- }
-
- memcpy(plain+conflen, text->value, text->length);
- /* XXX 8 is DES cblock size */
- pad = 8-(text->length%8);
-
- memset(plain+conflen+text->length, pad, pad);
- } else {
- /* plain is never used in the bigend && !encrypt case */
- plain = NULL;
- }
-
- if (encrypt) {
- if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL,
- (krb5_pointer) plain,
- (krb5_pointer) (ptr+cksum_size+14),
- tmsglen))) {
- if (plain)
- xfree(plain);
- xfree(t);
- return(code);
- }
- } else {
- if (bigend)
- memcpy(ptr+14+cksum_size, text->value, text->length);
- else
- memcpy(ptr+14+cksum_size, plain, tmsglen);
- }
+ if ((plain = (unsigned char *) xmalloc(msglen)) == NULL) {
+ xfree(t);
+ return(ENOMEM);
+ }
- /* compute the checksum */
+ if (conflen) {
+ if ((code = kg_make_confounder(context, enc, plain))) {
+ xfree(plain);
+ xfree(t);
+ return(code);
+ }
+ }
- /* 8 = head of token body as specified by mech spec */
- if (! (data_ptr =
- (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) {
- if (plain)
- xfree(plain);
- xfree(t);
- return(ENOMEM);
- }
- (void) memcpy(data_ptr, ptr-2, 8);
- if (bigend)
- (void) memcpy(data_ptr+8, text->value, text->length);
- else
- (void) memcpy(data_ptr+8, plain, tmsglen);
- plaind.length = 8 + (bigend ? text->length : tmsglen);
- plaind.data = data_ptr;
- code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
- KG_USAGE_SIGN, &plaind, &md5cksum);
- xfree(data_ptr);
-
- if (code) {
- if (plain)
- xfree(plain);
- xfree(t);
- return(code);
- }
+ memcpy(plain+conflen, text->value, text->length);
+ memset(plain+conflen+text->length, pad, pad);
- if (plain)
- xfree(plain);
- } else {
- /* Sign only. */
/* compute the checksum */
- if (! (data_ptr = (char *) xmalloc(8 + text->length))) {
- xfree(t);
- return(ENOMEM);
- }
- (void) memcpy(data_ptr, ptr-2, 8);
- (void) memcpy(data_ptr+8, text->value, text->length);
- plaind.length = 8 + text->length;
- plaind.data = data_ptr;
- code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
- KG_USAGE_SIGN, &plaind, &md5cksum);
- xfree(data_ptr);
- if (code) {
- xfree(t);
- return(code);
- }
+ /* 8 = head of token body as specified by mech spec */
+ if (! (data_ptr =
+ (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) {
+ xfree(plain);
+ xfree(t);
+ return(ENOMEM);
}
+ (void) memcpy(data_ptr, ptr-2, 8);
+ if (bigend)
+ (void) memcpy(data_ptr+8, text->value, text->length);
+ else
+ (void) memcpy(data_ptr+8, plain, msglen);
+ plaind.length = 8 + (bigend ? text->length : msglen);
+ plaind.data = data_ptr;
+ code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
+ sign_usage, &plaind, &md5cksum);
+ xfree(data_ptr);
+ if (code) {
+ xfree(plain);
+ xfree(t);
+ return(code);
+ }
switch(signalg) {
case SGN_ALG_DES_MAC_MD5:
case 3:
- if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL,
- (g_OID_equal(oid, gss_mech_krb5_old) ?
- seq->contents : NULL),
- md5cksum.contents, md5cksum.contents, 16))) {
- krb5_free_checksum_contents(context, &md5cksum);
- xfree(t);
- return code;
- }
+ if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL,
+ (g_OID_equal(oid, gss_mech_krb5_old) ?
+ seq->contents : NULL),
+ md5cksum.contents, md5cksum.contents, 16))) {
+ krb5_free_checksum_contents(context, &md5cksum);
+ xfree (plain);
+ xfree(t);
+ return code;
+ }
- cksum.length = cksum_size;
- cksum.contents = md5cksum.contents + 16 - cksum.length;
+ cksum.length = cksum_size;
+ cksum.contents = md5cksum.contents + 16 - cksum.length;
- memcpy(ptr+14, cksum.contents, cksum.length);
- break;
+ memcpy(ptr+14, cksum.contents, cksum.length);
+ break;
case SGN_ALG_HMAC_SHA1_DES3_KD:
- /*
- * Using key derivation, the call to krb5_c_make_checksum
- * already dealt with encrypting.
- */
- if (md5cksum.length != cksum_size)
- abort ();
- memcpy (ptr+14, md5cksum.contents, md5cksum.length);
- break;
+ /*
+ * Using key derivation, the call to krb5_c_make_checksum
+ * already dealt with encrypting.
+ */
+ if (md5cksum.length != cksum_size)
+ abort ();
+ memcpy (ptr+14, md5cksum.contents, md5cksum.length);
+ break;
+ case SGN_ALG_HMAC_MD5:
+ memcpy (ptr+14, md5cksum.contents, cksum_size);
+ break;
}
krb5_free_checksum_contents(context, &md5cksum);
@@ -302,9 +244,61 @@ make_seal_token_v1 (krb5_context context,
if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum,
ptr+14, ptr+6))) {
- xfree(t);
- return(code);
+ xfree (plain);
+ xfree(t);
+ return(code);
+ }
+
+ if (encrypt) {
+ switch(sealalg) {
+ case SEAL_ALG_MICROSOFT_RC4:
+ {
+ unsigned char bigend_seqnum[4];
+ krb5_keyblock *enc_key;
+ int i;
+ bigend_seqnum[0] = (*seqnum>>24) & 0xff;
+ bigend_seqnum[1] = (*seqnum>>16) & 0xff;
+ bigend_seqnum[2] = (*seqnum>>8) & 0xff;
+ bigend_seqnum[3] = *seqnum & 0xff;
+ code = krb5_copy_keyblock (context, enc, &enc_key);
+ if (code)
+ {
+ xfree(plain);
+ xfree(t);
+ return(code);
+ }
+ assert (enc_key->length == 16);
+ for (i = 0; i <= 15; i++)
+ ((char *) enc_key->contents)[i] ^=0xf0;
+ code = kg_arcfour_docrypt (enc_key, 0,
+ bigend_seqnum, 4,
+ plain, tmsglen,
+ ptr+14+cksum_size);
+ krb5_free_keyblock (context, enc_key);
+ if (code)
+ {
+ xfree(plain);
+ xfree(t);
+ return(code);
+ }
+ }
+ break;
+ default:
+ if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL,
+ (krb5_pointer) plain,
+ (krb5_pointer) (ptr+cksum_size+14),
+ tmsglen))) {
+ xfree(plain);
+ xfree(t);
+ return(code);
+ }
+ }
+ }else {
+ if (tmsglen)
+ memcpy(ptr+14+cksum_size, plain, tmsglen);
}
+ xfree(plain);
+
/* that's it. return the token */
diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
index 8d77c40245..9980688846 100644
--- a/src/lib/gssapi/krb5/k5unseal.c
+++ b/src/lib/gssapi/krb5/k5unseal.c
@@ -1,4 +1,5 @@
/*
+ * Copyright2001 by the Massachusetts Institute of Technology.
* Copyright 1993 by OpenVision Technologies, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
@@ -50,6 +51,7 @@
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
+#include <assert.h>
/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
conf_state is only valid if SEAL. */
@@ -85,6 +87,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
krb5_int32 seqnum;
OM_uint32 retval;
size_t sumlen;
+ krb5_keyusage sign_usage = KG_USAGE_SIGN;
if (toktype == KG_TOK_SEAL_MSG) {
message_buffer->length = 0;
@@ -125,7 +128,9 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
(ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
(ctx->sealalg == SEAL_ALG_DES3KD &&
- signalg != SGN_ALG_HMAC_SHA1_DES3_KD)) {
+ signalg != SGN_ALG_HMAC_SHA1_DES3_KD)||
+ (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 &&
+ signalg != SGN_ALG_HMAC_MD5)) {
*minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
@@ -133,8 +138,11 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
switch (signalg) {
case SGN_ALG_DES_MAC_MD5:
case SGN_ALG_MD2_5:
+ case SGN_ALG_HMAC_MD5:
cksum_len = 8;
- break;
+ if (toktype != KG_TOK_SEAL_MSG)
+ sign_usage = 15;
+ break;
case SGN_ALG_3:
cksum_len = 16;
break;
@@ -151,6 +159,12 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
/* get the token parameters */
+ if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
+ &seqnum))) {
+ *minor_status = code;
+ return(GSS_S_BAD_SIG);
+ }
+
/* decode the message, if SEAL */
if (toktype == KG_TOK_SEAL_MSG) {
@@ -159,10 +173,36 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
-
- if ((code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL,
- ptr+14+cksum_len, plain, tmsglen))) {
- xfree(plain);
+ if (ctx->enc->enctype == ENCTYPE_ARCFOUR_HMAC) {
+ unsigned char bigend_seqnum[4];
+ krb5_keyblock *enc_key;
+ int i;
+ bigend_seqnum[0] = (seqnum>>24) & 0xff;
+ bigend_seqnum[1] = (seqnum>>16) & 0xff;
+ bigend_seqnum[2] = (seqnum>>8) & 0xff;
+ bigend_seqnum[3] = seqnum & 0xff;
+ code = krb5_copy_keyblock (context, ctx->enc, &enc_key);
+ if (code)
+ {
+ xfree(plain);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ assert (enc_key->length == 16);
+ for (i = 0; i <= 15; i++)
+ ((char *) enc_key->contents)[i] ^=0xf0;
+ code = kg_arcfour_docrypt (enc_key, 0,
+ &bigend_seqnum[0], 4,
+ ptr+14+cksum_len, tmsglen,
+ plain);
+ krb5_free_keyblock (context, enc_key);
+ } else {
+ code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL,
+ ptr+14+cksum_len, plain, tmsglen);
+ }
+ if (code) {
+ xfree(plain);
*minor_status = code;
return(GSS_S_FAILURE);
}
@@ -205,11 +245,13 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
switch (signalg) {
case SGN_ALG_DES_MAC_MD5:
case SGN_ALG_MD2_5:
- case SGN_ALG_HMAC_MD5:
case SGN_ALG_DES_MAC:
case SGN_ALG_3:
md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
break;
+ case SGN_ALG_HMAC_MD5:
+ md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+ break;
case SGN_ALG_HMAC_SHA1_DES3_KD:
md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
break;
@@ -249,7 +291,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
plaind.data = data_ptr;
code = krb5_c_make_checksum(context, md5cksum.checksum_type,
- ctx->seq, KG_USAGE_SIGN,
+ ctx->seq, sign_usage,
&plaind, &md5cksum);
xfree(data_ptr);
@@ -316,7 +358,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
plaind.data = data_ptr;
krb5_free_checksum_contents(context, &md5cksum);
code = krb5_c_make_checksum(context, md5cksum.checksum_type,
- ctx->seq, KG_USAGE_SIGN,
+ ctx->seq, sign_usage,
&plaind, &md5cksum);
xfree(data_ptr);
@@ -337,6 +379,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
return(GSS_S_DEFECTIVE_TOKEN);
case SGN_ALG_HMAC_SHA1_DES3_KD:
+ case SGN_ALG_HMAC_MD5:
/* compute the checksum of the message */
/* 8 = bytes of token body to be checksummed according to spec */
@@ -361,7 +404,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
plaind.data = data_ptr;
code = krb5_c_make_checksum(context, md5cksum.checksum_type,
- ctx->seq, KG_USAGE_SIGN,
+ ctx->seq, sign_usage,
&plaind, &md5cksum);
xfree(data_ptr);
@@ -372,7 +415,7 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
return(GSS_S_FAILURE);
}
- code = memcmp(md5cksum.contents, ptr+14, md5cksum.length);
+ code = memcmp(md5cksum.contents, ptr+14, cksum_len);
break;
}
@@ -413,14 +456,6 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
/* do sequencing checks */
- if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
- &seqnum))) {
- if (toktype == KG_TOK_SEAL_MSG)
- xfree(token.value);
- *minor_status = code;
- return(GSS_S_BAD_SIG);
- }
-
if ((ctx->initiate && direction != 0xff) ||
(!ctx->initiate && direction != 0)) {
if (toktype == KG_TOK_SEAL_MSG)
diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
index a08b919828..424da90b3c 100644
--- a/src/lib/gssapi/krb5/util_crypt.c
+++ b/src/lib/gssapi/krb5/util_crypt.c
@@ -1,4 +1,5 @@
/*
+ * Copyright2001 by the Massachusetts Institute of Technology.
* Copyright 1993 by OpenVision Technologies, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
@@ -59,7 +60,9 @@ kg_confounder_size(context, key)
{
krb5_error_code code;
size_t blocksize;
-
+ /* We special case rc4*/
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC)
+ return 8;
code = krb5_c_block_size(context, key->enctype, &blocksize);
if (code)
return(-1); /* XXX */
@@ -189,3 +192,65 @@ kg_decrypt(context, key, usage, iv, in, out, length)
free(pivd->data);
return code;
}
+
+krb5_error_code
+kg_arcfour_docrypt (const krb5_keyblock *longterm_key , int ms_usage,
+ const unsigned char *kd_data, size_t kd_data_len,
+ const unsigned char *input_buf, size_t input_len,
+ unsigned char *output_buf)
+{
+ krb5_error_code code;
+ krb5_data input, output;
+ krb5int_access kaccess;
+ krb5_keyblock seq_enc_key, usage_key;
+ unsigned char t[4];
+
+ usage_key.length = longterm_key->length;
+ usage_key.contents = malloc(usage_key.length);
+ if (usage_key.contents == NULL)
+ return (ENOMEM);
+ seq_enc_key.length = longterm_key->length;
+ seq_enc_key.contents = malloc(seq_enc_key.length);
+ if (seq_enc_key.contents == NULL) {
+ free ((void *) usage_key.contents);
+ return (ENOMEM);
+ }
+ code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
+ if (code)
+ goto cleanup_arcfour;
+
+ t[0] = ms_usage &0xff;
+ t[1] = (ms_usage>>8) & 0xff;
+ t[2] = (ms_usage>>16) & 0xff;
+ t[3] = (ms_usage>>24) & 0xff;
+ input.data = (void *) &t;
+ input.length = 4;
+ output.data = (void *) usage_key.contents;
+ output.length = usage_key.length;
+ code = (*kaccess.krb5_hmac) (kaccess.md5_hash_provider,
+ longterm_key, 1, &input, &output);
+ if (code)
+ goto cleanup_arcfour;
+
+ input.data = ( void *) kd_data;
+ input.length = kd_data_len;
+ output.data = (void *) seq_enc_key.contents;
+ code = (*kaccess.krb5_hmac) (kaccess.md5_hash_provider,
+ &usage_key, 1, &input, &output);
+ if (code)
+ goto cleanup_arcfour;
+ input.data = ( void * ) input_buf;
+ input.length = input_len;
+ output.data = (void * ) output_buf;
+ output.length = input_len;
+ code = ((*kaccess.arcfour_enc_provider->encrypt)(
+ &seq_enc_key, 0,
+ &input, &output));
+ cleanup_arcfour:
+ memset ((void *) seq_enc_key.contents, 0, seq_enc_key.length);
+ memset ((void *) usage_key.contents, 0, usage_key.length);
+ free ((void *) usage_key.contents);
+ free ((void *) seq_enc_key.contents);
+ return (code);
+}
+
diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c
index 7c52c7fa74..4b44b8e5c8 100644
--- a/src/lib/gssapi/krb5/util_seqnum.c
+++ b/src/lib/gssapi/krb5/util_seqnum.c
@@ -1,4 +1,5 @@
/*
+ * Copyright2001 by the Massachusetts Institute of Technology.
* Copyright 1993 by OpenVision Technologies, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
@@ -21,6 +22,7 @@
*/
#include "gssapiP_krb5.h"
+#include "k5-int.h"
/*
* $Id$
@@ -37,15 +39,27 @@ kg_make_seq_num(context, key, direction, seqnum, cksum, buf)
{
unsigned char plain[8];
- plain[0] = (unsigned char) (seqnum&0xff);
- plain[1] = (unsigned char) ((seqnum>>8)&0xff);
- plain[2] = (unsigned char) ((seqnum>>16)&0xff);
- plain[3] = (unsigned char) ((seqnum>>24)&0xff);
-
plain[4] = direction;
plain[5] = direction;
plain[6] = direction;
plain[7] = direction;
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC ) {
+ /* Yes, Microsoft used big-endian sequence number.*/
+ plain[0] = (seqnum>>24) & 0xff;
+ plain[1] = (seqnum>>16) & 0xff;
+ plain[2] = (seqnum>>8) & 0xff;
+ plain[3] = seqnum & 0xff;
+ return kg_arcfour_docrypt (key, 0,
+ cksum, 8,
+ &plain[0], 8,
+ buf);
+
+ }
+
+ plain[0] = (unsigned char) (seqnum&0xff);
+ plain[1] = (unsigned char) ((seqnum>>8)&0xff);
+ plain[2] = (unsigned char) ((seqnum>>16)&0xff);
+ plain[3] = (unsigned char) ((seqnum>>24)&0xff);
return(kg_encrypt(context, key, KG_USAGE_SEQ, cksum, plain, buf, 8));
}
@@ -61,7 +75,14 @@ krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum)
krb5_error_code code;
unsigned char plain[8];
- code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8);
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC) {
+ code = kg_arcfour_docrypt (key, 0,
+ cksum, 8,
+ buf, 8,
+ plain);
+ } else {
+ code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8);
+ }
if (code)
return(code);
@@ -71,11 +92,14 @@ krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum)
return((krb5_error_code) KG_BAD_SEQ);
*direction = plain[4];
-
- *seqnum = ((plain[0]) |
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC) {
+ *seqnum = (plain[3]|(plain[2]<<8) | (plain[1]<<16)| (plain[0]<<24));
+ } else {
+ *seqnum = ((plain[0]) |
(plain[1]<<8) |
(plain[2]<<16) |
(plain[3]<<24));
+ }
return(0);
}
diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog
index fdb247c6ee..2926e6994c 100644
--- a/src/lib/krb5/os/ChangeLog
+++ b/src/lib/krb5/os/ChangeLog
@@ -1,3 +1,7 @@
+2001-10-24 Sam Hartman <hartmans@mit.edu>
+
+ * accessor.c (krb5int_accessor): Add fields for struct version 4
+
2001-10-17 Ken Raeburn <raeburn@mit.edu>
* locate_kdc.c (add_host_to_list): If sa_len field exists and is
diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c
index 64fd5089c7..5e77051a61 100644
--- a/src/lib/krb5/os/accessor.c
+++ b/src/lib/krb5/os/accessor.c
@@ -44,6 +44,9 @@ krb5int_accessor(internals, version)
internals_temp.krb5_skdc_timeout_shift = krb5_skdc_timeout_shift;
internals_temp.krb5_skdc_timeout_1 = krb5_skdc_timeout_1;
internals_temp.krb5_max_dgram_size = krb5_max_dgram_size;
+ internals_temp.krb5_hmac = krb5_hmac;
+ internals_temp.md5_hash_provider = &krb5int_hash_md5;
+ internals_temp.arcfour_enc_provider = &krb5int_enc_arcfour;
*internals = internals_temp;
return 0;
}