]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Pass TLS records to newly introduced TLS stack
authorMartin Willi <martin@revosec.ch>
Fri, 22 Jan 2010 14:35:29 +0000 (15:35 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 3 Aug 2010 13:39:24 +0000 (15:39 +0200)
src/charon/plugins/eap_tls/eap_tls.c
src/charon/plugins/eap_tls/tls/tls.c
src/charon/plugins/eap_tls/tls/tls.h

index b24805273dc3710e8b7d7467fa892d33b008a92f..2e87d8f1cf178935bcb9fb7f5c57cff9f040a4d1 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "eap_tls.h"
 
+#include "tls/tls.h"
+
 #include <daemon.h>
 #include <library.h>
 
@@ -45,6 +47,11 @@ struct private_eap_tls_t {
         */
        bool is_server;
 
+       /**
+        * TLS layers
+        */
+       tls_t *tls;
+
        /**
         * Allocated input buffer
         */
@@ -212,28 +219,62 @@ static eap_payload_t *read_buf(private_eap_tls_t *this, u_int8_t identifier)
  */
 static status_t process_buf(private_eap_tls_t *this)
 {
-       tls_record_t *record;
-       chunk_t input;
+       tls_record_t *in, out;
+       chunk_t data;
        u_int16_t len;
+       status_t status;
 
-       input = this->input;
-       while (input.len > sizeof(tls_record_t))
+       /* pass input buffer to upper layer, record for record */
+       data = this->input;
+       while (data.len > sizeof(tls_record_t))
        {
-               record = (tls_record_t*)input.ptr;
-               len = untoh16(&record->length);
-               if (len > input.len)
+               in = (tls_record_t*)data.ptr;
+               len = untoh16(&in->length);
+               if (len > data.len - sizeof(tls_record_t))
                {
                        DBG1(DBG_IKE, "TLS record length invalid");
                        break;
                }
-               /* TODO: pass record to next layer */
-               input = chunk_skip(input, len);
+               status = this->tls->process(this->tls, in->type,
+                                                                       chunk_create(in->data, len));
+               if (status != NEED_MORE)
+               {
+                       return status;
+               }
+               data = chunk_skip(data, len + sizeof(tls_record_t));
        }
        chunk_free(&this->input);
        this->inpos = 0;
 
-       /* TODO: read records from next layer */
-       return NEED_MORE;
+       /* read in records from upper layer, append to output buffer */
+       chunk_free(&this->output);
+       while (TRUE)
+       {
+               tls_content_type_t type;
+               chunk_t header = chunk_from_thing(out);
+
+               status = this->tls->build(this->tls, &type, &data);
+               switch (status)
+               {
+                       case INVALID_STATE:
+                               /* invalid state means we need more input from peer first */
+                               return NEED_MORE;
+                       case NEED_MORE:
+                       case SUCCESS:
+                               break;
+                       case FAILED:
+                       default:
+                               return FAILED;
+               }
+               out.type = type;
+               htoun16(&out.version, TLS_1_2);
+               htoun16(&out.length, data.len);
+               this->output = chunk_cat("mcm", this->output, header, data);
+               if (status == SUCCESS)
+               {
+                       return SUCCESS;
+               }
+       }
 }
 
 METHOD(eap_method_t, process, status_t,
@@ -309,6 +350,8 @@ METHOD(eap_method_t, destroy, void,
        free(this->input.ptr);
        free(this->output.ptr);
 
+       this->tls->destroy(this->tls);
+
        free(this);
 }
 
@@ -332,6 +375,7 @@ static eap_tls_t *eap_tls_create(identification_t *server,
                .peer = peer->clone(peer),
                .server = server->clone(server),
                .is_server = is_server,
+               .tls = tls_create(is_server),
        );
 
        return &this->public;
index 930ae78b67b74cc125a238b9b4bfc0f2355569c5..ddb0c81f0634f91805137c710efefb61e4c27a4f 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "tls.h"
 
+#include <daemon.h>
+
 ENUM(tls_version_names, SSL_2_0, TLS_1_2,
        "SSLv2",
        "SSLv3",
@@ -44,3 +46,59 @@ ENUM_NEXT(tls_handshake_type_names, TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TL
 ENUM_NEXT(tls_handshake_type_names, TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_EXCHANGE,
        "Finished");
 ENUM_END(tls_handshake_type_names, TLS_FINISHED);
+
+
+typedef struct private_tls_t private_tls_t;
+
+/**
+ * Private data of an tls_protection_t object.
+ */
+struct private_tls_t {
+
+       /**
+        * Public tls_t interface.
+        */
+       tls_t public;
+
+       /**
+        * Role this TLS stack acts as.
+        */
+       bool is_server;
+};
+
+METHOD(tls_t, process, status_t,
+       private_tls_t *this, tls_content_type_t type, chunk_t data)
+{
+       return NEED_MORE;
+}
+
+METHOD(tls_t, build, status_t,
+       private_tls_t *this, tls_content_type_t *type, chunk_t *data)
+{
+       return INVALID_STATE;
+}
+
+METHOD(tls_t, destroy, void,
+       private_tls_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+tls_t *tls_create(bool is_server)
+{
+       private_tls_t *this;
+
+       INIT(this,
+               .public = {
+                       .process = _process,
+                       .build = _build,
+                       .destroy = _destroy,
+               },
+               .is_server = is_server,
+       );
+
+       return &this->public;
+}
index d7a33175681786b8fb30c3a458edbee684e82245..2e3e04691303075f481f77767989bae1085ad4d7 100644 (file)
@@ -28,6 +28,7 @@ typedef enum tls_version_t tls_version_t;
 typedef enum tls_content_type_t tls_content_type_t;
 typedef enum tls_handshake_type_t tls_handshake_type_t;
 typedef enum tls_cipher_suite_t tls_cipher_suite_t;
+typedef struct tls_t tls_t;
 
 #include <library.h>
 
@@ -123,4 +124,48 @@ enum tls_cipher_suite_t {
        TLS_DH_ANON_WITH_AES_256_CBC_SHA256 =   0x6D,
 };
 
+/**
+ * A bottom-up driven TLS stack, suitable for EAP implementations.
+ */
+struct tls_t {
+
+       /**
+        * Process a TLS record, pass it to upper layers.
+        *
+        * @param type          type of the TLS record to process
+        * @param data          associated TLS record data
+        * @return
+        *                                      - SUCCESS if TLS negotiation complete
+        *                                      - FAILED if TLS handshake failed
+        *                                      - NEED_MORE if more invocations to process/build needed
+        */
+       status_t (*process)(tls_t *this, tls_content_type_t type, chunk_t data);
+
+       /**
+        * Query upper layer for TLS record, build protected record.
+        *
+        * @param type          type of the built TLS record
+        * @param data          allocated data of the built TLS record
+        * @return
+        *                                      - SUCCESS if TLS negotiation complete
+        *                                      - FAILED if TLS handshake failed
+        *                                      - NEED_MORE if upper layers have more records to send
+        *                                      - INVALID_STATE if more input records required
+        */
+       status_t (*build)(tls_t *this, tls_content_type_t *type, chunk_t *data);
+
+       /**
+        * Destroy a tls_t.
+        */
+       void (*destroy)(tls_t *this);
+};
+
+/**
+ * Create a tls instance.
+ *
+ * @param is_server            TRUE to act as server, FALSE for client
+ * @return                             TLS stack
+ */
+tls_t *tls_create(bool is_server);
+
 #endif /** TLS_H_ @}*/