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 	                auto param_a = BigInt.decode(reader.getRange!ubyte(2, 0, 65535));
925 	                m_pre_master = srp.step2(&param_a).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             auto cert = X509Certificate(cast(DataSource)cert_buf);
1294             m_certs.pushBack(cert);
1295             
1296             certs += cert_size + 3;
1297         }
1298     }
1299 
1300 protected:
1301     /**
1302     * Serialize a Certificate message
1303     */
1304     override Vector!ubyte serialize() const
1305     {
1306 		Vector!ubyte buf;
1307 		buf.reserve(2048);
1308 		buf.length = 3;
1309         for (size_t i = 0; i != m_certs.length; ++i)
1310         {
1311             auto cert = m_certs[i];
1312             if (!cert.isValid()) continue;
1313             Vector!ubyte raw_cert = cert.BER_encode();
1314             const size_t cert_size = raw_cert.length;
1315             foreach (size_t j; 0 .. 3)
1316                 buf.pushBack(get_byte!uint(j+1, cast(uint) cert_size));
1317             buf ~= raw_cert;
1318         }
1319         
1320         const size_t buf_size = buf.length - 3;
1321         foreach (size_t i; 0 .. 3)
1322             buf[i] = get_byte!uint(i+1, cast(uint) buf_size);
1323         
1324         return buf.move();
1325     }
1326 
1327 private:
1328     Array!X509Certificate m_certs;
1329 }
1330 
1331 /**
1332 * Certificate Request Message
1333 */
1334 final class CertificateReq : HandshakeMessage
1335 {
1336 public:
1337     override const(HandshakeType) type() const { return CERTIFICATE_REQUEST; }
1338 
1339     ref const(Vector!string) acceptableCertTypes() const
1340     { return m_cert_key_types; }
1341 
1342     ref const(Vector!X509DN) acceptableCAs() const { return m_names; }
1343 
1344     Vector!( Pair!(string, string) ) supportedAlgos() const
1345     { return m_supported_algos.dup; }
1346 
1347     /**
1348     * Create a new Certificate Request message
1349     */
1350     this(HandshakeIO io,
1351          ref HandshakeHash hash,
1352          in TLSPolicy policy,
1353          Vector!X509DN ca_certs,
1354          TLSProtocolVersion _version) 
1355     {
1356         m_names = ca_certs.move();
1357         m_cert_key_types = [ "RSA", "DSA", "ECDSA" ];
1358 		static Vector!( Pair!(string, string)  ) last_supported_algos;
1359 		static TLSPolicy last_tls_policy;
1360         static TLSProtocolVersion last_version;
1361 		if (policy is last_tls_policy && _version == last_version)
1362 			m_supported_algos = last_supported_algos.dup;
1363 		else {
1364 			m_supported_algos.reserve(16);
1365 	        if (_version.supportsNegotiableSignatureAlgorithms())
1366 	        {
1367 	            Vector!string hashes = policy.allowedSignatureHashes();
1368 	            Vector!string sigs = policy.allowedSignatureMethods();
1369 	            
1370 	            for (size_t i = 0; i != hashes.length; ++i)
1371 	                for (size_t j = 0; j != sigs.length; ++j)
1372 	                    m_supported_algos.pushBack(makePair(hashes[i], sigs[j]));
1373 	        }
1374 			last_tls_policy = cast() policy;
1375             last_version = _version;
1376 			last_supported_algos = m_supported_algos.dup;
1377 		}
1378         
1379         hash.update(io.send(this));
1380     }
1381 
1382     /**
1383     * Deserialize a Certificate Request message
1384     */
1385     this(const ref Vector!ubyte buf, TLSProtocolVersion _version)
1386     {
1387         if (buf.length < 4)
1388             throw new DecodingError("Certificate_Req: Bad certificate request");
1389         
1390         TLSDataReader reader = TLSDataReader("CertificateRequest", buf);
1391 
1392         Vector!ubyte cert_type_codes = reader.getRangeVector!ubyte(1, 1, 255);
1393         
1394         for (size_t i = 0; i != cert_type_codes.length; ++i)
1395         {
1396             const string cert_type_name = certTypeCodeToName(cert_type_codes[i]);
1397             
1398             if (cert_type_name == "") // something we don't know
1399                 continue;
1400             
1401             m_cert_key_types.pushBack(cert_type_name);
1402         }
1403         
1404         if (_version.supportsNegotiableSignatureAlgorithms())
1405         {
1406             Vector!ubyte sig_hash_algs = reader.getRangeVector!ubyte(2, 2, 65534);
1407             
1408             if (sig_hash_algs.length % 2 != 0)
1409                 throw new DecodingError("Bad length for signature IDs in certificate request");
1410             
1411             for (size_t i = 0; i != sig_hash_algs.length; i += 2)
1412             {
1413                 string hash = SignatureAlgorithms.hashAlgoName(sig_hash_algs[i]);
1414                 string sig = SignatureAlgorithms.sigAlgoName(sig_hash_algs[i+1]);
1415                 m_supported_algos.pushBack(makePair(hash, sig));
1416             }
1417         }
1418         
1419         const ushort purported_size = reader.get_ushort();
1420         
1421         if (reader.remainingBytes() != purported_size)
1422             throw new DecodingError("Inconsistent length in certificate request");
1423         
1424         while (reader.hasRemaining())
1425         {
1426             Vector!ubyte name_bits = reader.getRangeVector!ubyte(2, 0, 65535);
1427             
1428             BERDecoder decoder = BERDecoder(name_bits.ptr, name_bits.length);
1429             X509DN name = X509DN();
1430             decoder.decode(name);
1431             m_names.pushBack(name);
1432         }
1433     }
1434 
1435 protected:
1436 
1437     /**
1438     * Serialize a Certificate Request message
1439     */
1440     override Vector!ubyte serialize() const
1441     {
1442         Vector!ubyte buf;
1443 		buf.reserve(256);
1444         Vector!ubyte cert_types;
1445 		cert_types.reserve(64);
1446         for (size_t i = 0; i != m_cert_key_types.length; ++i)
1447             cert_types.pushBack(certTypeNameToCode(m_cert_key_types[i]));
1448 
1449         appendTlsLengthValue(buf, cert_types, 1);
1450         
1451         if (!m_supported_algos.empty) {
1452 			Unique!SignatureAlgorithms sig_algos = new SignatureAlgorithms(m_supported_algos.dup);
1453             buf ~= sig_algos.serialize();
1454 		}
1455         
1456         Vector!ubyte encoded_names;
1457         
1458         for (size_t i = 0; i != m_names.length; ++i)
1459         {
1460             DEREncoder encoder = DEREncoder();
1461             encoder.encode(m_names[i]);
1462             
1463             appendTlsLengthValue(encoded_names, encoder.getContents(), 2);
1464         }
1465         
1466         appendTlsLengthValue(buf, encoded_names, 2);
1467         
1468         return buf.move();
1469     }
1470 
1471 private:
1472     Vector!X509DN m_names;
1473     Vector!string m_cert_key_types;
1474 
1475     Vector!( Pair!(string, string)  ) m_supported_algos;
1476 }
1477 
1478 /**
1479 * Certificate Verify Message
1480 */
1481 final class CertificateVerify : HandshakeMessage
1482 {
1483 public:
1484     override const(HandshakeType) type() const { return CERTIFICATE_VERIFY; }
1485 
1486     /**
1487     * Check the signature on a certificate verify message
1488     * Params:
1489     *  cert = the purported certificate
1490     *  state = the handshake state
1491     */
1492     bool verify(const X509Certificate cert,
1493                 const HandshakeState state) const
1494     {
1495         Unique!PublicKey key = cert.subjectPublicKey();
1496         
1497         Pair!(string, SignatureFormat) format = state.understandSigFormat(*key, m_hash_algo, m_sig_algo, true);
1498         
1499         PKVerifier verifier = PKVerifier(*key, format.first, format.second);
1500         
1501         return verifier.verifyMessage(state.hash().getContents(), m_signature);
1502     }
1503 
1504     /*
1505     * Create a new Certificate Verify message
1506     */
1507     this(HandshakeIO io,
1508          HandshakeState state,
1509          in TLSPolicy policy,
1510          RandomNumberGenerator rng,
1511          const PrivateKey priv_key)
1512     {
1513         assert(priv_key, "No private key defined");
1514         
1515         Pair!(string, SignatureFormat) format = state.chooseSigFormat(priv_key, m_hash_algo, m_sig_algo, true, policy);
1516         
1517         PKSigner signer = PKSigner(priv_key, format.first, format.second);
1518         
1519 		m_signature = signer.signMessage(state.hash().getContents(), rng);
1520                 
1521         state.hash().update(io.send(this));
1522     }
1523 
1524     /*
1525     * Deserialize a Certificate Verify message
1526     */
1527     this(const ref Vector!ubyte buf,
1528          TLSProtocolVersion _version)
1529     {
1530         TLSDataReader reader = TLSDataReader("CertificateVerify", buf);
1531         
1532         if (_version.supportsNegotiableSignatureAlgorithms())
1533         {
1534             m_hash_algo = SignatureAlgorithms.hashAlgoName(reader.get_byte());
1535             m_sig_algo = SignatureAlgorithms.sigAlgoName(reader.get_byte());
1536         }
1537         
1538         m_signature = reader.getRange!ubyte(2, 0, 65535);
1539     }
1540 
1541 protected:
1542     /*
1543     * Serialize a Certificate Verify message
1544     */
1545     override Vector!ubyte serialize() const
1546     {
1547         Vector!ubyte buf;
1548         
1549         if (m_hash_algo != "" && m_sig_algo != "")
1550         {
1551             buf.pushBack(SignatureAlgorithms.hashAlgoCode(m_hash_algo));
1552             buf.pushBack(SignatureAlgorithms.sigAlgoCode(m_sig_algo));
1553         }
1554         
1555         const ushort sig_len = cast(ushort) m_signature.length;
1556         buf.pushBack(get_byte(0, sig_len));
1557         buf.pushBack(get_byte(1, sig_len));
1558         buf ~= m_signature[];
1559         
1560         return buf.move();
1561     }
1562 
1563 private:
1564     string m_sig_algo; // sig algo used to create signature
1565     string m_hash_algo; // hash used to create signature
1566     Vector!ubyte m_signature;
1567 }
1568 
1569 /**
1570 * Finished Message
1571 */
1572 final class Finished : HandshakeMessage
1573 {
1574 public:
1575     override const(HandshakeType) type() const { return FINISHED; }
1576 
1577     ref const(Vector!ubyte) verifyData() const
1578     { return m_verification_data; }
1579 
1580 	const(ubyte[]) verifyDataBytes() const { return m_verification_data[]; }
1581 
1582     /*
1583     * Verify a Finished message
1584     */
1585     bool verify(in HandshakeState state, ConnectionSide side) const
1586     {
1587         return (m_verification_data == finishedComputeVerify(state, side));
1588     }
1589 
1590     /*
1591     * Create a new Finished message
1592     */
1593     this(HandshakeIO io,
1594          HandshakeState state,
1595          ConnectionSide side)
1596     {
1597         m_verification_data = finishedComputeVerify(state, side);
1598         state.hash().update(io.send(this));
1599     }
1600 
1601     /*
1602     * Deserialize a Finished message
1603     */
1604     this(Vector!ubyte buf)
1605     {
1606         m_verification_data = buf.move();
1607     }
1608 
1609 protected:
1610     /*
1611     * Serialize a Finished message
1612     */
1613     override Vector!ubyte serialize() const
1614     {
1615         return m_verification_data.dup;
1616     }
1617    
1618 private:
1619     Vector!ubyte m_verification_data;
1620 }
1621 
1622 /**
1623 * Hello Request Message
1624 */
1625 final class HelloRequest : HandshakeMessage
1626 {
1627 public:
1628     override const(HandshakeType) type() const { return HELLO_REQUEST; }
1629 
1630     /*
1631     * Create a new Hello Request message
1632     */
1633     this(HandshakeIO io)
1634     {
1635         io.send(this);
1636     }
1637 
1638     /*
1639     * Deserialize a Hello Request message
1640     */
1641     this(const ref Vector!ubyte buf)
1642     {
1643         if (buf.length)
1644             throw new DecodingError("Bad HelloRequest, has non-zero size");
1645     }
1646 
1647 protected:
1648     /*
1649     * Serialize a Hello Request message
1650     */
1651     override Vector!ubyte serialize() const
1652     {
1653         return Vector!ubyte();
1654     }
1655 }
1656 
1657 /**
1658 * TLSServer Key Exchange Message
1659 */
1660 final class ServerKeyExchange : HandshakeMessage
1661 {
1662 public:
1663     override const(HandshakeType) type() const { return SERVER_KEX; }
1664 
1665     ref const(Vector!ubyte) params() const { return m_params; }
1666 
1667     /**
1668     * Verify a TLSServer Key Exchange message
1669     */
1670     bool verify(in PublicKey server_key,
1671                 const HandshakeState state) const
1672     {
1673         Pair!(string, SignatureFormat) format = state.understandSigFormat(server_key, m_hash_algo, m_sig_algo, false);
1674 
1675         PKVerifier verifier = PKVerifier(server_key, format.first, format.second);
1676         verifier.update(state.clientHello().random());
1677         verifier.update(state.serverHello().random());
1678         verifier.update(params());
1679         return verifier.checkSignature(m_signature);
1680     }
1681 
1682     // Only valid for certain kex types
1683     const(PrivateKey) serverKexKey() const
1684     {
1685         assert(m_kex_key, "PrivateKey cannot be null");
1686         return *m_kex_key;
1687     }
1688 
1689 	static if (BOTAN_HAS_SRP6) {
1690 	    // Only valid for SRP negotiation
1691 	    const(SRP6ServerSession) serverSrpParams() const
1692 	    {
1693 	        assert(m_srp_params, "SRP6ServerSession cannot be null");
1694 	        return *m_srp_params;
1695 	    }
1696 	}
1697 
1698     /**
1699     * Deserialize a TLSServer Key Exchange message
1700     */
1701     this(const ref Vector!ubyte buf,
1702          in string kex_algo,
1703          in string sig_algo,
1704          TLSProtocolVersion _version) 
1705     {
1706         m_kex_key.free();
1707 		static if (BOTAN_HAS_SRP6)
1708 	        m_srp_params.free();
1709         if (buf.length < 6)
1710             throw new DecodingError("ServerKeyExchange: Packet corrupted");
1711         
1712         TLSDataReader reader = TLSDataReader("ServerKeyExchange", buf);
1713         
1714         /*
1715         * We really are just serializing things back to what they were
1716         * before, but unfortunately to know where the signature is we need
1717         * to be able to parse the whole thing anyway.
1718         */
1719         
1720         if (kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
1721         {
1722             const string identity_hint = reader.getString(2, 0, 65535);
1723             appendTlsLengthValue(m_params, identity_hint, 2);
1724         }
1725         
1726         if (kex_algo == "DH" || kex_algo == "DHE_PSK")
1727         {
1728             // 3 bigints, DH p, g, Y
1729             
1730             foreach (size_t i; 0 .. 3)
1731             {
1732                 BigInt v = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1733                 appendTlsLengthValue(m_params, BigInt.encode(v), 2);
1734             }
1735         }
1736         else if (kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
1737         {
1738             const ubyte curve_type = reader.get_byte();
1739             
1740             if (curve_type != 3)
1741                 throw new DecodingError("ServerKeyExchange: TLSServer sent non-named ECC curve");
1742             
1743             const ushort curve_id = reader.get_ushort();
1744             
1745             const string name = SupportedEllipticCurves.curveIdToName(curve_id);
1746             
1747             Vector!ubyte ecdh_key = reader.getRange!ubyte(1, 1, 255);
1748             
1749             if (name == "")
1750                 throw new DecodingError("ServerKeyExchange: TLSServer sent unknown named curve " ~
1751                                          to!string(curve_id));
1752             
1753             m_params.pushBack(curve_type);
1754             m_params.pushBack(get_byte(0, curve_id));
1755             m_params.pushBack(get_byte(1, curve_id));
1756             appendTlsLengthValue(m_params, ecdh_key, 1);
1757         }
1758         else if (kex_algo == "SRP_SHA")
1759         {
1760             // 2 bigints (N,g) then salt, then server B
1761             
1762             const BigInt N = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1763             const BigInt g = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1764             Vector!ubyte salt = reader.getRange!ubyte(1, 1, 255);
1765             const BigInt B = BigInt.decode(reader.getRange!ubyte(2, 1, 65535));
1766             
1767             appendTlsLengthValue(m_params, BigInt.encode(N), 2);
1768             appendTlsLengthValue(m_params, BigInt.encode(g), 2);
1769             appendTlsLengthValue(m_params, salt, 1);
1770             appendTlsLengthValue(m_params, BigInt.encode(B), 2);
1771         }
1772         else if (kex_algo != "PSK")
1773                 throw new DecodingError("ServerKeyExchange: Unsupported kex type " ~ kex_algo);
1774         
1775         if (sig_algo != "")
1776         {
1777             if (_version.supportsNegotiableSignatureAlgorithms())
1778             {
1779 				ubyte hash_byte = reader.get_byte();
1780 				ubyte sig_byte = reader.get_byte();
1781 				if (hash_byte == 8) {
1782 					m_hash_algo = SignatureAlgorithms.hashAlgoName(sig_byte);
1783 					m_sig_algo = SignatureAlgorithms.sigAlgoName(hash_byte);
1784 				}
1785 				else {
1786 	                m_hash_algo = SignatureAlgorithms.hashAlgoName(hash_byte);
1787 	                m_sig_algo = SignatureAlgorithms.sigAlgoName(sig_byte);
1788 				}
1789             }
1790             m_signature = reader.getRange!ubyte(2, 0, 65535);
1791         }
1792         
1793         reader.assertDone();
1794     }
1795 
1796     /**
1797     * Create a new TLSServer Key Exchange message
1798     */
1799     this(HandshakeIO io,
1800          HandshakeState state,
1801          in TLSPolicy policy,
1802          TLSCredentialsManager creds,
1803          RandomNumberGenerator rng,
1804          in PrivateKey signing_key = null)
1805     {
1806         const string hostname = state.clientHello().sniHostname();
1807         const string kex_algo = state.ciphersuite().kexAlgo();
1808         
1809         if (kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
1810         {
1811             string identity_hint = creds.pskIdentityHint("tls-server", hostname);
1812             
1813             appendTlsLengthValue(m_params, identity_hint, 2);
1814         }
1815         
1816         if (kex_algo == "DH" || kex_algo == "DHE_PSK")
1817         {
1818             auto dh = DHPrivateKey(rng, policy.dhGroup());
1819 
1820             appendTlsLengthValue(m_params, BigInt.encode(dh.getDomain().getP()), 2);
1821             appendTlsLengthValue(m_params, BigInt.encode(dh.getDomain().getG()), 2);
1822             appendTlsLengthValue(m_params, dh.publicValue(), 2);
1823             m_kex_key = dh.release();
1824         }
1825         else if (kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
1826         {
1827             Vector!string curves = state.clientHello().supportedEccCurves();
1828             
1829             if (curves.empty)
1830                 throw new InternalError("TLSClient sent no ECC extension but we negotiated ECDH");
1831             
1832             const string curve_name = policy.chooseCurve(curves.move());
1833             
1834             if (curve_name == "")
1835                 throw new TLSException(TLSAlert.HANDSHAKE_FAILURE, "Could not agree on an ECC curve with the client");
1836 			const ushort named_curve_id = SupportedEllipticCurves.nameToCurveId(curve_name);
1837 			if (named_curve_id == 0)
1838 				throw new InternalError("TLS does not support ECC with " ~ curve_name);
1839 			Vector!ubyte ecdh_public_val;
1840 
1841 			if (curve_name == "x25519") {
1842 				import botan.pubkey.algo.curve25519;
1843 				Curve25519PrivateKey x25519 = Curve25519PrivateKey(rng);
1844 				ecdh_public_val = x25519.publicValue();
1845 				m_kex_key = x25519.release();
1846 			} else {
1847 	            ECGroup ec_group = ECGroup(curve_name);	            
1848 	            auto ecdh = ECDHPrivateKey(rng, ec_group);
1849 				ecdh_public_val = ecdh.publicValue();
1850 	            
1851 				m_kex_key = ecdh.release();
1852 			}
1853             m_params.pushBack(3); // named curve
1854             m_params.pushBack(get_byte(0, named_curve_id));
1855             m_params.pushBack(get_byte(1, named_curve_id));
1856             
1857             appendTlsLengthValue(m_params, ecdh_public_val, 1);
1858             
1859         }
1860         else if (kex_algo == "SRP_SHA")
1861         {
1862 			static if (BOTAN_HAS_SRP6) {
1863 	            const string srp_identifier = state.clientHello().srpIdentifier();
1864 	            
1865 	            string group_id;
1866 	            BigInt v;
1867 	            Vector!ubyte salt;
1868 	            
1869 	            const bool found = creds.srpVerifier("tls-server", hostname,
1870 	                                                  srp_identifier,
1871 	                                                  group_id, v, salt,
1872 	                                                  policy.hideUnknownUsers());
1873 	            
1874 	            if (!found)
1875 	                throw new TLSException(TLSAlert.UNKNOWN_PSK_IDENTITY, "Unknown SRP user " ~ srp_identifier);
1876 	            
1877 	            m_srp_params = new SRP6ServerSession;
1878 	            
1879 	            const BigInt* B = &m_srp_params.step1(v, group_id, "SHA-1", rng);
1880 	            
1881 	            DLGroup group = DLGroup(group_id);
1882 
1883 	            appendTlsLengthValue(m_params, BigInt.encode(group.getP()), 2);
1884 	            appendTlsLengthValue(m_params, BigInt.encode(group.getG()), 2);
1885 	            appendTlsLengthValue(m_params, salt, 1);
1886 	            appendTlsLengthValue(m_params, BigInt.encode(*B), 2);
1887 			} else {
1888 				throw new InternalError("ServerKeyExchange: Unknown kex type " ~ kex_algo);
1889 			}
1890         }
1891         else if (kex_algo != "PSK")
1892             throw new InternalError("ServerKeyExchange: Unknown kex type " ~ kex_algo);
1893         
1894         if (state.ciphersuite().sigAlgo() != "")
1895         {
1896             assert(signing_key, "Signing key was set");
1897             
1898             Pair!(string, SignatureFormat) format = state.chooseSigFormat(signing_key, m_hash_algo, m_sig_algo, false, policy);
1899             
1900             PKSigner signer = PKSigner(signing_key, format.first, format.second);
1901             
1902             signer.update(state.clientHello().random());
1903             signer.update(state.serverHello().random());
1904             signer.update(params());
1905             m_signature = signer.signature(rng);
1906         }
1907         
1908         state.hash().update(io.send(this));
1909     }
1910 
1911 protected:
1912     /**
1913     * Serialize a TLSServer Key Exchange message
1914     */
1915     override Vector!ubyte serialize() const
1916     {
1917         Vector!ubyte buf = params().dup;
1918         
1919         if (m_signature.length)
1920         {
1921             // This should be an explicit version check
1922             if (m_hash_algo != "" && m_sig_algo != "")
1923             {
1924                 buf.pushBack(SignatureAlgorithms.hashAlgoCode(m_hash_algo));
1925                 buf.pushBack(SignatureAlgorithms.sigAlgoCode(m_sig_algo));
1926             }
1927             
1928             appendTlsLengthValue(buf, m_signature, 2);
1929         }
1930         
1931         return buf.move();
1932     }
1933 
1934 private:
1935     Unique!PrivateKey m_kex_key;
1936 	static if (BOTAN_HAS_SRP6)
1937 	    Unique!SRP6ServerSession m_srp_params;
1938 
1939     Vector!ubyte m_params;
1940 
1941     string m_sig_algo; // sig algo used to create signature
1942     string m_hash_algo; // hash used to create signature
1943     Vector!ubyte m_signature;
1944 }
1945 
1946 /**
1947 * TLSServer Hello Done Message
1948 */
1949 final class ServerHelloDone : HandshakeMessage
1950 {
1951 public:
1952     override const(HandshakeType) type() const { return SERVER_HELLO_DONE; }
1953 
1954     /*
1955     * Create a new TLSServer Hello Done message
1956     */
1957     this(HandshakeIO io, ref HandshakeHash hash)
1958     {
1959         hash.update(io.send(this));
1960     }
1961 
1962     /*
1963     * Deserialize a TLSServer Hello Done message
1964     */
1965     this(const ref Vector!ubyte buf)
1966     {
1967         if (buf.length)
1968             throw new DecodingError("ServerHello_Done: Must be empty, and is not");
1969     }
1970 protected:
1971     /*
1972     * Serialize a TLSServer Hello Done message
1973     */
1974     override Vector!ubyte serialize() const
1975     {
1976         return Vector!ubyte();
1977     }
1978 }
1979 
1980 /**
1981  * New EncryptedExtensions Message used mainly for ChannelIDExtension
1982  */
1983 final class ChannelID : HandshakeMessage
1984 {
1985     override const(HandshakeType) type() const { return CHANNEL_ID; }
1986 
1987     this(HandshakeIO io, 
1988          ref HandshakeHash hash,
1989          TLSCredentialsManager creds, 
1990          string hostname, 
1991          SecureVector!ubyte hs_hash,
1992          SecureVector!ubyte orig_hs_hash = SecureVector!ubyte())
1993     {
1994         m_channel_id = new EncryptedChannelID(creds.channelPrivateKey(hostname), hs_hash.move(), orig_hs_hash.move());
1995         hash.update(io.send(this));
1996     }
1997 
1998     override Vector!ubyte serialize() const
1999     {
2000         Vector!ubyte buf;
2001         buf.reserve(130);
2002 
2003         const ushort extn_code = m_channel_id.type();
2004         const Vector!ubyte extn_val = m_channel_id.serialize();
2005         
2006         buf.pushBack(get_byte(0, extn_code));
2007         buf.pushBack(get_byte(1, extn_code));
2008         
2009         buf.pushBack(get_byte(0, cast(ushort) extn_val.length));
2010         buf.pushBack(get_byte(1, cast(ushort) extn_val.length));
2011         
2012         buf ~= extn_val[];
2013         return buf.move();
2014     }
2015 
2016 private:
2017     Unique!EncryptedChannelID m_channel_id;
2018 }
2019 
2020 /**
2021 * New TLS Session Ticket Message
2022 */
2023 final class NewSessionTicket : HandshakeMessage
2024 {
2025 public:
2026     override const(HandshakeType) type() const { return NEW_SESSION_TICKET; }
2027 
2028     const(Duration) ticketLifetimeHint() const { return m_ticket_lifetime_hint; }
2029     ref const(Vector!ubyte) ticket() const { return m_ticket; }
2030 
2031     this(HandshakeIO io,
2032          ref HandshakeHash hash,
2033          Vector!ubyte ticket,
2034          Duration lifetime) 
2035         
2036     {   
2037         m_ticket_lifetime_hint = lifetime;
2038         m_ticket = ticket.move();
2039         hash.update = io.send(this);
2040     }
2041 
2042     this(const ref Vector!ubyte buf)
2043     {
2044         if (buf.length < 6)
2045             throw new DecodingError("TLSSession ticket message too short to be valid");
2046         
2047         TLSDataReader reader = TLSDataReader("SessionTicket", buf);
2048         
2049         m_ticket_lifetime_hint = reader.get_uint().seconds;
2050         m_ticket = reader.getRange!ubyte(2, 0, 65535);
2051     }
2052 
2053     this(HandshakeIO io, ref HandshakeHash hash)
2054     {
2055         hash.update(io.send(this));
2056     }
2057 
2058 protected:
2059     override Vector!ubyte serialize() const
2060     {
2061         Vector!ubyte buf = Vector!ubyte(4);
2062         storeBigEndian(m_ticket_lifetime_hint.total!"seconds", buf.ptr);
2063         appendTlsLengthValue(buf, m_ticket, 2);
2064         return buf.move();
2065     }
2066 
2067 private:
2068     Duration m_ticket_lifetime_hint;
2069     Vector!ubyte m_ticket;
2070 }
2071 
2072 /**
2073 * Change Cipher Spec
2074 */
2075 final class ChangeCipherSpec : HandshakeMessage
2076 {
2077 public:
2078     override const(HandshakeType) type() const { return HANDSHAKE_CCS; }
2079 
2080     override Vector!ubyte serialize() const
2081     { return Vector!ubyte(cast(ubyte[])[1]); }
2082 }
2083 
2084 
2085 package:
2086 
2087 string certTypeCodeToName(ubyte code)
2088 {
2089     switch(code)
2090     {
2091         case 1:
2092             return "RSA";
2093         case 2:
2094             return "DSA";
2095         case 64:
2096             return "ECDSA";
2097         default:
2098             return ""; // DH or something else
2099     }
2100 }
2101 
2102 ubyte certTypeNameToCode(in string name)
2103 {
2104     if (name == "RSA")
2105         return 1;
2106     if (name == "DSA")
2107         return 2;
2108     if (name == "ECDSA")
2109         return 64;
2110     
2111     throw new InvalidArgument("Unknown cert type " ~ name);
2112 }
2113 
2114 
2115 SecureVector!ubyte stripLeadingZeros()(auto const ref SecureVector!ubyte input)
2116 {
2117     size_t leading_zeros = 0;
2118     
2119     for (size_t i = 0; i != input.length; ++i)
2120     {
2121         if (input[i] != 0)
2122             break;
2123         ++leading_zeros;
2124     }
2125     
2126     SecureVector!ubyte output = SecureVector!ubyte(input.ptr[leading_zeros .. input.length]);
2127     return output;
2128 }
2129 
2130 
2131 /*
2132 * Compute the verifyData
2133 */
2134 Vector!ubyte finishedComputeVerify(in HandshakeState state, ConnectionSide side)
2135 {
2136     __gshared immutable const(ubyte)[] TLS_CLIENT_LABEL = [
2137         0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69,
2138         0x73, 0x68, 0x65, 0x64 ];
2139     
2140     __gshared immutable const(ubyte)[] TLS_SERVER_LABEL = [
2141         0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69,
2142         0x73, 0x68, 0x65, 0x64 ];
2143     
2144     Unique!KDF prf = state.protocolSpecificPrf();
2145     
2146     Vector!ubyte input;
2147 	input.reserve(64);
2148     if (side == CLIENT)
2149         input ~= cast(ubyte[])TLS_CLIENT_LABEL;
2150     else
2151         input ~= cast(ubyte[])TLS_SERVER_LABEL;
2152     
2153     auto vec = state.hash().flushInto(state.Version(), state.ciphersuite().prfAlgo());
2154 	input ~= vec[];
2155 	return unlock(prf.deriveKey(12, state.sessionKeys().masterSecret(), input));
2156 
2157 }
2158 
2159 Vector!ubyte makeHelloRandom(RandomNumberGenerator rng, in TLSPolicy policy)
2160 {
2161     Vector!ubyte buf = Vector!ubyte(32);
2162     rng.randomize(&buf[0], buf.length);
2163 
2164     if (policy.includeTimeInHelloRandom())
2165     {
2166         const uint time32 = cast(uint)(Clock.currTime(UTC()).toUnixTime);
2167         storeBigEndian(time32, buf.ptr);
2168     }
2169 
2170     return buf;
2171 }