{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TLS handshake overview\n",
    "This is the standard, modern TLS 1.2 handshake:\n",
    "\n",
    "<img src=\"images/handshake_tls12.png\" alt=\"Handshake TLS 1.2\" width=\"400\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# We're going to parse several successive records from the passive listening of a standard TLS handshake\n",
    "from scapy.all import *\n",
    "load_layer('tls')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) ---> (S) ClientHello"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record1 = TLS(open('raw_data/tls_session_protected/01_cli.raw', 'rb').read())\n",
    "record1.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "for extension in record1.msg[0].ext:\n",
    "    print('')\n",
    "    extension.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) <--- (S) ServerHello"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record2 = TLS(open('raw_data/tls_session_protected/02_srv.raw', 'rb').read())\n",
    "record2.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) <--- (S) Certificate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record3 = TLS(open('raw_data/tls_session_protected/03_srv.raw', 'rb').read())\n",
    "record3.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# The Certificate message actually contains a *chain* of certificates\n",
    "for cert in record3.msg[0].certs:\n",
    "    print(type(cert[1]))\n",
    "    cert[1].show()\n",
    "    print('')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Let's recall the domain that the client wants to access\n",
    "record1.msg[0].ext[0].show()\n",
    "\n",
    "# Indeed the certificate may be used with other domains than its CN 'www.github.com'\n",
    "x509c = record3.msg[0].certs[0][1].x509Cert\n",
    "print(type(x509c))\n",
    "x509c.tbsCertificate.extensions[2].show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) <--- (S) CertificateStatus, ServerKeyExchange, ServerHelloDone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Here the server sent three TLS records in the same TCP segment\n",
    "record4 = TLS(open('raw_data/tls_session_protected/04_srv.raw', 'rb').read())\n",
    "record4.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Let's verify the signature in the ServerKeyExchange\n",
    "# First, we need to assemble the whole data being signed\n",
    "cli_random = pkcs_i2osp(record1.msg[0].gmt_unix_time, 4) + record1.msg[0].random_bytes\n",
    "srv_random = pkcs_i2osp(record2.msg[0].gmt_unix_time, 4) + record2.msg[0].random_bytes\n",
    "ecdh_params = bytes(record4[TLSServerKeyExchange].params)\n",
    "\n",
    "# Then we retrieve the server's Cert and verify the signature\n",
    "cert_srv = record3.msg[0].certs[0][1]\n",
    "cert_srv.verify(cli_random + srv_random + ecdh_params, record4[TLSServerKeyExchange].sig.sig_val, h='sha512')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## (C) ---> (S) ClientKeyExchange, ChangeCipherSpec, Finished"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record5_str = open('raw_data/tls_session_protected/05_cli.raw', 'rb').read()\n",
    "record5 = TLS(record5_str)\n",
    "record5.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Every record has a 'tls_session' context which may enhance the parsing of later records\n",
    "record5 = TLS(record5_str, tls_session=record2.tls_session.mirror())\n",
    "record5.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) <--- (S) NewSessionTicket, ChangeCipherSpec, Finished"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record6_str = open('raw_data/tls_session_protected/06_srv.raw', 'rb').read()\n",
    "record6 = TLS(record6_str, tls_session=record5.tls_session.mirror())\n",
    "record6.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (C) ---> (S) ApplicationData"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "record7_str = open('raw_data/tls_session_protected/07_cli.raw', 'rb').read()\n",
    "record7 = TLS(record7_str, tls_session=record6.tls_session.mirror())\n",
    "record7.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
