[1038] in Kerberos_V5_Development

home help back first fref pref prev next nref lref last post

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


home help back first fref pref prev next nref lref last post