cl-rw

Layered streams for Common Lisp
git clone https://logand.com/git/cl-rw.git/
Log | Files | Refs

tls.lisp (25156B)


      1 ;;; Copyright (C) 2014 Tomas Hlavaty <tom@logand.com>
      2 ;;;
      3 ;;; Permission is hereby granted, free of charge, to any person
      4 ;;; obtaining a copy of this software and associated documentation
      5 ;;; files (the "Software"), to deal in the Software without
      6 ;;; restriction, including without limitation the rights to use, copy,
      7 ;;; modify, merge, publish, distribute, sublicense, and/or sell copies
      8 ;;; of the Software, and to permit persons to whom the Software is
      9 ;;; furnished to do so, subject to the following conditions:
     10 ;;;
     11 ;;; The above copyright notice and this permission notice shall be
     12 ;;; included in all copies or substantial portions of the Software.
     13 ;;;
     14 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     17 ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     18 ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     19 ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 ;;; DEALINGS IN THE SOFTWARE.
     22 
     23 (defpackage :rw.tls
     24   (:use :cl))
     25 
     26 (in-package :rw.tls)
     27 
     28 ;; broken stuff: rc4 md5 sha1 aescbc rsa1024 rsa-keyxchg ecdsa
     29 
     30 ;; good: dhe ecdhe aesgcm pfs; better 512hash rsa4096+ aes256+
     31 
     32 ;;tshark -i wlp3s0 -V >~/git/cl-rw/tls.log
     33 ;;gnutls-cli wikipedia.org
     34 
     35 ;; https://en.wikipedia.org/wiki/Transport_Layer_Security
     36 ;; http://msdn.microsoft.com/en-us/library/windows/desktop/aa380513(v=vs.85).aspx
     37 ;; http://technet.microsoft.com/en-us/library/cc785811(v=ws.10).aspx
     38 ;; https://tools.ietf.org/html/rfc5246
     39 ;; https://tools.ietf.org/html/rfc4492
     40 
     41 (rw.wire:defenum $AlertLevel (:type rw:u8)
     42   (WARNING . 1)
     43   (FATAL   . 2))
     44 
     45 (rw.wire:defenum $AlertDescription (:type rw:u8)
     46   (CLOSE_NOTIFY                .   0)
     47   (UNEXPECTED_MESSAGE          .  10)
     48   (BAD_RECORD_MAC              .  20)
     49   (DECRYPTION_FAILED_RESERVED  .  21)
     50   (RECORD_OVERFLOW             .  22)
     51   (DECOMPRESSION_FAILURE       .  30)
     52   (HANDSHAKE_FAILURE           .  40)
     53   (NO_CERTIFICATE_RESERVED     .  41)
     54   (BAD_CERTIFICATE             .  42)
     55   (UNSUPPORTED_CERTIFICATE     .  43)
     56   (CERTIFICATE_REVOKED         .  44)
     57   (CERTIFICATE_EXPIRED         .  45)
     58   (CERTIFICATE_UNKNOWN         .  46)
     59   (ILLEGAL_PARAMETER           .  47)
     60   (UNKNOWN_CA                  .  48)
     61   (ACCESS_DENIED               .  49)
     62   (DECODE_ERROR                .  50)
     63   (DECRYPT_ERROR               .  51)
     64   (EXPORT_RESTRICTION_RESERVED .  60)
     65   (PROTOCOL_VERSION            .  70)
     66   (INSUFFICIENT_SECURITY       .  71)
     67   (INTERNAL_ERROR              .  80)
     68   (USER_CANCELED               .  90)
     69   (NO_RENEGOTIATION            . 100)
     70   (UNSUPPORTED_EXTENSION       . 110))
     71 
     72 (rw.wire:defenum $CipherSuite (:type rw:u16be)
     73   (TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA . #X0013)
     74   (TLS_DHE_DSS_WITH_AES_128_CBC_SHA . #X0032)
     75   (TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 . #X0040)
     76   (TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 . #X00A2)
     77   (TLS_DHE_DSS_WITH_AES_256_CBC_SHA . #X0038)
     78   (TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 . #X006A)
     79   (TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 . #X00A3)
     80   (TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA . #X0044)
     81   (TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 . #X00BD)
     82   (TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 . #XC080)
     83   (TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA . #X0087)
     84   (TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 . #X00C3)
     85   (TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 . #XC081)
     86   (TLS_DHE_DSS_WITH_RC4_128_SHA . #X0066)
     87   (TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA . #X0016)
     88   (TLS_DHE_RSA_WITH_AES_128_CBC_SHA . #X0033)
     89   (TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 . #X0067)
     90   (TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 . #X009E)
     91   (TLS_DHE_RSA_WITH_AES_256_CBC_SHA . #X0039)
     92   (TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 . #X006B)
     93   (TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 . #X009F)
     94   (TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA . #X0045)
     95   (TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 . #X00BE)
     96   (TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 . #XC07C)
     97   (TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA . #X0088)
     98   (TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 . #X00C4)
     99   (TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 . #XC07D)
    100   (TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA . #X001B)
    101   (TLS_DH_ANON_WITH_AES_128_CBC_SHA . #X0034)
    102   (TLS_DH_ANON_WITH_AES_128_CBC_SHA256 . #X006C)
    103   (TLS_DH_ANON_WITH_AES_256_CBC_SHA . #X003A)
    104   (TLS_DH_ANON_WITH_AES_256_CBC_SHA256 . #X006D)
    105   (TLS_DH_ANON_WITH_RC4_128_MD5 . #X0018)
    106   (TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA . #X000D)
    107   (TLS_DH_DSS_WITH_AES_128_CBC_SHA . #X0030)
    108   (TLS_DH_DSS_WITH_AES_128_CBC_SHA256 . #X003E)
    109   (TLS_DH_DSS_WITH_AES_256_CBC_SHA . #X0036)
    110   (TLS_DH_DSS_WITH_AES_256_CBC_SHA256 . #X0068)
    111   (TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA . #X0010)
    112   (TLS_DH_RSA_WITH_AES_128_CBC_SHA . #X0031)
    113   (TLS_DH_RSA_WITH_AES_128_CBC_SHA256 . #X003F)
    114   (TLS_DH_RSA_WITH_AES_256_CBC_SHA . #X0037)
    115   (TLS_DH_RSA_WITH_AES_256_CBC_SHA256 . #X0069)
    116   (TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA . #XC008)
    117   (TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA . #XC009)
    118   (TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 . #XC023)
    119   (TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 . #XC02B)
    120   (TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA . #XC00A)
    121   (TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 . #XC024)
    122   (TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 . #XC02C)
    123   (TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 . #XC072)
    124   (TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 . #XC086)
    125   (TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 . #XC073)
    126   (TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 . #XC087)
    127   (TLS_ECDHE_ECDSA_WITH_RC4_128_SHA . #XC007)
    128   (TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA . #XC012)
    129   (TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA . #XC013)
    130   (TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 . #XC027)
    131   (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 . #XC02F)
    132   (TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA . #XC014)
    133   (TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 . #XC028)
    134   (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 . #XC030)
    135   (TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 . #XC076)
    136   (TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 . #XC08A)
    137   (TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 . #XC077)
    138   (TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 . #XC08B)
    139   (TLS_ECDHE_RSA_WITH_RC4_128_SHA . #XC011)
    140   (TLS_NULL_WITH_NULL_NULL . #X0000)
    141   (TLS_RSA_WITH_3DES_EDE_CBC_SHA . #X000A)
    142   (TLS_RSA_WITH_AES_128_CBC_SHA . #X002F)
    143   (TLS_RSA_WITH_AES_128_CBC_SHA256 . #X003C)
    144   (TLS_RSA_WITH_AES_128_GCM_SHA256 . #X009C)
    145   (TLS_RSA_WITH_AES_256_CBC_SHA . #X0035)
    146   (TLS_RSA_WITH_AES_256_CBC_SHA256 . #X003D)
    147   (TLS_RSA_WITH_AES_256_GCM_SHA384 . #X009D)
    148   (TLS_RSA_WITH_CAMELLIA_128_CBC_SHA . #X0041)
    149   (TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 . #X00BA)
    150   (TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 . #XC07A)
    151   (TLS_RSA_WITH_CAMELLIA_256_CBC_SHA . #X0084)
    152   (TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 . #X00C0)
    153   (TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 . #XC07B)
    154   (TLS_RSA_WITH_NULL_MD5 . #X0001)
    155   (TLS_RSA_WITH_NULL_SHA . #X0002)
    156   (TLS_RSA_WITH_NULL_SHA256 . #X003B)
    157   (TLS_RSA_WITH_RC4_128_MD5 . #X0004)
    158   (TLS_RSA_WITH_RC4_128_SHA . #X0005))
    159 
    160 (rw.wire:defenum $ClientCertificateType (:type rw:u8)
    161   (rsa_sign                  . 1)
    162   (dss_sign                  . 2)
    163   (rsa_fixed_dh              . 3)
    164   (dss_fixed_dh              . 4)
    165   (rsa_ephemeral_dh_RESERVED . 5)
    166   (dss_ephemeral_dh_RESERVED . 6)
    167   (fortezza_dms_RESERVED     . 20))
    168 
    169 (rw.wire:defenum $CompressionMethod (:type rw:u8)
    170   (null . 0))
    171 
    172 (rw.wire:defenum $ContentType (:type rw:u8)
    173   (CHANGE_CIPHER_SPEC . 20)
    174   (ALERT              . 21)
    175   (HANDSHAKE          . 22)
    176   (APPLICATION_DATA   . 23))
    177 
    178 (rw.wire:defenum $ContentVersion (:type rw:u16be)
    179   (SSL3.0 . #x0300)
    180   (TLS1.2 . #x0303))
    181 
    182 (rw.wire:defenum $ExtensionType (:type rw:u16be)
    183   (ec_point_formats     . #x000b)
    184   (elliptic_curves      . #x000a)
    185   (renegotiation_info   . #xff01)
    186   (SessionTicket_TLS    . #x0023)
    187   (server_name          . #x0000)
    188   (signature_algorithms . #x000d)
    189   (status_request       . #x0005))
    190 
    191 (rw.wire:defenum $HandshakeType (:type rw:u8)
    192   (HELLO_REQUEST       .  0)
    193   (CLIENT_HELLO        .  1)
    194   (SERVER_HELLO        .  2)
    195   (CERTIFICATE         . 11)
    196   (SERVER_KEY_EXCHANGE . 12)
    197   (CERTIFICATE_REQUEST . 13)
    198   (SERVER_HELLO_DONE   . 14)
    199   (CERTIFICATE_VERIFY  . 15)
    200   (CLIENT_KEY_EXCHANGE . 16)
    201   (FINISHED            . 20))
    202 
    203 (rw.wire:defenum $HashAlgorithm (:type rw:u8)
    204   (none   . 0)
    205   (md5    . 1)
    206   (sha1   . 2)
    207   (sha224 . 3)
    208   (sha256 . 4)
    209   (sha384 . 5)
    210   (sha512 . 6))
    211 
    212 (rw.wire:defenum $ECCurveType (:type rw:u8)
    213   (explicit_prime . 1)
    214   (explicit_char2 . 2)
    215   (named_curve    . 3)
    216   #+nil(reserved 248..255))
    217 
    218 (rw.wire:defenum $NamedCurve (:type rw:u16be)
    219   (sect163k1 .  1)
    220   (sect163r1 .  2)
    221   (sect163r2 .  3)
    222   (sect193r1 .  4)
    223   (sect193r2 .  5)
    224   (sect233k1 .  6)
    225   (sect233r1 .  7)
    226   (sect239k1 .  8)
    227   (sect283k1 .  9)
    228   (sect283r1 . 10)
    229   (sect409k1 . 11)
    230   (sect409r1 . 12)
    231   (sect571k1 . 13)
    232   (sect571r1 . 14)
    233   (secp160k1 . 15)
    234   (secp160r1 . 16)
    235   (secp160r2 . 17)
    236   (secp192k1 . 18)
    237   (secp192r1 . 19)
    238   (secp224k1 . 20)
    239   (secp224r1 . 21)
    240   (secp256k1 . 22)
    241   (secp256r1 . 23)
    242   (secp384r1 . 24)
    243   (secp521r1 . 25)
    244   ;;reserved (0xfe00..0xfeff)
    245   (arbitrary_explicit_prime_curves . #xff01)
    246   (arbitrary_explicit_char2_curves . #xff02))
    247 
    248 (rw.wire:defenum %$SignatureHashAlgorithmSignature (:type rw:u8)
    249   (rsa . 1))
    250 
    251 (rw.wire:defenum $ECPointFormat (:type rw:u8)
    252   (uncompressed . 0)
    253   (ansiX962_compressed_prime . 1)
    254   (ansiX962_compressed_char2 . 2)
    255   #+nil(reserved 248..255))
    256 
    257 (defun PublicValueEncoding ()
    258   ;;'implicit
    259   'explicit)
    260 
    261 (defun KeyExchangeAlgorithm ()
    262   ;;'ecdhe_rsa
    263   'ec_diffie_hellman)
    264 
    265 ;; (rw.wire:defenum $KeyExchangeAlgorithm (:type rw:u8)
    266 ;;   (dhe_dss . 0)
    267 ;;   (dhe_rsa . 1)
    268 ;;   (dh_anon . 2)
    269 ;;   (rsa     . 3)
    270 ;;   (dh_dss  . 4)
    271 ;;   (dh_rsa  . 5))
    272 
    273 ;; ECDH_ECDSA          Fixed ECDH with ECDSA-signed certificates.
    274 ;; ECDHE_ECDSA         Ephemeral ECDH with ECDSA signatures.
    275 ;; ECDH_RSA            Fixed ECDH with RSA-signed certificates.
    276 ;; ECDHE_RSA           Ephemeral ECDH with RSA signatures.
    277 ;; ECDH_anon           Anonymous ECDH, no signatures.
    278 
    279 ;; (defun ECBasisType ()
    280 ;;   'ec_basis_trinomial
    281 ;;   'ec_basis_pentanomial)
    282 
    283 (defun SignatureAlgorithm ()
    284   ;;'anonymous
    285   ;;'rsa
    286   ;;'dsa
    287   'ecdsa)
    288 
    289 (rw.wire:defstruc $Alert ()
    290   ($AlertLevel level)
    291   ($AlertDescription description))
    292 
    293 #+nil
    294 (rw.wire:defstruc $ASN.1Cert ()
    295   (rw:u8 data :min 0 :max #.(1- (expt 2 24))))
    296 
    297 (rw.wire:defstruc %$Certificate ()
    298   (rw:u8 #+nil $ASN.1Cert data :length rw:u24be :min 0 :max #.(1- (expt 2 24)))
    299   (rw.wire::computed der :next (rw.der:next-der (rw:reader data))))
    300 
    301 (rw.wire:defstruc $Certificate ()
    302   (%$Certificate list :length rw:u24be :min 0 :max #.(1- (expt 2 24)) :size t))
    303 
    304 (rw.wire:defstruc %$ECPointFormatList ()
    305   ($ECPointFormat ec_point_format_list :length rw:u8 :min 1 :size t))
    306 
    307 (rw.wire:defstruc $ECPointFormatList ()
    308   (%$ECPointFormatList data :length rw:u16be))
    309 
    310 (rw.wire:defstruc $Extension ()
    311   ($ExtensionType type)
    312   ((ecase type
    313      ;;(status_request)
    314      ;;(server_name)
    315      ;;(renegotiation_info)
    316      ;;(SessionTicket_TLS)
    317      ;;(elliptic_curves)
    318      (ec_point_formats $ECPointFormatList)
    319      #+nil(signature_algorithms))
    320    data)
    321   #+nil(rw:u8 data :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
    322 
    323 (rw.wire:defstruc $ClientHello ()
    324   ($ContentVersion #+nil $ProtocolVersion version)
    325   ($Random random)
    326   ($SessionID session_id)
    327   ($CipherSuite cipher_suites :length rw:u16be :min 2 :max #.(- (expt 2 16) 2) :size t)
    328   ($CompressionMethod compression_methods :length rw:u8 :min 1 :max #.(1- (expt 2 8)) :size t)
    329   ($Extension extensions :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
    330 
    331 (rw.wire:defstruc $ServerDHParams ()
    332   (rw:u8 dh_p :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
    333   (rw:u8 dh_g :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
    334   (rw:u8 dh_Ys :length rw:u16be :min 1 :max #.(1- (expt 2 16))))
    335 
    336 (rw.wire:defstruc $signed_params ()
    337   (rw:u8 client_random :size 32)
    338   (rw:u8 server_random :size 32)
    339   ($ServerDHParams params2))
    340 
    341 (rw.wire:defstruc %$ServerDHParams ()
    342   ($ServerDHParams params)
    343   ($signed_params signed_params))
    344 
    345 (rw.wire:defstruc $ECCurve ()
    346   (rw:u8 a :length rw:u8 :min 1)
    347   (rw:u8 b :length rw:u8 :min 1))
    348 
    349 ;;http://stackoverflow.com/questions/10936171/how-do-i-compress-or-encode-the-elliptic-curve-public-key-and-put-it-over-the-ne
    350 (rw.wire:defstruc $ECPoint ()
    351   ;;(rw:u8 data :length rw:u8 :min 1 :size t)
    352   (rw:u8 length)
    353   (rw:u8 #+nil $ECPointFormat format #+nil :check #+nil(= 4 format)) ;; 4=uncompressed 2|3=compressed
    354   ;;(rw.wire::computed format :compute (progn (assert (= 4 %format)) %format))
    355   (rw:u8 x :size (floor length 2))
    356   (rw:u8 y :size (floor length 2)))
    357 
    358 
    359 ;; (rw.wire:defstruc %$ExplicitPrime ()
    360 ;;   opaque      prime_p <1..2^8-1>
    361 ;;   ECCurve     curve
    362 ;;   ECPoint     base
    363 ;;   opaque      order <1..2^8-1>
    364 ;;   opaque      cofactor <1..2^8-1>)
    365 
    366 ;; (rw.wire:defstruc %$ExplicitChar2 ()
    367 ;;   uint16      m
    368 ;;   ECBasisType basis
    369 ;;   select (basis) {
    370 ;;   case ec_trinomial:
    371 ;;   opaque  k <1..2^8-1>
    372 ;;   case ec_pentanomial:
    373 ;;   opaque  k1 <1..2^8-1>
    374 ;;   opaque  k2 <1..2^8-1>
    375 ;;   opaque  k3 <1..2^8-1>
    376 ;;   }
    377 ;;   ECCurve     curve
    378 ;;   ECPoint     base
    379 ;;   opaque      order <1..2^8-1>
    380 ;;   opaque      cofactor <1..2^8-1>)
    381 
    382 (rw.wire:defstruc $ECParameters ()
    383   ($ECCurveType curve_type)
    384   ((ecase curve_type
    385      ;;(explicit_prime %$ExplicitPrime)
    386      ;;(explicit_char2 %$ExplicitChar2)
    387      (named_curve $NamedCurve))
    388    data))
    389 
    390 (rw.wire:defstruc $ServerECDHParams ()
    391   ($ECParameters curve_params)
    392   ($ECPoint public))
    393 
    394 (rw.wire:defstruc %$SignatureHashAlgorithm ()
    395   ($HashAlgorithm hash)
    396   (%$SignatureHashAlgorithmSignature signature))
    397 
    398 (rw.wire:defstruc %$ECSASignature () ;; digitally-signed
    399   (%$SignatureHashAlgorithm algorithm)
    400   (rw:u16be length #+nil :compute #+nil(ShaSize))
    401   (rw:u8 sha_hash :size length))
    402 
    403 (rw.wire:defstruc $Signature ()
    404   (rw.wire::computed algorithm :compute (SignatureAlgorithm))
    405   ((ecase algorithm
    406      (ecdsa %$ECSASignature))
    407    data))
    408 
    409 (rw.wire:defstruc %$ServerECDHParams ()
    410   ($ServerECDHParams params)
    411   ($Signature signed_params))
    412 
    413 (rw.wire:defstruc $ServerKeyExchange ()
    414   ;;(rw:u8 data :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
    415   (rw.wire::computed type :compute (KeyExchangeAlgorithm))
    416   ((ecase type
    417      ;;(dh_anon $ServerDHParams)
    418      ;;((dhe_dss dhe_rsa) %$ServerDHParams)
    419      (ec_diffie_hellman %$ServerECDHParams)
    420      #+nil((rsa dh_dss dh_rsa)))
    421    data))
    422 
    423 (rw.wire:defstruc $SessionID ()
    424   (rw:u8 data :length rw:u8 :min 0 :max 32 :size t))
    425 
    426 (rw.wire:defstruc $Random ()
    427   (rw:u32be gmt_unix_time)
    428   (rw:u8 random_bytes :size 28))
    429 
    430 (rw.wire:defstruc $ServerHello ()
    431   ($ContentVersion #+nil ProtocolVersion version)
    432   ($Random random)
    433   ($SessionID session_id)
    434   ($CipherSuite cipher_suite)
    435   ($CompressionMethod compression_method)
    436   ($Extension extensions :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
    437 
    438 (rw.wire:defstruc $dh_Yc ()
    439   (rw:u8 data :length rw:u16be :min 1 :max #.(1- (expt 2 16))))
    440 
    441 (rw.wire:defstruc $EncryptedPreMasterSecret ()
    442   ($PreMasterSecret pubkey_encrypted))
    443 
    444 (rw.wire:defstruc $ClientDiffieHellmanPublic ()
    445   (rw.wire::computed type :compute (PublicValueEncoding))
    446   ((ecase type
    447      (implicit)
    448      (explicit $dh_Yc))
    449    dh_public))
    450 
    451 (rw.wire:defstruc $ClientECDiffieHellmanPublic ()
    452   (rw.wire::computed type :compute (PublicValueEncoding))
    453   ((ecase type
    454      (implicit)
    455      (explicit $ECPoint)) ;; ecdh_Yc
    456    ecdh_public))
    457 
    458 (rw.wire:defstruc $ClientKeyExchange ()
    459   (rw.wire::computed type :compute (KeyExchangeAlgorithm))
    460   ((ecase type
    461      ;;(rsa $EncryptedPreMasterSecret)
    462      ;;((dhe_dss dhe_rsa dh_dss dh_rsa dh_anon) $ClientDiffieHellmanPublic)
    463      (ec_diffie_hellman $ClientECDiffieHellmanPublic))
    464    data))
    465 
    466 (rw.wire:defstruc $Handshake ()
    467   ($HandshakeType type)
    468   ((ecase type
    469      (CERTIFICATE $Certificate)
    470      (CLIENT_HELLO $ClientHello)
    471      (CLIENT_KEY_EXCHANGE $ClientKeyExchange)
    472      (SERVER_HELLO $ServerHello)
    473      (SERVER_HELLO_DONE)
    474      (SERVER_KEY_EXCHANGE $ServerKeyExchange))
    475    data :length rw:u24be))
    476 
    477 (rw.wire:defstruc $PreMasterSecret ()
    478   ($ContentVersion #+nil ProtocolVersion client_version)
    479   (rw:u8 random :size 46))
    480 
    481 (rw.wire:defstruc $Record ()
    482   ($ContentType type)
    483   (rw:u16be #+nil ContentVersion version)
    484   ((ecase type
    485      (ALERT $Alert)
    486      (HANDSHAKE $Handshake))
    487    data :length rw:u16be :min 1 :max 16383)
    488   #+nil
    489   (rw:u8 data :length rw:u16be :min 1 :max 16383 :size t))
    490 
    491 ;; struct {
    492 ;;          HashAlgorithm hash
    493 ;;          SignatureAlgorithm signature
    494 ;;    } SignatureAndHashAlgorithm
    495 
    496 ;;    SignatureAndHashAlgorithm
    497 ;;     supported_signature_algorithms<2..2^16-1>
    498 
    499 (defun random-octets (length)
    500   (loop
    501      for i from 0 below length
    502      collect (random 256)))
    503 
    504 (defun universal-time-to-unix (x)
    505   (- x #.(encode-universal-time 0 0 0 1 1 1970 0)))
    506 
    507 ;;(universal-time-to-unix (encode-universal-time 19 22 23 28 7 2014 0)) ;; TODO broken
    508 
    509 (defun write-client-hello (writer client-random client-hello-time)
    510   (write-$Record
    511    writer
    512    (make-$Record
    513     :type 'HANDSHAKE
    514     :version ($ContentVersion 'SSL3.0)
    515     :data (make-$Handshake
    516            :type 'CLIENT_HELLO
    517            :data (make-$ClientHello
    518                   :version 'TLS1.2
    519                   :random (make-$Random
    520                            :gmt_unix_time client-hello-time
    521                            :random_bytes client-random)
    522                   :session_id (make-$SessionID #+nil :data #+nil(random-octets 32))
    523                   :cipher_suites '(
    524                                    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    525                                    ;; TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    526                                    ;; TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
    527                                    )
    528                   :compression_methods (list 'null)
    529                   :extensions (list
    530                                #+nil
    531                                (make-$Extension :type 'status_request
    532                                                 :data '(1 0 0 0 0))
    533                                #+nil
    534                                (make-$Extension :type 'server_name
    535                                                 :data '(0 #x10 0 0 #xd #x77 #x69 #x6b #x69 #x70 #x65 #x64 #x69 #x61 #x2e #x6f #x72 #x67))
    536                                #+nil
    537                                (make-$Extension :type 'renegotiation_info
    538                                                 :data '(0))
    539                                #+nil
    540                                (make-$Extension :type 'SessionTicket_TLS :data nil)
    541                                #+nil
    542                                (make-$Extension :type 'elliptic_curves ;; TODO
    543                                                 :data '(0 10 0 #x13 0 #x15 0 #x17 0 #x18 0 #x19))
    544                                (make-$Extension
    545                                 :type 'ec_point_formats ;; TODO
    546                                 :data (make-$ECPointFormatList
    547                                        :data
    548                                        (make-%$ECPointFormatList
    549                                         :ec_point_format_list
    550                                         '(uncompressed))))
    551                                #+nil
    552                                (make-$Extension :type 'signature_algorithms ;; TODO
    553                                                 :data '(0 #x1a 4 1 4 2 4 3 5 1 5 3 6 1 6 3 3 1 3 2 3 3 2 1 2 2 2 3))))))))
    554 
    555 (defun write-client-key-exchange (writer)
    556   (write-$Record
    557    writer
    558    (make-$Record
    559     :type 'HANDSHAKE
    560     :version ($ContentVersion 'SSL3.0)
    561     :data (make-$Handshake
    562            :type 'CLIENT_KEY_EXCHANGE
    563            :data (make-$ClientKeyExchange
    564                   :type 'dhe_rsa
    565                   :data (make-$ClientECDiffieHellmanPublic
    566                          :type 'explicit
    567                          :ecdh_public (make-$ECPoint
    568                                        :length 65
    569                                        :format 4 ;;'uncompressed
    570                                        :x #(47 33 158 197 200 79 233 37 253 19
    571                                             101 180 145 99 27 72 189 79 195 35
    572                                             43 226 40 247 85 134 48 189 7 134
    573                                             71 97)
    574                                        :y #(26 90 191 31 48 24 153 65 243 211
    575                                             213 24 113 9 11 139 111 253 83 190
    576                                             215 197 143 219 71 194 44 136 240
    577                                             78 112 25))))))))
    578 
    579 (defun next-server-hello (reader client-hello-time)
    580   (let ((x (next-$Record reader)))
    581     (let ((x ($Record-data x)))
    582       (let ((x ($Handshake-data x)))
    583         (assert (eq 'TLS1.2 ($ServerHello-version x)))
    584         (assert (eq 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    585                     ($ServerHello-cipher_suite x)))
    586         (let ((x ($ServerHello-random x)))
    587           (assert (<= 0 (- ($Random-gmt_unix_time x) client-hello-time) 1))
    588           ($Random-random_bytes x))
    589         ;; TODO server hello extensions
    590         ))))
    591 
    592 (defun next-server-certificate (reader)
    593   (let ((x (next-$Record reader)))
    594     (let ((x ($Record-data x)))
    595       (let ((x ($Handshake-data x)))
    596         (loop
    597            for x in ($Certificate-list x)
    598            collect (%$Certificate-der x))))))
    599 (defun der-decode-bit-string (x)
    600   (destructuring-bind (tag m n) x
    601     (assert (eq 'rw.der::bit-string tag))
    602     (assert (zerop m))
    603     (let* ((x (ash n m))
    604            (nbytes (ceiling (integer-length x) 8))
    605            (b (rw.wire:make-octet-buffer nbytes))
    606            (w (rw:writer b)))
    607       (loop
    608          for i from (1- nbytes) downto 0
    609          do (rw:write-u8 w (ldb (byte 8 (* 8 i)) x)))
    610       (rw.der:next-der (rw:reader b)))))
    611 
    612 (defun certificate-r-s (x)
    613   (labels ((rec (x)
    614              (when (consp x)
    615                (when (equal (car x)
    616                             '((rw.der::oid 1 2 840 113549 1 1 1) nil))
    617                  (assert (not (cddr x)))
    618                  (destructuring-bind (r s) (der-decode-bit-string (cadr x))
    619                    ;;(print (list :@@@ r s))
    620                    (return-from certificate-r-s (values r s))))
    621                (mapc #'rec x))))
    622     (rec x)))
    623 
    624 (defun next-server-key-exchange (reader client-random server-random server-certificates)
    625   (certificate-r-s (car server-certificates)) ;; TODO r s
    626   (let ((x (next-$Record reader)))
    627     (let ((x ($Record-data x)))
    628       (let ((x ($Handshake-data x)))
    629         (assert (eq 'ec_diffie_hellman ($ServerKeyExchange-type x)))
    630         (let ((x ($ServerKeyExchange-data x)))
    631           (let ((x (%$serverecdhparams-params x)))
    632             (let ((b (rw.wire:make-octet-buffer 42)))
    633               (write-$ServerECDHParams (rw:writer b) x)
    634               #+nil(print (list :@@@ :params b)))
    635             (let ((x ($serverecdhparams-public x)))
    636               ))
    637           (let ((x (%$serverecdhparams-signed_params x)))
    638             (assert (eq 'ecdsa ($signature-algorithm x)))
    639             (let ((x ($signature-data x)))
    640               (let ((hash (%$ecsasignature-sha_hash x)))
    641                 #+nil(print (list :@@@ :hash hash)))))
    642           ;; TODO check signed params
    643           (print x))))))
    644 
    645 (defun next-server-hello-done (reader)
    646   (let ((x (next-$Record reader)))
    647     ;;(print x)
    648     (let ((x ($Record-data x)))
    649       (assert (eq 'SERVER_HELLO_DONE ($Handshake-type x)))
    650       (assert (not ($Handshake-data x))))))
    651 
    652 #+nil
    653 (let ((saved (test)))
    654   (with-open-file (s "/tmp/a"
    655                      :direction :output
    656                      :if-exists :supersede
    657                      :if-does-not-exist :create
    658                      :element-type '(unsigned-byte 8))
    659     (write-sequence saved s))
    660   (with-open-file (s "/tmp/a" :element-type '(unsigned-byte 8))
    661     (next-$Record (rw:byte-reader s))
    662     #+nil(next-$ClientHello (record-reader (rw:byte-reader s)))))
    663 
    664 (defun %tls-connect (reader writer)
    665   (let ((client-random (random-octets 28))
    666         (client-hello-time (universal-time-to-unix (get-universal-time))))
    667     (write-client-hello writer client-random client-hello-time)
    668     (rw.wire:flush writer)
    669     (let ((server-random (next-server-hello reader client-hello-time))
    670           (server-certificates (next-server-certificate reader)))
    671       (next-server-key-exchange reader client-random server-random
    672                                 server-certificates)
    673       ;; TODO certificate request
    674       (next-server-hello-done reader)
    675       ;; TODO certificate
    676       (write-client-key-exchange writer)
    677       ;; TODO certificate verify
    678       ;; change cipher spec <<<<<<<<<<<<<<<<<<<<
    679       ;; multiple handshake messages
    680       (rw.wire:flush writer)
    681       (next-$Record reader) ;; expecting alert handshake failure
    682       #+nil
    683       (list (next-$Record r) ;; new session ticket
    684             (next-$Record r) ;; change cipher spec
    685             (next-$Record r) ;; encrypted handshake message
    686             ))))
    687 
    688 (defun tls-connect (hostname &optional (port 443))
    689   (with-open-stream (s (rw.socket:make-tcp-client-socket hostname port))
    690     (%tls-connect (rw:byte-reader s) (rw.wire:packet-writer s))))
    691 
    692 ;;(tls-connect "wikipedia.org")
    693 ;;(tls-connect "127.1" 5556)