1*37da2899SCharles.Forsyth# 2*37da2899SCharles.Forsyth# SSL 3.0 protocol 3*37da2899SCharles.Forsyth# 4*37da2899SCharles.Forsythimplement SSL3; 5*37da2899SCharles.Forsyth 6*37da2899SCharles.Forsythinclude "sys.m"; 7*37da2899SCharles.Forsyth sys : Sys; 8*37da2899SCharles.Forsyth 9*37da2899SCharles.Forsythinclude "keyring.m"; 10*37da2899SCharles.Forsyth keyring : Keyring; 11*37da2899SCharles.Forsyth IPint, DigestState : import keyring; 12*37da2899SCharles.Forsyth 13*37da2899SCharles.Forsythinclude "security.m"; 14*37da2899SCharles.Forsyth random : Random; 15*37da2899SCharles.Forsyth ssl : SSL; 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsythinclude "daytime.m"; 18*37da2899SCharles.Forsyth daytime : Daytime; 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsythinclude "asn1.m"; 21*37da2899SCharles.Forsyth asn1 : ASN1; 22*37da2899SCharles.Forsyth 23*37da2899SCharles.Forsythinclude "pkcs.m"; 24*37da2899SCharles.Forsyth pkcs : PKCS; 25*37da2899SCharles.Forsyth DHParams, DHPublicKey, DHPrivateKey, 26*37da2899SCharles.Forsyth RSAParams, RSAKey, 27*37da2899SCharles.Forsyth DSSPrivateKey, DSSPublicKey : import PKCS; 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsythinclude "x509.m"; 30*37da2899SCharles.Forsyth x509 : X509; 31*37da2899SCharles.Forsyth Signed, Certificate, SubjectPKInfo : import x509; 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsythinclude "sslsession.m"; 34*37da2899SCharles.Forsyth sslsession : SSLsession; 35*37da2899SCharles.Forsyth Session : import sslsession; 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsythinclude "ssl3.m"; 38*37da2899SCharles.Forsyth 39*37da2899SCharles.Forsyth# 40*37da2899SCharles.Forsyth# debug mode 41*37da2899SCharles.Forsyth# 42*37da2899SCharles.ForsythSSL_DEBUG : con 0; 43*37da2899SCharles.Forsythlogfd : ref Sys->FD; 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth# 46*37da2899SCharles.Forsyth# version {major, minor} 47*37da2899SCharles.Forsyth# 48*37da2899SCharles.ForsythSSL_VERSION_2_0 := array [] of {byte 0, byte 16r02}; 49*37da2899SCharles.ForsythSSL_VERSION_3_0 := array [] of {byte 16r03, byte 0}; 50*37da2899SCharles.Forsyth 51*37da2899SCharles.Forsyth 52*37da2899SCharles.Forsyth# SSL Record Protocol 53*37da2899SCharles.Forsyth 54*37da2899SCharles.ForsythSSL_CHANGE_CIPHER_SPEC : con 20; 55*37da2899SCharles.Forsyth SSL_ALERT : con 21; 56*37da2899SCharles.Forsyth SSL_HANDSHAKE : con 22; 57*37da2899SCharles.Forsyth SSL_APPLICATION_DATA : con 23; 58*37da2899SCharles.Forsyth SSL_V2HANDSHAKE : con 0; # escape to sslv2 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth# SSL Application Protocol consists of alert protocol, change cipher spec protocol 61*37da2899SCharles.Forsyth# v2 and v3 handshake protocol and application data protocol. The v2 handshake 62*37da2899SCharles.Forsyth# protocol is included only for backward compatibility 63*37da2899SCharles.Forsyth 64*37da2899SCharles.ForsythProtocol: adt { 65*37da2899SCharles.Forsyth pick { 66*37da2899SCharles.Forsyth pAlert => 67*37da2899SCharles.Forsyth alert : ref Alert; 68*37da2899SCharles.Forsyth pChangeCipherSpec => 69*37da2899SCharles.Forsyth change_cipher_spec : ref ChangeCipherSpec; 70*37da2899SCharles.Forsyth pHandshake => 71*37da2899SCharles.Forsyth handshake : ref Handshake; 72*37da2899SCharles.Forsyth pV2Handshake => 73*37da2899SCharles.Forsyth handshake : ref V2Handshake; 74*37da2899SCharles.Forsyth pApplicationData => 75*37da2899SCharles.Forsyth data : array of byte; 76*37da2899SCharles.Forsyth } 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth decode: fn(r: ref Record, ctx: ref Context): (ref Protocol, string); 79*37da2899SCharles.Forsyth encode: fn(p: self ref Protocol, vers: array of byte): (ref Record, string); 80*37da2899SCharles.Forsyth tostring: fn(p: self ref Protocol): string; 81*37da2899SCharles.Forsyth}; 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth# 84*37da2899SCharles.Forsyth# ssl alert protocol 85*37da2899SCharles.Forsyth# 86*37da2899SCharles.ForsythSSL_WARNING : con 1; 87*37da2899SCharles.Forsyth SSL_FATAL : con 2; 88*37da2899SCharles.Forsyth 89*37da2899SCharles.ForsythSSL_CLOSE_NOTIFY : con 0; 90*37da2899SCharles.Forsyth SSL_UNEXPECTED_MESSAGE : con 10; 91*37da2899SCharles.Forsyth SSL_BAD_RECORD_MAC : con 20; 92*37da2899SCharles.Forsyth SSL_DECOMPRESSION_FAILURE : con 30; 93*37da2899SCharles.Forsyth SSL_HANDSHAKE_FAILURE : con 40; 94*37da2899SCharles.Forsyth SSL_NO_CERTIFICATE : con 41; 95*37da2899SCharles.Forsyth SSL_BAD_CERTIFICATE : con 42; 96*37da2899SCharles.Forsyth SSL_UNSUPPORTED_CERTIFICATE : con 43; 97*37da2899SCharles.Forsyth SSL_CERTIFICATE_REVOKED : con 44; 98*37da2899SCharles.Forsyth SSL_CERTIFICATE_EXPIRED : con 45; 99*37da2899SCharles.Forsyth SSL_CERTIFICATE_UNKNOWN : con 46; 100*37da2899SCharles.Forsyth SSL_ILLEGAL_PARAMETER : con 47; 101*37da2899SCharles.Forsyth 102*37da2899SCharles.ForsythAlert: adt { 103*37da2899SCharles.Forsyth level : int; 104*37da2899SCharles.Forsyth description : int; 105*37da2899SCharles.Forsyth 106*37da2899SCharles.Forsyth tostring: fn(a: self ref Alert): string; 107*37da2899SCharles.Forsyth}; 108*37da2899SCharles.Forsyth 109*37da2899SCharles.Forsyth# 110*37da2899SCharles.Forsyth# ssl change cipher spec protocol 111*37da2899SCharles.Forsyth# 112*37da2899SCharles.ForsythChangeCipherSpec: adt { 113*37da2899SCharles.Forsyth value : int; 114*37da2899SCharles.Forsyth}; 115*37da2899SCharles.Forsyth 116*37da2899SCharles.Forsyth# 117*37da2899SCharles.Forsyth# ssl handshake protocol 118*37da2899SCharles.Forsyth# 119*37da2899SCharles.ForsythSSL_HANDSHAKE_HELLO_REQUEST : con 0; 120*37da2899SCharles.Forsyth SSL_HANDSHAKE_CLIENT_HELLO : con 1; 121*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_HELLO : con 2; 122*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE : con 11; 123*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_KEY_EXCHANGE : con 12; 124*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE_REQUEST : con 13; 125*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_HELLO_DONE : con 14; 126*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE_VERIFY : con 15; 127*37da2899SCharles.Forsyth SSL_HANDSHAKE_CLIENT_KEY_EXCHANGE : con 16; 128*37da2899SCharles.Forsyth SSL_HANDSHAKE_FINISHED : con 20; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.ForsythHandshake: adt { 131*37da2899SCharles.Forsyth pick { 132*37da2899SCharles.Forsyth HelloRequest => 133*37da2899SCharles.Forsyth ClientHello => 134*37da2899SCharles.Forsyth version : array of byte; # [2] 135*37da2899SCharles.Forsyth random : array of byte; # [32] 136*37da2899SCharles.Forsyth session_id : array of byte; # <0..32> 137*37da2899SCharles.Forsyth suites : array of byte; # [2] x 138*37da2899SCharles.Forsyth compressions : array of byte; # [1] x 139*37da2899SCharles.Forsyth ServerHello => 140*37da2899SCharles.Forsyth version : array of byte; # [2] 141*37da2899SCharles.Forsyth random : array of byte; # [32] 142*37da2899SCharles.Forsyth session_id : array of byte; # <0..32> 143*37da2899SCharles.Forsyth suite : array of byte; # [2] 144*37da2899SCharles.Forsyth compression : byte; # [1] 145*37da2899SCharles.Forsyth Certificate => 146*37da2899SCharles.Forsyth cert_list : list of array of byte; # X509 cert chain 147*37da2899SCharles.Forsyth ServerKeyExchange => 148*37da2899SCharles.Forsyth xkey : array of byte; # exchange_keys 149*37da2899SCharles.Forsyth CertificateRequest => 150*37da2899SCharles.Forsyth cert_types : array of byte; 151*37da2899SCharles.Forsyth dn_list : list of array of byte; # DN list 152*37da2899SCharles.Forsyth ServerHelloDone => 153*37da2899SCharles.Forsyth CertificateVerify => 154*37da2899SCharles.Forsyth signature : array of byte; 155*37da2899SCharles.Forsyth ClientKeyExchange => 156*37da2899SCharles.Forsyth xkey : array of byte; 157*37da2899SCharles.Forsyth Finished => 158*37da2899SCharles.Forsyth md5_hash : array of byte; # [16] Keyring->MD5dlen 159*37da2899SCharles.Forsyth sha_hash : array of byte; # [20] Keyring->SHA1dlen 160*37da2899SCharles.Forsyth } 161*37da2899SCharles.Forsyth 162*37da2899SCharles.Forsyth decode: fn(buf: array of byte): (ref Handshake, string); 163*37da2899SCharles.Forsyth encode: fn(hm: self ref Handshake): (array of byte, string); 164*37da2899SCharles.Forsyth tostring: fn(hm: self ref Handshake): string; 165*37da2899SCharles.Forsyth}; 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsyth# cipher suites and cipher specs (default, not all supported) 168*37da2899SCharles.Forsyth# - key exchange, signature, encrypt and digest algorithms 169*37da2899SCharles.Forsyth 170*37da2899SCharles.ForsythSSL3_Suites := array [] of { 171*37da2899SCharles.Forsyth NULL_WITH_NULL_NULL => array [] of {byte 0, byte 16r00}, 172*37da2899SCharles.Forsyth 173*37da2899SCharles.Forsyth RSA_WITH_NULL_MD5 => array [] of {byte 0, byte 16r01}, 174*37da2899SCharles.Forsyth RSA_WITH_NULL_SHA => array [] of {byte 0, byte 16r02}, 175*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC4_40_MD5 => array [] of {byte 0, byte 16r03}, 176*37da2899SCharles.Forsyth RSA_WITH_RC4_128_MD5 => array [] of {byte 0, byte 16r04}, 177*37da2899SCharles.Forsyth RSA_WITH_RC4_128_SHA => array [] of {byte 0, byte 16r05}, 178*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC2_CBC_40_MD5 => array [] of {byte 0, byte 16r06}, 179*37da2899SCharles.Forsyth RSA_WITH_IDEA_CBC_SHA => array [] of {byte 0, byte 16r07}, 180*37da2899SCharles.Forsyth RSA_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r08}, 181*37da2899SCharles.Forsyth RSA_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r09}, 182*37da2899SCharles.Forsyth RSA_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r0A}, 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth DH_DSS_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r0B}, 185*37da2899SCharles.Forsyth DH_DSS_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r0C}, 186*37da2899SCharles.Forsyth DH_DSS_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r0D}, 187*37da2899SCharles.Forsyth DH_RSA_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r0E}, 188*37da2899SCharles.Forsyth DH_RSA_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r0F}, 189*37da2899SCharles.Forsyth DH_RSA_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r10}, 190*37da2899SCharles.Forsyth DHE_DSS_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r11}, 191*37da2899SCharles.Forsyth DHE_DSS_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r12}, 192*37da2899SCharles.Forsyth DHE_DSS_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r13}, 193*37da2899SCharles.Forsyth DHE_RSA_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r14}, 194*37da2899SCharles.Forsyth DHE_RSA_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r15}, 195*37da2899SCharles.Forsyth DHE_RSA_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r16}, 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_RC4_40_MD5 => array [] of {byte 0, byte 16r17}, 198*37da2899SCharles.Forsyth DH_anon_WITH_RC4_128_MD5 => array [] of {byte 0, byte 16r18}, 199*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_DES40_CBC_SHA => array [] of {byte 0, byte 16r19}, 200*37da2899SCharles.Forsyth DH_anon_WITH_DES_CBC_SHA => array [] of {byte 0, byte 16r1A}, 201*37da2899SCharles.Forsyth DH_anon_WITH_3DES_EDE_CBC_SHA => array [] of {byte 0, byte 16r1B}, 202*37da2899SCharles.Forsyth 203*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_NULL_SHA => array [] of {byte 0, byte 16r1C}, 204*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA => array [] of {byte 0, byte 16r1D}, 205*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_RC4_128_SHA => array [] of {byte 0, byte 16r1E}, 206*37da2899SCharles.Forsyth}; 207*37da2899SCharles.Forsyth 208*37da2899SCharles.Forsyth# 209*37da2899SCharles.Forsyth# key exchange algorithms 210*37da2899SCharles.Forsyth# 211*37da2899SCharles.ForsythDHmodlen : con 512; # default length 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth# 215*37da2899SCharles.Forsyth# certificate types 216*37da2899SCharles.Forsyth# 217*37da2899SCharles.ForsythSSL_RSA_sign : con 1; 218*37da2899SCharles.Forsyth SSL_DSS_sign : con 2; 219*37da2899SCharles.Forsyth SSL_RSA_fixed_DH : con 3; 220*37da2899SCharles.Forsyth SSL_DSS_fixed_DH : con 4; 221*37da2899SCharles.Forsyth SSL_RSA_emhemeral_DH : con 5; 222*37da2899SCharles.Forsyth SSL_DSS_empemeral_DH : con 6; 223*37da2899SCharles.Forsyth SSL_FORTEZZA_MISSI : con 20; 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth# 226*37da2899SCharles.Forsyth# cipher definitions 227*37da2899SCharles.Forsyth# 228*37da2899SCharles.ForsythSSL_EXPORT_TRUE : con 0; 229*37da2899SCharles.Forsyth SSL_EXPORT_FALSE : con 1; 230*37da2899SCharles.Forsyth 231*37da2899SCharles.ForsythSSL_NULL_CIPHER, 232*37da2899SCharles.Forsyth SSL_RC4, 233*37da2899SCharles.Forsyth SSL_RC2_CBC, 234*37da2899SCharles.Forsyth SSL_IDEA_CBC, 235*37da2899SCharles.Forsyth SSL_DES_CBC, 236*37da2899SCharles.Forsyth SSL_3DES_EDE_CBC, 237*37da2899SCharles.Forsyth SSL_FORTEZZA_CBC : con iota; 238*37da2899SCharles.Forsyth 239*37da2899SCharles.ForsythSSL_STREAM_CIPHER, 240*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER : con iota; 241*37da2899SCharles.Forsyth 242*37da2899SCharles.ForsythSSL_NULL_MAC, 243*37da2899SCharles.Forsyth SSL_MD5, 244*37da2899SCharles.Forsyth SSL_SHA : con iota; 245*37da2899SCharles.Forsyth 246*37da2899SCharles.Forsyth# 247*37da2899SCharles.Forsyth# MAC paddings 248*37da2899SCharles.Forsyth# 249*37da2899SCharles.ForsythSSL_MAX_MAC_PADDING : con 48; 250*37da2899SCharles.ForsythSSL_MAC_PAD1 := array [] of { 251*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 252*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 253*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 254*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 255*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 256*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 257*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 258*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 259*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 260*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 261*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 262*37da2899SCharles.Forsyth byte 16r36, byte 16r36, byte 16r36, byte 16r36, 263*37da2899SCharles.Forsyth}; 264*37da2899SCharles.ForsythSSL_MAC_PAD2 := array [] of { 265*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 266*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 267*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 268*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 269*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 270*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 271*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 272*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 273*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 274*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 275*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 276*37da2899SCharles.Forsyth byte 16r5c, byte 16r5c, byte 16r5c, byte 16r5c, 277*37da2899SCharles.Forsyth}; 278*37da2899SCharles.Forsyth 279*37da2899SCharles.Forsyth# 280*37da2899SCharles.Forsyth# finished messages 281*37da2899SCharles.Forsyth# 282*37da2899SCharles.ForsythSSL_CLIENT_SENDER := array [] of { 283*37da2899SCharles.Forsyth byte 16r43, byte 16r4C, byte 16r4E, byte 16r54}; 284*37da2899SCharles.ForsythSSL_SERVER_SENDER := array [] of { 285*37da2899SCharles.Forsyth byte 16r53, byte 16r52, byte 16r56, byte 16r52}; 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth# 288*37da2899SCharles.Forsyth# a default distiguished names 289*37da2899SCharles.Forsyth# 290*37da2899SCharles.ForsythRSA_COMMERCIAL_CA_ROOT_SUBJECT_NAME := array [] of { 291*37da2899SCharles.Forsyth byte 16r30, byte 16r5F, byte 16r31, byte 16r0B, 292*37da2899SCharles.Forsyth byte 16r30, byte 16r09, byte 16r06, byte 16r03, 293*37da2899SCharles.Forsyth byte 16r55, byte 16r04, byte 16r06, byte 16r13, 294*37da2899SCharles.Forsyth byte 16r02, byte 16r55, byte 16r53, byte 16r31, 295*37da2899SCharles.Forsyth byte 16r20, byte 16r30, byte 16r1E, byte 16r06, 296*37da2899SCharles.Forsyth byte 16r03, byte 16r55, byte 16r04, byte 16r0A, 297*37da2899SCharles.Forsyth byte 16r13, byte 16r17, byte 16r52, byte 16r53, 298*37da2899SCharles.Forsyth byte 16r41, byte 16r20, byte 16r44, byte 16r61, 299*37da2899SCharles.Forsyth byte 16r74, byte 16r61, byte 16r20, byte 16r53, 300*37da2899SCharles.Forsyth byte 16r65, byte 16r63, byte 16r75, byte 16r72, 301*37da2899SCharles.Forsyth byte 16r69, byte 16r74, byte 16r79, byte 16r2C, 302*37da2899SCharles.Forsyth byte 16r20, byte 16r49, byte 16r6E, byte 16r63, 303*37da2899SCharles.Forsyth byte 16r2E, byte 16r31, byte 16r2E, byte 16r30, 304*37da2899SCharles.Forsyth byte 16r2C, byte 16r06, byte 16r03, byte 16r55, 305*37da2899SCharles.Forsyth byte 16r04, byte 16r0B, byte 16r13, byte 16r25, 306*37da2899SCharles.Forsyth byte 16r53, byte 16r65, byte 16r63, byte 16r75, 307*37da2899SCharles.Forsyth byte 16r72, byte 16r65, byte 16r20, byte 16r53, 308*37da2899SCharles.Forsyth byte 16r65, byte 16r72, byte 16r76, byte 16r65, 309*37da2899SCharles.Forsyth byte 16r72, byte 16r20, byte 16r43, byte 16r65, 310*37da2899SCharles.Forsyth byte 16r72, byte 16r74, byte 16r69, byte 16r66, 311*37da2899SCharles.Forsyth byte 16r69, byte 16r63, byte 16r61, byte 16r74, 312*37da2899SCharles.Forsyth byte 16r69, byte 16r6F, byte 16r6E, byte 16r20, 313*37da2899SCharles.Forsyth byte 16r41, byte 16r75, byte 16r74, byte 16r68, 314*37da2899SCharles.Forsyth byte 16r6F, byte 16r72, byte 16r69, byte 16r74, 315*37da2899SCharles.Forsyth byte 16r79, 316*37da2899SCharles.Forsyth}; 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth# SSL internal status 319*37da2899SCharles.ForsythUSE_DEVSSL, 320*37da2899SCharles.Forsyth SSL3_RECORD, 321*37da2899SCharles.Forsyth SSL3_HANDSHAKE, 322*37da2899SCharles.Forsyth SSL2_HANDSHAKE, 323*37da2899SCharles.Forsyth CLIENT_SIDE, 324*37da2899SCharles.Forsyth SESSION_RESUMABLE, 325*37da2899SCharles.Forsyth CLIENT_AUTH, 326*37da2899SCharles.Forsyth CERT_REQUEST, 327*37da2899SCharles.Forsyth CERT_SENT, 328*37da2899SCharles.Forsyth CERT_RECEIVED, 329*37da2899SCharles.Forsyth OUT_READY, 330*37da2899SCharles.Forsyth IN_READY : con 1 << iota; 331*37da2899SCharles.Forsyth 332*37da2899SCharles.Forsyth# SSL internal state 333*37da2899SCharles.ForsythSTATE_EXIT, 334*37da2899SCharles.Forsyth STATE_CHANGE_CIPHER_SPEC, 335*37da2899SCharles.Forsyth STATE_HELLO_REQUEST, 336*37da2899SCharles.Forsyth STATE_CLIENT_HELLO, 337*37da2899SCharles.Forsyth STATE_SERVER_HELLO, 338*37da2899SCharles.Forsyth STATE_CLIENT_KEY_EXCHANGE, 339*37da2899SCharles.Forsyth STATE_SERVER_KEY_EXCHANGE, 340*37da2899SCharles.Forsyth STATE_SERVER_HELLO_DONE, 341*37da2899SCharles.Forsyth STATE_CLIENT_CERTIFICATE, 342*37da2899SCharles.Forsyth STATE_SERVER_CERTIFICATE, 343*37da2899SCharles.Forsyth STATE_CERTIFICATE_VERIFY, 344*37da2899SCharles.Forsyth STATE_FINISHED : con iota; 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth# 347*37da2899SCharles.Forsyth# load necessary modules 348*37da2899SCharles.Forsyth# 349*37da2899SCharles.Forsythinit(): string 350*37da2899SCharles.Forsyth{ 351*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 352*37da2899SCharles.Forsyth if(sys == nil) 353*37da2899SCharles.Forsyth return "ssl3: load sys module failed"; 354*37da2899SCharles.Forsyth logfd = sys->fildes(1); 355*37da2899SCharles.Forsyth 356*37da2899SCharles.Forsyth keyring = load Keyring Keyring->PATH; 357*37da2899SCharles.Forsyth if(keyring == nil) 358*37da2899SCharles.Forsyth return "ssl3: load keyring module failed"; 359*37da2899SCharles.Forsyth 360*37da2899SCharles.Forsyth random = load Random Random->PATH; 361*37da2899SCharles.Forsyth if(random == nil) 362*37da2899SCharles.Forsyth return "ssl3: load random module failed"; 363*37da2899SCharles.Forsyth 364*37da2899SCharles.Forsyth daytime = load Daytime Daytime->PATH; 365*37da2899SCharles.Forsyth if(daytime == nil) 366*37da2899SCharles.Forsyth return "ssl3: load Daytime module failed"; 367*37da2899SCharles.Forsyth 368*37da2899SCharles.Forsyth pkcs = load PKCS PKCS->PATH; 369*37da2899SCharles.Forsyth if(pkcs == nil) 370*37da2899SCharles.Forsyth return "ssl3: load pkcs module failed"; 371*37da2899SCharles.Forsyth pkcs->init(); 372*37da2899SCharles.Forsyth 373*37da2899SCharles.Forsyth x509 = load X509 X509->PATH; 374*37da2899SCharles.Forsyth if(x509 == nil) 375*37da2899SCharles.Forsyth return "ssl3: load x509 module failed"; 376*37da2899SCharles.Forsyth x509->init(); 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth ssl = load SSL SSL->PATH; 379*37da2899SCharles.Forsyth if(ssl == nil) 380*37da2899SCharles.Forsyth return "ssl3: load SSL module failed"; 381*37da2899SCharles.Forsyth sslsession = load SSLsession SSLsession->PATH; 382*37da2899SCharles.Forsyth if(sslsession == nil) 383*37da2899SCharles.Forsyth return "ssl3: load sslsession module failed"; 384*37da2899SCharles.Forsyth e := sslsession->init(); 385*37da2899SCharles.Forsyth if(e != nil) 386*37da2899SCharles.Forsyth return "ssl3: sslsession init failed: "+e; 387*37da2899SCharles.Forsyth 388*37da2899SCharles.Forsyth return ""; 389*37da2899SCharles.Forsyth} 390*37da2899SCharles.Forsyth 391*37da2899SCharles.Forsythlog(s: string) 392*37da2899SCharles.Forsyth{ 393*37da2899SCharles.Forsyth a := array of byte (s + "\n"); 394*37da2899SCharles.Forsyth sys->write(logfd, a, len a); 395*37da2899SCharles.Forsyth} 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsyth# 398*37da2899SCharles.Forsyth# protocol context 399*37da2899SCharles.Forsyth# 400*37da2899SCharles.Forsyth 401*37da2899SCharles.ForsythContext.new(): ref Context 402*37da2899SCharles.Forsyth{ 403*37da2899SCharles.Forsyth ctx := ref Context; 404*37da2899SCharles.Forsyth 405*37da2899SCharles.Forsyth ctx.c = nil; 406*37da2899SCharles.Forsyth ctx.session = nil; 407*37da2899SCharles.Forsyth ctx.local_info = nil; 408*37da2899SCharles.Forsyth 409*37da2899SCharles.Forsyth ctx.sha_state = nil; 410*37da2899SCharles.Forsyth ctx.md5_state = nil; 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth ctx.status = 0; 413*37da2899SCharles.Forsyth ctx.state = 0; 414*37da2899SCharles.Forsyth 415*37da2899SCharles.Forsyth ctx.client_random = array [32] of byte; 416*37da2899SCharles.Forsyth ctx.server_random = array [32] of byte; 417*37da2899SCharles.Forsyth 418*37da2899SCharles.Forsyth ctx.cw_mac = nil; 419*37da2899SCharles.Forsyth ctx.sw_mac = nil; 420*37da2899SCharles.Forsyth ctx.cw_key = nil; 421*37da2899SCharles.Forsyth ctx.sw_key = nil; 422*37da2899SCharles.Forsyth ctx.cw_IV = nil; 423*37da2899SCharles.Forsyth ctx.sw_IV = nil; 424*37da2899SCharles.Forsyth 425*37da2899SCharles.Forsyth ctx.in_queue = RecordQueue.new(); 426*37da2899SCharles.Forsyth ctx.in_queue.data = ref Record(0, nil, array [1<<15] of byte) :: nil; 427*37da2899SCharles.Forsyth ctx.out_queue = RecordQueue.new(); 428*37da2899SCharles.Forsyth 429*37da2899SCharles.Forsyth # set session resumable as default 430*37da2899SCharles.Forsyth ctx.status |= SESSION_RESUMABLE; 431*37da2899SCharles.Forsyth 432*37da2899SCharles.Forsyth return ctx; 433*37da2899SCharles.Forsyth} 434*37da2899SCharles.Forsyth 435*37da2899SCharles.ForsythContext.client(ctx: self ref Context, fd: ref Sys->FD, peername: string, ver: int, info: ref Authinfo) 436*37da2899SCharles.Forsyth : (string, int) 437*37da2899SCharles.Forsyth{ 438*37da2899SCharles.Forsyth if(SSL_DEBUG) 439*37da2899SCharles.Forsyth log(sys->sprint("ssl3: Context.Client peername=%s ver=%d\n", peername, ver)); 440*37da2899SCharles.Forsyth if ((ckstr := cksuites(info.suites)) != nil) 441*37da2899SCharles.Forsyth return (ckstr, ver); 442*37da2899SCharles.Forsyth # the order is important 443*37da2899SCharles.Forsyth ctx.local_info = info; 444*37da2899SCharles.Forsyth ctx.state = STATE_HELLO_REQUEST; 445*37da2899SCharles.Forsyth e := ctx.connect(fd); 446*37da2899SCharles.Forsyth if(e != "") 447*37da2899SCharles.Forsyth return (e, ver); 448*37da2899SCharles.Forsyth ctx.session = sslsession->get_session_byname(peername); 449*37da2899SCharles.Forsyth 450*37da2899SCharles.Forsyth # Request to resume an SSL 3.0 session should use an SSL 3.0 client hello 451*37da2899SCharles.Forsyth if(ctx.session.session_id != nil) { 452*37da2899SCharles.Forsyth if((ctx.session.version[0] == SSL_VERSION_3_0[0]) && 453*37da2899SCharles.Forsyth (ctx.session.version[1] == SSL_VERSION_3_0[1])) { 454*37da2899SCharles.Forsyth ver = 3; 455*37da2899SCharles.Forsyth ctx.status |= SSL3_HANDSHAKE; 456*37da2899SCharles.Forsyth ctx.status &= ~SSL2_HANDSHAKE; 457*37da2899SCharles.Forsyth } 458*37da2899SCharles.Forsyth } 459*37da2899SCharles.Forsyth e = ctx.set_version(ver); 460*37da2899SCharles.Forsyth if(e != "") 461*37da2899SCharles.Forsyth return (e, ver); 462*37da2899SCharles.Forsyth reset_client_random(ctx); 463*37da2899SCharles.Forsyth ctx.status |= CLIENT_SIDE; 464*37da2899SCharles.Forsyth e = do_protocol(ctx); 465*37da2899SCharles.Forsyth if(e != nil) 466*37da2899SCharles.Forsyth return (e, ver); 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) 469*37da2899SCharles.Forsyth ver = 3; 470*37da2899SCharles.Forsyth else 471*37da2899SCharles.Forsyth ver = 2; 472*37da2899SCharles.Forsyth return (nil, ver); 473*37da2899SCharles.Forsyth} 474*37da2899SCharles.Forsyth 475*37da2899SCharles.ForsythContext.server(ctx: self ref Context, fd: ref Sys->FD, info: ref Authinfo, client_auth: int) 476*37da2899SCharles.Forsyth : string 477*37da2899SCharles.Forsyth{ 478*37da2899SCharles.Forsyth if ((ckstr := cksuites(info.suites)) != nil) 479*37da2899SCharles.Forsyth return ckstr; 480*37da2899SCharles.Forsyth ctx.local_info = info; 481*37da2899SCharles.Forsyth if(client_auth) 482*37da2899SCharles.Forsyth ctx.status |= CLIENT_AUTH; 483*37da2899SCharles.Forsyth ctx.state = STATE_CLIENT_HELLO; 484*37da2899SCharles.Forsyth e := ctx.connect(fd); 485*37da2899SCharles.Forsyth if(e != "") 486*37da2899SCharles.Forsyth return e; 487*37da2899SCharles.Forsyth reset_server_random(ctx); 488*37da2899SCharles.Forsyth e = ctx.set_version(3); # set ssl device to version 3 489*37da2899SCharles.Forsyth if(e != "") 490*37da2899SCharles.Forsyth return e; 491*37da2899SCharles.Forsyth ctx.status &= ~CLIENT_SIDE; 492*37da2899SCharles.Forsyth e = do_protocol(ctx); 493*37da2899SCharles.Forsyth if(e != nil) 494*37da2899SCharles.Forsyth return e; 495*37da2899SCharles.Forsyth 496*37da2899SCharles.Forsyth return ""; 497*37da2899SCharles.Forsyth} 498*37da2899SCharles.Forsyth 499*37da2899SCharles.Forsyth 500*37da2899SCharles.ForsythContext.use_devssl(ctx: self ref Context) 501*37da2899SCharles.Forsyth{ 502*37da2899SCharles.Forsyth if(!(ctx.status & IN_READY) && !(ctx.status & OUT_READY)) 503*37da2899SCharles.Forsyth ctx.status |= USE_DEVSSL; 504*37da2899SCharles.Forsyth} 505*37da2899SCharles.Forsyth 506*37da2899SCharles.ForsythContext.set_version(ctx: self ref Context, vers: int): string 507*37da2899SCharles.Forsyth{ 508*37da2899SCharles.Forsyth err := ""; 509*37da2899SCharles.Forsyth 510*37da2899SCharles.Forsyth if(ctx.c == nil) { 511*37da2899SCharles.Forsyth err = "no connection provided"; 512*37da2899SCharles.Forsyth } 513*37da2899SCharles.Forsyth else { 514*37da2899SCharles.Forsyth if(SSL_DEBUG) 515*37da2899SCharles.Forsyth log("ssl3: record version = " + string vers); 516*37da2899SCharles.Forsyth 517*37da2899SCharles.Forsyth if(vers == 2) { 518*37da2899SCharles.Forsyth ctx.status &= ~SSL3_RECORD; 519*37da2899SCharles.Forsyth ctx.status &= ~SSL3_HANDSHAKE; 520*37da2899SCharles.Forsyth ctx.status |= SSL2_HANDSHAKE; 521*37da2899SCharles.Forsyth if (ctx.session != nil) 522*37da2899SCharles.Forsyth ctx.session.version = SSL_VERSION_2_0; 523*37da2899SCharles.Forsyth } 524*37da2899SCharles.Forsyth else if(vers == 3) { # may be sslv2 handshake using ssl3 record 525*37da2899SCharles.Forsyth ctx.status |= SSL3_RECORD; 526*37da2899SCharles.Forsyth ctx.status |= SSL3_HANDSHAKE; 527*37da2899SCharles.Forsyth ctx.status &= ~SSL2_HANDSHAKE; # tmp test only 528*37da2899SCharles.Forsyth if (ctx.session != nil) 529*37da2899SCharles.Forsyth ctx.session.version = SSL_VERSION_3_0; 530*37da2899SCharles.Forsyth } 531*37da2899SCharles.Forsyth else if(vers == 23) { # may be sslv2 handshake using ssl3 record 532*37da2899SCharles.Forsyth ctx.status &= ~SSL3_RECORD; 533*37da2899SCharles.Forsyth ctx.status |= SSL3_HANDSHAKE; 534*37da2899SCharles.Forsyth ctx.status |= SSL2_HANDSHAKE; 535*37da2899SCharles.Forsyth vers = 2; 536*37da2899SCharles.Forsyth } 537*37da2899SCharles.Forsyth else 538*37da2899SCharles.Forsyth err = "unsupported ssl device version"; 539*37da2899SCharles.Forsyth 540*37da2899SCharles.Forsyth if((err == "") && (ctx.status & USE_DEVSSL)) { 541*37da2899SCharles.Forsyth if(sys->fprint(ctx.c.cfd, "ver %d", vers) < 0) 542*37da2899SCharles.Forsyth err = sys->sprint("ssl3: set ssl device version failed: %r"); 543*37da2899SCharles.Forsyth } 544*37da2899SCharles.Forsyth } 545*37da2899SCharles.Forsyth 546*37da2899SCharles.Forsyth return err; 547*37da2899SCharles.Forsyth} 548*37da2899SCharles.Forsyth 549*37da2899SCharles.ForsythContext.connect(ctx: self ref Context, fd: ref Sys->FD): string 550*37da2899SCharles.Forsyth{ 551*37da2899SCharles.Forsyth err := ""; 552*37da2899SCharles.Forsyth 553*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) 554*37da2899SCharles.Forsyth (err, ctx.c) = ssl->connect(fd); 555*37da2899SCharles.Forsyth else { 556*37da2899SCharles.Forsyth ctx.c = ref Sys->Connection(fd, nil, ""); 557*37da2899SCharles.Forsyth ctx.in_queue.sequence_numbers[0] = 0; 558*37da2899SCharles.Forsyth ctx.out_queue.sequence_numbers[1] = 0; 559*37da2899SCharles.Forsyth } 560*37da2899SCharles.Forsyth 561*37da2899SCharles.Forsyth return err; 562*37da2899SCharles.Forsyth} 563*37da2899SCharles.Forsyth 564*37da2899SCharles.ForsythContext.read(ctx: self ref Context, a: array of byte, n: int): int 565*37da2899SCharles.Forsyth{ 566*37da2899SCharles.Forsyth if(ctx.state != STATE_EXIT || !(ctx.status & IN_READY)) { 567*37da2899SCharles.Forsyth if(SSL_DEBUG) 568*37da2899SCharles.Forsyth log("ssl3: read not ready\n"); 569*37da2899SCharles.Forsyth return -1; 570*37da2899SCharles.Forsyth } 571*37da2899SCharles.Forsyth 572*37da2899SCharles.Forsyth if(ctx.out_queue.data != nil) 573*37da2899SCharles.Forsyth record_write_queue(ctx); 574*37da2899SCharles.Forsyth 575*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 576*37da2899SCharles.Forsyth fd := ctx.c.dfd; 577*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 578*37da2899SCharles.Forsyth buf := array [n+3] of byte; 579*37da2899SCharles.Forsyth m := sys->read(fd, buf, n+3); # header + n bytes 580*37da2899SCharles.Forsyth if(m < 3) { 581*37da2899SCharles.Forsyth if(SSL_DEBUG) 582*37da2899SCharles.Forsyth log(sys->sprint("ssl3: read failure: %r")); 583*37da2899SCharles.Forsyth return -1; 584*37da2899SCharles.Forsyth } 585*37da2899SCharles.Forsyth 586*37da2899SCharles.Forsyth if(buf[1] != SSL_VERSION_3_0[0] || buf[2] != SSL_VERSION_3_0[1]) { 587*37da2899SCharles.Forsyth if(SSL_DEBUG) 588*37da2899SCharles.Forsyth log("ssl3: not ssl version 3 data: header = [" + bastr(buf[0:3]) + "]"); 589*37da2899SCharles.Forsyth return -1; 590*37da2899SCharles.Forsyth } 591*37da2899SCharles.Forsyth 592*37da2899SCharles.Forsyth a[0:] = buf[3:m]; 593*37da2899SCharles.Forsyth 594*37da2899SCharles.Forsyth content_type := int buf[0]; 595*37da2899SCharles.Forsyth case content_type { 596*37da2899SCharles.Forsyth SSL_APPLICATION_DATA => 597*37da2899SCharles.Forsyth break; 598*37da2899SCharles.Forsyth SSL_ALERT => 599*37da2899SCharles.Forsyth if(SSL_DEBUG) 600*37da2899SCharles.Forsyth log("ssl3: expect application data, got alert: [" + bastr(buf[3:m]) +"]"); 601*37da2899SCharles.Forsyth return 0; 602*37da2899SCharles.Forsyth SSL_HANDSHAKE => 603*37da2899SCharles.Forsyth if(SSL_DEBUG) 604*37da2899SCharles.Forsyth log("ssl3: expect application data, got handshake message"); 605*37da2899SCharles.Forsyth return 0; 606*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC => 607*37da2899SCharles.Forsyth if(SSL_DEBUG) 608*37da2899SCharles.Forsyth log("ssl3: dynamic change cipher spec not supported yet"); 609*37da2899SCharles.Forsyth return 0; 610*37da2899SCharles.Forsyth } 611*37da2899SCharles.Forsyth return m-3; 612*37da2899SCharles.Forsyth } 613*37da2899SCharles.Forsyth else 614*37da2899SCharles.Forsyth return sys->read(fd, a, n); 615*37da2899SCharles.Forsyth } 616*37da2899SCharles.Forsyth else { 617*37da2899SCharles.Forsyth q := ctx.in_queue; 618*37da2899SCharles.Forsyth got := 0; 619*37da2899SCharles.Forsyth if(q.fragment) { 620*37da2899SCharles.Forsyth d := (hd q.data).data; 621*37da2899SCharles.Forsyth m := q.e - q.b; 622*37da2899SCharles.Forsyth i := q.e - q.fragment; 623*37da2899SCharles.Forsyth if(q.fragment > n) { 624*37da2899SCharles.Forsyth a[0:] = d[i:i+n]; 625*37da2899SCharles.Forsyth q.fragment -= n; 626*37da2899SCharles.Forsyth got = n; 627*37da2899SCharles.Forsyth } 628*37da2899SCharles.Forsyth else { 629*37da2899SCharles.Forsyth a[0:] = d[i:q.e]; 630*37da2899SCharles.Forsyth got = q.fragment; 631*37da2899SCharles.Forsyth q.fragment = 0; 632*37da2899SCharles.Forsyth } 633*37da2899SCharles.Forsyth } 634*37da2899SCharles.Forsythout: 635*37da2899SCharles.Forsyth while(got < n) { 636*37da2899SCharles.Forsyth err := q.read(ctx, ctx.c.dfd); 637*37da2899SCharles.Forsyth if(err != "") { 638*37da2899SCharles.Forsyth if(SSL_DEBUG) 639*37da2899SCharles.Forsyth log("ssl3: read: " + err); 640*37da2899SCharles.Forsyth break; 641*37da2899SCharles.Forsyth } 642*37da2899SCharles.Forsyth r := hd q.data; 643*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 644*37da2899SCharles.Forsyth case r.content_type { 645*37da2899SCharles.Forsyth SSL_APPLICATION_DATA => 646*37da2899SCharles.Forsyth break; 647*37da2899SCharles.Forsyth SSL_ALERT => 648*37da2899SCharles.Forsyth if(SSL_DEBUG) 649*37da2899SCharles.Forsyth log("ssl3: read: got alert\n\t\t" + bastr(r.data[q.b:q.e])); 650*37da2899SCharles.Forsyth # delete session id 651*37da2899SCharles.Forsyth ctx.session.session_id = nil; 652*37da2899SCharles.Forsyth ctx.status &= ~IN_READY; 653*37da2899SCharles.Forsyth break out; 654*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC => 655*37da2899SCharles.Forsyth if(SSL_DEBUG) 656*37da2899SCharles.Forsyth log("ssl3: read: got change cipher spec\n"); 657*37da2899SCharles.Forsyth SSL_HANDSHAKE => 658*37da2899SCharles.Forsyth if(SSL_DEBUG) 659*37da2899SCharles.Forsyth log("ssl3: read: got handshake data\n"); 660*37da2899SCharles.Forsyth #do_handshake(ctx, r); # ? 661*37da2899SCharles.Forsyth * => 662*37da2899SCharles.Forsyth if(SSL_DEBUG) 663*37da2899SCharles.Forsyth log("ssl3: read: unknown data\n"); 664*37da2899SCharles.Forsyth } 665*37da2899SCharles.Forsyth } 666*37da2899SCharles.Forsyth 667*37da2899SCharles.Forsyth if((n - got) <= (q.e - q.b)) { 668*37da2899SCharles.Forsyth a[got:] = r.data[q.b:q.b+n-got]; 669*37da2899SCharles.Forsyth q.fragment = q.e - q.b - n + got; 670*37da2899SCharles.Forsyth got = n; 671*37da2899SCharles.Forsyth } 672*37da2899SCharles.Forsyth else { 673*37da2899SCharles.Forsyth a[got:] = r.data[q.b:q.e]; 674*37da2899SCharles.Forsyth q.fragment = 0; 675*37da2899SCharles.Forsyth got += q.e - q.b; 676*37da2899SCharles.Forsyth } 677*37da2899SCharles.Forsyth } 678*37da2899SCharles.Forsyth if(SSL_DEBUG) 679*37da2899SCharles.Forsyth log(sys->sprint("ssl3: read: returning %d bytes\n", got)); 680*37da2899SCharles.Forsyth return got; 681*37da2899SCharles.Forsyth } 682*37da2899SCharles.Forsyth} 683*37da2899SCharles.Forsyth 684*37da2899SCharles.ForsythContext.write(ctx: self ref Context, a: array of byte, n: int): int 685*37da2899SCharles.Forsyth{ 686*37da2899SCharles.Forsyth if(ctx.state != STATE_EXIT || !(ctx.status & OUT_READY)) 687*37da2899SCharles.Forsyth return-1; 688*37da2899SCharles.Forsyth 689*37da2899SCharles.Forsyth if(ctx.out_queue.data != nil) 690*37da2899SCharles.Forsyth record_write_queue(ctx); 691*37da2899SCharles.Forsyth 692*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 693*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 694*37da2899SCharles.Forsyth buf := array [n+3] of byte; 695*37da2899SCharles.Forsyth buf[0] = byte SSL_APPLICATION_DATA; 696*37da2899SCharles.Forsyth buf[1:] = SSL_VERSION_3_0; 697*37da2899SCharles.Forsyth buf[3:] = a[0:n]; 698*37da2899SCharles.Forsyth n = sys->write(ctx.c.dfd, buf, n+3); 699*37da2899SCharles.Forsyth if(n > 0) 700*37da2899SCharles.Forsyth n -= 3; 701*37da2899SCharles.Forsyth } 702*37da2899SCharles.Forsyth else 703*37da2899SCharles.Forsyth n = sys->write(ctx.c.dfd, a, n); 704*37da2899SCharles.Forsyth } 705*37da2899SCharles.Forsyth else { 706*37da2899SCharles.Forsyth q := ctx.out_queue; 707*37da2899SCharles.Forsyth v := SSL_VERSION_2_0; 708*37da2899SCharles.Forsyth if(ctx.status&SSL3_RECORD) 709*37da2899SCharles.Forsyth v = SSL_VERSION_3_0; 710*37da2899SCharles.Forsyth for(i := 0; i < n;){ 711*37da2899SCharles.Forsyth m := n-i; 712*37da2899SCharles.Forsyth if(m > q.length) 713*37da2899SCharles.Forsyth m = q.length; 714*37da2899SCharles.Forsyth r := ref Record(SSL_APPLICATION_DATA, v, a[i:i+m]); 715*37da2899SCharles.Forsyth record_write(r, ctx); # return error? 716*37da2899SCharles.Forsyth i += m; 717*37da2899SCharles.Forsyth } 718*37da2899SCharles.Forsyth } 719*37da2899SCharles.Forsyth return n; 720*37da2899SCharles.Forsyth} 721*37da2899SCharles.Forsyth 722*37da2899SCharles.Forsythdevssl_read(ctx: ref Context): (ref Record, string) 723*37da2899SCharles.Forsyth{ 724*37da2899SCharles.Forsyth buf := array [Sys->ATOMICIO] of byte; 725*37da2899SCharles.Forsyth r: ref Record; 726*37da2899SCharles.Forsyth c := ctx.c; 727*37da2899SCharles.Forsyth 728*37da2899SCharles.Forsyth n := sys->read(c.dfd, buf, 3); 729*37da2899SCharles.Forsyth if(n < 0) 730*37da2899SCharles.Forsyth return (nil, sys->sprint("record read: read failure: %r")); 731*37da2899SCharles.Forsyth 732*37da2899SCharles.Forsyth # in case of undetermined, do auto record version detection 733*37da2899SCharles.Forsyth if((ctx.state == SSL2_STATE_SERVER_HELLO) && 734*37da2899SCharles.Forsyth (ctx.status & SSL2_HANDSHAKE) && (ctx.status & SSL3_HANDSHAKE)) { 735*37da2899SCharles.Forsyth 736*37da2899SCharles.Forsyth fstatus := sys->open(ctx.c.dir + "/status", Sys->OREAD); 737*37da2899SCharles.Forsyth if(fstatus == nil) 738*37da2899SCharles.Forsyth return (nil, "open status: " + sys->sprint("%r")); 739*37da2899SCharles.Forsyth status := array [64] of byte; 740*37da2899SCharles.Forsyth nbyte := sys->read(fstatus, status, len status); 741*37da2899SCharles.Forsyth if(nbyte != 1) 742*37da2899SCharles.Forsyth return (nil, "read status: " + sys->sprint("%r")); 743*37da2899SCharles.Forsyth 744*37da2899SCharles.Forsyth ver := int status[0]; 745*37da2899SCharles.Forsyth 746*37da2899SCharles.Forsyth if(SSL_DEBUG) 747*37da2899SCharles.Forsyth log("ssl3: auto record version detect as: " + string ver); 748*37da2899SCharles.Forsyth 749*37da2899SCharles.Forsyth # assert ctx.status & SSL2_RECORD true ? before reset 750*37da2899SCharles.Forsyth if(ver == 2) { 751*37da2899SCharles.Forsyth ctx.status &= ~SSL3_RECORD; 752*37da2899SCharles.Forsyth ctx.status |= SSL2_HANDSHAKE; 753*37da2899SCharles.Forsyth ctx.status &= ~SSL3_HANDSHAKE; 754*37da2899SCharles.Forsyth } 755*37da2899SCharles.Forsyth else { 756*37da2899SCharles.Forsyth ctx.status |= SSL3_RECORD; 757*37da2899SCharles.Forsyth } 758*37da2899SCharles.Forsyth } 759*37da2899SCharles.Forsyth 760*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 761*37da2899SCharles.Forsyth if(n < 3) 762*37da2899SCharles.Forsyth return (nil, sys->sprint("record read: read failure: %r")); 763*37da2899SCharles.Forsyth 764*37da2899SCharles.Forsyth # assert only major version number 765*37da2899SCharles.Forsyth if(buf[1] != SSL_VERSION_3_0[0]) 766*37da2899SCharles.Forsyth return (nil, "record read: version mismatch"); 767*37da2899SCharles.Forsyth 768*37da2899SCharles.Forsyth case int buf[0] { 769*37da2899SCharles.Forsyth SSL_ALERT => 770*37da2899SCharles.Forsyth n = sys->read(c.dfd, buf, 5); # read in header plus rest 771*37da2899SCharles.Forsyth if(n != 5) 772*37da2899SCharles.Forsyth return (nil, sys->sprint("read alert failed: %r")); 773*37da2899SCharles.Forsyth r = ref Record(SSL_ALERT, SSL_VERSION_3_0, buf[3:5]); 774*37da2899SCharles.Forsyth 775*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC => 776*37da2899SCharles.Forsyth n = sys->read(c.dfd, buf, 4); # read in header plus rest 777*37da2899SCharles.Forsyth if(n != 4) 778*37da2899SCharles.Forsyth return (nil, sys->sprint("read change_cipher_spec failed: %r")); 779*37da2899SCharles.Forsyth r = ref Record(SSL_CHANGE_CIPHER_SPEC, SSL_VERSION_3_0, buf[3:4]); 780*37da2899SCharles.Forsyth 781*37da2899SCharles.Forsyth SSL_HANDSHAKE => 782*37da2899SCharles.Forsyth n = sys->read(c.dfd, buf, 7); # header + msg length 783*37da2899SCharles.Forsyth if(n != 7) 784*37da2899SCharles.Forsyth return (nil, sys->sprint("read handshake header + msg length failed: %r")); 785*37da2899SCharles.Forsyth m := int_decode(buf[4:7]); 786*37da2899SCharles.Forsyth if(m < 0) 787*37da2899SCharles.Forsyth return (nil, "read handshake failed: unexpected length"); 788*37da2899SCharles.Forsyth data := array [m+4] of byte; 789*37da2899SCharles.Forsyth data[0:] = buf[3:7]; # msg type + length 790*37da2899SCharles.Forsyth if(m != 0) { 791*37da2899SCharles.Forsyth # need exact m bytes (exclude header), otherwise failure 792*37da2899SCharles.Forsyth remain := m; 793*37da2899SCharles.Forsyth now := 4; 794*37da2899SCharles.Forsyth while(remain > 0) { 795*37da2899SCharles.Forsyth n = sys->read(c.dfd, buf, remain+3); # header + msg 796*37da2899SCharles.Forsyth if(n < 3 || int buf[0] != SSL_HANDSHAKE) 797*37da2899SCharles.Forsyth return (nil, sys->sprint("read handshake msg body failed: %r")); 798*37da2899SCharles.Forsyth sys->print("expect %d, got %d bytes\n", m, n-3); 799*37da2899SCharles.Forsyth remain -= n - 3; 800*37da2899SCharles.Forsyth data[now:] = buf[3:n]; 801*37da2899SCharles.Forsyth now += n - 3; 802*37da2899SCharles.Forsyth } 803*37da2899SCharles.Forsyth } 804*37da2899SCharles.Forsyth 805*37da2899SCharles.Forsyth r = ref Record(SSL_HANDSHAKE, SSL_VERSION_3_0, data); 806*37da2899SCharles.Forsyth * => 807*37da2899SCharles.Forsyth return (nil, "trying to read unknown protocol message"); 808*37da2899SCharles.Forsyth } 809*37da2899SCharles.Forsyth 810*37da2899SCharles.Forsyth if(SSL_DEBUG) 811*37da2899SCharles.Forsyth log("ssl3: record_read: \n\theader = \n\t\t" + bastr(buf[0:3]) 812*37da2899SCharles.Forsyth + "\n\tdata = \n\t\t" + bastr(r.data) + "\n"); 813*37da2899SCharles.Forsyth } 814*37da2899SCharles.Forsyth # v2 record layer 815*37da2899SCharles.Forsyth else { 816*37da2899SCharles.Forsyth # assume the handshake record size less than Sys->ATOMICIO 817*37da2899SCharles.Forsyth # in most case, this is ok 818*37da2899SCharles.Forsyth if(n == 3) { 819*37da2899SCharles.Forsyth n = sys->read(c.dfd, buf[3:], Sys->ATOMICIO - 3); 820*37da2899SCharles.Forsyth if(n < 0) 821*37da2899SCharles.Forsyth return (nil, sys->sprint("v2 record read: read failure: %r")); 822*37da2899SCharles.Forsyth } 823*37da2899SCharles.Forsyth 824*37da2899SCharles.Forsyth r = ref Record(SSL_V2HANDSHAKE, SSL_VERSION_2_0, buf[0:n+3]); 825*37da2899SCharles.Forsyth 826*37da2899SCharles.Forsyth if(SSL_DEBUG) 827*37da2899SCharles.Forsyth log("ssl3: v2 record_read: \n\tdata = \n\t\t" + bastr(r.data) + "\n"); 828*37da2899SCharles.Forsyth } 829*37da2899SCharles.Forsyth 830*37da2899SCharles.Forsyth return (r, nil); 831*37da2899SCharles.Forsyth} 832*37da2899SCharles.Forsyth 833*37da2899SCharles.Forsythrecord_read(ctx: ref Context): (ref Record, string) 834*37da2899SCharles.Forsyth{ 835*37da2899SCharles.Forsyth q := ctx.in_queue; 836*37da2899SCharles.Forsyth if(q.fragment == 0) { 837*37da2899SCharles.Forsyth err := q.read(ctx, ctx.c.dfd); 838*37da2899SCharles.Forsyth if(err != "") 839*37da2899SCharles.Forsyth return (nil, err); 840*37da2899SCharles.Forsyth q.fragment = q.e - q.b; 841*37da2899SCharles.Forsyth } 842*37da2899SCharles.Forsyth 843*37da2899SCharles.Forsyth r := hd q.data; 844*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 845*37da2899SCharles.Forsyth # confirm only major version number 846*37da2899SCharles.Forsyth if(r.version[0] != SSL_VERSION_3_0[0]) 847*37da2899SCharles.Forsyth return (nil, "record read: not v3 record"); 848*37da2899SCharles.Forsyth 849*37da2899SCharles.Forsyth case r.content_type { 850*37da2899SCharles.Forsyth SSL_ALERT => 851*37da2899SCharles.Forsyth a := array [2] of byte; 852*37da2899SCharles.Forsyth n := fetch_data(ctx, a, 2); 853*37da2899SCharles.Forsyth if(n != 2) 854*37da2899SCharles.Forsyth return (nil, "read alert failed"); 855*37da2899SCharles.Forsyth r = ref Record(SSL_ALERT, SSL_VERSION_3_0, a); 856*37da2899SCharles.Forsyth 857*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC => 858*37da2899SCharles.Forsyth a := array [1] of byte; 859*37da2899SCharles.Forsyth n := fetch_data(ctx, a, 1); 860*37da2899SCharles.Forsyth if(n != 1) 861*37da2899SCharles.Forsyth return (nil, "read change_cipher_spec failed"); 862*37da2899SCharles.Forsyth r = ref Record(SSL_CHANGE_CIPHER_SPEC, SSL_VERSION_3_0, a); 863*37da2899SCharles.Forsyth 864*37da2899SCharles.Forsyth SSL_HANDSHAKE => 865*37da2899SCharles.Forsyth a := array [4] of byte; 866*37da2899SCharles.Forsyth n := fetch_data(ctx, a, 4); 867*37da2899SCharles.Forsyth if(n != 4) 868*37da2899SCharles.Forsyth return (nil, "read message length failed"); 869*37da2899SCharles.Forsyth m := int_decode(a[1:]); 870*37da2899SCharles.Forsyth if(m < 0) 871*37da2899SCharles.Forsyth return (nil, "unexpected handshake message length"); 872*37da2899SCharles.Forsyth b := array [m+4] of byte; 873*37da2899SCharles.Forsyth b[0:] = a; 874*37da2899SCharles.Forsyth n = fetch_data(ctx, b[4:], m); 875*37da2899SCharles.Forsyth if(n != m) 876*37da2899SCharles.Forsyth return (nil, "read message body failed"); 877*37da2899SCharles.Forsyth r = ref Record(SSL_HANDSHAKE, SSL_VERSION_3_0, b); 878*37da2899SCharles.Forsyth * => 879*37da2899SCharles.Forsyth return (nil, "trying to read unknown protocol message"); 880*37da2899SCharles.Forsyth } 881*37da2899SCharles.Forsyth } 882*37da2899SCharles.Forsyth # v2 record layer 883*37da2899SCharles.Forsyth else { 884*37da2899SCharles.Forsyth r = ref Record(SSL_V2HANDSHAKE, SSL_VERSION_2_0, r.data[q.b:q.e]); 885*37da2899SCharles.Forsyth q.fragment = 0; 886*37da2899SCharles.Forsyth } 887*37da2899SCharles.Forsyth 888*37da2899SCharles.Forsyth return (r, nil); 889*37da2899SCharles.Forsyth} 890*37da2899SCharles.Forsyth 891*37da2899SCharles.Forsythfetch_data(ctx: ref Context, a: array of byte, n: int): int 892*37da2899SCharles.Forsyth{ 893*37da2899SCharles.Forsyth q := ctx.in_queue; 894*37da2899SCharles.Forsyth r := hd q.data; 895*37da2899SCharles.Forsyth 896*37da2899SCharles.Forsyth got := 0; 897*37da2899SCharles.Forsyth cnt := -1; 898*37da2899SCharles.Forsythout: 899*37da2899SCharles.Forsyth while(got < n) { 900*37da2899SCharles.Forsyth if(q.fragment) { 901*37da2899SCharles.Forsyth cnt = r.content_type; 902*37da2899SCharles.Forsyth i := q.e - q.fragment; 903*37da2899SCharles.Forsyth if(n-got <= q.fragment) { 904*37da2899SCharles.Forsyth a[got:] = r.data[i:i+n-got]; 905*37da2899SCharles.Forsyth q.fragment -= n - got; 906*37da2899SCharles.Forsyth got = n; 907*37da2899SCharles.Forsyth } 908*37da2899SCharles.Forsyth else { 909*37da2899SCharles.Forsyth a[got:] = r.data[i:q.e]; 910*37da2899SCharles.Forsyth got += q.fragment; 911*37da2899SCharles.Forsyth q.fragment = 0; 912*37da2899SCharles.Forsyth } 913*37da2899SCharles.Forsyth } 914*37da2899SCharles.Forsyth else { 915*37da2899SCharles.Forsyth err := q.read(ctx, ctx.c.dfd); 916*37da2899SCharles.Forsyth if(err != "") 917*37da2899SCharles.Forsyth break out; 918*37da2899SCharles.Forsyth if(cnt == -1) 919*37da2899SCharles.Forsyth cnt = r.content_type; 920*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 921*37da2899SCharles.Forsyth case r.content_type { 922*37da2899SCharles.Forsyth SSL_APPLICATION_DATA => 923*37da2899SCharles.Forsyth break; 924*37da2899SCharles.Forsyth * => 925*37da2899SCharles.Forsyth if(cnt != r.content_type) 926*37da2899SCharles.Forsyth break out; 927*37da2899SCharles.Forsyth } 928*37da2899SCharles.Forsyth } 929*37da2899SCharles.Forsyth else { 930*37da2899SCharles.Forsyth r.content_type = SSL_V2HANDSHAKE; 931*37da2899SCharles.Forsyth } 932*37da2899SCharles.Forsyth } 933*37da2899SCharles.Forsyth } 934*37da2899SCharles.Forsyth return got; 935*37da2899SCharles.Forsyth} 936*37da2899SCharles.Forsyth 937*37da2899SCharles.Forsythrecord_write(r: ref Record, ctx: ref Context) 938*37da2899SCharles.Forsyth{ 939*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 940*37da2899SCharles.Forsyth buf: array of byte; 941*37da2899SCharles.Forsyth n: int; 942*37da2899SCharles.Forsyth c := ctx.c; 943*37da2899SCharles.Forsyth 944*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 945*37da2899SCharles.Forsyth buf = array [3 + len r.data] of byte; 946*37da2899SCharles.Forsyth buf[0] = byte r.content_type; 947*37da2899SCharles.Forsyth buf[1:] = r.version; 948*37da2899SCharles.Forsyth buf[3:] = r.data; 949*37da2899SCharles.Forsyth n = sys->write(c.dfd, buf, len buf); 950*37da2899SCharles.Forsyth if(n < 0 || n != len buf) { 951*37da2899SCharles.Forsyth if(SSL_DEBUG) 952*37da2899SCharles.Forsyth log(sys->sprint("ssl3: v3 record write error: %d %r", n)); 953*37da2899SCharles.Forsyth return; # don't terminated until alerts being read 954*37da2899SCharles.Forsyth } 955*37da2899SCharles.Forsyth } 956*37da2899SCharles.Forsyth else { 957*37da2899SCharles.Forsyth buf = r.data; 958*37da2899SCharles.Forsyth n = sys->write(c.dfd, buf, len buf); 959*37da2899SCharles.Forsyth if(n < 0 || n != len buf) { 960*37da2899SCharles.Forsyth if(SSL_DEBUG) 961*37da2899SCharles.Forsyth log(sys->sprint("ssl3: v2 record write error: %d %r", n)); 962*37da2899SCharles.Forsyth return; # don't terminated until alerts being read 963*37da2899SCharles.Forsyth } 964*37da2899SCharles.Forsyth } 965*37da2899SCharles.Forsyth } 966*37da2899SCharles.Forsyth else 967*37da2899SCharles.Forsyth ctx.out_queue.write(ctx, ctx.c.dfd, r); 968*37da2899SCharles.Forsyth 969*37da2899SCharles.Forsyth # if(SSL_DEBUG) 970*37da2899SCharles.Forsyth # log("ssl3: record_write: \n\t\t" + bastr(buf) + "\n"); 971*37da2899SCharles.Forsyth} 972*37da2899SCharles.Forsyth 973*37da2899SCharles.ForsythRecordQueue.new(): ref RecordQueue 974*37da2899SCharles.Forsyth{ 975*37da2899SCharles.Forsyth q := ref RecordQueue( 976*37da2899SCharles.Forsyth ref MacState.null(0), 977*37da2899SCharles.Forsyth ref CipherState.null(1), 978*37da2899SCharles.Forsyth 1 << 15, 979*37da2899SCharles.Forsyth array [2] of { * => 0}, 980*37da2899SCharles.Forsyth nil, 981*37da2899SCharles.Forsyth 0, 982*37da2899SCharles.Forsyth 0, # b 983*37da2899SCharles.Forsyth 0 # e 984*37da2899SCharles.Forsyth ); 985*37da2899SCharles.Forsyth return q; 986*37da2899SCharles.Forsyth} 987*37da2899SCharles.Forsyth 988*37da2899SCharles.ForsythRecordQueue.read(q: self ref RecordQueue, ctx: ref Context, fd: ref Sys->FD): string 989*37da2899SCharles.Forsyth{ 990*37da2899SCharles.Forsyth r := hd q.data; 991*37da2899SCharles.Forsyth a := r.data; 992*37da2899SCharles.Forsyth if(ensure(fd, a, 2) < 0) 993*37da2899SCharles.Forsyth return "no more data"; 994*37da2899SCharles.Forsyth # auto record version detection 995*37da2899SCharles.Forsyth m, h, pad: int = 0; 996*37da2899SCharles.Forsyth if(int a[0] < 20 || int a[0] > 23) { 997*37da2899SCharles.Forsyth ctx.status &= ~SSL3_RECORD; 998*37da2899SCharles.Forsyth if(int a[0] & 16r80) { 999*37da2899SCharles.Forsyth h = 2; 1000*37da2899SCharles.Forsyth m = ((int a[0] & 16r7f) << 8) | int a[1]; 1001*37da2899SCharles.Forsyth pad = 0; 1002*37da2899SCharles.Forsyth } else { 1003*37da2899SCharles.Forsyth h = 3; 1004*37da2899SCharles.Forsyth m = ((int a[0] & 16r3f) << 8) | int a[1]; 1005*37da2899SCharles.Forsyth if(ensure(fd, a[2:], 1) < 0) 1006*37da2899SCharles.Forsyth return "bad v2 record"; 1007*37da2899SCharles.Forsyth pad = int a[2]; 1008*37da2899SCharles.Forsyth if(pad > m) 1009*37da2899SCharles.Forsyth return "bad v2 pad"; 1010*37da2899SCharles.Forsyth } 1011*37da2899SCharles.Forsyth r.content_type = SSL_V2HANDSHAKE; 1012*37da2899SCharles.Forsyth r.version = SSL_VERSION_2_0; 1013*37da2899SCharles.Forsyth } 1014*37da2899SCharles.Forsyth else { 1015*37da2899SCharles.Forsyth ctx.status |= SSL3_RECORD; 1016*37da2899SCharles.Forsyth h = 5; 1017*37da2899SCharles.Forsyth if(ensure(fd, a[2:], 3) < 0) 1018*37da2899SCharles.Forsyth return "bad v3 record"; 1019*37da2899SCharles.Forsyth m = ((int a[3]) << 8) | int a[4]; 1020*37da2899SCharles.Forsyth r.content_type = int a[0]; 1021*37da2899SCharles.Forsyth r.version = a[1:3]; 1022*37da2899SCharles.Forsyth } 1023*37da2899SCharles.Forsyth if(ensure(fd, a[h:], m) < 0) 1024*37da2899SCharles.Forsyth# return "data too short"; 1025*37da2899SCharles.Forsyth return sys->sprint("data too short wanted %d", m); 1026*37da2899SCharles.Forsyth if(SSL_DEBUG) { 1027*37da2899SCharles.Forsyth log("ssl3: record read\n\tbefore decrypt\n\t\t" + bastr(a[0:m+h])); 1028*37da2899SCharles.Forsyth log(sys->sprint("SSL3=%d\n", ctx.status & SSL3_RECORD)); 1029*37da2899SCharles.Forsyth } 1030*37da2899SCharles.Forsyth 1031*37da2899SCharles.Forsyth # decrypt (data, pad, mac) 1032*37da2899SCharles.Forsyth pick dec := q.cipherState { 1033*37da2899SCharles.Forsyth null => 1034*37da2899SCharles.Forsyth rc4 => 1035*37da2899SCharles.Forsyth keyring->rc4(dec.es, a[h:], m); 1036*37da2899SCharles.Forsyth if (SSL_DEBUG) log("rc4 1"); 1037*37da2899SCharles.Forsyth descbc => 1038*37da2899SCharles.Forsyth keyring->descbc(dec.es, a[h:], m, 1); 1039*37da2899SCharles.Forsyth if (SSL_DEBUG) log("descbc 1"); 1040*37da2899SCharles.Forsyth ideacbc => 1041*37da2899SCharles.Forsyth keyring->ideacbc(dec.es, a[h:], m, 1); 1042*37da2899SCharles.Forsyth if (SSL_DEBUG) log("ideacbc 1"); 1043*37da2899SCharles.Forsyth * => 1044*37da2899SCharles.Forsyth } 1045*37da2899SCharles.Forsyth 1046*37da2899SCharles.Forsyth if(SSL_DEBUG) 1047*37da2899SCharles.Forsyth log("ssl3: record read\n\tafter decrypt\n\t\t" + bastr(a[0:m])); 1048*37da2899SCharles.Forsyth 1049*37da2899SCharles.Forsyth idata, imac, ipad: int = 0; 1050*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1051*37da2899SCharles.Forsyth if(q.cipherState.block_size > 1){ 1052*37da2899SCharles.Forsyth pad = int a[h + m - 1]; 1053*37da2899SCharles.Forsyth if(pad >= q.cipherState.block_size) 1054*37da2899SCharles.Forsyth return "bad v3 pad"; 1055*37da2899SCharles.Forsyth # pad++; 1056*37da2899SCharles.Forsyth ipad = h+m-pad-1; 1057*37da2899SCharles.Forsyth } 1058*37da2899SCharles.Forsyth else 1059*37da2899SCharles.Forsyth ipad = h+m-pad; 1060*37da2899SCharles.Forsyth imac = ipad - q.macState.hash_size; 1061*37da2899SCharles.Forsyth idata = h; 1062*37da2899SCharles.Forsyth } 1063*37da2899SCharles.Forsyth else { 1064*37da2899SCharles.Forsyth imac = h; 1065*37da2899SCharles.Forsyth idata = imac + q.macState.hash_size; 1066*37da2899SCharles.Forsyth ipad = h + m - pad; 1067*37da2899SCharles.Forsyth } 1068*37da2899SCharles.Forsyth if(tagof q.macState != tagof MacState.null) { 1069*37da2899SCharles.Forsyth if (ctx.status & SSL3_RECORD) 1070*37da2899SCharles.Forsyth mac := q.calcmac(ctx, r.content_type, a, idata, imac-idata); 1071*37da2899SCharles.Forsyth else 1072*37da2899SCharles.Forsyth mac = q.calcmac(ctx, r.content_type, a, idata, ipad+pad-idata); 1073*37da2899SCharles.Forsyth if(bytes_cmp(mac, a[imac:imac+len mac]) < 0) 1074*37da2899SCharles.Forsyth return "bad mac"; 1075*37da2899SCharles.Forsyth } 1076*37da2899SCharles.Forsyth q.b = idata; 1077*37da2899SCharles.Forsyth if (ctx.status & SSL3_RECORD) 1078*37da2899SCharles.Forsyth q.e = imac; 1079*37da2899SCharles.Forsyth else 1080*37da2899SCharles.Forsyth q.e = ipad; 1081*37da2899SCharles.Forsyth q.fragment = q.e - q.b; 1082*37da2899SCharles.Forsyth 1083*37da2899SCharles.Forsyth if((++q.sequence_numbers[0] == 0) && (ctx.status&SSL3_RECORD)) 1084*37da2899SCharles.Forsyth ++q.sequence_numbers[1]; 1085*37da2899SCharles.Forsyth 1086*37da2899SCharles.Forsyth return ""; 1087*37da2899SCharles.Forsyth} 1088*37da2899SCharles.Forsyth 1089*37da2899SCharles.Forsythensure(fd: ref Sys->FD, a: array of byte, n: int): int 1090*37da2899SCharles.Forsyth{ 1091*37da2899SCharles.Forsyth i, m: int = 0; 1092*37da2899SCharles.Forsyth while(i < n) { 1093*37da2899SCharles.Forsyth m = sys->read(fd, a[i:], n - i); 1094*37da2899SCharles.Forsyth if(m <= 0) { 1095*37da2899SCharles.Forsyth return -1; 1096*37da2899SCharles.Forsyth } 1097*37da2899SCharles.Forsyth i += m; 1098*37da2899SCharles.Forsyth } 1099*37da2899SCharles.Forsyth return n; 1100*37da2899SCharles.Forsyth} 1101*37da2899SCharles.Forsyth 1102*37da2899SCharles.ForsythRecordQueue.write(q: self ref RecordQueue, ctx: ref Context, fd: ref Sys->FD, 1103*37da2899SCharles.Forsyth r: ref Record): string 1104*37da2899SCharles.Forsyth{ 1105*37da2899SCharles.Forsyth m := len r.data; 1106*37da2899SCharles.Forsyth h, pad: int = 0; 1107*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1108*37da2899SCharles.Forsyth h = 5; 1109*37da2899SCharles.Forsyth if(q.cipherState.block_size > 1) { 1110*37da2899SCharles.Forsyth pad = (m+q.macState.hash_size+1)%q.cipherState.block_size; 1111*37da2899SCharles.Forsyth if (pad) 1112*37da2899SCharles.Forsyth pad = q.cipherState.block_size - pad; 1113*37da2899SCharles.Forsyth } 1114*37da2899SCharles.Forsyth } 1115*37da2899SCharles.Forsyth else { 1116*37da2899SCharles.Forsyth h = 2; 1117*37da2899SCharles.Forsyth if(q.cipherState.block_size > 1) { 1118*37da2899SCharles.Forsyth pad = m%q.cipherState.block_size; 1119*37da2899SCharles.Forsyth if(pad) { 1120*37da2899SCharles.Forsyth pad = q.cipherState.block_size - pad; 1121*37da2899SCharles.Forsyth h++; 1122*37da2899SCharles.Forsyth } 1123*37da2899SCharles.Forsyth } 1124*37da2899SCharles.Forsyth } 1125*37da2899SCharles.Forsyth 1126*37da2899SCharles.Forsyth m += pad + q.macState.hash_size; 1127*37da2899SCharles.Forsyth if ((ctx.status & SSL3_RECORD) && q.cipherState.block_size > 1) 1128*37da2899SCharles.Forsyth m++; 1129*37da2899SCharles.Forsyth a := array [h+m] of byte; 1130*37da2899SCharles.Forsyth 1131*37da2899SCharles.Forsyth idata, imac, ipad: int = 0; 1132*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1133*37da2899SCharles.Forsyth a[0] = byte r.content_type; 1134*37da2899SCharles.Forsyth a[1:] = r.version; 1135*37da2899SCharles.Forsyth a[3] = byte (m >> 8); #CJL - netscape ssl3 traces do not show top bit set 1136*37da2899SCharles.Forsyth# a[3] = byte ((m >> 8) | 16r80); #CJL 1137*37da2899SCharles.Forsyth# a[3] = byte (m | 16r8000) >> 8; 1138*37da2899SCharles.Forsyth a[4] = byte m; 1139*37da2899SCharles.Forsyth idata = h; 1140*37da2899SCharles.Forsyth imac = idata + len r.data; 1141*37da2899SCharles.Forsyth ipad = imac + q.macState.hash_size; 1142*37da2899SCharles.Forsyth if (q.cipherState.block_size > 1) 1143*37da2899SCharles.Forsyth a[h+m-1] = byte pad; 1144*37da2899SCharles.Forsyth } 1145*37da2899SCharles.Forsyth else { 1146*37da2899SCharles.Forsyth if(pad) { 1147*37da2899SCharles.Forsyth a[0] = byte m >> 8; 1148*37da2899SCharles.Forsyth a[2] = byte pad; 1149*37da2899SCharles.Forsyth } 1150*37da2899SCharles.Forsyth else 1151*37da2899SCharles.Forsyth a[0] = byte ((m >> 8) | 16r80); 1152*37da2899SCharles.Forsyth a[1] = byte m; 1153*37da2899SCharles.Forsyth imac = h; 1154*37da2899SCharles.Forsyth idata = imac + q.macState.hash_size; 1155*37da2899SCharles.Forsyth ipad = idata + len r.data; 1156*37da2899SCharles.Forsyth } 1157*37da2899SCharles.Forsyth a[idata:] = r.data; 1158*37da2899SCharles.Forsyth if(pad) 1159*37da2899SCharles.Forsyth a[ipad:] = array [pad] of { * => byte (pad-1)}; 1160*37da2899SCharles.Forsyth 1161*37da2899SCharles.Forsyth if(tagof q.macState != tagof MacState.null) { 1162*37da2899SCharles.Forsyth if (ctx.status & SSL3_RECORD) 1163*37da2899SCharles.Forsyth a[imac:] = q.calcmac(ctx, r.content_type, a, idata, len r.data); 1164*37da2899SCharles.Forsyth else 1165*37da2899SCharles.Forsyth a[imac:] = q.calcmac(ctx, r.content_type, a, idata, ipad+pad-idata); 1166*37da2899SCharles.Forsyth } 1167*37da2899SCharles.Forsyth 1168*37da2899SCharles.Forsyth if(SSL_DEBUG) { 1169*37da2899SCharles.Forsyth log("ssl3: record write\n\tbefore encrypt\n\t\t" + bastr(a)); 1170*37da2899SCharles.Forsyth log(sys->sprint("SSL3=%d\n", ctx.status & SSL3_RECORD)); 1171*37da2899SCharles.Forsyth } 1172*37da2899SCharles.Forsyth 1173*37da2899SCharles.Forsyth # encrypt (data, pad, mac) 1174*37da2899SCharles.Forsyth pick enc := q.cipherState { 1175*37da2899SCharles.Forsyth null => 1176*37da2899SCharles.Forsyth rc4 => 1177*37da2899SCharles.Forsyth keyring->rc4(enc.es, a[h:], m); 1178*37da2899SCharles.Forsyth if (SSL_DEBUG) log("rc4 0"); 1179*37da2899SCharles.Forsyth descbc => 1180*37da2899SCharles.Forsyth keyring->descbc(enc.es, a[h:], m, 0); 1181*37da2899SCharles.Forsyth if (SSL_DEBUG) log(sys->sprint("descbc 0 %d", m)); 1182*37da2899SCharles.Forsyth ideacbc => 1183*37da2899SCharles.Forsyth keyring->ideacbc(enc.es, a[h:], m, 0); 1184*37da2899SCharles.Forsyth if (SSL_DEBUG) log(sys->sprint("ideacbc 0 %d", m)); 1185*37da2899SCharles.Forsyth * => 1186*37da2899SCharles.Forsyth } 1187*37da2899SCharles.Forsyth 1188*37da2899SCharles.Forsyth if(SSL_DEBUG) 1189*37da2899SCharles.Forsyth log("ssl3: record write\n\tafter encrypt\n\t\t" + bastr(a)); 1190*37da2899SCharles.Forsyth 1191*37da2899SCharles.Forsyth if(sys->write(fd, a, h+m) < 0) 1192*37da2899SCharles.Forsyth return sys->sprint("ssl3: record write: %r"); 1193*37da2899SCharles.Forsyth 1194*37da2899SCharles.Forsyth if((++q.sequence_numbers[0] == 0) && (ctx.status&SSL3_RECORD)) 1195*37da2899SCharles.Forsyth ++q.sequence_numbers[1]; 1196*37da2899SCharles.Forsyth 1197*37da2899SCharles.Forsyth return ""; 1198*37da2899SCharles.Forsyth} 1199*37da2899SCharles.Forsyth 1200*37da2899SCharles.ForsythRecordQueue.calcmac(q: self ref RecordQueue, ctx: ref Context, cntype: int, a: array of byte, 1201*37da2899SCharles.Forsyth ofs, n: int) : array of byte 1202*37da2899SCharles.Forsyth{ 1203*37da2899SCharles.Forsyth digest, b: array of byte; 1204*37da2899SCharles.Forsyth 1205*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1206*37da2899SCharles.Forsyth b = array [11] of byte; 1207*37da2899SCharles.Forsyth i := putn(b, 0, q.sequence_numbers[1], 4); 1208*37da2899SCharles.Forsyth i = putn(b, i, q.sequence_numbers[0], 4); 1209*37da2899SCharles.Forsyth b[i++] = byte cntype; 1210*37da2899SCharles.Forsyth putn(b, i, n, 2); 1211*37da2899SCharles.Forsyth } 1212*37da2899SCharles.Forsyth else { 1213*37da2899SCharles.Forsyth b = array [4] of byte; 1214*37da2899SCharles.Forsyth putn(b, 0, q.sequence_numbers[0], 4); 1215*37da2899SCharles.Forsyth } 1216*37da2899SCharles.Forsyth 1217*37da2899SCharles.Forsyth # if(SSL_DEBUG) 1218*37da2899SCharles.Forsyth # log("ssl3: record mac\n\tother =\n\t\t" + bastr(b)); 1219*37da2899SCharles.Forsyth 1220*37da2899SCharles.Forsyth pick ms := q.macState { 1221*37da2899SCharles.Forsyth md5 => 1222*37da2899SCharles.Forsyth digest = array [Keyring->MD5dlen] of byte; 1223*37da2899SCharles.Forsyth ds0 := ms.ds[0].copy(); 1224*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1225*37da2899SCharles.Forsyth keyring->md5(b, len b, nil, ds0); 1226*37da2899SCharles.Forsyth keyring->md5(a[ofs:], n, digest, ds0); 1227*37da2899SCharles.Forsyth ds1 := ms.ds[1].copy(); 1228*37da2899SCharles.Forsyth keyring->md5(digest, len digest, digest, ds1); 1229*37da2899SCharles.Forsyth } 1230*37da2899SCharles.Forsyth else { 1231*37da2899SCharles.Forsyth keyring->md5(a[ofs:], n, nil, ds0); 1232*37da2899SCharles.Forsyth keyring->md5(b, len b, digest, ds0); 1233*37da2899SCharles.Forsyth } 1234*37da2899SCharles.Forsyth sha => 1235*37da2899SCharles.Forsyth digest = array [Keyring->SHA1dlen] of byte; 1236*37da2899SCharles.Forsyth ds0 := ms.ds[0].copy(); 1237*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1238*37da2899SCharles.Forsyth keyring->sha1(b, len b, nil, ds0); 1239*37da2899SCharles.Forsyth keyring->sha1(a[ofs:], n, digest, ds0); 1240*37da2899SCharles.Forsyth ds1 := ms.ds[1].copy(); 1241*37da2899SCharles.Forsyth keyring->sha1(digest, len digest, digest, ds1); 1242*37da2899SCharles.Forsyth } 1243*37da2899SCharles.Forsyth else { 1244*37da2899SCharles.Forsyth keyring->sha1(a[ofs:], n, nil, ds0); 1245*37da2899SCharles.Forsyth keyring->sha1(b, len b, digest, ds0); 1246*37da2899SCharles.Forsyth } 1247*37da2899SCharles.Forsyth } 1248*37da2899SCharles.Forsyth return digest; 1249*37da2899SCharles.Forsyth} 1250*37da2899SCharles.Forsyth 1251*37da2899SCharles.Forsythset_queues(ctx: ref Context): string 1252*37da2899SCharles.Forsyth{ 1253*37da2899SCharles.Forsyth sw: array of byte; 1254*37da2899SCharles.Forsyth if(ctx.sw_key != nil) { 1255*37da2899SCharles.Forsyth sw = array [len ctx.sw_key + len ctx.sw_IV] of byte; 1256*37da2899SCharles.Forsyth sw[0:] = ctx.sw_key; 1257*37da2899SCharles.Forsyth sw[len ctx.sw_key:] = ctx.sw_IV; 1258*37da2899SCharles.Forsyth } 1259*37da2899SCharles.Forsyth cw: array of byte; 1260*37da2899SCharles.Forsyth if(ctx.cw_key != nil) { 1261*37da2899SCharles.Forsyth cw = array [len ctx.cw_key + len ctx.cw_IV] of byte; 1262*37da2899SCharles.Forsyth cw[0:] = ctx.cw_key; 1263*37da2899SCharles.Forsyth cw[len ctx.cw_key:] = ctx.cw_IV; 1264*37da2899SCharles.Forsyth } 1265*37da2899SCharles.Forsyth 1266*37da2899SCharles.Forsyth err := ""; 1267*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 1268*37da2899SCharles.Forsyth err = set_secrets(ctx.c, ctx.sw_mac, ctx.cw_mac, sw, cw); 1269*37da2899SCharles.Forsyth if(err == "") 1270*37da2899SCharles.Forsyth err = set_cipher_algs(ctx); 1271*37da2899SCharles.Forsyth } 1272*37da2899SCharles.Forsyth else { 1273*37da2899SCharles.Forsyth err = set_out_queue(ctx); 1274*37da2899SCharles.Forsyth if(err == "") 1275*37da2899SCharles.Forsyth err = set_in_queue(ctx); 1276*37da2899SCharles.Forsyth } 1277*37da2899SCharles.Forsyth 1278*37da2899SCharles.Forsyth return err; 1279*37da2899SCharles.Forsyth} 1280*37da2899SCharles.Forsyth 1281*37da2899SCharles.Forsythset_in_queue(ctx: ref Context): string 1282*37da2899SCharles.Forsyth{ 1283*37da2899SCharles.Forsyth sw: array of byte; 1284*37da2899SCharles.Forsyth if(ctx.sw_key != nil) { 1285*37da2899SCharles.Forsyth sw = array [len ctx.sw_key + len ctx.sw_IV] of byte; 1286*37da2899SCharles.Forsyth sw[0:] = ctx.sw_key; 1287*37da2899SCharles.Forsyth sw[len ctx.sw_key:] = ctx.sw_IV; 1288*37da2899SCharles.Forsyth } 1289*37da2899SCharles.Forsyth 1290*37da2899SCharles.Forsyth err := ""; 1291*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 1292*37da2899SCharles.Forsyth err = set_secrets(ctx.c, ctx.sw_mac, nil, sw, nil); 1293*37da2899SCharles.Forsyth if(err == "") 1294*37da2899SCharles.Forsyth err = set_cipher_algs(ctx); 1295*37da2899SCharles.Forsyth } 1296*37da2899SCharles.Forsyth else 1297*37da2899SCharles.Forsyth err = set_queue(ctx, ctx.in_queue, ctx.sw_mac, sw); 1298*37da2899SCharles.Forsyth 1299*37da2899SCharles.Forsyth return err; 1300*37da2899SCharles.Forsyth} 1301*37da2899SCharles.Forsyth 1302*37da2899SCharles.Forsythset_out_queue(ctx: ref Context): string 1303*37da2899SCharles.Forsyth{ 1304*37da2899SCharles.Forsyth cw: array of byte; 1305*37da2899SCharles.Forsyth if(ctx.cw_key != nil) { 1306*37da2899SCharles.Forsyth cw = array [len ctx.cw_key + len ctx.cw_IV] of byte; 1307*37da2899SCharles.Forsyth cw[0:] = ctx.cw_key; 1308*37da2899SCharles.Forsyth cw[len ctx.cw_key:] = ctx.cw_IV; 1309*37da2899SCharles.Forsyth } 1310*37da2899SCharles.Forsyth 1311*37da2899SCharles.Forsyth err := ""; 1312*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) { 1313*37da2899SCharles.Forsyth err = set_secrets(ctx.c, nil, ctx.cw_mac, nil, cw); 1314*37da2899SCharles.Forsyth if(err == "") 1315*37da2899SCharles.Forsyth err = set_cipher_algs(ctx); 1316*37da2899SCharles.Forsyth } 1317*37da2899SCharles.Forsyth else 1318*37da2899SCharles.Forsyth err = set_queue(ctx, ctx.out_queue, ctx.cw_mac, cw); 1319*37da2899SCharles.Forsyth 1320*37da2899SCharles.Forsyth return err; 1321*37da2899SCharles.Forsyth} 1322*37da2899SCharles.Forsyth 1323*37da2899SCharles.Forsythset_queue(ctx: ref Context, q: ref RecordQueue, mac, key: array of byte): string 1324*37da2899SCharles.Forsyth{ 1325*37da2899SCharles.Forsyth e := ""; 1326*37da2899SCharles.Forsyth 1327*37da2899SCharles.Forsyth case ctx.sel_ciph.mac_algorithm { 1328*37da2899SCharles.Forsyth SSL_NULL_MAC => 1329*37da2899SCharles.Forsyth q.macState = ref MacState.null(0); 1330*37da2899SCharles.Forsyth SSL_MD5 => 1331*37da2899SCharles.Forsyth ds: array of ref DigestState; 1332*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1333*37da2899SCharles.Forsyth ds = array [2] of ref DigestState; 1334*37da2899SCharles.Forsyth ds[0] = keyring->md5(mac, len mac, nil, nil); 1335*37da2899SCharles.Forsyth ds[1] = keyring->md5(mac, len mac, nil, nil); 1336*37da2899SCharles.Forsyth ds[0] = keyring->md5(SSL_MAC_PAD1, 48, nil, ds[0]); 1337*37da2899SCharles.Forsyth ds[1] = keyring->md5(SSL_MAC_PAD2, 48, nil, ds[1]); 1338*37da2899SCharles.Forsyth } 1339*37da2899SCharles.Forsyth else { 1340*37da2899SCharles.Forsyth ds = array [1] of ref DigestState; 1341*37da2899SCharles.Forsyth ds[0] = keyring->md5(mac, len mac, nil, nil); 1342*37da2899SCharles.Forsyth } 1343*37da2899SCharles.Forsyth q.macState = ref MacState.md5(Keyring->MD5dlen, ds); 1344*37da2899SCharles.Forsyth SSL_SHA => 1345*37da2899SCharles.Forsyth ds: array of ref DigestState; 1346*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1347*37da2899SCharles.Forsyth ds = array [2] of ref DigestState; 1348*37da2899SCharles.Forsyth ds[0] = keyring->sha1(mac, len mac, nil, nil); 1349*37da2899SCharles.Forsyth ds[1] = keyring->sha1(mac, len mac, nil, nil); 1350*37da2899SCharles.Forsyth ds[0] = keyring->sha1(SSL_MAC_PAD1, 40, nil, ds[0]); 1351*37da2899SCharles.Forsyth ds[1] = keyring->sha1(SSL_MAC_PAD2, 40, nil, ds[1]); 1352*37da2899SCharles.Forsyth } 1353*37da2899SCharles.Forsyth else { 1354*37da2899SCharles.Forsyth ds = array [1] of ref DigestState; 1355*37da2899SCharles.Forsyth ds[0] = keyring->sha1(mac, len mac, nil, nil); 1356*37da2899SCharles.Forsyth } 1357*37da2899SCharles.Forsyth q.macState = ref MacState.sha(Keyring->SHA1dlen, ds); 1358*37da2899SCharles.Forsyth * => 1359*37da2899SCharles.Forsyth e = "ssl3: digest method: unknown"; 1360*37da2899SCharles.Forsyth } 1361*37da2899SCharles.Forsyth 1362*37da2899SCharles.Forsyth case ctx.sel_ciph.bulk_cipher_algorithm { 1363*37da2899SCharles.Forsyth SSL_NULL_CIPHER => 1364*37da2899SCharles.Forsyth q.cipherState = ref CipherState.null(1); 1365*37da2899SCharles.Forsyth SSL_RC4 => 1366*37da2899SCharles.Forsyth if (SSL_DEBUG) log("rc4setup"); 1367*37da2899SCharles.Forsyth rcs := keyring->rc4setup(key); 1368*37da2899SCharles.Forsyth q.cipherState = ref CipherState.rc4(1, rcs); 1369*37da2899SCharles.Forsyth SSL_DES_CBC => 1370*37da2899SCharles.Forsyth dcs : ref keyring->DESstate; 1371*37da2899SCharles.Forsyth 1372*37da2899SCharles.Forsyth if (SSL_DEBUG) log(sys->sprint("dessetup %d", len key)); 1373*37da2899SCharles.Forsyth if (len key >= 16) 1374*37da2899SCharles.Forsyth dcs = keyring->dessetup(key[0:8], key[8:16]); 1375*37da2899SCharles.Forsyth else if (len key >= 8) 1376*37da2899SCharles.Forsyth dcs = keyring->dessetup(key[0:8], nil); 1377*37da2899SCharles.Forsyth else 1378*37da2899SCharles.Forsyth e = "ssl3: bad DES key length"; 1379*37da2899SCharles.Forsyth q.cipherState = ref CipherState.descbc(8, dcs); 1380*37da2899SCharles.Forsyth SSL_IDEA_CBC => 1381*37da2899SCharles.Forsyth ics : ref keyring->IDEAstate; 1382*37da2899SCharles.Forsyth 1383*37da2899SCharles.Forsyth if (SSL_DEBUG) log(sys->sprint("ideasetup %d", len key)); 1384*37da2899SCharles.Forsyth if (len key >= 24) 1385*37da2899SCharles.Forsyth ics = keyring->ideasetup(key[0:16], key[16:24]); 1386*37da2899SCharles.Forsyth else if (len key >= 16) 1387*37da2899SCharles.Forsyth ics = keyring->ideasetup(key[0:16], nil); 1388*37da2899SCharles.Forsyth else 1389*37da2899SCharles.Forsyth e = "ssl3: bad IDEA key length"; 1390*37da2899SCharles.Forsyth q.cipherState = ref CipherState.ideacbc(8, ics); 1391*37da2899SCharles.Forsyth SSL_RC2_CBC or 1392*37da2899SCharles.Forsyth SSL_3DES_EDE_CBC or 1393*37da2899SCharles.Forsyth SSL_FORTEZZA_CBC => 1394*37da2899SCharles.Forsyth e = "ssl3: unsupported cipher"; 1395*37da2899SCharles.Forsyth * => 1396*37da2899SCharles.Forsyth e = "ssl3: unknown cipher"; 1397*37da2899SCharles.Forsyth } 1398*37da2899SCharles.Forsyth 1399*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) { 1400*37da2899SCharles.Forsyth q.length = 1 << 14; 1401*37da2899SCharles.Forsyth if(tagof q.macState != tagof MacState.null) 1402*37da2899SCharles.Forsyth q.length += 2048; 1403*37da2899SCharles.Forsyth } 1404*37da2899SCharles.Forsyth else { 1405*37da2899SCharles.Forsyth if(q.cipherState.block_size > 1) { 1406*37da2899SCharles.Forsyth q.length = (1<<14) - q.macState.hash_size - 1; 1407*37da2899SCharles.Forsyth q.length -= q.length % q.cipherState.block_size; 1408*37da2899SCharles.Forsyth } 1409*37da2899SCharles.Forsyth else 1410*37da2899SCharles.Forsyth q.length = (1<<15) - q.macState.hash_size - 1; 1411*37da2899SCharles.Forsyth } 1412*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) 1413*37da2899SCharles.Forsyth q.sequence_numbers[0] = q.sequence_numbers[1] = 0; 1414*37da2899SCharles.Forsyth 1415*37da2899SCharles.Forsyth return e; 1416*37da2899SCharles.Forsyth} 1417*37da2899SCharles.Forsyth 1418*37da2899SCharles.Forsythset_cipher_algs(ctx: ref Context) : string 1419*37da2899SCharles.Forsyth{ 1420*37da2899SCharles.Forsyth e: string; 1421*37da2899SCharles.Forsyth 1422*37da2899SCharles.Forsyth algspec := "alg"; 1423*37da2899SCharles.Forsyth 1424*37da2899SCharles.Forsyth case enc := ctx.sel_ciph.bulk_cipher_algorithm { 1425*37da2899SCharles.Forsyth SSL_NULL_CIPHER => 1426*37da2899SCharles.Forsyth algspec += " clear"; 1427*37da2899SCharles.Forsyth SSL_RC4 => # stream cipher 1428*37da2899SCharles.Forsyth algspec += " rc4_128"; 1429*37da2899SCharles.Forsyth SSL_DES_CBC => # block cipher 1430*37da2899SCharles.Forsyth algspec += " descbc"; 1431*37da2899SCharles.Forsyth SSL_IDEA_CBC => # block cipher 1432*37da2899SCharles.Forsyth algspec += " ideacbc"; 1433*37da2899SCharles.Forsyth SSL_RC2_CBC or 1434*37da2899SCharles.Forsyth SSL_3DES_EDE_CBC or 1435*37da2899SCharles.Forsyth SSL_FORTEZZA_CBC => 1436*37da2899SCharles.Forsyth e = "ssl3: encrypt method: unsupported"; 1437*37da2899SCharles.Forsyth * => 1438*37da2899SCharles.Forsyth e = "ssl3: encrypt method: unknown"; 1439*37da2899SCharles.Forsyth } 1440*37da2899SCharles.Forsyth 1441*37da2899SCharles.Forsyth case mac := ctx.sel_ciph.mac_algorithm { 1442*37da2899SCharles.Forsyth SSL_NULL_MAC => 1443*37da2899SCharles.Forsyth algspec += " clear"; 1444*37da2899SCharles.Forsyth SSL_MD5 => 1445*37da2899SCharles.Forsyth algspec += " md5"; 1446*37da2899SCharles.Forsyth SSL_SHA => 1447*37da2899SCharles.Forsyth algspec += " sha1"; 1448*37da2899SCharles.Forsyth * => 1449*37da2899SCharles.Forsyth e = "ssl3: digest method: unknown"; 1450*37da2899SCharles.Forsyth } 1451*37da2899SCharles.Forsyth 1452*37da2899SCharles.Forsyth e = set_ctl(ctx.c, algspec); 1453*37da2899SCharles.Forsyth if(e != "") { 1454*37da2899SCharles.Forsyth if(SSL_DEBUG) 1455*37da2899SCharles.Forsyth log("failed to set cipher algs: " + e); 1456*37da2899SCharles.Forsyth } 1457*37da2899SCharles.Forsyth 1458*37da2899SCharles.Forsyth return e; 1459*37da2899SCharles.Forsyth} 1460*37da2899SCharles.Forsyth 1461*37da2899SCharles.Forsythset_ctl(c: ref Sys->Connection, s: string): string 1462*37da2899SCharles.Forsyth{ 1463*37da2899SCharles.Forsyth a := array of byte s; 1464*37da2899SCharles.Forsyth if(sys->write(c.cfd, a, len a) < 0) 1465*37da2899SCharles.Forsyth return sys->sprint("error writing sslctl: %r"); 1466*37da2899SCharles.Forsyth 1467*37da2899SCharles.Forsyth if(SSL_DEBUG) 1468*37da2899SCharles.Forsyth log("ssl3: set cipher algorithm:\n\t\t" + s + "\n"); 1469*37da2899SCharles.Forsyth 1470*37da2899SCharles.Forsyth return ""; 1471*37da2899SCharles.Forsyth} 1472*37da2899SCharles.Forsyth 1473*37da2899SCharles.Forsythset_secrets(c: ref Sys->Connection, min, mout, sin, sout: array of byte) : string 1474*37da2899SCharles.Forsyth{ 1475*37da2899SCharles.Forsyth fmin := sys->open(c.dir + "/macin", Sys->OWRITE); 1476*37da2899SCharles.Forsyth fmout := sys->open(c.dir + "/macout", Sys->OWRITE); 1477*37da2899SCharles.Forsyth fsin := sys->open(c.dir + "/secretin", Sys->OWRITE); 1478*37da2899SCharles.Forsyth fsout := sys->open(c.dir + "/secretout", Sys->OWRITE); 1479*37da2899SCharles.Forsyth if(fmin == nil || fmout == nil || fsin == nil || fsout == nil) 1480*37da2899SCharles.Forsyth return sys->sprint("can't open ssl secret files: %r\n"); 1481*37da2899SCharles.Forsyth 1482*37da2899SCharles.Forsyth if(sin != nil) { 1483*37da2899SCharles.Forsyth if(SSL_DEBUG) 1484*37da2899SCharles.Forsyth log("ssl3: set encryption secret and IV\n\tsecretin:\n\t\t" + bastr(sin) + "\n"); 1485*37da2899SCharles.Forsyth if(sys->write(fsin, sin, len sin) < 0) 1486*37da2899SCharles.Forsyth return sys->sprint("error writing secretin: %r"); 1487*37da2899SCharles.Forsyth } 1488*37da2899SCharles.Forsyth if(sout != nil) { 1489*37da2899SCharles.Forsyth if(SSL_DEBUG) 1490*37da2899SCharles.Forsyth log("ssl3: set encryption secret and IV\n\tsecretout:\n\t\t" + bastr(sout) + "\n"); 1491*37da2899SCharles.Forsyth if(sys->write(fsout, sout, len sout) < 0) 1492*37da2899SCharles.Forsyth return sys->sprint("error writing secretout: %r"); 1493*37da2899SCharles.Forsyth } 1494*37da2899SCharles.Forsyth if(min != nil) { 1495*37da2899SCharles.Forsyth if(SSL_DEBUG) 1496*37da2899SCharles.Forsyth log("ssl3: set digest secret\n\tmacin:\n\t\t" + bastr(min) + "\n"); 1497*37da2899SCharles.Forsyth if(sys->write(fmin, min, len min) < 0) 1498*37da2899SCharles.Forsyth return sys->sprint("error writing macin: %r"); 1499*37da2899SCharles.Forsyth } 1500*37da2899SCharles.Forsyth if(mout != nil) { 1501*37da2899SCharles.Forsyth if(SSL_DEBUG) 1502*37da2899SCharles.Forsyth log("ssl3: set digest secret\n\tmacout:\n\t\t" + bastr(mout) + "\n"); 1503*37da2899SCharles.Forsyth if(sys->write(fmout, mout, len mout) < 0) 1504*37da2899SCharles.Forsyth return sys->sprint("error writing macout: %r"); 1505*37da2899SCharles.Forsyth } 1506*37da2899SCharles.Forsyth 1507*37da2899SCharles.Forsyth return ""; 1508*37da2899SCharles.Forsyth} 1509*37da2899SCharles.Forsyth 1510*37da2899SCharles.Forsyth# 1511*37da2899SCharles.Forsyth# description must be alert description 1512*37da2899SCharles.Forsyth# 1513*37da2899SCharles.Forsythfatal(description: int, debug_msg: string, ctx: ref Context) 1514*37da2899SCharles.Forsyth{ 1515*37da2899SCharles.Forsyth if(SSL_DEBUG) 1516*37da2899SCharles.Forsyth log("ssl3: " + debug_msg); 1517*37da2899SCharles.Forsyth 1518*37da2899SCharles.Forsyth # TODO: use V2Handshake.Error for v2 1519*37da2899SCharles.Forsyth alert_enque(ref Alert(SSL_FATAL, description), ctx); 1520*37da2899SCharles.Forsyth 1521*37da2899SCharles.Forsyth # delete session id 1522*37da2899SCharles.Forsyth ctx.session.session_id = nil; 1523*37da2899SCharles.Forsyth 1524*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 1525*37da2899SCharles.Forsyth} 1526*37da2899SCharles.Forsyth 1527*37da2899SCharles.Forsythalert_enque(a: ref Alert, ctx: ref Context) 1528*37da2899SCharles.Forsyth{ 1529*37da2899SCharles.Forsyth p := ref Protocol.pAlert(a); 1530*37da2899SCharles.Forsyth 1531*37da2899SCharles.Forsyth protocol_write(p, ctx); 1532*37da2899SCharles.Forsyth} 1533*37da2899SCharles.Forsyth 1534*37da2899SCharles.Forsyth# clean up out queue before switch cipher. this is why 1535*37da2899SCharles.Forsyth# change cipher spec differs from handshake message by ssl spec 1536*37da2899SCharles.Forsyth 1537*37da2899SCharles.Forsythccs_enque(cs: ref ChangeCipherSpec, ctx: ref Context) 1538*37da2899SCharles.Forsyth{ 1539*37da2899SCharles.Forsyth p := ref Protocol.pChangeCipherSpec(cs); 1540*37da2899SCharles.Forsyth 1541*37da2899SCharles.Forsyth protocol_write(p, ctx); 1542*37da2899SCharles.Forsyth 1543*37da2899SCharles.Forsyth record_write_queue(ctx); 1544*37da2899SCharles.Forsyth ctx.out_queue.data = nil; 1545*37da2899SCharles.Forsyth} 1546*37da2899SCharles.Forsyth 1547*37da2899SCharles.Forsythhandshake_enque(h: ref Handshake, ctx: ref Context) 1548*37da2899SCharles.Forsyth{ 1549*37da2899SCharles.Forsyth p := ref Protocol.pHandshake(h); 1550*37da2899SCharles.Forsyth 1551*37da2899SCharles.Forsyth protocol_write(p, ctx); 1552*37da2899SCharles.Forsyth} 1553*37da2899SCharles.Forsyth 1554*37da2899SCharles.Forsythprotocol_write(p: ref Protocol, ctx: ref Context) 1555*37da2899SCharles.Forsyth{ 1556*37da2899SCharles.Forsyth record_version := SSL_VERSION_2_0; 1557*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) 1558*37da2899SCharles.Forsyth record_version = SSL_VERSION_3_0; 1559*37da2899SCharles.Forsyth (r, e) := p.encode(record_version); 1560*37da2899SCharles.Forsyth if(e != "") { 1561*37da2899SCharles.Forsyth if(SSL_DEBUG) 1562*37da2899SCharles.Forsyth log("ssl3: protocol_write: " + e); 1563*37da2899SCharles.Forsyth exit; 1564*37da2899SCharles.Forsyth } 1565*37da2899SCharles.Forsyth 1566*37da2899SCharles.Forsyth # Note: only for sslv3 1567*37da2899SCharles.Forsyth if((ctx.status&SSL2_HANDSHAKE) && (ctx.status&SSL3_HANDSHAKE)) { 1568*37da2899SCharles.Forsyth if(ctx.state == STATE_HELLO_REQUEST) { 1569*37da2899SCharles.Forsyth e = update_handshake_hash(ctx, r); 1570*37da2899SCharles.Forsyth if(e != "") { 1571*37da2899SCharles.Forsyth if(SSL_DEBUG) 1572*37da2899SCharles.Forsyth log("ssl3: protocol_write: " + e); 1573*37da2899SCharles.Forsyth exit; 1574*37da2899SCharles.Forsyth } 1575*37da2899SCharles.Forsyth } 1576*37da2899SCharles.Forsyth } 1577*37da2899SCharles.Forsyth if((ctx.status&SSL3_HANDSHAKE) && (r.content_type == SSL_HANDSHAKE)) { 1578*37da2899SCharles.Forsyth e = update_handshake_hash(ctx, r); 1579*37da2899SCharles.Forsyth if(e != "") { 1580*37da2899SCharles.Forsyth if(SSL_DEBUG) 1581*37da2899SCharles.Forsyth log("ssl3: protocol_write: " + e); 1582*37da2899SCharles.Forsyth exit; 1583*37da2899SCharles.Forsyth } 1584*37da2899SCharles.Forsyth } 1585*37da2899SCharles.Forsyth 1586*37da2899SCharles.Forsyth ctx.out_queue.data = r :: ctx.out_queue.data; 1587*37da2899SCharles.Forsyth} 1588*37da2899SCharles.Forsyth 1589*37da2899SCharles.Forsyth#feed_data(ctx: ref Context, a: array of byte, n: int): int 1590*37da2899SCharles.Forsyth#{ 1591*37da2899SCharles.Forsyth# 1592*37da2899SCharles.Forsyth#} 1593*37da2899SCharles.Forsyth 1594*37da2899SCharles.Forsyth# FIFO 1595*37da2899SCharles.Forsythrecord_write_queue(ctx: ref Context) 1596*37da2899SCharles.Forsyth{ 1597*37da2899SCharles.Forsyth write_queue : list of ref Record; 1598*37da2899SCharles.Forsyth 1599*37da2899SCharles.Forsyth wq := ctx.out_queue.data; 1600*37da2899SCharles.Forsyth while(wq != nil) { 1601*37da2899SCharles.Forsyth write_queue = hd wq :: write_queue; 1602*37da2899SCharles.Forsyth wq = tl wq; 1603*37da2899SCharles.Forsyth } 1604*37da2899SCharles.Forsyth 1605*37da2899SCharles.Forsyth wq = write_queue; 1606*37da2899SCharles.Forsyth while(wq != nil) { 1607*37da2899SCharles.Forsyth record_write(hd wq, ctx); 1608*37da2899SCharles.Forsyth wq = tl wq; 1609*37da2899SCharles.Forsyth } 1610*37da2899SCharles.Forsyth} 1611*37da2899SCharles.Forsyth 1612*37da2899SCharles.Forsyth# Possible combinations are v2 only, v3 only and both (undetermined). The v2 only must be 1613*37da2899SCharles.Forsyth# v2 handshake and v2 record layer. The v3 only must be v3 handshake and v3 record layer. 1614*37da2899SCharles.Forsyth# If both v2 and v3 are supported, it may be v2 handshake and v2 record layer, or v3 1615*37da2899SCharles.Forsyth# handshake and v3 record layer, or v2 handshake and v3 record layer. In the case of 1616*37da2899SCharles.Forsyth# both, the client should send a v2 client hello message with handshake protocol version v3. 1617*37da2899SCharles.Forsyth 1618*37da2899SCharles.Forsythdo_protocol(ctx: ref Context): string 1619*37da2899SCharles.Forsyth{ 1620*37da2899SCharles.Forsyth r: ref Record; 1621*37da2899SCharles.Forsyth in: ref Protocol; 1622*37da2899SCharles.Forsyth e: string = nil; 1623*37da2899SCharles.Forsyth 1624*37da2899SCharles.Forsyth while(ctx.state != STATE_EXIT) { 1625*37da2899SCharles.Forsyth 1626*37da2899SCharles.Forsyth if(SSL_DEBUG) 1627*37da2899SCharles.Forsyth log("ssl3: state = " + state_info(ctx)); 1628*37da2899SCharles.Forsyth 1629*37da2899SCharles.Forsyth # init a new handshake 1630*37da2899SCharles.Forsyth if(ctx.state == STATE_HELLO_REQUEST) { 1631*37da2899SCharles.Forsyth # v2 and v3 1632*37da2899SCharles.Forsyth if((ctx.status&SSL2_HANDSHAKE) && (ctx.status&SSL3_HANDSHAKE)) { 1633*37da2899SCharles.Forsyth ch := ref V2Handshake.ClientHello( 1634*37da2899SCharles.Forsyth SSL_VERSION_3_0, 1635*37da2899SCharles.Forsyth v3tov2specs(ctx.local_info.suites), 1636*37da2899SCharles.Forsyth ctx.session.session_id, 1637*37da2899SCharles.Forsyth ctx.client_random 1638*37da2899SCharles.Forsyth ); 1639*37da2899SCharles.Forsyth v2handshake_enque(ch, ctx); 1640*37da2899SCharles.Forsyth in = ref Protocol.pV2Handshake(ch); 1641*37da2899SCharles.Forsyth } 1642*37da2899SCharles.Forsyth # v3 only 1643*37da2899SCharles.Forsyth else if(ctx.status&SSL3_HANDSHAKE) { 1644*37da2899SCharles.Forsyth in = ref Protocol.pHandshake(ref Handshake.HelloRequest()); 1645*37da2899SCharles.Forsyth } 1646*37da2899SCharles.Forsyth # v2 only 1647*37da2899SCharles.Forsyth else if(ctx.status&SSL2_HANDSHAKE) { 1648*37da2899SCharles.Forsyth ch := ref V2Handshake.ClientHello( 1649*37da2899SCharles.Forsyth SSL_VERSION_2_0, 1650*37da2899SCharles.Forsyth v3tov2specs(ctx.local_info.suites), 1651*37da2899SCharles.Forsyth ctx.session.session_id, 1652*37da2899SCharles.Forsyth ctx.client_random[32-SSL2_CHALLENGE_LENGTH:32] 1653*37da2899SCharles.Forsyth ); 1654*37da2899SCharles.Forsyth v2handshake_enque(ch, ctx); 1655*37da2899SCharles.Forsyth in = ref Protocol.pV2Handshake(ch); 1656*37da2899SCharles.Forsyth } 1657*37da2899SCharles.Forsyth # unknown version 1658*37da2899SCharles.Forsyth else { 1659*37da2899SCharles.Forsyth e = "unknown ssl device version"; 1660*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "ssl3: " + e, ctx); 1661*37da2899SCharles.Forsyth continue; 1662*37da2899SCharles.Forsyth } 1663*37da2899SCharles.Forsyth } 1664*37da2899SCharles.Forsyth 1665*37da2899SCharles.Forsyth if(in == nil) { 1666*37da2899SCharles.Forsyth (r, in, e) = protocol_read(ctx); 1667*37da2899SCharles.Forsyth if(e != "") { 1668*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "ssl3: " + e, ctx); 1669*37da2899SCharles.Forsyth continue; 1670*37da2899SCharles.Forsyth } 1671*37da2899SCharles.Forsyth if(SSL_DEBUG) 1672*37da2899SCharles.Forsyth log("ssl3: protocol_read: ------\n" + in.tostring()); 1673*37da2899SCharles.Forsyth } 1674*37da2899SCharles.Forsyth 1675*37da2899SCharles.Forsyth pick p := in { 1676*37da2899SCharles.Forsyth pAlert => 1677*37da2899SCharles.Forsyth do_alert(p.alert, ctx); 1678*37da2899SCharles.Forsyth 1679*37da2899SCharles.Forsyth pChangeCipherSpec => 1680*37da2899SCharles.Forsyth if(ctx.state != STATE_CHANGE_CIPHER_SPEC) { 1681*37da2899SCharles.Forsyth e += "ChangeCipherSpec"; 1682*37da2899SCharles.Forsyth break; 1683*37da2899SCharles.Forsyth } 1684*37da2899SCharles.Forsyth do_change_cipher_spec(ctx); 1685*37da2899SCharles.Forsyth 1686*37da2899SCharles.Forsyth pHandshake => 1687*37da2899SCharles.Forsyth if(!(ctx.status & SSL3_HANDSHAKE)) { 1688*37da2899SCharles.Forsyth e = "Wrong Handshake"; 1689*37da2899SCharles.Forsyth break; 1690*37da2899SCharles.Forsyth } 1691*37da2899SCharles.Forsyth if((ctx.status & SSL3_RECORD) && 1692*37da2899SCharles.Forsyth (ctx.state == SSL2_STATE_SERVER_HELLO)) { 1693*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_HELLO; 1694*37da2899SCharles.Forsyth ctx.status &= ~SSL2_HANDSHAKE; 1695*37da2899SCharles.Forsyth } 1696*37da2899SCharles.Forsyth e = do_handshake(p.handshake, ctx); 1697*37da2899SCharles.Forsyth 1698*37da2899SCharles.Forsyth pV2Handshake => 1699*37da2899SCharles.Forsyth if(ctx.state != STATE_HELLO_REQUEST) { 1700*37da2899SCharles.Forsyth if(!(ctx.status & SSL2_HANDSHAKE)) { 1701*37da2899SCharles.Forsyth e = "Wrong Handshake"; 1702*37da2899SCharles.Forsyth break; 1703*37da2899SCharles.Forsyth } 1704*37da2899SCharles.Forsyth e = do_v2handshake(p.handshake, ctx); 1705*37da2899SCharles.Forsyth } 1706*37da2899SCharles.Forsyth else 1707*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_SERVER_HELLO; 1708*37da2899SCharles.Forsyth 1709*37da2899SCharles.Forsyth 1710*37da2899SCharles.Forsyth * => 1711*37da2899SCharles.Forsyth e = "unknown protocol message"; 1712*37da2899SCharles.Forsyth } 1713*37da2899SCharles.Forsyth 1714*37da2899SCharles.Forsyth if(e != nil) { 1715*37da2899SCharles.Forsyth e = "do_protocol: wrong protocol side or protocol message: " + e; 1716*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, e, ctx); 1717*37da2899SCharles.Forsyth } 1718*37da2899SCharles.Forsyth 1719*37da2899SCharles.Forsyth in = nil; 1720*37da2899SCharles.Forsyth 1721*37da2899SCharles.Forsyth record_write_queue(ctx); 1722*37da2899SCharles.Forsyth ctx.out_queue.data = nil; 1723*37da2899SCharles.Forsyth } 1724*37da2899SCharles.Forsyth 1725*37da2899SCharles.Forsyth return e; 1726*37da2899SCharles.Forsyth} 1727*37da2899SCharles.Forsyth 1728*37da2899SCharles.Forsythstate_info(ctx: ref Context): string 1729*37da2899SCharles.Forsyth{ 1730*37da2899SCharles.Forsyth info: string; 1731*37da2899SCharles.Forsyth 1732*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) 1733*37da2899SCharles.Forsyth info = "\n\tRecord Version 3: "; 1734*37da2899SCharles.Forsyth else 1735*37da2899SCharles.Forsyth info = "\n\tRecord Version 2: "; 1736*37da2899SCharles.Forsyth 1737*37da2899SCharles.Forsyth if(ctx.status & SSL2_HANDSHAKE) { 1738*37da2899SCharles.Forsyth 1739*37da2899SCharles.Forsyth if(ctx.status & SSL3_HANDSHAKE) { 1740*37da2899SCharles.Forsyth info += "\n\tHandshake Version Undetermined: Client Hello"; 1741*37da2899SCharles.Forsyth } 1742*37da2899SCharles.Forsyth else { 1743*37da2899SCharles.Forsyth info += "\n\tHandshake Version 2: "; 1744*37da2899SCharles.Forsyth 1745*37da2899SCharles.Forsyth case ctx.state { 1746*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_HELLO => 1747*37da2899SCharles.Forsyth info += "Client Hello"; 1748*37da2899SCharles.Forsyth SSL2_STATE_SERVER_HELLO => 1749*37da2899SCharles.Forsyth info += "Server Hello"; 1750*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_MASTER_KEY => 1751*37da2899SCharles.Forsyth info += "Client Master Key"; 1752*37da2899SCharles.Forsyth SSL2_STATE_SERVER_VERIFY => 1753*37da2899SCharles.Forsyth info += "Server Verify"; 1754*37da2899SCharles.Forsyth SSL2_STATE_REQUEST_CERTIFICATE => 1755*37da2899SCharles.Forsyth info += "Request Certificate"; 1756*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_CERTIFICATE => 1757*37da2899SCharles.Forsyth info += "Client Certificate"; 1758*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_FINISHED => 1759*37da2899SCharles.Forsyth info += "Client Finished"; 1760*37da2899SCharles.Forsyth SSL2_STATE_SERVER_FINISHED => 1761*37da2899SCharles.Forsyth info += "Server Finished"; 1762*37da2899SCharles.Forsyth SSL2_STATE_ERROR => 1763*37da2899SCharles.Forsyth info += "Error"; 1764*37da2899SCharles.Forsyth } 1765*37da2899SCharles.Forsyth } 1766*37da2899SCharles.Forsyth } 1767*37da2899SCharles.Forsyth else { 1768*37da2899SCharles.Forsyth info = "\n\tHandshake Version 3: "; 1769*37da2899SCharles.Forsyth 1770*37da2899SCharles.Forsyth case ctx.state { 1771*37da2899SCharles.Forsyth STATE_EXIT => 1772*37da2899SCharles.Forsyth info += "Exit"; 1773*37da2899SCharles.Forsyth 1774*37da2899SCharles.Forsyth STATE_CHANGE_CIPHER_SPEC => 1775*37da2899SCharles.Forsyth info += "Change Cipher Spec"; 1776*37da2899SCharles.Forsyth 1777*37da2899SCharles.Forsyth STATE_HELLO_REQUEST => 1778*37da2899SCharles.Forsyth info += "Hello Request"; 1779*37da2899SCharles.Forsyth 1780*37da2899SCharles.Forsyth STATE_CLIENT_HELLO => 1781*37da2899SCharles.Forsyth info += "Client Hello"; 1782*37da2899SCharles.Forsyth 1783*37da2899SCharles.Forsyth STATE_SERVER_HELLO => 1784*37da2899SCharles.Forsyth info += "Server Hello"; 1785*37da2899SCharles.Forsyth 1786*37da2899SCharles.Forsyth STATE_CLIENT_KEY_EXCHANGE => 1787*37da2899SCharles.Forsyth info += "Client Key Exchange"; 1788*37da2899SCharles.Forsyth 1789*37da2899SCharles.Forsyth STATE_SERVER_KEY_EXCHANGE => 1790*37da2899SCharles.Forsyth info += "Server Key Exchange"; 1791*37da2899SCharles.Forsyth 1792*37da2899SCharles.Forsyth STATE_SERVER_HELLO_DONE => 1793*37da2899SCharles.Forsyth info += "Server Hello Done"; 1794*37da2899SCharles.Forsyth 1795*37da2899SCharles.Forsyth STATE_CLIENT_CERTIFICATE => 1796*37da2899SCharles.Forsyth info += "Client Certificate"; 1797*37da2899SCharles.Forsyth 1798*37da2899SCharles.Forsyth STATE_SERVER_CERTIFICATE => 1799*37da2899SCharles.Forsyth info += "Server Certificate"; 1800*37da2899SCharles.Forsyth 1801*37da2899SCharles.Forsyth STATE_CERTIFICATE_VERIFY => 1802*37da2899SCharles.Forsyth info += "Certificate Verify"; 1803*37da2899SCharles.Forsyth 1804*37da2899SCharles.Forsyth STATE_FINISHED => 1805*37da2899SCharles.Forsyth info += "Finished"; 1806*37da2899SCharles.Forsyth } 1807*37da2899SCharles.Forsyth } 1808*37da2899SCharles.Forsyth 1809*37da2899SCharles.Forsyth if(ctx.status & CLIENT_AUTH) 1810*37da2899SCharles.Forsyth info += ": Client Auth"; 1811*37da2899SCharles.Forsyth if(ctx.status & CERT_REQUEST) 1812*37da2899SCharles.Forsyth info += ": Cert Request"; 1813*37da2899SCharles.Forsyth if(ctx.status & CERT_SENT) 1814*37da2899SCharles.Forsyth info += ": Cert Sent"; 1815*37da2899SCharles.Forsyth if(ctx.status & CERT_RECEIVED) 1816*37da2899SCharles.Forsyth info += ": Cert Received"; 1817*37da2899SCharles.Forsyth 1818*37da2899SCharles.Forsyth return info; 1819*37da2899SCharles.Forsyth} 1820*37da2899SCharles.Forsyth 1821*37da2899SCharles.Forsythreset_client_random(ctx: ref Context) 1822*37da2899SCharles.Forsyth{ 1823*37da2899SCharles.Forsyth ctx.client_random[0:] = int_encode(ctx.session.connection_time, 4); 1824*37da2899SCharles.Forsyth ctx.client_random[4:] = random->randombuf(Random->NotQuiteRandom, 28); 1825*37da2899SCharles.Forsyth} 1826*37da2899SCharles.Forsyth 1827*37da2899SCharles.Forsythreset_server_random(ctx: ref Context) 1828*37da2899SCharles.Forsyth{ 1829*37da2899SCharles.Forsyth ctx.server_random[0:] = int_encode(ctx.session.connection_time, 4); 1830*37da2899SCharles.Forsyth ctx.server_random[4:] = random->randombuf(Random->NotQuiteRandom, 28); 1831*37da2899SCharles.Forsyth} 1832*37da2899SCharles.Forsyth 1833*37da2899SCharles.Forsythupdate_handshake_hash(ctx: ref Context, r: ref Record): string 1834*37da2899SCharles.Forsyth{ 1835*37da2899SCharles.Forsyth err := ""; 1836*37da2899SCharles.Forsyth 1837*37da2899SCharles.Forsyth ctx.sha_state = keyring->sha1(r.data, len r.data, nil, ctx.sha_state); 1838*37da2899SCharles.Forsyth ctx.md5_state = keyring->md5(r.data, len r.data, nil, ctx.md5_state); 1839*37da2899SCharles.Forsyth if(ctx.sha_state == nil || ctx.md5_state == nil) 1840*37da2899SCharles.Forsyth err = "update handshake hash failed"; 1841*37da2899SCharles.Forsyth 1842*37da2899SCharles.Forsyth # if(SSL_DEBUG) 1843*37da2899SCharles.Forsyth # log("ssl3: update_handshake_hash\n\tmessage_data =\n\t\t" + bastr(r.data) + "\n"); 1844*37da2899SCharles.Forsyth 1845*37da2899SCharles.Forsyth return err; 1846*37da2899SCharles.Forsyth} 1847*37da2899SCharles.Forsyth 1848*37da2899SCharles.Forsyth# Note: 1849*37da2899SCharles.Forsyth# this depends on the record protocol 1850*37da2899SCharles.Forsythprotocol_read(ctx: ref Context): (ref Record, ref Protocol, string) 1851*37da2899SCharles.Forsyth{ 1852*37da2899SCharles.Forsyth p: ref Protocol; 1853*37da2899SCharles.Forsyth r: ref Record; 1854*37da2899SCharles.Forsyth e: string; 1855*37da2899SCharles.Forsyth 1856*37da2899SCharles.Forsyth vers := SSL_VERSION_2_0; 1857*37da2899SCharles.Forsyth if(ctx.status & SSL3_RECORD) 1858*37da2899SCharles.Forsyth vers = SSL_VERSION_3_0; 1859*37da2899SCharles.Forsyth if(ctx.status & USE_DEVSSL) 1860*37da2899SCharles.Forsyth (r, e) = devssl_read(ctx); 1861*37da2899SCharles.Forsyth else 1862*37da2899SCharles.Forsyth (r, e) = record_read(ctx); 1863*37da2899SCharles.Forsyth if(e != "") 1864*37da2899SCharles.Forsyth return (nil, nil, e); 1865*37da2899SCharles.Forsyth 1866*37da2899SCharles.Forsyth (p, e) = Protocol.decode(r, ctx); 1867*37da2899SCharles.Forsyth if(e != "") 1868*37da2899SCharles.Forsyth return (r, nil, e); 1869*37da2899SCharles.Forsyth 1870*37da2899SCharles.Forsyth return (r, p, nil); 1871*37da2899SCharles.Forsyth} 1872*37da2899SCharles.Forsyth 1873*37da2899SCharles.Forsyth# Alert messages with a level of fatal result in the immediate 1874*37da2899SCharles.Forsyth# termination of the connection and zero out session. 1875*37da2899SCharles.Forsyth 1876*37da2899SCharles.Forsythdo_alert(a: ref Alert, ctx: ref Context) 1877*37da2899SCharles.Forsyth{ 1878*37da2899SCharles.Forsyth case a.level { 1879*37da2899SCharles.Forsyth SSL_FATAL => 1880*37da2899SCharles.Forsyth 1881*37da2899SCharles.Forsyth case a.description { 1882*37da2899SCharles.Forsyth SSL_UNEXPECTED_MESSAGE => 1883*37da2899SCharles.Forsyth 1884*37da2899SCharles.Forsyth # should never be observed in communication 1885*37da2899SCharles.Forsyth # between proper implementations. 1886*37da2899SCharles.Forsyth break; 1887*37da2899SCharles.Forsyth 1888*37da2899SCharles.Forsyth SSL_HANDSHAKE_FAILURE => 1889*37da2899SCharles.Forsyth 1890*37da2899SCharles.Forsyth # unable to negotiate an acceptable set of security 1891*37da2899SCharles.Forsyth # parameters given the options available. 1892*37da2899SCharles.Forsyth break; 1893*37da2899SCharles.Forsyth 1894*37da2899SCharles.Forsyth * => 1895*37da2899SCharles.Forsyth break; 1896*37da2899SCharles.Forsyth } 1897*37da2899SCharles.Forsyth 1898*37da2899SCharles.Forsyth ctx.session.session_id = nil; 1899*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 1900*37da2899SCharles.Forsyth 1901*37da2899SCharles.Forsyth SSL_WARNING => 1902*37da2899SCharles.Forsyth 1903*37da2899SCharles.Forsyth case a.description { 1904*37da2899SCharles.Forsyth SSL_CLOSE_NOTIFY => 1905*37da2899SCharles.Forsyth 1906*37da2899SCharles.Forsyth if(SSL_DEBUG) 1907*37da2899SCharles.Forsyth log("ssl3: do_alert SSL_WARNING:SSL_CLOSE_NOTIFY\n"); 1908*37da2899SCharles.Forsyth # notifies the recipient that the sender will not 1909*37da2899SCharles.Forsyth # send any more messages on this connection. 1910*37da2899SCharles.Forsyth 1911*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 1912*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "ssl3: response close notify", ctx); 1913*37da2899SCharles.Forsyth 1914*37da2899SCharles.Forsyth SSL_NO_CERTIFICATE => 1915*37da2899SCharles.Forsyth 1916*37da2899SCharles.Forsyth # A no_certificate alert message may be sent in 1917*37da2899SCharles.Forsyth # response to a certification request if no 1918*37da2899SCharles.Forsyth # appropriate certificate is available. 1919*37da2899SCharles.Forsyth 1920*37da2899SCharles.Forsyth if(ctx.state == STATE_CLIENT_CERTIFICATE) { 1921*37da2899SCharles.Forsyth hm := ref Handshake.Certificate(ctx.local_info.certs); 1922*37da2899SCharles.Forsyth handshake_enque(hm, ctx); 1923*37da2899SCharles.Forsyth } 1924*37da2899SCharles.Forsyth 1925*37da2899SCharles.Forsyth SSL_BAD_CERTIFICATE or 1926*37da2899SCharles.Forsyth 1927*37da2899SCharles.Forsyth # A certificate was corrupt, contained signatures 1928*37da2899SCharles.Forsyth # that did not verify correctly, etc. 1929*37da2899SCharles.Forsyth 1930*37da2899SCharles.Forsyth SSL_UNSUPPORTED_CERTIFICATE or 1931*37da2899SCharles.Forsyth 1932*37da2899SCharles.Forsyth # A certificate was of an unsupported type. 1933*37da2899SCharles.Forsyth 1934*37da2899SCharles.Forsyth SSL_CERTIFICATE_REVOKED or 1935*37da2899SCharles.Forsyth 1936*37da2899SCharles.Forsyth # A certificate was revoked by its signer. 1937*37da2899SCharles.Forsyth 1938*37da2899SCharles.Forsyth SSL_CERTIFICATE_EXPIRED or 1939*37da2899SCharles.Forsyth 1940*37da2899SCharles.Forsyth # A certificate has expired or is not currently 1941*37da2899SCharles.Forsyth # valid. 1942*37da2899SCharles.Forsyth 1943*37da2899SCharles.Forsyth SSL_CERTIFICATE_UNKNOWN => 1944*37da2899SCharles.Forsyth 1945*37da2899SCharles.Forsyth # Some other (unspecified) issue arose in 1946*37da2899SCharles.Forsyth # processing the certificate, rendering it 1947*37da2899SCharles.Forsyth # unacceptable. 1948*37da2899SCharles.Forsyth break; 1949*37da2899SCharles.Forsyth 1950*37da2899SCharles.Forsyth * => 1951*37da2899SCharles.Forsyth ctx.session.session_id = nil; 1952*37da2899SCharles.Forsyth fatal(SSL_ILLEGAL_PARAMETER, "ssl3: unknown alert description", ctx); 1953*37da2899SCharles.Forsyth } 1954*37da2899SCharles.Forsyth 1955*37da2899SCharles.Forsyth * => 1956*37da2899SCharles.Forsyth ctx.session.session_id = nil; 1957*37da2899SCharles.Forsyth fatal(SSL_ILLEGAL_PARAMETER, "ssl3: unknown alert level received", ctx); 1958*37da2899SCharles.Forsyth } 1959*37da2899SCharles.Forsyth} 1960*37da2899SCharles.Forsyth 1961*37da2899SCharles.Forsyth# notify the receiving party that subsequent records will 1962*37da2899SCharles.Forsyth# be protected under the just-negotiated CipherSpec and keys. 1963*37da2899SCharles.Forsyth 1964*37da2899SCharles.Forsythdo_change_cipher_spec(ctx: ref Context) 1965*37da2899SCharles.Forsyth{ 1966*37da2899SCharles.Forsyth # calculate and set new keys 1967*37da2899SCharles.Forsyth if(!(ctx.status & IN_READY)) { 1968*37da2899SCharles.Forsyth e := set_in_queue(ctx); 1969*37da2899SCharles.Forsyth if(e != "") { 1970*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "do_change_cipher_spec: setup new cipher failed", ctx); 1971*37da2899SCharles.Forsyth return; 1972*37da2899SCharles.Forsyth } 1973*37da2899SCharles.Forsyth ctx.status |= IN_READY; 1974*37da2899SCharles.Forsyth 1975*37da2899SCharles.Forsyth if(SSL_DEBUG) 1976*37da2899SCharles.Forsyth log("ssl3: set in cipher done\n"); 1977*37da2899SCharles.Forsyth } 1978*37da2899SCharles.Forsyth 1979*37da2899SCharles.Forsyth ctx.state = STATE_FINISHED; 1980*37da2899SCharles.Forsyth} 1981*37da2899SCharles.Forsyth 1982*37da2899SCharles.Forsyth 1983*37da2899SCharles.Forsyth# process and advance handshake messages, update internal stack and switch to next 1984*37da2899SCharles.Forsyth# expected state(s). 1985*37da2899SCharles.Forsyth 1986*37da2899SCharles.Forsythdo_handshake(handshake: ref Handshake, ctx: ref Context) : string 1987*37da2899SCharles.Forsyth{ 1988*37da2899SCharles.Forsyth e := ""; 1989*37da2899SCharles.Forsyth 1990*37da2899SCharles.Forsyth pick h := handshake { 1991*37da2899SCharles.Forsyth HelloRequest => 1992*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != STATE_HELLO_REQUEST) { 1993*37da2899SCharles.Forsyth e = "HelloRequest"; 1994*37da2899SCharles.Forsyth break; 1995*37da2899SCharles.Forsyth } 1996*37da2899SCharles.Forsyth do_hello_request(ctx); 1997*37da2899SCharles.Forsyth 1998*37da2899SCharles.Forsyth ClientHello => 1999*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != STATE_CLIENT_HELLO) { 2000*37da2899SCharles.Forsyth e = "ClientHello"; 2001*37da2899SCharles.Forsyth break; 2002*37da2899SCharles.Forsyth } 2003*37da2899SCharles.Forsyth do_client_hello(h, ctx); 2004*37da2899SCharles.Forsyth 2005*37da2899SCharles.Forsyth ServerHello => 2006*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != STATE_SERVER_HELLO) { 2007*37da2899SCharles.Forsyth e = "ServerHello"; 2008*37da2899SCharles.Forsyth break; 2009*37da2899SCharles.Forsyth } 2010*37da2899SCharles.Forsyth do_server_hello(h, ctx); 2011*37da2899SCharles.Forsyth 2012*37da2899SCharles.Forsyth ClientKeyExchange => 2013*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != STATE_CLIENT_KEY_EXCHANGE) { 2014*37da2899SCharles.Forsyth e = "ClientKeyExchange"; 2015*37da2899SCharles.Forsyth break; 2016*37da2899SCharles.Forsyth } 2017*37da2899SCharles.Forsyth do_client_keyex(h, ctx); 2018*37da2899SCharles.Forsyth 2019*37da2899SCharles.Forsyth ServerKeyExchange => 2020*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || 2021*37da2899SCharles.Forsyth (ctx.state != STATE_SERVER_KEY_EXCHANGE && ctx.state != STATE_SERVER_HELLO_DONE)) { 2022*37da2899SCharles.Forsyth e = "ServerKeyExchange"; 2023*37da2899SCharles.Forsyth break; 2024*37da2899SCharles.Forsyth } 2025*37da2899SCharles.Forsyth do_server_keyex(h, ctx); 2026*37da2899SCharles.Forsyth 2027*37da2899SCharles.Forsyth ServerHelloDone => 2028*37da2899SCharles.Forsyth # diff from SSLRef, to support variant impl 2029*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || 2030*37da2899SCharles.Forsyth (ctx.state != STATE_SERVER_HELLO_DONE && ctx.state != STATE_SERVER_KEY_EXCHANGE)) { 2031*37da2899SCharles.Forsyth e = "ServerHelloDone"; 2032*37da2899SCharles.Forsyth break; 2033*37da2899SCharles.Forsyth } 2034*37da2899SCharles.Forsyth do_server_done(ctx); 2035*37da2899SCharles.Forsyth 2036*37da2899SCharles.Forsyth Certificate => 2037*37da2899SCharles.Forsyth if(ctx.status & CLIENT_SIDE) { 2038*37da2899SCharles.Forsyth if(ctx.state != STATE_SERVER_CERTIFICATE) { 2039*37da2899SCharles.Forsyth e = "ServerCertificate"; 2040*37da2899SCharles.Forsyth break; 2041*37da2899SCharles.Forsyth } 2042*37da2899SCharles.Forsyth do_server_cert(h, ctx); 2043*37da2899SCharles.Forsyth } 2044*37da2899SCharles.Forsyth else { 2045*37da2899SCharles.Forsyth if(ctx.state != STATE_CLIENT_CERTIFICATE) { 2046*37da2899SCharles.Forsyth e = "ClientCertificate"; 2047*37da2899SCharles.Forsyth break; 2048*37da2899SCharles.Forsyth } 2049*37da2899SCharles.Forsyth do_client_cert(h, ctx); # server_side 2050*37da2899SCharles.Forsyth } 2051*37da2899SCharles.Forsyth 2052*37da2899SCharles.Forsyth CertificateRequest => 2053*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != STATE_SERVER_HELLO_DONE 2054*37da2899SCharles.Forsyth || ctx.state != STATE_SERVER_KEY_EXCHANGE) { 2055*37da2899SCharles.Forsyth e = "CertificateRequest"; 2056*37da2899SCharles.Forsyth break; 2057*37da2899SCharles.Forsyth } 2058*37da2899SCharles.Forsyth do_cert_request(h, ctx); 2059*37da2899SCharles.Forsyth 2060*37da2899SCharles.Forsyth CertificateVerify => 2061*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != STATE_CERTIFICATE_VERIFY) { 2062*37da2899SCharles.Forsyth e = "CertificateVerify"; 2063*37da2899SCharles.Forsyth break; 2064*37da2899SCharles.Forsyth } 2065*37da2899SCharles.Forsyth do_cert_verify(h, ctx); 2066*37da2899SCharles.Forsyth 2067*37da2899SCharles.Forsyth Finished => 2068*37da2899SCharles.Forsyth if(ctx.status & CLIENT_SIDE) { 2069*37da2899SCharles.Forsyth if(ctx.state != STATE_FINISHED) { 2070*37da2899SCharles.Forsyth e = "ClientFinished"; 2071*37da2899SCharles.Forsyth break; 2072*37da2899SCharles.Forsyth } 2073*37da2899SCharles.Forsyth do_finished(SSL_CLIENT_SENDER, ctx); 2074*37da2899SCharles.Forsyth } 2075*37da2899SCharles.Forsyth else { 2076*37da2899SCharles.Forsyth if(ctx.state != STATE_FINISHED) { 2077*37da2899SCharles.Forsyth e = "ServerFinished"; 2078*37da2899SCharles.Forsyth break; 2079*37da2899SCharles.Forsyth } 2080*37da2899SCharles.Forsyth do_finished(SSL_SERVER_SENDER, ctx); 2081*37da2899SCharles.Forsyth } 2082*37da2899SCharles.Forsyth 2083*37da2899SCharles.Forsyth * => 2084*37da2899SCharles.Forsyth e = "unknown handshake message"; 2085*37da2899SCharles.Forsyth } 2086*37da2899SCharles.Forsyth 2087*37da2899SCharles.Forsyth if(e != nil) 2088*37da2899SCharles.Forsyth e = "do_handshake: " + e; 2089*37da2899SCharles.Forsyth 2090*37da2899SCharles.Forsyth return e; 2091*37da2899SCharles.Forsyth} 2092*37da2899SCharles.Forsyth 2093*37da2899SCharles.Forsyth# [client side] 2094*37da2899SCharles.Forsyth# The hello request message may be sent by server at any time, but will be ignored by 2095*37da2899SCharles.Forsyth# the client if the handshake protocol is already underway. It is simple notification 2096*37da2899SCharles.Forsyth# that the client should begin the negotiation process anew by sending a client hello 2097*37da2899SCharles.Forsyth# message. 2098*37da2899SCharles.Forsyth 2099*37da2899SCharles.Forsythdo_hello_request(ctx: ref Context) 2100*37da2899SCharles.Forsyth{ 2101*37da2899SCharles.Forsyth # start from new handshake digest state 2102*37da2899SCharles.Forsyth ctx.sha_state = ctx.md5_state = nil; 2103*37da2899SCharles.Forsyth 2104*37da2899SCharles.Forsyth # Note: 2105*37da2899SCharles.Forsyth # sending ctx.local_info.suites instead of ctx.session.suite, 2106*37da2899SCharles.Forsyth # if session is resumable by server, ctx.session.suite will be used. 2107*37da2899SCharles.Forsyth handshake_enque( 2108*37da2899SCharles.Forsyth ref Handshake.ClientHello( 2109*37da2899SCharles.Forsyth ctx.session.version, 2110*37da2899SCharles.Forsyth ctx.client_random, 2111*37da2899SCharles.Forsyth ctx.session.session_id, 2112*37da2899SCharles.Forsyth ctx.local_info.suites, 2113*37da2899SCharles.Forsyth ctx.local_info.comprs 2114*37da2899SCharles.Forsyth ), 2115*37da2899SCharles.Forsyth ctx 2116*37da2899SCharles.Forsyth ); 2117*37da2899SCharles.Forsyth 2118*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_HELLO; 2119*37da2899SCharles.Forsyth} 2120*37da2899SCharles.Forsyth 2121*37da2899SCharles.Forsyth# [client side] 2122*37da2899SCharles.Forsyth# Processes the received server hello handshake message and determines if the session 2123*37da2899SCharles.Forsyth# is resumable. (The client sends a client hello using the session id of the session 2124*37da2899SCharles.Forsyth# to be resumed. The server then checks its session cache for a match. If a match is 2125*37da2899SCharles.Forsyth# FOUND, and the server is WILLING to re-establish the connection under the specified 2126*37da2899SCharles.Forsyth# session state, it will send a server hello with the SAME session id value.) If the 2127*37da2899SCharles.Forsyth# session is resumed, at this point both client and server must send change cipher 2128*37da2899SCharles.Forsyth# spec messages. If the session is not resumable, the client and server perform 2129*37da2899SCharles.Forsyth# a full handshake. (On the server side, if a session id match is not found, the 2130*37da2899SCharles.Forsyth# server generates a new session id or if the server is not willing to resume, the 2131*37da2899SCharles.Forsyth# server uses a null session id). 2132*37da2899SCharles.Forsyth 2133*37da2899SCharles.Forsythdo_server_hello(hm: ref Handshake.ServerHello, ctx: ref Context) 2134*37da2899SCharles.Forsyth{ 2135*37da2899SCharles.Forsyth # trying to resume 2136*37da2899SCharles.Forsyth if(bytes_cmp(ctx.session.session_id, hm.session_id) == 0) { 2137*37da2899SCharles.Forsyth 2138*37da2899SCharles.Forsyth if(SSL_DEBUG) 2139*37da2899SCharles.Forsyth log("ssl3: session resumed\n"); 2140*37da2899SCharles.Forsyth 2141*37da2899SCharles.Forsyth ctx.status |= SESSION_RESUMABLE; 2142*37da2899SCharles.Forsyth # avoid version attack 2143*37da2899SCharles.Forsyth if(ctx.session.version[0] != hm.version[0] || 2144*37da2899SCharles.Forsyth ctx.session.version[1] != hm.version[1]) { 2145*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "do_server_hello: version mismatch", ctx); 2146*37da2899SCharles.Forsyth return; 2147*37da2899SCharles.Forsyth } 2148*37da2899SCharles.Forsyth 2149*37da2899SCharles.Forsyth ctx.server_random = hm.random; 2150*37da2899SCharles.Forsyth 2151*37da2899SCharles.Forsyth # uses the retrieved session suite by server (should be same by client) 2152*37da2899SCharles.Forsyth (ciph, keyx, sign, e) 2153*37da2899SCharles.Forsyth := suite_to_spec(hm.suite, SSL3_Suites); 2154*37da2899SCharles.Forsyth if(e != nil) { 2155*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "server hello: suite not found", ctx); 2156*37da2899SCharles.Forsyth return; 2157*37da2899SCharles.Forsyth } 2158*37da2899SCharles.Forsyth ctx.sel_ciph = ciph; 2159*37da2899SCharles.Forsyth ctx.sel_keyx = keyx; 2160*37da2899SCharles.Forsyth ctx.sel_sign = sign; 2161*37da2899SCharles.Forsyth ctx.sel_cmpr = int ctx.session.compression; # not supported by ssl3 yet 2162*37da2899SCharles.Forsyth 2163*37da2899SCharles.Forsyth # calculate keys 2164*37da2899SCharles.Forsyth (ctx.cw_mac, ctx.sw_mac, ctx.cw_key, ctx.sw_key, ctx.cw_IV, ctx.sw_IV) 2165*37da2899SCharles.Forsyth = calc_keys(ctx.sel_ciph, ctx.session.master_secret, 2166*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 2167*37da2899SCharles.Forsyth 2168*37da2899SCharles.Forsyth 2169*37da2899SCharles.Forsyth ctx.state = STATE_CHANGE_CIPHER_SPEC; 2170*37da2899SCharles.Forsyth } 2171*37da2899SCharles.Forsyth else { 2172*37da2899SCharles.Forsyth ctx.status &= ~SESSION_RESUMABLE; 2173*37da2899SCharles.Forsyth 2174*37da2899SCharles.Forsyth # On the server side, if a session id match is not found, the 2175*37da2899SCharles.Forsyth # server generates a new session id or if the server is not willing 2176*37da2899SCharles.Forsyth # to resume, the server uses an empty session id and cannot be 2177*37da2899SCharles.Forsyth # cached by both client and server. 2178*37da2899SCharles.Forsyth 2179*37da2899SCharles.Forsyth ctx.session.session_id = hm.session_id; 2180*37da2899SCharles.Forsyth ctx.session.version = hm.version; 2181*37da2899SCharles.Forsyth ctx.server_random = hm.random; 2182*37da2899SCharles.Forsyth 2183*37da2899SCharles.Forsyth if(SSL_DEBUG) 2184*37da2899SCharles.Forsyth log("ssl3: do_server_hello:\n\tselected cipher suite =\n\t\t" 2185*37da2899SCharles.Forsyth + cipher_suite_info(hm.suite, SSL3_Suites) + "\n"); 2186*37da2899SCharles.Forsyth 2187*37da2899SCharles.Forsyth (ciph, keyx, sign, e) := suite_to_spec(hm.suite, SSL3_Suites); 2188*37da2899SCharles.Forsyth if(e != nil) { 2189*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "server hello: suite not found", ctx); 2190*37da2899SCharles.Forsyth return; 2191*37da2899SCharles.Forsyth } 2192*37da2899SCharles.Forsyth 2193*37da2899SCharles.Forsyth ctx.sel_ciph = ciph; 2194*37da2899SCharles.Forsyth ctx.sel_keyx = keyx; 2195*37da2899SCharles.Forsyth ctx.sel_sign = sign; 2196*37da2899SCharles.Forsyth ctx.sel_cmpr = int hm.compression; # not supported by ssl3 yet 2197*37da2899SCharles.Forsyth 2198*37da2899SCharles.Forsyth # next state is determined by selected key exchange and signature methods 2199*37da2899SCharles.Forsyth # the ctx.sel_keyx and ctx.sel_sign are completed by the following handshake 2200*37da2899SCharles.Forsyth # Certificate and/or ServerKeyExchange 2201*37da2899SCharles.Forsyth 2202*37da2899SCharles.Forsyth if(tagof ctx.sel_keyx == tagof KeyExAlg.DH && 2203*37da2899SCharles.Forsyth tagof ctx.sel_sign == tagof SigAlg.anon) 2204*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_KEY_EXCHANGE; 2205*37da2899SCharles.Forsyth else 2206*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_CERTIFICATE; 2207*37da2899SCharles.Forsyth } 2208*37da2899SCharles.Forsyth} 2209*37da2899SCharles.Forsyth 2210*37da2899SCharles.Forsyth# [client side] 2211*37da2899SCharles.Forsyth# Processes the received server key exchange message. The server key exchange message 2212*37da2899SCharles.Forsyth# is sent by the server if it has no certificate, has a certificate only used for 2213*37da2899SCharles.Forsyth# signing, or FORTEZZA KEA key exchange is used. 2214*37da2899SCharles.Forsyth 2215*37da2899SCharles.Forsythdo_server_keyex(hm: ref Handshake.ServerKeyExchange, ctx: ref Context) 2216*37da2899SCharles.Forsyth{ 2217*37da2899SCharles.Forsyth # install exchange keys sent by server, this may require public key 2218*37da2899SCharles.Forsyth # retrieved from certificate sent by Handshake.Certificate message 2219*37da2899SCharles.Forsyth 2220*37da2899SCharles.Forsyth (err, i) := install_server_xkey(hm.xkey, ctx.sel_keyx); 2221*37da2899SCharles.Forsyth if(err == "") 2222*37da2899SCharles.Forsyth err = verify_server_xkey(ctx.client_random, ctx.server_random, hm.xkey, i, ctx.sel_sign); 2223*37da2899SCharles.Forsyth 2224*37da2899SCharles.Forsyth if(err == "") 2225*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_HELLO_DONE; 2226*37da2899SCharles.Forsyth else 2227*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_server_keyex: " + err, ctx); 2228*37da2899SCharles.Forsyth} 2229*37da2899SCharles.Forsyth 2230*37da2899SCharles.Forsyth# [client side] 2231*37da2899SCharles.Forsyth# Processes the received server hello done message by verifying that the server 2232*37da2899SCharles.Forsyth# provided a valid certificate if required and checking that the server hello 2233*37da2899SCharles.Forsyth# parameters are acceptable. 2234*37da2899SCharles.Forsyth 2235*37da2899SCharles.Forsythdo_server_done(ctx: ref Context) 2236*37da2899SCharles.Forsyth{ 2237*37da2899SCharles.Forsyth # On client side, optionally send client cert chain if client_auth 2238*37da2899SCharles.Forsyth # is required by the server. The server may drop the connection, 2239*37da2899SCharles.Forsyth # if it does not receive client certificate in the following 2240*37da2899SCharles.Forsyth # Handshake.ClientCertificate message 2241*37da2899SCharles.Forsyth if(ctx.status & CLIENT_AUTH) { 2242*37da2899SCharles.Forsyth if(ctx.local_info.certs != nil) { 2243*37da2899SCharles.Forsyth handshake_enque( 2244*37da2899SCharles.Forsyth ref Handshake.Certificate(ctx.local_info.certs), 2245*37da2899SCharles.Forsyth ctx 2246*37da2899SCharles.Forsyth ); 2247*37da2899SCharles.Forsyth ctx.status |= CERT_SENT; 2248*37da2899SCharles.Forsyth } 2249*37da2899SCharles.Forsyth else { 2250*37da2899SCharles.Forsyth alert_enque( 2251*37da2899SCharles.Forsyth ref Alert(SSL_WARNING, SSL_NO_CERTIFICATE), 2252*37da2899SCharles.Forsyth ctx 2253*37da2899SCharles.Forsyth ); 2254*37da2899SCharles.Forsyth } 2255*37da2899SCharles.Forsyth } 2256*37da2899SCharles.Forsyth 2257*37da2899SCharles.Forsyth # calculate premaster secrect, client exchange keys and update ref KeyExAlg 2258*37da2899SCharles.Forsyth # of the client side 2259*37da2899SCharles.Forsyth (x, pm, e) := calc_client_xkey(ctx.sel_keyx); 2260*37da2899SCharles.Forsyth if(e != "") { 2261*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, e, ctx); 2262*37da2899SCharles.Forsyth return; 2263*37da2899SCharles.Forsyth } 2264*37da2899SCharles.Forsyth handshake_enque(ref Handshake.ClientKeyExchange(x), ctx); 2265*37da2899SCharles.Forsyth 2266*37da2899SCharles.Forsyth ms := calc_master_secret(pm, ctx.client_random, ctx.server_random); 2267*37da2899SCharles.Forsyth if(ms == nil) { 2268*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "server hello done: calc master secret failed", ctx); 2269*37da2899SCharles.Forsyth return; 2270*37da2899SCharles.Forsyth } 2271*37da2899SCharles.Forsyth # ctx.premaster_secret = pm; 2272*37da2899SCharles.Forsyth ctx.session.master_secret = ms; 2273*37da2899SCharles.Forsyth 2274*37da2899SCharles.Forsyth # sending certificate verifiy message if the client auth is required 2275*37da2899SCharles.Forsyth # and client certificate has been sent, 2276*37da2899SCharles.Forsyth if(ctx.status & CERT_SENT) { 2277*37da2899SCharles.Forsyth sig : array of byte; 2278*37da2899SCharles.Forsyth (md5_hash, sha_hash) 2279*37da2899SCharles.Forsyth := calc_finished(nil, ctx.session.master_secret, ctx.sha_state, ctx.md5_state); 2280*37da2899SCharles.Forsyth # check type of client cert being sent 2281*37da2899SCharles.Forsyth pick sk := ctx.local_info.sk { 2282*37da2899SCharles.Forsyth RSA => 2283*37da2899SCharles.Forsyth hashes := array [36] of byte; 2284*37da2899SCharles.Forsyth hashes[0:] = md5_hash; 2285*37da2899SCharles.Forsyth hashes[16:] = sha_hash; 2286*37da2899SCharles.Forsyth #(e, sig) = pkcs->rsa_sign(hashes, sk, PKCS->MD5_WithRSAEncryption); 2287*37da2899SCharles.Forsyth DSS => 2288*37da2899SCharles.Forsyth #(e, sig) = pkcs->dss_sign(sha_hash, sk); 2289*37da2899SCharles.Forsyth * => 2290*37da2899SCharles.Forsyth e = "unknown sign"; 2291*37da2899SCharles.Forsyth } 2292*37da2899SCharles.Forsyth if(e != "") { 2293*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "server hello done: sign cert verify failed", ctx); 2294*37da2899SCharles.Forsyth return; 2295*37da2899SCharles.Forsyth } 2296*37da2899SCharles.Forsyth handshake_enque(ref Handshake.CertificateVerify(sig), ctx); 2297*37da2899SCharles.Forsyth } 2298*37da2899SCharles.Forsyth 2299*37da2899SCharles.Forsyth ccs_enque(ref ChangeCipherSpec(1), ctx); 2300*37da2899SCharles.Forsyth (ctx.cw_mac, ctx.sw_mac, ctx.cw_key, ctx.sw_key, ctx.cw_IV, ctx.sw_IV) 2301*37da2899SCharles.Forsyth = calc_keys(ctx.sel_ciph, ctx.session.master_secret, 2302*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 2303*37da2899SCharles.Forsyth 2304*37da2899SCharles.Forsyth # set cipher on write channel 2305*37da2899SCharles.Forsyth e = set_out_queue(ctx); 2306*37da2899SCharles.Forsyth if(e != nil) { 2307*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_server_done: " + e, ctx); 2308*37da2899SCharles.Forsyth return; 2309*37da2899SCharles.Forsyth } 2310*37da2899SCharles.Forsyth ctx.status |= OUT_READY; 2311*37da2899SCharles.Forsyth 2312*37da2899SCharles.Forsyth if(SSL_DEBUG) 2313*37da2899SCharles.Forsyth log("ssl3: set out cipher done\n"); 2314*37da2899SCharles.Forsyth (mh, sh) := calc_finished(SSL_CLIENT_SENDER, ctx.session.master_secret, 2315*37da2899SCharles.Forsyth ctx.sha_state, ctx.md5_state); 2316*37da2899SCharles.Forsyth# sending out the Finished msg causes MS https servers to hangup 2317*37da2899SCharles.Forsyth#sys->print("RETURNING FROM DO_SERVER_DONE\n"); 2318*37da2899SCharles.Forsyth#return; 2319*37da2899SCharles.Forsyth handshake_enque(ref Handshake.Finished(mh, sh), ctx); 2320*37da2899SCharles.Forsyth 2321*37da2899SCharles.Forsyth ctx.state = STATE_CHANGE_CIPHER_SPEC; 2322*37da2899SCharles.Forsyth} 2323*37da2899SCharles.Forsyth 2324*37da2899SCharles.Forsyth# [client side] 2325*37da2899SCharles.Forsyth# Process the received certificate message. 2326*37da2899SCharles.Forsyth# Note: 2327*37da2899SCharles.Forsyth# according to current US export law, RSA moduli larger than 512 bits 2328*37da2899SCharles.Forsyth# may not be used for key exchange in software exported from US. With 2329*37da2899SCharles.Forsyth# this message, larger RSA keys may be used as signature only 2330*37da2899SCharles.Forsyth# certificates to sign temporary shorter RSA keys for key exchange. 2331*37da2899SCharles.Forsyth 2332*37da2899SCharles.Forsythdo_server_cert(hm: ref Handshake.Certificate, ctx: ref Context) 2333*37da2899SCharles.Forsyth{ 2334*37da2899SCharles.Forsyth if(hm.cert_list == nil) { 2335*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "nil peer certificate", ctx); 2336*37da2899SCharles.Forsyth return; 2337*37da2899SCharles.Forsyth } 2338*37da2899SCharles.Forsyth 2339*37da2899SCharles.Forsyth # server's certificate is the last one in the chain (reverse required) 2340*37da2899SCharles.Forsyth cl := hm.cert_list; 2341*37da2899SCharles.Forsyth ctx.session.peer_certs = nil; 2342*37da2899SCharles.Forsyth while(cl != nil) { 2343*37da2899SCharles.Forsyth ctx.session.peer_certs = hd cl::ctx.session.peer_certs; 2344*37da2899SCharles.Forsyth cl = tl cl; 2345*37da2899SCharles.Forsyth } 2346*37da2899SCharles.Forsyth 2347*37da2899SCharles.Forsyth # TODO: verify certificate chain 2348*37da2899SCharles.Forsyth # check if in the acceptable dnlist 2349*37da2899SCharles.Forsyth # ctx.sel_keyx.peer_pk = x509->verify_chain(ctx.session.peer_certs); 2350*37da2899SCharles.Forsyth if(SSL_DEBUG) 2351*37da2899SCharles.Forsyth log("ssl3: number certificates got: " + string len ctx.session.peer_certs); 2352*37da2899SCharles.Forsyth peer_cert := hd ctx.session.peer_certs; 2353*37da2899SCharles.Forsyth (e, signed) := x509->Signed.decode(peer_cert); 2354*37da2899SCharles.Forsyth if(e != "") { 2355*37da2899SCharles.Forsyth if(SSL_DEBUG) 2356*37da2899SCharles.Forsyth log("ss3: server certificate: " + e); 2357*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "server certificate: " + e, ctx); 2358*37da2899SCharles.Forsyth return; 2359*37da2899SCharles.Forsyth } 2360*37da2899SCharles.Forsyth 2361*37da2899SCharles.Forsyth srv_cert: ref Certificate; 2362*37da2899SCharles.Forsyth (e, srv_cert) = x509->Certificate.decode(signed.tobe_signed); 2363*37da2899SCharles.Forsyth if(e != "") { 2364*37da2899SCharles.Forsyth if(SSL_DEBUG) 2365*37da2899SCharles.Forsyth log("ss3: server certificate: " + e); 2366*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "server certificate: " + e, ctx); 2367*37da2899SCharles.Forsyth return; 2368*37da2899SCharles.Forsyth } 2369*37da2899SCharles.Forsyth if(SSL_DEBUG) 2370*37da2899SCharles.Forsyth log("ssl3: " + srv_cert.tostring()); 2371*37da2899SCharles.Forsyth 2372*37da2899SCharles.Forsyth # extract and determine byte of user certificate 2373*37da2899SCharles.Forsyth id: int; 2374*37da2899SCharles.Forsyth peer_pk: ref X509->PublicKey; 2375*37da2899SCharles.Forsyth (e, id, peer_pk) = srv_cert.subject_pkinfo.getPublicKey(); 2376*37da2899SCharles.Forsyth if(e != "") { 2377*37da2899SCharles.Forsyth if(SSL_DEBUG) 2378*37da2899SCharles.Forsyth log("ss3: server certificate: " + e); 2379*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "server certificate:" + e, ctx); 2380*37da2899SCharles.Forsyth return; 2381*37da2899SCharles.Forsyth } 2382*37da2899SCharles.Forsyth 2383*37da2899SCharles.Forsyth pick key := peer_pk { 2384*37da2899SCharles.Forsyth RSA => 2385*37da2899SCharles.Forsyth # TODO: to allow checking X509v3 KeyUsage extension 2386*37da2899SCharles.Forsyth if((0 && key.pk.modulus.bits() > 512 && ctx.sel_ciph.is_exportable) 2387*37da2899SCharles.Forsyth || id == PKCS->id_pkcs_md2WithRSAEncryption 2388*37da2899SCharles.Forsyth || id == PKCS->id_pkcs_md4WithRSAEncryption 2389*37da2899SCharles.Forsyth || id == PKCS->id_pkcs_md5WithRSAEncryption) { 2390*37da2899SCharles.Forsyth pick sign := ctx.sel_sign { 2391*37da2899SCharles.Forsyth anon => 2392*37da2899SCharles.Forsyth break; 2393*37da2899SCharles.Forsyth RSA => 2394*37da2899SCharles.Forsyth break; 2395*37da2899SCharles.Forsyth * => 2396*37da2899SCharles.Forsyth # error 2397*37da2899SCharles.Forsyth } 2398*37da2899SCharles.Forsyth if(ctx.local_info.sk == nil) 2399*37da2899SCharles.Forsyth ctx.sel_sign = ref SigAlg.RSA(nil, key.pk); 2400*37da2899SCharles.Forsyth else { 2401*37da2899SCharles.Forsyth pick mysk := ctx.local_info.sk { 2402*37da2899SCharles.Forsyth RSA => 2403*37da2899SCharles.Forsyth ctx.sel_sign = ref SigAlg.RSA(mysk.sk, key.pk); 2404*37da2899SCharles.Forsyth * => 2405*37da2899SCharles.Forsyth ctx.sel_sign = ref SigAlg.RSA(nil, key.pk); 2406*37da2899SCharles.Forsyth } 2407*37da2899SCharles.Forsyth } 2408*37da2899SCharles.Forsyth # key exchange may be tmp RSA, emhemeral DH depending on cipher suite 2409*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_KEY_EXCHANGE; 2410*37da2899SCharles.Forsyth } 2411*37da2899SCharles.Forsyth # TODO: allow id == PKCS->id_rsa 2412*37da2899SCharles.Forsyth else if(id == PKCS->id_pkcs_rsaEncryption) { 2413*37da2899SCharles.Forsyth pick sign := ctx.sel_sign { 2414*37da2899SCharles.Forsyth anon => 2415*37da2899SCharles.Forsyth break; 2416*37da2899SCharles.Forsyth * => 2417*37da2899SCharles.Forsyth # error 2418*37da2899SCharles.Forsyth } 2419*37da2899SCharles.Forsyth ctx.sel_sign = ref SigAlg.anon(); 2420*37da2899SCharles.Forsyth pick keyx := ctx.sel_keyx { 2421*37da2899SCharles.Forsyth RSA => 2422*37da2899SCharles.Forsyth keyx.peer_pk = key.pk; 2423*37da2899SCharles.Forsyth * => 2424*37da2899SCharles.Forsyth # error 2425*37da2899SCharles.Forsyth } 2426*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_HELLO_DONE; 2427*37da2899SCharles.Forsyth } 2428*37da2899SCharles.Forsyth else { 2429*37da2899SCharles.Forsyth # error 2430*37da2899SCharles.Forsyth } 2431*37da2899SCharles.Forsyth DSS => 2432*37da2899SCharles.Forsyth pick sign := ctx.sel_sign { 2433*37da2899SCharles.Forsyth DSS => 2434*37da2899SCharles.Forsyth sign.peer_pk = key.pk; 2435*37da2899SCharles.Forsyth break; 2436*37da2899SCharles.Forsyth * => 2437*37da2899SCharles.Forsyth # error 2438*37da2899SCharles.Forsyth } 2439*37da2899SCharles.Forsyth # should be key exchagne such as emhemeral DH 2440*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_KEY_EXCHANGE; 2441*37da2899SCharles.Forsyth DH => 2442*37da2899SCharles.Forsyth # fixed DH signed in certificate either by RSA or DSS??? 2443*37da2899SCharles.Forsyth pick keyx := ctx.sel_keyx { 2444*37da2899SCharles.Forsyth DH => 2445*37da2899SCharles.Forsyth keyx.peer_pk = key.pk; 2446*37da2899SCharles.Forsyth * => 2447*37da2899SCharles.Forsyth # error 2448*37da2899SCharles.Forsyth } 2449*37da2899SCharles.Forsyth ctx.state = STATE_SERVER_KEY_EXCHANGE; 2450*37da2899SCharles.Forsyth } 2451*37da2899SCharles.Forsyth 2452*37da2899SCharles.Forsyth if(e != nil) { 2453*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_server_cert: " + e, ctx); 2454*37da2899SCharles.Forsyth return; 2455*37da2899SCharles.Forsyth } 2456*37da2899SCharles.Forsyth} 2457*37da2899SCharles.Forsyth 2458*37da2899SCharles.Forsyth# [client side] 2459*37da2899SCharles.Forsyth# Processes certificate request message. A non-anonymous server can optionally 2460*37da2899SCharles.Forsyth# request a certificate from the client, if appropriate for the selected cipher 2461*37da2899SCharles.Forsyth# suite It is a fatal handshake failure alert for an anonymous server to 2462*37da2899SCharles.Forsyth# request client identification. 2463*37da2899SCharles.Forsyth 2464*37da2899SCharles.Forsyth# TODO: use another module to do x509 certs, lookup and matching rules 2465*37da2899SCharles.Forsyth 2466*37da2899SCharles.Forsythdo_cert_request(hm: ref Handshake.CertificateRequest, ctx: ref Context) 2467*37da2899SCharles.Forsyth{ 2468*37da2899SCharles.Forsyth found := 0; 2469*37da2899SCharles.Forsyth for(i := 0; i < len hm.cert_types; i++) { 2470*37da2899SCharles.Forsyth if(ctx.local_info.root_type == int hm.cert_types[i]) { 2471*37da2899SCharles.Forsyth found = 1; 2472*37da2899SCharles.Forsyth break; 2473*37da2899SCharles.Forsyth } 2474*37da2899SCharles.Forsyth } 2475*37da2899SCharles.Forsyth if(!found) { 2476*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_cert_request: no required type of cert", ctx); 2477*37da2899SCharles.Forsyth return; 2478*37da2899SCharles.Forsyth } 2479*37da2899SCharles.Forsyth if(dn_cmp(ctx.local_info.dns, hm.dn_list) < 0) { 2480*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_cert_request: no required dn", ctx); 2481*37da2899SCharles.Forsyth return; 2482*37da2899SCharles.Forsyth } 2483*37da2899SCharles.Forsyth if(ctx.session.peer_certs == nil) { 2484*37da2899SCharles.Forsyth fatal(SSL_NO_CERTIFICATE, "certificate request: no peer certificates", ctx); 2485*37da2899SCharles.Forsyth return; 2486*37da2899SCharles.Forsyth } 2487*37da2899SCharles.Forsyth 2488*37da2899SCharles.Forsyth ctx.status |= CLIENT_AUTH; 2489*37da2899SCharles.Forsyth} 2490*37da2899SCharles.Forsyth 2491*37da2899SCharles.Forsythdn_cmp(a, b: list of array of byte): int 2492*37da2899SCharles.Forsyth{ 2493*37da2899SCharles.Forsyth return -1; 2494*37da2899SCharles.Forsyth} 2495*37da2899SCharles.Forsyth 2496*37da2899SCharles.Forsyth# [server side] 2497*37da2899SCharles.Forsyth# Process client hello message. 2498*37da2899SCharles.Forsyth 2499*37da2899SCharles.Forsythdo_client_hello(hm: ref Handshake.ClientHello, ctx: ref Context) 2500*37da2899SCharles.Forsyth{ 2501*37da2899SCharles.Forsyth sndm : ref Handshake; 2502*37da2899SCharles.Forsyth e : string; 2503*37da2899SCharles.Forsyth 2504*37da2899SCharles.Forsyth if(hm.version[0] != SSL_VERSION_3_0[0] || hm.version[1] != SSL_VERSION_3_0[1]) { 2505*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "client hello: version mismatch", ctx); 2506*37da2899SCharles.Forsyth return; 2507*37da2899SCharles.Forsyth } 2508*37da2899SCharles.Forsyth # else SSL_VERSION_2_0 2509*37da2899SCharles.Forsyth 2510*37da2899SCharles.Forsyth if(hm.session_id != nil) { # trying to resume 2511*37da2899SCharles.Forsyth if(ctx.status & SESSION_RESUMABLE) { 2512*37da2899SCharles.Forsyth s := sslsession->get_session_byid(hm.session_id); 2513*37da2899SCharles.Forsyth if(s == nil) { 2514*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "client hello: retrieve nil session", ctx); 2515*37da2899SCharles.Forsyth return; 2516*37da2899SCharles.Forsyth } 2517*37da2899SCharles.Forsyth 2518*37da2899SCharles.Forsyth if(s.version[0] != hm.version[0] || s.version[1] != hm.version[1]) { 2519*37da2899SCharles.Forsyth # avoid version attack 2520*37da2899SCharles.Forsyth fatal(SSL_UNEXPECTED_MESSAGE, "client hello: protocol mismatch", ctx); 2521*37da2899SCharles.Forsyth return; 2522*37da2899SCharles.Forsyth } 2523*37da2899SCharles.Forsyth 2524*37da2899SCharles.Forsyth reset_server_random(ctx); 2525*37da2899SCharles.Forsyth ctx.client_random = hm.random; 2526*37da2899SCharles.Forsyth 2527*37da2899SCharles.Forsyth sndm = ref Handshake.ServerHello(s.version, ctx.server_random, 2528*37da2899SCharles.Forsyth s.session_id, s.suite, s.compression); 2529*37da2899SCharles.Forsyth handshake_enque(sndm, ctx); 2530*37da2899SCharles.Forsyth 2531*37da2899SCharles.Forsyth ccs_enque(ref ChangeCipherSpec(1), ctx); 2532*37da2899SCharles.Forsyth # use existing master_secret, calc keys 2533*37da2899SCharles.Forsyth (ctx.cw_mac, ctx.sw_mac, ctx.cw_key, ctx.sw_key, ctx.cw_IV, ctx.sw_IV) 2534*37da2899SCharles.Forsyth = calc_keys(ctx.sel_ciph, ctx.session.master_secret, ctx.client_random, 2535*37da2899SCharles.Forsyth ctx.server_random); 2536*37da2899SCharles.Forsyth e = set_out_queue(ctx); 2537*37da2899SCharles.Forsyth if(e != nil) { 2538*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "client hello: setup new cipher failure", ctx); 2539*37da2899SCharles.Forsyth return; 2540*37da2899SCharles.Forsyth } 2541*37da2899SCharles.Forsyth if(SSL_DEBUG) 2542*37da2899SCharles.Forsyth log("do_client_hello: set out cipher done\n"); 2543*37da2899SCharles.Forsyth 2544*37da2899SCharles.Forsyth (md5_hash, sha_hash) := calc_finished(SSL_SERVER_SENDER, 2545*37da2899SCharles.Forsyth s.master_secret, ctx.sha_state, ctx.md5_state); 2546*37da2899SCharles.Forsyth 2547*37da2899SCharles.Forsyth handshake_enque(ref Handshake.Finished(md5_hash, sha_hash), ctx); 2548*37da2899SCharles.Forsyth 2549*37da2899SCharles.Forsyth ctx.session = s; 2550*37da2899SCharles.Forsyth ctx.state = STATE_CHANGE_CIPHER_SPEC; 2551*37da2899SCharles.Forsyth return; 2552*37da2899SCharles.Forsyth } 2553*37da2899SCharles.Forsyth 2554*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "client hello: resume session failed", ctx); 2555*37da2899SCharles.Forsyth return; 2556*37da2899SCharles.Forsyth } 2557*37da2899SCharles.Forsyth 2558*37da2899SCharles.Forsyth ctx.session.version = hm.version; 2559*37da2899SCharles.Forsyth if(ctx.session.peer != nil) { 2560*37da2899SCharles.Forsyth ctx.session.session_id = random->randombuf(Random->NotQuiteRandom, 32); 2561*37da2899SCharles.Forsyth if(ctx.session.session_id == nil) { 2562*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "client hello: generate session id failed", ctx); 2563*37da2899SCharles.Forsyth return; 2564*37da2899SCharles.Forsyth } 2565*37da2899SCharles.Forsyth } 2566*37da2899SCharles.Forsyth 2567*37da2899SCharles.Forsyth suite := find_cipher_suite(hm.suites, ctx.local_info.suites); 2568*37da2899SCharles.Forsyth if(suite != nil) { 2569*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "client hello: find cipher suite failed", ctx); 2570*37da2899SCharles.Forsyth return; 2571*37da2899SCharles.Forsyth } 2572*37da2899SCharles.Forsyth 2573*37da2899SCharles.Forsyth (ctx.sel_ciph, ctx.sel_keyx, ctx.sel_sign, e) = suite_to_spec(suite, SSL3_Suites); 2574*37da2899SCharles.Forsyth if(e != nil) { 2575*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "client hello: find cipher suite failed" + e, ctx); 2576*37da2899SCharles.Forsyth return; 2577*37da2899SCharles.Forsyth } 2578*37da2899SCharles.Forsyth 2579*37da2899SCharles.Forsyth # not supported by ssl3 yet 2580*37da2899SCharles.Forsyth ctx.sel_cmpr = int hm.compressions[0]; 2581*37da2899SCharles.Forsyth ctx.client_random = hm.random; 2582*37da2899SCharles.Forsyth ctx.sha_state = nil; 2583*37da2899SCharles.Forsyth ctx.md5_state = nil; 2584*37da2899SCharles.Forsyth 2585*37da2899SCharles.Forsyth sndm = ref Handshake.ServerHello(ctx.session.version, ctx.server_random, 2586*37da2899SCharles.Forsyth ctx.session.session_id, ctx.session.suite, ctx.session.compression); 2587*37da2899SCharles.Forsyth handshake_enque(sndm, ctx); 2588*37da2899SCharles.Forsyth 2589*37da2899SCharles.Forsyth # set up keys based on algorithms 2590*37da2899SCharles.Forsyth 2591*37da2899SCharles.Forsyth if(tagof ctx.sel_keyx != tagof KeyExAlg.DH) { 2592*37da2899SCharles.Forsyth if(ctx.local_info.certs == nil || ctx.local_info.sk == nil) { 2593*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "client hello: no local cert or key", ctx); 2594*37da2899SCharles.Forsyth return; 2595*37da2899SCharles.Forsyth } 2596*37da2899SCharles.Forsyth 2597*37da2899SCharles.Forsyth sndm = ref Handshake.Certificate(ctx.local_info.certs); 2598*37da2899SCharles.Forsyth handshake_enque(sndm, ctx); 2599*37da2899SCharles.Forsyth } 2600*37da2899SCharles.Forsyth 2601*37da2899SCharles.Forsyth if(tagof ctx.sel_keyx != tagof KeyExAlg.RSA || 2602*37da2899SCharles.Forsyth tagof ctx.sel_sign != tagof SigAlg.anon) { 2603*37da2899SCharles.Forsyth params, signed_params, xkey: array of byte; 2604*37da2899SCharles.Forsyth (params, e) = calc_server_xkey(ctx.sel_keyx); 2605*37da2899SCharles.Forsyth if(e == "") 2606*37da2899SCharles.Forsyth (signed_params, e) = sign_server_xkey(ctx.sel_sign, params, 2607*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 2608*37da2899SCharles.Forsyth if(e != "") 2609*37da2899SCharles.Forsyth 2610*37da2899SCharles.Forsyth n := len params + 2 + len signed_params; 2611*37da2899SCharles.Forsyth xkey = array [n] of byte; 2612*37da2899SCharles.Forsyth xkey[0:] = params; 2613*37da2899SCharles.Forsyth xkey[len params:] = int_encode(len signed_params, 2); 2614*37da2899SCharles.Forsyth xkey[len params+2:] = signed_params; 2615*37da2899SCharles.Forsyth handshake_enque(ref Handshake.ServerKeyExchange(xkey), ctx); 2616*37da2899SCharles.Forsyth } 2617*37da2899SCharles.Forsyth 2618*37da2899SCharles.Forsyth if(ctx.status & CLIENT_AUTH) { 2619*37da2899SCharles.Forsyth sndm = ref Handshake.CertificateRequest(ctx.local_info.types, ctx.local_info.dns); 2620*37da2899SCharles.Forsyth handshake_enque(sndm, ctx); 2621*37da2899SCharles.Forsyth 2622*37da2899SCharles.Forsyth ctx.status |= CERT_REQUEST; 2623*37da2899SCharles.Forsyth ctx.state = STATE_CLIENT_CERTIFICATE; 2624*37da2899SCharles.Forsyth } 2625*37da2899SCharles.Forsyth else 2626*37da2899SCharles.Forsyth ctx.state = STATE_CLIENT_KEY_EXCHANGE; 2627*37da2899SCharles.Forsyth 2628*37da2899SCharles.Forsyth handshake_enque(ref Handshake.ServerHelloDone(), ctx); 2629*37da2899SCharles.Forsyth} 2630*37da2899SCharles.Forsyth 2631*37da2899SCharles.Forsyth# [server side] 2632*37da2899SCharles.Forsyth# Process the received client key exchange message. 2633*37da2899SCharles.Forsyth 2634*37da2899SCharles.Forsythdo_client_keyex(hm: ref Handshake.ClientKeyExchange, ctx: ref Context) 2635*37da2899SCharles.Forsyth{ 2636*37da2899SCharles.Forsyth (premaster_secret, err) := install_client_xkey(hm.xkey, ctx.sel_keyx); 2637*37da2899SCharles.Forsyth if(err != "") { 2638*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, err, ctx); 2639*37da2899SCharles.Forsyth return; 2640*37da2899SCharles.Forsyth } 2641*37da2899SCharles.Forsyth 2642*37da2899SCharles.Forsyth ctx.session.master_secret = calc_master_secret(premaster_secret, 2643*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 2644*37da2899SCharles.Forsyth 2645*37da2899SCharles.Forsyth if(ctx.status & CERT_RECEIVED) 2646*37da2899SCharles.Forsyth ctx.state = STATE_CERTIFICATE_VERIFY; 2647*37da2899SCharles.Forsyth else 2648*37da2899SCharles.Forsyth ctx.state = STATE_CHANGE_CIPHER_SPEC; 2649*37da2899SCharles.Forsyth} 2650*37da2899SCharles.Forsyth 2651*37da2899SCharles.Forsyth# [server side] 2652*37da2899SCharles.Forsyth# Process the received certificate message from client. 2653*37da2899SCharles.Forsyth 2654*37da2899SCharles.Forsythdo_client_cert(hm: ref Handshake.Certificate, ctx: ref Context) 2655*37da2899SCharles.Forsyth{ 2656*37da2899SCharles.Forsyth ctx.session.peer_certs = hm.cert_list; 2657*37da2899SCharles.Forsyth 2658*37da2899SCharles.Forsyth # verify cert chain and determine the type of cert 2659*37da2899SCharles.Forsyth # ctx.peer_info.sk = x509->verify_chain(ctx.session.peer_certs); 2660*37da2899SCharles.Forsyth # if(ctx.peer_info.key == nil) { 2661*37da2899SCharles.Forsyth # fatal(SSL_HANDSHAKE_FAILURE, "client certificate: cert verify failed", ctx); 2662*37da2899SCharles.Forsyth # return; 2663*37da2899SCharles.Forsyth # } 2664*37da2899SCharles.Forsyth 2665*37da2899SCharles.Forsyth ctx.status |= CERT_RECEIVED; 2666*37da2899SCharles.Forsyth 2667*37da2899SCharles.Forsyth ctx.state = STATE_CLIENT_KEY_EXCHANGE; 2668*37da2899SCharles.Forsyth} 2669*37da2899SCharles.Forsyth 2670*37da2899SCharles.Forsyth# [server side] 2671*37da2899SCharles.Forsyth# Process the received certificate verify message from client. 2672*37da2899SCharles.Forsyth 2673*37da2899SCharles.Forsythdo_cert_verify(hm: ref Handshake.CertificateVerify, ctx: ref Context) 2674*37da2899SCharles.Forsyth{ 2675*37da2899SCharles.Forsyth if(ctx.status & CERT_RECEIVED) { 2676*37da2899SCharles.Forsyth # exp : array of byte; 2677*37da2899SCharles.Forsyth (md5_hash, sha_hash) 2678*37da2899SCharles.Forsyth := calc_finished(nil, ctx.session.master_secret, ctx.sha_state, ctx.md5_state); 2679*37da2899SCharles.Forsyth ok := 0; 2680*37da2899SCharles.Forsyth pick upk := ctx.sel_sign { 2681*37da2899SCharles.Forsyth RSA => 2682*37da2899SCharles.Forsyth hashes := array [36] of byte; 2683*37da2899SCharles.Forsyth hashes[0:] = md5_hash; 2684*37da2899SCharles.Forsyth hashes[16:] = sha_hash; 2685*37da2899SCharles.Forsyth ok = pkcs->rsa_verify(hashes, hm.signature, upk.peer_pk, PKCS->MD5_WithRSAEncryption); 2686*37da2899SCharles.Forsyth DSS => 2687*37da2899SCharles.Forsyth ok = pkcs->dss_verify(sha_hash, hm.signature, upk.peer_pk); 2688*37da2899SCharles.Forsyth } 2689*37da2899SCharles.Forsyth 2690*37da2899SCharles.Forsyth if(!ok) { 2691*37da2899SCharles.Forsyth fatal(SSL_HANDSHAKE_FAILURE, "do_cert_verify: client auth failed", ctx); 2692*37da2899SCharles.Forsyth return; 2693*37da2899SCharles.Forsyth } 2694*37da2899SCharles.Forsyth } 2695*37da2899SCharles.Forsyth else { 2696*37da2899SCharles.Forsyth alert_enque(ref Alert(SSL_WARNING, SSL_NO_CERTIFICATE), ctx); 2697*37da2899SCharles.Forsyth return; 2698*37da2899SCharles.Forsyth } 2699*37da2899SCharles.Forsyth 2700*37da2899SCharles.Forsyth ctx.state = STATE_CHANGE_CIPHER_SPEC; 2701*37da2899SCharles.Forsyth} 2702*37da2899SCharles.Forsyth 2703*37da2899SCharles.Forsyth# [client or server side] 2704*37da2899SCharles.Forsyth# Process the received finished message either from client or server. 2705*37da2899SCharles.Forsyth 2706*37da2899SCharles.Forsythdo_finished(sender: array of byte, ctx: ref Context) 2707*37da2899SCharles.Forsyth{ 2708*37da2899SCharles.Forsyth # setup write_cipher if not yet 2709*37da2899SCharles.Forsyth if(!(ctx.status & OUT_READY)) { 2710*37da2899SCharles.Forsyth ccs_enque(ref ChangeCipherSpec(1), ctx); 2711*37da2899SCharles.Forsyth e := set_out_queue(ctx); 2712*37da2899SCharles.Forsyth if(e != nil) { 2713*37da2899SCharles.Forsyth fatal(SSL_CLOSE_NOTIFY, "do_finished: setup new cipher failed", ctx); 2714*37da2899SCharles.Forsyth return; 2715*37da2899SCharles.Forsyth } 2716*37da2899SCharles.Forsyth ctx.status |= OUT_READY; 2717*37da2899SCharles.Forsyth 2718*37da2899SCharles.Forsyth if(SSL_DEBUG) 2719*37da2899SCharles.Forsyth log("ssl3: set out cipher done\n"); 2720*37da2899SCharles.Forsyth 2721*37da2899SCharles.Forsyth (md5_hash, sha_hash) := calc_finished(sender, ctx.session.master_secret, 2722*37da2899SCharles.Forsyth ctx.sha_state, ctx.md5_state); 2723*37da2899SCharles.Forsyth handshake_enque(ref Handshake.Finished(md5_hash, sha_hash), ctx); 2724*37da2899SCharles.Forsyth } 2725*37da2899SCharles.Forsyth 2726*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; # normal 2727*37da2899SCharles.Forsyth 2728*37da2899SCharles.Forsyth # clean read queue 2729*37da2899SCharles.Forsyth ctx.in_queue.fragment = 0; 2730*37da2899SCharles.Forsyth 2731*37da2899SCharles.Forsyth sslsession->add_session(ctx.session); 2732*37da2899SCharles.Forsyth 2733*37da2899SCharles.Forsyth if(SSL_DEBUG) 2734*37da2899SCharles.Forsyth log("ssl3: add session to session database done\n"); 2735*37da2899SCharles.Forsyth} 2736*37da2899SCharles.Forsyth 2737*37da2899SCharles.Forsythinstall_client_xkey(a: array of byte, keyx: ref KeyExAlg): (array of byte, string) 2738*37da2899SCharles.Forsyth{ 2739*37da2899SCharles.Forsyth pmaster, x : array of byte; 2740*37da2899SCharles.Forsyth err := ""; 2741*37da2899SCharles.Forsyth pick kx := keyx { 2742*37da2899SCharles.Forsyth DH => 2743*37da2899SCharles.Forsyth i := 0; 2744*37da2899SCharles.Forsyth (kx.peer_pk, i) = dh_params_decode(a); 2745*37da2899SCharles.Forsyth if(kx.peer_pk != nil) 2746*37da2899SCharles.Forsyth pmaster = pkcs->computeDHAgreedKey(kx.sk.param, kx.sk.sk, kx.peer_pk.pk); 2747*37da2899SCharles.Forsyth else 2748*37da2899SCharles.Forsyth err = "decode dh params failed"; 2749*37da2899SCharles.Forsyth RSA => 2750*37da2899SCharles.Forsyth (err, x) = pkcs->rsa_decrypt(a, kx.sk, 2); 2751*37da2899SCharles.Forsyth if(err != "" || len x != 48) { 2752*37da2899SCharles.Forsyth err = "impl error"; 2753*37da2899SCharles.Forsyth } 2754*37da2899SCharles.Forsyth else { 2755*37da2899SCharles.Forsyth if(x[0] != SSL_VERSION_3_0[0] && x[1] != SSL_VERSION_3_0[1]) 2756*37da2899SCharles.Forsyth err = "version wrong: possible version attack"; 2757*37da2899SCharles.Forsyth else 2758*37da2899SCharles.Forsyth pmaster = x[2:]; 2759*37da2899SCharles.Forsyth } 2760*37da2899SCharles.Forsyth FORTEZZA_KEA => 2761*37da2899SCharles.Forsyth err = "Fortezza unsupported"; 2762*37da2899SCharles.Forsyth } 2763*37da2899SCharles.Forsyth return (pmaster, err); 2764*37da2899SCharles.Forsyth} 2765*37da2899SCharles.Forsyth 2766*37da2899SCharles.Forsythinstall_server_xkey(a: array of byte, keyx: ref KeyExAlg): (string, int) 2767*37da2899SCharles.Forsyth{ 2768*37da2899SCharles.Forsyth err := ""; 2769*37da2899SCharles.Forsyth i := 0; 2770*37da2899SCharles.Forsyth 2771*37da2899SCharles.Forsyth pick kx := keyx { 2772*37da2899SCharles.Forsyth DH => 2773*37da2899SCharles.Forsyth (kx.peer_pk, i) = dh_params_decode(a); 2774*37da2899SCharles.Forsyth if(kx.peer_pk != nil) 2775*37da2899SCharles.Forsyth kx.peer_params = kx.peer_pk.param; 2776*37da2899SCharles.Forsyth RSA => 2777*37da2899SCharles.Forsyth peer_tmp: ref RSAParams; 2778*37da2899SCharles.Forsyth (peer_tmp, i, err) = rsa_params_decode(a); 2779*37da2899SCharles.Forsyth if(err == "") { 2780*37da2899SCharles.Forsyth modlen := len peer_tmp.modulus.iptobebytes(); 2781*37da2899SCharles.Forsyth kx.peer_pk = ref RSAKey(peer_tmp.modulus, modlen, peer_tmp.exponent); 2782*37da2899SCharles.Forsyth } 2783*37da2899SCharles.Forsyth FORTEZZA_KEA => 2784*37da2899SCharles.Forsyth return ("Fortezza unsupported", i); 2785*37da2899SCharles.Forsyth } 2786*37da2899SCharles.Forsyth 2787*37da2899SCharles.Forsyth return (err, i); 2788*37da2899SCharles.Forsyth} 2789*37da2899SCharles.Forsyth 2790*37da2899SCharles.Forsythverify_server_xkey(crand, srand: array of byte, a: array of byte, i : int, sign: ref SigAlg) 2791*37da2899SCharles.Forsyth : string 2792*37da2899SCharles.Forsyth{ 2793*37da2899SCharles.Forsyth pick sg := sign { 2794*37da2899SCharles.Forsyth anon => 2795*37da2899SCharles.Forsyth RSA => 2796*37da2899SCharles.Forsyth lb := a[0:i]::crand::srand::nil; 2797*37da2899SCharles.Forsyth (exp, nil, nil) := md5_sha_hash(lb, nil, nil); 2798*37da2899SCharles.Forsyth ok := pkcs->rsa_verify(exp, a[i+2:], sg.peer_pk, PKCS->MD5_WithRSAEncryption); 2799*37da2899SCharles.Forsyth if(!ok) 2800*37da2899SCharles.Forsyth return "RSA sigature verification failed"; 2801*37da2899SCharles.Forsyth DSS => 2802*37da2899SCharles.Forsyth lb := a[0:i]::crand::srand::nil; 2803*37da2899SCharles.Forsyth (exp, nil) := sha_hash(lb, nil); 2804*37da2899SCharles.Forsyth ok := pkcs->dss_verify(exp, a[i+2:], sg.peer_pk); 2805*37da2899SCharles.Forsyth if(!ok) 2806*37da2899SCharles.Forsyth return "DSS sigature verification failed"; 2807*37da2899SCharles.Forsyth } 2808*37da2899SCharles.Forsyth 2809*37da2899SCharles.Forsyth return ""; 2810*37da2899SCharles.Forsyth} 2811*37da2899SCharles.Forsyth 2812*37da2899SCharles.Forsythcalc_client_xkey(keyx: ref KeyExAlg): (array of byte, array of byte, string) 2813*37da2899SCharles.Forsyth{ 2814*37da2899SCharles.Forsyth pm, x : array of byte; 2815*37da2899SCharles.Forsyth err := ""; 2816*37da2899SCharles.Forsyth pick kx := keyx { 2817*37da2899SCharles.Forsyth DH => 2818*37da2899SCharles.Forsyth # generate our own DH keys based on DH params of peer side 2819*37da2899SCharles.Forsyth (kx.sk, kx.exch_pk) = pkcs->setupDHAgreement(kx.peer_params); 2820*37da2899SCharles.Forsyth # TODO: need check type of client cert if(!ctx.status & CLIENT_AUTH) 2821*37da2899SCharles.Forsyth # for implicit case 2822*37da2899SCharles.Forsyth (x, err) = dh_exchpub_encode(kx.exch_pk); 2823*37da2899SCharles.Forsyth pm = pkcs->computeDHAgreedKey(kx.sk.param, kx.sk.sk, kx.peer_pk.pk); 2824*37da2899SCharles.Forsyth RSA => 2825*37da2899SCharles.Forsyth pm = array [48] of byte; 2826*37da2899SCharles.Forsyth pm[0:] = SSL_VERSION_3_0; # against version attack 2827*37da2899SCharles.Forsyth pm[2:] = random->randombuf(Random->NotQuiteRandom, 46); 2828*37da2899SCharles.Forsyth (err, x) = pkcs->rsa_encrypt(pm, kx.peer_pk, 2); 2829*37da2899SCharles.Forsyth FORTEZZA_KEA => 2830*37da2899SCharles.Forsyth err = "Fortezza unsupported"; 2831*37da2899SCharles.Forsyth } 2832*37da2899SCharles.Forsyth if(SSL_DEBUG) 2833*37da2899SCharles.Forsyth log("ssl3: calc_client_xkey: " + bastr(x)); 2834*37da2899SCharles.Forsyth return (x, pm, err); 2835*37da2899SCharles.Forsyth} 2836*37da2899SCharles.Forsyth 2837*37da2899SCharles.Forsythcalc_server_xkey(keyx: ref KeyExAlg): (array of byte, string) 2838*37da2899SCharles.Forsyth{ 2839*37da2899SCharles.Forsyth params: array of byte; 2840*37da2899SCharles.Forsyth err: string; 2841*37da2899SCharles.Forsyth pick kx := keyx { 2842*37da2899SCharles.Forsyth DH => 2843*37da2899SCharles.Forsyth (kx.sk, kx.exch_pk) = pkcs->setupDHAgreement(kx.params); 2844*37da2899SCharles.Forsyth (params, err) = dh_params_encode(kx.exch_pk); 2845*37da2899SCharles.Forsyth RSA => 2846*37da2899SCharles.Forsyth tmp := ref RSAParams(kx.export_key.modulus, kx.export_key.exponent); 2847*37da2899SCharles.Forsyth (params, err) = rsa_params_encode(tmp); 2848*37da2899SCharles.Forsyth 2849*37da2899SCharles.Forsyth FORTEZZA_KEA => 2850*37da2899SCharles.Forsyth err = "Fortezza unsupported"; 2851*37da2899SCharles.Forsyth } 2852*37da2899SCharles.Forsyth return (params, err); 2853*37da2899SCharles.Forsyth} 2854*37da2899SCharles.Forsyth 2855*37da2899SCharles.Forsythsign_server_xkey(sign: ref SigAlg, params, cr, sr: array of byte): (array of byte, string) 2856*37da2899SCharles.Forsyth{ 2857*37da2899SCharles.Forsyth signed_params: array of byte; 2858*37da2899SCharles.Forsyth err: string; 2859*37da2899SCharles.Forsyth pick sg := sign { 2860*37da2899SCharles.Forsyth anon => 2861*37da2899SCharles.Forsyth RSA => 2862*37da2899SCharles.Forsyth lb := cr::sr::params::nil; 2863*37da2899SCharles.Forsyth (hashes, nil, nil) := md5_sha_hash(lb, nil, nil); 2864*37da2899SCharles.Forsyth (err, signed_params) = pkcs->rsa_sign(hashes, sg.sk, PKCS->MD5_WithRSAEncryption); 2865*37da2899SCharles.Forsyth DSS => 2866*37da2899SCharles.Forsyth lb := cr::sr::params::nil; 2867*37da2899SCharles.Forsyth (hashes, nil) := sha_hash(lb, nil); 2868*37da2899SCharles.Forsyth (err, signed_params) = pkcs->dss_sign(hashes, sg.sk); 2869*37da2899SCharles.Forsyth } 2870*37da2899SCharles.Forsyth return (signed_params, err); 2871*37da2899SCharles.Forsyth} 2872*37da2899SCharles.Forsyth 2873*37da2899SCharles.Forsyth# ssl encoding of DH exchange public key 2874*37da2899SCharles.Forsyth 2875*37da2899SCharles.Forsythdh_exchpub_encode(dh: ref DHPublicKey): (array of byte, string) 2876*37da2899SCharles.Forsyth{ 2877*37da2899SCharles.Forsyth if(dh != nil) { 2878*37da2899SCharles.Forsyth yb := dh.pk.iptobebytes(); 2879*37da2899SCharles.Forsyth if(yb != nil) { 2880*37da2899SCharles.Forsyth n := 2 + len yb; 2881*37da2899SCharles.Forsyth a := array [n] of byte; 2882*37da2899SCharles.Forsyth i := 0; 2883*37da2899SCharles.Forsyth a[i:] = int_encode(len yb, 2); 2884*37da2899SCharles.Forsyth i += 2; 2885*37da2899SCharles.Forsyth a[i:] = yb; 2886*37da2899SCharles.Forsyth return (a, nil); 2887*37da2899SCharles.Forsyth } 2888*37da2899SCharles.Forsyth } 2889*37da2899SCharles.Forsyth return (nil, "nil dh params"); 2890*37da2899SCharles.Forsyth} 2891*37da2899SCharles.Forsyth 2892*37da2899SCharles.Forsythdh_params_encode(dh: ref DHPublicKey): (array of byte, string) 2893*37da2899SCharles.Forsyth{ 2894*37da2899SCharles.Forsyth if(dh != nil && dh.param != nil) { 2895*37da2899SCharles.Forsyth pb := dh.param.prime.iptobebytes(); 2896*37da2899SCharles.Forsyth gb := dh.param.base.iptobebytes(); 2897*37da2899SCharles.Forsyth yb := dh.pk.iptobebytes(); 2898*37da2899SCharles.Forsyth if(pb != nil && gb != nil && yb != nil) { 2899*37da2899SCharles.Forsyth n := 6 + len pb + len gb + len yb; 2900*37da2899SCharles.Forsyth a := array [n] of byte; 2901*37da2899SCharles.Forsyth i := 0; 2902*37da2899SCharles.Forsyth a[i:] = int_encode(len pb, 2); 2903*37da2899SCharles.Forsyth i += 2; 2904*37da2899SCharles.Forsyth a[i:] = pb; 2905*37da2899SCharles.Forsyth i += len pb; 2906*37da2899SCharles.Forsyth a[i:] = int_encode(len gb, 2); 2907*37da2899SCharles.Forsyth i += 2; 2908*37da2899SCharles.Forsyth a[i:] = gb; 2909*37da2899SCharles.Forsyth i += len gb; 2910*37da2899SCharles.Forsyth a[i:] = int_encode(len yb, 2); 2911*37da2899SCharles.Forsyth i += 2; 2912*37da2899SCharles.Forsyth a[i:] = yb; 2913*37da2899SCharles.Forsyth i += len yb; 2914*37da2899SCharles.Forsyth return (a, nil); 2915*37da2899SCharles.Forsyth } 2916*37da2899SCharles.Forsyth } 2917*37da2899SCharles.Forsyth return (nil, "nil dh public key"); 2918*37da2899SCharles.Forsyth} 2919*37da2899SCharles.Forsyth 2920*37da2899SCharles.Forsythdh_params_decode(a: array of byte): (ref DHPublicKey, int) 2921*37da2899SCharles.Forsyth{ 2922*37da2899SCharles.Forsyth i := 0; 2923*37da2899SCharles.Forsyth for(;;) { 2924*37da2899SCharles.Forsyth n := int_decode(a[i:i+2]); 2925*37da2899SCharles.Forsyth i += 2; 2926*37da2899SCharles.Forsyth if(i+n > len a) 2927*37da2899SCharles.Forsyth break; 2928*37da2899SCharles.Forsyth p := a[i:i+n]; 2929*37da2899SCharles.Forsyth i += n; 2930*37da2899SCharles.Forsyth n = int_decode(a[i:i+2]); 2931*37da2899SCharles.Forsyth i += 2; 2932*37da2899SCharles.Forsyth if(i+n > len a) 2933*37da2899SCharles.Forsyth break; 2934*37da2899SCharles.Forsyth g := a[i:i+n]; 2935*37da2899SCharles.Forsyth i += n; 2936*37da2899SCharles.Forsyth n = int_decode(a[i:i+2]); 2937*37da2899SCharles.Forsyth i += 2; 2938*37da2899SCharles.Forsyth if(i+n > len a) 2939*37da2899SCharles.Forsyth break; 2940*37da2899SCharles.Forsyth Ys := a[i:i+n]; 2941*37da2899SCharles.Forsyth i += n; 2942*37da2899SCharles.Forsyth 2943*37da2899SCharles.Forsyth if(SSL_DEBUG) 2944*37da2899SCharles.Forsyth log("ssl3: dh_params_decode:" + "\n\tp =\n\t\t" + bastr(p) 2945*37da2899SCharles.Forsyth + "\n\tg =\n\t\t" + bastr(g) + "\n\tYs =\n\t\t" + bastr(Ys) + "\n"); 2946*37da2899SCharles.Forsyth 2947*37da2899SCharles.Forsyth # don't care privateValueLength 2948*37da2899SCharles.Forsyth param := ref DHParams(IPint.bebytestoip(p), IPint.bebytestoip(g), 0); 2949*37da2899SCharles.Forsyth return (ref DHPublicKey(param, IPint.bebytestoip(Ys)), i); 2950*37da2899SCharles.Forsyth } 2951*37da2899SCharles.Forsyth return (nil, i); 2952*37da2899SCharles.Forsyth} 2953*37da2899SCharles.Forsyth 2954*37da2899SCharles.Forsythrsa_params_encode(rsa_params: ref RSAParams): (array of byte, string) 2955*37da2899SCharles.Forsyth{ 2956*37da2899SCharles.Forsyth if(rsa_params != nil) { 2957*37da2899SCharles.Forsyth mod := rsa_params.modulus.iptobebytes(); 2958*37da2899SCharles.Forsyth exp := rsa_params.exponent.iptobebytes(); 2959*37da2899SCharles.Forsyth if(mod != nil || exp != nil) { 2960*37da2899SCharles.Forsyth n := 4 + len mod + len exp; 2961*37da2899SCharles.Forsyth a := array [n] of byte; 2962*37da2899SCharles.Forsyth i := 0; 2963*37da2899SCharles.Forsyth a[i:] = int_encode(len mod, 2); 2964*37da2899SCharles.Forsyth i += 2; 2965*37da2899SCharles.Forsyth a[i:] = mod; 2966*37da2899SCharles.Forsyth i += len mod; 2967*37da2899SCharles.Forsyth a[i:] = int_encode(len exp, 2); 2968*37da2899SCharles.Forsyth i += 2; 2969*37da2899SCharles.Forsyth a[i:] = exp; 2970*37da2899SCharles.Forsyth i += len exp; 2971*37da2899SCharles.Forsyth return (a, nil); 2972*37da2899SCharles.Forsyth } 2973*37da2899SCharles.Forsyth } 2974*37da2899SCharles.Forsyth return (nil, "nil rsa params"); 2975*37da2899SCharles.Forsyth} 2976*37da2899SCharles.Forsyth 2977*37da2899SCharles.Forsythrsa_params_decode(a: array of byte): (ref RSAParams, int, string) 2978*37da2899SCharles.Forsyth{ 2979*37da2899SCharles.Forsyth i := 0; 2980*37da2899SCharles.Forsyth for(;;) { 2981*37da2899SCharles.Forsyth if(len a < 2) 2982*37da2899SCharles.Forsyth break; 2983*37da2899SCharles.Forsyth n := int_decode(a[i:i+2]); 2984*37da2899SCharles.Forsyth i += 2; 2985*37da2899SCharles.Forsyth if(n < 0 || n + i > len a) 2986*37da2899SCharles.Forsyth break; 2987*37da2899SCharles.Forsyth mod := a[i:i+n]; 2988*37da2899SCharles.Forsyth i += n; 2989*37da2899SCharles.Forsyth n = int_decode(a[i:i+2]); 2990*37da2899SCharles.Forsyth i += 2; 2991*37da2899SCharles.Forsyth if(n < 0 || n + i > len a) 2992*37da2899SCharles.Forsyth break; 2993*37da2899SCharles.Forsyth exp := a[i:i+n]; 2994*37da2899SCharles.Forsyth i += n; 2995*37da2899SCharles.Forsyth m := i; 2996*37da2899SCharles.Forsyth modulus := IPint.bebytestoip(mod); 2997*37da2899SCharles.Forsyth exponent := IPint.bebytestoip(exp); 2998*37da2899SCharles.Forsyth 2999*37da2899SCharles.Forsyth if(SSL_DEBUG) 3000*37da2899SCharles.Forsyth log("ssl3: decode RSA params\n\tmodulus = \n\t\t" + bastr(mod) 3001*37da2899SCharles.Forsyth + "\n\texponent = \n\t\t" + bastr(exp) + "\n"); 3002*37da2899SCharles.Forsyth 3003*37da2899SCharles.Forsyth if(len a < i+2) 3004*37da2899SCharles.Forsyth break; 3005*37da2899SCharles.Forsyth n = int_decode(a[i:i+2]); 3006*37da2899SCharles.Forsyth i += 2; 3007*37da2899SCharles.Forsyth if(len a != i + n) 3008*37da2899SCharles.Forsyth break; 3009*37da2899SCharles.Forsyth return (ref RSAParams(modulus, exponent), m, nil); 3010*37da2899SCharles.Forsyth } 3011*37da2899SCharles.Forsyth return (nil, i, "encoding error"); 3012*37da2899SCharles.Forsyth} 3013*37da2899SCharles.Forsyth 3014*37da2899SCharles.Forsyth# md5_hash MD5(master_secret + pad2 + 3015*37da2899SCharles.Forsyth# MD5(handshake_messages + Sender + 3016*37da2899SCharles.Forsyth# master_secret + pad1)); 3017*37da2899SCharles.Forsyth# sha_hash SHA(master_secret + pad2 + 3018*37da2899SCharles.Forsyth# SHA(handshake_messages + Sender + 3019*37da2899SCharles.Forsyth# master_secret + pad1)); 3020*37da2899SCharles.Forsyth# 3021*37da2899SCharles.Forsyth# handshake_messages All of the data from all handshake messages 3022*37da2899SCharles.Forsyth# up to but not including this message. This 3023*37da2899SCharles.Forsyth# is only data visible at the handshake layer 3024*37da2899SCharles.Forsyth# and does not include record layer headers. 3025*37da2899SCharles.Forsyth# 3026*37da2899SCharles.Forsyth# sender [4], master_secret [48] 3027*37da2899SCharles.Forsyth# pad1 and pad2, 48 bytes for md5, 40 bytes for sha 3028*37da2899SCharles.Forsyth 3029*37da2899SCharles.Forsythcalc_finished(sender, master_secret: array of byte, sha_state, md5_state: ref DigestState) 3030*37da2899SCharles.Forsyth : (array of byte, array of byte) 3031*37da2899SCharles.Forsyth{ 3032*37da2899SCharles.Forsyth sha_value := array [Keyring->SHA1dlen] of byte; 3033*37da2899SCharles.Forsyth md5_value := array [Keyring->MD5dlen] of byte; 3034*37da2899SCharles.Forsyth sha_inner := array [Keyring->SHA1dlen] of byte; 3035*37da2899SCharles.Forsyth md5_inner := array [Keyring->MD5dlen] of byte; 3036*37da2899SCharles.Forsyth 3037*37da2899SCharles.Forsyth lb := master_secret::SSL_MAC_PAD1[0:48]::nil; 3038*37da2899SCharles.Forsyth if(sender != nil) 3039*37da2899SCharles.Forsyth lb = sender::lb; 3040*37da2899SCharles.Forsyth (md5_inner, nil) = md5_hash(lb, md5_state); 3041*37da2899SCharles.Forsyth 3042*37da2899SCharles.Forsyth lb = master_secret::SSL_MAC_PAD1[0:40]::nil; 3043*37da2899SCharles.Forsyth if(sender != nil) 3044*37da2899SCharles.Forsyth lb = sender::lb; 3045*37da2899SCharles.Forsyth (sha_inner, nil) = sha_hash(lb, sha_state); 3046*37da2899SCharles.Forsyth 3047*37da2899SCharles.Forsyth (md5_value, nil) = md5_hash(master_secret::SSL_MAC_PAD2[0:48]::md5_inner::nil, nil); 3048*37da2899SCharles.Forsyth (sha_value, nil) = sha_hash(master_secret::SSL_MAC_PAD2[0:40]::sha_inner::nil, nil); 3049*37da2899SCharles.Forsyth 3050*37da2899SCharles.Forsyth # if(SSL_DEBUG) 3051*37da2899SCharles.Forsyth # log("ssl3: calc_finished:" 3052*37da2899SCharles.Forsyth # + "\n\tmd5_inner = \n\t\t" + bastr(md5_inner) 3053*37da2899SCharles.Forsyth # + "\n\tsha_inner = \n\t\t" + bastr(sha_inner) 3054*37da2899SCharles.Forsyth # + "\n\tmd5_value = \n\t\t" + bastr(md5_value) 3055*37da2899SCharles.Forsyth # + "\n\tsha_value = \n\t\t" + bastr(sha_value) 3056*37da2899SCharles.Forsyth # + "\n"); 3057*37da2899SCharles.Forsyth 3058*37da2899SCharles.Forsyth return (md5_value, sha_value); 3059*37da2899SCharles.Forsyth} 3060*37da2899SCharles.Forsyth 3061*37da2899SCharles.Forsyth 3062*37da2899SCharles.Forsyth# master_secret = 3063*37da2899SCharles.Forsyth# MD5(premaster_secret + SHA('A' + premaster_secret + 3064*37da2899SCharles.Forsyth# ClientHello.random + ServerHello.random)) + 3065*37da2899SCharles.Forsyth# MD5(premaster_secret + SHA('BB' + premaster_secret + 3066*37da2899SCharles.Forsyth# ClientHello.random + ServerHello.random)) + 3067*37da2899SCharles.Forsyth# MD5(premaster_secret + SHA('CCC' + premaster_secret + 3068*37da2899SCharles.Forsyth# ClientHello.random + ServerHello.random)); 3069*37da2899SCharles.Forsyth 3070*37da2899SCharles.Forsythcalc_master_secret(pm, cr, sr: array of byte): array of byte 3071*37da2899SCharles.Forsyth{ 3072*37da2899SCharles.Forsyth ms := array [48] of byte; 3073*37da2899SCharles.Forsyth sha_value := array [Keyring->SHA1dlen] of byte; 3074*37da2899SCharles.Forsyth leader := array [3] of byte; 3075*37da2899SCharles.Forsyth 3076*37da2899SCharles.Forsyth j := 0; 3077*37da2899SCharles.Forsyth lb := pm::cr::sr::nil; 3078*37da2899SCharles.Forsyth for(i := 1; i <= 3; i++) { 3079*37da2899SCharles.Forsyth leader[0] = leader[1] = leader[2] = byte (16r40 + i); 3080*37da2899SCharles.Forsyth (sha_value, nil) = sha_hash(leader[0:i]::lb, nil); 3081*37da2899SCharles.Forsyth (ms[j:], nil) = md5_hash(pm::sha_value::nil, nil); 3082*37da2899SCharles.Forsyth j += 16; # Keyring->MD5dlen 3083*37da2899SCharles.Forsyth } 3084*37da2899SCharles.Forsyth 3085*37da2899SCharles.Forsyth if(SSL_DEBUG) 3086*37da2899SCharles.Forsyth log("ssl3: calc_master_secret:\n\tmaster_secret = \n\t\t" + bastr(ms) + "\n"); 3087*37da2899SCharles.Forsyth 3088*37da2899SCharles.Forsyth return ms; 3089*37da2899SCharles.Forsyth} 3090*37da2899SCharles.Forsyth 3091*37da2899SCharles.Forsyth 3092*37da2899SCharles.Forsyth# key_block = 3093*37da2899SCharles.Forsyth# MD5(master_secret + SHA(`A' + master_secret + 3094*37da2899SCharles.Forsyth# ServerHello.random + ClientHello.random)) + 3095*37da2899SCharles.Forsyth# MD5(master_secret + SHA(`BB' + master_secret + 3096*37da2899SCharles.Forsyth# ServerHello.random + ClientHello.random)) + 3097*37da2899SCharles.Forsyth# MD5(master_secret + SHA(`CCC' + master_secret + 3098*37da2899SCharles.Forsyth# ServerHello.random + ClientHello.random)) + 3099*37da2899SCharles.Forsyth# [...]; 3100*37da2899SCharles.Forsyth 3101*37da2899SCharles.Forsythcalc_key_material(n: int, ms, cr, sr: array of byte): array of byte 3102*37da2899SCharles.Forsyth{ 3103*37da2899SCharles.Forsyth key_block := array [n] of byte; 3104*37da2899SCharles.Forsyth sha_value := array [Keyring->SHA1dlen] of byte; # [20] 3105*37da2899SCharles.Forsyth md5_value := array [Keyring->MD5dlen] of byte; # [16] 3106*37da2899SCharles.Forsyth leader := array [10] of byte; 3107*37da2899SCharles.Forsyth 3108*37da2899SCharles.Forsyth if(n > 16*(len leader)) { 3109*37da2899SCharles.Forsyth if(SSL_DEBUG) 3110*37da2899SCharles.Forsyth log(sys->sprint("ssl3: calc key block: key size too long [%d]", n)); 3111*37da2899SCharles.Forsyth return nil; 3112*37da2899SCharles.Forsyth } 3113*37da2899SCharles.Forsyth 3114*37da2899SCharles.Forsyth m := n; 3115*37da2899SCharles.Forsyth i, j, consumed, next : int = 0; 3116*37da2899SCharles.Forsyth lb := ms::sr::cr::nil; 3117*37da2899SCharles.Forsyth for(i = 0; m > 0; i++) { 3118*37da2899SCharles.Forsyth for(j = 0; j <= i; j++) 3119*37da2899SCharles.Forsyth leader[j] = byte (16r41 + i); # 'A', 'BB', 'CCC', etc. 3120*37da2899SCharles.Forsyth 3121*37da2899SCharles.Forsyth (sha_value, nil) = sha_hash(leader[0:i+1]::lb, nil); 3122*37da2899SCharles.Forsyth (md5_value, nil) = md5_hash(ms::sha_value::nil, nil); 3123*37da2899SCharles.Forsyth 3124*37da2899SCharles.Forsyth consumed = Keyring->MD5dlen; 3125*37da2899SCharles.Forsyth if(m < Keyring->MD5dlen) 3126*37da2899SCharles.Forsyth consumed = m; 3127*37da2899SCharles.Forsyth m -= consumed; 3128*37da2899SCharles.Forsyth 3129*37da2899SCharles.Forsyth key_block[next:] = md5_value[0:consumed]; 3130*37da2899SCharles.Forsyth next += consumed; 3131*37da2899SCharles.Forsyth } 3132*37da2899SCharles.Forsyth 3133*37da2899SCharles.Forsyth if(SSL_DEBUG) 3134*37da2899SCharles.Forsyth log("ssl3: calc_key_material:" + "\n\tkey_block = \n\t\t" + bastr(key_block) + "\n"); 3135*37da2899SCharles.Forsyth 3136*37da2899SCharles.Forsyth return key_block; 3137*37da2899SCharles.Forsyth} 3138*37da2899SCharles.Forsyth 3139*37da2899SCharles.Forsyth# Then the key_block is partitioned as follows. 3140*37da2899SCharles.Forsyth# 3141*37da2899SCharles.Forsyth# client_write_MAC_secret[CipherSpec.hash_size] 3142*37da2899SCharles.Forsyth# server_write_MAC_secret[CipherSpec.hash_size] 3143*37da2899SCharles.Forsyth# client_write_key[CipherSpec.key_material] 3144*37da2899SCharles.Forsyth# server_write_key[CipherSpec.key_material] 3145*37da2899SCharles.Forsyth# client_write_IV[CipherSpec.IV_size] /* non-export ciphers */ 3146*37da2899SCharles.Forsyth# server_write_IV[CipherSpec.IV_size] /* non-export ciphers */ 3147*37da2899SCharles.Forsyth# 3148*37da2899SCharles.Forsyth# Any extra key_block material is discarded. 3149*37da2899SCharles.Forsyth# 3150*37da2899SCharles.Forsyth# Exportable encryption algorithms (for which 3151*37da2899SCharles.Forsyth# CipherSpec.is_exportable is true) require additional processing as 3152*37da2899SCharles.Forsyth# follows to derive their final write keys: 3153*37da2899SCharles.Forsyth# 3154*37da2899SCharles.Forsyth# final_client_write_key = MD5(client_write_key + 3155*37da2899SCharles.Forsyth# ClientHello.random + 3156*37da2899SCharles.Forsyth# ServerHello.random); 3157*37da2899SCharles.Forsyth# final_server_write_key = MD5(server_write_key + 3158*37da2899SCharles.Forsyth# ServerHello.random + 3159*37da2899SCharles.Forsyth# ClientHello.random); 3160*37da2899SCharles.Forsyth# 3161*37da2899SCharles.Forsyth# Exportable encryption algorithms derive their IVs from the random 3162*37da2899SCharles.Forsyth# messages: 3163*37da2899SCharles.Forsyth# 3164*37da2899SCharles.Forsyth# client_write_IV = MD5(ClientHello.random + ServerHello.random); 3165*37da2899SCharles.Forsyth# server_write_IV = MD5(ServerHello.random + ClientHello.random); 3166*37da2899SCharles.Forsyth 3167*37da2899SCharles.Forsythcalc_keys(ciph: ref CipherSpec, ms, cr, sr: array of byte) 3168*37da2899SCharles.Forsyth : (array of byte, array of byte, array of byte, array of byte, array of byte, array of byte) 3169*37da2899SCharles.Forsyth{ 3170*37da2899SCharles.Forsyth cw_mac, sw_mac, cw_key, sw_key, cw_IV, sw_IV: array of byte; 3171*37da2899SCharles.Forsyth 3172*37da2899SCharles.Forsyth n := ciph.key_material + ciph.hash_size; 3173*37da2899SCharles.Forsyth if(ciph.is_exportable == SSL_EXPORT_FALSE) 3174*37da2899SCharles.Forsyth n += ciph.IV_size; 3175*37da2899SCharles.Forsyth n *= 2; 3176*37da2899SCharles.Forsyth 3177*37da2899SCharles.Forsyth key_block := calc_key_material(n, ms, cr, sr); 3178*37da2899SCharles.Forsyth 3179*37da2899SCharles.Forsyth i := 0; 3180*37da2899SCharles.Forsyth if(ciph.hash_size != 0) { 3181*37da2899SCharles.Forsyth cw_mac = key_block[i:i+ciph.hash_size]; 3182*37da2899SCharles.Forsyth i += ciph.hash_size; 3183*37da2899SCharles.Forsyth sw_mac = key_block[i:i+ciph.hash_size]; 3184*37da2899SCharles.Forsyth i += ciph.hash_size; 3185*37da2899SCharles.Forsyth } 3186*37da2899SCharles.Forsyth 3187*37da2899SCharles.Forsyth if(ciph.is_exportable == SSL_EXPORT_FALSE) { 3188*37da2899SCharles.Forsyth if(ciph.key_material != 0) { 3189*37da2899SCharles.Forsyth cw_key = key_block[i:i+ciph.key_material]; 3190*37da2899SCharles.Forsyth i += ciph.key_material; 3191*37da2899SCharles.Forsyth sw_key = key_block[i:i+ciph.key_material]; 3192*37da2899SCharles.Forsyth i += ciph.key_material; 3193*37da2899SCharles.Forsyth } 3194*37da2899SCharles.Forsyth if(ciph.IV_size != 0) { 3195*37da2899SCharles.Forsyth cw_IV = key_block[i:i+ciph.IV_size]; 3196*37da2899SCharles.Forsyth i += ciph.IV_size; 3197*37da2899SCharles.Forsyth sw_IV = key_block[i:i+ciph.IV_size]; 3198*37da2899SCharles.Forsyth i += ciph.IV_size; 3199*37da2899SCharles.Forsyth } 3200*37da2899SCharles.Forsyth } 3201*37da2899SCharles.Forsyth else { 3202*37da2899SCharles.Forsyth if(ciph.key_material != 0) { 3203*37da2899SCharles.Forsyth cw_key = key_block[i:i+ciph.key_material]; 3204*37da2899SCharles.Forsyth i += ciph.key_material; 3205*37da2899SCharles.Forsyth sw_key = key_block[i:i+ciph.key_material]; 3206*37da2899SCharles.Forsyth i += ciph.key_material; 3207*37da2899SCharles.Forsyth (cw_key, nil) = md5_hash(cw_key::cr::sr::nil, nil); 3208*37da2899SCharles.Forsyth (sw_key, nil) = md5_hash(sw_key::sr::cr::nil, nil); 3209*37da2899SCharles.Forsyth } 3210*37da2899SCharles.Forsyth if(ciph.IV_size != 0) { 3211*37da2899SCharles.Forsyth (cw_IV, nil) = md5_hash(cr::sr::nil, nil); 3212*37da2899SCharles.Forsyth (sw_IV, nil) = md5_hash(sr::cr::nil, nil); 3213*37da2899SCharles.Forsyth } 3214*37da2899SCharles.Forsyth } 3215*37da2899SCharles.Forsyth 3216*37da2899SCharles.Forsyth if(SSL_DEBUG) 3217*37da2899SCharles.Forsyth log("ssl3: calc_keys:" 3218*37da2899SCharles.Forsyth + "\n\tclient_write_mac = \n\t\t" + bastr(cw_mac) 3219*37da2899SCharles.Forsyth + "\n\tserver_write_mac = \n\t\t" + bastr(sw_mac) 3220*37da2899SCharles.Forsyth + "\n\tclient_write_key = \n\t\t" + bastr(cw_key) 3221*37da2899SCharles.Forsyth + "\n\tserver_write_key = \n\t\t" + bastr(sw_key) 3222*37da2899SCharles.Forsyth + "\n\tclient_write_IV = \n\t\t" + bastr(cw_IV) 3223*37da2899SCharles.Forsyth + "\n\tserver_write_IV = \n\t\t" + bastr(sw_IV) + "\n"); 3224*37da2899SCharles.Forsyth 3225*37da2899SCharles.Forsyth return (cw_mac, sw_mac, cw_key, sw_key, cw_IV, sw_IV); 3226*37da2899SCharles.Forsyth} 3227*37da2899SCharles.Forsyth 3228*37da2899SCharles.Forsyth# 3229*37da2899SCharles.Forsyth# decode protocol message 3230*37da2899SCharles.Forsyth# 3231*37da2899SCharles.ForsythProtocol.decode(r: ref Record, ctx: ref Context): (ref Protocol, string) 3232*37da2899SCharles.Forsyth{ 3233*37da2899SCharles.Forsyth p : ref Protocol; 3234*37da2899SCharles.Forsyth 3235*37da2899SCharles.Forsyth case r.content_type { 3236*37da2899SCharles.Forsyth SSL_ALERT => 3237*37da2899SCharles.Forsyth if(len r.data != 2) 3238*37da2899SCharles.Forsyth return (nil, "alert decode failed"); 3239*37da2899SCharles.Forsyth 3240*37da2899SCharles.Forsyth p = ref Protocol.pAlert(ref Alert(int r.data[0], int r.data[1])); 3241*37da2899SCharles.Forsyth 3242*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC => 3243*37da2899SCharles.Forsyth if(len r.data != 1 || r.data[0] != byte 1) 3244*37da2899SCharles.Forsyth return (nil, "ChangeCipherSpec decode failed"); 3245*37da2899SCharles.Forsyth 3246*37da2899SCharles.Forsyth p = ref Protocol.pChangeCipherSpec(ref ChangeCipherSpec(1)); 3247*37da2899SCharles.Forsyth 3248*37da2899SCharles.Forsyth SSL_HANDSHAKE => 3249*37da2899SCharles.Forsyth (hm, e) := Handshake.decode(r.data); 3250*37da2899SCharles.Forsyth if(e != nil) 3251*37da2899SCharles.Forsyth return (nil, e); 3252*37da2899SCharles.Forsyth 3253*37da2899SCharles.Forsyth pick h := hm { 3254*37da2899SCharles.Forsyth Finished => 3255*37da2899SCharles.Forsyth exp_sender := SSL_CLIENT_SENDER; 3256*37da2899SCharles.Forsyth if(ctx.status & CLIENT_SIDE) 3257*37da2899SCharles.Forsyth exp_sender = SSL_SERVER_SENDER; 3258*37da2899SCharles.Forsyth 3259*37da2899SCharles.Forsyth (md5_hash, sha_hash) := calc_finished(exp_sender, 3260*37da2899SCharles.Forsyth ctx.session.master_secret, ctx.sha_state, ctx.md5_state); 3261*37da2899SCharles.Forsyth 3262*37da2899SCharles.Forsyth if(SSL_DEBUG) 3263*37da2899SCharles.Forsyth log("ssl3: handshake_decode: finished" 3264*37da2899SCharles.Forsyth + "\n\texpected_md5_hash = \n\t\t" + bastr(md5_hash) 3265*37da2899SCharles.Forsyth + "\n\tgot_md5_hash = \n\t\t" + bastr(h.md5_hash) 3266*37da2899SCharles.Forsyth + "\n\texpected_sha_hash = \n\t\t" + bastr(sha_hash) 3267*37da2899SCharles.Forsyth + "\n\tgot_sha_hash = \n\t\t" + bastr(h.sha_hash) + "\n"); 3268*37da2899SCharles.Forsyth 3269*37da2899SCharles.Forsyth #if(string md5_hash != string h.md5_hash || string sha_hash != string h.sha_hash) 3270*37da2899SCharles.Forsyth if(bytes_cmp(md5_hash, h.md5_hash) < 0 || bytes_cmp(sha_hash, h.sha_hash) < 0) 3271*37da2899SCharles.Forsyth return (nil, "finished: sender mismatch"); 3272*37da2899SCharles.Forsyth 3273*37da2899SCharles.Forsyth e = update_handshake_hash(ctx, r); 3274*37da2899SCharles.Forsyth if(e != nil) 3275*37da2899SCharles.Forsyth return (nil, e); 3276*37da2899SCharles.Forsyth 3277*37da2899SCharles.Forsyth CertificateVerify => 3278*37da2899SCharles.Forsyth 3279*37da2899SCharles.Forsyth e = update_handshake_hash(ctx, r); 3280*37da2899SCharles.Forsyth if(e != nil) 3281*37da2899SCharles.Forsyth return (nil, e); 3282*37da2899SCharles.Forsyth 3283*37da2899SCharles.Forsyth * => 3284*37da2899SCharles.Forsyth e = update_handshake_hash(ctx, r); 3285*37da2899SCharles.Forsyth if(e != nil) 3286*37da2899SCharles.Forsyth return (nil, e); 3287*37da2899SCharles.Forsyth } 3288*37da2899SCharles.Forsyth 3289*37da2899SCharles.Forsyth p = ref Protocol.pHandshake(hm); 3290*37da2899SCharles.Forsyth 3291*37da2899SCharles.Forsyth SSL_V2HANDSHAKE => 3292*37da2899SCharles.Forsyth 3293*37da2899SCharles.Forsyth (hm, e) := V2Handshake.decode(r.data); 3294*37da2899SCharles.Forsyth if(e != "") 3295*37da2899SCharles.Forsyth return (nil, e); 3296*37da2899SCharles.Forsyth 3297*37da2899SCharles.Forsyth p = ref Protocol.pV2Handshake(hm); 3298*37da2899SCharles.Forsyth 3299*37da2899SCharles.Forsyth * => 3300*37da2899SCharles.Forsyth return (nil, "protocol read: unknown protocol"); 3301*37da2899SCharles.Forsyth } 3302*37da2899SCharles.Forsyth 3303*37da2899SCharles.Forsyth return (p, nil); 3304*37da2899SCharles.Forsyth 3305*37da2899SCharles.Forsyth} 3306*37da2899SCharles.Forsyth 3307*37da2899SCharles.Forsyth 3308*37da2899SCharles.Forsyth# encode protocol message and return tuple of data record and error message, 3309*37da2899SCharles.Forsyth# may be v2 or v3 record depending on vers. 3310*37da2899SCharles.Forsyth 3311*37da2899SCharles.ForsythProtocol.encode(protocol: self ref Protocol, vers: array of byte): (ref Record, string) 3312*37da2899SCharles.Forsyth{ 3313*37da2899SCharles.Forsyth r: ref Record; 3314*37da2899SCharles.Forsyth e: string; 3315*37da2899SCharles.Forsyth 3316*37da2899SCharles.Forsyth pick p := protocol { 3317*37da2899SCharles.Forsyth pAlert => 3318*37da2899SCharles.Forsyth r = ref Record( 3319*37da2899SCharles.Forsyth SSL_ALERT, 3320*37da2899SCharles.Forsyth vers, 3321*37da2899SCharles.Forsyth array [] of {byte p.alert.level, byte p.alert.description} 3322*37da2899SCharles.Forsyth ); 3323*37da2899SCharles.Forsyth 3324*37da2899SCharles.Forsyth pChangeCipherSpec => 3325*37da2899SCharles.Forsyth r = ref Record( 3326*37da2899SCharles.Forsyth SSL_CHANGE_CIPHER_SPEC, 3327*37da2899SCharles.Forsyth vers, 3328*37da2899SCharles.Forsyth array [] of {byte p.change_cipher_spec.value} 3329*37da2899SCharles.Forsyth ); 3330*37da2899SCharles.Forsyth 3331*37da2899SCharles.Forsyth pHandshake => 3332*37da2899SCharles.Forsyth data: array of byte; 3333*37da2899SCharles.Forsyth (data, e) = p.handshake.encode(); 3334*37da2899SCharles.Forsyth if(e != "") 3335*37da2899SCharles.Forsyth break; 3336*37da2899SCharles.Forsyth r = ref Record( 3337*37da2899SCharles.Forsyth SSL_HANDSHAKE, 3338*37da2899SCharles.Forsyth vers, 3339*37da2899SCharles.Forsyth data 3340*37da2899SCharles.Forsyth ); 3341*37da2899SCharles.Forsyth 3342*37da2899SCharles.Forsyth pV2Handshake => 3343*37da2899SCharles.Forsyth data: array of byte; 3344*37da2899SCharles.Forsyth (data, e) = p.handshake.encode(); 3345*37da2899SCharles.Forsyth if(e != "") 3346*37da2899SCharles.Forsyth break; 3347*37da2899SCharles.Forsyth r = ref Record( 3348*37da2899SCharles.Forsyth SSL_V2HANDSHAKE, 3349*37da2899SCharles.Forsyth vers, 3350*37da2899SCharles.Forsyth data 3351*37da2899SCharles.Forsyth ); 3352*37da2899SCharles.Forsyth 3353*37da2899SCharles.Forsyth * => 3354*37da2899SCharles.Forsyth e = "unknown protocol"; 3355*37da2899SCharles.Forsyth } 3356*37da2899SCharles.Forsyth 3357*37da2899SCharles.Forsyth if(SSL_DEBUG) 3358*37da2899SCharles.Forsyth log("ssl3: protocol encode\n" + protocol.tostring()); 3359*37da2899SCharles.Forsyth 3360*37da2899SCharles.Forsyth return (r, e); 3361*37da2899SCharles.Forsyth} 3362*37da2899SCharles.Forsyth 3363*37da2899SCharles.Forsyth# 3364*37da2899SCharles.Forsyth# protocol message description 3365*37da2899SCharles.Forsyth# 3366*37da2899SCharles.ForsythProtocol.tostring(protocol: self ref Protocol): string 3367*37da2899SCharles.Forsyth{ 3368*37da2899SCharles.Forsyth info : string; 3369*37da2899SCharles.Forsyth 3370*37da2899SCharles.Forsyth pick p := protocol { 3371*37da2899SCharles.Forsyth pAlert => 3372*37da2899SCharles.Forsyth info = "\tAlert\n" + p.alert.tostring(); 3373*37da2899SCharles.Forsyth 3374*37da2899SCharles.Forsyth pChangeCipherSpec => 3375*37da2899SCharles.Forsyth info = "\tChangeCipherSpec\n"; 3376*37da2899SCharles.Forsyth 3377*37da2899SCharles.Forsyth pHandshake => 3378*37da2899SCharles.Forsyth info = "\tHandshake\n" + p.handshake.tostring(); 3379*37da2899SCharles.Forsyth 3380*37da2899SCharles.Forsyth pV2Handshake => 3381*37da2899SCharles.Forsyth info = "\tV2Handshake\n" + p.handshake.tostring(); 3382*37da2899SCharles.Forsyth 3383*37da2899SCharles.Forsyth pApplicationData => 3384*37da2899SCharles.Forsyth info = "\tApplicationData\n"; 3385*37da2899SCharles.Forsyth 3386*37da2899SCharles.Forsyth * => 3387*37da2899SCharles.Forsyth info = "\tUnknownProtocolType\n"; 3388*37da2899SCharles.Forsyth } 3389*37da2899SCharles.Forsyth 3390*37da2899SCharles.Forsyth return "ssl3: Protocol:\n" + info; 3391*37da2899SCharles.Forsyth} 3392*37da2899SCharles.Forsyth 3393*37da2899SCharles.ForsythHandshake.decode(buf: array of byte): (ref Handshake, string) 3394*37da2899SCharles.Forsyth{ 3395*37da2899SCharles.Forsyth m : ref Handshake; 3396*37da2899SCharles.Forsyth e : string; 3397*37da2899SCharles.Forsyth 3398*37da2899SCharles.Forsyth a := buf[4:]; # ignore msg length 3399*37da2899SCharles.Forsyth 3400*37da2899SCharles.Forsyth i := 0; 3401*37da2899SCharles.Forsyth case int buf[0] { 3402*37da2899SCharles.Forsyth SSL_HANDSHAKE_HELLO_REQUEST => 3403*37da2899SCharles.Forsyth m = ref Handshake.HelloRequest(); 3404*37da2899SCharles.Forsyth 3405*37da2899SCharles.Forsyth SSL_HANDSHAKE_CLIENT_HELLO => 3406*37da2899SCharles.Forsyth if(len a < 38) { 3407*37da2899SCharles.Forsyth e = "client hello: unexpected message"; 3408*37da2899SCharles.Forsyth break; 3409*37da2899SCharles.Forsyth } 3410*37da2899SCharles.Forsyth cv := a[i:i+2]; 3411*37da2899SCharles.Forsyth i += 2; 3412*37da2899SCharles.Forsyth rd := a[i:i+32]; 3413*37da2899SCharles.Forsyth i += 32; 3414*37da2899SCharles.Forsyth lsi := int a[i++]; 3415*37da2899SCharles.Forsyth if(len a < 38 + lsi) { 3416*37da2899SCharles.Forsyth e = "client hello: unexpected message"; 3417*37da2899SCharles.Forsyth break; 3418*37da2899SCharles.Forsyth } 3419*37da2899SCharles.Forsyth sid: array of byte; 3420*37da2899SCharles.Forsyth if(lsi != 0) { 3421*37da2899SCharles.Forsyth sid = a[i:i+lsi]; 3422*37da2899SCharles.Forsyth i += lsi; 3423*37da2899SCharles.Forsyth } 3424*37da2899SCharles.Forsyth else 3425*37da2899SCharles.Forsyth sid = nil; 3426*37da2899SCharles.Forsyth lcs := int_decode(a[i:i+2]); 3427*37da2899SCharles.Forsyth i += 2; 3428*37da2899SCharles.Forsyth if((lcs & 1) || lcs < 2 || len a < 40 + lsi + lcs) { 3429*37da2899SCharles.Forsyth e = "client hello: unexpected message"; 3430*37da2899SCharles.Forsyth break; 3431*37da2899SCharles.Forsyth } 3432*37da2899SCharles.Forsyth cs := array [lcs/2] of byte; 3433*37da2899SCharles.Forsyth cs = a[i:i+lcs]; 3434*37da2899SCharles.Forsyth i += lcs; 3435*37da2899SCharles.Forsyth lcm := int a[i++]; 3436*37da2899SCharles.Forsyth cr := a[i:i+lcm]; 3437*37da2899SCharles.Forsyth i += lcm; 3438*37da2899SCharles.Forsyth # In the interest of forward compatibility, it is 3439*37da2899SCharles.Forsyth # permitted for a client hello message to include 3440*37da2899SCharles.Forsyth # extra data after the compression methods. This 3441*37da2899SCharles.Forsyth # data must be included in the handshake hashes, 3442*37da2899SCharles.Forsyth # but otherwise be ignored. 3443*37da2899SCharles.Forsyth # if(i != len a) { 3444*37da2899SCharles.Forsyth # e = "client hello: unexpected message"; 3445*37da2899SCharles.Forsyth # break; 3446*37da2899SCharles.Forsyth # } 3447*37da2899SCharles.Forsyth m = ref Handshake.ClientHello(cv, rd, sid, cs, cr); 3448*37da2899SCharles.Forsyth 3449*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_HELLO => 3450*37da2899SCharles.Forsyth if(len a < 38) { 3451*37da2899SCharles.Forsyth e = "server hello: unexpected message"; 3452*37da2899SCharles.Forsyth break; 3453*37da2899SCharles.Forsyth } 3454*37da2899SCharles.Forsyth sv := a[i:i+2]; 3455*37da2899SCharles.Forsyth i += 2; 3456*37da2899SCharles.Forsyth rd := a[i:i+32]; 3457*37da2899SCharles.Forsyth i += 32; 3458*37da2899SCharles.Forsyth lsi := int a[i++]; 3459*37da2899SCharles.Forsyth if(len a < 38 + lsi) { 3460*37da2899SCharles.Forsyth e = "server hello: unexpected message"; 3461*37da2899SCharles.Forsyth break; 3462*37da2899SCharles.Forsyth } 3463*37da2899SCharles.Forsyth sid : array of byte; 3464*37da2899SCharles.Forsyth if(lsi != 0) { 3465*37da2899SCharles.Forsyth sid = a[i:i+lsi]; 3466*37da2899SCharles.Forsyth i += lsi; 3467*37da2899SCharles.Forsyth } 3468*37da2899SCharles.Forsyth else 3469*37da2899SCharles.Forsyth sid = nil; 3470*37da2899SCharles.Forsyth cs := a[i:i+2]; 3471*37da2899SCharles.Forsyth i += 2; 3472*37da2899SCharles.Forsyth cr := a[i++]; 3473*37da2899SCharles.Forsyth if(i != len a) { 3474*37da2899SCharles.Forsyth e = "server hello: unexpected message"; 3475*37da2899SCharles.Forsyth break; 3476*37da2899SCharles.Forsyth } 3477*37da2899SCharles.Forsyth m = ref Handshake.ServerHello(sv, rd, sid, cs, cr); 3478*37da2899SCharles.Forsyth 3479*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE => 3480*37da2899SCharles.Forsyth n := int_decode(a[i:i+3]); 3481*37da2899SCharles.Forsyth i += 3; 3482*37da2899SCharles.Forsyth if(len a != n + 3) { 3483*37da2899SCharles.Forsyth e = "certificate: unexpected message"; 3484*37da2899SCharles.Forsyth break; 3485*37da2899SCharles.Forsyth } 3486*37da2899SCharles.Forsyth cl : list of array of byte; 3487*37da2899SCharles.Forsyth k : int; 3488*37da2899SCharles.Forsyth while(i < n) { 3489*37da2899SCharles.Forsyth k = int_decode(a[i:i+3]); 3490*37da2899SCharles.Forsyth i += 3; 3491*37da2899SCharles.Forsyth if(k < 0 || i + k > len a) { 3492*37da2899SCharles.Forsyth e = "certificate: unexpected message"; 3493*37da2899SCharles.Forsyth break; 3494*37da2899SCharles.Forsyth } 3495*37da2899SCharles.Forsyth cl = a[i:i+k] :: cl; 3496*37da2899SCharles.Forsyth i += k; 3497*37da2899SCharles.Forsyth } 3498*37da2899SCharles.Forsyth if(e != nil) 3499*37da2899SCharles.Forsyth break; 3500*37da2899SCharles.Forsyth m = ref Handshake.Certificate(cl); 3501*37da2899SCharles.Forsyth 3502*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_KEY_EXCHANGE => 3503*37da2899SCharles.Forsyth 3504*37da2899SCharles.Forsyth m = ref Handshake.ServerKeyExchange(a[i:]); 3505*37da2899SCharles.Forsyth 3506*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE_REQUEST => 3507*37da2899SCharles.Forsyth ln := int_decode(a[i:i+2]); 3508*37da2899SCharles.Forsyth i += 2; 3509*37da2899SCharles.Forsyth types := a[i:i+ln]; 3510*37da2899SCharles.Forsyth i += ln; 3511*37da2899SCharles.Forsyth ln = int_decode(a[i:i+2]); 3512*37da2899SCharles.Forsyth i += 2; 3513*37da2899SCharles.Forsyth auths : list of array of byte; 3514*37da2899SCharles.Forsyth for(j := 0; j < ln; j++) { 3515*37da2899SCharles.Forsyth ln = int_decode(a[i:i+2]); 3516*37da2899SCharles.Forsyth i += 2; 3517*37da2899SCharles.Forsyth auths = a[i:i+ln]::auths; 3518*37da2899SCharles.Forsyth i += ln; 3519*37da2899SCharles.Forsyth } 3520*37da2899SCharles.Forsyth m = ref Handshake.CertificateRequest(types, auths); 3521*37da2899SCharles.Forsyth 3522*37da2899SCharles.Forsyth SSL_HANDSHAKE_SERVER_HELLO_DONE => 3523*37da2899SCharles.Forsyth if(len a != 0) { 3524*37da2899SCharles.Forsyth e = "server hello done: unexpected message"; 3525*37da2899SCharles.Forsyth break; 3526*37da2899SCharles.Forsyth } 3527*37da2899SCharles.Forsyth m = ref Handshake.ServerHelloDone(); 3528*37da2899SCharles.Forsyth 3529*37da2899SCharles.Forsyth SSL_HANDSHAKE_CERTIFICATE_VERIFY => 3530*37da2899SCharles.Forsyth ln := int_decode(a[i:i+2]); 3531*37da2899SCharles.Forsyth i +=2; 3532*37da2899SCharles.Forsyth sig := a[i:]; 3533*37da2899SCharles.Forsyth i += ln; 3534*37da2899SCharles.Forsyth if(i != len a) { 3535*37da2899SCharles.Forsyth e = "certificate verify: unexpected message"; 3536*37da2899SCharles.Forsyth break; 3537*37da2899SCharles.Forsyth } 3538*37da2899SCharles.Forsyth m = ref Handshake.CertificateVerify(sig); 3539*37da2899SCharles.Forsyth 3540*37da2899SCharles.Forsyth SSL_HANDSHAKE_CLIENT_KEY_EXCHANGE => 3541*37da2899SCharles.Forsyth m = ref Handshake.ClientKeyExchange(a); 3542*37da2899SCharles.Forsyth 3543*37da2899SCharles.Forsyth SSL_HANDSHAKE_FINISHED => 3544*37da2899SCharles.Forsyth if(len a != Keyring->MD5dlen + Keyring->SHA1dlen) { # 16+20 3545*37da2899SCharles.Forsyth e = "finished: unexpected message"; 3546*37da2899SCharles.Forsyth break; 3547*37da2899SCharles.Forsyth } 3548*37da2899SCharles.Forsyth md5_hash := a[i:i+Keyring->MD5dlen]; 3549*37da2899SCharles.Forsyth i += Keyring->MD5dlen; 3550*37da2899SCharles.Forsyth sha_hash := a[i:i+Keyring->SHA1dlen]; 3551*37da2899SCharles.Forsyth i += Keyring->SHA1dlen; 3552*37da2899SCharles.Forsyth if(i != len a) { 3553*37da2899SCharles.Forsyth e = "finished: unexpected message"; 3554*37da2899SCharles.Forsyth break; 3555*37da2899SCharles.Forsyth } 3556*37da2899SCharles.Forsyth m = ref Handshake.Finished(md5_hash, sha_hash); 3557*37da2899SCharles.Forsyth 3558*37da2899SCharles.Forsyth * => 3559*37da2899SCharles.Forsyth e = "unknown message"; 3560*37da2899SCharles.Forsyth } 3561*37da2899SCharles.Forsyth 3562*37da2899SCharles.Forsyth if(e != nil) 3563*37da2899SCharles.Forsyth return (nil, "Handshake decode: " + e); 3564*37da2899SCharles.Forsyth 3565*37da2899SCharles.Forsyth return (m, nil); 3566*37da2899SCharles.Forsyth} 3567*37da2899SCharles.Forsyth 3568*37da2899SCharles.ForsythHandshake.encode(hm: self ref Handshake): (array of byte, string) 3569*37da2899SCharles.Forsyth{ 3570*37da2899SCharles.Forsyth a : array of byte; 3571*37da2899SCharles.Forsyth n : int; 3572*37da2899SCharles.Forsyth e : string; 3573*37da2899SCharles.Forsyth 3574*37da2899SCharles.Forsyth i := 0; 3575*37da2899SCharles.Forsyth pick m := hm { 3576*37da2899SCharles.Forsyth HelloRequest => 3577*37da2899SCharles.Forsyth a = array [4] of byte; 3578*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_HELLO_REQUEST; 3579*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3580*37da2899SCharles.Forsyth i += 3; 3581*37da2899SCharles.Forsyth if(i != 4) 3582*37da2899SCharles.Forsyth e = "hello request: wrong message length"; 3583*37da2899SCharles.Forsyth 3584*37da2899SCharles.Forsyth ClientHello => 3585*37da2899SCharles.Forsyth lsi := len m.session_id; 3586*37da2899SCharles.Forsyth lcs := len m.suites; 3587*37da2899SCharles.Forsyth if((lcs &1) || lcs < 2) { 3588*37da2899SCharles.Forsyth e = "client hello: cipher suites is not multiple of 2 bytes"; 3589*37da2899SCharles.Forsyth break; 3590*37da2899SCharles.Forsyth } 3591*37da2899SCharles.Forsyth lcm := len m.compressions; 3592*37da2899SCharles.Forsyth n = 38 + lsi + lcs + lcm; # 2+32+1+2+1 3593*37da2899SCharles.Forsyth a = array[n+4] of byte; 3594*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_CLIENT_HELLO; 3595*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3596*37da2899SCharles.Forsyth i += 3; 3597*37da2899SCharles.Forsyth a[i:] = m.version; 3598*37da2899SCharles.Forsyth i += 2; 3599*37da2899SCharles.Forsyth a[i:] = m.random; 3600*37da2899SCharles.Forsyth i += 32; 3601*37da2899SCharles.Forsyth a[i++] = byte lsi; 3602*37da2899SCharles.Forsyth if(lsi != 0) { 3603*37da2899SCharles.Forsyth a[i:] = m.session_id; 3604*37da2899SCharles.Forsyth i += lsi; 3605*37da2899SCharles.Forsyth } 3606*37da2899SCharles.Forsyth a[i:] = int_encode(lcs, 2); 3607*37da2899SCharles.Forsyth i += 2; 3608*37da2899SCharles.Forsyth a[i:] = m.suites; # not nil 3609*37da2899SCharles.Forsyth i += lcs; 3610*37da2899SCharles.Forsyth a[i++] = byte lcm; 3611*37da2899SCharles.Forsyth a[i:] = m.compressions; # not nil 3612*37da2899SCharles.Forsyth i += lcm; 3613*37da2899SCharles.Forsyth if(i != n+4) 3614*37da2899SCharles.Forsyth e = "client hello: wrong message length"; 3615*37da2899SCharles.Forsyth 3616*37da2899SCharles.Forsyth ServerHello => 3617*37da2899SCharles.Forsyth lsi := len m.session_id; 3618*37da2899SCharles.Forsyth n = 38 + lsi; # 2+32+1+2+1 3619*37da2899SCharles.Forsyth a = array [n+4] of byte; 3620*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_SERVER_HELLO; 3621*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3622*37da2899SCharles.Forsyth i += 3; 3623*37da2899SCharles.Forsyth a[i:] = m.version; 3624*37da2899SCharles.Forsyth i += 2; 3625*37da2899SCharles.Forsyth a[i:] = m.random; 3626*37da2899SCharles.Forsyth i += 32; 3627*37da2899SCharles.Forsyth a[i++] = byte lsi; 3628*37da2899SCharles.Forsyth if(lsi != 0) { 3629*37da2899SCharles.Forsyth a[i:] = m.session_id; 3630*37da2899SCharles.Forsyth i += lsi; 3631*37da2899SCharles.Forsyth } 3632*37da2899SCharles.Forsyth a[i:] = m.suite; # should be verified, not nil 3633*37da2899SCharles.Forsyth i += 2; 3634*37da2899SCharles.Forsyth a[i++] = m.compression; # should be verified, not nil 3635*37da2899SCharles.Forsyth if(i != n+4) 3636*37da2899SCharles.Forsyth e = "server hello: wrong message length"; 3637*37da2899SCharles.Forsyth 3638*37da2899SCharles.Forsyth Certificate => 3639*37da2899SCharles.Forsyth cl := m.cert_list; 3640*37da2899SCharles.Forsyth while(cl != nil) { 3641*37da2899SCharles.Forsyth n += 3 + len hd cl; 3642*37da2899SCharles.Forsyth cl = tl cl; 3643*37da2899SCharles.Forsyth } 3644*37da2899SCharles.Forsyth a = array [n+7] of byte; 3645*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_CERTIFICATE; 3646*37da2899SCharles.Forsyth a[i:] = int_encode(n+3, 3); # length of record 3647*37da2899SCharles.Forsyth i += 3; 3648*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); # total length of cert chain 3649*37da2899SCharles.Forsyth i += 3; 3650*37da2899SCharles.Forsyth cl = m.cert_list; 3651*37da2899SCharles.Forsyth while(cl != nil) { 3652*37da2899SCharles.Forsyth a[i:] = int_encode(len hd cl, 3); 3653*37da2899SCharles.Forsyth i += 3; 3654*37da2899SCharles.Forsyth a[i:] = hd cl; 3655*37da2899SCharles.Forsyth i += len hd cl; 3656*37da2899SCharles.Forsyth cl = tl cl; 3657*37da2899SCharles.Forsyth } 3658*37da2899SCharles.Forsyth if(i != n+7) 3659*37da2899SCharles.Forsyth e = "certificate: wrong message length"; 3660*37da2899SCharles.Forsyth 3661*37da2899SCharles.Forsyth ServerKeyExchange => 3662*37da2899SCharles.Forsyth n = len m.xkey; 3663*37da2899SCharles.Forsyth a = array [n+4] of byte; 3664*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_SERVER_KEY_EXCHANGE; 3665*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3666*37da2899SCharles.Forsyth i += 3; 3667*37da2899SCharles.Forsyth a[i:] = m.xkey; 3668*37da2899SCharles.Forsyth i += len m.xkey; 3669*37da2899SCharles.Forsyth if(i != n+4) 3670*37da2899SCharles.Forsyth e = "server key exchange: wrong message length"; 3671*37da2899SCharles.Forsyth 3672*37da2899SCharles.Forsyth CertificateRequest => 3673*37da2899SCharles.Forsyth ntypes := len m.cert_types; 3674*37da2899SCharles.Forsyth nauths := len m.dn_list; 3675*37da2899SCharles.Forsyth n = 1 + ntypes; 3676*37da2899SCharles.Forsyth dl := m.dn_list; 3677*37da2899SCharles.Forsyth while(dl != nil) { 3678*37da2899SCharles.Forsyth n += 2 + len hd dl; 3679*37da2899SCharles.Forsyth dl = tl dl; 3680*37da2899SCharles.Forsyth } 3681*37da2899SCharles.Forsyth n += 2; 3682*37da2899SCharles.Forsyth a = array [n+4] of byte; 3683*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_CERTIFICATE_REQUEST; 3684*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3685*37da2899SCharles.Forsyth i += 3; 3686*37da2899SCharles.Forsyth a[i++] = byte ntypes; 3687*37da2899SCharles.Forsyth a[i:] = m.cert_types; 3688*37da2899SCharles.Forsyth i += ntypes; 3689*37da2899SCharles.Forsyth a[i:] = int_encode(nauths, 2); 3690*37da2899SCharles.Forsyth i += 2; 3691*37da2899SCharles.Forsyth dl = m.dn_list; 3692*37da2899SCharles.Forsyth while(dl != nil) { 3693*37da2899SCharles.Forsyth a[i:] = int_encode(len hd dl, 2); 3694*37da2899SCharles.Forsyth i += 2; 3695*37da2899SCharles.Forsyth a[i:] = hd dl; 3696*37da2899SCharles.Forsyth i += len hd dl; 3697*37da2899SCharles.Forsyth dl = tl dl; 3698*37da2899SCharles.Forsyth } 3699*37da2899SCharles.Forsyth if(i != n+4) 3700*37da2899SCharles.Forsyth e = "certificate request: wrong message length"; 3701*37da2899SCharles.Forsyth 3702*37da2899SCharles.Forsyth ServerHelloDone => 3703*37da2899SCharles.Forsyth n = 0; 3704*37da2899SCharles.Forsyth a = array[n+4] of byte; 3705*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_SERVER_HELLO_DONE; 3706*37da2899SCharles.Forsyth a[i:] = int_encode(0, 3); # message has 0 length 3707*37da2899SCharles.Forsyth i += 3; 3708*37da2899SCharles.Forsyth if(i != n+4) 3709*37da2899SCharles.Forsyth e = "server hello done: wrong message length"; 3710*37da2899SCharles.Forsyth 3711*37da2899SCharles.Forsyth CertificateVerify => 3712*37da2899SCharles.Forsyth n = 2 + len m.signature; 3713*37da2899SCharles.Forsyth a = array [n+4] of byte; 3714*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_CERTIFICATE_VERIFY; 3715*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3716*37da2899SCharles.Forsyth i += 3; 3717*37da2899SCharles.Forsyth a[i:] = int_encode(n-2, 2); 3718*37da2899SCharles.Forsyth i += 2; 3719*37da2899SCharles.Forsyth a[i:] = m.signature; 3720*37da2899SCharles.Forsyth i += n-2; 3721*37da2899SCharles.Forsyth if(i != n+4) 3722*37da2899SCharles.Forsyth e = "certificate verify: wrong message length"; 3723*37da2899SCharles.Forsyth 3724*37da2899SCharles.Forsyth ClientKeyExchange => 3725*37da2899SCharles.Forsyth n = len m.xkey; 3726*37da2899SCharles.Forsyth a = array [n+4] of byte; 3727*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_CLIENT_KEY_EXCHANGE; 3728*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3729*37da2899SCharles.Forsyth i += 3; 3730*37da2899SCharles.Forsyth a[i:] = m.xkey; 3731*37da2899SCharles.Forsyth i += n; 3732*37da2899SCharles.Forsyth if(i != n+4) 3733*37da2899SCharles.Forsyth e = "client key exchange: wrong message length"; 3734*37da2899SCharles.Forsyth 3735*37da2899SCharles.Forsyth Finished => 3736*37da2899SCharles.Forsyth n = len m.md5_hash + len m.sha_hash; 3737*37da2899SCharles.Forsyth a = array [n+4] of byte; 3738*37da2899SCharles.Forsyth a[i++] = byte SSL_HANDSHAKE_FINISHED; 3739*37da2899SCharles.Forsyth a[i:] = int_encode(n, 3); 3740*37da2899SCharles.Forsyth i += 3; 3741*37da2899SCharles.Forsyth a[i:] = m.md5_hash; 3742*37da2899SCharles.Forsyth i += len m.md5_hash; 3743*37da2899SCharles.Forsyth a[i:] = m.sha_hash; 3744*37da2899SCharles.Forsyth i += len m.sha_hash; 3745*37da2899SCharles.Forsyth if(i != n+4) 3746*37da2899SCharles.Forsyth e = "finished: wrong message length"; 3747*37da2899SCharles.Forsyth 3748*37da2899SCharles.Forsyth * => 3749*37da2899SCharles.Forsyth e = "unknown message"; 3750*37da2899SCharles.Forsyth } 3751*37da2899SCharles.Forsyth 3752*37da2899SCharles.Forsyth if(e != nil) 3753*37da2899SCharles.Forsyth return (nil, "Handshake encode: " + e); 3754*37da2899SCharles.Forsyth 3755*37da2899SCharles.Forsyth return (a, e); 3756*37da2899SCharles.Forsyth} 3757*37da2899SCharles.Forsyth 3758*37da2899SCharles.ForsythHandshake.tostring(handshake: self ref Handshake): string 3759*37da2899SCharles.Forsyth{ 3760*37da2899SCharles.Forsyth info: string; 3761*37da2899SCharles.Forsyth 3762*37da2899SCharles.Forsyth pick m := handshake { 3763*37da2899SCharles.Forsyth HelloRequest => 3764*37da2899SCharles.Forsyth info = "\tHelloRequest\n"; 3765*37da2899SCharles.Forsyth 3766*37da2899SCharles.Forsyth ClientHello => 3767*37da2899SCharles.Forsyth info = "\tClientHello\n" + 3768*37da2899SCharles.Forsyth "\tversion = \n\t\t" + bastr(m.version) + "\n" + 3769*37da2899SCharles.Forsyth "\trandom = \n\t\t" + bastr(m.random) + "\n" + 3770*37da2899SCharles.Forsyth "\tsession_id = \n\t\t" + bastr(m.session_id) + "\n" + 3771*37da2899SCharles.Forsyth "\tsuites = \n\t\t" + bastr(m.suites) + "\n" + 3772*37da2899SCharles.Forsyth "\tcomperssion_methods = \n\t\t" + bastr(m.compressions) +"\n"; 3773*37da2899SCharles.Forsyth 3774*37da2899SCharles.Forsyth ServerHello => 3775*37da2899SCharles.Forsyth info = "\tServerHello\n" + 3776*37da2899SCharles.Forsyth "\tversion = \n\t\t" + bastr(m.version) + "\n" + 3777*37da2899SCharles.Forsyth "\trandom = \n\t\t" + bastr(m.random) + "\n" + 3778*37da2899SCharles.Forsyth "\tsession_id = \n\t\t" + bastr(m.session_id) + "\n" + 3779*37da2899SCharles.Forsyth "\tsuite = \n\t\t" + bastr(m.suite) + "\n" + 3780*37da2899SCharles.Forsyth "\tcomperssion_method = \n\t\t" + string m.compression +"\n"; 3781*37da2899SCharles.Forsyth 3782*37da2899SCharles.Forsyth Certificate => 3783*37da2899SCharles.Forsyth info = "\tCertificate\n" + 3784*37da2899SCharles.Forsyth "\tcert_list = \n\t\t" + lbastr(m.cert_list) + "\n"; 3785*37da2899SCharles.Forsyth 3786*37da2899SCharles.Forsyth ServerKeyExchange => 3787*37da2899SCharles.Forsyth info = "\tServerKeyExchange\n" + 3788*37da2899SCharles.Forsyth "\txkey = \n\t\t" + bastr(m.xkey) +"\n"; 3789*37da2899SCharles.Forsyth 3790*37da2899SCharles.Forsyth CertificateRequest => 3791*37da2899SCharles.Forsyth info = "\tCertificateRequest\n" + 3792*37da2899SCharles.Forsyth "\tcert_types = \n\t\t" + bastr(m.cert_types) + "\n" + 3793*37da2899SCharles.Forsyth "\tdn_list = \n\t\t" + lbastr(m.dn_list) + "\n"; 3794*37da2899SCharles.Forsyth 3795*37da2899SCharles.Forsyth ServerHelloDone => 3796*37da2899SCharles.Forsyth info = "\tServerDone\n"; 3797*37da2899SCharles.Forsyth 3798*37da2899SCharles.Forsyth CertificateVerify => 3799*37da2899SCharles.Forsyth info = "\tCertificateVerify\n" + 3800*37da2899SCharles.Forsyth "\tsignature = \n\t\t" + bastr(m.signature) + "\n"; 3801*37da2899SCharles.Forsyth 3802*37da2899SCharles.Forsyth ClientKeyExchange => 3803*37da2899SCharles.Forsyth info = "\tClientKeyExchange\n" + 3804*37da2899SCharles.Forsyth "\txkey = \n\t\t" + bastr(m.xkey) +"\n"; 3805*37da2899SCharles.Forsyth 3806*37da2899SCharles.Forsyth Finished => 3807*37da2899SCharles.Forsyth info = "\tFinished\n" + 3808*37da2899SCharles.Forsyth "\tmd5_hash = \n\t\t" + bastr(m.md5_hash) + "\n" + 3809*37da2899SCharles.Forsyth "\tsha_hash = \n\t\t" + bastr(m.sha_hash) + "\n"; 3810*37da2899SCharles.Forsyth } 3811*37da2899SCharles.Forsyth 3812*37da2899SCharles.Forsyth return info; 3813*37da2899SCharles.Forsyth} 3814*37da2899SCharles.Forsyth 3815*37da2899SCharles.ForsythAlert.tostring(alert: self ref Alert): string 3816*37da2899SCharles.Forsyth{ 3817*37da2899SCharles.Forsyth info: string; 3818*37da2899SCharles.Forsyth 3819*37da2899SCharles.Forsyth case alert.level { 3820*37da2899SCharles.Forsyth SSL_WARNING => 3821*37da2899SCharles.Forsyth info += "\t\twarning: "; 3822*37da2899SCharles.Forsyth 3823*37da2899SCharles.Forsyth SSL_FATAL => 3824*37da2899SCharles.Forsyth info += "\t\tfatal: "; 3825*37da2899SCharles.Forsyth 3826*37da2899SCharles.Forsyth * => 3827*37da2899SCharles.Forsyth info += sys->sprint("unknown alert level[%d]: ", alert.level); 3828*37da2899SCharles.Forsyth } 3829*37da2899SCharles.Forsyth 3830*37da2899SCharles.Forsyth case alert.description { 3831*37da2899SCharles.Forsyth SSL_CLOSE_NOTIFY => 3832*37da2899SCharles.Forsyth info += "close notify"; 3833*37da2899SCharles.Forsyth 3834*37da2899SCharles.Forsyth SSL_NO_CERTIFICATE => 3835*37da2899SCharles.Forsyth info += "no certificate"; 3836*37da2899SCharles.Forsyth 3837*37da2899SCharles.Forsyth SSL_BAD_CERTIFICATE => 3838*37da2899SCharles.Forsyth info += "bad certificate"; 3839*37da2899SCharles.Forsyth 3840*37da2899SCharles.Forsyth SSL_UNSUPPORTED_CERTIFICATE => 3841*37da2899SCharles.Forsyth info += "unsupported certificate"; 3842*37da2899SCharles.Forsyth 3843*37da2899SCharles.Forsyth SSL_CERTIFICATE_REVOKED => 3844*37da2899SCharles.Forsyth info += "certificate revoked"; 3845*37da2899SCharles.Forsyth 3846*37da2899SCharles.Forsyth SSL_CERTIFICATE_EXPIRED => 3847*37da2899SCharles.Forsyth info += "certificate expired"; 3848*37da2899SCharles.Forsyth 3849*37da2899SCharles.Forsyth SSL_CERTIFICATE_UNKNOWN => 3850*37da2899SCharles.Forsyth info += "certificate unknown"; 3851*37da2899SCharles.Forsyth 3852*37da2899SCharles.Forsyth SSL_UNEXPECTED_MESSAGE => 3853*37da2899SCharles.Forsyth info += "unexpected message"; 3854*37da2899SCharles.Forsyth 3855*37da2899SCharles.Forsyth SSL_BAD_RECORD_MAC => 3856*37da2899SCharles.Forsyth info += "bad record mac"; 3857*37da2899SCharles.Forsyth 3858*37da2899SCharles.Forsyth SSL_DECOMPRESSION_FAILURE => 3859*37da2899SCharles.Forsyth info += "decompression failure"; 3860*37da2899SCharles.Forsyth 3861*37da2899SCharles.Forsyth SSL_HANDSHAKE_FAILURE => 3862*37da2899SCharles.Forsyth info += "handshake failure"; 3863*37da2899SCharles.Forsyth 3864*37da2899SCharles.Forsyth SSL_ILLEGAL_PARAMETER => 3865*37da2899SCharles.Forsyth info += "illegal parameter"; 3866*37da2899SCharles.Forsyth 3867*37da2899SCharles.Forsyth * => 3868*37da2899SCharles.Forsyth info += sys->sprint("unknown alert description[%d]", alert.description); 3869*37da2899SCharles.Forsyth } 3870*37da2899SCharles.Forsyth 3871*37da2899SCharles.Forsyth return info; 3872*37da2899SCharles.Forsyth} 3873*37da2899SCharles.Forsyth 3874*37da2899SCharles.Forsythfind_cipher_suite(s, suites: array of byte) : array of byte 3875*37da2899SCharles.Forsyth{ 3876*37da2899SCharles.Forsyth i, j : int; 3877*37da2899SCharles.Forsyth a, b : array of byte; 3878*37da2899SCharles.Forsyth 3879*37da2899SCharles.Forsyth n := len s; 3880*37da2899SCharles.Forsyth if((n & 1) || n < 2) 3881*37da2899SCharles.Forsyth return nil; 3882*37da2899SCharles.Forsyth 3883*37da2899SCharles.Forsyth m := len suites; 3884*37da2899SCharles.Forsyth if((m & 1) || m < 2) 3885*37da2899SCharles.Forsyth return nil; 3886*37da2899SCharles.Forsyth 3887*37da2899SCharles.Forsyth for(i = 0; i < n; ) { 3888*37da2899SCharles.Forsyth a = s[i:i+2]; 3889*37da2899SCharles.Forsyth i += 2; 3890*37da2899SCharles.Forsyth for(j = 0; j < m; ) { 3891*37da2899SCharles.Forsyth b = suites[j:j+2]; 3892*37da2899SCharles.Forsyth j += 2; 3893*37da2899SCharles.Forsyth if(a[0] == b[0] && a[1] == b[1]) 3894*37da2899SCharles.Forsyth return b; 3895*37da2899SCharles.Forsyth } 3896*37da2899SCharles.Forsyth } 3897*37da2899SCharles.Forsyth 3898*37da2899SCharles.Forsyth return nil; 3899*37da2899SCharles.Forsyth} 3900*37da2899SCharles.Forsyth 3901*37da2899SCharles.Forsyth# 3902*37da2899SCharles.Forsyth# cipher suites and specs 3903*37da2899SCharles.Forsyth# 3904*37da2899SCharles.Forsythsuite_to_spec(cs: array of byte, cipher_suites: array of array of byte) 3905*37da2899SCharles.Forsyth : (ref CipherSpec, ref KeyExAlg, ref SigAlg, string) 3906*37da2899SCharles.Forsyth{ 3907*37da2899SCharles.Forsyth cip : ref CipherSpec; 3908*37da2899SCharles.Forsyth kex : ref KeyExAlg; 3909*37da2899SCharles.Forsyth sig : ref SigAlg; 3910*37da2899SCharles.Forsyth 3911*37da2899SCharles.Forsyth n := len cipher_suites; 3912*37da2899SCharles.Forsyth i : int; 3913*37da2899SCharles.Forsyth found := array [2] of byte; 3914*37da2899SCharles.Forsyth for(i = 0; i < n; i++) { 3915*37da2899SCharles.Forsyth found = cipher_suites[i]; 3916*37da2899SCharles.Forsyth if(found[0]==cs[0] && found[1]==cs[1]) break; 3917*37da2899SCharles.Forsyth } 3918*37da2899SCharles.Forsyth 3919*37da2899SCharles.Forsyth if(i == n) 3920*37da2899SCharles.Forsyth return (nil, nil, nil, "fail to find a matched spec"); 3921*37da2899SCharles.Forsyth 3922*37da2899SCharles.Forsyth case i { 3923*37da2899SCharles.Forsyth NULL_WITH_NULL_NULL => 3924*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_NULL_CIPHER, 3925*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 0, 0, SSL_NULL_MAC, 0); 3926*37da2899SCharles.Forsyth kex = ref KeyExAlg.NULL(); 3927*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3928*37da2899SCharles.Forsyth 3929*37da2899SCharles.Forsyth RSA_WITH_NULL_MD5 => # sign only certificate 3930*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_NULL_CIPHER, 3931*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 0, 0, SSL_MD5, Keyring->MD5dlen); 3932*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3933*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3934*37da2899SCharles.Forsyth 3935*37da2899SCharles.Forsyth RSA_WITH_NULL_SHA => 3936*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_NULL_CIPHER, 3937*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 0, 0, SSL_SHA, Keyring->SHA1dlen); 3938*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3939*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3940*37da2899SCharles.Forsyth 3941*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC4_40_MD5 => 3942*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_RC4, 3943*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 5, 0, SSL_MD5, Keyring->MD5dlen); 3944*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3945*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3946*37da2899SCharles.Forsyth 3947*37da2899SCharles.Forsyth RSA_WITH_RC4_128_MD5 => 3948*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC4, 3949*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 16, 0, SSL_MD5, Keyring->MD5dlen); 3950*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3951*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3952*37da2899SCharles.Forsyth 3953*37da2899SCharles.Forsyth RSA_WITH_RC4_128_SHA => 3954*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC4, 3955*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 16, 0, SSL_SHA, Keyring->SHA1dlen); 3956*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3957*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3958*37da2899SCharles.Forsyth 3959*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC2_CBC_40_MD5 => 3960*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_RC2_CBC, 3961*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_MD5, Keyring->MD5dlen); 3962*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3963*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 3964*37da2899SCharles.Forsyth 3965*37da2899SCharles.Forsyth RSA_WITH_IDEA_CBC_SHA => 3966*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_IDEA_CBC, 3967*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 16, 8, SSL_SHA, Keyring->SHA1dlen); 3968*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3969*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3970*37da2899SCharles.Forsyth 3971*37da2899SCharles.Forsyth RSA_EXPORT_WITH_DES40_CBC_SHA => 3972*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_DES_CBC, 3973*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 3974*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3975*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 3976*37da2899SCharles.Forsyth 3977*37da2899SCharles.Forsyth RSA_WITH_DES_CBC_SHA => 3978*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 3979*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 3980*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3981*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3982*37da2899SCharles.Forsyth 3983*37da2899SCharles.Forsyth RSA_WITH_3DES_EDE_CBC_SHA => 3984*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 3985*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 3986*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 3987*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 3988*37da2899SCharles.Forsyth 3989*37da2899SCharles.Forsyth DH_DSS_EXPORT_WITH_DES40_CBC_SHA => 3990*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_DES_CBC, 3991*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 3992*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 3993*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 3994*37da2899SCharles.Forsyth 3995*37da2899SCharles.Forsyth DH_DSS_WITH_DES_CBC_SHA => 3996*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 3997*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 3998*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 3999*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 4000*37da2899SCharles.Forsyth 4001*37da2899SCharles.Forsyth DH_DSS_WITH_3DES_EDE_CBC_SHA => 4002*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 4003*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 4004*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4005*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 4006*37da2899SCharles.Forsyth 4007*37da2899SCharles.Forsyth DH_RSA_EXPORT_WITH_DES40_CBC_SHA => 4008*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_DES_CBC, 4009*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 4010*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4011*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4012*37da2899SCharles.Forsyth 4013*37da2899SCharles.Forsyth DH_RSA_WITH_DES_CBC_SHA => 4014*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 4015*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 4016*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4017*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4018*37da2899SCharles.Forsyth 4019*37da2899SCharles.Forsyth DH_RSA_WITH_3DES_EDE_CBC_SHA => 4020*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 4021*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 4022*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4023*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4024*37da2899SCharles.Forsyth 4025*37da2899SCharles.Forsyth DHE_DSS_EXPORT_WITH_DES40_CBC_SHA => 4026*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 4027*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 4028*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4029*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 4030*37da2899SCharles.Forsyth 4031*37da2899SCharles.Forsyth DHE_DSS_WITH_DES_CBC_SHA => 4032*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 4033*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 4034*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4035*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 4036*37da2899SCharles.Forsyth 4037*37da2899SCharles.Forsyth DHE_DSS_WITH_3DES_EDE_CBC_SHA => 4038*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 4039*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 4040*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4041*37da2899SCharles.Forsyth sig = ref SigAlg.DSS(nil, nil); 4042*37da2899SCharles.Forsyth 4043*37da2899SCharles.Forsyth DHE_RSA_EXPORT_WITH_DES40_CBC_SHA => 4044*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_DES_CBC, 4045*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 4046*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4047*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4048*37da2899SCharles.Forsyth 4049*37da2899SCharles.Forsyth DHE_RSA_WITH_DES_CBC_SHA => 4050*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 4051*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 4052*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4053*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4054*37da2899SCharles.Forsyth 4055*37da2899SCharles.Forsyth DHE_RSA_WITH_3DES_EDE_CBC_SHA => 4056*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 4057*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 4058*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4059*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 4060*37da2899SCharles.Forsyth 4061*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_RC4_40_MD5 => 4062*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_RC4, 4063*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 5, 0, SSL_MD5, Keyring->MD5dlen); 4064*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4065*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 4066*37da2899SCharles.Forsyth 4067*37da2899SCharles.Forsyth DH_anon_WITH_RC4_128_MD5 => 4068*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC4, 4069*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 16, 0, SSL_MD5, Keyring->MD5dlen); 4070*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4071*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 4072*37da2899SCharles.Forsyth 4073*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_DES40_CBC_SHA => 4074*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_DES_CBC, 4075*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 5, 8, SSL_SHA, Keyring->SHA1dlen); 4076*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4077*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 4078*37da2899SCharles.Forsyth 4079*37da2899SCharles.Forsyth DH_anon_WITH_DES_CBC_SHA => 4080*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, 4081*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 8, 8, SSL_SHA, Keyring->SHA1dlen); 4082*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4083*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 4084*37da2899SCharles.Forsyth 4085*37da2899SCharles.Forsyth DH_anon_WITH_3DES_EDE_CBC_SHA => 4086*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, 4087*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 24, 8, SSL_SHA, Keyring->SHA1dlen); 4088*37da2899SCharles.Forsyth kex = ref KeyExAlg.DH(nil, nil, nil, nil, nil); 4089*37da2899SCharles.Forsyth sig = ref SigAlg.anon(); 4090*37da2899SCharles.Forsyth 4091*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_NULL_SHA => 4092*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_NULL_CIPHER, 4093*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 0, 0, SSL_SHA, Keyring->SHA1dlen); 4094*37da2899SCharles.Forsyth kex = ref KeyExAlg.FORTEZZA_KEA(); 4095*37da2899SCharles.Forsyth sig = ref SigAlg.FORTEZZA_KEA(); 4096*37da2899SCharles.Forsyth 4097*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA => 4098*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_FORTEZZA_CBC, 4099*37da2899SCharles.Forsyth SSL_BLOCK_CIPHER, 0, 0, SSL_SHA, Keyring->SHA1dlen); 4100*37da2899SCharles.Forsyth kex = ref KeyExAlg.FORTEZZA_KEA(); 4101*37da2899SCharles.Forsyth sig = ref SigAlg.FORTEZZA_KEA(); 4102*37da2899SCharles.Forsyth 4103*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_RC4_128_SHA => 4104*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC4, 4105*37da2899SCharles.Forsyth SSL_STREAM_CIPHER, 16, 0, SSL_SHA, Keyring->SHA1dlen); 4106*37da2899SCharles.Forsyth kex = ref KeyExAlg.FORTEZZA_KEA(); 4107*37da2899SCharles.Forsyth sig = ref SigAlg.FORTEZZA_KEA(); 4108*37da2899SCharles.Forsyth 4109*37da2899SCharles.Forsyth } 4110*37da2899SCharles.Forsyth 4111*37da2899SCharles.Forsyth return (cip, kex, sig, nil); 4112*37da2899SCharles.Forsyth} 4113*37da2899SCharles.Forsyth 4114*37da2899SCharles.Forsyth# 4115*37da2899SCharles.Forsyth# use suites as default SSL3_Suites 4116*37da2899SCharles.Forsyth# 4117*37da2899SCharles.Forsythcipher_suite_info(cs: array of byte, suites: array of array of byte) : string 4118*37da2899SCharles.Forsyth{ 4119*37da2899SCharles.Forsyth tag : string; 4120*37da2899SCharles.Forsyth 4121*37da2899SCharles.Forsyth a := array [2] of byte; 4122*37da2899SCharles.Forsyth n := len suites; 4123*37da2899SCharles.Forsyth for(i := 0; i < n; i++) { 4124*37da2899SCharles.Forsyth a = suites[i]; 4125*37da2899SCharles.Forsyth if(a[0]==cs[0] && a[1]==cs[1]) break; 4126*37da2899SCharles.Forsyth } 4127*37da2899SCharles.Forsyth 4128*37da2899SCharles.Forsyth if(i == n) 4129*37da2899SCharles.Forsyth return "unknown cipher suite [" + string cs + "]"; 4130*37da2899SCharles.Forsyth 4131*37da2899SCharles.Forsyth case i { 4132*37da2899SCharles.Forsyth NULL_WITH_NULL_NULL => 4133*37da2899SCharles.Forsyth tag = "NULL_WITH_NULL_NULL"; 4134*37da2899SCharles.Forsyth 4135*37da2899SCharles.Forsyth RSA_WITH_NULL_MD5 => 4136*37da2899SCharles.Forsyth tag = "RSA_WITH_NULL_MD5"; 4137*37da2899SCharles.Forsyth 4138*37da2899SCharles.Forsyth RSA_WITH_NULL_SHA => 4139*37da2899SCharles.Forsyth tag = "RSA_WITH_NULL_SHA"; 4140*37da2899SCharles.Forsyth 4141*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC4_40_MD5 => 4142*37da2899SCharles.Forsyth tag = "RSA_EXPORT_WITH_RC4_40_MD5"; 4143*37da2899SCharles.Forsyth 4144*37da2899SCharles.Forsyth RSA_WITH_RC4_128_MD5 => 4145*37da2899SCharles.Forsyth tag = "RSA_WITH_RC4_128_MD5"; 4146*37da2899SCharles.Forsyth 4147*37da2899SCharles.Forsyth RSA_WITH_RC4_128_SHA => 4148*37da2899SCharles.Forsyth tag = "RSA_WITH_RC4_128_SHA"; 4149*37da2899SCharles.Forsyth 4150*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC2_CBC_40_MD5 => 4151*37da2899SCharles.Forsyth tag = "RSA_EXPORT_WITH_RC2_CBC_40_MD5"; 4152*37da2899SCharles.Forsyth 4153*37da2899SCharles.Forsyth RSA_WITH_IDEA_CBC_SHA => 4154*37da2899SCharles.Forsyth tag = "RSA_WITH_IDEA_CBC_SHA"; 4155*37da2899SCharles.Forsyth 4156*37da2899SCharles.Forsyth RSA_EXPORT_WITH_DES40_CBC_SHA => 4157*37da2899SCharles.Forsyth tag ="RSA_EXPORT_WITH_DES40_CBC_SHA"; 4158*37da2899SCharles.Forsyth 4159*37da2899SCharles.Forsyth RSA_WITH_DES_CBC_SHA => 4160*37da2899SCharles.Forsyth tag = "RSA_WITH_DES_CBC_SHA"; 4161*37da2899SCharles.Forsyth 4162*37da2899SCharles.Forsyth RSA_WITH_3DES_EDE_CBC_SHA => 4163*37da2899SCharles.Forsyth tag = "RSA_WITH_3DES_EDE_CBC_SHA"; 4164*37da2899SCharles.Forsyth 4165*37da2899SCharles.Forsyth DH_DSS_EXPORT_WITH_DES40_CBC_SHA => 4166*37da2899SCharles.Forsyth tag = "DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; 4167*37da2899SCharles.Forsyth 4168*37da2899SCharles.Forsyth DH_DSS_WITH_DES_CBC_SHA => 4169*37da2899SCharles.Forsyth tag = "DH_DSS_WITH_DES_CBC_SHA"; 4170*37da2899SCharles.Forsyth 4171*37da2899SCharles.Forsyth DH_DSS_WITH_3DES_EDE_CBC_SHA => 4172*37da2899SCharles.Forsyth tag = "DH_DSS_WITH_3DES_EDE_CBC_SHA"; 4173*37da2899SCharles.Forsyth 4174*37da2899SCharles.Forsyth DH_RSA_EXPORT_WITH_DES40_CBC_SHA => 4175*37da2899SCharles.Forsyth tag = "DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; 4176*37da2899SCharles.Forsyth 4177*37da2899SCharles.Forsyth DH_RSA_WITH_DES_CBC_SHA => 4178*37da2899SCharles.Forsyth tag = "DH_RSA_WITH_DES_CBC_SHA"; 4179*37da2899SCharles.Forsyth 4180*37da2899SCharles.Forsyth DH_RSA_WITH_3DES_EDE_CBC_SHA => 4181*37da2899SCharles.Forsyth tag = "DH_RSA_WITH_3DES_EDE_CBC_SHA"; 4182*37da2899SCharles.Forsyth 4183*37da2899SCharles.Forsyth DHE_DSS_EXPORT_WITH_DES40_CBC_SHA => 4184*37da2899SCharles.Forsyth tag = "DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; 4185*37da2899SCharles.Forsyth 4186*37da2899SCharles.Forsyth DHE_DSS_WITH_DES_CBC_SHA => 4187*37da2899SCharles.Forsyth tag = "DHE_DSS_WITH_DES_CBC_SHA"; 4188*37da2899SCharles.Forsyth 4189*37da2899SCharles.Forsyth DHE_DSS_WITH_3DES_EDE_CBC_SHA => 4190*37da2899SCharles.Forsyth tag = "DHE_DSS_WITH_3DES_EDE_CBC_SHA"; 4191*37da2899SCharles.Forsyth 4192*37da2899SCharles.Forsyth DHE_RSA_EXPORT_WITH_DES40_CBC_SHA => 4193*37da2899SCharles.Forsyth tag = "DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; 4194*37da2899SCharles.Forsyth 4195*37da2899SCharles.Forsyth DHE_RSA_WITH_DES_CBC_SHA => 4196*37da2899SCharles.Forsyth tag = "DHE_RSA_WITH_DES_CBC_SHA"; 4197*37da2899SCharles.Forsyth 4198*37da2899SCharles.Forsyth DHE_RSA_WITH_3DES_EDE_CBC_SHA => 4199*37da2899SCharles.Forsyth tag = "DHE_RSA_WITH_3DES_EDE_CBC_SHA"; 4200*37da2899SCharles.Forsyth 4201*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_RC4_40_MD5 => 4202*37da2899SCharles.Forsyth tag = "DH_anon_EXPORT_WITH_RC4_40_MD5"; 4203*37da2899SCharles.Forsyth 4204*37da2899SCharles.Forsyth DH_anon_WITH_RC4_128_MD5 => 4205*37da2899SCharles.Forsyth tag = "DH_anon_WITH_RC4_128_MD5"; 4206*37da2899SCharles.Forsyth 4207*37da2899SCharles.Forsyth DH_anon_EXPORT_WITH_DES40_CBC_SHA => 4208*37da2899SCharles.Forsyth tag = "DH_anon_EXPORT_WITH_DES40_CBC_SHA"; 4209*37da2899SCharles.Forsyth 4210*37da2899SCharles.Forsyth DH_anon_WITH_DES_CBC_SHA => 4211*37da2899SCharles.Forsyth tag = "DH_anon_WITH_DES_CBC_SHA"; 4212*37da2899SCharles.Forsyth 4213*37da2899SCharles.Forsyth DH_anon_WITH_3DES_EDE_CBC_SHA => 4214*37da2899SCharles.Forsyth tag = "DH_anon_WITH_3DES_EDE_CBC_SHA"; 4215*37da2899SCharles.Forsyth 4216*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_NULL_SHA => 4217*37da2899SCharles.Forsyth tag = "FORTEZZA_KEA_WITH_NULL_SHA"; 4218*37da2899SCharles.Forsyth 4219*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA => 4220*37da2899SCharles.Forsyth tag = "FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"; 4221*37da2899SCharles.Forsyth 4222*37da2899SCharles.Forsyth FORTEZZA_KEA_WITH_RC4_128_SHA => 4223*37da2899SCharles.Forsyth tag = "FORTEZZA_KEA_WITH_RC4_128_SHA"; 4224*37da2899SCharles.Forsyth } 4225*37da2899SCharles.Forsyth 4226*37da2899SCharles.Forsyth return "cipher suite = [" + tag + "]"; 4227*37da2899SCharles.Forsyth} 4228*37da2899SCharles.Forsyth 4229*37da2899SCharles.Forsyth################################# 4230*37da2899SCharles.Forsyth## FOR SSLv2 BACKWARD COMPATIBLE 4231*37da2899SCharles.Forsyth################################# 4232*37da2899SCharles.Forsyth 4233*37da2899SCharles.Forsyth# Protocol Version Codes 4234*37da2899SCharles.ForsythSSL2_CLIENT_VERSION := array [] of {byte 0, byte 16r02}; 4235*37da2899SCharles.ForsythSSL2_SERVER_VERSION := array [] of {byte 0, byte 16r02}; 4236*37da2899SCharles.Forsyth 4237*37da2899SCharles.Forsyth# Protocol Message Codes 4238*37da2899SCharles.Forsyth 4239*37da2899SCharles.ForsythSSL2_MT_ERROR, 4240*37da2899SCharles.Forsyth SSL2_MT_CLIENT_HELLO, 4241*37da2899SCharles.Forsyth SSL2_MT_CLIENT_MASTER_KEY, 4242*37da2899SCharles.Forsyth SSL2_MT_CLIENT_FINISHED, 4243*37da2899SCharles.Forsyth SSL2_MT_SERVER_HELLO, 4244*37da2899SCharles.Forsyth SSL2_MT_SERVER_VERIFY, 4245*37da2899SCharles.Forsyth SSL2_MT_SERVER_FINISHED, 4246*37da2899SCharles.Forsyth SSL2_MT_REQUEST_CERTIFICATE, 4247*37da2899SCharles.Forsyth SSL2_MT_CLIENT_CERTIFICATE : con iota; 4248*37da2899SCharles.Forsyth 4249*37da2899SCharles.Forsyth# Error Message Codes 4250*37da2899SCharles.Forsyth 4251*37da2899SCharles.ForsythSSL2_PE_NO_CIPHER := array [] of {byte 0, byte 16r01}; 4252*37da2899SCharles.ForsythSSL2_PE_NO_CERTIFICATE := array [] of {byte 0, byte 16r02}; 4253*37da2899SCharles.ForsythSSL2_PE_BAD_CERTIFICATE := array [] of {byte 0, byte 16r04}; 4254*37da2899SCharles.ForsythSSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE := array [] of {byte 0, byte 16r06}; 4255*37da2899SCharles.Forsyth 4256*37da2899SCharles.Forsyth# Cipher Kind Values 4257*37da2899SCharles.Forsyth 4258*37da2899SCharles.ForsythSSL2_CK_RC4_128_WITH_MD5, 4259*37da2899SCharles.Forsyth SSL2_CK_RC4_128_EXPORT40_WITH_MD5, 4260*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_WITH_MD5, 4261*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_EXPORT40_WITH_MD5, 4262*37da2899SCharles.Forsyth SSL2_CK_IDEA_128_CBC_WITH_MD5, 4263*37da2899SCharles.Forsyth SSL2_CK_DES_64_CBC_WITH_MD5, 4264*37da2899SCharles.Forsyth SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 : con iota; 4265*37da2899SCharles.Forsyth 4266*37da2899SCharles.ForsythSSL2_Cipher_Kinds := array [] of { 4267*37da2899SCharles.Forsyth SSL2_CK_RC4_128_WITH_MD5 => array [] of {byte 16r01, byte 0, byte 16r80}, 4268*37da2899SCharles.Forsyth SSL2_CK_RC4_128_EXPORT40_WITH_MD5 => array [] of {byte 16r02, byte 0, byte 16r80}, 4269*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_WITH_MD5 => array [] of {byte 16r03, byte 0, byte 16r80}, 4270*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_EXPORT40_WITH_MD5 => 4271*37da2899SCharles.Forsyth array [] of {byte 16r04, byte 0, byte 16r80}, 4272*37da2899SCharles.Forsyth SSL2_CK_IDEA_128_CBC_WITH_MD5 => array [] of {byte 16r05, byte 0, byte 16r80}, 4273*37da2899SCharles.Forsyth SSL2_CK_DES_64_CBC_WITH_MD5 => array [] of {byte 16r06, byte 0, byte 16r40}, 4274*37da2899SCharles.Forsyth SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 => array [] of {byte 16r07, byte 0, byte 16rC0}, 4275*37da2899SCharles.Forsyth}; 4276*37da2899SCharles.Forsyth 4277*37da2899SCharles.Forsyth# Certificate Type Codes 4278*37da2899SCharles.Forsyth 4279*37da2899SCharles.ForsythSSL2_CT_X509_CERTIFICATE : con 16r01; # encode as one byte 4280*37da2899SCharles.Forsyth 4281*37da2899SCharles.Forsyth# Authentication Type Codes 4282*37da2899SCharles.Forsyth 4283*37da2899SCharles.ForsythSSL2_AT_MD5_WITH_RSA_ENCRYPTION : con byte 16r01; 4284*37da2899SCharles.Forsyth 4285*37da2899SCharles.Forsyth# Upper/Lower Bounds 4286*37da2899SCharles.Forsyth 4287*37da2899SCharles.ForsythSSL2_MAX_MASTER_KEY_LENGTH_IN_BITS : con 256; 4288*37da2899SCharles.ForsythSSL2_MAX_SESSION_ID_LENGTH_IN_BYTES : con 16; 4289*37da2899SCharles.ForsythSSL2_MIN_RSA_MODULUS_LENGTH_IN_BYTES : con 64; 4290*37da2899SCharles.ForsythSSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER : con 32767; 4291*37da2899SCharles.ForsythSSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER : con 16383; 4292*37da2899SCharles.Forsyth 4293*37da2899SCharles.Forsyth# Handshake Internal State 4294*37da2899SCharles.Forsyth 4295*37da2899SCharles.ForsythSSL2_STATE_CLIENT_HELLO, 4296*37da2899SCharles.Forsyth SSL2_STATE_SERVER_HELLO, 4297*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_MASTER_KEY, 4298*37da2899SCharles.Forsyth SSL2_STATE_SERVER_VERIFY, 4299*37da2899SCharles.Forsyth SSL2_STATE_REQUEST_CERTIFICATE, 4300*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_CERTIFICATE, 4301*37da2899SCharles.Forsyth SSL2_STATE_CLIENT_FINISHED, 4302*37da2899SCharles.Forsyth SSL2_STATE_SERVER_FINISHED, 4303*37da2899SCharles.Forsyth SSL2_STATE_ERROR : con iota; 4304*37da2899SCharles.Forsyth 4305*37da2899SCharles.Forsyth# The client's challenge to the server for the server to identify itself is a 4306*37da2899SCharles.Forsyth# (near) arbitary length random. The v3 server will right justify the challenge 4307*37da2899SCharles.Forsyth# data to become the ClientHello.random data (padding with leading zeros, if 4308*37da2899SCharles.Forsyth# necessary). If the length of the challenge is greater than 32 bytes, then only 4309*37da2899SCharles.Forsyth# the last 32 bytes are used. It is legitimate (but not necessary) for a v3 4310*37da2899SCharles.Forsyth# server to reject a v2 ClientHello that has fewer than 16 bytes of challenge 4311*37da2899SCharles.Forsyth# data. 4312*37da2899SCharles.Forsyth 4313*37da2899SCharles.ForsythSSL2_CHALLENGE_LENGTH : con 16; 4314*37da2899SCharles.Forsyth 4315*37da2899SCharles.ForsythV2Handshake: adt { 4316*37da2899SCharles.Forsyth pick { 4317*37da2899SCharles.Forsyth Error => 4318*37da2899SCharles.Forsyth code : array of byte; # [2]; 4319*37da2899SCharles.Forsyth ClientHello => 4320*37da2899SCharles.Forsyth version : array of byte; # [2] 4321*37da2899SCharles.Forsyth cipher_specs : array of byte; # [3] x 4322*37da2899SCharles.Forsyth session_id : array of byte; 4323*37da2899SCharles.Forsyth challenge : array of byte; 4324*37da2899SCharles.Forsyth ServerHello => 4325*37da2899SCharles.Forsyth session_id_hit : int; 4326*37da2899SCharles.Forsyth certificate_type : int; 4327*37da2899SCharles.Forsyth version : array of byte; # [2] 4328*37da2899SCharles.Forsyth certificate : array of byte; # only user certificate 4329*37da2899SCharles.Forsyth cipher_specs : array of byte; # [3] x 4330*37da2899SCharles.Forsyth connection_id : array of byte; 4331*37da2899SCharles.Forsyth ClientMasterKey => 4332*37da2899SCharles.Forsyth cipher_kind : array of byte; # [3] 4333*37da2899SCharles.Forsyth clear_key : array of byte; 4334*37da2899SCharles.Forsyth encrypt_key : array of byte; 4335*37da2899SCharles.Forsyth key_arg : array of byte; 4336*37da2899SCharles.Forsyth ServerVerify => 4337*37da2899SCharles.Forsyth challenge : array of byte; 4338*37da2899SCharles.Forsyth RequestCertificate => 4339*37da2899SCharles.Forsyth authentication_type : int; 4340*37da2899SCharles.Forsyth certificate_challenge : array of byte; 4341*37da2899SCharles.Forsyth ClientCertificate => 4342*37da2899SCharles.Forsyth certificate_type : int; 4343*37da2899SCharles.Forsyth certificate : array of byte; # only user certificate 4344*37da2899SCharles.Forsyth response : array of byte; 4345*37da2899SCharles.Forsyth ClientFinished => 4346*37da2899SCharles.Forsyth connection_id : array of byte; 4347*37da2899SCharles.Forsyth ServerFinished => 4348*37da2899SCharles.Forsyth session_id : array of byte; 4349*37da2899SCharles.Forsyth } 4350*37da2899SCharles.Forsyth 4351*37da2899SCharles.Forsyth encode: fn(hm: self ref V2Handshake): (array of byte, string); 4352*37da2899SCharles.Forsyth decode: fn(a: array of byte): (ref V2Handshake, string); 4353*37da2899SCharles.Forsyth tostring: fn(h: self ref V2Handshake): string; 4354*37da2899SCharles.Forsyth}; 4355*37da2899SCharles.Forsyth 4356*37da2899SCharles.Forsyth 4357*37da2899SCharles.ForsythV2Handshake.tostring(handshake: self ref V2Handshake): string 4358*37da2899SCharles.Forsyth{ 4359*37da2899SCharles.Forsyth info := ""; 4360*37da2899SCharles.Forsyth 4361*37da2899SCharles.Forsyth pick m := handshake { 4362*37da2899SCharles.Forsyth ClientHello => 4363*37da2899SCharles.Forsyth info += "\tClientHello\n" + 4364*37da2899SCharles.Forsyth "\tversion = \n\t\t" + bastr(m.version) + "\n" + 4365*37da2899SCharles.Forsyth "\tcipher_specs = \n\t\t" + bastr(m.cipher_specs) + "\n" + 4366*37da2899SCharles.Forsyth "\tsession_id = \n\t\t" + bastr(m.session_id) + "\n" + 4367*37da2899SCharles.Forsyth "\tchallenge = \n\t\t" + bastr(m.challenge) + "\n"; 4368*37da2899SCharles.Forsyth 4369*37da2899SCharles.Forsyth ServerHello => 4370*37da2899SCharles.Forsyth info += "\tServerHello\n" + 4371*37da2899SCharles.Forsyth "\tsession_id_hit = \n\t\t" + string m.session_id_hit + "\n" + 4372*37da2899SCharles.Forsyth "\tcertificate_type = \n\t\t" + string m.certificate_type + "\n" + 4373*37da2899SCharles.Forsyth "\tversion = \n\t\t" + bastr(m.version) + "\n" + 4374*37da2899SCharles.Forsyth "\tcertificate = \n\t\t" + bastr(m.certificate) + "\n" + 4375*37da2899SCharles.Forsyth "\tcipher_specs = \n\t\t" + bastr(m.cipher_specs) + "\n" + 4376*37da2899SCharles.Forsyth "\tconnection_id = \n\t\t" + bastr(m.connection_id) + "\n"; 4377*37da2899SCharles.Forsyth 4378*37da2899SCharles.Forsyth ClientMasterKey => 4379*37da2899SCharles.Forsyth info += "\tClientMasterKey\n" + 4380*37da2899SCharles.Forsyth "\tcipher_kind = \n\t\t" + bastr(m.cipher_kind) + "\n" + 4381*37da2899SCharles.Forsyth "\tclear_key = \n\t\t" + bastr(m.clear_key) + "\n" + 4382*37da2899SCharles.Forsyth "\tencrypt_key = \n\t\t" + bastr(m.encrypt_key) + "\n" + 4383*37da2899SCharles.Forsyth "\tkey_arg = \n\t\t" + bastr(m.key_arg) + "\n"; 4384*37da2899SCharles.Forsyth 4385*37da2899SCharles.Forsyth ServerVerify => 4386*37da2899SCharles.Forsyth info += "\tServerVerify\n" + 4387*37da2899SCharles.Forsyth "\tchallenge = \n\t\t" + bastr(m.challenge) + "\n"; 4388*37da2899SCharles.Forsyth 4389*37da2899SCharles.Forsyth RequestCertificate => 4390*37da2899SCharles.Forsyth info += "\tRequestCertificate\n" + 4391*37da2899SCharles.Forsyth "\tauthentication_type = \n\t\t" + string m.authentication_type + "\n" + 4392*37da2899SCharles.Forsyth "\tcertificate_challenge = \n\t\t" + bastr(m.certificate_challenge) + "\n"; 4393*37da2899SCharles.Forsyth 4394*37da2899SCharles.Forsyth ClientCertificate => 4395*37da2899SCharles.Forsyth info += "ClientCertificate\n" + 4396*37da2899SCharles.Forsyth "\tcertificate_type = \n\t\t" + string m.certificate_type + "\n" + 4397*37da2899SCharles.Forsyth "\tcertificate = \n\t\t" + bastr(m.certificate) + "\n" + 4398*37da2899SCharles.Forsyth "\tresponse = \n\t\t" + bastr(m.response) + "\n"; 4399*37da2899SCharles.Forsyth 4400*37da2899SCharles.Forsyth ClientFinished => 4401*37da2899SCharles.Forsyth info += "\tClientFinished\n" + 4402*37da2899SCharles.Forsyth "\tconnection_id = \n\t\t" + bastr(m.connection_id) + "\n"; 4403*37da2899SCharles.Forsyth 4404*37da2899SCharles.Forsyth ServerFinished => 4405*37da2899SCharles.Forsyth info += "\tServerFinished\n" + 4406*37da2899SCharles.Forsyth "\tsession_id = \n\t\t" + bastr(m.session_id) + "\n"; 4407*37da2899SCharles.Forsyth } 4408*37da2899SCharles.Forsyth 4409*37da2899SCharles.Forsyth return info; 4410*37da2899SCharles.Forsyth} 4411*37da2899SCharles.Forsyth 4412*37da2899SCharles.Forsyth 4413*37da2899SCharles.Forsyth# v2 handshake protocol - message driven, v2 and v3 sharing the same context stack 4414*37da2899SCharles.Forsyth 4415*37da2899SCharles.Forsythdo_v2handshake(v2hs: ref V2Handshake, ctx: ref Context): string 4416*37da2899SCharles.Forsyth{ 4417*37da2899SCharles.Forsyth e: string = nil; 4418*37da2899SCharles.Forsyth 4419*37da2899SCharles.Forsyth pick h := v2hs { 4420*37da2899SCharles.Forsyth Error => 4421*37da2899SCharles.Forsyth do_v2error(h, ctx); 4422*37da2899SCharles.Forsyth 4423*37da2899SCharles.Forsyth ClientHello => 4424*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_CLIENT_HELLO) { 4425*37da2899SCharles.Forsyth e = "V2ClientHello"; 4426*37da2899SCharles.Forsyth break; 4427*37da2899SCharles.Forsyth } 4428*37da2899SCharles.Forsyth do_v2client_hello(h, ctx); 4429*37da2899SCharles.Forsyth 4430*37da2899SCharles.Forsyth ServerHello => 4431*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_SERVER_HELLO) { 4432*37da2899SCharles.Forsyth e = "V2ServerHello"; 4433*37da2899SCharles.Forsyth break; 4434*37da2899SCharles.Forsyth } 4435*37da2899SCharles.Forsyth do_v2server_hello(h, ctx); 4436*37da2899SCharles.Forsyth 4437*37da2899SCharles.Forsyth ClientMasterKey => 4438*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_CLIENT_MASTER_KEY) { 4439*37da2899SCharles.Forsyth e = "V2ClientMasterKey"; 4440*37da2899SCharles.Forsyth break; 4441*37da2899SCharles.Forsyth } 4442*37da2899SCharles.Forsyth do_v2client_master_key(h, ctx); 4443*37da2899SCharles.Forsyth 4444*37da2899SCharles.Forsyth ServerVerify => 4445*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_SERVER_VERIFY) { 4446*37da2899SCharles.Forsyth e = "V2ServerVerify"; 4447*37da2899SCharles.Forsyth break; 4448*37da2899SCharles.Forsyth } 4449*37da2899SCharles.Forsyth do_v2server_verify(h, ctx); 4450*37da2899SCharles.Forsyth 4451*37da2899SCharles.Forsyth RequestCertificate => 4452*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_SERVER_VERIFY) { 4453*37da2899SCharles.Forsyth e = "V2RequestCertificate"; 4454*37da2899SCharles.Forsyth break; 4455*37da2899SCharles.Forsyth } 4456*37da2899SCharles.Forsyth do_v2req_cert(h, ctx); 4457*37da2899SCharles.Forsyth 4458*37da2899SCharles.Forsyth ClientCertificate => 4459*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_CLIENT_CERTIFICATE) { 4460*37da2899SCharles.Forsyth e = "V2ClientCertificate"; 4461*37da2899SCharles.Forsyth break; 4462*37da2899SCharles.Forsyth } 4463*37da2899SCharles.Forsyth do_v2client_certificate(h, ctx); 4464*37da2899SCharles.Forsyth 4465*37da2899SCharles.Forsyth ClientFinished => 4466*37da2899SCharles.Forsyth if((ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_CLIENT_FINISHED) { 4467*37da2899SCharles.Forsyth e = "V2ClientFinished"; 4468*37da2899SCharles.Forsyth break; 4469*37da2899SCharles.Forsyth } 4470*37da2899SCharles.Forsyth do_v2client_finished(h, ctx); 4471*37da2899SCharles.Forsyth 4472*37da2899SCharles.Forsyth ServerFinished => 4473*37da2899SCharles.Forsyth if(!(ctx.status & CLIENT_SIDE) || ctx.state != SSL2_STATE_SERVER_FINISHED) { 4474*37da2899SCharles.Forsyth e = "V2ServerFinished"; 4475*37da2899SCharles.Forsyth break; 4476*37da2899SCharles.Forsyth } 4477*37da2899SCharles.Forsyth do_v2server_finished(h, ctx); 4478*37da2899SCharles.Forsyth } 4479*37da2899SCharles.Forsyth 4480*37da2899SCharles.Forsyth return e; 4481*37da2899SCharles.Forsyth} 4482*37da2899SCharles.Forsyth 4483*37da2899SCharles.Forsythdo_v2error(v2hs: ref V2Handshake.Error, ctx: ref Context) 4484*37da2899SCharles.Forsyth{ 4485*37da2899SCharles.Forsyth if(SSL_DEBUG) 4486*37da2899SCharles.Forsyth log("do_v2error: " + string v2hs.code); 4487*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 4488*37da2899SCharles.Forsyth} 4489*37da2899SCharles.Forsyth 4490*37da2899SCharles.Forsyth# [server side] 4491*37da2899SCharles.Forsythdo_v2client_hello(v2hs: ref V2Handshake.ClientHello, ctx: ref Context) 4492*37da2899SCharles.Forsyth{ 4493*37da2899SCharles.Forsyth if(v2hs.version[0] != SSL2_CLIENT_VERSION[0] || v2hs.version[1] != SSL2_CLIENT_VERSION[1]) { 4494*37da2899SCharles.Forsyth # promote this message to v3 handshake protocol 4495*37da2899SCharles.Forsyth ctx.state = STATE_CLIENT_HELLO; 4496*37da2899SCharles.Forsyth return; 4497*37da2899SCharles.Forsyth } 4498*37da2899SCharles.Forsyth 4499*37da2899SCharles.Forsyth # trying to resume 4500*37da2899SCharles.Forsyth s: ref Session; 4501*37da2899SCharles.Forsyth if((v2hs.session_id != nil) && (ctx.status & SESSION_RESUMABLE)) 4502*37da2899SCharles.Forsyth s = sslsession->get_session_byid(v2hs.session_id); 4503*37da2899SCharles.Forsyth if(s != nil) { # found a hit 4504*37da2899SCharles.Forsyth # prepare and send v2 handshake hello message 4505*37da2899SCharles.Forsyth v2handshake_enque( 4506*37da2899SCharles.Forsyth ref V2Handshake.ServerHello( 4507*37da2899SCharles.Forsyth 1, # hit found 4508*37da2899SCharles.Forsyth 0, # no certificate required 4509*37da2899SCharles.Forsyth SSL2_SERVER_VERSION, 4510*37da2899SCharles.Forsyth nil, # no authetication required 4511*37da2899SCharles.Forsyth s.suite, # use hit session cipher kind 4512*37da2899SCharles.Forsyth ctx.server_random # connection_id 4513*37da2899SCharles.Forsyth ), 4514*37da2899SCharles.Forsyth ctx 4515*37da2899SCharles.Forsyth ); 4516*37da2899SCharles.Forsyth # TODO: should in supported cipher_kinds 4517*37da2899SCharles.Forsyth err: string; 4518*37da2899SCharles.Forsyth (ctx.sel_ciph, ctx.sel_keyx, ctx.sel_sign, err) 4519*37da2899SCharles.Forsyth = v2suite_to_spec(ctx.session.suite, SSL2_Cipher_Kinds); 4520*37da2899SCharles.Forsyth if(err != "") { 4521*37da2899SCharles.Forsyth if(SSL_DEBUG) 4522*37da2899SCharles.Forsyth log("do_v2client_hello: " + err); 4523*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4524*37da2899SCharles.Forsyth return; 4525*37da2899SCharles.Forsyth } 4526*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_SERVER_FINISHED; 4527*37da2899SCharles.Forsyth } 4528*37da2899SCharles.Forsyth else { 4529*37da2899SCharles.Forsyth # find matching cipher kinds 4530*37da2899SCharles.Forsyth n := len v2hs.cipher_specs; 4531*37da2899SCharles.Forsyth matchs := array [n] of byte; 4532*37da2899SCharles.Forsyth j, k: int = 0; 4533*37da2899SCharles.Forsyth while(j < n) { 4534*37da2899SCharles.Forsyth # ignore those not in SSL2_Cipher_Kinds 4535*37da2899SCharles.Forsyth matchs[k:] = v2hs.cipher_specs[j:j+3]; 4536*37da2899SCharles.Forsyth for(i := 0; i < len SSL2_Cipher_Kinds; i++) { 4537*37da2899SCharles.Forsyth ck := SSL2_Cipher_Kinds[i]; 4538*37da2899SCharles.Forsyth if(matchs[k] == ck[0] && matchs[k+1] == ck[1] && matchs[k+2] == ck[2]) 4539*37da2899SCharles.Forsyth k +=3; 4540*37da2899SCharles.Forsyth } 4541*37da2899SCharles.Forsyth j += 3; 4542*37da2899SCharles.Forsyth } 4543*37da2899SCharles.Forsyth if(k == 0) { 4544*37da2899SCharles.Forsyth if(SSL_DEBUG) 4545*37da2899SCharles.Forsyth log("do_v2client_hello: No matching cipher kind"); 4546*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4547*37da2899SCharles.Forsyth } 4548*37da2899SCharles.Forsyth else { 4549*37da2899SCharles.Forsyth matchs = matchs[0:k]; 4550*37da2899SCharles.Forsyth 4551*37da2899SCharles.Forsyth # Note: 4552*37da2899SCharles.Forsyth # v2 challenge -> v3 client_random 4553*37da2899SCharles.Forsyth # v2 connection_id -> v3 server_random 4554*37da2899SCharles.Forsyth 4555*37da2899SCharles.Forsyth chlen := len v2hs.challenge; 4556*37da2899SCharles.Forsyth if(chlen > 32) 4557*37da2899SCharles.Forsyth chlen = 32; 4558*37da2899SCharles.Forsyth ctx.client_random = array [chlen] of byte; 4559*37da2899SCharles.Forsyth if(chlen > 32) 4560*37da2899SCharles.Forsyth ctx.client_random[0:] = v2hs.challenge[chlen-32:]; 4561*37da2899SCharles.Forsyth else 4562*37da2899SCharles.Forsyth ctx.client_random[0:] = v2hs.challenge; 4563*37da2899SCharles.Forsyth ctx.server_random = random->randombuf(Random->NotQuiteRandom, 16); 4564*37da2899SCharles.Forsyth s.session_id = random->randombuf ( 4565*37da2899SCharles.Forsyth Random->NotQuiteRandom, 4566*37da2899SCharles.Forsyth SSL2_MAX_SESSION_ID_LENGTH_IN_BYTES 4567*37da2899SCharles.Forsyth ); 4568*37da2899SCharles.Forsyth s.suite = matchs; 4569*37da2899SCharles.Forsyth ctx.session = s; 4570*37da2899SCharles.Forsyth v2handshake_enque( 4571*37da2899SCharles.Forsyth ref V2Handshake.ServerHello( 4572*37da2899SCharles.Forsyth 0, # no hit - not resumable 4573*37da2899SCharles.Forsyth SSL2_CT_X509_CERTIFICATE, 4574*37da2899SCharles.Forsyth SSL2_SERVER_VERSION, 4575*37da2899SCharles.Forsyth hd ctx.local_info.certs, # the first is user certificate 4576*37da2899SCharles.Forsyth ctx.session.suite, # matched cipher kinds 4577*37da2899SCharles.Forsyth ctx.server_random # connection_id 4578*37da2899SCharles.Forsyth ), 4579*37da2899SCharles.Forsyth ctx 4580*37da2899SCharles.Forsyth ); 4581*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_CLIENT_MASTER_KEY; 4582*37da2899SCharles.Forsyth } 4583*37da2899SCharles.Forsyth } 4584*37da2899SCharles.Forsyth} 4585*37da2899SCharles.Forsyth 4586*37da2899SCharles.Forsyth# [client side] 4587*37da2899SCharles.Forsyth 4588*37da2899SCharles.Forsythdo_v2server_hello(v2hs: ref V2Handshake.ServerHello, ctx: ref Context) 4589*37da2899SCharles.Forsyth{ 4590*37da2899SCharles.Forsyth # must be v2 server hello otherwise it will be v3 server hello 4591*37da2899SCharles.Forsyth # determined by auto record layer version detection 4592*37da2899SCharles.Forsyth if(v2hs.version[0] != SSL2_SERVER_VERSION[0] 4593*37da2899SCharles.Forsyth || v2hs.version[1] != SSL2_SERVER_VERSION[1]) { 4594*37da2899SCharles.Forsyth if(SSL_DEBUG) 4595*37da2899SCharles.Forsyth log("do_v2server_hello: not a v2 version"); 4596*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4597*37da2899SCharles.Forsyth return; 4598*37da2899SCharles.Forsyth } 4599*37da2899SCharles.Forsyth 4600*37da2899SCharles.Forsyth ctx.session.version = SSL2_SERVER_VERSION; 4601*37da2899SCharles.Forsyth ctx.server_random = v2hs.connection_id; 4602*37da2899SCharles.Forsyth 4603*37da2899SCharles.Forsyth # check if a resumable session is found 4604*37da2899SCharles.Forsyth if(v2hs.session_id_hit != 0) { # resume ok 4605*37da2899SCharles.Forsyth err: string; 4606*37da2899SCharles.Forsyth # TODO: should in supported cipher_kinds 4607*37da2899SCharles.Forsyth (ctx.sel_ciph, nil, nil, err) = v2suite_to_spec(ctx.session.suite, SSL2_Cipher_Kinds); 4608*37da2899SCharles.Forsyth if(err != "") { 4609*37da2899SCharles.Forsyth if(SSL_DEBUG) 4610*37da2899SCharles.Forsyth log("do_v2server_hello: " + err); 4611*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4612*37da2899SCharles.Forsyth return; 4613*37da2899SCharles.Forsyth } 4614*37da2899SCharles.Forsyth } 4615*37da2899SCharles.Forsyth else { # not resumable session 4616*37da2899SCharles.Forsyth 4617*37da2899SCharles.Forsyth # use the first matched cipher kind; install cipher spec 4618*37da2899SCharles.Forsyth if(len v2hs.cipher_specs < 3) { 4619*37da2899SCharles.Forsyth if(SSL_DEBUG) 4620*37da2899SCharles.Forsyth log("do_v2server_hello: too few bytes"); 4621*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4622*37da2899SCharles.Forsyth return; 4623*37da2899SCharles.Forsyth } 4624*37da2899SCharles.Forsyth ctx.session.suite = array [3] of byte; 4625*37da2899SCharles.Forsyth ctx.session.suite[0:] = v2hs.cipher_specs[0:3]; 4626*37da2899SCharles.Forsyth err: string; 4627*37da2899SCharles.Forsyth (ctx.sel_ciph, nil, nil, err) = v2suite_to_spec(ctx.session.suite, SSL2_Cipher_Kinds); 4628*37da2899SCharles.Forsyth if(err != "") { 4629*37da2899SCharles.Forsyth if(SSL_DEBUG) 4630*37da2899SCharles.Forsyth log("do_v2server_hello: " + err); 4631*37da2899SCharles.Forsyth return; 4632*37da2899SCharles.Forsyth } 4633*37da2899SCharles.Forsyth 4634*37da2899SCharles.Forsyth # decode x509 certificates, authenticate server and extract 4635*37da2899SCharles.Forsyth # public key from server certificate 4636*37da2899SCharles.Forsyth if(v2hs.certificate_type != int SSL2_CT_X509_CERTIFICATE) { 4637*37da2899SCharles.Forsyth if(SSL_DEBUG) 4638*37da2899SCharles.Forsyth log("do_v2server_hello: not x509 certificate"); 4639*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4640*37da2899SCharles.Forsyth return; 4641*37da2899SCharles.Forsyth } 4642*37da2899SCharles.Forsyth ctx.session.peer_certs = v2hs.certificate :: nil; 4643*37da2899SCharles.Forsyth # TODO: decode v2hs.certificate as list of certificate 4644*37da2899SCharles.Forsyth # verify the list of certificate 4645*37da2899SCharles.Forsyth (e, signed) := x509->Signed.decode(v2hs.certificate); 4646*37da2899SCharles.Forsyth if(e != "") { 4647*37da2899SCharles.Forsyth if(SSL_DEBUG) 4648*37da2899SCharles.Forsyth log("do_v2server_hello: " + e); 4649*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4650*37da2899SCharles.Forsyth return; 4651*37da2899SCharles.Forsyth } 4652*37da2899SCharles.Forsyth certificate: ref Certificate; 4653*37da2899SCharles.Forsyth (e, certificate) = x509->Certificate.decode(signed.tobe_signed); 4654*37da2899SCharles.Forsyth if(e != "") { 4655*37da2899SCharles.Forsyth if(SSL_DEBUG) 4656*37da2899SCharles.Forsyth log("do_v2server_hello: " + e); 4657*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4658*37da2899SCharles.Forsyth return; 4659*37da2899SCharles.Forsyth } 4660*37da2899SCharles.Forsyth id: int; 4661*37da2899SCharles.Forsyth peer_pk: ref X509->PublicKey; 4662*37da2899SCharles.Forsyth (e, id, peer_pk) = certificate.subject_pkinfo.getPublicKey(); 4663*37da2899SCharles.Forsyth if(e != nil) { 4664*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; # protocol error 4665*37da2899SCharles.Forsyth return; 4666*37da2899SCharles.Forsyth } 4667*37da2899SCharles.Forsyth pk: ref RSAKey; 4668*37da2899SCharles.Forsyth pick key := peer_pk { 4669*37da2899SCharles.Forsyth RSA => 4670*37da2899SCharles.Forsyth pk = key.pk; 4671*37da2899SCharles.Forsyth * => 4672*37da2899SCharles.Forsyth } 4673*37da2899SCharles.Forsyth # prepare and send client master key message 4674*37da2899SCharles.Forsyth # TODO: change CipherSpec adt for more key info 4675*37da2899SCharles.Forsyth # Temporary solution 4676*37da2899SCharles.Forsyth # mkey (master key), ckey (clear key), skey(secret key) 4677*37da2899SCharles.Forsyth mkey, ckey, skey, keyarg: array of byte; 4678*37da2899SCharles.Forsyth (mkeylen, ckeylen, keyarglen) := v2suite_more(ctx.sel_ciph); 4679*37da2899SCharles.Forsyth mkey = random->randombuf(Random->NotQuiteRandom, mkeylen); 4680*37da2899SCharles.Forsyth if(ckeylen != 0) 4681*37da2899SCharles.Forsyth ckey = mkey[0:ckeylen]; 4682*37da2899SCharles.Forsyth if(mkeylen > ckeylen) 4683*37da2899SCharles.Forsyth skey = mkey[ckeylen:]; 4684*37da2899SCharles.Forsyth if(keyarglen > 0) 4685*37da2899SCharles.Forsyth keyarg = random->randombuf(Random->NotQuiteRandom, keyarglen); 4686*37da2899SCharles.Forsyth ekey: array of byte; 4687*37da2899SCharles.Forsyth (e, ekey) = pkcs->rsa_encrypt(skey, pk, 2); 4688*37da2899SCharles.Forsyth if(e != nil) { 4689*37da2899SCharles.Forsyth if(SSL_DEBUG) 4690*37da2899SCharles.Forsyth log("do_v2server_hello: " + e); 4691*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4692*37da2899SCharles.Forsyth return; 4693*37da2899SCharles.Forsyth } 4694*37da2899SCharles.Forsyth ctx.session.master_secret = mkey; 4695*37da2899SCharles.Forsyth v2handshake_enque( 4696*37da2899SCharles.Forsyth ref V2Handshake.ClientMasterKey(ctx.session.suite, ckey, ekey, keyarg), 4697*37da2899SCharles.Forsyth ctx 4698*37da2899SCharles.Forsyth ); 4699*37da2899SCharles.Forsyth } 4700*37da2899SCharles.Forsyth 4701*37da2899SCharles.Forsyth # clean up out_queue before switch cipher 4702*37da2899SCharles.Forsyth record_write_queue(ctx); 4703*37da2899SCharles.Forsyth ctx.out_queue.data = nil; 4704*37da2899SCharles.Forsyth 4705*37da2899SCharles.Forsyth # install keys onto ctx that will be pushed on ssl record when ready 4706*37da2899SCharles.Forsyth (ctx.cw_mac, ctx.sw_mac, ctx.cw_key, ctx.sw_key, ctx.cw_IV, ctx.sw_IV) 4707*37da2899SCharles.Forsyth = v2calc_keys(ctx.sel_ciph, ctx.session.master_secret, 4708*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 4709*37da2899SCharles.Forsyth e := set_queues(ctx); 4710*37da2899SCharles.Forsyth if(e != "") { 4711*37da2899SCharles.Forsyth if(SSL_DEBUG) 4712*37da2899SCharles.Forsyth log("do_v2server_finished: " + e); 4713*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4714*37da2899SCharles.Forsyth return; 4715*37da2899SCharles.Forsyth } 4716*37da2899SCharles.Forsyth ctx.status |= IN_READY; 4717*37da2899SCharles.Forsyth ctx.status |= OUT_READY; 4718*37da2899SCharles.Forsyth 4719*37da2899SCharles.Forsyth # prepare and send client finished message 4720*37da2899SCharles.Forsyth v2handshake_enque( 4721*37da2899SCharles.Forsyth ref V2Handshake.ClientFinished(ctx.server_random), # as connection_id 4722*37da2899SCharles.Forsyth ctx 4723*37da2899SCharles.Forsyth ); 4724*37da2899SCharles.Forsyth 4725*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_SERVER_VERIFY; 4726*37da2899SCharles.Forsyth} 4727*37da2899SCharles.Forsyth 4728*37da2899SCharles.Forsyth# [server side] 4729*37da2899SCharles.Forsyth 4730*37da2899SCharles.Forsythdo_v2client_master_key(v2hs: ref V2Handshake.ClientMasterKey, ctx: ref Context) 4731*37da2899SCharles.Forsyth{ 4732*37da2899SCharles.Forsyth #if(cmk.cipher == -1 || cipher_info[cmk.cipher].cryptalg == -1) { 4733*37da2899SCharles.Forsyth # # return ("protocol error: bad cipher in masterkey", nullc); 4734*37da2899SCharles.Forsyth # ctx.state = SSL2_STATE_ERROR; # protocol error 4735*37da2899SCharles.Forsyth # return; 4736*37da2899SCharles.Forsyth #} 4737*37da2899SCharles.Forsyth 4738*37da2899SCharles.Forsyth ctx.session.suite = v2hs.cipher_kind; 4739*37da2899SCharles.Forsyth 4740*37da2899SCharles.Forsyth # TODO: 4741*37da2899SCharles.Forsyth # someplace shall be able to install the key 4742*37da2899SCharles.Forsyth # need further encapsulate encrypt and decrypt functions from KeyExAlg adt 4743*37da2899SCharles.Forsyth master_key_length: int; 4744*37da2899SCharles.Forsyth secret_key: array of byte; 4745*37da2899SCharles.Forsyth pick alg := ctx.sel_keyx { 4746*37da2899SCharles.Forsyth RSA => 4747*37da2899SCharles.Forsyth e: string; 4748*37da2899SCharles.Forsyth (e, secret_key) = pkcs->rsa_decrypt(v2hs.encrypt_key, alg.sk, 0); 4749*37da2899SCharles.Forsyth if(e != "") { 4750*37da2899SCharles.Forsyth if(SSL_DEBUG) 4751*37da2899SCharles.Forsyth log("do_v2client_master_key: " + e); 4752*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4753*37da2899SCharles.Forsyth return; 4754*37da2899SCharles.Forsyth } 4755*37da2899SCharles.Forsyth master_key_length = len v2hs.clear_key + len secret_key; 4756*37da2899SCharles.Forsyth * => 4757*37da2899SCharles.Forsyth if(SSL_DEBUG) 4758*37da2899SCharles.Forsyth log("do_v2client_master_key: unknown public key algorithm"); 4759*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4760*37da2899SCharles.Forsyth return; 4761*37da2899SCharles.Forsyth } 4762*37da2899SCharles.Forsyth #TODO: do the following lines after modifying the CipherSpec adt 4763*37da2899SCharles.Forsyth #if(master_key_length != ci.keylen) { 4764*37da2899SCharles.Forsyth # ctx.state = SSL2_STATE_ERROR; # protocol error 4765*37da2899SCharles.Forsyth # return; 4766*37da2899SCharles.Forsyth #} 4767*37da2899SCharles.Forsyth 4768*37da2899SCharles.Forsyth ctx.session.master_secret = array [master_key_length] of byte; 4769*37da2899SCharles.Forsyth ctx.session.master_secret[0:] = v2hs.clear_key; 4770*37da2899SCharles.Forsyth ctx.session.master_secret[len v2hs.clear_key:] = secret_key; 4771*37da2899SCharles.Forsyth 4772*37da2899SCharles.Forsyth # install keys onto ctx that will be pushed on ssl record when ready 4773*37da2899SCharles.Forsyth (ctx.cw_mac, ctx.sw_mac, ctx.cw_key, ctx.sw_key, ctx.cw_IV, ctx.sw_IV) 4774*37da2899SCharles.Forsyth = v2calc_keys(ctx.sel_ciph, ctx.session.master_secret, 4775*37da2899SCharles.Forsyth ctx.client_random, ctx.server_random); 4776*37da2899SCharles.Forsyth v2handshake_enque( 4777*37da2899SCharles.Forsyth ref V2Handshake.ServerVerify(ctx.client_random[16:]), 4778*37da2899SCharles.Forsyth ctx 4779*37da2899SCharles.Forsyth ); 4780*37da2899SCharles.Forsyth v2handshake_enque( 4781*37da2899SCharles.Forsyth ref V2Handshake.ServerFinished(ctx.session.session_id), 4782*37da2899SCharles.Forsyth ctx 4783*37da2899SCharles.Forsyth ); 4784*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_CLIENT_FINISHED; 4785*37da2899SCharles.Forsyth} 4786*37da2899SCharles.Forsyth 4787*37da2899SCharles.Forsyth# used by client side 4788*37da2899SCharles.Forsythdo_v2server_verify(v2hs: ref V2Handshake.ServerVerify, ctx: ref Context) 4789*37da2899SCharles.Forsyth{ 4790*37da2899SCharles.Forsyth # TODO: 4791*37da2899SCharles.Forsyth # the challenge length may not be 16 bytes 4792*37da2899SCharles.Forsyth if(bytes_cmp(v2hs.challenge, ctx.client_random[32-SSL2_CHALLENGE_LENGTH:]) < 0) { 4793*37da2899SCharles.Forsyth if(SSL_DEBUG) 4794*37da2899SCharles.Forsyth log("do_v2server_verify: challenge mismatch"); 4795*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4796*37da2899SCharles.Forsyth return; 4797*37da2899SCharles.Forsyth } 4798*37da2899SCharles.Forsyth 4799*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_SERVER_FINISHED; 4800*37da2899SCharles.Forsyth} 4801*37da2899SCharles.Forsyth 4802*37da2899SCharles.Forsyth# [client side] 4803*37da2899SCharles.Forsyth 4804*37da2899SCharles.Forsythdo_v2req_cert(v2hs: ref V2Handshake.RequestCertificate, ctx: ref Context) 4805*37da2899SCharles.Forsyth{ 4806*37da2899SCharles.Forsyth # not supported until v3 4807*37da2899SCharles.Forsyth if(SSL_DEBUG) 4808*37da2899SCharles.Forsyth log("do_v2req_cert: authenticate client not supported"); 4809*37da2899SCharles.Forsyth v2hs = nil; 4810*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4811*37da2899SCharles.Forsyth} 4812*37da2899SCharles.Forsyth 4813*37da2899SCharles.Forsyth# [server side] 4814*37da2899SCharles.Forsyth 4815*37da2899SCharles.Forsythdo_v2client_certificate(v2hs: ref V2Handshake.ClientCertificate, ctx: ref Context) 4816*37da2899SCharles.Forsyth{ 4817*37da2899SCharles.Forsyth # not supported until v3 4818*37da2899SCharles.Forsyth if(SSL_DEBUG) 4819*37da2899SCharles.Forsyth log("do_v2client_certificate: authenticate client not supported"); 4820*37da2899SCharles.Forsyth v2handshake_enque ( 4821*37da2899SCharles.Forsyth ref V2Handshake.Error(SSL2_PE_NO_CERTIFICATE), 4822*37da2899SCharles.Forsyth ctx 4823*37da2899SCharles.Forsyth ); 4824*37da2899SCharles.Forsyth v2hs = nil; 4825*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4826*37da2899SCharles.Forsyth} 4827*37da2899SCharles.Forsyth 4828*37da2899SCharles.Forsyth# [server side] 4829*37da2899SCharles.Forsyth 4830*37da2899SCharles.Forsythdo_v2client_finished(v2hs: ref V2Handshake.ClientFinished, ctx: ref Context) 4831*37da2899SCharles.Forsyth{ 4832*37da2899SCharles.Forsyth if(bytes_cmp(ctx.server_random, v2hs.connection_id) < 0) { 4833*37da2899SCharles.Forsyth ctx.session.session_id = nil; 4834*37da2899SCharles.Forsyth if(SSL_DEBUG) 4835*37da2899SCharles.Forsyth log("do_v2client_finished: connection id mismatch"); 4836*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4837*37da2899SCharles.Forsyth } 4838*37da2899SCharles.Forsyth # TODO: 4839*37da2899SCharles.Forsyth # the challenge length may not be 16 bytes 4840*37da2899SCharles.Forsyth v2handshake_enque( 4841*37da2899SCharles.Forsyth ref V2Handshake.ServerVerify(ctx.client_random[32-SSL2_CHALLENGE_LENGTH:]), 4842*37da2899SCharles.Forsyth ctx 4843*37da2899SCharles.Forsyth ); 4844*37da2899SCharles.Forsyth if(ctx.session.session_id == nil) 4845*37da2899SCharles.Forsyth ctx.session.session_id = random->randombuf(Random->NotQuiteRandom, 16); 4846*37da2899SCharles.Forsyth v2handshake_enque( 4847*37da2899SCharles.Forsyth ref V2Handshake.ServerFinished(ctx.session.session_id), 4848*37da2899SCharles.Forsyth ctx 4849*37da2899SCharles.Forsyth ); 4850*37da2899SCharles.Forsyth e := set_queues(ctx); 4851*37da2899SCharles.Forsyth if(e != "") { 4852*37da2899SCharles.Forsyth if(SSL_DEBUG) 4853*37da2899SCharles.Forsyth log("do_v2client_finished: " + e); 4854*37da2899SCharles.Forsyth ctx.state = SSL2_STATE_ERROR; 4855*37da2899SCharles.Forsyth return; 4856*37da2899SCharles.Forsyth } 4857*37da2899SCharles.Forsyth ctx.status |= IN_READY; 4858*37da2899SCharles.Forsyth ctx.status |= OUT_READY; 4859*37da2899SCharles.Forsyth sslsession->add_session(ctx.session); 4860*37da2899SCharles.Forsyth 4861*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 4862*37da2899SCharles.Forsyth} 4863*37da2899SCharles.Forsyth 4864*37da2899SCharles.Forsyth# [client side] 4865*37da2899SCharles.Forsyth 4866*37da2899SCharles.Forsythdo_v2server_finished(v2hs: ref V2Handshake.ServerFinished, ctx: ref Context) 4867*37da2899SCharles.Forsyth{ 4868*37da2899SCharles.Forsyth if(ctx.session.session_id == nil) 4869*37da2899SCharles.Forsyth ctx.session.session_id = array [16] of byte; 4870*37da2899SCharles.Forsyth ctx.session.session_id[0:] = v2hs.session_id[0:]; 4871*37da2899SCharles.Forsyth 4872*37da2899SCharles.Forsyth sslsession->add_session(ctx.session); 4873*37da2899SCharles.Forsyth 4874*37da2899SCharles.Forsyth ctx.state = STATE_EXIT; 4875*37da2899SCharles.Forsyth} 4876*37da2899SCharles.Forsyth 4877*37da2899SCharles.Forsyth 4878*37da2899SCharles.Forsyth# Note: 4879*37da2899SCharles.Forsyth# the key partitioning for v2 is different from v3 4880*37da2899SCharles.Forsyth 4881*37da2899SCharles.Forsythv2calc_keys(ciph: ref CipherSpec, ms, cr, sr: array of byte) 4882*37da2899SCharles.Forsyth : (array of byte, array of byte, array of byte, array of byte, array of byte, array of byte) 4883*37da2899SCharles.Forsyth{ 4884*37da2899SCharles.Forsyth cw_mac, sw_mac, cw_key, sw_key, cw_IV, sw_IV: array of byte; 4885*37da2899SCharles.Forsyth 4886*37da2899SCharles.Forsyth # TODO: check the size of key block if IV exists 4887*37da2899SCharles.Forsyth (mkeylen, ckeylen, keyarglen) := v2suite_more(ciph); 4888*37da2899SCharles.Forsyth kblen := 2*mkeylen; 4889*37da2899SCharles.Forsyth if(kblen%Keyring->MD5dlen != 0) { 4890*37da2899SCharles.Forsyth if(SSL_DEBUG) 4891*37da2899SCharles.Forsyth log("v2calc_keys: key block length is not multiple of MD5 hash length"); 4892*37da2899SCharles.Forsyth } 4893*37da2899SCharles.Forsyth else { 4894*37da2899SCharles.Forsyth key_block := array [kblen] of byte; 4895*37da2899SCharles.Forsyth 4896*37da2899SCharles.Forsyth challenge := cr[32-SSL2_CHALLENGE_LENGTH:32]; # TODO: if challenge length != 16 ? 4897*37da2899SCharles.Forsyth connection_id := sr[0:16]; # TODO: if connection_id length != 16 ? 4898*37da2899SCharles.Forsyth var := array [1] of byte; 4899*37da2899SCharles.Forsyth var[0] = byte 16r30; 4900*37da2899SCharles.Forsyth i := 0; 4901*37da2899SCharles.Forsyth while(i < kblen) { 4902*37da2899SCharles.Forsyth (hash, nil) := md5_hash(ms::var::challenge::connection_id::nil, nil); 4903*37da2899SCharles.Forsyth key_block[i:] = hash; 4904*37da2899SCharles.Forsyth i += Keyring->MD5dlen; 4905*37da2899SCharles.Forsyth ++var[0]; 4906*37da2899SCharles.Forsyth } 4907*37da2899SCharles.Forsyth 4908*37da2899SCharles.Forsyth if(SSL_DEBUG) 4909*37da2899SCharles.Forsyth log("ssl3: calc_keys:" 4910*37da2899SCharles.Forsyth + "\n\tmaster key = \n\t\t" + bastr(ms) 4911*37da2899SCharles.Forsyth + "\n\tchallenge = \n\t\t" + bastr(challenge) 4912*37da2899SCharles.Forsyth + "\n\tconnection id = \n\t\t" + bastr(connection_id) 4913*37da2899SCharles.Forsyth + "\n\tkey block = \n\t\t" + bastr(key_block) + "\n"); 4914*37da2899SCharles.Forsyth 4915*37da2899SCharles.Forsyth i = 0; 4916*37da2899SCharles.Forsyth # server write key == client read key 4917*37da2899SCharles.Forsyth # server write mac == server write key 4918*37da2899SCharles.Forsyth sw_key = array [mkeylen] of byte; 4919*37da2899SCharles.Forsyth sw_key[0:] = key_block[i:mkeylen]; 4920*37da2899SCharles.Forsyth sw_mac = array [mkeylen] of byte; 4921*37da2899SCharles.Forsyth sw_mac[0:] = key_block[i:mkeylen]; 4922*37da2899SCharles.Forsyth # client write key == server read key 4923*37da2899SCharles.Forsyth # client write mac == client write key 4924*37da2899SCharles.Forsyth i += mkeylen; 4925*37da2899SCharles.Forsyth cw_key = array [mkeylen] of byte; 4926*37da2899SCharles.Forsyth cw_key[0:] = key_block[i:i+mkeylen]; 4927*37da2899SCharles.Forsyth cw_mac = array [mkeylen] of byte; 4928*37da2899SCharles.Forsyth cw_mac[0:] = key_block[i:i+mkeylen]; 4929*37da2899SCharles.Forsyth # client IV == server IV 4930*37da2899SCharles.Forsyth # Note: 4931*37da2899SCharles.Forsyth # IV is a part of writing or reading key for ssl device 4932*37da2899SCharles.Forsyth # this is composed again in setctl 4933*37da2899SCharles.Forsyth cw_IV = array [keyarglen] of byte; 4934*37da2899SCharles.Forsyth cw_IV[0:] = ms[mkeylen:mkeylen+keyarglen]; 4935*37da2899SCharles.Forsyth sw_IV = array [keyarglen] of byte; 4936*37da2899SCharles.Forsyth sw_IV[0:] = ms[mkeylen:mkeylen+keyarglen]; 4937*37da2899SCharles.Forsyth } 4938*37da2899SCharles.Forsyth 4939*37da2899SCharles.Forsyth if(SSL_DEBUG) 4940*37da2899SCharles.Forsyth log("ssl3: calc_keys:" 4941*37da2899SCharles.Forsyth + "\n\tclient_write_mac = \n\t\t" + bastr(cw_mac) 4942*37da2899SCharles.Forsyth + "\n\tserver_write_mac = \n\t\t" + bastr(sw_mac) 4943*37da2899SCharles.Forsyth + "\n\tclient_write_key = \n\t\t" + bastr(cw_key) 4944*37da2899SCharles.Forsyth + "\n\tserver_write_key = \n\t\t" + bastr(sw_key) 4945*37da2899SCharles.Forsyth + "\n\tclient_write_IV = \n\t\t" + bastr(cw_IV) 4946*37da2899SCharles.Forsyth + "\n\tserver_write_IV = \n\t\t" + bastr(sw_IV) + "\n"); 4947*37da2899SCharles.Forsyth 4948*37da2899SCharles.Forsyth return (cw_mac, sw_mac, cw_key, sw_key, cw_IV, sw_IV); 4949*37da2899SCharles.Forsyth} 4950*37da2899SCharles.Forsyth 4951*37da2899SCharles.Forsythv3tov2specs(suites: array of byte): array of byte 4952*37da2899SCharles.Forsyth{ 4953*37da2899SCharles.Forsyth # v3 suite codes are 2 bytes each, v2 codes are 3 bytes 4954*37da2899SCharles.Forsyth n := len suites / 2; 4955*37da2899SCharles.Forsyth kinds := array [n*3*2] of byte; 4956*37da2899SCharles.Forsyth k := 0; 4957*37da2899SCharles.Forsyth for(i := 0; i < n;) { 4958*37da2899SCharles.Forsyth a := suites[i:i+2]; 4959*37da2899SCharles.Forsyth i += 2; 4960*37da2899SCharles.Forsyth m := len SSL3_Suites; 4961*37da2899SCharles.Forsyth for(j := 0; j < m; j++) { 4962*37da2899SCharles.Forsyth b := SSL3_Suites[j]; 4963*37da2899SCharles.Forsyth if(a[0]==b[0] && a[1]==b[1]) 4964*37da2899SCharles.Forsyth break; 4965*37da2899SCharles.Forsyth } 4966*37da2899SCharles.Forsyth if (j == m) { 4967*37da2899SCharles.Forsyth if(SSL_DEBUG) 4968*37da2899SCharles.Forsyth log("ssl3: unknown v3 suite"); 4969*37da2899SCharles.Forsyth continue; 4970*37da2899SCharles.Forsyth } 4971*37da2899SCharles.Forsyth case j { 4972*37da2899SCharles.Forsyth RSA_EXPORT_WITH_RC4_40_MD5 => 4973*37da2899SCharles.Forsyth kinds[k:] = SSL2_Cipher_Kinds[SSL2_CK_RC4_128_EXPORT40_WITH_MD5]; 4974*37da2899SCharles.Forsyth k += 3; 4975*37da2899SCharles.Forsyth RSA_WITH_RC4_128_MD5 => 4976*37da2899SCharles.Forsyth kinds[k:] = SSL2_Cipher_Kinds[SSL2_CK_RC4_128_WITH_MD5]; 4977*37da2899SCharles.Forsyth k += 3; 4978*37da2899SCharles.Forsyth RSA_WITH_IDEA_CBC_SHA => 4979*37da2899SCharles.Forsyth kinds[k:] = SSL2_Cipher_Kinds[SSL2_CK_IDEA_128_CBC_WITH_MD5]; 4980*37da2899SCharles.Forsyth k += 3; 4981*37da2899SCharles.Forsyth RSA_WITH_DES_CBC_SHA => 4982*37da2899SCharles.Forsyth ; 4983*37da2899SCharles.Forsyth * => 4984*37da2899SCharles.Forsyth if(SSL_DEBUG) 4985*37da2899SCharles.Forsyth log("ssl3: unable to convert v3 suite to v2 kind"); 4986*37da2899SCharles.Forsyth } 4987*37da2899SCharles.Forsyth # append v3 code in v2-safe manner 4988*37da2899SCharles.Forsyth # (suite[0] == 0) => will be ignored by v2 server, picked up by v3 server 4989*37da2899SCharles.Forsyth kinds[k] = byte 16r00; 4990*37da2899SCharles.Forsyth kinds[k+1:] = SSL3_Suites[j]; 4991*37da2899SCharles.Forsyth k += 3; 4992*37da2899SCharles.Forsyth } 4993*37da2899SCharles.Forsyth return kinds[0:k]; 4994*37da2899SCharles.Forsyth} 4995*37da2899SCharles.Forsyth 4996*37da2899SCharles.Forsythv2suite_to_spec(cs: array of byte, cipher_kinds: array of array of byte) 4997*37da2899SCharles.Forsyth : (ref CipherSpec, ref KeyExAlg, ref SigAlg, string) 4998*37da2899SCharles.Forsyth{ 4999*37da2899SCharles.Forsyth cip : ref CipherSpec; 5000*37da2899SCharles.Forsyth kex : ref KeyExAlg; 5001*37da2899SCharles.Forsyth sig : ref SigAlg; 5002*37da2899SCharles.Forsyth 5003*37da2899SCharles.Forsyth n := len cipher_kinds; 5004*37da2899SCharles.Forsyth for(i := 0; i < n; i++) { 5005*37da2899SCharles.Forsyth found := cipher_kinds[i]; 5006*37da2899SCharles.Forsyth if(found[0]==cs[0] && found[1]==cs[1] && found[2]==cs[2]) break; 5007*37da2899SCharles.Forsyth } 5008*37da2899SCharles.Forsyth 5009*37da2899SCharles.Forsyth if(i == n) 5010*37da2899SCharles.Forsyth return (nil, nil, nil, "fail to find a matched spec"); 5011*37da2899SCharles.Forsyth 5012*37da2899SCharles.Forsyth case i { 5013*37da2899SCharles.Forsyth SSL2_CK_RC4_128_WITH_MD5 => 5014*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC4, SSL_STREAM_CIPHER, 5015*37da2899SCharles.Forsyth 16, 0, SSL_MD5, Keyring->MD4dlen); 5016*37da2899SCharles.Forsyth 5017*37da2899SCharles.Forsyth SSL2_CK_RC4_128_EXPORT40_WITH_MD5 => 5018*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_RC4, SSL_STREAM_CIPHER, 5019*37da2899SCharles.Forsyth 5, 0, SSL_MD5, Keyring->MD4dlen); 5020*37da2899SCharles.Forsyth 5021*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_WITH_MD5 => 5022*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_RC2_CBC, SSL_BLOCK_CIPHER, 5023*37da2899SCharles.Forsyth 16, 8, SSL_MD5, Keyring->MD4dlen); 5024*37da2899SCharles.Forsyth 5025*37da2899SCharles.Forsyth SSL2_CK_RC2_CBC_128_CBC_EXPORT40_WITH_MD5 => 5026*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_TRUE, SSL_RC2_CBC, SSL_BLOCK_CIPHER, 5027*37da2899SCharles.Forsyth 5, 8, SSL_MD5, Keyring->MD4dlen); 5028*37da2899SCharles.Forsyth 5029*37da2899SCharles.Forsyth SSL2_CK_IDEA_128_CBC_WITH_MD5 => 5030*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_IDEA_CBC, SSL_BLOCK_CIPHER, 5031*37da2899SCharles.Forsyth 16, 8, SSL_MD5, Keyring->MD4dlen); 5032*37da2899SCharles.Forsyth 5033*37da2899SCharles.Forsyth SSL2_CK_DES_64_CBC_WITH_MD5 => 5034*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_DES_CBC, SSL_BLOCK_CIPHER, 5035*37da2899SCharles.Forsyth 8, 8, SSL_MD5, Keyring->MD4dlen); 5036*37da2899SCharles.Forsyth 5037*37da2899SCharles.Forsyth SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 => 5038*37da2899SCharles.Forsyth cip = ref CipherSpec(SSL_EXPORT_FALSE, SSL_3DES_EDE_CBC, SSL_BLOCK_CIPHER, 5039*37da2899SCharles.Forsyth 24, 8, SSL_MD5, Keyring->MD4dlen); 5040*37da2899SCharles.Forsyth } 5041*37da2899SCharles.Forsyth 5042*37da2899SCharles.Forsyth kex = ref KeyExAlg.RSA(nil, nil, nil); 5043*37da2899SCharles.Forsyth sig = ref SigAlg.RSA(nil, nil); 5044*37da2899SCharles.Forsyth 5045*37da2899SCharles.Forsyth return (cip, kex, sig, nil); 5046*37da2899SCharles.Forsyth} 5047*37da2899SCharles.Forsyth 5048*37da2899SCharles.Forsythv2suite_more(ciph: ref CipherSpec): (int, int, int) 5049*37da2899SCharles.Forsyth{ 5050*37da2899SCharles.Forsyth mkeylen, ckeylen, keyarglen: int; 5051*37da2899SCharles.Forsyth 5052*37da2899SCharles.Forsyth case ciph.bulk_cipher_algorithm { 5053*37da2899SCharles.Forsyth SSL_RC4 => 5054*37da2899SCharles.Forsyth mkeylen = 16; 5055*37da2899SCharles.Forsyth if(ciph.key_material == 5) 5056*37da2899SCharles.Forsyth ckeylen = 16 - 5; 5057*37da2899SCharles.Forsyth else 5058*37da2899SCharles.Forsyth ckeylen = 0; 5059*37da2899SCharles.Forsyth keyarglen = 0; 5060*37da2899SCharles.Forsyth 5061*37da2899SCharles.Forsyth SSL_RC2_CBC => 5062*37da2899SCharles.Forsyth mkeylen = 16; 5063*37da2899SCharles.Forsyth if(ciph.key_material == 5) 5064*37da2899SCharles.Forsyth ckeylen = 16 - 5; 5065*37da2899SCharles.Forsyth else 5066*37da2899SCharles.Forsyth ckeylen = 0; 5067*37da2899SCharles.Forsyth keyarglen = 8; 5068*37da2899SCharles.Forsyth 5069*37da2899SCharles.Forsyth SSL_IDEA_CBC => 5070*37da2899SCharles.Forsyth mkeylen = 16; 5071*37da2899SCharles.Forsyth ckeylen = 0; 5072*37da2899SCharles.Forsyth keyarglen = 8; 5073*37da2899SCharles.Forsyth 5074*37da2899SCharles.Forsyth SSL_DES_CBC => 5075*37da2899SCharles.Forsyth mkeylen = 8; 5076*37da2899SCharles.Forsyth if(ciph.key_material == 5) 5077*37da2899SCharles.Forsyth ckeylen = 8 - 5; 5078*37da2899SCharles.Forsyth else 5079*37da2899SCharles.Forsyth ckeylen = 0; 5080*37da2899SCharles.Forsyth keyarglen = 8; 5081*37da2899SCharles.Forsyth 5082*37da2899SCharles.Forsyth SSL_3DES_EDE_CBC => 5083*37da2899SCharles.Forsyth mkeylen = 24; 5084*37da2899SCharles.Forsyth ckeylen = 0; 5085*37da2899SCharles.Forsyth keyarglen = 8; 5086*37da2899SCharles.Forsyth } 5087*37da2899SCharles.Forsyth 5088*37da2899SCharles.Forsyth return (mkeylen, ckeylen, keyarglen); 5089*37da2899SCharles.Forsyth} 5090*37da2899SCharles.Forsyth 5091*37da2899SCharles.Forsythv2handshake_enque(h: ref V2Handshake, ctx: ref Context) 5092*37da2899SCharles.Forsyth{ 5093*37da2899SCharles.Forsyth p := ref Protocol.pV2Handshake(h); 5094*37da2899SCharles.Forsyth 5095*37da2899SCharles.Forsyth protocol_write(p, ctx); 5096*37da2899SCharles.Forsyth} 5097*37da2899SCharles.Forsyth 5098*37da2899SCharles.ForsythV2Handshake.encode(hm: self ref V2Handshake): (array of byte, string) 5099*37da2899SCharles.Forsyth{ 5100*37da2899SCharles.Forsyth a : array of byte; 5101*37da2899SCharles.Forsyth n : int; 5102*37da2899SCharles.Forsyth e : string; 5103*37da2899SCharles.Forsyth 5104*37da2899SCharles.Forsyth i := 0; 5105*37da2899SCharles.Forsyth pick m := hm { 5106*37da2899SCharles.Forsyth Error => 5107*37da2899SCharles.Forsyth n = 3; 5108*37da2899SCharles.Forsyth a = array[n] of byte; 5109*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_ERROR; 5110*37da2899SCharles.Forsyth a[i:] = m.code; 5111*37da2899SCharles.Forsyth 5112*37da2899SCharles.Forsyth ClientHello => 5113*37da2899SCharles.Forsyth specslen := len m.cipher_specs; 5114*37da2899SCharles.Forsyth sidlen := len m.session_id; 5115*37da2899SCharles.Forsyth challen := len m.challenge; 5116*37da2899SCharles.Forsyth n = 9+specslen + sidlen + challen; 5117*37da2899SCharles.Forsyth a = array[n] of byte; 5118*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_CLIENT_HELLO; 5119*37da2899SCharles.Forsyth a[i:] = m.version; 5120*37da2899SCharles.Forsyth i += 2; 5121*37da2899SCharles.Forsyth a[i:] = int_encode(specslen, 2); 5122*37da2899SCharles.Forsyth i += 2; 5123*37da2899SCharles.Forsyth a[i:] = int_encode(sidlen, 2); 5124*37da2899SCharles.Forsyth i += 2; 5125*37da2899SCharles.Forsyth a[i:] = int_encode(challen, 2); 5126*37da2899SCharles.Forsyth i += 2; 5127*37da2899SCharles.Forsyth a[i:] = m.cipher_specs; 5128*37da2899SCharles.Forsyth i += specslen; 5129*37da2899SCharles.Forsyth if(sidlen != 0) { 5130*37da2899SCharles.Forsyth a[i:] = m.session_id; 5131*37da2899SCharles.Forsyth i += sidlen; 5132*37da2899SCharles.Forsyth } 5133*37da2899SCharles.Forsyth if(challen != 0) { 5134*37da2899SCharles.Forsyth a[i:] = m.challenge; 5135*37da2899SCharles.Forsyth i += challen; 5136*37da2899SCharles.Forsyth } 5137*37da2899SCharles.Forsyth 5138*37da2899SCharles.Forsyth ServerHello => 5139*37da2899SCharles.Forsyth # use only the user certificate 5140*37da2899SCharles.Forsyth certlen := len m.certificate; 5141*37da2899SCharles.Forsyth# specslen := 3*len m.cipher_specs; 5142*37da2899SCharles.Forsyth specslen := len m.cipher_specs; 5143*37da2899SCharles.Forsyth cidlen := len m.connection_id; 5144*37da2899SCharles.Forsyth n = 11 + certlen + specslen + cidlen; 5145*37da2899SCharles.Forsyth a = array[n] of byte; 5146*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_SERVER_HELLO; 5147*37da2899SCharles.Forsyth a[i++] = byte m.session_id_hit; 5148*37da2899SCharles.Forsyth a[i++] = byte m.certificate_type; 5149*37da2899SCharles.Forsyth a[i:] = m.version; 5150*37da2899SCharles.Forsyth i += 2; 5151*37da2899SCharles.Forsyth a[i:] = int_encode(certlen, 2); 5152*37da2899SCharles.Forsyth i += 2; 5153*37da2899SCharles.Forsyth a[i:] = int_encode(specslen, 2); 5154*37da2899SCharles.Forsyth i += 2; 5155*37da2899SCharles.Forsyth a[i:] = int_encode(cidlen, 2); 5156*37da2899SCharles.Forsyth i += 2; 5157*37da2899SCharles.Forsyth a[i:] = m.certificate; 5158*37da2899SCharles.Forsyth i += certlen; 5159*37da2899SCharles.Forsyth a[i:] = m.cipher_specs; 5160*37da2899SCharles.Forsyth i += specslen; 5161*37da2899SCharles.Forsyth a[i:] = m.connection_id; 5162*37da2899SCharles.Forsyth i += cidlen; 5163*37da2899SCharles.Forsyth 5164*37da2899SCharles.Forsyth ClientMasterKey => 5165*37da2899SCharles.Forsyth ckeylen := len m.clear_key; 5166*37da2899SCharles.Forsyth ekeylen := len m.encrypt_key; 5167*37da2899SCharles.Forsyth karglen := len m.key_arg; 5168*37da2899SCharles.Forsyth n = 10 + ckeylen + ekeylen + karglen; 5169*37da2899SCharles.Forsyth a = array[n] of byte; 5170*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_CLIENT_MASTER_KEY; 5171*37da2899SCharles.Forsyth a[i:] = m.cipher_kind; 5172*37da2899SCharles.Forsyth i += 3; 5173*37da2899SCharles.Forsyth a[i:] = int_encode(ckeylen, 2); 5174*37da2899SCharles.Forsyth i += 2; 5175*37da2899SCharles.Forsyth a[i:] = int_encode(ekeylen, 2); 5176*37da2899SCharles.Forsyth i += 2; 5177*37da2899SCharles.Forsyth a[i:] = int_encode(karglen, 2); 5178*37da2899SCharles.Forsyth i += 2; 5179*37da2899SCharles.Forsyth a[i:] = m.clear_key; 5180*37da2899SCharles.Forsyth i += ckeylen; 5181*37da2899SCharles.Forsyth a[i:] = m.encrypt_key; 5182*37da2899SCharles.Forsyth i += ekeylen; 5183*37da2899SCharles.Forsyth a[i:] = m.key_arg; 5184*37da2899SCharles.Forsyth i += karglen; 5185*37da2899SCharles.Forsyth 5186*37da2899SCharles.Forsyth ServerVerify => 5187*37da2899SCharles.Forsyth challen := len m.challenge; 5188*37da2899SCharles.Forsyth n = 1 + challen; 5189*37da2899SCharles.Forsyth a = array[n] of byte; 5190*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_SERVER_VERIFY; 5191*37da2899SCharles.Forsyth a[i:] = m.challenge; 5192*37da2899SCharles.Forsyth 5193*37da2899SCharles.Forsyth RequestCertificate => 5194*37da2899SCharles.Forsyth cclen := len m.certificate_challenge; 5195*37da2899SCharles.Forsyth n = 2 + cclen; 5196*37da2899SCharles.Forsyth a = array[n] of byte; 5197*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_REQUEST_CERTIFICATE; 5198*37da2899SCharles.Forsyth a[i++] = byte m.authentication_type; 5199*37da2899SCharles.Forsyth a[i:] = m.certificate_challenge; 5200*37da2899SCharles.Forsyth i += cclen; 5201*37da2899SCharles.Forsyth 5202*37da2899SCharles.Forsyth ClientCertificate => 5203*37da2899SCharles.Forsyth # use only the user certificate 5204*37da2899SCharles.Forsyth certlen := len m.certificate; 5205*37da2899SCharles.Forsyth resplen := len m.response; 5206*37da2899SCharles.Forsyth n = 6 + certlen + resplen; 5207*37da2899SCharles.Forsyth a = array[n] of byte; 5208*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_CLIENT_CERTIFICATE; 5209*37da2899SCharles.Forsyth a[i++] = byte m.certificate_type; 5210*37da2899SCharles.Forsyth a[i:] = int_encode(certlen, 2); 5211*37da2899SCharles.Forsyth i += 2; 5212*37da2899SCharles.Forsyth a[i:] = int_encode(resplen, 2); 5213*37da2899SCharles.Forsyth i += 2; 5214*37da2899SCharles.Forsyth a[i:] = m.certificate; 5215*37da2899SCharles.Forsyth i += certlen; 5216*37da2899SCharles.Forsyth a[i:] = m.response; 5217*37da2899SCharles.Forsyth i += resplen; 5218*37da2899SCharles.Forsyth 5219*37da2899SCharles.Forsyth ClientFinished => 5220*37da2899SCharles.Forsyth cidlen := len m.connection_id; 5221*37da2899SCharles.Forsyth n = 1 + cidlen; 5222*37da2899SCharles.Forsyth a = array[n] of byte; 5223*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_CLIENT_FINISHED; 5224*37da2899SCharles.Forsyth a[i:] = m.connection_id; 5225*37da2899SCharles.Forsyth i += cidlen; 5226*37da2899SCharles.Forsyth 5227*37da2899SCharles.Forsyth ServerFinished => 5228*37da2899SCharles.Forsyth sidlen := len m.session_id; 5229*37da2899SCharles.Forsyth n = 1 + sidlen; 5230*37da2899SCharles.Forsyth a = array[n] of byte; 5231*37da2899SCharles.Forsyth a[i++] = byte SSL2_MT_SERVER_FINISHED; 5232*37da2899SCharles.Forsyth a[i:] = m.session_id; 5233*37da2899SCharles.Forsyth i += sidlen; 5234*37da2899SCharles.Forsyth } 5235*37da2899SCharles.Forsyth 5236*37da2899SCharles.Forsyth return (a, e); 5237*37da2899SCharles.Forsyth} 5238*37da2899SCharles.Forsyth 5239*37da2899SCharles.ForsythV2Handshake.decode(a: array of byte): (ref V2Handshake, string) 5240*37da2899SCharles.Forsyth{ 5241*37da2899SCharles.Forsyth m : ref V2Handshake; 5242*37da2899SCharles.Forsyth e : string; 5243*37da2899SCharles.Forsyth 5244*37da2899SCharles.Forsyth n := len a; 5245*37da2899SCharles.Forsyth i := 1; 5246*37da2899SCharles.Forsyth case int a[0] { 5247*37da2899SCharles.Forsyth SSL2_MT_ERROR => 5248*37da2899SCharles.Forsyth if(n != 3) 5249*37da2899SCharles.Forsyth break; 5250*37da2899SCharles.Forsyth code := a[i:i+2]; 5251*37da2899SCharles.Forsyth i += 2; 5252*37da2899SCharles.Forsyth m = ref V2Handshake.Error(code); 5253*37da2899SCharles.Forsyth 5254*37da2899SCharles.Forsyth SSL2_MT_CLIENT_HELLO => 5255*37da2899SCharles.Forsyth if(n < 9) { 5256*37da2899SCharles.Forsyth e = "client hello: message too short"; 5257*37da2899SCharles.Forsyth break; 5258*37da2899SCharles.Forsyth } 5259*37da2899SCharles.Forsyth ver := a[i:i+2]; 5260*37da2899SCharles.Forsyth i += 2; 5261*37da2899SCharles.Forsyth specslen := int_decode(a[i:i+2]); 5262*37da2899SCharles.Forsyth i += 2; 5263*37da2899SCharles.Forsyth sidlen := int_decode(a[i:i+2]); 5264*37da2899SCharles.Forsyth i += 2; 5265*37da2899SCharles.Forsyth challen := int_decode(a[i:i+2]); 5266*37da2899SCharles.Forsyth i += 2; 5267*37da2899SCharles.Forsyth if(n != 9+specslen+sidlen+challen) { 5268*37da2899SCharles.Forsyth e = "client hello: length mismatch"; 5269*37da2899SCharles.Forsyth break; 5270*37da2899SCharles.Forsyth } 5271*37da2899SCharles.Forsyth if(specslen%3 != 0) { 5272*37da2899SCharles.Forsyth e = "client hello: must multiple of 3 bytes"; 5273*37da2899SCharles.Forsyth break; 5274*37da2899SCharles.Forsyth } 5275*37da2899SCharles.Forsyth specs: array of byte; 5276*37da2899SCharles.Forsyth if(specslen != 0) { 5277*37da2899SCharles.Forsyth specs = a[i:i+specslen]; 5278*37da2899SCharles.Forsyth i += specslen; 5279*37da2899SCharles.Forsyth } 5280*37da2899SCharles.Forsyth sid: array of byte; 5281*37da2899SCharles.Forsyth if(sidlen != 0) { 5282*37da2899SCharles.Forsyth sid = a[i:i+sidlen]; 5283*37da2899SCharles.Forsyth i += sidlen; 5284*37da2899SCharles.Forsyth } 5285*37da2899SCharles.Forsyth chal: array of byte; 5286*37da2899SCharles.Forsyth if(challen != 0) { 5287*37da2899SCharles.Forsyth chal = a[i:i+challen]; 5288*37da2899SCharles.Forsyth i += challen; 5289*37da2899SCharles.Forsyth } 5290*37da2899SCharles.Forsyth m = ref V2Handshake.ClientHello(ver, specs, sid, chal); 5291*37da2899SCharles.Forsyth 5292*37da2899SCharles.Forsyth SSL2_MT_CLIENT_MASTER_KEY => 5293*37da2899SCharles.Forsyth if(n < 10) { 5294*37da2899SCharles.Forsyth e = "client master key: message too short"; 5295*37da2899SCharles.Forsyth break; 5296*37da2899SCharles.Forsyth } 5297*37da2899SCharles.Forsyth kind := a[i:i+3]; 5298*37da2899SCharles.Forsyth i += 3; 5299*37da2899SCharles.Forsyth ckeylen := int_decode(a[i:i+2]); 5300*37da2899SCharles.Forsyth i += 2; 5301*37da2899SCharles.Forsyth ekeylen := int_decode(a[i:i+2]); 5302*37da2899SCharles.Forsyth i += 2; 5303*37da2899SCharles.Forsyth karglen := int_decode(a[i:i+2]); 5304*37da2899SCharles.Forsyth i += 2; 5305*37da2899SCharles.Forsyth if(n != 10 + ckeylen + ekeylen + karglen) { 5306*37da2899SCharles.Forsyth e = "client master key: length mismatch"; 5307*37da2899SCharles.Forsyth break; 5308*37da2899SCharles.Forsyth } 5309*37da2899SCharles.Forsyth ckey := a[i:i+ckeylen]; 5310*37da2899SCharles.Forsyth i += ckeylen; 5311*37da2899SCharles.Forsyth ekey := a[i:i+ekeylen]; 5312*37da2899SCharles.Forsyth i += ekeylen; 5313*37da2899SCharles.Forsyth karg := a[i:i+karglen]; 5314*37da2899SCharles.Forsyth i += karglen; 5315*37da2899SCharles.Forsyth m = ref V2Handshake.ClientMasterKey(kind, ckey, ekey, karg); 5316*37da2899SCharles.Forsyth 5317*37da2899SCharles.Forsyth SSL2_MT_CLIENT_FINISHED => 5318*37da2899SCharles.Forsyth cid := a[i:n]; 5319*37da2899SCharles.Forsyth i = n; 5320*37da2899SCharles.Forsyth m = ref V2Handshake.ClientFinished(cid); 5321*37da2899SCharles.Forsyth 5322*37da2899SCharles.Forsyth SSL2_MT_SERVER_HELLO => 5323*37da2899SCharles.Forsyth if(n < 11) { 5324*37da2899SCharles.Forsyth e = "server hello: messsage too short"; 5325*37da2899SCharles.Forsyth break; 5326*37da2899SCharles.Forsyth } 5327*37da2899SCharles.Forsyth sidhit := int a[i++]; 5328*37da2899SCharles.Forsyth certtype := int a[i++]; 5329*37da2899SCharles.Forsyth ver := a[i:i+2]; 5330*37da2899SCharles.Forsyth i += 2; 5331*37da2899SCharles.Forsyth certlen := int_decode(a[i:i+2]); 5332*37da2899SCharles.Forsyth i += 2; 5333*37da2899SCharles.Forsyth specslen := int_decode(a[i:i+2]); 5334*37da2899SCharles.Forsyth i += 2; 5335*37da2899SCharles.Forsyth cidlen := int_decode(a[i:i+2]); 5336*37da2899SCharles.Forsyth i += 2; 5337*37da2899SCharles.Forsyth if(n != 11+certlen+specslen+cidlen) { 5338*37da2899SCharles.Forsyth e = "server hello: length mismatch"; 5339*37da2899SCharles.Forsyth break; 5340*37da2899SCharles.Forsyth } 5341*37da2899SCharles.Forsyth cert := a[i:i+certlen]; 5342*37da2899SCharles.Forsyth i += certlen; 5343*37da2899SCharles.Forsyth if(specslen%3 != 0) { 5344*37da2899SCharles.Forsyth e = "server hello: must be multiple of 3 bytes"; 5345*37da2899SCharles.Forsyth break; 5346*37da2899SCharles.Forsyth } 5347*37da2899SCharles.Forsyth specs := a[i:i+specslen]; 5348*37da2899SCharles.Forsyth i += specslen; 5349*37da2899SCharles.Forsyth if(cidlen < 16 || cidlen > 32) { 5350*37da2899SCharles.Forsyth e = "server hello: connection id length out of range"; 5351*37da2899SCharles.Forsyth break; 5352*37da2899SCharles.Forsyth } 5353*37da2899SCharles.Forsyth cid := a[i:i+cidlen]; 5354*37da2899SCharles.Forsyth i += cidlen; 5355*37da2899SCharles.Forsyth m = ref V2Handshake.ServerHello(sidhit, certtype, ver, cert, specs, cid); 5356*37da2899SCharles.Forsyth 5357*37da2899SCharles.Forsyth SSL2_MT_SERVER_VERIFY => 5358*37da2899SCharles.Forsyth chal := a[i:n]; 5359*37da2899SCharles.Forsyth i = n; 5360*37da2899SCharles.Forsyth m = ref V2Handshake.ServerVerify(chal); 5361*37da2899SCharles.Forsyth 5362*37da2899SCharles.Forsyth SSL2_MT_SERVER_FINISHED => 5363*37da2899SCharles.Forsyth sid := a[i:n]; 5364*37da2899SCharles.Forsyth m = ref V2Handshake.ServerFinished(sid); 5365*37da2899SCharles.Forsyth 5366*37da2899SCharles.Forsyth SSL2_MT_REQUEST_CERTIFICATE => 5367*37da2899SCharles.Forsyth if(n < 2) { 5368*37da2899SCharles.Forsyth e = "request certificate: message too short"; 5369*37da2899SCharles.Forsyth break; 5370*37da2899SCharles.Forsyth } 5371*37da2899SCharles.Forsyth authtype := int a[i++]; 5372*37da2899SCharles.Forsyth certchal := a[i:n]; 5373*37da2899SCharles.Forsyth i = n; 5374*37da2899SCharles.Forsyth m = ref V2Handshake.RequestCertificate(authtype, certchal); 5375*37da2899SCharles.Forsyth 5376*37da2899SCharles.Forsyth SSL2_MT_CLIENT_CERTIFICATE => 5377*37da2899SCharles.Forsyth if(n < 6) { 5378*37da2899SCharles.Forsyth e = "client certificate: message too short"; 5379*37da2899SCharles.Forsyth break; 5380*37da2899SCharles.Forsyth } 5381*37da2899SCharles.Forsyth certtype := int a[i++]; 5382*37da2899SCharles.Forsyth certlen := int_decode(a[i:i+2]); 5383*37da2899SCharles.Forsyth i += 2; 5384*37da2899SCharles.Forsyth resplen := int_decode(a[i:i+2]); 5385*37da2899SCharles.Forsyth i += 2; 5386*37da2899SCharles.Forsyth if(n != 6+certlen+resplen) { 5387*37da2899SCharles.Forsyth e = "client certificate: length mismatch"; 5388*37da2899SCharles.Forsyth break; 5389*37da2899SCharles.Forsyth } 5390*37da2899SCharles.Forsyth cert := a[i:i+certlen]; 5391*37da2899SCharles.Forsyth i += certlen; 5392*37da2899SCharles.Forsyth resp := a[i:i+resplen]; 5393*37da2899SCharles.Forsyth m = ref V2Handshake.ClientCertificate(certtype, cert, resp); 5394*37da2899SCharles.Forsyth 5395*37da2899SCharles.Forsyth * => 5396*37da2899SCharles.Forsyth e = "unknown message [" + string a[0] + "]"; 5397*37da2899SCharles.Forsyth } 5398*37da2899SCharles.Forsyth 5399*37da2899SCharles.Forsyth return (m, e); 5400*37da2899SCharles.Forsyth} 5401*37da2899SCharles.Forsyth 5402*37da2899SCharles.Forsyth# utilities 5403*37da2899SCharles.Forsyth 5404*37da2899SCharles.Forsythmd5_hash(input: list of array of byte, md5_ds: ref DigestState): (array of byte, ref DigestState) 5405*37da2899SCharles.Forsyth{ 5406*37da2899SCharles.Forsyth hash_value := array [Keyring->MD5dlen] of byte; 5407*37da2899SCharles.Forsyth ds : ref DigestState; 5408*37da2899SCharles.Forsyth 5409*37da2899SCharles.Forsyth if(md5_ds != nil) 5410*37da2899SCharles.Forsyth ds = md5_ds.copy(); 5411*37da2899SCharles.Forsyth 5412*37da2899SCharles.Forsyth lab := input; 5413*37da2899SCharles.Forsyth for(i := 0; i < len input - 1; i++) { 5414*37da2899SCharles.Forsyth ds = keyring->md5(hd lab, len hd lab, nil, ds); 5415*37da2899SCharles.Forsyth lab = tl lab; 5416*37da2899SCharles.Forsyth } 5417*37da2899SCharles.Forsyth ds = keyring->md5(hd lab, len hd lab, hash_value, ds); 5418*37da2899SCharles.Forsyth 5419*37da2899SCharles.Forsyth return (hash_value, ds); 5420*37da2899SCharles.Forsyth} 5421*37da2899SCharles.Forsyth 5422*37da2899SCharles.Forsythsha_hash(input: list of array of byte, sha_ds: ref DigestState): (array of byte, ref DigestState) 5423*37da2899SCharles.Forsyth{ 5424*37da2899SCharles.Forsyth hash_value := array [Keyring->SHA1dlen] of byte; 5425*37da2899SCharles.Forsyth ds : ref DigestState; 5426*37da2899SCharles.Forsyth 5427*37da2899SCharles.Forsyth if(sha_ds != nil) 5428*37da2899SCharles.Forsyth ds = sha_ds.copy(); 5429*37da2899SCharles.Forsyth 5430*37da2899SCharles.Forsyth lab := input; 5431*37da2899SCharles.Forsyth for(i := 0; i < len input - 1; i++) { 5432*37da2899SCharles.Forsyth ds = keyring->sha1(hd lab, len hd lab, nil, ds); 5433*37da2899SCharles.Forsyth lab = tl lab; 5434*37da2899SCharles.Forsyth } 5435*37da2899SCharles.Forsyth ds = keyring->sha1(hd lab, len hd lab, hash_value, ds); 5436*37da2899SCharles.Forsyth 5437*37da2899SCharles.Forsyth return (hash_value, ds); 5438*37da2899SCharles.Forsyth} 5439*37da2899SCharles.Forsyth 5440*37da2899SCharles.Forsythmd5_sha_hash(input: list of array of byte, md5_ds, sha_ds: ref DigestState) 5441*37da2899SCharles.Forsyth : (array of byte, ref DigestState, ref DigestState) 5442*37da2899SCharles.Forsyth{ 5443*37da2899SCharles.Forsyth buf := array [Keyring->MD5dlen+Keyring->SHA1dlen] of byte; 5444*37da2899SCharles.Forsyth 5445*37da2899SCharles.Forsyth (buf[0:], md5_ds) = md5_hash(input, md5_ds); 5446*37da2899SCharles.Forsyth (buf[Keyring->MD5dlen:], sha_ds) = sha_hash(input, sha_ds); 5447*37da2899SCharles.Forsyth 5448*37da2899SCharles.Forsyth return (buf, md5_ds, sha_ds); 5449*37da2899SCharles.Forsyth} 5450*37da2899SCharles.Forsyth 5451*37da2899SCharles.Forsythint_decode(buf: array of byte): int 5452*37da2899SCharles.Forsyth{ 5453*37da2899SCharles.Forsyth val := 0; 5454*37da2899SCharles.Forsyth for(i := 0; i < len buf; i++) 5455*37da2899SCharles.Forsyth val = (val << 8) | (int buf[i]); 5456*37da2899SCharles.Forsyth 5457*37da2899SCharles.Forsyth return val; 5458*37da2899SCharles.Forsyth} 5459*37da2899SCharles.Forsyth 5460*37da2899SCharles.Forsythint_encode(value, length: int): array of byte 5461*37da2899SCharles.Forsyth{ 5462*37da2899SCharles.Forsyth buf := array [length] of byte; 5463*37da2899SCharles.Forsyth 5464*37da2899SCharles.Forsyth while(length--) { 5465*37da2899SCharles.Forsyth buf[length] = byte value; 5466*37da2899SCharles.Forsyth value >>= 8; 5467*37da2899SCharles.Forsyth } 5468*37da2899SCharles.Forsyth 5469*37da2899SCharles.Forsyth return buf; 5470*37da2899SCharles.Forsyth} 5471*37da2899SCharles.Forsyth 5472*37da2899SCharles.Forsyth 5473*37da2899SCharles.Forsythbastr(a: array of byte) : string 5474*37da2899SCharles.Forsyth{ 5475*37da2899SCharles.Forsyth ans : string = ""; 5476*37da2899SCharles.Forsyth 5477*37da2899SCharles.Forsyth for(i := 0; i < len a; i++) { 5478*37da2899SCharles.Forsyth if(i < len a - 1 && i != 0 && i%10 == 0) 5479*37da2899SCharles.Forsyth ans += "\n\t\t"; 5480*37da2899SCharles.Forsyth if(i == len a -1) 5481*37da2899SCharles.Forsyth ans += sys->sprint("%2x", int a[i]); 5482*37da2899SCharles.Forsyth else 5483*37da2899SCharles.Forsyth ans += sys->sprint("%2x ", int a[i]); 5484*37da2899SCharles.Forsyth } 5485*37da2899SCharles.Forsyth 5486*37da2899SCharles.Forsyth return ans; 5487*37da2899SCharles.Forsyth} 5488*37da2899SCharles.Forsyth 5489*37da2899SCharles.Forsythbbastr(a: array of array of byte) : string 5490*37da2899SCharles.Forsyth{ 5491*37da2899SCharles.Forsyth info := ""; 5492*37da2899SCharles.Forsyth 5493*37da2899SCharles.Forsyth for(i := 0; i < len a; i++) 5494*37da2899SCharles.Forsyth info += bastr(a[i]); 5495*37da2899SCharles.Forsyth 5496*37da2899SCharles.Forsyth return info; 5497*37da2899SCharles.Forsyth} 5498*37da2899SCharles.Forsyth 5499*37da2899SCharles.Forsythlbastr(a: list of array of byte) : string 5500*37da2899SCharles.Forsyth{ 5501*37da2899SCharles.Forsyth info := ""; 5502*37da2899SCharles.Forsyth 5503*37da2899SCharles.Forsyth l := a; 5504*37da2899SCharles.Forsyth while(l != nil) { 5505*37da2899SCharles.Forsyth info += bastr(hd l) + "\n\t\t"; 5506*37da2899SCharles.Forsyth l = tl l; 5507*37da2899SCharles.Forsyth } 5508*37da2899SCharles.Forsyth 5509*37da2899SCharles.Forsyth return info; 5510*37da2899SCharles.Forsyth} 5511*37da2899SCharles.Forsyth 5512*37da2899SCharles.Forsyth# need to fix (string a == string b) 5513*37da2899SCharles.Forsythbytes_cmp(a, b: array of byte): int 5514*37da2899SCharles.Forsyth{ 5515*37da2899SCharles.Forsyth if(len a != len b) 5516*37da2899SCharles.Forsyth return -1; 5517*37da2899SCharles.Forsyth 5518*37da2899SCharles.Forsyth n := len a; 5519*37da2899SCharles.Forsyth for(i := 0; i < n; i++) { 5520*37da2899SCharles.Forsyth if(a[i] != b[i]) 5521*37da2899SCharles.Forsyth return -1; 5522*37da2899SCharles.Forsyth } 5523*37da2899SCharles.Forsyth 5524*37da2899SCharles.Forsyth return 0; 5525*37da2899SCharles.Forsyth} 5526*37da2899SCharles.Forsyth 5527*37da2899SCharles.Forsythputn(a: array of byte, i, value, n: int): int 5528*37da2899SCharles.Forsyth{ 5529*37da2899SCharles.Forsyth j := n; 5530*37da2899SCharles.Forsyth while(j--) { 5531*37da2899SCharles.Forsyth a[i+j] = byte value; 5532*37da2899SCharles.Forsyth value >>= 8; 5533*37da2899SCharles.Forsyth } 5534*37da2899SCharles.Forsyth return i+n; 5535*37da2899SCharles.Forsyth} 5536*37da2899SCharles.Forsyth 5537*37da2899SCharles.ForsythINVALID_SUITE : con "invalid suite list"; 5538*37da2899SCharles.ForsythILLEGAL_SUITE : con "illegal suite list"; 5539*37da2899SCharles.Forsyth 5540*37da2899SCharles.Forsythcksuites(suites : array of byte) : string 5541*37da2899SCharles.Forsyth{ 5542*37da2899SCharles.Forsyth m := len suites; 5543*37da2899SCharles.Forsyth if (m == 0 || (m&1)) 5544*37da2899SCharles.Forsyth return INVALID_SUITE; 5545*37da2899SCharles.Forsyth n := len SSL3_Suites; 5546*37da2899SCharles.Forsyth ssl3s := array [2] of byte; 5547*37da2899SCharles.Forsyth for (j := 0; j < m; j += 2) { 5548*37da2899SCharles.Forsyth for( i := 0; i < n; i++) { 5549*37da2899SCharles.Forsyth ssl3s = SSL3_Suites[i]; 5550*37da2899SCharles.Forsyth if(suites[j] == ssl3s[0] && suites[j+1] == ssl3s[1]) 5551*37da2899SCharles.Forsyth break; 5552*37da2899SCharles.Forsyth } 5553*37da2899SCharles.Forsyth if (i == n) 5554*37da2899SCharles.Forsyth return ILLEGAL_SUITE; 5555*37da2899SCharles.Forsyth } 5556*37da2899SCharles.Forsyth return nil; 5557*37da2899SCharles.Forsyth} 5558