[1038] in Kerberos_V5_Development
3-des patches for GSSAPI
daemon@ATHENA.MIT.EDU (Richard Basch)
Thu Mar 28 19:55:12 1996
Date: Thu, 28 Mar 1996 19:51:44 -0500
To: krbdev@MIT.EDU
From: "Richard Basch" <basch@lehman.com>
Please review and incorporate them into the tree, if appropriate. I did
notice that DES-MAC-MD5 was not behaving according to spec, as I
previously mentioned.
--- 1.1 1996/03/28 04:04:38
+++ src/lib/gssapi/krb5/ChangeLog 1996/03/29 00:48:25
@@ -1,3 +1,12 @@
+Thu Mar 28 11:47:26 1996 Richard Basch <basch@lehman.com>
+
+ * k5unseal.c, k5seal.c:
+ Implemented a DES3 checksum algorithm (MD5 DES3-MAC)
+ Also, DES MAC MD5 did not follow spec by using a zero ivec.
+
+ * init_sec_context.c, accept_sec_context.c:
+ Allow for DES3_CBC_MD5 credentials to be used.
+
Wed Mar 20 20:25:53 1996 Theodore Y. Ts'o <tytso@dcl>
* rel_oid.c (krb5_gss_release_oid): Don't compile this procedure,
--- 1.1 1996/03/28 05:18:31
+++ src/lib/gssapi/krb5/k5seal.c 1996/03/29 00:38:39
@@ -38,8 +38,11 @@
int bigend;
{
krb5_error_code code;
+ krb5_cksumtype cksum_type;
MD5_CTX md5;
- krb5_checksum desmac;
+ krb5_enctype enctype;
+ krb5_checksum cksum;
+ int cksum_size;
int tmsglen, tlen;
unsigned char *t, *ptr;
@@ -54,7 +57,21 @@
tmsglen = 0;
}
- tlen = g_token_size((gss_OID) gss_mech_krb5, 22+tmsglen);
+ enctype = krb5_eblock_enctype(context, &enc_ed->eblock);
+ switch(enctype) {
+ case ENCTYPE_DES_CBC_RAW:
+ cksum_type = 0;
+ cksum_size = 8;
+ break;
+ case ENCTYPE_DES3_CBC_RAW:
+ cksum_type = 3;
+ cksum_size = 8;
+ break;
+ default:
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+
+ tlen = g_token_size((gss_OID) gss_mech_krb5, 14+cksum_size+tmsglen);
if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
return(ENOMEM);
@@ -63,25 +80,36 @@
ptr = t;
- g_make_token_header((gss_OID) gss_mech_krb5, 22+tmsglen, &ptr, toktype);
+ g_make_token_header((gss_OID) gss_mech_krb5,
+ 14+cksum_size+tmsglen, &ptr, toktype);
- /* for now, only generate DES integrity */
+ /* 0..1 SIGN_ALG */
- ptr[0] = 0;
+ ptr[0] = cksum_type;
ptr[1] = 0;
+
+ /* 2..3 SEAL_ALG or Filler */
- /* SEAL_ALG, or filler */
-
- if (((toktype == KG_TOK_SEAL_MSG) ||
- (toktype == KG_TOK_WRAP_MSG)) && encrypt) {
- ptr[2] = 0;
- ptr[3] = 0;
+ if (!encrypt ||
+ ((toktype != KG_TOK_SEAL_MSG) && (toktype != KG_TOK_WRAP_MSG)))
+ {
+ /* No seal */
+ ptr[2] = 0xff;
+ ptr[3] = 0xff;
} else {
- ptr[2] = 0xff;
- ptr[3] = 0xff;
+ switch(enctype) {
+ case ENCTYPE_DES_CBC_RAW:
+ ptr[2] = 0; ptr[3] = 0;
+ break;
+ case ENCTYPE_DES3_CBC_RAW:
+ ptr[2] = 1; ptr[3] = 0;
+ break;
+ default:
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
}
- /* filler */
+ /* 4..5 Filler */
ptr[4] = 0xff;
ptr[5] = 0xff;
@@ -111,53 +139,58 @@
if (encrypt) {
if (code = kg_encrypt(enc_ed, NULL, (krb5_pointer) plain,
- (krb5_pointer) (ptr+22), tmsglen)) {
+ (krb5_pointer) (ptr+14+cksum_size), tmsglen)) {
xfree(plain);
xfree(t);
return(code);
}
} else {
if (bigend)
- memcpy(ptr+22, text->value, text->length);
+ memcpy(ptr+14+cksum_size, text->value, text->length);
else
- memcpy(ptr+22, plain, tmsglen);
+ memcpy(ptr+14+cksum_size, plain, tmsglen);
}
- /* compute the checksum */
-
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *) ptr-2, 8);
- if (bigend)
- MD5Update(&md5, text->value, text->length);
- else
- MD5Update(&md5, plain, tmsglen);
- MD5Final(&md5);
-
xfree(plain);
- } else {
- /* compute the checksum */
-
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *) ptr-2, 8);
- MD5Update(&md5, text->value, text->length);
- MD5Final(&md5);
}
- /* XXX this depends on the key being a single-des key, but that's
- all that kerberos supports right now */
-
- if (code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC, md5.digest, 16,
+ switch(cksum_type) {
+ case 0:
+ case 3:
+ MD5Init(&md5);
+ MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ if (!bigend &&
+ ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)))
+ MD5Update(&md5, ptr+14+cksum_size, tmsglen);
+ else
+ MD5Update(&md5, text->value, text->length);
+ MD5Final(&md5);
+
+#if 0
+ code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC,
+ md5.digest, 16,
seq_ed->key->contents,
- seq_ed->key->length,
- &desmac)) {
- xfree(t);
- return(code);
+ seq_ed->key->length, &cksum);
+#endif
+ code = kg_encrypt(seq_ed, NULL, md5.digest, md5.digest, 16);
+
+ cksum.contents = (krb5_pointer)md5.digest + 8;
+ cksum.length = 8;
+
+ if (code) {
+ xfree(t);
+ return code;
+ }
+
+ break;
+ }
+
+ if (cksum.length != cksum_size) {
+ xfree(t);
+ return GSS_S_FAILURE;
}
-
- memcpy(ptr+14, desmac.contents, 8);
-
- /* XXX krb5_free_checksum_contents? */
- xfree(desmac.contents);
+
+ memcpy(ptr+14, cksum.contents, cksum.length);
/* create the seq_num */
@@ -276,7 +309,8 @@
/* Calculate the token size and subtract that from the output size */
cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
- ohlen = g_token_size((gss_OID) gss_mech_krb5, (unsigned int) cfsize + 22);
+ ohlen = g_token_size((gss_OID) gss_mech_krb5,
+ (unsigned int) cfsize + 14 + 8);
/* Cannot have trailer length that will cause us to pad over our length */
*input_size = (output_size - ohlen) & (~7);
--- 1.1 1996/03/28 04:04:38
+++ src/lib/gssapi/krb5/init_sec_context.c 1996/03/29 00:11:28
@@ -142,7 +142,7 @@
goto cleanup;
in_creds.times.endtime = *endtime;
- in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+
/*
* Get the credential..., I don't know in 0 is a good value for the
* kdcoptions
@@ -230,6 +230,7 @@
krb5_gss_cred_id_t cred;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
+ krb5_enctype enctype;
krb5_timestamp now;
gss_buffer_desc token;
int i;
@@ -350,20 +351,42 @@
/* fill in the encryption descriptors */
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ enctype = ENCTYPE_DES_CBC_RAW;
+ break;
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ break;
+ default:
+ return GSS_S_FAILURE;
+ }
+
/* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
- krb5_use_enctype(context, &ctx->enc.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->enc.eblock, enctype);
ctx->enc.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
return(code);
for (i=0; i<ctx->enc.key->length; i++)
/*SUPPRESS 113*/
ctx->enc.key->contents[i] ^= 0xf0;
+#if 0
+ if ((code = krb5_process_key(context, &ctx->enc.eblock, ctx->enc.key)))
+ return(code);
+ ctx->enc.processed = 1;
+#endif
- krb5_use_enctype(context, &ctx->seq.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->seq.eblock, enctype);
ctx->seq.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
return(code);
+#if 0
+ if ((code = krb5_process_key(context, &ctx->seq.eblock, ctx->seq.key)))
+ return(code);
+ ctx->seq.processed = 1;
+#endif
/* at this point, the context is constructed and valid,
hence, releaseable */
--- 1.1 1996/03/28 06:36:16
+++ src/lib/gssapi/krb5/k5unseal.c 1996/03/29 00:34:13
@@ -48,11 +48,13 @@
int sealalg;
gss_buffer_desc token;
unsigned char *ptr;
+ krb5_checksum cksum;
krb5_checksum desmac;
+ krb5_enctype enctype;
MD5_CTX md5;
- unsigned char *cksum;
krb5_timestamp now;
unsigned char *plain;
+ int cksum_len;
int plainlen;
if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
@@ -85,62 +87,106 @@
return(GSS_S_DEFECTIVE_TOKEN);
}
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
- tmsglen = bodysize-22;
-
/* get the sign and seal algorithms */
signalg = ptr[0] + (ptr[1]<<8);
sealalg = ptr[2] + (ptr[3]<<8);
- if (((signalg != 0) && (signalg != 1)) ||
- (((toktype != KG_TOK_SEAL_MSG) &&
- (toktype != KG_TOK_WRAP_MSG)) && (sealalg != 0xffff)) ||
- (((toktype == KG_TOK_SEAL_MSG) ||
- (toktype == KG_TOK_WRAP_MSG)) &&
- ((sealalg != 0xffff) && (sealalg != 0))) ||
- (ptr[4] != 0xff) ||
- (ptr[5] != 0xff)) {
- *minor_status = 0;
- return(GSS_S_DEFECTIVE_TOKEN);
+ /* Sanity checks */
+
+ if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ if ((sealalg != 0xffff) &&
+ (toktype != KG_TOK_SEAL_MSG) && (toktype != KG_TOK_WRAP_MSG)) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ enctype = krb5_eblock_enctype(context, &ctx->seq.eblock);
+
+ switch(sealalg) {
+ case 0xffff:
+ break;
+ case 0:
+ if (enctype != ENCTYPE_DES_CBC_RAW) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+ break;
+ case 1:
+ if (enctype != ENCTYPE_DES3_CBC_RAW) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+ break;
+ default:
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ switch(signalg) {
+ case 0:
+ case 1:
+ if (enctype != ENCTYPE_DES_CBC_RAW) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+ cksum_len = 8;
+ break;
+ case 3:
+ if (enctype != ENCTYPE_DES3_CBC_RAW) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+ cksum_len = 8;
+ break;
+ default:
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
}
+ if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ tmsglen = bodysize-14-cksum_len;
+
/* get the token parameters */
/* decode the message, if SEAL */
if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
- if (sealalg == 0) {
+ if (sealalg != 0xffff) {
if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
- if (code = kg_decrypt(&ctx->enc, NULL, ptr+22, plain, tmsglen)) {
+ if (code = kg_decrypt(&ctx->enc, NULL, ptr+14+cksum_len, plain, tmsglen)) {
xfree(plain);
*minor_status = code;
return(GSS_S_FAILURE);
}
} else {
- plain = ptr+22;
+ plain = ptr+14+cksum_len;
}
plainlen = tmsglen;
- if (sealalg && ctx->big_endian)
+ if ((sealalg == 0xffff) && ctx->big_endian)
token.length = tmsglen;
else
token.length = tmsglen - 8 - plain[tmsglen-1];
if (token.length) {
if ((token.value = xmalloc(token.length)) == NULL) {
- if (sealalg == 0)
+ if (sealalg != 0xffff)
xfree(plain);
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
- if (sealalg && ctx->big_endian)
+ if ((sealalg == 0xffff) && ctx->big_endian)
memcpy(token.value, plain, token.length);
else
memcpy(token.value, plain+8, token.length);
@@ -158,75 +204,84 @@
/* compute the checksum of the message */
- if (signalg == 0) {
- /* compute the checksum of the message */
-
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *) ptr-2, 8);
- if (ctx->big_endian)
- MD5Update(&md5, token.value, token.length);
- else
- MD5Update(&md5, plain, plainlen);
- MD5Final(&md5);
-
- if (sealalg == 0)
- xfree(plain);
-
- /* XXX this depends on the key being a single-des key, but that's
- all that kerberos supports right now */
-
- if (code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC, md5.digest,
- 16, ctx->seq.key->contents,
- ctx->seq.key->length,
- &desmac)) {
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
- xfree(token.value);
- *minor_status = code;
- return(GSS_S_FAILURE);
- }
-
- cksum = desmac.contents;
- } else {
- if (! ctx->seed_init) {
- if (code = kg_make_seed(ctx->subkey, ctx->seed)) {
- if (sealalg == 0)
+ switch (signalg) {
+ case 0xffff:
+ break;
+
+ case 0:
+ case 3:
+ MD5Init(&md5);
+ MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ if (ctx->big_endian)
+ MD5Update(&md5, token.value, token.length);
+ else
+ MD5Update(&md5, plain, plainlen);
+ MD5Final(&md5);
+
+ if (sealalg != 0xffff)
+ xfree(plain);
+
+#if 0
+ code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC,
+ md5.digest, 16,
+ ctx->seq.key->contents,
+ ctx->seq.key->length, &cksum);
+#endif
+ code = kg_encrypt(&ctx->seq, NULL, md5.digest, md5.digest, 16);
+
+ cksum.contents = (krb5_pointer)md5.digest + 8;
+ cksum.length = 8;
+
+ if (code) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ break;
+
+ case 1:
+ if (!ctx->seed_init && (code = kg_make_seed(ctx->subkey, ctx->seed))) {
+ if (sealalg != 0xffff)
xfree(plain);
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
xfree(token.value);
- *minor_status = code;
- return(GSS_S_FAILURE);
- }
- ctx->seed_init = 1;
- }
-
- MD5Init(&md5);
- MD5Update(&md5, ctx->seed, sizeof(ctx->seed));
- MD5Update(&md5, (unsigned char *) ptr-2, 8);
- if (ctx->big_endian)
- MD5Update(&md5, token.value, token.length);
- else
- MD5Update(&md5, plain, plainlen);
- MD5Final(&md5);
-
- if (sealalg == 0)
- xfree(plain);
-
- cksum = md5.digest;
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ MD5Init(&md5);
+ MD5Update(&md5, ctx->seed, sizeof(ctx->seed));
+ MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ if (ctx->big_endian)
+ MD5Update(&md5, token.value, token.length);
+ else
+ MD5Update(&md5, plain, plainlen);
+ MD5Final(&md5);
+
+ if (sealalg != 0xffff)
+ xfree(plain);
+
+ cksum.contents = md5.digest;
+ cksum.length = 8;
+ break;
+
+ default:
+ *minor_status = 0;
+ return GSS_S_FAILURE;
}
+
/* compare the computed checksum against the transmitted checksum */
- if (memcmp(cksum, ptr+14, 8) != 0) {
- if (signalg == 0)
- xfree(desmac.contents);
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
- xfree(token.value);
- *minor_status = 0;
- return(GSS_S_BAD_SIG);
- }
+ if ((signalg != 0xffff) &&
+ (memcmp(cksum.contents, ptr+14, cksum.length) != 0))
+ {
+ if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ xfree(token.value);
- if (signalg == 0)
- xfree(desmac.contents);
+ *minor_status = 0;
+ return GSS_S_BAD_SIG;
+ }
/* XXX this is where the seq_num check would go */
@@ -236,7 +291,7 @@
*message_buffer = token;
if (conf_state)
- *conf_state = (sealalg == 0);
+ *conf_state = (sealalg != 0xffff);
if (qop_state)
*qop_state = GSS_C_QOP_DEFAULT;
--- 1.1 1996/03/28 16:01:45
+++ src/lib/gssapi/krb5/accept_sec_context.c 1996/03/29 00:07:00
@@ -89,6 +89,7 @@
krb5_principal name;
int gss_flags;
krb5_gss_ctx_id_rec *ctx;
+ krb5_enctype enctype;
krb5_timestamp now;
gss_buffer_desc token;
krb5_auth_context auth_context = NULL;
@@ -344,20 +345,43 @@
return(GSS_S_FAILURE);
}
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ enctype = ENCTYPE_DES_CBC_RAW;
+ break;
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ break;
+ default:
+ return GSS_S_FAILURE;
+ }
+
/* fill in the encryption descriptors */
- krb5_use_enctype(context, &ctx->enc.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->enc.eblock, enctype);
ctx->enc.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
return(code);
for (i=0; i<ctx->enc.key->length; i++)
/*SUPPRESS 113*/
ctx->enc.key->contents[i] ^= 0xf0;
+#if 0
+ if ((code = krb5_process_key(context, &ctx->enc.eblock, ctx->enc.key)))
+ return(code);
+ ctx->enc.processed = 1;
+#endif
- krb5_use_enctype(context, &ctx->seq.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->seq.eblock, enctype);
ctx->seq.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
return(code);
+#if 0
+ if ((code = krb5_process_key(context, &ctx->seq.eblock, ctx->seq.key)))
+ return(code);
+ ctx->seq.processed = 1;
+#endif
+
ctx->endtime = ticket->enc_part2->times.endtime;
ctx->flags = ticket->enc_part2->flags;
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