]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tls] Use hybrid MD5+SHA1 algorithm
authorMichael Brown <mcb30@ipxe.org>
Tue, 20 Mar 2012 04:07:53 +0000 (04:07 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 20 Mar 2012 16:57:16 +0000 (16:57 +0000)
TLSv1.1 and earlier use a hybrid of MD5 and SHA-1 to generate digests
over the handshake messages.  Formalise this as a separate digest
algorithm "md5+sha1".

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/tls.h
src/net/tls.c

index a2504f19cb22a006d85e24dff0ef918fb1d43212..a491b79582e6a6dc630004640faa46ecac85bcd3 100644 (file)
@@ -145,6 +145,28 @@ struct tls_client_random {
        uint8_t random[28];
 } __attribute__ (( packed ));
 
+/** An MD5+SHA1 context */
+struct md5_sha1_context {
+       /** MD5 context */
+       uint8_t md5[MD5_CTX_SIZE];
+       /** SHA-1 context */
+       uint8_t sha1[SHA1_CTX_SIZE];
+} __attribute__ (( packed ));
+
+/** MD5+SHA1 context size */
+#define MD5_SHA1_CTX_SIZE sizeof ( struct md5_sha1_context )
+
+/** An MD5+SHA1 digest */
+struct md5_sha1_digest {
+       /** MD5 digest */
+       uint8_t md5[MD5_DIGEST_SIZE];
+       /** SHA-1 digest */
+       uint8_t sha1[SHA1_DIGEST_SIZE];
+} __attribute__ (( packed ));
+
+/** MD5+SHA1 digest size */
+#define MD5_SHA1_DIGEST_SIZE sizeof ( struct md5_sha1_digest )
+
 /** A TLS session */
 struct tls_session {
        /** Reference counter */
@@ -175,10 +197,8 @@ struct tls_session {
        uint8_t server_random[32];
        /** Client random bytes */
        struct tls_client_random client_random;
-       /** MD5 context for handshake verification */
-       uint8_t handshake_md5_ctx[MD5_CTX_SIZE];
-       /** SHA1 context for handshake verification */
-       uint8_t handshake_sha1_ctx[SHA1_CTX_SIZE];
+       /** MD5+SHA1 context for handshake verification */
+       uint8_t handshake_md5_sha1_ctx[MD5_SHA1_CTX_SIZE];
        /** SHA256 context for handshake verification */
        uint8_t handshake_sha256_ctx[SHA256_CTX_SIZE];
 
index 3aefb19de1838640348e553858abd23084c23aab..2580008db50b1ab36da939e3e891be8bf259757d 100644 (file)
@@ -79,6 +79,64 @@ static unsigned long tls_uint24 ( const uint8_t field24[3] ) {
        return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] );
 }
 
+/******************************************************************************
+ *
+ * Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Initialise MD5+SHA1 algorithm
+ *
+ * @v ctx              MD5+SHA1 context
+ */
+static void md5_sha1_init ( void *ctx ) {
+       struct md5_sha1_context *context = ctx;
+
+       digest_init ( &md5_algorithm, context->md5 );
+       digest_init ( &sha1_algorithm, context->sha1 );
+}
+
+/**
+ * Accumulate data with MD5+SHA1 algorithm
+ *
+ * @v ctx              MD5+SHA1 context
+ * @v data             Data
+ * @v len              Length of data
+ */
+static void md5_sha1_update ( void *ctx, const void *data, size_t len ) {
+       struct md5_sha1_context *context = ctx;
+
+       digest_update ( &md5_algorithm, context->md5, data, len );
+       digest_update ( &sha1_algorithm, context->sha1, data, len );
+}
+
+/**
+ * Generate MD5+SHA1 digest
+ *
+ * @v ctx              MD5+SHA1 context
+ * @v out              Output buffer
+ */
+static void md5_sha1_final ( void *ctx, void *out ) {
+       struct md5_sha1_context *context = ctx;
+       struct md5_sha1_digest *digest = out;
+
+       digest_final ( &md5_algorithm, context->md5, digest->md5 );
+       digest_final ( &sha1_algorithm, context->sha1, digest->sha1 );
+}
+
+/** Hybrid MD5+SHA1 digest algorithm */
+static struct digest_algorithm md5_sha1_algorithm = {
+       .name           = "md5+sha1",
+       .ctxsize        = sizeof ( struct md5_sha1_context ),
+       .blocksize      = 0, /* Not applicable */
+       .digestsize     = sizeof ( struct md5_sha1_digest ),
+       .init           = md5_sha1_init,
+       .update         = md5_sha1_update,
+       .final          = md5_sha1_final,
+};
+
 /******************************************************************************
  *
  * Cleanup functions
@@ -633,8 +691,8 @@ static int tls_change_cipher ( struct tls_session *tls,
 static void tls_add_handshake ( struct tls_session *tls,
                                const void *data, size_t len ) {
 
-       digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len );
-       digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len );
+       digest_update ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx,
+                       data, len );
        digest_update ( &sha256_algorithm, tls->handshake_sha256_ctx,
                        data, len );
 }
@@ -651,7 +709,7 @@ static size_t tls_verify_handshake_len ( struct tls_session *tls ) {
                return SHA256_DIGEST_SIZE;
        } else {
                /* Use MD5+SHA1 for TLSv1.1 and earlier */
-               return ( MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE );
+               return MD5_SHA1_DIGEST_SIZE;
        }
 }
 
@@ -666,8 +724,7 @@ static size_t tls_verify_handshake_len ( struct tls_session *tls ) {
  */
 static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
        union {
-               uint8_t md5[MD5_CTX_SIZE];
-               uint8_t sha1[SHA1_CTX_SIZE];
+               uint8_t md5_sha1[MD5_SHA1_CTX_SIZE];
                uint8_t sha256[SHA256_CTX_SIZE];
        } ctx;
 
@@ -678,12 +735,9 @@ static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
                digest_final ( &sha256_algorithm, ctx.sha256, out );
        } else {
                /* Use MD5+SHA1 for TLSv1.1 and earlier */
-               memcpy ( ctx.md5, tls->handshake_md5_ctx, sizeof ( ctx.md5 ) );
-               digest_final ( &md5_algorithm, ctx.md5, out );
-               memcpy ( ctx.sha1, tls->handshake_sha1_ctx,
-                        sizeof ( ctx.sha1 ) );
-               digest_final ( &sha1_algorithm, ctx.sha1,
-                              ( out + MD5_DIGEST_SIZE ) );
+               memcpy ( ctx.md5_sha1, tls->handshake_md5_sha1_ctx,
+                        sizeof ( ctx.md5_sha1 ) );
+               digest_final ( &md5_sha1_algorithm, ctx.md5_sha1, out );
        }
 }
 
@@ -2043,8 +2097,7 @@ int add_tls ( struct interface *xfer, const char *name,
                      ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) {
                goto err_random;
        }
-       digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
-       digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
+       digest_init ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx );
        digest_init ( &sha256_algorithm, tls->handshake_sha256_ctx );
        tls->tx_pending = TLS_TX_CLIENT_HELLO;
        process_init ( &tls->process, &tls_process_desc, &tls->refcnt );