More work on krb5 crypto merge
authorLuke Howard <lukeh@padl.com>
Wed, 8 Sep 2010 10:23:35 +0000 (12:23 +0200)
committerLuke Howard <lukeh@padl.com>
Wed, 8 Sep 2010 10:23:35 +0000 (12:23 +0200)
Makefile.am
TODO [new file with mode: 0644]
gssapiP_eap.h
unwrap_iov.c
util.h [new file with mode: 0644]
util_cksum.c
util_context.c
util_crypt.c
wrap_iov.c

index 3a86451..1938056 100644 (file)
@@ -53,6 +53,7 @@ libmech_eap_la_SOURCES =                      \
        util_cred.c                             \
        util_crypt.c                            \
        util_name.c                             \
+       util_ordering.c                         \
        verify_mic.c                            \
        wrap.c                                  \
        wrap_iov.c                              \
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..7d185ab
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+- SAML
+- encoders
+- OID encoders
+- stream
index 128b0fe..b6e4b04 100644 (file)
@@ -53,6 +53,7 @@
 
 /* Kerberos includes */
 #include <krb5.h>
+#include "util.h"
 
 struct gss_name_struct {
     OM_uint32 flags;
@@ -135,88 +136,17 @@ struct gss_ctx_id_struct {
 #define TOK_FLAG_WRAP_CONFIDENTIAL          0x02
 #define TOK_FLAG_ACCEPTOR_SUBKEY            0x04
 
+#define KEY_USAGE_ACCEPTOR_SEAL             512
+#define KEY_USAGE_ACCEPTOR_SIGN             513
+#define KEY_USAGE_INITIATOR_SEAL            514
+#define KEY_USAGE_INITIATOR_SIGN            515
+
 enum gss_eap_token_type {
     TOK_TYPE_MIC     = 0x0404,
     TOK_TYPE_WRAP    = 0x0504,
     TOK_TYPE_DELETE  = 0x0405
 };
 
-/* Helper APIs */
-OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
-OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
-
-OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
-OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
-
-OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
-OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
-
-/* Kerberos token services */
-#define KRB_USAGE_ACCEPTOR_SEAL             22
-#define KRB_USAGE_ACCEPTOR_SIGN             23
-#define KRB_USAGE_INITIATOR_SEAL            24
-#define KRB_USAGE_INITIATOR_SIGN            25
-
-#if 0
-#define KRB_KEYTYPE(key)                    ((key)->keytype)
-#else
-#define KRB_KEYTYPE(key)                    ((key)->enctype)
-#endif
-
-/* util_crypt.c */
-int
-gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
-              size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv,
-              gss_iov_buffer_desc *iov, int iov_count);
-
-int
-gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
-              size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv,
-              gss_iov_buffer_desc *iov, int iov_count);
-
-krb5_cryptotype
-gssEapTranslateCryptoFlag(OM_uint32 type);
-
-gss_iov_buffer_t
-gssEapLocateIov(gss_iov_buffer_desc *iov,
-                int iov_count,
-                OM_uint32 type);
-
-void
-gssEapIovMessageLength(gss_iov_buffer_desc *iov,
-                       int iov_count,
-                       size_t *data_length,
-                       size_t *assoc_data_length);
-
-void
-gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count);
-
-int
-gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count);
-
-int
-gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
-
-/* util_cksum.c */
-int
-gssEapSign(krb5_context context,
-           krb5_cksumtype type,
-           size_t rrc,
-           krb5_keyblock *key,
-           krb5_keyusage sign_usage,
-           gss_iov_buffer_desc *iov,
-           int iov_count);
-
-int
-gssEapVerify(krb5_context context,
-             krb5_cksumtype type,
-             size_t rrc,  
-             krb5_keyblock *key,
-             krb5_keyusage sign_usage,
-             gss_iov_buffer_desc *iov,
-             int iov_count,
-             int *valid);
-
 /* wrap_iov.c */
 OM_uint32
 gssEapWrapOrGetMIC(OM_uint32 *minor,
@@ -236,17 +166,5 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
                         int iov_count,
                         enum gss_eap_token_type toktype);
 
