* Expose some rc4 crypto routines through the accessor mechanism; cleaner than raw...
authorSam Hartman <hartmans@mit.edu>
Fri, 26 Oct 2001 05:50:25 +0000 (05:50 +0000)
committerSam Hartman <hartmans@mit.edu>
Fri, 26 Oct 2001 05:50:25 +0000 (05:50 +0000)
* 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

14 files changed:
src/include/ChangeLog
src/include/k5-int.h
src/lib/crypto/arcfour/ChangeLog
src/lib/crypto/arcfour/arcfour.c
src/lib/gssapi/krb5/ChangeLog
src/lib/gssapi/krb5/accept_sec_context.c
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/k5seal.c
src/lib/gssapi/krb5/k5unseal.c
src/lib/gssapi/krb5/util_crypt.c
src/lib/gssapi/krb5/util_seqnum.c
src/lib/krb5/os/ChangeLog
src/lib/krb5/os/accessor.c

index 8d18c2c414b5c1b16e0688951aae79703ed50156..958dc2ab54be34987a387aa7589f4146dccfe57a 100644 (file)
@@ -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
index 9f7a78ebae59e007caabf951900984ea24910d12..34fe737955d8bb5fe6a1b4ce429cb381710bc135 100644 (file)
@@ -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) | \
index 335304a9330c5a6026af456c70d2885101d32735..9f9cbc76a2e7b2764bba12427ac6b2637a268a48 100644 (file)
@@ -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
index cc1857770bc58e034798701d6e6e1612e5171df6..66c0bd3355e2c52cf1d0b585667028052f2fa4f6 100644 (file)
@@ -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;
 }
index e40b3fc1f4113eb226f327e2fb7c85d86bdad306..d5aa402f7f189def70f73b9d0b990364d9a52dda 100644 (file)
@@ -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.) 
 
+
+
+
+       
index a3d4a73374dde154e9eb9957e8f69ea8cd94aeb8..3cc291d80eddbcbe9a62c22263a43a88a5996fe1 100644 (file)
@@ -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;
index 634b9e6b8ba3f882170592cf80798fe9c70daef9..238ce2507c3b3b042d6d8cd2cab00c0d98a9903f 100644 (file)
@@ -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,
index a39372ff0d287fe8ec92849eab7a895b97978dca..6a88a4ebcf95850f56f62c9739c6518c2c19a036 100644 (file)
@@ -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;
index 9c718f0731f67f85818674b67bab175a5b185f42..a8b10f6a5a4675c9330f3f10e40d0486c84f8514 100644 (file)
@@ -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 */
 
index 8d77c40245d6af31ed5495f7307b0e9b2bd7a4ce..9980688846968715cdaeb8282899e75a05628197 100644 (file)
@@ -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)
index a08b9198286523ef87a0776d55b738c6ef067db2..424da90b3c5bd7398f8d1616306cd5caa8aa82ed 100644 (file)
@@ -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);
+}
+                   
index 7c52c7fa74c2824c7fa8a28d55c130acf4475400..4b44b8e5c898ed008edbe70dd2bd8b0e6181b619 100644 (file)
@@ -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);
 }
index fdb247c6ee24b452349fa3610b827a7d2ffbbb0a..2926e6994c045adcb521a6b20800f0ffa984b1ec 100644 (file)
@@ -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
index 64fd5089c76223552a8f6256307592abcc0f9d2d..5e77051a61410680b6f37bed9ab2974ba6f71d96 100644 (file)
@@ -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;
   }