1 /**
2 * TLS Messages
3 * 
4 * Copyright:
5 * (C) 2004-2011,2015 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.tls.messages;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_TLS):
15 package:
16 
17 import botan.tls.handshake_state;
18 import botan.tls.session_key;
19 import std.algorithm : canFind;
20 import botan.tls.alert : TLSAlert;
21 import memutils.dictionarylist;
22 
23 public import botan.algo_base.sym_algo;
24 public import botan.tls.session;
25 public import botan.tls.policy;
26 public import botan.tls.ciphersuite;
27 public import botan.tls.reader;
28 public import botan.tls.extensions;
29 public import botan.tls.handshake_io;
30 public import botan.tls.version_;
31 public import botan.tls.handshake_hash;
32 public import botan.tls.magic;
33 public import botan.tls.credentials_manager;
34 import botan.constructs.srp6;
35 import botan.utils.loadstor;
36 import botan.constructs.srp6;
37 import botan.math.bigint.bigint;
38 import botan.pubkey.algo.ec_group;
39 import botan.math.ec_gfp.point_gfp;
40 import botan.pubkey.pkcs8;
41 import botan.pubkey.pubkey;
42 import botan.pubkey.algo.dh;
43 import botan.pubkey.algo.ecdh;
44 import botan.pubkey.algo.rsa;
45 import botan.cert.x509.x509cert;
46 import botan.asn1.oids;
47 import botan.asn1.der_enc;
48 import botan.asn1.ber_dec;
49 import botan.utils.loadstor;
50 import botan.utils.types;
51 import botan.libstate.lookup;
52 import botan.rng.rng;
53 import botan.utils.types : Unique;
54 import std.datetime;
55 import botan.utils.types;
56 
57 // import string;
58 
59 enum {
60     TLS_EMPTY_RENEGOTIATION_INFO_SCSV  = 0x00FF,
61     TLS_FALLBACK_SCSV                  = 0x5600
62 }
63 
64 /**
65 * TLS Handshake Message Base Class
66 */
67 interface HandshakeMessage
68 {
69 public:
70     abstract HandshakeType type() const;
71     
72     abstract Vector!ubyte serialize() const;
73 }
74 
75 /**
76 * DTLS Hello Verify Request
77 */
78 final class HelloVerifyRequest : HandshakeMessage
79 {
80 public:
81     override Vector!ubyte serialize() const
82     {
83         /* DTLS 1.2 server implementations SHOULD use DTLS version 1.0
84             regardless of the version of TLS that is expected to be
85             negotiated (RFC 6347, section 4.2.1)
86         */
87             
88         TLSProtocolVersion format_version = TLSProtocolVersion(TLSProtocolVersion.DTLS_V10);
89         
90         Vector!ubyte bits;
91         bits.pushBack(format_version.majorVersion());
92         bits.pushBack(format_version.minorVersion());
93         bits.pushBack(cast(ubyte) m_cookie.length);
94         bits ~= m_cookie[];
95         return bits.move();
96     }
97 
98     override HandshakeType type() const { return HELLO_VERIFY_REQUEST; }
99 
100     ref const(Vector!ubyte) cookie() const { return m_cookie; }
101 
102     this(const ref Vector!ubyte buf)
103     {
104         if (buf.length < 3)
105             throw new DecodingError("Hello verify request too small");
106         
107         TLSProtocolVersion version_ = TLSProtocolVersion(buf[0], buf[1]);
108         
109         if (version_ != TLSProtocolVersion.DTLS_V10 &&
110             version_ != TLSProtocolVersion.DTLS_V12)
111         {
112             throw new DecodingError("Unknown version from server in hello verify request");
113         }
114 
115         if ((cast(size_t) buf[2]) + 3 != buf.length)
116             throw new DecodingError("Bad length in hello verify request");
117         
118         m_cookie[] = buf.ptr[3 .. buf.length];
119     }
120 
121     this(const ref Vector!ubyte client_hello_bits, in string client_identity, in SymmetricKey secret_key)
122     {
123         Unique!MessageAuthenticationCode hmac = retrieveMac("HMAC(SHA-256)").clone();
124         hmac.setKey(secret_key);
125         
126         hmac.updateBigEndian(client_hello_bits.length);
127         hmac.update(client_hello_bits);
128         hmac.updateBigEndian(client_identity.length);
129         hmac.update(client_identity);
130         
131         m_cookie = unlock(hmac.finished());
132     }
133 private:
134     Vector!ubyte m_cookie;
135 }
136 
137 enum GreaseType : size_t {
138 	CIPHER = 0,
139 	ELLIPTIC_CURVE,
140 	EXTENSION_FIRST,
141 	EXTENSION_LAST
142 };
143 
144 /**
145 * TLSClient Hello Message
146 */
147 final class ClientHello : HandshakeMessage
148 {
149 public:
150     override HandshakeType type() const { return CLIENT_HELLO; }
151 
152     const(TLSProtocolVersion) Version() const { return m_version; }
153 
154     ref const(Vector!ubyte) random() const { return m_random; }
155 
156 	const(ubyte[]) randomBytes() const { return m_random[]; }
157 
158 	private const(ushort) grease(GreaseType idx) const {
159 		if (!m_grease) return 0;
160 		ushort ret = *cast(ushort*) m_random[idx*2 .. (idx+1)*2].ptr;
161 		ret = (ret & 0xf0) | 0x0a;
162 		ret |= ret << 8;
163 		return ret;
164 	}
165 
166 	ref const(Vector!ubyte) sessionId() const { return m_session_id; }
167 	
168 	const(ubyte[]) sessionIdBytes() const { return m_session_id[]; }
169 
170 	ref const(Vector!ushort) ciphersuites() const { return m_suites; }
171 
172 	const(ushort[]) ciphersuitesData() const { return m_suites[]; }
173 
174     ref const(Vector!ubyte) compressionMethods() const { return m_comp_methods; }
175 
176     /*
177     * Check if we offered this ciphersuite
178     */
179     bool offeredSuite(ushort ciphersuite) const
180     {
181         for (size_t i = 0; i != m_suites.length; ++i)
182             if (m_suites[i] == ciphersuite)
183                 return true;
184         return false;
185     }
186 
187     Vector!( Pair!(string, string) ) supportedAlgos() const
188     {
189         if (SignatureAlgorithms sigs = m_extensions.get!SignatureAlgorithms())
190             return sigs.supportedSignatureAlgorthms().dup();
191         return Vector!( Pair!(string, string) )();
192     }
193 
194     Vector!string supportedEccCurves() const
195     {
196         if (SupportedEllipticCurves ecc = m_extensions.get!SupportedEllipticCurves())
197             return ecc.curves().dup();
198         return Vector!string();
199     }
200 
201     string sniHostname() const
202     {
203         if (ServerNameIndicator sni = m_extensions.get!ServerNameIndicator())
204             return sni.hostName();
205         return "";
206     }
207 
208     string srpIdentifier() const
209     {
210         if (SRPIdentifier srp = m_extensions.get!SRPIdentifier())
211             return srp.identifier();
212         return "";
213     }
214 
215     bool sentFallbackSCSV() const
216     {
217         return offeredSuite(cast(ushort) TLS_FALLBACK_SCSV);
218     }
219 
220     bool secureRenegotiation() const
221     {
222         return m_extensions.get!RenegotiationExtension() !is null;
223     }
224 
225     Vector!ubyte renegotiationInfo() const
226     {
227         if (RenegotiationExtension reneg = m_extensions.get!RenegotiationExtension())
228             return reneg.renegotiationInfo().dup();
229         return Vector!ubyte();
230     }
231 
232     size_t fragmentSize() const
233     {
234         if (MaximumFragmentLength frag = m_extensions.get!MaximumFragmentLength())
235             return frag.fragmentSize();
236         return 0;
237     }
238 
239     bool supportsSessionTicket() const
240     {
241         return m_extensions.get!SessionTicket() !is null;
242     }
243 
244     Vector!ubyte sessionTicket() const
245     {
246         if (SessionTicket ticket = m_extensions.get!SessionTicket())
247             return ticket.contents().dup();
248         return Vector!ubyte();
249     }
250 
251 	bool supportsAlpn() const
252 	{
253 		return m_extensions.get!ApplicationLayerProtocolNotification() !is null;
254 	}
255 
256 	bool supportsExtendedMasterSecret() const
257 	{
258 		return m_extensions.get!ExtendedMasterSecret() !is null;
259 	}
260 
261     const(Vector!string) nextProtocols() const
262     {
263         if (auto alpn = m_extensions.get!ApplicationLayerProtocolNotification())
264             return alpn.protocols().dup;
265         return Vector!string();
266     }
267 
268     bool supportsHeartbeats() const
269     {
270         return m_extensions.get!HeartbeatSupportIndicator() !is null;
271     }
272 
273     bool peerCanSendHeartbeats() const
274     {
275         if (HeartbeatSupportIndicator hb = m_extensions.get!HeartbeatSupportIndicator())
276             return hb.peerAllowedToSend();
277         return false;
278     }
279 
280     bool supportsChannelID() const
281     {
282         return m_extensions.get!ChannelIDSupport() !is null;
283     }
284 
285     void updateHelloCookie(in HelloVerifyRequest hello_verify)
286     {
287         if (!m_version.isDatagramProtocol())
288             throw new Exception("Cannot use hello cookie with stream protocol");
289         
290         m_hello_cookie = hello_verify.cookie().dup;
291     }
292 
293     const(Vector!HandshakeExtensionType) extensionTypes() const
294     { return m_extensions.extensionTypes(); }
295 
296     /*
297     * Create a new TLSClient Hello message
298     */
299     this(HandshakeIO io,
300          ref HandshakeHash hash,
301          TLSProtocolVersion _version,
302          in TLSPolicy policy,
303          RandomNumberGenerator rng,
304          Vector!ubyte reneg_info,
305          Vector!string next_protocols,
306          in string hostname,
307          in string srp_identifier) 
308     {
309 		//logDebug("ClientHello with hostname: ", hostname);
310 
311         bool reneg_empty = reneg_info.empty;
312         m_version = _version;
313 
314 		assert(policy.acceptableProtocolVersion(_version), "Our policy accepts the version we are offering");
315 
316         m_random = makeHelloRandom(rng, policy);
317 		m_suites.reserve(16);
318 		m_grease = policy.allowClientHelloGrease();
319 		if (m_grease) {
320 			m_suites ~= grease(GreaseType.CIPHER);
321 			m_extensions.grease(grease(GreaseType.EXTENSION_FIRST), grease(GreaseType.EXTENSION_LAST));
322 		}
323 		m_suites ~= policy.ciphersuiteList(m_version, (srp_identifier != ""));
324         m_comp_methods = policy.compression();
325 
326 		Vector!ubyte fmts = policy.ecPointFormats();
327         bool has_safe_reneg;
328 		foreach (extension_; policy.enabledExtensions()) {
329 			switch (extension_) {
330 				case TLSEXT_SAFE_RENEGOTIATION:
331                     has_safe_reneg = true;
332 					m_extensions.add(new RenegotiationExtension(reneg_info.move()));
333 					break;
334 				case TLSEXT_SERVER_NAME_INDICATION:
335 					m_extensions.add(new ServerNameIndicator(hostname));
336 					break;
337 				case TLSEXT_EC_POINT_FORMATS:
338 					m_extensions.add(new SupportedPointFormats(fmts.move()));
339 					break;
340 				case TLSEXT_USABLE_ELLIPTIC_CURVES:
341 					m_extensions.add(new SupportedEllipticCurves(policy.allowedEccCurves(), grease(GreaseType.ELLIPTIC_CURVE)));
342 					break;
343 				case TLSEXT_EXTENDED_MASTER_SECRET:
344 					m_extensions.add(new ExtendedMasterSecret);
345 					break;
346 				case TLSEXT_SESSION_TICKET:
347 					m_extensions.add(new SessionTicket());
348 					break;
349 				case TLSEXT_SIGNATURE_ALGORITHMS:
350 					if (m_version.supportsNegotiableSignatureAlgorithms())
351 						m_extensions.add(new SignatureAlgorithms(policy.allowedSignatureHashes(),
352 							policy.allowedSignatureMethods(), policy.signatureAlgorithms()));
353 					break;
354 				case TLSEXT_STATUS_REQUEST: //todo: Complete support
355 					m_extensions.add(new StatusRequest);
356 					break;
357 				case TLSEXT_NPN:
358 					m_extensions.add(new NPN);
359 					break;
360 				case TLSEXT_SIGNED_CERT_TIMESTAMP:
361 					m_extensions.add(new SignedCertificateTimestamp);
362 					break;
363 				case TLSEXT_ALPN:
364 					if (reneg_empty && !next_protocols.empty)
365 						m_extensions.add(new ApplicationLayerProtocolNotification(next_protocols.move));
366 					break;
367 				case TLSEXT_CHANNEL_ID:
368                     m_extensions.add(new ChannelIDSupport);
369 					break;
370 				case TLSEXT_SRP_IDENTIFIER:
371 					m_extensions.add(new SRPIdentifier(srp_identifier));
372 					break;
373 				case TLSEXT_HEARTBEAT_SUPPORT:
374 					if (policy.negotiateHeartbeatSupport())
375 	            		m_extensions.add(new HeartbeatSupportIndicator(true));
376 					break;
377 				case TLSEXT_PADDING:
378 					m_has_padding = true;
379 					break;
380                 default:
381                     break;
382 			}
383 
384 		}
385 
386         if (policy.sendFallbackSCSV(_version))
387             m_suites.pushBack(TLS_FALLBACK_SCSV);
388         else if (has_safe_reneg)
389             m_suites.pushBack(TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
390 
391         hash.update(io.send(this));
392     }
393 
394 
395     /*
396     * Create a new TLSClient Hello message (session resumption case)
397     */
398     this(HandshakeIO io,
399          ref HandshakeHash hash,
400          in TLSPolicy policy,
401          RandomNumberGenerator rng,
402          Vector!ubyte reneg_info,
403          in TLSSession session,
404          Vector!string next_protocols)
405     { 
406         bool reneg_empty = reneg_info.empty;
407 
408         m_version = session.Version();
409         m_session_id = session.sessionId().dup;
410         m_random = makeHelloRandom(rng, policy);
411 		m_suites.reserve(16);
412 		m_grease = policy.allowClientHelloGrease();
413 		if (m_grease) {
414 			m_suites ~= grease(GreaseType.CIPHER);
415 			m_extensions.grease(grease(GreaseType.EXTENSION_FIRST), grease(GreaseType.EXTENSION_LAST));
416 		}
417         m_suites ~= policy.ciphersuiteList(m_version, (session.srpIdentifier() != ""));
418 		m_comp_methods = policy.compression();
419 		Vector!ubyte fmts = policy.ecPointFormats();
420         if (!valueExists(m_suites, session.ciphersuiteCode()))
421             m_suites.pushBack(session.ciphersuiteCode());
422         
423         if (!valueExists(m_comp_methods, session.compressionMethod()))
424             m_comp_methods.pushBack(session.compressionMethod());
425         bool has_safe_reneg;
426 		foreach (extension_; policy.enabledExtensions()) {
427 			switch (extension_) {
428 				case TLSEXT_SAFE_RENEGOTIATION:
429                     has_safe_reneg = true;
430 					m_extensions.add(new RenegotiationExtension(reneg_info.move()));
431 					break;
432 				case TLSEXT_SERVER_NAME_INDICATION:
433 					m_extensions.add(new ServerNameIndicator(session.serverInfo().hostname()));
434 					break;
435 				case TLSEXT_EC_POINT_FORMATS:
436 					m_extensions.add(new SupportedPointFormats(fmts.move()));
437 					break;
438 				case TLSEXT_USABLE_ELLIPTIC_CURVES:
439 					m_extensions.add(new SupportedEllipticCurves(policy.allowedEccCurves(), grease(GreaseType.ELLIPTIC_CURVE)));
440 					break;
441 				case TLSEXT_EXTENDED_MASTER_SECRET:
442 					m_extensions.add(new ExtendedMasterSecret);
443 					break;
444 				case TLSEXT_SESSION_TICKET:
445 					m_extensions.add(new SessionTicket(session.sessionTicket().dup));
446 					break;
447 				case TLSEXT_SIGNATURE_ALGORITHMS:
448 					if (m_version.supportsNegotiableSignatureAlgorithms())
449 						m_extensions.add(new SignatureAlgorithms(policy.allowedSignatureHashes(),
450 								policy.allowedSignatureMethods(), policy.signatureAlgorithms()));
451 					break;
452 				case TLSEXT_STATUS_REQUEST: //todo: Complete support
453 					m_extensions.add(new StatusRequest);
454 					break;
455 				case TLSEXT_NPN:
456 					m_extensions.add(new NPN);
457 					break;
458 				case TLSEXT_SIGNED_CERT_TIMESTAMP:
459 					m_extensions.add(new SignedCertificateTimestamp);
460 					break;
461 				case TLSEXT_ALPN:
462 					if (reneg_empty && !next_protocols.empty)
463 						m_extensions.add(new ApplicationLayerProtocolNotification(next_protocols.move));
464 					break;
465 				case TLSEXT_CHANNEL_ID:
466                     m_extensions.add(new ChannelIDSupport);
467 					break;
468 				case TLSEXT_SRP_IDENTIFIER:
469 					m_extensions.add(new SRPIdentifier(session.srpIdentifier()));
470 					break;
471 				case TLSEXT_HEARTBEAT_SUPPORT:
472 					if (policy.negotiateHeartbeatSupport())
473 						m_extensions.add(new HeartbeatSupportIndicator(true));
474 					break;
475 				case TLSEXT_MAX_FRAGMENT_LENGTH:
476 					if (session.fragmentSize() != 0)
477 						m_extensions.add(new MaximumFragmentLength(session.fragmentSize()));
478 					break;
479 				case TLSEXT_PADDING:
480 					m_has_padding = true;
481 					break;
482                 default:
483                     break;
484 			}
485 		}
486 
487         
488         if (policy.sendFallbackSCSV(m_version))
489             m_suites.pushBack(TLS_FALLBACK_SCSV);
490         else if (has_safe_reneg)
491             m_suites.pushBack(TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
492 
493         hash.update(io.send(this));
494     }
495 	bool deserialized;
496     /*
497     * Read a counterparty client hello
498     */
499     this(const ref Vector!ubyte buf, HandshakeType type)
500     {
501 		deserialized = true;
502         if (type == CLIENT_HELLO)
503             deserialize(buf);
504     }
505 
506 protected:
507     /*
508     * Serialize a TLSClient Hello message
509     */
510     override Vector!ubyte serialize() const
511     {
512 
513 		/*logDebug("Ciphersuites: ", ciphersuites()[]);
514 		logDebug("Supported ECC curves: ", supportedEccCurves()[]);
515 		logDebug("SupportedAlgos: ", supportedAlgos()[]);
516 		logDebug("Session ID: ", sessionId[]);
517 		logDebug("Random: ", random()[]);
518 		logDebug("sni Hostname: ", sniHostname);
519 		logDebug("sentFallback SCSV: ", sentFallbackSCSV());
520 		logDebug("Secure renegotiation: ", secureRenegotiation());
521 		logDebug("NextProtocol: ", nextProtocols[]);
522 		*/
523         Vector!ubyte buf;
524 		buf.reserve(512);
525 
526         buf.pushBack(m_version.majorVersion());
527         buf.pushBack(m_version.minorVersion());
528         buf ~= m_random[];
529         
530         appendTlsLengthValue(buf, m_session_id, 1);
531         
532         if (m_version.isDatagramProtocol())
533             appendTlsLengthValue(buf, m_hello_cookie, 1);
534         
535         appendTlsLengthValue(buf, m_suites, 2);
536         appendTlsLengthValue(buf, m_comp_methods, 1);
537         
538         /*
539         * May not want to send extensions at all in some cases. If so,
540         * should include SCSV value (if reneg info is empty, if not we are
541         * renegotiating with a modern server)
542         */
543         
544         auto vec = m_extensions.serialize();
545         // pad when between 256 and 511 (inclusive) bytes long
546 		if (m_has_padding && (buf.length+4) + vec.length <= 511 &&  (buf.length+4) + vec.length >= 256)
547         {
548             long pad = 512L - cast(long)vec.length - (cast(long)buf.length+4L) - 4L;
549             if (pad <= 0)
550                 pad = 1;
551             ushort extn_size = cast(ushort)(vec.length+pad+4-2);
552             vec[0] = get_byte(0, extn_size);
553             vec[1] = get_byte(1, extn_size);
554             vec.pushBack(get_byte(0, cast(ushort) 21));
555             vec.pushBack(get_byte(1, cast(ushort) 21)); // padding extension identifier
556             vec.pushBack(get_byte(0, cast(ushort) pad));
557             vec.pushBack(get_byte(1, cast(ushort) pad));
558             foreach (i; 0 .. pad)
559                 vec ~= cast(ubyte)0x00;
560         }
561         buf ~= vec[];
562 
563         return buf.move();
564     }
565 
566     /*
567     * Deserialize a TLSClient Hello message
568     */
569     void deserialize(const ref Vector!ubyte buf)
570     {
571 		if (buf.length == 0)
572             throw new DecodingError("ClientHello: Packet corrupted");
573         
574         if (buf.length < 41)
575             throw new DecodingError("ClientHello: Packet corrupted");
576         
577         TLSDataReader reader = TLSDataReader("ClientHello", buf);
578         
579         const ubyte major_version = reader.get_byte();
580         const ubyte minor_version = reader.get_byte();
581         
582         m_version = TLSProtocolVersion(major_version, minor_version);
583         m_random = reader.getFixed!ubyte(32);
584         
585         if (m_version.isDatagramProtocol())
586             m_hello_cookie = reader.getRange!ubyte(1, 0, 255);
587         
588         m_session_id = reader.getRange!ubyte(1, 0, 32);
589         
590         m_suites = reader.getRangeVector!ushort(2, 1, 32767);
591         
592         m_comp_methods = reader.getRangeVector!ubyte(1, 1, 255);
593         
594 		m_extensions.reserve(8);
595         m_extensions.deserialize(reader);
596         
597         if (offeredSuite(cast(ushort)(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
598         {
599             if (RenegotiationExtension reneg = m_extensions.get!RenegotiationExtension())
600             {
601                 if (!reneg.renegotiationInfo().empty)
602                     throw new TLSException(TLSAlert.HANDSHAKE_FAILURE,
603                                             "Client sent renegotiation SCSV and non-empty extension");
604             }
605             else
606             {
607                 // add fake extension
608                 m_extensions.add(new RenegotiationExtension());
609             }
610         }
611 		/*logDebug("Ciphersuites: ", ciphersuites()[]);
612 		logDebug("Session ID: ", sessionId[]);
613 		logDebug("Random: ", random()[]);
614 		logDebug("sni Hostname: ", sniHostname);
615 		logDebug("sentFallback SCSV: ", sentFallbackSCSV());
616 		logDebug("Secure renegotiation: ", secureRenegotiation());*/
617 		//logDebug("NextProtocol: ", nextProtocols[]);
618     }
619 
620 private:
621 	bool m_grease;
622 	bool m_has_padding;
623     TLSProtocolVersion m_version;
624     Vector!ubyte m_session_id;
625     Vector!ubyte m_random;
626     Vector!ushort m_suites;
627     Vector!ubyte m_comp_methods;
628     Vector!ubyte m_hello_cookie; // DTLS only
629 
630     TLSExtensions m_extensions;
631 }
632 
633 /**
634 * TLSServer Hello Message
635 */
636 final class ServerHello : HandshakeMessage
637 {
638 public:
639     override const(HandshakeType) type() const { return SERVER_HELLO; }
640 
641     TLSProtocolVersion Version() const { return m_version; }
642 
643     ref const(Vector!ubyte) random() const { return m_random; }
644 
645 	const(ubyte[]) randomBytes() const { return m_random[]; }
646 
647 	ref const(Vector!ubyte) sessionId() const { return m_session_id; }
648 
649 	const(ubyte[]) sessionIdBytes() const { return m_session_id[]; }
650 
651     ushort ciphersuite() const { return m_ciphersuite; }
652 
653     ubyte compressionMethod() const { return m_comp_method; }
654 
655     bool secureRenegotiation() const
656     {
657         return m_extensions.get!RenegotiationExtension() !is null;
658     }
659 
660     Vector!ubyte renegotiationInfo() const
661     {
662         if (RenegotiationExtension reneg = m_extensions.get!RenegotiationExtension())
663             return reneg.renegotiationInfo().dup;
664         return Vector!ubyte();
665     }
666 
667     size_t fragmentSize() const
668     {
669         if (MaximumFragmentLength frag = m_extensions.get!MaximumFragmentLength())
670             return frag.fragmentSize();
671         return 0;
672     }
673 
674 	bool supportsExtendedMasterSecret() const
675 	{
676 		return m_extensions.get!ExtendedMasterSecret() !is null;
677 	}
678 
679     bool supportsSessionTicket() const
680     {
681         return m_extensions.get!SessionTicket() !is null;
682     }
683 
684     bool supportsHeartbeats() const
685     {
686         return m_extensions.get!HeartbeatSupportIndicator() !is null;
687     }
688 
689     bool supportsChannelID() const
690     {
691         return m_extensions.get!ChannelIDSupport() !is null;
692     }
693 
694     bool peerCanSendHeartbeats() const
695     {
696         if (auto hb = m_extensions.get!HeartbeatSupportIndicator())
697             return hb.peerAllowedToSend();
698         return false;
699     }
700 
701     string nextProtocol() const
702     {
703         if (auto alpn = m_extensions.get!ApplicationLayerProtocolNotification())
704             return alpn.singleProtocol();
705         return "";
706     }
707 
708     const(Vector!HandshakeExtensionType) extensionTypes() const
709     { return m_extensions.extensionTypes(); }
710 
711     /*
712     * Create a new TLSServer Hello message
713     */
714     this(HandshakeIO io,
715          ref HandshakeHash hash,
716          in TLSPolicy policy,
717          Vector!ubyte session_id,
718          TLSProtocolVersion ver,
719          ushort ciphersuite,
720          ubyte compression,
721          size_t max_fragment_size,
722          bool client_has_secure_renegotiation,
723          bool client_has_extended_master_secret,
724          Vector!ubyte reneg_info,
725          bool offer_session_ticket,
726          bool client_has_alpn,
727          in string next_protocol,
728          bool client_has_heartbeat,
729          RandomNumberGenerator rng) 
730     {
731         m_version = ver;
732         m_session_id = session_id.move();
733         m_random = makeHelloRandom(rng, policy);
734         m_ciphersuite = ciphersuite;
735         m_comp_method = compression;
736 		m_extensions.reserve(8);
737 
738 		if (client_has_extended_master_secret)
739 			m_extensions.add(new ExtendedMasterSecret);
740 
741         if (client_has_heartbeat && policy.negotiateHeartbeatSupport())
742             m_extensions.add(new HeartbeatSupportIndicator(true));
743         
744         if (client_has_secure_renegotiation)
745             m_extensions.add(new RenegotiationExtension(reneg_info.move()));
746         
747         if (max_fragment_size)
748             m_extensions.add(new MaximumFragmentLength(max_fragment_size));
749         
750         if (next_protocol != "" && client_has_alpn)
751             m_extensions.add(new ApplicationLayerProtocolNotification(next_protocol));
752         
753         if (offer_session_ticket)
754             m_extensions.add(new SessionTicket());
755         
756         hash.update(io.send(this));
757     }
758 
759     /*
760     * Deserialize a TLSServer Hello message
761     */
762     this(const ref Vector!ubyte buf)
763     {
764         if (buf.length < 38)
765             throw new DecodingError("ServerHello: Packet corrupted");
766 
767         TLSDataReader reader = TLSDataReader("ServerHello", buf);
768         
769         const ubyte major_version = reader.get_byte();
770         const ubyte minor_version = reader.get_byte();
771         
772         m_version = TLSProtocolVersion(major_version, minor_version);
773         
774         m_random = reader.getFixed!ubyte(32);
775 
776         m_session_id = reader.getRange!ubyte(1, 0, 32);
777 
778         m_ciphersuite = reader.get_ushort();
779         
780         m_comp_method = reader.get_byte();
781         
782 		m_extensions.reserve(8);
783         m_extensions.deserialize(reader);
784     }
785 
786 protected:
787     /*
788     * Serialize a TLSServer Hello message
789     */
790     override Vector!ubyte serialize() const
791     {
792         Vector!ubyte buf;
793 		buf.reserve(512);
794 
795         buf.pushBack(m_version.majorVersion());
796         buf.pushBack(m_version.minorVersion());
797         buf ~= m_random[];
798         
799         appendTlsLengthValue(buf, m_session_id, 1);
800         
801         buf.pushBack(get_byte(0, m_ciphersuite));
802         buf.pushBack(get_byte(1, m_ciphersuite));
803         
804         buf.pushBack(m_comp_method);
805                 
806 		auto vec = m_extensions.serialize();
807 		buf ~= vec[];
808 		return buf.move();
809     }
810 
811 private:
812     TLSProtocolVersion m_version;
813     Vector!ubyte m_session_id, m_random;
814     ushort m_ciphersuite;
815     ubyte m_comp_method;
816 
817     TLSExtensions m_extensions;
818 }
819 
820 /**
821 * TLSClient Key Exchange Message
822 */
823 final class ClientKeyExchange : HandshakeMessage
824 {
825 public:
826     override HandshakeType type() const { return CLIENT_KEX; }
827 
828     ref const(SecureVector!ubyte) preMasterSecret() const
829     { return m_pre_master; }
830 
831     /*
832     * Read a TLSClient Key Exchange message
833     */
834     this(const ref Vector!ubyte contents,
835          in HandshakeState state,
836          in PrivateKey server_rsa_kex_key,
837          TLSCredentialsManager creds,
838          in TLSPolicy policy,
839          RandomNumberGenerator rng)
840     {
841         const string kex_algo = state.ciphersuite().kexAlgo();
842         
843         if (kex_algo == "RSA")
844         {
845             assert(state.serverCerts() && !state.serverCerts().certChain().empty,
846                          "RSA key exchange negotiated so server sent a certificate");
847             
848             if (!server_rsa_kex_key)
849                 throw new InternalError("Expected RSA kex but no server kex key set");
850             
851             if (server_rsa_kex_key.algoName != "RSA")
852                 throw new InternalError("Expected RSA key but got " ~ server_rsa_kex_key.algoName);
853             
854             auto decryptor = scoped!PKDecryptorEME(server_rsa_kex_key, "PKCS1v15");
855             
856             TLSProtocolVersion client_version = state.clientHello().Version();
857             
858             /*
859             * This is used as the pre-master if RSA decryption fails.
860             * Otherwise we can be used as an oracle. See Bleichenbacher
861             * "Chosen Ciphertext Attacks against Protocols Based on RSA
862             * Encryption Standard PKCS #1", Crypto 98
863             *
864             * Create it here instead if in the catch clause as otherwise we
865             * expose a timing channel WRT the generation of the fake value.
866             * Some timing channel likely remains due to exception handling
867             * and the like.
868             */
869             SecureVector!ubyte fake_pre_master = rng.randomVec(48);
870             fake_pre_master[0] = client_version.majorVersion();
871             fake_pre_master[1] = client_version.minorVersion();
872             
873             try
874             {
875                 TLSDataReader reader = TLSDataReader("ClientKeyExchange", contents);
876                 m_pre_master = decryptor.decrypt(reader.getRange!ubyte(2, 0, 65535));
877 
878                 if (m_pre_master.length != 48 ||
879                     client_version.majorVersion() != m_pre_master[0] ||
880                     client_version.minorVersion() != m_pre_master[1])
881                 {
882                     throw new DecodingError("ClientKeyExchange: Secret corrupted");
883                 }
884             }
885             catch (Exception)
886             {
887                 m_pre_master = fake_pre_master;
888             }
889         }
890         else
891         {
892             TLSDataReader reader = TLSDataReader("ClientKeyExchange", contents);
893             
894             auto psk = SymmetricKey();
895             
896             if (kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
897             {
898                 const string psk_identity = reader.getString(2, 0, 65535);
899                 
900                 psk = creds.psk("tls-server",
901                                 state.clientHello().sniHostname(),
902                                 psk_identity);
903                 
904                 if (psk.length == 0)
905                 {
906                     if (policy.hideUnknownUsers())
907                         psk = SymmetricKey(rng, 16);
908                     else
909                         throw new TLSException(TLSAlert.UNKNOWN_PSK_IDENTITY,
910                                                 "No PSK for identifier " ~ psk_identity);
911                 }
912             }
913             
914             if (kex_algo == "PSK")
915             {
916                 Vector!ubyte zeros = Vector!ubyte(psk.length);
917                 appendTlsLengthValue(m_pre_master, zeros, 2);
918                 appendTlsLengthValue(m_pre_master, psk.bitsOf(), 2);
919             }
920             else if (kex_algo == "SRP_SHA")
921             {
922 				static if (BOTAN_HAS_SRP6) {
923 	                SRP6ServerSession srp = cast(SRP6ServerSession) state.serverKex().serverSrpParams();
924 	                
925 	                m_pre_master = srp.step2(BigInt.decode(reader.getRange!ubyte(2, 0, 65535))).bitsOf();
926 				}
927 				else {
928 					throw new InternalError("ClientKeyExchange: Unknown kex type " ~ kex_algo);
929 				}
930             }
931             else if (kex_algo == "DH" || kex_algo == "DHE_PSK" ||
932                      kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
933             {
934                 const PrivateKey private_key = state.serverKex().serverKexKey();
935                 
936                 const PKKeyAgreementKey ka_key = cast(const PKKeyAgreementKey)(private_key);
937                 
938                 if (!ka_key)
939                     throw new InternalError("Expected key agreement key type but got " ~
940                                              private_key.algoName);
941                 
942                 try
943                 {
944                     auto ka = scoped!PKKeyAgreement(ka_key, "Raw");
945                     
946                     Vector!ubyte client_pubkey;
947                     
948                     if (ka_key.algoName == "DH")
949                         client_pubkey = reader.getRange!ubyte(2, 0, 65535);
950                     else
951                         client_pubkey = reader.getRange!ubyte(1, 0, 255);
952 					auto derived_key = ka.deriveKey(0, client_pubkey);
953 					SecureVector!ubyte shared_secret = derived_key.bitsOf();
954                     
955                     if (ka_key.algoName == "DH")
956                         shared_secret = stripLeadingZeros(shared_secret);
957                     
958                     if (kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
959                     {
960                         appendTlsLengthValue(m_pre_master, shared_secret, 2);
961                         appendTlsLengthValue(m_pre_master, psk.bitsOf(), 2);
962                     }
963                     else
964                         m_pre_master = shared_secret.move();
965                 }
966                 catch(Exception e)
967                 {
968                     /*
969                     * Something failed in the DH computation. To avoid possible
970                     * timing attacks, randomize the pre-master output and carry
971                     * on, allowing the protocol to fail later in the finished
972                     * checks.
973                     */
974                     m_pre_master = rng.randomVec(ka_key.publicValue().length);
975                 }
976             }
977             else
978                 throw new InternalError("ClientKeyExchange: Unknown kex type " ~ kex_algo);
979         }
980     }
981 
982     /*
983     * Create a new TLSClient Key Exchange message
984     */
985     this(HandshakeIO io,
986          HandshakeState state,
987          in TLSPolicy policy,
988          TLSCredentialsManager creds,
989          const PublicKey server_public_key,
990          in string hostname,
991          RandomNumberGenerator rng)
992     {
993         const string kex_algo = state.ciphersuite().kexAlgo();
994         
995         if (kex_algo == "PSK")
996         {
997             string identity_hint = "";
998             
999             if (state.serverKex())
1000             {
1001                 TLSDataReader reader = TLSDataReader("ClientKeyExchange", state.serverKex().params());
1002                 identity_hint = reader.getString(2, 0, 65535);
1003             }
1004             
1005             const string hostname_ = state.clientHello().sniHostname();
1006             
1007             const string psk_identity = creds.pskIdentity("tls-client",
1008                                                            hostname_,
1009                                                            identity_hint);
1010             
1011             appendTlsLengthValue(m_key_material, psk_identity, 2);
1012             
1013             SymmetricKey psk = creds.psk("tls-client", hostname_, psk_identity);
1014             
1015             Vector!ubyte zeros = Vector!ubyte(psk.length);
1016             
1017             appendTlsLengthValue(m_pre_master, zeros, 2);
1018             appendTlsLengthValue(m_pre_master, psk.bitsOf(), 2);
1019         }
1020         else if (state.serverKex())
1021         {
1022             TLSDataReader reader = TLSDataReader("ClientKeyExchange", state.serverKex().params());
1023             
1024             auto psk = SymmetricKey();
1025             
1026             if (kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
1027             {
1028                 string identity_hint = reader.getString(2, 0, 65535);
1029                 
1030                 const string hostname_ = state.clientHello().sniHostname();
1031                 
1032                 const string psk_identity = creds.pskIdentity("tls-client",
1033                                                                hostname_,
1034                                                                identity_hint);
1035                 
1036                 appendTlsLengthValue(m_key_material, psk_identity, 2);
1037                 
1038                 psk = creds.psk("tls-client", hostname_, psk_identity);
1039             }
1040             
1041             if (kex_algo == "DH" || kex_algo == "DHE_PSK")
1042             {
1043                 BigInt p = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1044                 BigInt g = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1045                 BigInt Y = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1046                 
1047                 if (reader.remainingBytes())
1048                     throw new DecodingError("Bad params size for DH key exchange");
1049                 
1050                 if (p.bits() < policy.minimumDhGroupSize())
1051                     throw new TLSException(TLSAlert.INSUFFICIENT_SECURITY,
1052                                             "TLSServer sent DH group of " ~
1053                                             to!string(p.bits()) ~
1054                                             " bits, policy requires at least " ~
1055                                             to!string(policy.minimumDhGroupSize()));
1056                 
1057                 /*
1058                 * A basic check for key validity. As we do not know q here we
1059                 * cannot check that Y is in the right subgroup. However since
1060                 * our key is ephemeral there does not seem to be any
1061                 * advantage to bogus keys anyway.
1062                 */
1063                 if (Y <= 1 || Y >= p - 1)
1064                     throw new TLSException(TLSAlert.INSUFFICIENT_SECURITY,
1065                                             "TLSServer sent bad DH key for DHE exchange");
1066                 
1067                 DLGroup group = DLGroup(p, g);
1068                 
1069                 if (!group.verifyGroup(rng, false))
1070                     throw new TLSException(TLSAlert.INSUFFICIENT_SECURITY, "DH group failed validation, possible attack");
1071                 auto counterparty_key = DHPublicKey(group.dup, Y.move);
1072                 
1073                 auto priv_key = DHPrivateKey(rng, group.move);
1074                 
1075                 auto ka = scoped!PKKeyAgreement(priv_key, "Raw");
1076                 
1077 				auto octet_string = ka.deriveKey(0, counterparty_key.publicValue());
1078                 SecureVector!ubyte dh_secret = stripLeadingZeros(octet_string.bitsOf());
1079                 
1080                 if (kex_algo == "DH")
1081                     m_pre_master = dh_secret.move();
1082                 else
1083                 {
1084                     appendTlsLengthValue(m_pre_master, dh_secret, 2);
1085                     appendTlsLengthValue(m_pre_master, psk.bitsOf(), 2);
1086                 }
1087                 
1088                 appendTlsLengthValue(m_key_material, priv_key.publicValue(), 2);
1089             }
1090             else if (kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
1091             {
1092                 const ubyte curve_type = reader.get_byte();
1093                 
1094                 if (curve_type != 3)
1095                     throw new DecodingError("TLSServer sent non-named ECC curve");
1096                 
1097                 const ushort curve_id = reader.get_ushort();
1098                 
1099                 const string curve_name = SupportedEllipticCurves.curveIdToName(curve_id);
1100                 
1101 				if (curve_name == "")
1102                     throw new DecodingError("TLSServer sent unknown named curve " ~ to!string(curve_id));
1103 				{
1104 					Vector!string allowed_curves = policy.allowedEccCurves();
1105 					if(!(allowed_curves[]).canFind(curve_name))
1106 						throw new TLSException(TLSAlert.HANDSHAKE_FAILURE, "Server sent ECC curve prohibited by policy");
1107 				}
1108 				Vector!ubyte ecdh_key = reader.getRange!ubyte(1, 1, 255);
1109 
1110 				Vector!ubyte our_ecdh_public;
1111 				SecureVector!ubyte ecdh_secret;
1112 
1113 				if (curve_name == "x25519") {
1114 					import botan.pubkey.algo.curve25519;
1115 					if (ecdh_key.length != 32)
1116 						throw new TLSException(TLSAlert.HANDSHAKE_FAILURE, "Invalid X25519 key size");
1117 					Curve25519PublicKey counterparty_key = Curve25519PublicKey(ecdh_key);
1118 					Curve25519PrivateKey priv_key = Curve25519PrivateKey(rng);
1119 
1120 					auto ka = scoped!PKKeyAgreement(priv_key, "Raw");
1121 					auto public_value = counterparty_key.publicValue();
1122 					auto derived_key = ka.deriveKey(0, public_value);
1123 
1124 					ecdh_secret = derived_key.bitsOf();
1125 					our_ecdh_public = priv_key.publicValue();
1126 
1127 				} else {
1128 					ECGroup group = ECGroup(curve_name);
1129 	                
1130 	                
1131 	                auto counterparty_key = ECDHPublicKey(group, OS2ECP(ecdh_key, group.getCurve()));	                
1132 	                auto priv_key = ECDHPrivateKey(rng, group);
1133 					
1134 					auto ka = scoped!PKKeyAgreement(priv_key, "Raw");
1135 					auto public_value = counterparty_key.publicValue();
1136 					auto derived_key = ka.deriveKey(0, public_value);
1137 
1138 					ecdh_secret = derived_key.bitsOf();
1139 					our_ecdh_public = priv_key.publicValue();
1140 				}
1141                 if (kex_algo == "ECDH")
1142                     m_pre_master = ecdh_secret.move();
1143                 else
1144                 {
1145                     appendTlsLengthValue(m_pre_master, ecdh_secret, 2);
1146                     appendTlsLengthValue(m_pre_master, psk.bitsOf(), 2);
1147                 }
1148                 
1149 				appendTlsLengthValue(m_key_material, our_ecdh_public, 1);
1150             }
1151             else if (kex_algo == "SRP_SHA")
1152             {
1153 				static if (BOTAN_HAS_SRP6) {
1154 	                const BigInt N = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1155 	                const BigInt g = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1156 	                Vector!ubyte salt = reader.getRange!ubyte(1, 1, 255);
1157 	                const BigInt B = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1158 	                
1159 	                const string srp_group = srp6GroupIdentifier(N, g);
1160 	                
1161 	                const string srp_identifier = creds.srpIdentifier("tls-client", hostname);
1162 	                
1163 	                const string srp_password = creds.srpPassword("tls-client", hostname, srp_identifier);
1164 	                
1165 	                SRP6KeyPair srp_vals = srp6ClientAgree(srp_identifier,
1166 	                                                                       srp_password,
1167 	                                                                       srp_group,
1168 	                                                                       "SHA-1",
1169 	                                                                       salt,
1170 	                                                                       B,
1171 	                                                                       rng);
1172 	                
1173 	                appendTlsLengthValue(m_key_material, BigInt.encode(srp_vals.privkey), 2);
1174 	                m_pre_master = srp_vals.pubkey.bitsOf();
1175 				} else {
1176 					throw new InternalError("ClientKeyExchange: Unknown kex " ~ kex_algo);
1177 				}
1178             }
1179             else
1180             {
1181                 throw new InternalError("ClientKeyExchange: Unknown kex " ~
1182                                          kex_algo);
1183             }
1184             
1185             reader.assertDone();
1186         }
1187         else
1188         {
1189             // No server key exchange msg better mean RSA kex + RSA key in cert
1190             
1191             if (kex_algo != "RSA")
1192                 throw new TLSUnexpectedMessage("No server kex but negotiated kex " ~ kex_algo);
1193             
1194             if (!server_public_key)
1195                 throw new InternalError("No server public key for RSA exchange");
1196             
1197             if (server_public_key.algoName == "RSA")
1198             {
1199                 auto rsa_pub = RSAPublicKey(cast(PublicKey)server_public_key);
1200                 const TLSProtocolVersion offered_version = state.clientHello().Version();
1201                 
1202                 m_pre_master = rng.randomVec(48);
1203                 m_pre_master[0] = offered_version.majorVersion();
1204                 m_pre_master[1] = offered_version.minorVersion();
1205                 
1206                 auto encryptor = scoped!PKEncryptorEME(rsa_pub, "PKCS1v15");
1207                 
1208                 Vector!ubyte encrypted_key = encryptor.encrypt(m_pre_master, rng);
1209                 
1210                 appendTlsLengthValue(m_key_material, encrypted_key, 2);
1211             }
1212             else
1213                 throw new TLSException(TLSAlert.HANDSHAKE_FAILURE,
1214                                         "Expected a RSA key in server cert but got " ~
1215                                         server_public_key.algoName);
1216         }
1217         
1218         state.hash().update(io.send(this));
1219     }
1220 
1221 
1222 protected:
1223     override Vector!ubyte serialize() const { return m_key_material.dup; }
1224 
1225 private:
1226     Vector!ubyte m_key_material;
1227     SecureVector!ubyte m_pre_master;
1228 }
1229 
1230 /**
1231 * Certificate Message
1232 */
1233 final class Certificate : HandshakeMessage
1234 {
1235 public:
1236     override const(HandshakeType) type() const { return CERTIFICATE; }
1237     ref const(Vector!X509Certificate) certChain() const { return *m_certs; }
1238 
1239     size_t count() const { return m_certs.length; }
1240     @property bool empty() const { return m_certs.empty; }
1241 
1242     /**
1243     * Create a new Certificate message
1244     */
1245     this()(HandshakeIO io,
1246            ref HandshakeHash hash,
1247            auto ref Array!X509Certificate cert_list)
1248     {
1249         m_certs = cert_list;
1250         hash.update(io.send(this));
1251     }
1252 
1253     /**
1254     * Create a new Certificate message
1255     */
1256     this()(HandshakeIO io,
1257         ref HandshakeHash hash,
1258         auto ref Vector!X509Certificate cert_list)
1259     {
1260         m_certs = cert_list.dupr;
1261         hash.update(io.send(this));
1262     }
1263 
1264     /**
1265     * Deserialize a Certificate message
1266     */
1267     this()(auto const ref Vector!ubyte buf)
1268     {
1269         if (buf.length < 3)
1270             throw new DecodingError("Certificate: Message malformed");
1271         
1272         const size_t total_size = make_uint(0, buf[0], buf[1], buf[2]);
1273 
1274         if (total_size != buf.length - 3)
1275             throw new DecodingError("Certificate: Message malformed");
1276         
1277         const(ubyte)* certs = buf.ptr + 3;
1278         
1279         while (true)
1280         {
1281             size_t remaining_bytes = buf.ptr + buf.length - certs;
1282             if (remaining_bytes <= 0)
1283                 break;
1284             if (remaining_bytes < 3)
1285                 throw new DecodingError("Certificate: Message malformed");
1286             
1287             const size_t cert_size = make_uint(0, certs[0], certs[1], certs[2]);
1288             
1289             if (remaining_bytes < (3 + cert_size))
1290                 throw new DecodingError("Certificate: Message malformed");
1291             
1292             auto cert_buf = DataSourceMemory(&certs[3], cert_size);
1293             m_certs.pushBack(X509Certificate(cast(DataSource)cert_buf));
1294             
1295             certs += cert_size + 3;
1296         }
1297     }
1298 
1299 protected:
1300     /**
1301     * Serialize a Certificate message
1302     */
1303     override Vector!ubyte serialize() const
1304     {
1305 		Vector!ubyte buf;
1306 		buf.reserve(2048);
1307 		buf.length = 3;
1308         for (size_t i = 0; i != m_certs.length; ++i)
1309         {
1310             Vector!ubyte raw_cert = m_certs[i].BER_encode();
1311             const size_t cert_size = raw_cert.length;
1312             foreach (size_t j; 0 .. 3)
1313                 buf.pushBack(get_byte!uint(j+1, cast(uint) cert_size));
1314             buf ~= raw_cert;
1315         }
1316         
1317         const size_t buf_size = buf.length - 3;
1318         foreach (size_t i; 0 .. 3)
1319             buf[i] = get_byte!uint(i+1, cast(uint) buf_size);
1320         
1321         return buf.move();
1322     }
1323 
1324 private:
1325     Array!X509Certificate m_certs;
1326 }
1327 
1328 /**
1329 * Certificate Request Message
1330 */
1331 final class CertificateReq : HandshakeMessage
1332 {
1333 public:
1334     override const(HandshakeType) type() const { return CERTIFICATE_REQUEST; }
1335 
1336     ref const(Vector!string) acceptableCertTypes() const
1337     { return m_cert_key_types; }
1338 
1339     ref const(Vector!X509DN) acceptableCAs() const { return m_names; }
1340 
1341     Vector!( Pair!(string, string) ) supportedAlgos() const
1342     { return m_supported_algos.dup; }
1343 
1344     /**
1345     * Create a new Certificate Request message
1346     */
1347     this(HandshakeIO io,
1348          ref HandshakeHash hash,
1349          in TLSPolicy policy,
1350          Vector!X509DN ca_certs,
1351          TLSProtocolVersion _version) 
1352     {
1353         m_names = ca_certs.move();
1354         m_cert_key_types = [ "RSA", "DSA", "ECDSA" ];
1355 		static Vector!( Pair!(string, string)  ) last_supported_algos;
1356 		static TLSPolicy last_tls_policy;
1357         static TLSProtocolVersion last_version;
1358 		if (policy is last_tls_policy && _version == last_version)
1359 			m_supported_algos = last_supported_algos.dup;
1360 		else {
1361 			m_supported_algos.reserve(16);
1362 	        if (_version.supportsNegotiableSignatureAlgorithms())
1363 	        {
1364 	            Vector!string hashes = policy.allowedSignatureHashes();
1365 	            Vector!string sigs = policy.allowedSignatureMethods();
1366 	            
1367 	            for (size_t i = 0; i != hashes.length; ++i)
1368 	                for (size_t j = 0; j != sigs.length; ++j)
1369 	                    m_supported_algos.pushBack(makePair(hashes[i], sigs[j]));
1370 	        }
1371 			last_tls_policy = cast() policy;
1372             last_version = _version;
1373 			last_supported_algos = m_supported_algos.dup;
1374 		}
1375         
1376         hash.update(io.send(this));
1377     }
1378 
1379     /**
1380     * Deserialize a Certificate Request message
1381     */
1382     this(const ref Vector!ubyte buf, TLSProtocolVersion _version)
1383     {
1384         if (buf.length < 4)
1385             throw new DecodingError("Certificate_Req: Bad certificate request");
1386         
1387         TLSDataReader reader = TLSDataReader("CertificateRequest", buf);
1388 
1389         Vector!ubyte cert_type_codes = reader.getRangeVector!ubyte(1, 1, 255);
1390         
1391         for (size_t i = 0; i != cert_type_codes.length; ++i)
1392         {
1393             const string cert_type_name = certTypeCodeToName(cert_type_codes[i]);
1394             
1395             if (cert_type_name == "") // something we don't know
1396                 continue;
1397             
1398             m_cert_key_types.pushBack(cert_type_name);
1399         }
1400         
1401         if (_version.supportsNegotiableSignatureAlgorithms())
1402         {
1403             Vector!ubyte sig_hash_algs = reader.getRangeVector!ubyte(2, 2, 65534);
1404             
1405             if (sig_hash_algs.length % 2 != 0)
1406                 throw new DecodingError("Bad length for signature IDs in certificate request");
1407             
1408             for (size_t i = 0; i != sig_hash_algs.length; i += 2)
1409             {
1410                 string hash = SignatureAlgorithms.hashAlgoName(sig_hash_algs[i]);
1411                 string sig = SignatureAlgorithms.sigAlgoName(sig_hash_algs[i+1]);
1412                 m_supported_algos.pushBack(makePair(hash, sig));
1413             }
1414         }
1415         
1416         const ushort purported_size = reader.get_ushort();
1417         
1418         if (reader.remainingBytes() != purported_size)
1419             throw new DecodingError("Inconsistent length in certificate request");
1420         
1421         while (reader.hasRemaining())
1422         {
1423             Vector!ubyte name_bits = reader.getRangeVector!ubyte(2, 0, 65535);
1424             
1425             BERDecoder decoder = BERDecoder(name_bits.ptr, name_bits.length);
1426             X509DN name = X509DN();
1427             decoder.decode(name);
1428             m_names.pushBack(name);
1429         }
1430     }
1431 
1432 protected:
1433 
1434     /**
1435     * Serialize a Certificate Request message
1436     */
1437     override Vector!ubyte serialize() const
1438     {
1439         Vector!ubyte buf;
1440 		buf.reserve(256);
1441         Vector!ubyte cert_types;
1442 		cert_types.reserve(64);
1443         for (size_t i = 0; i != m_cert_key_types.length; ++i)
1444             cert_types.pushBack(certTypeNameToCode(m_cert_key_types[i]));
1445 
1446         appendTlsLengthValue(buf, cert_types, 1);
1447         
1448         if (!m_supported_algos.empty) {
1449 			Unique!SignatureAlgorithms sig_algos = new SignatureAlgorithms(m_supported_algos.dup);
1450             buf ~= sig_algos.serialize();
1451 		}
1452         
1453         Vector!ubyte encoded_names;
1454         
1455         for (size_t i = 0; i != m_names.length; ++i)
1456         {
1457             DEREncoder encoder = DEREncoder();
1458             encoder.encode(m_names[i]);
1459             
1460             appendTlsLengthValue(encoded_names, encoder.getContents(), 2);
1461         }
1462         
1463         appendTlsLengthValue(buf, encoded_names, 2);
1464         
1465         return buf.move();
1466     }
1467 
1468 private:
1469     Vector!X509DN m_names;
1470     Vector!string m_cert_key_types;
1471 
1472     Vector!( Pair!(string, string)  ) m_supported_algos;
1473 }
1474 
1475 /**
1476 * Certificate Verify Message
1477 */
1478 final class CertificateVerify : HandshakeMessage
1479 {
1480 public:
1481     override const(HandshakeType) type() const { return CERTIFICATE_VERIFY; }
1482 
1483     /**
1484     * Check the signature on a certificate verify message
1485     * Params:
1486     *  cert = the purported certificate
1487     *  state = the handshake state
1488     */
1489     bool verify(const X509Certificate cert,
1490                 const HandshakeState state) const
1491     {
1492         Unique!PublicKey key = cert.subjectPublicKey();
1493         
1494         Pair!(string, SignatureFormat) format = state.understandSigFormat(*key, m_hash_algo, m_sig_algo, true);
1495         
1496         PKVerifier verifier = PKVerifier(*key, format.first, format.second);
1497         
1498         return verifier.verifyMessage(state.hash().getContents(), m_signature);
1499     }
1500 
1501     /*
1502     * Create a new Certificate Verify message
1503     */
1504     this(HandshakeIO io,
1505          HandshakeState state,
1506          in TLSPolicy policy,
1507          RandomNumberGenerator rng,
1508          const PrivateKey priv_key)
1509     {
1510         assert(priv_key, "No private key defined");
1511         
1512         Pair!(string, SignatureFormat) format = state.chooseSigFormat(priv_key, m_hash_algo, m_sig_algo, true, policy);
1513         
1514         PKSigner signer = PKSigner(priv_key, format.first, format.second);
1515         
1516 		m_signature = signer.signMessage(state.hash().getContents(), rng);
1517                 
1518         state.hash().update(io.send(this));
1519     }
1520 
1521     /*
1522     * Deserialize a Certificate Verify message
1523     */
1524     this(const ref Vector!ubyte buf,
1525          TLSProtocolVersion _version)
1526     {
1527         TLSDataReader reader = TLSDataReader("CertificateVerify", buf);
1528         
1529         if (_version.supportsNegotiableSignatureAlgorithms())
1530         {
1531             m_hash_algo = SignatureAlgorithms.hashAlgoName(reader.get_byte());
1532             m_sig_algo = SignatureAlgorithms.sigAlgoName(reader.get_byte());
1533         }
1534         
1535         m_signature = reader.getRange!ubyte(2, 0, 65535);
1536     }
1537 
1538 protected:
1539     /*
1540     * Serialize a Certificate Verify message
1541     */
1542     override Vector!ubyte serialize() const
1543     {
1544         Vector!ubyte buf;
1545         
1546         if (m_hash_algo != "" && m_sig_algo != "")
1547         {
1548             buf.pushBack(SignatureAlgorithms.hashAlgoCode(m_hash_algo));
1549             buf.pushBack(SignatureAlgorithms.sigAlgoCode(m_sig_algo));
1550         }
1551         
1552         const ushort sig_len = cast(ushort) m_signature.length;
1553         buf.pushBack(get_byte(0, sig_len));
1554         buf.pushBack(get_byte(1, sig_len));
1555         buf ~= m_signature[];
1556         
1557         return buf.move();
1558     }
1559 
1560 private:
1561     string m_sig_algo; // sig algo used to create signature
1562     string m_hash_algo; // hash used to create signature
1563     Vector!ubyte m_signature;
1564 }
1565 
1566 /**
1567 * Finished Message
1568 */
1569 final class Finished : HandshakeMessage
1570 {
1571 public:
1572     override const(HandshakeType) type() const { return FINISHED; }
1573 
1574     ref const(Vector!ubyte) verifyData() const
1575     { return m_verification_data; }
1576 
1577 	const(ubyte[]) verifyDataBytes() const { return m_verification_data[]; }
1578 
1579     /*
1580     * Verify a Finished message
1581     */
1582     bool verify(in HandshakeState state, ConnectionSide side) const
1583     {
1584         return (m_verification_data == finishedComputeVerify(state, side));
1585     }
1586 
1587     /*
1588     * Create a new Finished message
1589     */
1590     this(HandshakeIO io,
1591          HandshakeState state,
1592          ConnectionSide side)
1593     {
1594         m_verification_data = finishedComputeVerify(state, side);
1595         state.hash().update(io.send(this));
1596     }
1597 
1598     /*
1599     * Deserialize a Finished message
1600     */
1601     this(Vector!ubyte buf)
1602     {
1603         m_verification_data = buf.move();
1604     }
1605 
1606 protected:
1607     /*
1608     * Serialize a Finished message
1609     */
1610     override Vector!ubyte serialize() const
1611     {
1612         return m_verification_data.dup;
1613     }
1614    
1615 private:
1616     Vector!ubyte m_verification_data;
1617 }
1618 
1619 /**
1620 * Hello Request Message
1621 */
1622 final class HelloRequest : HandshakeMessage
1623 {
1624 public:
1625     override const(HandshakeType) type() const { return HELLO_REQUEST; }
1626 
1627     /*
1628     * Create a new Hello Request message
1629     */
1630     this(HandshakeIO io)
1631     {
1632         io.send(this);
1633     }
1634 
1635     /*
1636     * Deserialize a Hello Request message
1637     */
1638     this(const ref Vector!ubyte buf)
1639     {
1640         if (buf.length)
1641             throw new DecodingError("Bad HelloRequest, has non-zero size");
1642     }
1643 
1644 protected:
1645     /*
1646     * Serialize a Hello Request message
1647     */
1648     override Vector!ubyte serialize() const
1649     {
1650         return Vector!ubyte();
1651     }
1652 }
1653 
1654 /**
1655 * TLSServer Key Exchange Message
1656 */
1657 final class ServerKeyExchange : HandshakeMessage
1658 {
1659 public:
1660     override const(HandshakeType) type() const { return SERVER_KEX; }
1661 
1662     ref const(Vector!ubyte) params() const { return m_params; }
1663 
1664     /**
1665     * Verify a TLSServer Key Exchange message
1666     */
1667     bool verify(in PublicKey server_key,
1668                 const HandshakeState state) const
1669     {
1670         Pair!(string, SignatureFormat) format = state.understandSigFormat(server_key, m_hash_algo, m_sig_algo, false);
1671 
1672         PKVerifier verifier = PKVerifier(server_key, format.first, format.second);
1673         verifier.update(state.clientHello().random());
1674         verifier.update(state.serverHello().random());
1675         verifier.update(params());
1676         return verifier.checkSignature(m_signature);
1677     }
1678 
1679     // Only valid for certain kex types
1680     const(PrivateKey) serverKexKey() const
1681     {
1682         assert(m_kex_key, "PrivateKey cannot be null");
1683         return *m_kex_key;
1684     }
1685 
1686 	static if (BOTAN_HAS_SRP6) {
1687 	    // Only valid for SRP negotiation
1688 	    const(SRP6ServerSession) serverSrpParams() const
1689 	    {
1690 	        assert(m_srp_params, "SRP6ServerSession cannot be null");
1691 	        return *m_srp_params;
1692 	    }
1693 	}
1694 
1695     /**
1696     * Deserialize a TLSServer Key Exchange message
1697     */
1698     this(const ref Vector!ubyte buf,
1699          in string kex_algo,
1700          in string sig_algo,
1701          TLSProtocolVersion _version) 
1702     {
1703         m_kex_key.free();
1704 		static if (BOTAN_HAS_SRP6)
1705 	        m_srp_params.free();
1706         if (buf.length < 6)
1707             throw new DecodingError("ServerKeyExchange: Packet corrupted");
1708         
1709         TLSDataReader reader = TLSDataReader("ServerKeyExchange", buf);
1710         
1711         /*
1712         * We really are just serializing things back to what they were
1713         * before, but unfortunately to know where the signature is we need
1714         * to be able to parse the whole thing anyway.
1715         */
1716         
1717         if (kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
1718         {
1719             const string identity_hint = reader.getString(2, 0, 65535);
1720             appendTlsLengthValue(m_params, identity_hint, 2);
1721         }
1722         
1723         if (kex_algo == "DH" || kex_algo == "DHE_PSK")
1724         {
1725             // 3 bigints, DH p, g, Y
1726             
1727             foreach (size_t i; 0 .. 3)
1728             {
1729                 BigInt v = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1730                 appendTlsLengthValue(m_params, BigInt.encode(v), 2);
1731             }
1732         }
1733         else if (kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
1734         {
1735             const ubyte curve_type = reader.get_byte();
1736             
1737             if (curve_type != 3)
1738                 throw new DecodingError("ServerKeyExchange: TLSServer sent non-named ECC curve");
1739             
1740             const ushort curve_id = reader.get_ushort();
1741             
1742             const string name = SupportedEllipticCurves.curveIdToName(curve_id);
1743             
1744             Vector!ubyte ecdh_key = reader.getRange!ubyte(1, 1, 255);
1745             
1746             if (name == "")
1747                 throw new DecodingError("ServerKeyExchange: TLSServer sent unknown named curve " ~
1748                                          to!string(curve_id));
1749             
1750             m_params.pushBack(curve_type);
1751             m_params.pushBack(get_byte(0, curve_id));
1752             m_params.pushBack(get_byte(1, curve_id));
1753             appendTlsLengthValue(m_params, ecdh_key, 1);
1754         }
1755         else if (kex_algo == "SRP_SHA")
1756         {
1757             // 2 bigints (N,g) then salt, then server B
1758             
1759             const BigInt N = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1760             const BigInt g = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1761             Vector!ubyte salt = reader.getRange!ubyte(1, 1, 255);
1762             const BigInt B = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1763             
1764             appendTlsLengthValue(m_params, BigInt.encode(N), 2);
1765             appendTlsLengthValue(m_params, BigInt.encode(g), 2);
1766             appendTlsLengthValue(m_params, salt, 1);
1767             appendTlsLengthValue(m_params, BigInt.encode(B), 2);
1768         }
1769         else if (kex_algo != "PSK")
1770                 throw new DecodingError("ServerKeyExchange: Unsupported kex type " ~ kex_algo);
1771         
1772         if (sig_algo != "")
1773         {
1774             if (_version.supportsNegotiableSignatureAlgorithms())
1775             {
1776 				ubyte hash_byte = reader.get_byte();
1777 				ubyte sig_byte = reader.get_byte();
1778 				if (hash_byte == 8) {
1779 					m_hash_algo = SignatureAlgorithms.hashAlgoName(sig_byte);
1780 					m_sig_algo = SignatureAlgorithms.sigAlgoName(hash_byte);
1781 				}
1782 				else {
1783 	                m_hash_algo = SignatureAlgorithms.hashAlgoName(hash_byte);
1784 	                m_sig_algo = SignatureAlgorithms.sigAlgoName(sig_byte);
1785 				}
1786             }
1787             m_signature = reader.getRange!ubyte(2, 0, 65535);
1788         }
1789         
1790         reader.assertDone();
1791     }
1792 
1793     /**
1794     * Create a new TLSServer Key Exchange message
1795     */
1796     this(HandshakeIO io,
1797          HandshakeState state,
1798          in TLSPolicy policy,
1799          TLSCredentialsManager creds,
1800          RandomNumberGenerator rng,
1801          in PrivateKey signing_key = null)
1802     {
1803         const string hostname = state.clientHello().sniHostname();
1804         const string kex_algo = state.ciphersuite().kexAlgo();
1805         
1806         if (kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
1807         {
1808             string identity_hint = creds.pskIdentityHint("tls-server", hostname);
1809             
1810             appendTlsLengthValue(m_params, identity_hint, 2);
1811         }
1812         
1813         if (kex_algo == "DH" || kex_algo == "DHE_PSK")
1814         {
1815             auto dh = DHPrivateKey(rng, policy.dhGroup());
1816 
1817             appendTlsLengthValue(m_params, BigInt.encode(dh.getDomain().getP()), 2);
1818             appendTlsLengthValue(m_params, BigInt.encode(dh.getDomain().getG()), 2);
1819             appendTlsLengthValue(m_params, dh.publicValue(), 2);
1820             m_kex_key = dh.release();
1821         }
1822         else if (kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
1823         {
1824             Vector!string curves = state.clientHello().supportedEccCurves();
1825             
1826             if (curves.empty)
1827                 throw new InternalError("TLSClient sent no ECC extension but we negotiated ECDH");
1828             
1829             const string curve_name = policy.chooseCurve(curves.move());
1830             
1831             if (curve_name == "")
1832                 throw new TLSException(TLSAlert.HANDSHAKE_FAILURE, "Could not agree on an ECC curve with the client");
1833 			const ushort named_curve_id = SupportedEllipticCurves.nameToCurveId(curve_name);
1834 			if (named_curve_id == 0)
1835 				throw new InternalError("TLS does not support ECC with " ~ curve_name);
1836 			Vector!ubyte ecdh_public_val;
1837 
1838 			if (curve_name == "x25519") {
1839 				import botan.pubkey.algo.curve25519;
1840 				Curve25519PrivateKey x25519 = Curve25519PrivateKey(rng);
1841 				ecdh_public_val = x25519.publicValue();
1842 				m_kex_key = x25519.release();
1843 			} else {
1844 	            ECGroup ec_group = ECGroup(curve_name);	            
1845 	            auto ecdh = ECDHPrivateKey(rng, ec_group);
1846 				ecdh_public_val = ecdh.publicValue();
1847 	            
1848 				m_kex_key = ecdh.release();
1849 			}
1850             m_params.pushBack(3); // named curve
1851             m_params.pushBack(get_byte(0, named_curve_id));
1852             m_params.pushBack(get_byte(1, named_curve_id));
1853             
1854             appendTlsLengthValue(m_params, ecdh_public_val, 1);
1855             
1856         }
1857         else if (kex_algo == "SRP_SHA")
1858         {
1859 			static if (BOTAN_HAS_SRP6) {
1860 	            const string srp_identifier = state.clientHello().srpIdentifier();
1861 	            
1862 	            string group_id;
1863 	            BigInt v;
1864 	            Vector!ubyte salt;
1865 	            
1866 	            const bool found = creds.srpVerifier("tls-server", hostname,
1867 	                                                  srp_identifier,
1868 	                                                  group_id, v, salt,
1869 	                                                  policy.hideUnknownUsers());
1870 	            
1871 	            if (!found)
1872 	                throw new TLSException(TLSAlert.UNKNOWN_PSK_IDENTITY, "Unknown SRP user " ~ srp_identifier);
1873 	            
1874 	            m_srp_params = new SRP6ServerSession;
1875 	            
1876 	            const BigInt* B = &m_srp_params.step1(v, group_id, "SHA-1", rng);
1877 	            
1878 	            DLGroup group = DLGroup(group_id);
1879 
1880 	            appendTlsLengthValue(m_params, BigInt.encode(group.getP()), 2);
1881 	            appendTlsLengthValue(m_params, BigInt.encode(group.getG()), 2);
1882 	            appendTlsLengthValue(m_params, salt, 1);
1883 	            appendTlsLengthValue(m_params, BigInt.encode(*B), 2);
1884 			} else {
1885 				throw new InternalError("ServerKeyExchange: Unknown kex type " ~ kex_algo);
1886 			}
1887         }
1888         else if (kex_algo != "PSK")
1889             throw new InternalError("ServerKeyExchange: Unknown kex type " ~ kex_algo);
1890         
1891         if (state.ciphersuite().sigAlgo() != "")
1892         {
1893             assert(signing_key, "Signing key was set");
1894             
1895             Pair!(string, SignatureFormat) format = state.chooseSigFormat(signing_key, m_hash_algo, m_sig_algo, false, policy);
1896             
1897             PKSigner signer = PKSigner(signing_key, format.first, format.second);
1898             
1899             signer.update(state.clientHello().random());
1900             signer.update(state.serverHello().random());
1901             signer.update(params());
1902             m_signature = signer.signature(rng);
1903         }
1904         
1905         state.hash().update(io.send(this));
1906     }
1907 
1908 protected:
1909     /**
1910     * Serialize a TLSServer Key Exchange message
1911     */
1912     override Vector!ubyte serialize() const
1913     {
1914         Vector!ubyte buf = params().dup;
1915         
1916         if (m_signature.length)
1917         {
1918             // This should be an explicit version check
1919             if (m_hash_algo != "" && m_sig_algo != "")
1920             {
1921                 buf.pushBack(SignatureAlgorithms.hashAlgoCode(m_hash_algo));
1922                 buf.pushBack(SignatureAlgorithms.sigAlgoCode(m_sig_algo));
1923             }
1924             
1925             appendTlsLengthValue(buf, m_signature, 2);
1926         }
1927         
1928         return buf.move();
1929     }
1930 
1931 private:
1932     Unique!PrivateKey m_kex_key;
1933 	static if (BOTAN_HAS_SRP6)
1934 	    Unique!SRP6ServerSession m_srp_params;
1935 
1936     Vector!ubyte m_params;
1937 
1938     string m_sig_algo; // sig algo used to create signature
1939     string m_hash_algo; // hash used to create signature
1940     Vector!ubyte m_signature;
1941 }
1942 
1943 /**
1944 * TLSServer Hello Done Message
1945 */
1946 final class ServerHelloDone : HandshakeMessage
1947 {
1948 public:
1949     override const(HandshakeType) type() const { return SERVER_HELLO_DONE; }
1950 
1951     /*
1952     * Create a new TLSServer Hello Done message
1953     */
1954     this(HandshakeIO io, ref HandshakeHash hash)
1955     {
1956         hash.update(io.send(this));
1957     }
1958 
1959     /*
1960     * Deserialize a TLSServer Hello Done message
1961     */
1962     this(const ref Vector!ubyte buf)
1963     {
1964         if (buf.length)
1965             throw new DecodingError("ServerHello_Done: Must be empty, and is not");
1966     }
1967 protected:
1968     /*
1969     * Serialize a TLSServer Hello Done message
1970     */
1971     override Vector!ubyte serialize() const
1972     {
1973         return Vector!ubyte();
1974     }
1975 }
1976 
1977 /**
1978  * New EncryptedExtensions Message used mainly for ChannelIDExtension
1979  */
1980 final class ChannelID : HandshakeMessage
1981 {
1982     override const(HandshakeType) type() const { return CHANNEL_ID; }
1983 
1984     this(HandshakeIO io, 
1985          ref HandshakeHash hash,
1986          TLSCredentialsManager creds, 
1987          string hostname, 
1988          SecureVector!ubyte hs_hash,
1989          SecureVector!ubyte orig_hs_hash = SecureVector!ubyte())
1990     {
1991         m_channel_id = new EncryptedChannelID(creds.channelPrivateKey(hostname), hs_hash.move(), orig_hs_hash.move());
1992         hash.update(io.send(this));
1993     }
1994 
1995     override Vector!ubyte serialize() const
1996     {
1997         Vector!ubyte buf;
1998         buf.reserve(130);
1999 
2000         const ushort extn_code = m_channel_id.type();
2001         const Vector!ubyte extn_val = m_channel_id.serialize();
2002         
2003         buf.pushBack(get_byte(0, extn_code));
2004         buf.pushBack(get_byte(1, extn_code));
2005         
2006         buf.pushBack(get_byte(0, cast(ushort) extn_val.length));
2007         buf.pushBack(get_byte(1, cast(ushort) extn_val.length));
2008         
2009         buf ~= extn_val[];
2010         return buf.move();
2011     }
2012 
2013 private:
2014     Unique!EncryptedChannelID m_channel_id;
2015 }
2016 
2017 /**
2018 * New TLS Session Ticket Message
2019 */
2020 final class NewSessionTicket : HandshakeMessage
2021 {
2022 public:
2023     override const(HandshakeType) type() const { return NEW_SESSION_TICKET; }
2024 
2025     const(Duration) ticketLifetimeHint() const { return m_ticket_lifetime_hint; }
2026     ref const(Vector!ubyte) ticket() const { return m_ticket; }
2027 
2028     this(HandshakeIO io,
2029          ref HandshakeHash hash,
2030          Vector!ubyte ticket,
2031          Duration lifetime) 
2032         
2033     {   
2034         m_ticket_lifetime_hint = lifetime;
2035         m_ticket = ticket.move();
2036         hash.update = io.send(this);
2037     }
2038 
2039     this(const ref Vector!ubyte buf)
2040     {
2041         if (buf.length < 6)
2042             throw new DecodingError("TLSSession ticket message too short to be valid");
2043         
2044         TLSDataReader reader = TLSDataReader("SessionTicket", buf);
2045         
2046         m_ticket_lifetime_hint = reader.get_uint().seconds;
2047         m_ticket = reader.getRange!ubyte(2, 0, 65535);
2048     }
2049 
2050     this(HandshakeIO io, ref HandshakeHash hash)
2051     {
2052         hash.update(io.send(this));
2053     }
2054 
2055 protected:
2056     override Vector!ubyte serialize() const
2057     {
2058         Vector!ubyte buf = Vector!ubyte(4);
2059         storeBigEndian(m_ticket_lifetime_hint.total!"seconds", buf.ptr);
2060         appendTlsLengthValue(buf, m_ticket, 2);
2061         return buf.move();
2062     }
2063 
2064 private:
2065     Duration m_ticket_lifetime_hint;
2066     Vector!ubyte m_ticket;
2067 }
2068 
2069 /**
2070 * Change Cipher Spec
2071 */
2072 final class ChangeCipherSpec : HandshakeMessage
2073 {
2074 public:
2075     override const(HandshakeType) type() const { return HANDSHAKE_CCS; }
2076 
2077     override Vector!ubyte serialize() const
2078     { return Vector!ubyte(cast(ubyte[])[1]); }
2079 }
2080 
2081 
2082 package:
2083 
2084 string certTypeCodeToName(ubyte code)
2085 {
2086     switch(code)
2087     {
2088         case 1:
2089             return "RSA";
2090         case 2:
2091             return "DSA";
2092         case 64:
2093             return "ECDSA";
2094         default:
2095             return ""; // DH or something else
2096     }
2097 }
2098 
2099 ubyte certTypeNameToCode(in string name)
2100 {
2101     if (name == "RSA")
2102         return 1;
2103     if (name == "DSA")
2104         return 2;
2105     if (name == "ECDSA")
2106         return 64;
2107     
2108     throw new InvalidArgument("Unknown cert type " ~ name);
2109 }
2110 
2111 
2112 SecureVector!ubyte stripLeadingZeros()(auto const ref SecureVector!ubyte input)
2113 {
2114     size_t leading_zeros = 0;
2115     
2116     for (size_t i = 0; i != input.length; ++i)
2117     {
2118         if (input[i] != 0)
2119             break;
2120         ++leading_zeros;
2121     }
2122     
2123     SecureVector!ubyte output = SecureVector!ubyte(input.ptr[leading_zeros .. input.length]);
2124     return output;
2125 }
2126 
2127 
2128 /*
2129 * Compute the verifyData
2130 */
2131 Vector!ubyte finishedComputeVerify(in HandshakeState state, ConnectionSide side)
2132 {
2133     __gshared immutable const(ubyte)[] TLS_CLIENT_LABEL = [
2134         0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69,
2135         0x73, 0x68, 0x65, 0x64 ];
2136     
2137     __gshared immutable const(ubyte)[] TLS_SERVER_LABEL = [
2138         0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69,
2139         0x73, 0x68, 0x65, 0x64 ];
2140     
2141     Unique!KDF prf = state.protocolSpecificPrf();
2142     
2143     Vector!ubyte input;
2144 	input.reserve(64);
2145     if (side == CLIENT)
2146         input ~= cast(ubyte[])TLS_CLIENT_LABEL;
2147     else
2148         input ~= cast(ubyte[])TLS_SERVER_LABEL;
2149     
2150     auto vec = state.hash().flushInto(state.Version(), state.ciphersuite().prfAlgo());
2151 	input ~= vec[];
2152 	return unlock(prf.deriveKey(12, state.sessionKeys().masterSecret(), input));
2153 
2154 }
2155 
2156 Vector!ubyte makeHelloRandom(RandomNumberGenerator rng, in TLSPolicy policy)
2157 {
2158     Vector!ubyte buf = Vector!ubyte(32);
2159     rng.randomize(&buf[0], buf.length);
2160 
2161     if (policy.includeTimeInHelloRandom())
2162     {
2163         const uint time32 = cast(uint)(Clock.currTime(UTC()).toUnixTime);
2164         storeBigEndian(time32, buf.ptr);
2165     }
2166 
2167     return buf;
2168 }