-/* Helper macros */
-#define GSSEAP_CALLOC(count, size)      (calloc((count), (size)))
-#define GSSEAP_FREE(ptr)                (free((ptr)))
-#define GSSEAP_MALLOC(size)             (malloc((size)))
-#define GSSEAP_REALLOC(ptr, size)       (realloc((ptr), (size)))
-
-#define GSSEAP_NOT_IMPLEMENTED          do {            \
-        assert(0 && "not implemented");                 \
-        *minor = ENOSYS;                                \
-        return GSS_S_FAILURE;                           \
-    } while (0)
 
 #endif /* _GSSAPIP_EAP_H_ */
-
index 3cec4f0..45c4b25 100644 (file)
@@ -30,8 +30,6 @@
  * SUCH DAMAGE.
  */
 /*
- * lib/gssapi/krb5/k5sealv3iov.c
- *
  * Copyright 2008 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * M.I.T. makes no representations about the suitability of
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
- *
- *
  */
 
 #include "gssapiP_eap.h"
 
+/*
+ * Caller must provide TOKEN | DATA | PADDING | TRAILER, except
+ * for DCE in which case it can just provide TOKEN | DATA (must
+ * guarantee that DATA is padded)
+ */
 OM_uint32
-gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
-                        gss_ctx_id_t ctx,
-                        int *conf_state,
-                        gss_qop_t *qop_state,
-                        gss_iov_buffer_desc *iov,
-                        int iov_count,
-                        enum gss_eap_token_type toktype)
+unwrapToken(OM_uint32 *minor,
+            gss_ctx_id_t ctx,
+            int *conf_state,
+            gss_qop_t *qop_state,
+            gss_iov_buffer_desc *iov,
+            int iov_count,
+            enum gss_eap_token_type toktype)
 {
     OM_uint32 code;
     gss_iov_buffer_t header;
@@ -78,18 +79,15 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
     size_t rrc, ec;
     size_t data_length, assoc_data_length;
     uint64_t seqnum;
-    krb5_boolean valid;
+    int valid = 0;
     krb5_cksumtype cksumtype;
     int conf_flag = 0;
 
-    *minor_status = 0;
+    *minor = 0;
 
     if (qop_state != NULL)
         *qop_state = GSS_C_QOP_DEFAULT;
 
-    if (!CTX_IS_ESTABLISHED(ctx))
-        return GSS_S_NO_CONTEXT;
-
     header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
     assert(header != NULL);
 
@@ -102,18 +100,18 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
     acceptor_flag = CTX_IS_INITIATOR(ctx) ? TOK_FLAG_SENDER_IS_ACCEPTOR : 0;
     key_usage = (toktype == TOK_TYPE_WRAP
                  ? (!CTX_IS_INITIATOR(ctx)
-                    ? KRB_USAGE_INITIATOR_SEAL
-                    : KRB_USAGE_ACCEPTOR_SEAL)
+                    ? KEY_USAGE_INITIATOR_SEAL
+                    : KEY_USAGE_ACCEPTOR_SEAL)
                  : (!CTX_IS_INITIATOR(ctx)
-                    ? KRB_USAGE_INITIATOR_SIGN
-                    : KRB_USAGE_ACCEPTOR_SIGN));
+                    ? KEY_USAGE_INITIATOR_SIGN
+                    : KEY_USAGE_ACCEPTOR_SIGN));
 
     gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length);
 
     ptr = (unsigned char *)header->buffer.value;
 
     if (header->buffer.length < 16) {
-        *minor_status = 0;
+        *minor = 0;
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
@@ -128,14 +126,14 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
     if (toktype == TOK_TYPE_WRAP) {
         unsigned int k5_trailerlen;
 
-        if (load_16_be(ptr) != TOK_TYPE_WRAP)
+        if (load_uint16_be(ptr) != TOK_TYPE_WRAP)
             goto defective;
         conf_flag = ((ptr[2] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
         if (ptr[3] != 0xFF)
             goto defective;
-        ec = load_16_be(ptr + 4);
-        rrc = load_16_be(ptr + 6);
-        seqnum = load_64_be(ptr + 8);
+        ec = load_uint16_be(ptr + 4);
+        rrc = load_uint16_be(ptr + 6);
+        seqnum = load_uint64_be(ptr + 8);
 
         code = krb5_c_crypto_length(ctx->kerberosCtx,
                                     KRB_KEYTYPE(ctx->encryptionKey),
@@ -143,7 +141,7 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
                                     KRB5_CRYPTO_TYPE_CHECKSUM,
                                     &k5_trailerlen);
         if (code != 0) {
-            *minor_status = code;
+            *minor = code;
             return GSS_S_FAILURE;
         }
 
@@ -174,7 +172,7 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
                                  ec, rrc, ctx->encryptionKey,
                                  key_usage, 0, iov, iov_count);
             if (code != 0) {
-                *minor_status = code;
+                *minor = code;
                 return GSS_S_BAD_SIG;
             }
 
@@ -184,11 +182,11 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
             else
                 althdr = (unsigned char *)trailer->buffer.value + ec;
 
-            if (load_16_be(althdr) != TOK_TYPE_WRAP
+            if (load_uint16_be(althdr) != TOK_TYPE_WRAP
                 || althdr[2] != ptr[2]
                 || althdr[3] != ptr[3]
                 || memcmp(althdr + 8, ptr + 8, 8) != 0) {
-                *minor_status = 0;
+                *minor = 0;
                 return GSS_S_BAD_SIG;
             }
         } else {
@@ -197,45 +195,45 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
                 goto defective;
 
             /* Zero EC, RRC before computing checksum */
-            store_16_be(0, ptr + 4);
-            store_16_be(0, ptr + 6);
+            store_uint16_be(0, ptr + 4);
+            store_uint16_be(0, ptr + 6);
 
             code = gssEapVerify(ctx->kerberosCtx, cksumtype, rrc,
                                 ctx->encryptionKey, key_usage,
                                 iov, iov_count, &valid);
             if (code != 0 || valid == FALSE) {
-                *minor_status = code;
+                *minor = code;
                 return GSS_S_BAD_SIG;
             }
         }
 
-        code = g_order_check(&ctx->seqState, seqnum);
+        code = sequenceCheck(&ctx->seqState, seqnum);
     } else if (toktype == TOK_TYPE_MIC) {
-        if (load_16_be(ptr) != TOK_TYPE_MIC)
+        if (load_uint16_be(ptr) != TOK_TYPE_MIC)
             goto defective;
 
     verify_mic_1:
         if (ptr[3] != 0xFF)
             goto defective;
-        seqnum = load_64_be(ptr + 8);
+        seqnum = load_uint64_be(ptr + 8);
 
         code = gssEapVerify(ctx->kerberosCtx, cksumtype, 0,
                             ctx->encryptionKey, key_usage,
                             iov, iov_count, &valid);
         if (code != 0 || valid == FALSE) {
-            *minor_status = code;
+            *minor = code;
             return GSS_S_BAD_SIG;
         }
-        code = g_order_check(&ctx->seqState, seqnum);
+        code = sequenceCheck(&ctx->seqState, seqnum);
     } else if (toktype == TOK_TYPE_DELETE) {
-        if (load_16_be(ptr) != TOK_TYPE_DELETE)
+        if (load_uint16_be(ptr) != TOK_TYPE_DELETE)
             goto defective;
         goto verify_mic_1;
     } else {
         goto defective;
     }
 
-    *minor_status = 0;
+    *minor = 0;
 
     if (conf_state != NULL)
         *conf_state = conf_flag;
@@ -243,11 +241,242 @@ gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
     return code;
 
 defective:
-    *minor_status = 0;
+    *minor = 0;
 
     return GSS_S_DEFECTIVE_TOKEN;
 }
 
+int
+rotateLeft(void *ptr, size_t bufsiz, size_t rc)
+{
+    void *tbuf;
+
+    if (bufsiz == 0)
+        return 0;
+    rc = rc % bufsiz;
+    if (rc == 0)
+        return 0;
+
+    tbuf = GSSEAP_MALLOC(rc);
+    if (tbuf == NULL)
+        return ENOMEM;
+
+    memcpy(tbuf, ptr, rc);
+    memmove(ptr, (char *)ptr + rc, bufsiz - rc);
+    memcpy((char *)ptr + bufsiz - rc, tbuf, rc);
+    GSSEAP_FREE(tbuf);
+
+    return 0;
+}
+
+/*
+ * Split a STREAM | SIGN_DATA | DATA into
+ *         HEADER | SIGN_DATA | DATA | PADDING | TRAILER
+ */
+static OM_uint32
+unwrapStream(OM_uint32 *minor,
+             gss_ctx_id_t ctx,
+             int *conf_state,
+             gss_qop_t *qop_state,
+             gss_iov_buffer_desc *iov,
+             int iov_count,
+             enum gss_eap_token_type toktype)
+{
+    unsigned char *ptr;
+    OM_uint32 code = 0, major = GSS_S_FAILURE;
+    krb5_context context = ctx->kerberosCtx;
+    int conf_req_flag, toktype2;
+    int i = 0, j;
+    gss_iov_buffer_desc *tiov = NULL;
+    gss_iov_buffer_t stream, data = NULL;
+    gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer;
+
+    assert(toktype == TOK_TYPE_WRAP);
+
+    if (toktype != TOK_TYPE_WRAP || (ctx->gssFlags & GSS_C_DCE_STYLE)) {
+        code = EINVAL;
+        goto cleanup;
+    }
+
+    stream = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM);
+    assert(stream != NULL);
+
+    if (stream->buffer.length < 16) {
+        major = GSS_S_DEFECTIVE_TOKEN;
+        goto cleanup;
+    }
+
+    ptr = (unsigned char *)stream->buffer.value;
+    toktype2 = load_uint16_be(ptr);
+    ptr += 2;
+
+    tiov = (gss_iov_buffer_desc *)GSSEAP_CALLOC((size_t)iov_count + 2,
+                                                sizeof(gss_iov_buffer_desc));
+    if (tiov == NULL) {
+        code = ENOMEM;
+        goto cleanup;
+    }
+
+    /* HEADER */
+    theader = &tiov[i++];
+    theader->type = GSS_IOV_BUFFER_TYPE_HEADER;
+    theader->buffer.value = stream->buffer.value;
+    theader->buffer.length = 16;
+
+    /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */
+    for (j = 0; j < iov_count; j++) {
+        OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type);
+
+        if (type == GSS_IOV_BUFFER_TYPE_DATA) {
+            if (data != NULL) {
+                /* only a single DATA buffer can appear */
+                code = EINVAL;
+                goto cleanup;
+            }
+
+            data = &iov[j];
+            tdata = &tiov[i];
+        }
+        if (type == GSS_IOV_BUFFER_TYPE_DATA ||
+            type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
+            tiov[i++] = iov[j];
+    }
+
+    if (data == NULL) {
+        /* a single DATA buffer must be present */
+        code = EINVAL;
+        goto cleanup;
+    }
+
+    /* PADDING | TRAILER */
+    tpadding = &tiov[i++];
+    tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING;
+    tpadding->buffer.length = 0;
+    tpadding->buffer.value = NULL;
+
+    ttrailer = &tiov[i++];
+    ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER;
+
+    {
+        size_t ec, rrc;
+        unsigned int k5_headerlen = 0;
+        unsigned int k5_trailerlen = 0;
+
+        conf_req_flag = ((ptr[0] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
+        ec = conf_req_flag ? load_uint16_be(ptr + 2) : 0;
+        rrc = load_uint16_be(ptr + 4);
+
+        if (rrc != 0) {
+            code = rotateLeft((unsigned char *)stream->buffer.value + 16,
+                              stream->buffer.length - 16, rrc);
+            if (code != 0)
+                goto cleanup;
+            store_uint16_be(0, ptr + 4); /* set RRC to zero */
+        }
+
+        if (conf_req_flag) {
+            code = krb5_c_crypto_length(context, ctx->encryptionType,
+                                        KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen);
+            if (code != 0)
+                goto cleanup;
+            theader->buffer.length += k5_headerlen; /* length validated later */
+        }
+
+        /* no PADDING for CFX, EC is used instead */
+        code = krb5_c_crypto_length(context, ctx->encryptionType,
+                                    conf_req_flag
+                                      ? KRB5_CRYPTO_TYPE_TRAILER
+                                      : KRB5_CRYPTO_TYPE_CHECKSUM,
+                                    &k5_trailerlen);
+        if (code != 0)
+            goto cleanup;
+
+        ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) +
+                                  k5_trailerlen;
+        ttrailer->buffer.value = (unsigned char *)stream->buffer.value +
+            stream->buffer.length - ttrailer->buffer.length;
+    }
+
+    /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/
+    /* Old: GSS-Header | Conf        | Data  | Pad |                               */
+    /* CFX: GSS-Header | Kerb-Header | Data  |     | EC | E(Header) | Kerb-Trailer */
+    /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/
+
+    /* validate lengths */
+    if (stream->buffer.length < theader->buffer.length +
+        tpadding->buffer.length +
+        ttrailer->buffer.length) {
+        code = KRB5_BAD_MSIZE;
+        major = GSS_S_DEFECTIVE_TOKEN;
+        goto cleanup;
+    }
+
+    /* setup data */
+    tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length -
+        tpadding->buffer.length - theader->buffer.length;
+
+    assert(data != NULL);
+
+    if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
+        code = gssEapAllocIov(tdata, tdata->buffer.length);
+        if (code != 0)
+            goto cleanup;
+
+        memcpy(tdata->buffer.value,
+               (unsigned char *)stream->buffer.value + theader->buffer.length,
+               tdata->buffer.length);
+    } else {
+        tdata->buffer.value = (unsigned char *)stream->buffer.value +
+                              theader->buffer.length;
+    }
+
+    assert(i <= iov_count + 2);
+
+    major = unwrapToken(&code, ctx, conf_state, qop_state,
+                        tiov, i, toktype);
+    if (major == GSS_S_COMPLETE) {
+        *data = *tdata;
+    } else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
+        OM_uint32 tmp;
+
+        gss_release_buffer(&tmp, &tdata->buffer);
+        tdata->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
+    }
+
+cleanup:
+    if (tiov != NULL)
+        GSSEAP_FREE(tiov);
+
+    *minor = code;
+
+    return major;
+}
+
+OM_uint32
+gssEapUnwrapOrVerifyMIC(OM_uint32 *minor,
+                        gss_ctx_id_t ctx,
+                        int *conf_state,
+                        gss_qop_t *qop_state,
+                        gss_iov_buffer_desc *iov,
+                        int iov_count,
+                        enum gss_eap_token_type toktype)
+{
+    OM_uint32 major;
+
+    if (!CTX_IS_ESTABLISHED(ctx))
+        return GSS_S_NO_CONTEXT;
+
+    if (gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) {
+        major = unwrapStream(minor, ctx, conf_state, qop_state,
+                             iov, iov_count, toktype);
+    } else {
+        major = unwrapToken(minor, ctx, conf_state, qop_state,
+                            iov, iov_count, toktype);
+    }
+
+    return major;
+}
+
 OM_uint32
 gss_unwrap_iov(OM_uint32 *minor,
                gss_ctx_id_t ctx,
@@ -256,8 +485,6 @@ gss_unwrap_iov(OM_uint32 *minor,
                gss_iov_buffer_desc *iov,
                int iov_count)
 {
-    return gssEapUnwrapOrVerifyMIC(minor, ctx,
-                                   iov, iov_count, conf_state,
-                                   qop_state, TOK_TYPE_WRAP);
-
+    return gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
+                                   iov, iov_count, TOK_TYPE_WRAP);
 }
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..f062888
--- /dev/null
+++ b/util.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2010, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Portions Copyright 2003-2010 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#ifndef _UTIL_H_
+#define _UTIL_H_ 1
+
+/* Helper APIs */
+OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
+OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
+
+OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
+OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
+
+OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
+OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
+
+/* Kerberos token services */
+#define KRB_KEYTYPE(key)        ((key)->enctype)
+
+/* util_crypt.c */
+int
+gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
+              size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv,
+              gss_iov_buffer_desc *iov, int iov_count);
+
+int
+gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
+              size_t rrc, krb5_keyblock *key, int usage, krb5_pointer iv,
+              gss_iov_buffer_desc *iov, int iov_count);
+
+krb5_cryptotype
+gssEapMapCryptoFlag(OM_uint32 type);
+
+gss_iov_buffer_t
+gssEapLocateIov(gss_iov_buffer_desc *iov,
+                int iov_count,
+                OM_uint32 type);
+
+void
+gssEapIovMessageLength(gss_iov_buffer_desc *iov,
+                       int iov_count,
+                       size_t *data_length,
+                       size_t *assoc_data_length);
+
+void
+gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count);
+
+int
+gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count);
+
+int
+gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
+
+/* util_cksum.c */
+int
+gssEapSign(krb5_context context,
+           krb5_cksumtype type,
+           size_t rrc,
+           krb5_keyblock *key,
+           krb5_keyusage sign_usage,
+           gss_iov_buffer_desc *iov,
+           int iov_count);
+
+int
+gssEapVerify(krb5_context context,
+             krb5_cksumtype type,
+             size_t rrc,  
+             krb5_keyblock *key,
+             krb5_keyusage sign_usage,
+             gss_iov_buffer_desc *iov,
+             int iov_count,
+             int *valid);
+
+/* util_ordering.c */
+int
+sequenceInternalize(void **vqueue, unsigned char **buf, size_t *lenremain);
+
+int
+sequenceExternalize(void *vqueue, unsigned char **buf, size_t *lenremain);
+
+int
+sequenceSize(void *vqueue, size_t *sizep);
+
+void
+sequenceFree(void **vqueue);
+
+int
+sequenceCheck(void **vqueue, uint64_t seqnum);
+
+int
+sequenceInit(void **vqueue, uint64_t seqnum,
+             int do_replay, int do_sequence, int wide_nums);
+
+/* Helper macros */
+#define GSSEAP_CALLOC(count, size)      (calloc((count), (size)))
+#define GSSEAP_FREE(ptr)                (free((ptr)))
+#define GSSEAP_MALLOC(size)             (malloc((size)))
+#define GSSEAP_REALLOC(ptr, size)       (realloc((ptr), (size)))
+
+#define GSSEAP_NOT_IMPLEMENTED          do {            \
+        assert(0 && "not implemented");                 \
+        *minor = ENOSYS;                                \
+        return GSS_S_FAILURE;                           \
+    } while (0)
+
+/* Helper functions */
+static inline void
+store_uint16_be(uint16_t val, void *vp)
+{
+    unsigned char *p = (unsigned char *)vp;
+
+    p[0] = (val >>  8) & 0xff;
+    p[1] = (val      ) & 0xff;
+}
+
+static inline uint16_t
+load_uint16_be(const void *cvp)
+{
+    const unsigned char *p = (const unsigned char *)cvp;
+
+    return (p[1] | (p[0] << 8));
+}
+
+static inline void
+store_uint32_be(uint32_t val, void *vp)
+{
+    unsigned char *p = (unsigned char *)vp;
+
+    p[0] = (val >> 24) & 0xff;
+    p[1] = (val >> 16) & 0xff;
+    p[2] = (val >>  8) & 0xff;
+    p[3] = (val      ) & 0xff;
+}
+
+static inline uint32_t
+load_uint32_be(const void *cvp)
+{
+    const unsigned char *p = (const unsigned char *)cvp;
+
+    return (p[3] | (p[2] << 8)
+            | ((uint32_t) p[1] << 16)
+            | ((uint32_t) p[0] << 24));
+}
+
+static inline void
+store_uint64_be(uint64_t val, void *vp)
+{
+    unsigned char *p = (unsigned char *)vp;
+
+    p[0] = (unsigned char)((val >> 56) & 0xff);
+    p[1] = (unsigned char)((val >> 48) & 0xff);
+    p[2] = (unsigned char)((val >> 40) & 0xff);
+    p[3] = (unsigned char)((val >> 32) & 0xff);
+    p[4] = (unsigned char)((val >> 24) & 0xff);
+    p[5] = (unsigned char)((val >> 16) & 0xff);
+    p[6] = (unsigned char)((val >>  8) & 0xff);
+    p[7] = (unsigned char)((val      ) & 0xff);
+}
+
+static inline uint64_t
+load_uint64_be(const void *cvp)
+{
+    const unsigned char *p = (const unsigned char *)cvp;
+
+    return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4);
+}
+
+#endif /* _UTIL_H_ */
index 4852127..d2b0bd8 100644 (file)
@@ -75,7 +75,8 @@ gssEapChecksum(krb5_context context,
     if (verify)
         *valid = FALSE;
 
-    code = krb5_c_crypto_length(context, KRB_KEYTYPE(key), KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen);
+    code = krb5_c_crypto_length(context, KRB_KEYTYPE(key),
+                                KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen);
     if (code != 0)
         return code;
 
@@ -102,7 +103,7 @@ gssEapChecksum(krb5_context context,
 
     /* Data */
     for (j = 0; j < iov_count; j++) {
-        kiov[i].flags = gssEapTranslateCryptoFlag(iov[j].type);
+        kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
         kiov[i].data.length = iov[j].buffer.length;
         kiov[i].data.data = (char *)iov[j].buffer.value;
         i++;
index 7121d7f..b0a9e52 100644 (file)
@@ -98,6 +98,8 @@ gssEapReleaseContext(OM_uint32 *minor,
     gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
     gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
 
+    sequenceFree(ctx->seqState);
+
     memset(ctx, 0, sizeof(*ctx));
     GSSEAP_FREE(ctx);
     *pCtx = GSS_C_NO_CONTEXT;
index 48f5a5e..e4d5d0d 100644 (file)
  * RRC is rotate count.
  */
 static krb5_error_code
-translateIov(krb5_context context, int dce_style, size_t ec, size_t rrc,
-             krb5_enctype enctype, gss_iov_buffer_desc *iov,
-             int iov_count, krb5_crypto_iov **pkiov,
-             size_t *pkiov_count)
+mapIov(krb5_context context, int dce_style, size_t ec, size_t rrc,
+       krb5_enctype enctype, gss_iov_buffer_desc *iov,
+       int iov_count, krb5_crypto_iov **pkiov,
+       size_t *pkiov_count)
 {
     gss_iov_buffer_t header;
     gss_iov_buffer_t trailer;
@@ -156,7 +156,7 @@ translateIov(krb5_context context, int dce_style, size_t ec, size_t rrc,
     i++;
 
     for (j = 0; j < iov_count; j++) {
-        kiov[i].flags = gssEapTranslateCryptoFlag(iov[j].type);
+        kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
         if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY)
             continue;
 
@@ -219,9 +219,9 @@ gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
         pivd = NULL;
     }
 
-    code = translateIov(context, dce_style, ec, rrc,
-                        KRB_KEYTYPE(key), iov, iov_count,
-                        &kiov, &kiov_count);
+    code = mapIov(context, dce_style, ec, rrc,
+                  KRB_KEYTYPE(key), iov, iov_count,
+                  &kiov, &kiov_count);
     if (code == 0) {
         code = krb5_c_encrypt_iov(context, key, usage, pivd, kiov, kiov_count);
         GSSEAP_FREE(kiov);
@@ -259,9 +259,9 @@ gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
         pivd = NULL;
     }
 
-    code = translateIov(context, dce_style, ec, rrc,
-                        KRB_KEYTYPE(key), iov, iov_count,
-                        &kiov, &kiov_count);
+    code = mapIov(context, dce_style, ec, rrc,
+                  KRB_KEYTYPE(key), iov, iov_count,
+                  &kiov, &kiov_count);
     if (code == 0) {
         code = krb5_c_decrypt_iov(context, key, usage, pivd, kiov, kiov_count);
         GSSEAP_FREE(kiov);
@@ -274,7 +274,7 @@ gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
 }
 
 krb5_cryptotype
-gssEapTranslateCryptoFlag(OM_uint32 type)
+gssEapMapCryptoFlag(OM_uint32 type)
 {
     krb5_cryptotype ktype;
 
index 7bf7f94..0b172f8 100644 (file)
@@ -76,18 +76,17 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
     unsigned int gss_headerlen, gss_trailerlen;
     size_t data_length, assoc_data_length;
 
-    if (!CTX_IS_ESTABLISHED(ctx)) {
+    if (!CTX_IS_ESTABLISHED(ctx))
         return GSS_S_NO_CONTEXT;
-    }
 
     acceptor_flag = CTX_IS_INITIATOR(ctx) ? 0 : TOK_FLAG_SENDER_IS_ACCEPTOR;
     key_usage = ((toktype == TOK_TYPE_WRAP)
                  ? (CTX_IS_INITIATOR(ctx)
-                    ? KRB_USAGE_INITIATOR_SEAL
-                    : KRB_USAGE_ACCEPTOR_SEAL)
+                    ? KEY_USAGE_INITIATOR_SEAL
+                    : KEY_USAGE_ACCEPTOR_SEAL)
                  : (CTX_IS_INITIATOR(ctx)
-                    ? KRB_USAGE_INITIATOR_SIGN
-                    : KRB_USAGE_ACCEPTOR_SIGN));
+                    ? KEY_USAGE_INITIATOR_SIGN
+                    : KEY_USAGE_ACCEPTOR_SIGN));
 
     gssEapIovMessageLength(iov, iov_count, &data_length, &assoc_data_length);
 
@@ -163,7 +162,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
         }
 
         /* TOK_ID */
-        store_16_be((uint16_t)toktype, outbuf);
+        store_uint16_be((uint16_t)toktype, outbuf);
         /* flags */
         outbuf[2] = (acceptor_flag
                      | (conf_req_flag ? TOK_FLAG_WRAP_CONFIDENTIAL : 0)
@@ -171,12 +170,15 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
         /* filler */
         outbuf[3] = 0xFF;
         /* EC */
-        store_16_be(ec, outbuf + 4);
+        store_uint16_be(ec, outbuf + 4);
         /* RRC */
-        store_16_be(0, outbuf + 6);
+        store_uint16_be(0, outbuf + 6);
         store_64_be(ctx->sendSeq, outbuf + 8);
 
-        /* EC | copy of header to be encrypted, located in (possibly rotated) trailer */
+        /*
+         * EC | copy of header to be encrypted, located in
+         * (possibly rotated) trailer
+         */
         if (trailer == NULL)
             tbuf = (unsigned char *)header->buffer.value + 16; /* Header */
         else
@@ -193,7 +195,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
             goto cleanup;
 
         /* RRC */
-        store_16_be(rrc, outbuf + 6);
+        store_uint16_be(rrc, outbuf + 6);
 
         ctx->sendSeq++;
     } else if (toktype == TOK_TYPE_WRAP && !conf_req_flag) {
@@ -234,7 +236,7 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
         }
 
         /* TOK_ID */
-        store_16_be((uint16_t)toktype, outbuf);
+        store_uint16_be((uint16_t)toktype, outbuf);
         /* flags */
         outbuf[2] = (acceptor_flag
                      | (0 ? TOK_FLAG_ACCEPTOR_SUBKEY : 0));
@@ -245,13 +247,13 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
              * checksum length later.
              */
             /* EC */
-            store_16_be(0, outbuf + 4);
+            store_uint16_be(0, outbuf + 4);
             /* RRC */
-            store_16_be(0, outbuf + 6);
+            store_uint16_be(0, outbuf + 6);
         } else {
             /* MIC and DEL store 0xFF in EC and RRC */
-            store_16_be(0xFFFF, outbuf + 4);
-            store_16_be(0xFFFF, outbuf + 6);
+            store_uint16_be(0xFFFF, outbuf + 4);
+            store_uint16_be(0xFFFF, outbuf + 6);
         }
         store_64_be(ctx->sendSeq, outbuf + 8);
 
@@ -265,9 +267,9 @@ gssEapWrapOrGetMIC(OM_uint32 *minor,
 
         if (toktype == TOK_TYPE_WRAP) {
             /* Fix up EC field */
-            store_16_be(gss_trailerlen, outbuf + 4);
+            store_uint16_be(gss_trailerlen, outbuf + 4);
             /* Fix up RRC field */
-            store_16_be(rrc, outbuf + 6);
+            store_uint16_be(rrc, outbuf + 6);
         }
     } else if (toktype == TOK_TYPE_MIC) {
         trailer = NULL;