From "wiresharkbugzilla@jdkbx.cjb.net":
authorAnders Broman <anders.broman@ericsson.com>
Thu, 24 Jun 2010 06:01:11 +0000 (06:01 -0000)
committerAnders Broman <anders.broman@ericsson.com>
Thu, 24 Jun 2010 06:01:11 +0000 (06:01 -0000)
Support for RFC4279 Pre-Shared Key Ciphersuites for Transport Layer Security (TLS)
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4853

svn path=/trunk/; revision=33309

epan/dissectors/packet-ssl-utils.c
epan/dissectors/packet-ssl-utils.h
epan/dissectors/packet-ssl.c

index f123e47e31183e618caceea48e30888b7103c99c..349ceab9d05ab2131f0ba0ab7c5dd70248608c84 100644 (file)
@@ -1304,6 +1304,10 @@ static SslCipherSuite cipher_suites[]={
     {100,KEX_RSA,SIG_RSA,ENC_RC4,1,128,56,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
     {101,KEX_DH,SIG_DSS,ENC_RC4,1,128,56,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
     {102,KEX_DH,SIG_DSS,ENC_RC4,1,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_STREAM},
+    /*{138,KEX_PSK,SIG_RSA,ENC_RC4,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},*/
+    {139,KEX_PSK,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
+    {140,KEX_PSK,SIG_RSA,ENC_AES,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
+    {141,KEX_PSK,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
     {-1, 0,0,0,0,0,0,0,0,0, 0}
 };
 
index 5184134fd1c452904ceb06403ca1f3bc812fe3dc..1de9b8cb7c23b4e8524c508e8a0fe45c3c8b9ae2 100644 (file)
@@ -44,6 +44,7 @@
 #define SSL_DECRYPT_DEBUG
 
 #define SSL_CIPHER_CTX gcry_cipher_hd_t
+#define SSL_PSK_KEY guchar
 #ifdef SSL_FAST
 #define SSL_PRIVATE_KEY gcry_mpi_t
 #else /* SSL_FAST */
@@ -52,6 +53,7 @@
 #else  /* HAVE_LIBGNUTLS */
 #define SSL_CIPHER_CTX void*
 #define SSL_PRIVATE_KEY void
+#define SSL_PSK_KEY void
 #endif /* HAVE_LIBGNUTLS */
 
 
@@ -241,6 +243,7 @@ typedef struct _SslDecoder {
 
 #define KEX_RSA         0x10
 #define KEX_DH          0x11
+#define KEX_PSK         0x12
 
 #define SIG_RSA         0x20
 #define SIG_DSS         0x21
@@ -305,6 +308,7 @@ typedef struct _SslDecryptSession {
     SslDecoder *server_new;
     SslDecoder *client_new;
     SSL_PRIVATE_KEY* private_key;
+    SSL_PSK_KEY* psk;
     guint32 version;
     guint16 version_netorder;
     StringInfo app_data_segment;
index 25b2aaca354c2b9e674e0e72f68b6c230a55dd58..21fdc931e7615a78371239ac3e62fe50a241b8e9 100644 (file)
@@ -280,6 +280,7 @@ static StringInfo ssl_decrypted_data = {NULL, 0};
 static gint ssl_decrypted_data_avail = 0;
 
 static gchar* ssl_keys_list = NULL;
+static gchar* ssl_psk = NULL;
 
 #if defined(SSL_DECRYPT_DEBUG) || defined(HAVE_LIBGNUTLS)
 static gchar* ssl_debug_file_name = NULL;
@@ -1822,44 +1823,118 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
             case SSL_HND_CLIENT_KEY_EXCHG:
                 {
                     /* PAOLO: here we can have all the data to build session key*/
-                    StringInfo encrypted_pre_master;
-                    gint ret;
-                    guint encrlen, skip;
-                    encrlen = length;
-                    skip = 0;
+
+                    gint cipher_num;
 
                     if (!ssl)
                         break;
 
-                    /* get encrypted data, on tls1 we have to skip two bytes
-                     * (it's the encrypted len and should be equal to record len - 2)
-                     */
-                    if (ssl->version == SSL_VER_TLS||ssl->version == SSL_VER_TLSv1DOT1||ssl->version == SSL_VER_TLSv1DOT2)
+                    cipher_num = ssl->cipher;
+
+                    if (cipher_num == 0x8a || cipher_num == 0x8b || cipher_num == 0x8c || cipher_num == 0x8d)
                     {
-                        encrlen  = tvb_get_ntohs(tvb, offset);
-                        skip = 2;
-                        if (encrlen > length - 2)
+                        /* calculate pre master secret*/
+                        StringInfo pre_master_secret;
+                        guint psk_len, pre_master_len;
+
+                        int size;
+                        unsigned char *out;
+                        int i,j = 0;
+                        char input[2];
+
+                        if (!ssl_psk || (ssl_psk[0] == 0)) {
+                               ssl_debug_printf("dissect_ssl3_handshake can't find pre-shared-key\n");
+                            break;
+                        }
+
+                        size = (int)strlen(ssl_psk);
+
+                        /* psk must be 0 to 16 bytes*/
+                        if (size < 0 || size > 32 || size % 2 != 0)
                         {
-                            ssl_debug_printf("dissect_ssl3_handshake wrong encrypted length (%d max %d)\n",
-                                encrlen, length);
                             break;
                         }
-                    }
-                    encrypted_pre_master.data = se_alloc(encrlen);
-                    encrypted_pre_master.data_len = encrlen;
-                    tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
 
-                    if (!ssl->private_key) {
-                        ssl_debug_printf("dissect_ssl3_handshake can't find private key\n");
-                        break;
+                        /* convert hex string into char*/
+                        out = (unsigned char*) g_malloc(size > 0 ? size / 2 : 0);
+
+                        for (i = 0; i < size; i+=2)
+                        {
+                            input[0] = ssl_psk[0 + i];
+                            input[1] = ssl_psk[1 + i];
+                            out[j++] = (unsigned int) strtoul((const char*)&input, NULL, 16);
+                        }
+
+                        ssl->psk = (guchar*) out;
+
+                        psk_len = size > 0 ? size / 2 : 0;
+                        pre_master_len = psk_len * 2 + 4;
+
+                        pre_master_secret.data = se_alloc(pre_master_len);
+                        pre_master_secret.data_len = pre_master_len;
+                        /* 2 bytes psk_len*/
+                        pre_master_secret.data[0] = psk_len >> 8;
+                        pre_master_secret.data[1] = psk_len & 0xFF;
+                        /* psk_len bytes times 0*/
+                        memset(&pre_master_secret.data[2], 0, psk_len);
+                        /* 2 bytes psk_len*/
+                        pre_master_secret.data[psk_len + 2] = psk_len >> 8;
+                        pre_master_secret.data[psk_len + 3] = psk_len & 0xFF;
+                        /* psk*/
+                        memcpy(&pre_master_secret.data[psk_len + 4], ssl->psk, psk_len);
+
+                        g_free(out);
+
+                        ssl->pre_master_secret.data = pre_master_secret.data;
+                        ssl->pre_master_secret.data_len = pre_master_len;
+                        ssl_debug_printf("pre master secret",&ssl->pre_master_secret);
+
+                        /* Remove the master secret if it was there.
+                           This forces keying material regeneration in
+                           case we're renegotiating */
+                        ssl->state &= ~(SSL_MASTER_SECRET|SSL_HAVE_SESSION_KEY);
+                        ssl->state |= SSL_PRE_MASTER_SECRET;
                     }
+                    else
+                    {
+                        StringInfo encrypted_pre_master;
+                        gint ret;
+                        guint encrlen, skip;
+                        encrlen = length;
+                        skip = 0;
+
+                        /* get encrypted data, on tls1 we have to skip two bytes
+                         * (it's the encrypted len and should be equal to record len - 2)
+                         * in case of rsa1024 that would be 128 + 2 = 130; for psk not neccessary
+                                                */
+                        if (ssl->version == SSL_VER_TLS||ssl->version == SSL_VER_TLSv1DOT1||ssl->version == SSL_VER_TLSv1DOT2)
+                        {
+                            encrlen  = tvb_get_ntohs(tvb, offset);
+                            skip = 2;
+                            if (encrlen > length - 2)
+                            {
+                                ssl_debug_printf("dissect_ssl3_handshake wrong encrypted length (%d max %d)\n",
+                                    encrlen, length);
+                                break;
+                            }
+                        }
+                        encrypted_pre_master.data = se_alloc(encrlen);
+                        encrypted_pre_master.data_len = encrlen;
+                        tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
 
-                    /* go with ssl key processessing; encrypted_pre_master
-                     * will be used for master secret store*/
-                    ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
-                    if (ret < 0) {
-                        ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
-                        break;
+                        if (!ssl->private_key) {
+                            ssl_debug_printf("dissect_ssl3_handshake can't find private key\n");
+                            break;
+                        }
+
+                        /* go with ssl key processessing; encrypted_pre_master
+                         * will be used for master secret store
+                                                */
+                        ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
+                        if (ret < 0) {
+                            ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
+                            break;
+                        }
                     }
                     if (ssl_generate_keyring_material(ssl)<0) {
                         ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n");
@@ -4424,6 +4499,9 @@ proto_register_ssl(void)
              "Redirect SSL debug to file name; leave empty to disable debugging, "
              "or use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
              (const gchar **)&ssl_debug_file_name);
+        prefs_register_string_preference(ssl_module, "psk", "Pre-Shared-Key",
+             "Pre-Shared-Key as HEX string, should be 0 to 16 bytes",
+             (const gchar **)&ssl_psk);
 #endif
     }