2
0

TLS.Mod 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944
  1. MODULE TLS; (** AUTHOR "F.N."; PURPOSE "RFC 2246: Transport Layer Security v1.0"; *)
  2. (*
  3. 05.2014 -- Timothée Martiel -- Implemented TLS client connection.
  4. *)
  5. IMPORT
  6. TCP, Streams, Files, IP, KernelLog , Pipes, Kernel, Clock, BIT, Dates,
  7. Ciphers := CryptoCiphers, Utils := CryptoUtils, HMAC := CryptoHMAC, CSPRNG := CryptoCSPRNG,
  8. CryptoMD5, CryptoSHA1, CryptoRSA, CryptoBigNumbers, PKCS1, X509;
  9. CONST
  10. (* debugging *)
  11. Trace = TRUE;
  12. (** tlsStates *)
  13. ServerHandshake* = 12;
  14. ClientHandshake* = 13;
  15. (* client and server common handshake states *)
  16. NotAValidHandshakeState = 100; HandshakeFinished = 101; GenerateChangeCipherSpec = 102; AwaitFinished = 103;
  17. (* server-side handshake states *)
  18. AwaitClientHello = 201; GenerateServerHello = 202; GenerateServerHelloDone = 203; AwaitClientKeyExchange = 204;
  19. AwaitChangeSpec = 205; GenerateHelloWithResumption = 210;
  20. AwaitChangeSpecWithResumption = 211; AwaitFinishedWithResumption = 212;
  21. (* client-side handshake states *)
  22. GenerateClientHello = 300; AwaitServerHello = 301; AwaitCertificate = 302; AwaitServerHelloDone = 303; GenerateClientKeyExchange = 304;
  23. (** available cipher suites *)
  24. TlsRsaWithNullMd5* = 0001H; TlsRsaWithNullSha* = 0002H; TlsRsaWithRc4128Md5* = 0004H;
  25. TlsRsaWithRc4128Sha* = 0005H; TlsRsaWithIdeaCbcSha* = 0007H; TlsRsaWithDesCbcSha* = 0009H;
  26. TlsRsaWith3DesEdeCbcSha* = 000AH;
  27. (* not supported
  28. TlsDhDssWithDesCbcSha* = 000CH; TlsDhDssWith3DesEdeCbcSha* = 000DH;
  29. TlsDhRsaWithDesCbcSha* = 000FH; TlsDhRsaWith3DesEdeCbcSha* = 0010H;
  30. TlsDhAnonWithRc4128Md5* = 0018H; TlsDhAnonWithDesCbcSha* = 001AH; TlsDhAnonWith3DesEdeCbcSha* = 001BH;
  31. *)
  32. (* TLS 1.2 cipher suites, not implemented yet *)
  33. TlsRsaWithAes128CbcSha* = 002FH;
  34. (* not supported
  35. TlsDhDssWithAes128CbcSha* = 0030H; TlsDhRsaWithAes128CbcSha* = 0031H;
  36. TlsDheDssWithAes128CbcSha* = 0032H; TlsDheRsaWithAes128CbcSha* = 0033H;
  37. TlsDhAnonWithAes128CbcSha* = 0034H;
  38. *)
  39. TlsRsaWithAes256CbcSha* = 0035H;
  40. (* not supported
  41. TlsDhDssWithAes256CbcSha* = 0036H; TlsDhRsaWithAes256CbcSha* = 0037H;
  42. TlsDheDssWithAes256CbcSha* = 0038H; TlsDheRsaWithAes256CbcSha* = 0039H;
  43. TlsDhAnonWithAes256CbcSha* = 003AH;
  44. *)
  45. (** record layer content type *)
  46. ChangeCipherSpec* = 20; Alert* = 21; Handshake* = 22; ApplicationData* = 23; SSLv2ClientHello* = 128;
  47. (** handshake message types *)
  48. HelloRequest* = 0; ClientHello* = 1; ServerHello* = 2; Certificate* = 11;
  49. ServerKeyExchange* = 12; CertificateRequest* = 13; ServerHelloDone* = 14; CertificateVerify* = 15;
  50. ClientKeyExchange* = 16; Finished* = 20;
  51. V2ClientHello* = 30;
  52. (* alert levels *)
  53. Warning = 1; Fatal = 2;
  54. (* alert types *)
  55. NoError = -1;
  56. CloseNotify = 0; UnexpectedMessage = 10; BadRecordMac = 20; DecryptionFailed = 21;
  57. RecordOverflow = 22; DecompressionFailure = 30; HandshakeFailure = 40; NoCertificate = 41; (* only SSL 3.0 *)
  58. BadCertificate = 42; UnsupportedCertificate = 43; CertificateRevoked = 44; CertificateExpired = 45;
  59. CertificateUnknown = 46; IllegalParameter = 47; UnknownCA = 48; AccessDenied = 49;
  60. DecodeError = 50; DecryptError = 51; ExportRestriction = 60; ProtocolVersion = 70;
  61. InsufficientSecurity = 71; InternalError = 80; UserCancelled = 90; NoRenegotiation = 100; UnsupportedExtension=110;
  62. (** error numbers *)
  63. Ok* = 0; TLSHandshakeAborted* = 2;
  64. Suites* = 20;
  65. Buflen = 18500;
  66. MaxPHashKernelLogput = 1024;
  67. MaxKeyBlock = 144;
  68. MaxPHashSeed = 128;
  69. MaxPlaintextLength = 16384; (* 2^14 *)
  70. MaxCompressedLength = 17408; (* 2^14 + 2^10 *)
  71. MaxCiphertextLength = 18432; (* 2^14 + 2^11 *)
  72. SessionIdLength = 16;
  73. SessionHashtableSize = 1023; (* 256 * 456 *)
  74. SessionCleanUpInterval = 60; (* seconds *)
  75. DefaultSessionLifetime = 3600; (* seconds *)
  76. DefaultSuitesNbr = 3;
  77. TYPE
  78. SecurityParameters = OBJECT
  79. VAR
  80. cipherSuite, cipherKeySize: LONGINT; (* size in bytes *)
  81. clientRandom, serverRandom: ARRAY 32 OF CHAR;
  82. PRFAlgorithm: ARRAY 32 OF CHAR;
  83. END SecurityParameters;
  84. ConnectionState = OBJECT
  85. VAR
  86. cipher: Ciphers.Cipher;
  87. mac: HMAC.HMac;
  88. recordSeq: DoubleLong;
  89. cipherKey: ARRAY 32 OF CHAR;
  90. iv: ARRAY 16 OF CHAR;
  91. macSecret: ARRAY 20 OF CHAR;
  92. PROCEDURE & Init*;
  93. BEGIN
  94. NEW( recordSeq)
  95. END Init;
  96. END ConnectionState;
  97. (*
  98. DoubleLong = OBJECT (* 64-bit number, the initial value is -1 *)
  99. VAR num -: ARRAY 2 OF LONGINT; (* 64 bits, msb: num[ 0 ] *)
  100. PROCEDURE & Init*;
  101. BEGIN
  102. num[ 0 ] := 0; num[ 1 ] := -1
  103. END Init;
  104. PROCEDURE Inc;
  105. BEGIN
  106. ASSERT( ( num[ 0 ] < MAX( LONGINT ) ) OR ( num[ 1 ] < MAX( LONGINT ) ) );
  107. IF num[ 1 ] < MAX( LONGINT ) THEN
  108. INC( num[ 1 ] );
  109. RETURN
  110. ELSE
  111. num[ 1 ] := 0;
  112. INC( num[ 0 ] )
  113. END
  114. END Inc;
  115. (* write the current value of num in big-endian to data starting at ofs *)
  116. PROCEDURE GetBytes( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  117. BEGIN
  118. ASSERT( ofs < LEN( data ) - 7 );
  119. data[ ofs ] := CHR( num[ 0 ] DIV ( 256*256*256 ) );
  120. data[ ofs + 1 ] := CHR( num[ 0 ] DIV ( 256*256 ) );
  121. data[ ofs + 2 ] := CHR( num[ 0 ] DIV 256 );
  122. data[ ofs + 3 ] := CHR( num[ 0 ] );
  123. data[ ofs + 4 ] := CHR( num[ 1 ] DIV ( 256*256*256 ) );
  124. data[ ofs + 5 ] := CHR( num[ 1 ] DIV ( 256*256 ) );
  125. data[ ofs + 6 ] := CHR( num[ 1 ] DIV 256 );
  126. data[ ofs + 7 ] := CHR( num[ 1 ] )
  127. END GetBytes;
  128. END DoubleLong;
  129. *) (*! contains a large gap between 80000000 and 100000000. g.f. *)
  130. DoubleLong = OBJECT (* 64-bit counter, the initial value is -1 *)
  131. VAR
  132. numH, numL: LONGINT;
  133. PROCEDURE &Init;
  134. BEGIN
  135. numH := -1; numL := -1
  136. END Init;
  137. PROCEDURE Inc;
  138. BEGIN
  139. IF numL # -1 THEN INC( numL )
  140. ELSIF numH = -1 THEN numH := 0; numL := 0
  141. ELSE INC( numH ); numL := 0
  142. END
  143. END Inc;
  144. (* write the current value of num in big-endian to buf starting at ofs *)
  145. PROCEDURE GetBytes( VAR buf: ARRAY OF CHAR; ofs: LONGINT );
  146. VAR p, val: LONGINT;
  147. BEGIN
  148. p := ofs + 7; val := numL;
  149. REPEAT
  150. buf[p] := CHR( val MOD 256 );
  151. IF p = ofs + 4 THEN val := numH ELSE val := val DIV 256 END;
  152. DEC( p )
  153. UNTIL p < ofs;
  154. END GetBytes;
  155. END DoubleLong;
  156. (* data expansion function as defined in rfc2246, section 5 *)
  157. PHash = OBJECT
  158. VAR hMac: HMAC.HMac;
  159. (* initialization of a PHash object using h as internal hashing-function *)
  160. PROCEDURE & Init*( hashname: ARRAY OF CHAR );
  161. BEGIN
  162. NEW( hMac, hashname );
  163. END Init;
  164. PROCEDURE Expand( VAR secret, seed, outbuf: ARRAY OF CHAR; secretLen, seedLen, outLen: LONGINT );
  165. VAR
  166. a: ARRAY 2 * MaxPHashSeed OF CHAR;
  167. i, iterations: LONGINT;
  168. BEGIN
  169. ASSERT( seedLen <= ( MaxPHashSeed ) );
  170. ASSERT( outLen <= ( MaxPHashKernelLogput ) );
  171. hMac.Initialize( secret, secretLen );
  172. hMac.Update( seed, 0, seedLen );
  173. hMac.GetMac( a, 0 ); (* a( 1 ) *)
  174. FOR i := 0 TO seedLen-1 DO a[ hMac.size + i ] := seed[ i ] END; (* concatenate seed to a( 1 ) *)
  175. iterations := ( outLen DIV hMac.size ) + 1;
  176. (* iteration *)
  177. FOR i := 0 TO iterations - 1 DO
  178. hMac.Initialize( secret, secretLen );
  179. hMac.Update( a, 0, hMac.size+seedLen );
  180. hMac.GetMac( outbuf, i*hMac.size );
  181. (* increment a *)
  182. hMac.Initialize( secret, secretLen );
  183. hMac.Update( a, 0, hMac.size );
  184. hMac.GetMac( a, 0 )
  185. END
  186. END Expand;
  187. END PHash;
  188. (* pseudorandom stream as defined in rfc2246, section 5 *)
  189. PRF = OBJECT
  190. VAR
  191. pMD5, pSHA: PHash; (* Used for "SHA1 XOR MD5", i.e. <= v1.1 *)
  192. pHash: PHash; (* Used in > v1.1 *)
  193. PROCEDURE & Init* (CONST algorithm: ARRAY OF CHAR);
  194. BEGIN
  195. IF algorithm = "SHA1 XOR MD5" THEN
  196. NEW( pMD5, "CryptoMD5" ); NEW( pSHA, "CryptoSHA1" )
  197. ELSE
  198. NEW( pHash, algorithm)
  199. END;
  200. END Init;
  201. PROCEDURE GetBytes( VAR secret, seed, outbuf: ARRAY OF CHAR; CONST label: ARRAY OF CHAR; secretLen, seedLen, outLen: LONGINT );
  202. VAR
  203. md5Result, shaResult: ARRAY MaxKeyBlock OF CHAR;
  204. pSeed, s1, s2: ARRAY 140 OF CHAR;
  205. i, j, l: LONGINT;
  206. BEGIN
  207. IF pHash = NIL THEN (* Use SHA1 XOR MD5 algo *)
  208. (* pseed := label::seed *)
  209. l := LEN( label ) - 1;
  210. FOR i := 0 TO l-1 DO pSeed[ i ] := label[ i ] END;
  211. FOR i := 0 TO seedLen-1 DO pSeed[ l + i ] := seed[ i ] END;
  212. j := secretLen DIV 2 + secretLen MOD 2; (* j := ceil( secretLen / 2 ) *)
  213. FOR i := 0 TO j-1 DO s1[ i ] := secret[ i ] END;
  214. FOR i := secretLen-j TO secretLen-1 DO s2[ i+j-secretLen ] := secret[ i ] END;
  215. pMD5.Expand( s1, pSeed, md5Result, j, seedLen+l, outLen );
  216. pSHA.Expand( s2, pSeed, shaResult, j, seedLen+l, outLen );
  217. FOR i := 0 TO outLen-1 DO outbuf[ i ] := BIT.CXOR( md5Result[ i ], shaResult[ i ] ) END
  218. ELSE (* Use direct algo *)
  219. pHash.Expand( secret, seed, shaResult, secretLen, seedLen, outLen );
  220. (* Copy to truncate *)
  221. FOR i := 0 TO outLen - 1 DO outbuf[i] := shaResult[i] END
  222. END
  223. END GetBytes;
  224. END PRF;
  225. Policy* = OBJECT
  226. VAR
  227. cipherSuites -: ARRAY Suites OF LONGINT;
  228. nofCipherSuites -: LONGINT; (** number of enabled cipher-suites *)
  229. sessionResumptionEnabled -: BOOLEAN;
  230. sessionLifetime -: LONGINT; (** seconds *)
  231. version-: ARRAY 2 OF CHAR;
  232. PROCEDURE &Init*;
  233. BEGIN
  234. (* set default values *)
  235. sessionResumptionEnabled := TRUE;
  236. sessionLifetime := DefaultSessionLifetime;
  237. END Init;
  238. (** set n negotiable cipher suites in order of preference*)
  239. PROCEDURE SetCipherSuites*( VAR s: ARRAY OF LONGINT; n: LONGINT );
  240. VAR i: LONGINT;
  241. BEGIN
  242. ASSERT( n <= Suites );
  243. FOR i := 0 TO n-1 DO cipherSuites[ i ] := s[ i ] END;
  244. nofCipherSuites := n
  245. END SetCipherSuites;
  246. (** Returns TRUE if the cipher-suite s is supported by this policy *)
  247. PROCEDURE IsSupported*( s: LONGINT ): BOOLEAN;
  248. VAR i: LONGINT;
  249. BEGIN
  250. FOR i := 0 TO nofCipherSuites - 1 DO
  251. IF cipherSuites[ i ] = s THEN RETURN TRUE END
  252. END;
  253. RETURN FALSE
  254. END IsSupported;
  255. (** set whether sessions may be resumed; default is TRUE *)
  256. PROCEDURE EnableSessionResumption*( enable: BOOLEAN );
  257. BEGIN sessionResumptionEnabled := enable
  258. END EnableSessionResumption;
  259. (** lifetime of a session in seconds; default: 3600s *)
  260. PROCEDURE SetSessionLifetime*( t: LONGINT );
  261. BEGIN
  262. ASSERT( t >= 0 );
  263. sessionLifetime := t
  264. END SetSessionLifetime;
  265. (** set TLS version to use *)
  266. PROCEDURE SetVersion*(major, minor: LONGINT);
  267. BEGIN
  268. ASSERT(major = 1);
  269. ASSERT(minor >= 0);
  270. ASSERT(minor <= 2);
  271. version[0] := CHR(3);
  272. version[1] := CHR(1 + minor)
  273. END SetVersion;
  274. END Policy;
  275. Session = OBJECT
  276. VAR
  277. id : ARRAY 32 OF CHAR;
  278. idLength : LONGINT;
  279. resumable : BOOLEAN;
  280. cipherSuite : LONGINT;
  281. preMasterSecret, masterSecret -: ARRAY 48 OF CHAR;
  282. lifetime: LONGINT; (* seconds *)
  283. timer: Kernel.Timer;
  284. next: Session;
  285. (** initialize a session.
  286. If caching is FALSE, no session-id will associated with the new session.
  287. if cache is TRUE and len is zero, a session id will be randomly generated.
  288. if cache is TRUE and len is non-zero, a session-id will be read from data *)
  289. PROCEDURE & Init*( caching: BOOLEAN; VAR data: ARRAY OF CHAR; ofs, len, lifetime: LONGINT );
  290. VAR i: LONGINT;
  291. BEGIN
  292. ASSERT( ofs > -1 ); ASSERT( len > -1 ); ASSERT( ofs + len <= LEN( data ) ); ASSERT( lifetime > 0 );
  293. resumable := caching;
  294. IF caching THEN
  295. IF len = 0 THEN (* server-side: session-id has to be generated *)
  296. idLength := SessionIdLength;
  297. (*Utils.RandomBytes( id, 0, SessionIdLength )*)
  298. CSPRNG.CSRand(id, SessionIdLength * 8);
  299. ELSE (* client-side: session-id has been generated by server *)
  300. idLength := len;
  301. FOR i := 0 TO len - 1 DO id[ i ] := data[ ofs + i ] END
  302. END
  303. END;
  304. cipherSuite := 0;
  305. SELF.lifetime := lifetime
  306. END Init;
  307. (** Marks this Session as not resumable for future Connections *)
  308. PROCEDURE Invalidate;
  309. BEGIN
  310. resumable := FALSE
  311. END Invalidate;
  312. (** Sets the PreMasterSecret contained in data, starting at ofs. The lenght of the PreMasterSecret is always 48 bytes *)
  313. PROCEDURE SetPreMasterSecret( data: ARRAY OF CHAR; ofs: LONGINT );
  314. VAR i: LONGINT;
  315. BEGIN
  316. ASSERT( LEN(data) >= ofs + 48 );
  317. FOR i := 0 TO 47 DO preMasterSecret[ i ] := data[ ofs + i ] END
  318. END SetPreMasterSecret;
  319. BEGIN { ACTIVE }
  320. NEW( timer );
  321. timer.Sleep( 1000 * lifetime );
  322. Invalidate( )
  323. END Session;
  324. Context* = OBJECT
  325. VAR
  326. policy-: Policy;
  327. rsaCertificate: ARRAY 10000 OF CHAR;
  328. rsaPrivateKey, rsaPublicKey: CryptoRSA.Key;
  329. lengthOfRsaCertificate: LONGINT;
  330. sessionCache: ARRAY SessionHashtableSize OF Session;
  331. timer: Kernel.Timer;
  332. active: BOOLEAN;
  333. PROCEDURE & Init*( p: Policy );
  334. BEGIN
  335. policy := p;
  336. NEW( timer );
  337. active := TRUE
  338. END Init;
  339. PROCEDURE Dispose*;
  340. BEGIN
  341. active := FALSE
  342. END Dispose;
  343. (** Loads the rsa-certificate specified with filename. The certificate must be DER-formatted *)
  344. PROCEDURE LoadRsaCertificate*( filename: ARRAY OF CHAR ): LONGINT;
  345. VAR
  346. f: Files.File;
  347. r: Files.Reader;
  348. i: LONGINT;
  349. BEGIN
  350. f := Files.Old(filename); (* open an old file *)
  351. IF f # NIL THEN
  352. Files.OpenReader( r, f, 0); (* open a buffer on the file *)
  353. i := 0;
  354. WHILE r.res # Streams.EOF DO
  355. rsaCertificate[ i + 6 ] := r.Get( ); (* first six bytes are length-fields of the certificate *)
  356. INC( i )
  357. END;
  358. lengthOfRsaCertificate := i-1;
  359. IF Trace THEN PrintRsaCertificate( ) END;
  360. (* length-fields *)
  361. rsaCertificate[ 0 ] := CHR( ( lengthOfRsaCertificate + 3 ) DIV ( 256 * 256 ) );
  362. rsaCertificate[ 1 ] := CHR( ( lengthOfRsaCertificate + 3 ) DIV 256 MOD 256 );
  363. rsaCertificate[ 2 ] := CHR( ( lengthOfRsaCertificate + 3 ) MOD 256 );
  364. rsaCertificate[ 3 ] := CHR( ( lengthOfRsaCertificate ) DIV ( 256 * 256 ) );
  365. rsaCertificate[ 4 ] := CHR( ( lengthOfRsaCertificate ) DIV 256 MOD 256 );
  366. rsaCertificate[ 5 ] := CHR( ( lengthOfRsaCertificate ) MOD 256 );
  367. INC( lengthOfRsaCertificate, 6 );
  368. RETURN Ok
  369. ELSE
  370. KernelLog.String("RSA Certificate file not found"); KernelLog.Ln;
  371. RETURN -1;
  372. END
  373. END LoadRsaCertificate;
  374. (** Loads the material needed to establish an rsa private key. Parameters p and q are two big prime numbers,
  375. e is the public exponent of the public key of the rsa certificate to be used. p, q and e have to be hexadecimal strings.
  376. pLen, qLen and eLen are the lengths of the hex strings *)
  377. PROCEDURE LoadRsaPrivateKey*( pHex, qHex, eHex: ARRAY OF CHAR; pLen, qLen, eLen: INTEGER );
  378. VAR
  379. p, q, e: CryptoBigNumbers.BigNumber;
  380. dummy: CryptoRSA.Key;
  381. BEGIN
  382. CryptoBigNumbers.AssignHex( p, pHex, pLen );
  383. CryptoBigNumbers.AssignHex( q, qHex, qLen );
  384. CryptoBigNumbers.AssignHex( e, eHex, eLen );
  385. NEW( SELF.rsaPrivateKey ); NEW( dummy );
  386. CryptoRSA.MakeKeys( p, q, e, "AosTLS", dummy, SELF.rsaPrivateKey );
  387. IF Trace THEN
  388. KernelLog.String("RSA-key loaded"); KernelLog.Ln;
  389. KernelLog.String(" prime p:"); KernelLog.Ln;
  390. CryptoBigNumbers.Print( p );
  391. KernelLog.String(" prime q:"); KernelLog.Ln;
  392. CryptoBigNumbers.Print( q );
  393. KernelLog.String(" public exponent:"); KernelLog.Ln;
  394. CryptoBigNumbers.Print( e );
  395. KernelLog.String(" modulus:"); KernelLog.Ln;
  396. CryptoBigNumbers.Print( SELF.rsaPrivateKey.modulus );
  397. KernelLog.String(" private exponent:"); KernelLog.Ln;
  398. CryptoBigNumbers.Print( SELF.rsaPrivateKey.exponent );
  399. END
  400. END LoadRsaPrivateKey;
  401. (** Fills rsaPublicKey from server certificate. *)
  402. PROCEDURE GetRsaPublicKey*;
  403. VAR
  404. certificate: X509.Certificate;
  405. reader: Streams.StringReader;
  406. BEGIN
  407. IF rsaPublicKey = NIL THEN
  408. (* Read X509 Certificate *)
  409. NEW(certificate);
  410. NEW(reader, lengthOfRsaCertificate);
  411. (* Skip 6 bytes: they represent the length of the certificate, but are not part of it. *)
  412. reader.SetRaw(rsaCertificate, 6, lengthOfRsaCertificate);
  413. certificate := X509.Read(reader);
  414. (* Get modulus and exponent of public key *)
  415. rsaPublicKey := certificate.publicKey;
  416. END
  417. END GetRsaPublicKey;
  418. PROCEDURE PrintRsaCertificate*;
  419. BEGIN
  420. KernelLog.String("Certificate [");KernelLog.Int(lengthOfRsaCertificate,3);KernelLog.String("]");KernelLog.Ln;
  421. KernelLog.Buffer(rsaCertificate, 6, lengthOfRsaCertificate )
  422. END PrintRsaCertificate;
  423. (** A new server-side Session-object is created and returned according to the policy settings *)
  424. PROCEDURE GetNewServerSession*( ): Session;
  425. VAR
  426. dummy: ARRAY 1 OF CHAR;
  427. s: Session;
  428. BEGIN
  429. NEW( s, policy.sessionResumptionEnabled, dummy, 0, 0, policy.sessionLifetime );
  430. RETURN s
  431. END GetNewServerSession;
  432. (** look up the session cache for a stored cache associated with the session-id of length len,
  433. starting at ofs in data. If no session is found, NIL is returned. This method is invoked by a TLS-server. *)
  434. PROCEDURE FindSessionByID*( VAR data: ARRAY OF CHAR; ofs, idLen: LONGINT ): Session;
  435. VAR
  436. i: LONGINT;
  437. current, previous: Session; (* fork search *)
  438. BEGIN
  439. ASSERT( idLen = SessionIdLength );
  440. ASSERT( idLen < 33 ); ASSERT( idLen >= 2 ); ASSERT( ofs > -1 ); ASSERT( LEN( data ) >= ofs + idLen );
  441. IF ~policy.sessionResumptionEnabled THEN RETURN NIL END;
  442. i := ( ORD( data[ ofs ] ) + 256 * ORD( data[ ofs + 1 ] ) ) MOD SessionHashtableSize;
  443. current := sessionCache[ i ];
  444. previous := sessionCache[ i ];
  445. WHILE current # NIL DO
  446. IF EqualSessionID( current.id, data, 0, ofs, idLen ) THEN
  447. IF current.resumable THEN
  448. IF current # previous THEN (* if current is NOT the first element in the list *)
  449. previous.next := current.next;
  450. current.next := sessionCache[ i ];
  451. sessionCache[ i ] := current
  452. END;
  453. RETURN current
  454. ELSE
  455. RETURN NIL
  456. END
  457. ELSE
  458. previous := current;
  459. current := current.next
  460. END
  461. END;
  462. RETURN NIL
  463. END FindSessionByID;
  464. (* stores a given Session-object in the session-cache *)
  465. PROCEDURE StoreSession( s: Session );
  466. VAR i: LONGINT;
  467. BEGIN
  468. ASSERT( s.resumable );
  469. i := ORD( s.id[ 0 ] ) + 256 * ORD( s.id[ 1 ] );
  470. i := i MOD SessionHashtableSize;
  471. s.next := sessionCache[ i ];
  472. sessionCache[ i ] := s
  473. END StoreSession;
  474. (* returns TRUE iff data1 and data2 contain the same string of length len starting at different offsets *)
  475. PROCEDURE EqualSessionID( VAR data1, data2: ARRAY OF CHAR; ofs1, ofs2, len: LONGINT ): BOOLEAN;
  476. VAR i: LONGINT;
  477. BEGIN
  478. FOR i := 0 TO len - 1 DO
  479. IF data1[ ofs1 + i ] # data2[ ofs2 + i ] THEN RETURN FALSE END;
  480. END;
  481. RETURN TRUE
  482. END EqualSessionID;
  483. (* recursive function *)
  484. PROCEDURE DeleteUnresumableSessions( s: Session ): Session;
  485. BEGIN
  486. IF s = NIL THEN RETURN NIL END; (* end of recursion *)
  487. IF s.resumable THEN
  488. s.next := DeleteUnresumableSessions( s.next );
  489. RETURN s
  490. ELSE
  491. RETURN DeleteUnresumableSessions( s.next )
  492. END
  493. END DeleteUnresumableSessions;
  494. (* delete unresumable sessions *)
  495. PROCEDURE CleanUpSessionCache;
  496. VAR i: LONGINT;
  497. BEGIN
  498. FOR i := 0 TO SessionHashtableSize - 1 DO
  499. sessionCache[ i ] := DeleteUnresumableSessions( sessionCache[ i ] )
  500. END
  501. END CleanUpSessionCache;
  502. BEGIN { ACTIVE }
  503. WHILE active DO
  504. timer.Sleep( SessionCleanUpInterval * 1000 );
  505. CleanUpSessionCache( )
  506. END
  507. END Context;
  508. Connection* = OBJECT ( TCP.Connection )
  509. VAR
  510. conn: TCP.Connection;
  511. in: Streams.Reader;
  512. out, appDataWriter: Streams.Writer;
  513. appDataReader: Streams.Reader;
  514. applicationDataPipe: Pipes.Pipe;
  515. context: Context;
  516. session: Session;
  517. tlsErrorCause -: LONGINT; (** alert type that lead to failure *)
  518. handshakeState: LONGINT;
  519. outbuf, inbuf: ARRAY Buflen OF CHAR; (* buffers for outgoing and incoming messages *)
  520. hsMD5send, hsMD5verify: CryptoMD5.Hash; (* handshake hash functions; to be used in the Finished messages *)
  521. hsSHAsend, hsSHAverify: CryptoSHA1.Hash; (* handshake hash functions; to be used in the Finished messages *)
  522. pendingSecurityParameters: SecurityParameters;
  523. currentWriteState, pendingWriteState, currentReadState, pendingReadState: ConnectionState;
  524. version -: ARRAY 2 OF CHAR;
  525. client, trapped: BOOLEAN;
  526. PROCEDURE &Init*;
  527. BEGIN
  528. state := TCP.Unused;
  529. tlsErrorCause := NoError;
  530. (* establish application-data-out-buffer *)
  531. NEW( applicationDataPipe, 1024 * 1024(*4096*) ); (* is this a good size? *)
  532. (*Streams.OpenWriter( appDataWriter, applicationDataPipe.Send );*)
  533. NEW(appDataWriter, applicationDataPipe.Send, 1024*1024);
  534. Streams.OpenReader( appDataReader, applicationDataPipe.Receive );
  535. NEW( hsMD5send ); NEW( hsSHAsend );
  536. NEW( hsMD5verify ); NEW( hsSHAverify );
  537. NEW( pendingWriteState ); NEW( currentWriteState );
  538. NEW( pendingReadState ); NEW( currentReadState );
  539. NEW( pendingSecurityParameters );
  540. hsMD5send.Initialize( ); hsSHAsend.Initialize( );
  541. hsMD5verify.Initialize( ); hsSHAverify.Initialize( )
  542. END Init;
  543. PROCEDURE AwaitStateNotEqual*(s : LONGINT);
  544. BEGIN { EXCLUSIVE}
  545. AWAIT(state # s);
  546. END AwaitStateNotEqual;
  547. PROCEDURE AwaitStateEqual*(s : LONGINT);
  548. BEGIN { EXCLUSIVE}
  549. AWAIT(state = s);
  550. END AwaitStateEqual;
  551. PROCEDURE SetState*(s : SHORTINT);
  552. BEGIN { EXCLUSIVE}
  553. state := s;
  554. END SetState;
  555. PROCEDURE ChangeWriteState;
  556. BEGIN
  557. currentWriteState := pendingWriteState;
  558. NEW( pendingWriteState )
  559. END ChangeWriteState;
  560. PROCEDURE ChangeReadState;
  561. BEGIN
  562. currentReadState := pendingReadState;
  563. NEW( pendingReadState )
  564. END ChangeReadState;
  565. (** Must be called before Open *)
  566. PROCEDURE SetContext*( cxt: Context );
  567. BEGIN
  568. ASSERT( conn = NIL );
  569. context := cxt;
  570. version[0] := cxt.policy.version[0];
  571. version[1] := cxt.policy.version[1]
  572. END SetContext;
  573. (** open a TLS connection (only use once per Connection instance). Use IP.NilPort for lport to automatically assign
  574. an unused local port. Use IP.NilAdr for fip to open a passive connection. *)
  575. PROCEDURE Open*( lport: LONGINT; fip: IP.Adr; fport: LONGINT; VAR res: WORD );
  576. BEGIN
  577. (*ASSERT( IP.IsNilAdr(fip) ); (* only server-side is implemented *)*)
  578. (*ASSERT( context # NIL );*) (* context must be set before calling Open *)
  579. ASSERT( conn = NIL ); (* invoke this method only once per instance *)
  580. IF context=NIL THEN
  581. SetDefaultPolicy
  582. END;
  583. client := ~IP.IsNilAdr(fip);
  584. (* open TCPConnection *)
  585. NEW( SELF.conn );
  586. SELF.conn.Open( lport, fip, fport, res );
  587. IF res # TCP.Ok THEN RETURN END;
  588. SetState(conn.state);
  589. res := Ok;
  590. IF client THEN Connect END;
  591. ASSERT( conn # NIL )
  592. END Open;
  593. PROCEDURE SetDefaultPolicy*;
  594. VAR ctx:Context;
  595. BEGIN
  596. NEW(ctx, defaultCipherPolicy);
  597. SetContext(ctx);
  598. END SetDefaultPolicy;
  599. (* set a TCP Connection for communication; this method should only be invoked by the Accept-method *)
  600. PROCEDURE SetConnection*( c: TCP.Connection );
  601. BEGIN
  602. ASSERT( conn = NIL );
  603. ASSERT( State()= TCP.Unused );
  604. conn := c;
  605. Streams.OpenReader( in, SELF.conn.Receive ); Streams.OpenWriter( out, SELF.conn.Send );
  606. SetState(ServerHandshake);
  607. handshakeState := AwaitClientHello
  608. END SetConnection;
  609. (** Call this method only on a passive (listenig server-side) TLS.Connection. Non blocking *)
  610. PROCEDURE Accept*( VAR client: TCP.Connection; VAR res: WORD );
  611. VAR
  612. newTLSConn: Connection;
  613. newTCPConn: TCP.Connection;
  614. BEGIN
  615. ASSERT( State() = TCP.Listen );
  616. ASSERT ( SELF.conn # NIL );
  617. SELF.conn.Accept( newTCPConn, res );
  618. IF res # TCP.Ok THEN RETURN END;
  619. NEW( newTLSConn );
  620. newTLSConn.SetContext( SELF.context );
  621. newTLSConn.SetConnection( newTCPConn );
  622. client := newTLSConn;
  623. res := Ok
  624. END Accept;
  625. (** Sets up the TCP connection for a client-side connection. *)
  626. PROCEDURE Connect*;
  627. BEGIN
  628. Streams.OpenReader( in, SELF.conn.Receive );
  629. Streams.OpenWriter( out, SELF.conn.Send );
  630. SetState(ClientHandshake);
  631. handshakeState := GenerateClientHello
  632. END Connect;
  633. (** Close this TLS.Connection *)
  634. PROCEDURE Close*;
  635. BEGIN
  636. IF Trace THEN KernelLog.String("Close"); KernelLog.Ln; END;
  637. ASSERT( SELF.conn # NIL );
  638. IF ( State() = TCP.Established ) OR ( State() = ServerHandshake ) THEN
  639. SendWarning( CloseNotify )
  640. END;
  641. conn.Close();
  642. applicationDataPipe.Close();
  643. handshakeState := NotAValidHandshakeState;
  644. SetState(TCP.Closed);
  645. END Close;
  646. (** Send secured data *)
  647. PROCEDURE Send*( CONST data: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD );
  648. VAR i, size: LONGINT;
  649. BEGIN {EXCLUSIVE}
  650. AWAIT((state = TCP.Established) OR (state = TCP.Closed));
  651. IF state = TCP.Established THEN
  652. WHILE len > 0 DO
  653. IF Trace THEN PrintDirection(TRUE); KernelLog.String("Application Data");KernelLog.Ln END;
  654. size := len;
  655. IF size > MaxPlaintextLength THEN size := MaxPlaintextLength END;
  656. FOR i := 0 TO size-1 DO
  657. outbuf[ i ] := data[ ofs + i ]
  658. END;
  659. SendRecord( outbuf, ApplicationData, 0, size );
  660. INC( ofs, size );
  661. DEC( len, size )
  662. END
  663. ELSE
  664. res := Streams.EOF;
  665. END;
  666. END Send;
  667. (** Receive secured data *)
  668. PROCEDURE Receive*( VAR data: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD);
  669. BEGIN
  670. applicationDataPipe.Receive(data, ofs, size, min, len ,res);
  671. END Receive;
  672. (* Generates the MasterSecret for the current session as described in rfc 2246, section 8 *)
  673. PROCEDURE GenerateMasterSecret;
  674. VAR
  675. prf: PRF;
  676. seed: ARRAY 64 OF CHAR;
  677. i: LONGINT;
  678. BEGIN
  679. FOR i := 0 TO 31 DO
  680. seed[ i ] := SELF.pendingSecurityParameters.clientRandom[ i ];
  681. seed[ i + 32 ] := SELF.pendingSecurityParameters.serverRandom[ i ]
  682. END;
  683. NEW( prf, pendingSecurityParameters.PRFAlgorithm );
  684. prf.GetBytes( SELF.session.preMasterSecret, seed, SELF.session.masterSecret, "master secret", 48, 64, 48 );
  685. (* discard preMasterSecret *)
  686. FOR i := 0 TO 47 DO SELF.session.preMasterSecret[ i ] := CHR( 0 ) END
  687. END GenerateMasterSecret;
  688. (* Generates key-material for the pending state *)
  689. PROCEDURE GenerateKeys;
  690. VAR
  691. prf: PRF;
  692. keyBlock: ARRAY 136 OF CHAR;
  693. seed: ARRAY 64 OF CHAR;
  694. i, keyBlockLen, ofs, macSecretSize, cipherKeySize, cipherBlockSize: LONGINT;
  695. BEGIN
  696. (* calculate the needed amount of key-material *)
  697. macSecretSize := SELF.pendingWriteState.mac.size;
  698. cipherKeySize := SELF.pendingSecurityParameters.cipherKeySize;
  699. IF SELF.pendingWriteState.cipher # NIL THEN
  700. cipherBlockSize := SELF.pendingWriteState.cipher.blockSize
  701. ELSE
  702. cipherBlockSize := 0
  703. END;
  704. keyBlockLen := 2 * macSecretSize + 2 * cipherKeySize;
  705. IF cipherBlockSize > 1 THEN (* if a blockcipher is used, initialization vectors are needed *)
  706. INC( keyBlockLen, 2 * cipherBlockSize )
  707. END;
  708. ASSERT( keyBlockLen <= 136 ); (* AES-256-CBC-SHA needs 136 bytes of keymaterial. all others need less *)
  709. FOR i := 0 TO 31 DO
  710. seed[ i ] := SELF.pendingSecurityParameters.serverRandom[ i ];
  711. seed[ i + 32 ] := SELF.pendingSecurityParameters.clientRandom[ i ]
  712. END;
  713. NEW( prf, pendingSecurityParameters.PRFAlgorithm );
  714. prf.GetBytes( SELF.session.masterSecret, seed, keyBlock, "key expansion", 48, 64, keyBlockLen );
  715. (* mac secret *)
  716. FOR i := 0 TO macSecretSize - 1 DO
  717. IF client THEN
  718. SELF.pendingWriteState.macSecret[ i ] := keyBlock[ i ];
  719. SELF.pendingReadState.macSecret[ i ] := keyBlock[ macSecretSize + i ]
  720. ELSE
  721. SELF.pendingReadState.macSecret[ i ] := keyBlock[ i ];
  722. SELF.pendingWriteState.macSecret[ i ] := keyBlock[ macSecretSize + i ]
  723. END
  724. END;
  725. (* keys for encryption and decription *)
  726. ofs := 2 * macSecretSize;
  727. FOR i := 0 TO cipherKeySize - 1 DO
  728. IF client THEN
  729. SELF.pendingWriteState.cipherKey[ i ] := keyBlock[ ofs + i ];
  730. SELF.pendingReadState.cipherKey[ i ] := keyBlock[ ofs + cipherKeySize + i ]
  731. ELSE
  732. SELF.pendingReadState.cipherKey[ i ] := keyBlock[ ofs + i ];
  733. SELF.pendingWriteState.cipherKey[ i ] := keyBlock[ ofs + cipherKeySize + i ]
  734. END
  735. END;
  736. (* initialization vectors *)
  737. IF cipherBlockSize > 1 THEN
  738. ofs := 2 * macSecretSize + 2 * cipherKeySize;
  739. FOR i := 0 TO cipherBlockSize - 1 DO
  740. IF client THEN
  741. SELF.pendingWriteState.iv[ i ] := keyBlock[ ofs + i ];
  742. SELF.pendingReadState.iv[ i ] := keyBlock[ ofs + cipherBlockSize + i ]
  743. ELSE
  744. SELF.pendingReadState.iv[ i ] := keyBlock[ ofs + i ];
  745. SELF.pendingWriteState.iv[ i ] := keyBlock[ ofs + cipherBlockSize + i ]
  746. END
  747. END
  748. END
  749. END GenerateKeys;
  750. (* initializes a given ConnectionState with the key material contained in the ConnectionState and in
  751. the given SecurityParameters *)
  752. PROCEDURE InitializeConnectionState( state: ConnectionState; sp: SecurityParameters );
  753. BEGIN
  754. IF state.cipher # NIL THEN
  755. state.cipher.InitKey( state.cipherKey, 8 * sp.cipherKeySize );
  756. IF state.cipher.blockSize > 0 THEN
  757. state.cipher.SetIV( state.iv, Ciphers.CBC )
  758. END
  759. END
  760. END InitializeConnectionState;
  761. PROCEDURE PrepareConnectionState( state: ConnectionState; cipherSuite: LONGINT ; VAR res : WORD);
  762. BEGIN
  763. ASSERT( cipherSuite # 0 );
  764. res := Ok;
  765. CASE cipherSuite OF
  766. | TlsRsaWithNullMd5:
  767. NEW( state.mac, "CryptoMD5" );
  768. state.cipher := NIL;
  769. | TlsRsaWithNullSha:
  770. NEW( state.mac, "CryptoSHA1" );
  771. state.cipher := NIL;
  772. | TlsRsaWithRc4128Md5:
  773. NEW( state.mac, "CryptoMD5" );
  774. state.cipher := Ciphers.NewCipher( "CryptoARC4" );
  775. | TlsRsaWithRc4128Sha:
  776. NEW( state.mac, "CryptoSHA1" );
  777. state.cipher := Ciphers.NewCipher( "CryptoARC4" );
  778. | TlsRsaWithIdeaCbcSha:
  779. NEW( state.mac, "CryptoSHA1" );
  780. state.cipher := Ciphers.NewCipher( "CryptoIDEA" );
  781. | TlsRsaWithDesCbcSha:
  782. NEW( state.mac, "CryptoSHA1" );
  783. state.cipher := Ciphers.NewCipher( "CryptoDES" );
  784. | TlsRsaWith3DesEdeCbcSha:
  785. NEW( state.mac, "CryptoSHA1" );
  786. state.cipher := Ciphers.NewCipher( "CryptoDES3" );
  787. | TlsRsaWithAes128CbcSha, TlsRsaWithAes256CbcSha:
  788. NEW( state.mac, "CryptoSHA1" );
  789. state.cipher := Ciphers.NewCipher( "CryptoAES" );
  790. ELSE
  791. res := -1;
  792. END;
  793. END PrepareConnectionState;
  794. PROCEDURE PrepareSecurityParameters( sp: SecurityParameters; cipherSuite: LONGINT ; VAR res : WORD);
  795. BEGIN
  796. ASSERT( cipherSuite # 0 );
  797. res := Ok;
  798. sp.cipherSuite := cipherSuite;
  799. CASE cipherSuite OF
  800. | TlsRsaWithNullMd5:
  801. sp.cipherKeySize := 0;
  802. | TlsRsaWithNullSha:
  803. sp.cipherKeySize := 0;
  804. | TlsRsaWithRc4128Md5:
  805. sp.cipherKeySize := 16;
  806. | TlsRsaWithRc4128Sha:
  807. sp.cipherKeySize := 16;
  808. | TlsRsaWithIdeaCbcSha:
  809. sp.cipherKeySize := 16;
  810. | TlsRsaWithDesCbcSha:
  811. sp.cipherKeySize := 8;
  812. | TlsRsaWith3DesEdeCbcSha:
  813. sp.cipherKeySize := 24;
  814. | TlsRsaWithAes128CbcSha:
  815. sp.cipherKeySize := 16;
  816. | TlsRsaWithAes256CbcSha:
  817. sp.cipherKeySize := 32
  818. ELSE
  819. res := -1
  820. END;
  821. IF version[1] < 3X THEN
  822. sp.PRFAlgorithm := "SHA1 XOR MD5"
  823. ELSE
  824. sp.PRFAlgorithm := "CryptoSHA256"
  825. END
  826. END PrepareSecurityParameters;
  827. (* **********************************************************************************
  828. RECORD LAYER
  829. ********************************************************************************** *)
  830. PROCEDURE SendRecord( VAR data: ARRAY OF CHAR; contentType, ofs, len: LONGINT );
  831. VAR
  832. macInput: ARRAY 13 OF CHAR;
  833. iv: ARRAY 16 OF CHAR; (* used in TLSv1.1 *)
  834. i, length, padLen, blocksize: LONGINT;
  835. sendIV: BOOLEAN; (* Send an IV before data *)
  836. BEGIN
  837. ASSERT( len <= MaxPlaintextLength );
  838. (* increment the number of sent records *)
  839. currentWriteState.recordSeq.Inc( );
  840. length := len;
  841. (* data compression: no other algo than NULL is implemented *)
  842. (* mac *)
  843. IF currentWriteState.mac # NIL THEN
  844. currentWriteState.recordSeq.GetBytes( macInput, 0 );
  845. macInput[ 8 ] := CHR( contentType );
  846. macInput[ 9 ] := version[ 0 ];
  847. macInput[ 10 ] := version[ 1 ];
  848. macInput[ 11 ] := CHR( len DIV 256 );
  849. macInput[ 12 ] := CHR( len );
  850. currentWriteState.mac.Initialize( currentWriteState.macSecret, currentWriteState.mac.size );
  851. currentWriteState.mac.Update( macInput, 0, 13 );
  852. currentWriteState.mac.Update( data, ofs, len );
  853. currentWriteState.mac.GetMac( data, ofs+len );
  854. INC( length, currentWriteState.mac.size )
  855. END;
  856. (* encryption *)
  857. IF currentWriteState.cipher # NIL THEN (* encryption has to be done *)
  858. blocksize := currentWriteState.cipher.blockSize;
  859. IF blocksize > 1 THEN (* padding for encryption has to be added *)
  860. sendIV := ORD(version[1]) >= 2;
  861. IF sendIV THEN (* TLSv1.1 and greater has an additional IV field *)
  862. CSPRNG.CSRand(iv, blocksize * 8);
  863. currentWriteState.cipher.Encrypt(iv, 0, blocksize);
  864. END;
  865. padLen := ( blocksize - ( ( length + 1 ) MOD blocksize ) ) MOD blocksize; (* padLen = [ 0, blocksize-1 ] *)
  866. IF padLen > 0 THEN
  867. ASSERT(padLen < 255);
  868. FOR i := 0 TO padLen - 1 DO data[ ofs + length + i ] := CHR( padLen MOD 100H) END
  869. END;
  870. data[ ofs + length + padLen ] := CHR( padLen MOD 100H );
  871. length := length + padLen + 1
  872. END;
  873. ASSERT(length MOD blocksize = 0);
  874. currentWriteState.cipher.Encrypt( data, ofs, length );
  875. END;
  876. IF sendIV THEN INC(length, blocksize) END;
  877. (* record header *)
  878. out.Char( CHR( contentType ) );
  879. out.Char( version[0] );
  880. out.Char( version[1] );
  881. out.Char( CHR( length DIV 256 ) );
  882. out.Char( CHR( length ) );
  883. IF sendIV THEN out.Bytes(iv, 0, blocksize); DEC(length, blocksize) END;
  884. out.Bytes( data, ofs, length );
  885. out.Update;
  886. END SendRecord;
  887. (* receive one record *)
  888. PROCEDURE ReceiveRecord;
  889. VAR
  890. macInput: ARRAY 13 OF CHAR;
  891. verify: ARRAY 20 OF CHAR;
  892. i, padd, length, len, type, macSize, res, major, minor, ofs: LONGINT;
  893. badRecordMac: BOOLEAN; (* Send a bad_record_mac error *)
  894. BEGIN
  895. (* increment the number of received records *)
  896. currentReadState.recordSeq.Inc( );
  897. (* record header *)
  898. type := ORD( in.Get( ) ); (* content type *)
  899. IF type = 128 THEN (* SSLv2-compatible ClientHello *)
  900. len := ORD( in.Get() );
  901. in.Bytes( inbuf, 0, len, length );
  902. IF len = length THEN
  903. ReceiveV2Handshake( inbuf, 0, len );
  904. RETURN
  905. ELSE
  906. SendError( InternalError );
  907. RETURN
  908. END
  909. END;
  910. major := ORD( in.Get() ); minor := ORD( in.Get() );
  911. (*IF ( major # 3 ) OR ( minor # 1) THEN END; (* version control *)*)
  912. IF (major # ORD(version[0])) OR (minor # ORD(version[1])) THEN
  913. SendError( ProtocolVersion );
  914. RETURN
  915. END;
  916. len := 256 * ORD( in.Get() ) + ORD( in.Get() ); (* length of payload *)
  917. IF len > MaxCiphertextLength THEN
  918. SendError( RecordOverflow );
  919. RETURN
  920. END;
  921. (* payload *)
  922. in.Bytes( inbuf, 0, len, length );
  923. IF in.res # Streams.Ok THEN
  924. IF Trace THEN KernelLog.String("Can't read record: supposed to read:"); KernelLog.Int(len, 7); KernelLog.String(" read: "); KernelLog.Int(length,7);END;
  925. RETURN
  926. END;
  927. (* records with unknown client protocol type are ignored; type=128: SSLv2-compatible ClientHello *)
  928. IF ( type = 128 ) OR ( type < 20 ) OR ( type > 23 ) THEN RETURN END;
  929. IF length # len THEN
  930. SendError( IllegalParameter );
  931. RETURN
  932. END;
  933. (* decryption *)
  934. IF currentReadState.cipher # NIL THEN
  935. IF (currentReadState.cipher.blockSize > 1) & (len MOD currentReadState.cipher.blockSize # 0) THEN
  936. badRecordMac := TRUE;
  937. DEC(len, len MOD currentReadState.cipher.blockSize)
  938. END;
  939. currentReadState.cipher.Decrypt( inbuf, 0, len );
  940. IF (minor >= 2) & (currentReadState.cipher.blockSize > 1) THEN INC(ofs, currentReadState.cipher.blockSize); DEC(len, ofs) END;
  941. IF res # Ciphers.Ok THEN
  942. IF Trace THEN KernelLog.String("There was a Problem while decrypting record.");KernelLog.Ln END;
  943. (*SendError( InternalError );
  944. RETURN*)
  945. badRecordMac := TRUE
  946. END;
  947. IF currentReadState.cipher.blockSize > 1 THEN (* padding has to be removed *)
  948. padd := ORD(inbuf[ofs + len - 1]);
  949. KernelLog.Enter; KernelLog.Buffer(inbuf, ofs, len); KernelLog.Exit;
  950. FOR i := 0 TO padd DO (* check padding *)
  951. IF ofs + len - i - 1 < 0 THEN badRecordMac := TRUE
  952. ELSIF ORD(inbuf[ofs + len - i - 1]) # padd THEN badRecordMac := TRUE END
  953. END;
  954. IF len - padd - 1 < currentReadState.mac.size THEN
  955. badRecordMac := TRUE
  956. ELSE
  957. len := len - padd - 1
  958. END
  959. END
  960. END;
  961. (* mac verification *)
  962. IF currentReadState.mac # NIL THEN
  963. macSize := currentReadState.mac.size;
  964. len := len - macSize;
  965. currentReadState.recordSeq.GetBytes( macInput, 0 );
  966. macInput[ 8 ] := CHR( type );
  967. macInput[ 9 ] := CHR( major );
  968. macInput[ 10 ] := CHR( minor );
  969. macInput[ 11 ] := CHR( len DIV 256 );
  970. macInput[ 12 ] := CHR( len );
  971. currentReadState.mac.Initialize( currentReadState.macSecret, macSize );
  972. currentReadState.mac.Update( macInput, 0, 13 );
  973. currentReadState.mac.Update( inbuf, ofs, len );
  974. currentReadState.mac.GetMac( verify, 0 );
  975. IF ~badRecordMac THEN
  976. FOR i := 0 TO macSize - 1 DO
  977. IF inbuf[ ofs + len + i ] # verify[ i ] THEN
  978. badRecordMac := TRUE
  979. END
  980. (*SendError( BadRecordMac );
  981. RETURN*)
  982. END
  983. END;
  984. END;
  985. IF badRecordMac THEN
  986. SendError( BadRecordMac );
  987. RETURN
  988. END;
  989. (* data compression: no other algo than NULL is implemented *)
  990. (* dispatching *)
  991. CASE type OF
  992. | Handshake:
  993. ReceiveHandshake( inbuf, ofs, len )
  994. | ApplicationData:
  995. appDataWriter.Bytes( inbuf, ofs, len );
  996. appDataWriter.Update;
  997. | Alert:
  998. ASSERT( len = 2 );
  999. ReceiveAlert( inbuf, ofs, len )
  1000. | ChangeCipherSpec:
  1001. ASSERT( len = 1 );
  1002. Transition( inbuf, ChangeCipherSpec, 0, ofs, len )
  1003. ELSE
  1004. (* Unknown record type, send unexpected_message *)
  1005. SendError( UnexpectedMessage );
  1006. RETURN
  1007. END;
  1008. END ReceiveRecord;
  1009. (* **********************************************************************************
  1010. CHANGE CIPHER SPEC PROTOCOL
  1011. ********************************************************************************** *)
  1012. PROCEDURE SendChangeCipherSpec;
  1013. BEGIN
  1014. IF Trace THEN PrintDirection(TRUE); KernelLog.String("ChangeCipherSpec");KernelLog.Ln END;
  1015. outbuf[ 0 ] := CHR( 1 );
  1016. SendRecord( outbuf, ChangeCipherSpec, 0, 1 );
  1017. ChangeWriteState( )
  1018. END SendChangeCipherSpec;
  1019. PROCEDURE ReceiveChangeCipherSpec( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  1020. BEGIN
  1021. IF Trace THEN PrintDirection(FALSE); KernelLog.String("ChangeCipherSpec");KernelLog.Ln END;
  1022. IF ORD( data[ ofs ] ) # 1 THEN (* wrong content of ChangeCipherSpec *)
  1023. SendError( IllegalParameter )
  1024. ELSE
  1025. ChangeReadState( )
  1026. END
  1027. END ReceiveChangeCipherSpec;
  1028. (* **********************************************************************************
  1029. HANDSHAKE PROTOCOL
  1030. ********************************************************************************** *)
  1031. PROCEDURE SendHandshake( VAR data: ARRAY OF CHAR; hsType, ofs, len: LONGINT );
  1032. VAR l: LONGINT;
  1033. BEGIN
  1034. ASSERT( len < 256 * 256 * 256 );
  1035. l := len;
  1036. data[ ofs ] := CHR( hsType );
  1037. data[ ofs + 3 ] := CHR( l MOD 256 ); l := l DIV 256;
  1038. data[ ofs + 2 ] := CHR( l MOD 256 ); l := l DIV 256;
  1039. data[ ofs + 1 ] := CHR( l MOD 256 );
  1040. IF hsType # HelloRequest THEN
  1041. (* update the digests used in the finished-messages *)
  1042. IF (hsType # Finished) OR (hsType # ClientHello) THEN (* Finished-msg doesn't contain digest of itself *)
  1043. hsMD5send.Update( data, ofs, len + 4 );
  1044. hsSHAsend.Update( data, ofs, len + 4 )
  1045. END;
  1046. hsMD5verify.Update( data, ofs, len + 4 );
  1047. hsSHAverify.Update( data, ofs, len + 4 )
  1048. END;
  1049. SendRecord( data, Handshake, ofs, len + 4 );
  1050. END SendHandshake;
  1051. (* receives one or more handshake messages *)
  1052. PROCEDURE ReceiveHandshake( VAR data: ARRAY OF CHAR; ofs, len: LONGINT );
  1053. VAR msgLen, hsType, ptr: LONGINT;
  1054. BEGIN
  1055. ASSERT( LEN( data ) >= ofs + len );
  1056. ptr := ofs;
  1057. WHILE ptr < ofs + len DO (* for each handshake message *)
  1058. hsType := ORD( data[ ptr ] ); (* handshake type *)
  1059. msgLen := 256 * 256 * ORD( data[ ptr + 1 ] ) + 256 * ORD( data[ ptr + 2 ] ) + ORD( data[ ptr + 3 ] );
  1060. (* update the digests used in the finished-messages *)
  1061. hsMD5send.Update( data, ptr, msgLen + 4 );
  1062. hsSHAsend.Update( data, ptr, msgLen + 4 );
  1063. IF hsType # Finished THEN (* Finished-msg doesn't contain digest of itself *)
  1064. hsMD5verify.Update( data, ptr, msgLen + 4 );
  1065. hsSHAverify.Update( data, ptr, msgLen + 4 )
  1066. END;
  1067. Transition( data, Handshake, hsType, ptr + 4, msgLen );
  1068. ptr := ptr + 4 + msgLen
  1069. END
  1070. END ReceiveHandshake;
  1071. PROCEDURE ReceiveV2Handshake( VAR data: ARRAY OF CHAR; ofs, len: LONGINT );
  1072. BEGIN
  1073. ASSERT( data[ofs] = CHR( 1 ) ); (* v2ClientHello *)
  1074. (* re-initialize hashes *)
  1075. hsMD5send.Initialize( ); hsSHAsend.Initialize( );
  1076. hsMD5verify.Initialize( ); hsSHAverify.Initialize( );
  1077. (* update the digests used in the finished-messages *)
  1078. hsMD5send.Update( data, ofs, len );
  1079. hsSHAsend.Update( data, ofs, len );
  1080. hsMD5verify.Update( data, ofs, len );
  1081. hsSHAverify.Update( data, ofs, len );
  1082. Transition( data, Handshake, V2ClientHello, ofs, len );
  1083. END ReceiveV2Handshake;
  1084. PROCEDURE StartHandshake;
  1085. BEGIN
  1086. Streams.OpenReader( in, SELF.conn.Receive );
  1087. Streams.OpenWriter( out, SELF.conn.Send );
  1088. SetState(ClientHandshake);
  1089. handshakeState := GenerateClientHello;
  1090. Transition(outbuf, Handshake, 0, 0, 0)
  1091. END StartHandshake;
  1092. PROCEDURE ReceiveClientHello( VAR data: ARRAY OF CHAR; ofs, len: LONGINT ): LONGINT;
  1093. VAR
  1094. nofSuites, i, idLen, idPos, pos, cipherSuite, major, minor: LONGINT; res: WORD;
  1095. BEGIN
  1096. IF Trace THEN PrintDirection(FALSE); KernelLog.String("ClientHello");KernelLog.Ln END;
  1097. pos := ofs;
  1098. (* version check *)
  1099. major := ORD( data[ pos ] ); minor := ORD( data[ pos + 1 ] );
  1100. IF Trace THEN KernelLog.String(" version: ");KernelLog.Int(major,1);KernelLog.String(".");KernelLog.Int(minor,1);KernelLog.Ln END;
  1101. IF ( major < 3 ) OR ( minor < 1 ) THEN (* fatal error: protocol version not supported *)
  1102. SendError( ProtocolVersion );
  1103. RETURN -1
  1104. END;
  1105. INC( pos, 2 );
  1106. (* 32 bytes client random *)
  1107. FOR i := 0 TO 31 DO pendingSecurityParameters.clientRandom[ i ] := data[ pos + i ] END;
  1108. INC( pos, 32 );
  1109. IF Trace THEN KernelLog.String("SERVER client random:"); KernelLog.Ln; KernelLog.Buffer(pendingSecurityParameters.clientRandom, 0, 32); KernelLog.Ln END;
  1110. (* session id *)
  1111. idLen := ORD( data[ pos ] );
  1112. idPos := pos + 1;
  1113. INC( pos, idLen + 1 );
  1114. (* cipher-suites *)
  1115. nofSuites := (256 * ORD( data[ pos ] ) + ORD( data[ pos + 1 ] )) DIV 2; (* number of cipher-suites supported by the client *)
  1116. INC( pos, 2 );
  1117. IF idLen = SessionIdLength THEN (* client attempted session resumption *)
  1118. session := context.FindSessionByID( data, idPos, idLen );
  1119. IF session # NIL THEN
  1120. (* check: is the resumed session's cipher-suite contained by the client-hello ? *)
  1121. FOR i := 0 TO nofSuites - 1 DO
  1122. cipherSuite := 256 * ORD( data[ pos + 2 * i ] ) + ORD( data[ pos + 2 * i + 1 ] );
  1123. IF cipherSuite = session.cipherSuite THEN (* session resumption *)
  1124. pendingSecurityParameters.cipherSuite := session.cipherSuite;
  1125. IF Trace THEN KernelLog.String("ciphersuite: ");KernelLog.Int(pendingSecurityParameters.cipherSuite, 8 );KernelLog.Ln END;
  1126. RETURN GenerateHelloWithResumption
  1127. END
  1128. END
  1129. END
  1130. END;
  1131. (* establish new session *)
  1132. session := context.GetNewServerSession( );
  1133. (* choose cipher-suite *)
  1134. i := 0;
  1135. LOOP
  1136. cipherSuite := 256 * ORD( data[ pos + 2 * i ] ) + ORD( data[ pos + 2 * i + 1 ] );
  1137. IF Trace THEN KernelLog.String("Server: client accepts cipher suite: "); KernelLog.Int(cipherSuite, 0); KernelLog.Ln END;
  1138. IF context.policy.IsSupported( cipherSuite ) THEN
  1139. EXIT
  1140. END;
  1141. INC( i );
  1142. IF i = nofSuites THEN EXIT END
  1143. END;
  1144. IF cipherSuite = 0 THEN (* no compatible cipher-suite found *)
  1145. IF Trace THEN KernelLog.String("Server: No common cipher suite found"); KernelLog.Ln END;
  1146. SendError( HandshakeFailure );
  1147. RETURN -1
  1148. END;
  1149. SELF.session.cipherSuite := cipherSuite;
  1150. PrepareSecurityParameters( pendingSecurityParameters, cipherSuite, res );
  1151. IF res < 0 THEN
  1152. IF Trace THEN KernelLog.String("Server: Error preparing cipher suite"); KernelLog.Ln END;
  1153. SendError( HandshakeFailure );
  1154. RETURN -1
  1155. END;
  1156. PrepareConnectionState( pendingWriteState, cipherSuite, res );
  1157. IF res < 0 THEN
  1158. IF Trace THEN KernelLog.String("Server: Error preparing pending write state"); KernelLog.Ln END;
  1159. SendError( HandshakeFailure );
  1160. RETURN -1
  1161. END;
  1162. PrepareConnectionState( pendingReadState, cipherSuite, res );
  1163. IF res < 0 THEN
  1164. IF Trace THEN KernelLog.String("Server: Error preparing pending read state"); KernelLog.Ln END;
  1165. SendError( HandshakeFailure );
  1166. RETURN -1
  1167. END;
  1168. (* ignore compression method *)
  1169. RETURN GenerateServerHello
  1170. END ReceiveClientHello;
  1171. PROCEDURE SendClientHello(VAR data: ARRAY OF CHAR; ofs: LONGINT);
  1172. VAR
  1173. pos, i: LONGINT;
  1174. BEGIN
  1175. IF Trace THEN PrintDirection(TRUE); KernelLog.String("ClientHello");KernelLog.Ln END;
  1176. ASSERT( ofs > 3 );
  1177. pos := ofs;
  1178. (* client version *)
  1179. data[ pos ] := version[ 0 ]; data[ pos + 1 ] := version[ 1 ]; (* only 3.1 is supported *)
  1180. INC( pos, 2 );
  1181. (* client random bytes generation*)
  1182. Create32RandomBytes( pendingSecurityParameters.clientRandom );
  1183. FOR i := 0 TO 31 DO data[ pos + i ] := pendingSecurityParameters.clientRandom[ i ] END; (* copy random to outbuf *)
  1184. INC( pos, 32 );
  1185. (* session-id *)
  1186. IF session # NIL THEN
  1187. (* if a previous session is available, ask server to resume it. *)
  1188. data[ pos ] := CHR( session.idLength );
  1189. INC(pos);
  1190. FOR i := 0 TO session.idLength - 1 DO data[pos + i] := session.id[i] END;
  1191. INC(pos, session.idLength)
  1192. ELSE
  1193. data[pos] := 0X;
  1194. INC(pos)
  1195. END;
  1196. (* cipher-suite: length, then suite *)
  1197. data[pos] := CHR((2 * context.policy.nofCipherSuites) DIV 256);
  1198. data[pos + 1] := CHR((2 * context.policy.nofCipherSuites) MOD 256);
  1199. INC(pos, 2);
  1200. FOR i := 0 TO context.policy.nofCipherSuites - 1 DO
  1201. data[ pos ] := CHR(context.policy.cipherSuites[i] DIV 256);
  1202. data[ pos + 1 ] := CHR(context.policy.cipherSuites[i] MOD 256);
  1203. INC( pos, 2 )
  1204. END;
  1205. (* compression-method *)
  1206. data[ pos ] := 1X;
  1207. INC( pos );
  1208. data[ pos ] := 0X;
  1209. INC( pos );
  1210. SendHandshake( data, ClientHello, ofs - 4, pos - ofs)
  1211. END SendClientHello;
  1212. PROCEDURE ReceiveV2ClientHello( VAR data: ARRAY OF CHAR; ofs, len: LONGINT ): LONGINT;
  1213. VAR nofSuites, idLen, challengeLen, i, cipherSuite: LONGINT; res: WORD;
  1214. BEGIN
  1215. IF Trace THEN PrintDirection(FALSE); KernelLog.String("SSLv2.0 ClientHello");KernelLog.Ln END;
  1216. nofSuites := ( 256 * ORD(data[ofs+3]) + ORD(data[ofs+4]) ) DIV 3;
  1217. idLen := 256 * ORD(data[ofs+5]) + ORD(data[ofs+6]);
  1218. challengeLen := 256 * ORD(data[ofs+7]) + ORD(data[ofs+8]);
  1219. (* if an SSLv2.0-ClientHello is received, a new session has to be established, because a client sends an TLSv1.0-ClientHello when resuming a session *)
  1220. session := context.GetNewServerSession( );
  1221. (* choose cipher-suite *)
  1222. INC( ofs, 9);
  1223. i := 0;
  1224. LOOP
  1225. cipherSuite := 256*256*ORD( data[ ofs + 3 * i ] ) + 256 * ORD( data[ ofs + 3 * i + 1 ] ) + ORD( data[ ofs + 3 * i + 2 ] );
  1226. IF context.policy.IsSupported( cipherSuite ) THEN
  1227. EXIT
  1228. END;
  1229. INC( i );
  1230. IF (i = nofSuites) OR (ofs + 3 * i + 2 >= LEN(data)) THEN EXIT END
  1231. END;
  1232. IF cipherSuite = 0 THEN (* no compatible cipher-suite found *)
  1233. SendError( HandshakeFailure );
  1234. RETURN -1
  1235. END;
  1236. SELF.session.cipherSuite := cipherSuite;
  1237. PrepareSecurityParameters( pendingSecurityParameters, cipherSuite, res );
  1238. IF res < 0 THEN
  1239. SendError( HandshakeFailure );
  1240. RETURN -1
  1241. END;
  1242. PrepareConnectionState( pendingWriteState, cipherSuite, res );
  1243. IF res < 0 THEN
  1244. SendError( HandshakeFailure );
  1245. RETURN -1
  1246. END;
  1247. PrepareConnectionState( pendingReadState, cipherSuite, res );
  1248. IF res < 0 THEN
  1249. SendError( HandshakeFailure );
  1250. RETURN -1
  1251. END;
  1252. INC( ofs, nofSuites * 3 );
  1253. (* session id *)
  1254. IF idLen = SessionIdLength THEN (* client attempted session resumption *)
  1255. session := context.FindSessionByID( data, ofs, idLen );
  1256. IF session # NIL THEN
  1257. RETURN GenerateHelloWithResumption
  1258. END
  1259. END;
  1260. INC( ofs, idLen );
  1261. (* 32 bytes client random *)
  1262. FOR i := 0 TO 31-challengeLen DO pendingSecurityParameters.clientRandom[ i ] := CHR(0) END;
  1263. FOR i := 0 TO challengeLen-1 DO pendingSecurityParameters.clientRandom[ 32-challengeLen + i ] := data[ ofs + i ] END;
  1264. RETURN GenerateServerHello
  1265. END ReceiveV2ClientHello;
  1266. PROCEDURE ReceiveServerHello(VAR data: ARRAY OF CHAR; ofs, len: LONGINT): LONGINT;
  1267. VAR
  1268. pos, major, minor, i, idLen, idPos, cipherSuite: LONGINT; res: WORD;
  1269. BEGIN
  1270. IF Trace THEN PrintDirection(FALSE); KernelLog.String("ServerHello");KernelLog.Ln END;
  1271. pos := ofs;
  1272. (* version check *)
  1273. major := ORD( data[ pos ] ); minor := ORD( data[ pos + 1 ] );
  1274. IF ( major < 3 ) OR ( minor < 1 ) THEN (* fatal error: protocol version not supported *)
  1275. IF Trace THEN KernelLog.String("Incompatible protocol version"); KernelLog.Ln END;
  1276. RETURN -1
  1277. END;
  1278. INC( pos, 2 );
  1279. (* 32 bytes server random *)
  1280. FOR i := 0 TO 31 DO pendingSecurityParameters.serverRandom[ i ] := data[ pos + i ] END;
  1281. INC( pos, 32 );
  1282. (* session id *)
  1283. idLen := ORD( data[ pos ] );
  1284. idPos := pos + 1;
  1285. INC( pos, idLen + 1 );
  1286. IF session # NIL THEN
  1287. (* See if session was restored *)
  1288. session := context.FindSessionByID(data, idPos, idLen);
  1289. END;
  1290. IF session = NIL THEN
  1291. (* create a new session *)
  1292. NEW(session, TRUE, data, idPos, idLen, context.policy.sessionLifetime);
  1293. END;
  1294. (* cipher-suite selected by the server*)
  1295. cipherSuite := 250 * ORD( data[ pos] ) + ORD( data[ pos + 1 ] );
  1296. SELF.session.cipherSuite := cipherSuite;
  1297. PrepareSecurityParameters( pendingSecurityParameters, cipherSuite, res );
  1298. IF res < 0 THEN
  1299. IF Trace THEN KernelLog.String("Failed to Prepare TLS security parameters"); KernelLog.Ln END;
  1300. RETURN -1
  1301. END;
  1302. PrepareConnectionState( pendingWriteState, cipherSuite, res );
  1303. IF res < 0 THEN
  1304. IF Trace THEN KernelLog.String("Failed to Prepare TLS pending write state"); KernelLog.Ln END;
  1305. RETURN -1
  1306. END;
  1307. PrepareConnectionState( pendingReadState, cipherSuite, res );
  1308. IF res < 0 THEN
  1309. IF Trace THEN KernelLog.String("Failed to Prepare TLS pending read state"); KernelLog.Ln END;
  1310. RETURN -1
  1311. END;
  1312. (* ignore compression method *)
  1313. RETURN AwaitCertificate
  1314. END ReceiveServerHello;
  1315. PROCEDURE SendServerHello( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  1316. VAR i, pos: LONGINT;
  1317. BEGIN
  1318. IF Trace THEN PrintDirection(TRUE); KernelLog.String("ServerHello");KernelLog.Ln END;
  1319. ASSERT( ofs > 3 );
  1320. pos := ofs;
  1321. (* server version *)
  1322. data[ pos ] := version[ 0 ]; data[ pos + 1 ] := version[ 1 ]; (* only 3.1 is supported *)
  1323. INC( pos, 2 );
  1324. (* server random bytes generation*)
  1325. Create32RandomBytes( pendingSecurityParameters.serverRandom );
  1326. FOR i := 0 TO 31 DO data[ pos + i ] := pendingSecurityParameters.serverRandom[ i ] END; (* copy random to outbuf *)
  1327. INC( pos, 32 );
  1328. (* session-id *)
  1329. data[ pos ] := CHR( session.idLength );
  1330. INC( pos );
  1331. FOR i := 0 TO session.idLength - 1 DO data[ pos + i ] := session.id[ i ] END; (* copy session-id to data *)
  1332. INC( pos, session.idLength );
  1333. (* cipher-suite *)
  1334. data[ pos ] := CHR( pendingSecurityParameters.cipherSuite DIV 250 );
  1335. data[ pos + 1 ] := CHR( pendingSecurityParameters.cipherSuite MOD 250 );
  1336. INC( pos, 2 );
  1337. (* compression-method *)
  1338. data[ pos ] := CHR( 0 );
  1339. INC( pos );
  1340. SendHandshake( data, ServerHello, ofs-4, pos-ofs )
  1341. END SendServerHello;
  1342. PROCEDURE SendClientKeyExchange(VAR data: ARRAY OF CHAR; ofs: LONGINT): LONGINT;
  1343. VAR
  1344. length: LONGINT;
  1345. BEGIN
  1346. IF Trace THEN
  1347. PrintDirection(TRUE);
  1348. KernelLog.String("Client Key Exchange"); KernelLog.Ln
  1349. END;
  1350. context.GetRsaPublicKey;
  1351. (* Premaster secret *)
  1352. (*Utils.RandomBytes(session.preMasterSecret, 2, 46);*)
  1353. CSPRNG.CSRand(session.preMasterSecret, 48 * 8);
  1354. session.preMasterSecret[0] := version[0];
  1355. session.preMasterSecret[1] := version[1];
  1356. PKCS1.Encrypt(session.preMasterSecret, 0, 48, context.rsaPublicKey, 2, data, ofs + 2, length);
  1357. ASSERT(length # 0);
  1358. data[ofs] := CHR(length DIV 256);
  1359. data[ofs + 1] := CHR(length MOD 256);
  1360. SendHandshake(data, ClientKeyExchange, ofs - 4, length + 2);
  1361. (* Generate master secret. Done in the end, because premaster secret is erased. *)
  1362. GenerateMasterSecret;
  1363. GenerateKeys;
  1364. InitializeConnectionState( SELF.pendingWriteState, SELF.pendingSecurityParameters );
  1365. InitializeConnectionState( SELF.pendingReadState, SELF.pendingSecurityParameters );
  1366. RETURN GenerateChangeCipherSpec
  1367. END SendClientKeyExchange;
  1368. PROCEDURE ReceiveClientKeyExchange(CONST data: ARRAY OF CHAR; ofs, len: LONGINT );
  1369. VAR
  1370. encryptedPremasterSecret, premasterSecret: CryptoBigNumbers.BigNumber;
  1371. tmp: ARRAY 512 OF CHAR;
  1372. rnd: ARRAY 48 OF CHAR;
  1373. i: LONGINT;
  1374. error: BOOLEAN;
  1375. BEGIN
  1376. INC( ofs, 2 ); DEC( len, 2 ); (* the two first bytes have to be ignored *)
  1377. IF Trace THEN
  1378. PrintDirection(FALSE);
  1379. KernelLog.String("ClientKeyExchange");KernelLog.Ln;
  1380. END;
  1381. (* Get random premaster secret in case of decryption error *)
  1382. CSPRNG.CSRand(rnd, 48 * 8);
  1383. (* decryption of the PreMasterSecret *)
  1384. CryptoBigNumbers.AssignBin( encryptedPremasterSecret, data, ofs, len );
  1385. premasterSecret := SELF.context.rsaPrivateKey.Decrypt( encryptedPremasterSecret );
  1386. IF premasterSecret = NIL THEN
  1387. IF Trace THEN KernelLog.String("Decryption of PreMasterSecret was NOT successful!");KernelLog.Ln END;
  1388. error := TRUE
  1389. ELSE
  1390. CryptoBigNumbers.GetBinaryValue( premasterSecret, tmp, 0 );
  1391. END;
  1392. (* pkcs#1 block type 2 has to be used *)
  1393. error := ( tmp[ 0 ] # CHR( 0 ) ) OR ( tmp[ 1 ] # CHR( 2 ) ) OR error;
  1394. IF ~error THEN
  1395. i := 10; (* there are at least 8 padding bytes *)
  1396. WHILE tmp[ i ] # CHR( 0 ) DO INC( i ) END; (* padding ends with a zero-byte *)
  1397. INC( i );
  1398. SELF.session.SetPreMasterSecret( tmp, i );
  1399. ELSE
  1400. SELF.session.SetPreMasterSecret( rnd, 0);
  1401. END;
  1402. GenerateMasterSecret( );
  1403. GenerateKeys( );
  1404. InitializeConnectionState( SELF.pendingWriteState, SELF.pendingSecurityParameters );
  1405. InitializeConnectionState( SELF.pendingReadState, SELF.pendingSecurityParameters )
  1406. END ReceiveClientKeyExchange;
  1407. PROCEDURE ReceiveCertificate( VAR data: ARRAY OF CHAR; ofs, len: LONGINT ): LONGINT;
  1408. VAR
  1409. pos, length, lengthP3: LONGINT;
  1410. BEGIN
  1411. IF Trace THEN
  1412. PrintDirection(FALSE);
  1413. KernelLog.String("Certificate"); KernelLog.Ln;
  1414. END;
  1415. (* Get Certificate Length. First 3 bytes: length + 3, next 3 bytes: length *)
  1416. lengthP3 := ORD(data[ofs]) * 256 * 256 + ORD(data[ofs + 1]) * 256 + ORD(data[ofs + 2]);
  1417. length := ORD(data[ofs + 3]) * 256 * 256 + ORD(data[ofs + 4]) * 256 + ORD(data[ofs + 5]);
  1418. (*ASSERT(lengthP3 = length + 3);*)
  1419. context.lengthOfRsaCertificate := length;
  1420. (* Get content, including first 6 bytes *)
  1421. FOR pos := 0 TO length + 5 DO
  1422. context.rsaCertificate[pos] := data[pos + ofs]
  1423. END;
  1424. (* Check certificate *)
  1425. RETURN AwaitServerHelloDone
  1426. END ReceiveCertificate;
  1427. PROCEDURE SendCertificate( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  1428. VAR i: LONGINT;
  1429. BEGIN
  1430. ASSERT( ofs > 3 );
  1431. IF Trace THEN PrintDirection(TRUE); KernelLog.String("Certificate");KernelLog.Ln END;
  1432. FOR i := 0 TO context.lengthOfRsaCertificate-1 DO
  1433. data[ ofs + i ] := context.rsaCertificate[ i ];
  1434. END;
  1435. SendHandshake( data, Certificate, ofs-4, context.lengthOfRsaCertificate );
  1436. END SendCertificate;
  1437. PROCEDURE SendServerHelloDone( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  1438. BEGIN
  1439. ASSERT( ofs > 3 );
  1440. IF Trace THEN PrintDirection(TRUE); KernelLog.String("ServerHelloDone");KernelLog.Ln END;
  1441. SendHandshake( data, ServerHelloDone, ofs-4, 0 )
  1442. END SendServerHelloDone;
  1443. PROCEDURE ReceiveServerHelloDone(CONST data: ARRAY OF CHAR; ofs, len: LONGINT): LONGINT;
  1444. BEGIN
  1445. IF Trace THEN PrintDirection(FALSE); KernelLog.String("ServerHelloDone"); KernelLog.Ln END;
  1446. RETURN GenerateClientKeyExchange
  1447. END ReceiveServerHelloDone;
  1448. PROCEDURE SendFinished( VAR data: ARRAY OF CHAR; ofs: LONGINT );
  1449. VAR
  1450. seed: ARRAY 36 OF CHAR;
  1451. verifyData: ARRAY 12 OF CHAR;
  1452. i: LONGINT;
  1453. prf: PRF;
  1454. BEGIN
  1455. IF Trace THEN PrintDirection(TRUE); KernelLog.String("Finished");KernelLog.Ln END;
  1456. ASSERT( ofs > 3 );
  1457. hsMD5send.GetHash( seed, 0 ); hsSHAsend.GetHash( seed, 16 ); (* concatenate md5 and sha output *)
  1458. NEW( prf, pendingSecurityParameters.PRFAlgorithm );
  1459. IF client THEN
  1460. prf.GetBytes( SELF.session.masterSecret, seed, verifyData, "client finished", 48, 36, 12 )
  1461. ELSE
  1462. prf.GetBytes( SELF.session.masterSecret, seed, verifyData, "server finished", 48, 36, 12 )
  1463. END;
  1464. FOR i := 0 TO 11 DO
  1465. data[ ofs + i ] := verifyData[ i ]
  1466. END;
  1467. SendHandshake( data, Finished, ofs-4, 12 )
  1468. END SendFinished;
  1469. PROCEDURE ReceiveFinished(CONST data: ARRAY OF CHAR; ofs, len: LONGINT );
  1470. VAR
  1471. seed: ARRAY 36 OF CHAR;
  1472. verifyData: ARRAY 12 OF CHAR;
  1473. prf: PRF;
  1474. i: LONGINT;
  1475. BEGIN
  1476. IF Trace THEN PrintDirection(FALSE); KernelLog.String("Finished"); KernelLog.Ln END;
  1477. ASSERT( len = 12 );
  1478. hsMD5verify.GetHash( seed, 0 ); hsSHAverify.GetHash( seed, 16 ); (* concatenate md5 and sha output *)
  1479. NEW( prf, pendingSecurityParameters.PRFAlgorithm );
  1480. IF client THEN
  1481. prf.GetBytes( SELF.session.masterSecret, seed, verifyData, "server finished", 48, 36, 12 )
  1482. ELSE
  1483. prf.GetBytes( SELF.session.masterSecret, seed, verifyData, "client finished", 48, 36, 12 )
  1484. END;
  1485. FOR i := 0 TO 11 DO
  1486. IF verifyData[ i ] # data[ ofs + i ] THEN
  1487. SendError( DecryptError );
  1488. RETURN
  1489. END
  1490. END
  1491. END ReceiveFinished;
  1492. (* **********************************************************************************
  1493. ALERT PROTOCOL
  1494. ********************************************************************************** *)
  1495. PROCEDURE ReceiveAlert( VAR data: ARRAY OF CHAR; ofs, len: LONGINT );
  1496. VAR level, description, ptr: LONGINT;
  1497. BEGIN
  1498. ptr := ofs;
  1499. WHILE ptr < ofs + len DO (* for each Alert-message *)
  1500. level := ORD( data[ ptr ] );
  1501. description := ORD( data[ ptr + 1 ] );
  1502. IF level = Warning THEN
  1503. ReceiveWarning( description )
  1504. ELSIF level = Fatal THEN
  1505. ReceiveError( description )
  1506. ELSE (* illegal level *)
  1507. SendError( IllegalParameter )
  1508. END;
  1509. INC( ptr, 2 )
  1510. END
  1511. END ReceiveAlert;
  1512. PROCEDURE ReceiveWarning( desc: LONGINT);
  1513. BEGIN
  1514. (* always send an error; this could be more sophisticated *)
  1515. tlsErrorCause := desc;
  1516. SendError( CloseNotify )
  1517. END ReceiveWarning;
  1518. PROCEDURE ReceiveError( alertType: LONGINT);
  1519. BEGIN
  1520. IF Trace THEN
  1521. PrintDirection(FALSE);
  1522. KernelLog.String("Error");KernelLog.Ln;
  1523. KernelLog.String(" alertType: ");KernelLog.Int(alertType, 3);KernelLog.Ln;
  1524. END;
  1525. IF session # NIL THEN SELF.session.Invalidate( ) END;
  1526. SELF.conn.Close( );
  1527. applicationDataPipe.Close();
  1528. SetState(TCP.Closed);
  1529. END ReceiveError;
  1530. PROCEDURE SendWarning( alertType: LONGINT );
  1531. BEGIN
  1532. IF Trace THEN
  1533. PrintDirection(TRUE);
  1534. KernelLog.String("Warning");KernelLog.Ln;
  1535. KernelLog.String(" alertType: ");KernelLog.Int(alertType, 3);KernelLog.Ln;
  1536. END;
  1537. outbuf[ 0 ] := CHR( 1 ); (* level: warning *)
  1538. outbuf[ 1 ] := CHR( alertType );
  1539. SendRecord( outbuf, Alert, 0, 2 );
  1540. END SendWarning;
  1541. PROCEDURE SendError( alertType: LONGINT );
  1542. BEGIN
  1543. IF Trace THEN
  1544. PrintDirection(TRUE);
  1545. KernelLog.String("Error");KernelLog.Ln;
  1546. KernelLog.String(" alertType: ");KernelLog.Int(alertType, 3);KernelLog.Ln;
  1547. END;
  1548. outbuf[ 0 ] := CHR( 2 ); (* level: fatal *)
  1549. outbuf[ 1 ] := CHR( alertType );
  1550. SendRecord( outbuf, Alert, 0, 2 );
  1551. IF session # NIL THEN SELF.session.Invalidate( ) END;
  1552. SELF.conn.Close( );
  1553. applicationDataPipe.Close();
  1554. SetState(TCP.Closed);
  1555. END SendError;
  1556. (* **********************************************************************************
  1557. FINITE STATE MACHINE
  1558. ********************************************************************************** *)
  1559. PROCEDURE Transition( VAR data: ARRAY OF CHAR; action, subAction, ofs, len: LONGINT );
  1560. VAR dummy: ARRAY 1 OF CHAR;
  1561. res : WORD;
  1562. BEGIN
  1563. IF action = ChangeCipherSpec THEN
  1564. CASE handshakeState OF
  1565. | AwaitChangeSpec:
  1566. ReceiveChangeCipherSpec( data, ofs );
  1567. handshakeState := AwaitFinished
  1568. | AwaitChangeSpecWithResumption:
  1569. ReceiveChangeCipherSpec( data, ofs );
  1570. handshakeState := AwaitFinishedWithResumption
  1571. ELSE
  1572. SendError( UnexpectedMessage )
  1573. END
  1574. ELSIF action = Handshake THEN
  1575. IF State()= ServerHandshake THEN
  1576. CASE handshakeState OF
  1577. | AwaitClientHello:
  1578. IF subAction = ClientHello THEN
  1579. handshakeState := ReceiveClientHello( data, ofs, len );
  1580. Transition( dummy, Handshake, 0, 0, 0 )
  1581. ELSIF subAction = V2ClientHello THEN
  1582. handshakeState := ReceiveV2ClientHello( data, ofs, len );
  1583. Transition( dummy, Handshake, 0, 0, 0 )
  1584. ELSE (* fatal error *)
  1585. SendError( UnexpectedMessage )
  1586. END
  1587. | GenerateServerHello: (* establish new session *)
  1588. SendServerHello( outbuf, 4 );
  1589. SendCertificate( outbuf, 4 );
  1590. handshakeState := GenerateServerHelloDone;
  1591. Transition( dummy, Handshake, 0, 0, 0 )
  1592. | GenerateServerHelloDone:
  1593. SendServerHelloDone( outbuf, 4 );
  1594. handshakeState := AwaitClientKeyExchange;
  1595. | AwaitClientKeyExchange:
  1596. IF subAction = ClientKeyExchange THEN
  1597. ReceiveClientKeyExchange( data, ofs, len );
  1598. handshakeState := AwaitChangeSpec;
  1599. ELSE (* fatal error *)
  1600. SendError( UnexpectedMessage )
  1601. END
  1602. | AwaitFinished:
  1603. IF subAction = Finished THEN
  1604. ReceiveFinished( data, ofs, len );
  1605. handshakeState := GenerateChangeCipherSpec;
  1606. Transition( dummy, Handshake, 0, 0, 0 )
  1607. ELSE (* fatal error *)
  1608. SendError( UnexpectedMessage )
  1609. END
  1610. | GenerateChangeCipherSpec:
  1611. SendChangeCipherSpec;
  1612. SendFinished( outbuf, 4 );
  1613. handshakeState := HandshakeFinished;
  1614. SetState(TCP.Established);
  1615. IF SELF.context.policy.sessionResumptionEnabled THEN
  1616. SELF.context.StoreSession( SELF.session )
  1617. END
  1618. | GenerateHelloWithResumption: (* session resumption *)
  1619. SendServerHello( outbuf, 4 );
  1620. PrepareSecurityParameters( pendingSecurityParameters, pendingSecurityParameters.cipherSuite, res );
  1621. IF res < 0 THEN
  1622. SendError( UnexpectedMessage )
  1623. END;
  1624. PrepareConnectionState( pendingWriteState, pendingSecurityParameters.cipherSuite,res );
  1625. IF res < 0 THEN
  1626. SendError( HandshakeFailure );
  1627. END;
  1628. PrepareConnectionState( pendingReadState, pendingSecurityParameters.cipherSuite, res );
  1629. IF res < 0 THEN
  1630. SendError( HandshakeFailure );
  1631. END;
  1632. GenerateKeys( );
  1633. InitializeConnectionState( SELF.pendingWriteState, SELF.pendingSecurityParameters );
  1634. InitializeConnectionState( SELF.pendingReadState, SELF.pendingSecurityParameters );
  1635. SendChangeCipherSpec;
  1636. SendFinished( outbuf, 4 );
  1637. handshakeState := AwaitChangeSpecWithResumption
  1638. | AwaitFinishedWithResumption:
  1639. IF subAction = Finished THEN
  1640. ReceiveFinished( data, ofs, len );
  1641. handshakeState := HandshakeFinished;
  1642. SetState(TCP.Established);
  1643. ELSE (* fatal error *)
  1644. SendError( UnexpectedMessage )
  1645. END
  1646. END (* CASE *)
  1647. ELSIF State() = ClientHandshake THEN
  1648. CASE handshakeState OF
  1649. GenerateClientHello:
  1650. SendClientHello(outbuf, 4);
  1651. handshakeState := AwaitServerHello
  1652. |AwaitServerHello:
  1653. handshakeState := ReceiveServerHello(data, ofs, len);
  1654. |AwaitCertificate:
  1655. handshakeState := ReceiveCertificate(data, ofs, len);
  1656. |AwaitServerHelloDone:
  1657. handshakeState := ReceiveServerHelloDone(data, ofs, len);
  1658. Transition(dummy, Handshake, 0, 0, 0)
  1659. |GenerateClientKeyExchange:
  1660. handshakeState := SendClientKeyExchange(outbuf, 4);
  1661. Transition(dummy, Handshake, 0, 0, 0)
  1662. |GenerateChangeCipherSpec:
  1663. SendChangeCipherSpec;
  1664. SendFinished(outbuf, 4);
  1665. handshakeState := AwaitChangeSpec
  1666. |AwaitChangeSpec:
  1667. ReceiveChangeCipherSpec(data, ofs);
  1668. handshakeState := AwaitFinished
  1669. |AwaitFinished:
  1670. ReceiveFinished(data, ofs, len);
  1671. SetState(TCP.Established);
  1672. END
  1673. ELSIF State() = TCP.Established THEN
  1674. IF subAction = ClientHello THEN (* the only handshake msg a server should receive after a finished handshake *)
  1675. SetState(ServerHandshake);
  1676. handshakeState := ReceiveClientHello( data, ofs, len );
  1677. Transition( dummy, Handshake, 0, 0, 0 )
  1678. ELSE (* fatal error *)
  1679. SendError( UnexpectedMessage )
  1680. END
  1681. END
  1682. END;
  1683. END Transition;
  1684. (* **********************************************************************************
  1685. UTILITIES
  1686. ********************************************************************************** *)
  1687. PROCEDURE Create32RandomBytes( VAR data: ARRAY OF CHAR );
  1688. VAR i, time, date, timestamp, d, h, m, s: LONGINT; unixEpoch: Dates.DateTime;
  1689. BEGIN
  1690. ASSERT( LEN( data ) > 31 );
  1691. (* 28 random bytes *)
  1692. CSPRNG.CSRand(data, 32 * 8);
  1693. (* 4 bytes timestamp *)
  1694. (*Clock.Get( date, time );*)
  1695. (*timestamp := BIT.LXOR( date, time );*)
  1696. unixEpoch.year := 1970; unixEpoch.month := 1; unixEpoch.day := 1;
  1697. ASSERT(Dates.ValidDateTime(unixEpoch));
  1698. Dates.TimeDifference(Dates.Now(), unixEpoch, d, h, m, s);
  1699. INC(s, m * 60);
  1700. INC(s, h * 3600);
  1701. INC(s, d * 86400);
  1702. timestamp := s;
  1703. FOR i := 3 TO 0 BY -1 DO
  1704. data[ i ] := CHR( timestamp );
  1705. timestamp := timestamp DIV 256
  1706. END;
  1707. (*Utils.RandomBytes( data, 4, 28 )*)
  1708. END Create32RandomBytes;
  1709. (** Prints the correct S > C or C > S depending on current action and state *)
  1710. PROCEDURE PrintDirection(send: BOOLEAN);
  1711. BEGIN
  1712. IF client & send THEN
  1713. KernelLog.String("CLIENT: C > S ")
  1714. ELSIF client & ~send THEN
  1715. KernelLog.String("CLIENT: S > C ")
  1716. ELSIF ~client & send THEN
  1717. KernelLog.String("SERVER: S > C ")
  1718. ELSE
  1719. KernelLog.String("SERVER: C > S ")
  1720. END
  1721. END PrintDirection;
  1722. BEGIN { ACTIVE }
  1723. IF trapped THEN SetState(TCP.Closed); RETURN END;
  1724. trapped := TRUE;
  1725. AwaitStateNotEqual(TCP.Unused);
  1726. IF client THEN
  1727. StartHandshake;
  1728. REPEAT
  1729. ReceiveRecord
  1730. UNTIL (State() = TCP.Established) OR (State() = TCP.Closed);
  1731. IF State() = TCP.Established THEN
  1732. REPEAT
  1733. ReceiveRecord
  1734. UNTIL (State() = TCP.Closed) OR (in.res # Streams.Ok);
  1735. Close
  1736. END
  1737. ELSE
  1738. IF State() # TCP.Listen THEN
  1739. (* listen for incoming messages *)
  1740. REPEAT
  1741. ReceiveRecord( )
  1742. UNTIL (State() = TCP.Closed) OR (in.res # Streams.Ok);
  1743. Close();
  1744. END;
  1745. END
  1746. END Connection;
  1747. VAR
  1748. (*version: ARRAY 2 OF CHAR;*)
  1749. defaultCipherPolicy: Policy;
  1750. (** Returns a new connection with a reasonnable default policy *)
  1751. PROCEDURE GetConnection * (): Connection;
  1752. VAR
  1753. con: Connection;
  1754. BEGIN
  1755. NEW(con);
  1756. RETURN con
  1757. END GetConnection;
  1758. PROCEDURE GetServerConnection * (CONST certificate, pHex, qHex, eHex: ARRAY OF CHAR; pLen, qLen, eLen: LONGINT): Connection;
  1759. VAR
  1760. con: Connection;
  1761. ctx: Context;
  1762. BEGIN
  1763. NEW(ctx, defaultCipherPolicy);
  1764. IF ctx.LoadRsaCertificate(certificate) # Ok THEN RETURN NIL END;
  1765. ctx.LoadRsaPrivateKey(pHex, qHex, eHex, INTEGER(pLen), INTEGER(qLen), INTEGER(eLen));
  1766. NEW(con);
  1767. con.SetContext(ctx);
  1768. RETURN con
  1769. END GetServerConnection;
  1770. (** Prepares default ciphers for TLS v1.2 *)
  1771. PROCEDURE InitDefaults;
  1772. VAR
  1773. defaultSuites:ARRAY DefaultSuitesNbr OF LONGINT;
  1774. BEGIN
  1775. defaultSuites[0] := TlsRsaWithAes256CbcSha;
  1776. defaultSuites[1] := TlsRsaWithAes128CbcSha;
  1777. defaultSuites[2] := TlsRsaWith3DesEdeCbcSha;
  1778. NEW(defaultCipherPolicy);
  1779. defaultCipherPolicy.SetCipherSuites(defaultSuites, DefaultSuitesNbr);
  1780. defaultCipherPolicy.SetVersion(1, 2)
  1781. END InitDefaults;
  1782. BEGIN
  1783. InitDefaults
  1784. END TLS.