1 /**
2 * TLS Extensions
3 * 
4 * Copyright:
5 * (C) 2011-2012,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.extensions;
12 
13 import std.exception : enforce;
14 import botan.constants;
15 static if (BOTAN_HAS_TLS):
16 public alias ushort HandshakeExtensionType;
17 public enum : HandshakeExtensionType {
18     TLSEXT_SERVER_NAME_INDICATION    = 0,
19     TLSEXT_MAX_FRAGMENT_LENGTH       = 1,
20     TLSEXT_CLIENT_CERT_URL           = 2,
21     TLSEXT_TRUSTED_CA_KEYS           = 3,
22     TLSEXT_TRUNCATED_HMAC            = 4,
23 	TLSEXT_STATUS_REQUEST            = 5,
24 
25     TLSEXT_CERTIFICATE_TYPES         = 9,
26     TLSEXT_USABLE_ELLIPTIC_CURVES    = 10,
27     TLSEXT_EC_POINT_FORMATS          = 11,
28     TLSEXT_SRP_IDENTIFIER            = 12,
29     TLSEXT_SIGNATURE_ALGORITHMS      = 13,
30     TLSEXT_HEARTBEAT_SUPPORT         = 15,
31     TLSEXT_ALPN                      = 16,
32 	TLSEXT_SIGNED_CERT_TIMESTAMP     = 18,
33 	TLSEXT_PADDING                   = 21,
34 	TLSEXT_EXTENDED_MASTER_SECRET    = 23,
35 
36     TLSEXT_SESSION_TICKET            = 35,
37 
38 	TLSEXT_NPN                       = 13172,
39 
40 	TLSEXT_CHANNEL_ID                = 30032,
41 
42     TLSEXT_SAFE_RENEGOTIATION        = 65281,
43 }
44 
45 package:
46 
47 import memutils.vector;
48 import botan.tls.magic;
49 import botan.utils.types;
50 import memutils.hashmap;
51 import botan.tls.reader;
52 import botan.tls.exceptn;
53 import botan.tls.alert;
54 import botan.utils.types : Unique;
55 import botan.utils.get_byte;
56 import std.conv : to;
57 import std.array : Appender;
58 
59 /**
60 * Base class representing a TLS extension of some kind
61 */
62 interface Extension
63 {
64 public:
65     /**
66     * Returns: code number of the extension
67     */
68     abstract HandshakeExtensionType type() const;
69 
70     /**
71     * Returns: serialized binary for the extension
72     */
73     abstract Vector!ubyte serialize() const;
74 
75     /**
76     * Returns: if we should encode this extension or not
77     */
78     abstract @property bool empty() const;
79 }
80 
81 class NPN : Extension
82 {
83 	static HandshakeExtensionType staticType() { return TLSEXT_NPN; }
84 	
85 	override HandshakeExtensionType type() const { return staticType(); }
86 	
87 	override Vector!ubyte serialize() const
88 	{
89 		return Vector!ubyte();
90 	}
91 	
92 	override @property bool empty() const { return false; }
93 }
94 
95 /**
96  * OCSP Stapling
97 */
98 class StatusRequest : Extension
99 {
100 	static HandshakeExtensionType staticType() { return TLSEXT_STATUS_REQUEST; }
101 	
102 	override HandshakeExtensionType type() const { return staticType(); }
103 	
104 	override Vector!ubyte serialize() const
105 	{
106 		Vector!ubyte buf;
107 		buf.reserve(5);
108 		buf.pushBack(0x01); // OCSP
109 
110 		// Responders
111 		buf.pushBack(0x00);
112 		buf.pushBack(0x00);
113 
114 		// Request Extensions
115 		buf.pushBack(0x00);
116 		buf.pushBack(0x00);
117 		
118 		return buf.move();
119 	}
120 	
121 	override @property bool empty() const { return false; }
122 }
123 
124 /**
125  * Extended master secret
126  */
127 class ExtendedMasterSecret : Extension
128 {
129 	static HandshakeExtensionType staticType() { return TLSEXT_EXTENDED_MASTER_SECRET; }
130 	
131 	override HandshakeExtensionType type() const { return staticType(); }
132 	
133 	override Vector!ubyte serialize() const
134 	{
135 		return Vector!ubyte();
136 	}
137 	
138 	override @property bool empty() const { return false; }
139 
140 	this(){}
141 
142 	this(ref TLSDataReader reader, ushort extension_size)
143 	{
144 		if (extension_size != 0)
145 			throw new DecodingError("Invalid extended_master_secret extension");
146 	}
147 }
148 
149 /**
150 * Signed Certificate Timestamp
151 */
152 class SignedCertificateTimestamp : Extension
153 {
154 public:
155 	static HandshakeExtensionType staticType() { return TLSEXT_SIGNED_CERT_TIMESTAMP; }
156 	
157 	override HandshakeExtensionType type() const { return staticType(); }
158 	
159 	override Vector!ubyte serialize() const
160 	{
161 		return Vector!ubyte();
162 	}
163 	
164 	override @property bool empty() const { return false; }
165 }
166 
167 /**
168 * Channel ID
169 */
170 class ChannelIDSupport : Extension
171 {
172 public:
173     static HandshakeExtensionType staticType() { return TLSEXT_CHANNEL_ID; }
174     
175     override HandshakeExtensionType type() const { return staticType(); }
176     
177     override Vector!ubyte serialize() const
178     {
179         return Vector!ubyte();
180     }
181 
182     this() {}
183 
184     this(ref TLSDataReader reader, ushort extension_size)
185     {
186         /*
187         * This is used by the server to confirm that it supports Channel ID
188         */
189     }
190         
191     override @property bool empty() const { return false; }
192     
193 }
194 /**
195 * Channel ID
196 */
197 class EncryptedChannelID : Extension
198 {
199     import botan.pubkey.pk_keys;
200     import botan.pubkey.algo.ecdsa;
201     import botan.math.bigint.bigint;
202 public:
203     static HandshakeExtensionType staticType() { return TLSEXT_CHANNEL_ID; }
204     
205     override HandshakeExtensionType type() const { return staticType(); }
206   
207 
208     this(PrivateKey pkey, SecureVector!ubyte hs_hash, SecureVector!ubyte orig_hs_hash) {
209         m_priv = pkey;
210         m_hs_hash = hs_hash.move();
211         m_orig_hs_hash = orig_hs_hash.move();
212     }
213     
214     this(ref TLSDataReader reader, ushort extension_size)
215     {
216         /*
217         * The (x,y) pubkey verifies the info and its hash will be saved and used as a machine identifier
218         */
219     }
220 
221     override Vector!ubyte serialize() const
222     {
223         Vector!ubyte buf;
224         static string magic = "TLS Channel ID signature\x00";
225         static string resume_magic = "Resumption\x00";
226         buf.reserve(32*4);
227         SecureVector!ubyte concat = cast(ubyte[])magic;
228 
229         if (m_orig_hs_hash.length > 0) {
230             concat.reserve(128);
231             concat ~= resume_magic;
232             concat ~= m_orig_hs_hash[];
233         }
234 
235         concat ~= m_hs_hash[];
236         import botan.libstate.lookup;
237         Unique!HashFunction sha256 = retrieveHash("SHA-256").clone();
238         sha256.update(concat[]);
239         SecureVector!ubyte channel_id_hash = sha256.finished();
240         ECDSAPrivateKey ecdsa_priv = ECDSAPrivateKey(m_priv);
241         const BigInt x = ecdsa_priv.publicPoint().getAffineX();
242         const BigInt y = ecdsa_priv.publicPoint().getAffineY();
243         import std.algorithm : max;
244         size_t part_size = max(x.bytes(), y.bytes());
245         enforce(part_size <= 32);
246         Vector!ubyte bits = Vector!ubyte(64);
247         
248         x.binaryEncode(bits.ptr);
249         y.binaryEncode(bits.ptr + 32);
250 
251         buf ~= bits[];
252         auto signer = scoped!ECDSASignatureOperation(ecdsa_priv);
253         import botan.rng.auto_rng : AutoSeededRNG;
254         auto rng = scoped!AutoSeededRNG();
255         auto sig = signer.sign(channel_id_hash.ptr, channel_id_hash.length, rng).unlock();
256         buf ~= sig;
257         return buf.move();
258     }
259 
260     override @property bool empty() const { return false; }
261 
262 private:
263     PrivateKey m_priv;
264     SecureVector!ubyte m_orig_hs_hash;
265     SecureVector!ubyte m_hs_hash;
266 }
267 
268 /**
269 * EC Point formats (RFC 4492) only uncompressed supported.
270 */
271 class SupportedPointFormats : Extension
272 {
273 public:
274 	static HandshakeExtensionType staticType() { return TLSEXT_EC_POINT_FORMATS; }
275 	
276 	override HandshakeExtensionType type() const { return staticType(); }
277 		
278 	override Vector!ubyte serialize() const
279 	{
280 		Vector!ubyte buf;
281 		buf.reserve(4);
282 		buf.pushBack(0x01); // 1 point format
283 
284 		//uncompressed
285 		buf.pushBack(0x00);
286 		
287 		return buf.move();
288 	}
289 	
290 	override @property bool empty() const { return false; }
291 }
292 
293 /**
294 * TLS Server Name Indicator extension (RFC 3546)
295 */
296 class ServerNameIndicator : Extension
297 {
298 public:
299     static HandshakeExtensionType staticType() { return TLSEXT_SERVER_NAME_INDICATION; }
300 
301     override HandshakeExtensionType type() const { return staticType(); }
302 
303     this(in string host_name) 
304     {
305 		//logDebug("SNI loaded with host name: ", host_name);
306         m_sni_host_name = host_name;
307     }
308 
309     this(ref TLSDataReader reader, ushort extension_size)
310     {
311         /*
312         * This is used by the server to confirm that it knew the name
313         */
314         if (extension_size == 0)
315             return;
316         
317         ushort name_bytes = reader.get_ushort();
318         
319         if (name_bytes + 2 != extension_size)
320             throw new DecodingError("Bad encoding of SNI extension");
321         
322         while (name_bytes)
323         {
324             ubyte name_type = reader.get_byte();
325             name_bytes--;
326             
327             if (name_type == 0) // DNS
328             {
329                 m_sni_host_name = reader.getString(2, 1, 65535);
330                 name_bytes -= (2 + m_sni_host_name.length);
331             }
332             else // some other unknown name type
333             {
334                 reader.discardNext(name_bytes);
335                 name_bytes = 0;
336             }
337         }
338     }
339 
340 	string hostName() const { return m_sni_host_name; }
341 
342     override Vector!ubyte serialize() const
343     {
344         Vector!ubyte buf;
345         
346         size_t name_len = m_sni_host_name.length;
347         
348         buf.pushBack(get_byte(0, cast(ushort) (name_len+3)));
349         buf.pushBack(get_byte(1, cast(ushort) (name_len+3)));
350         buf.pushBack(0); // DNS
351         
352         buf.pushBack(get_byte(0, cast(ushort) name_len));
353         buf.pushBack(get_byte(1, cast(ushort) name_len));
354         
355         buf ~= (cast(const(ubyte)*)m_sni_host_name.ptr)[0 .. m_sni_host_name.length];
356         
357         return buf.move();
358     }
359 
360     override @property bool empty() const { return m_sni_host_name == ""; }
361 private:
362     string m_sni_host_name;
363 }
364 
365 /**
366 * SRP identifier extension (RFC 5054)
367 */
368 class SRPIdentifier : Extension
369 {
370 public:
371     static HandshakeExtensionType staticType() { return TLSEXT_SRP_IDENTIFIER; }
372 
373     override HandshakeExtensionType type() const { return staticType(); }
374 
375     this(in string identifier) 
376     {
377         m_srp_identifier = identifier;
378     }
379 
380     this(ref TLSDataReader reader, ushort extension_size)
381     {
382         m_srp_identifier = reader.getString(1, 1, 255);
383         
384         if (m_srp_identifier.length + 1 != extension_size)
385             throw new DecodingError("Bad encoding for SRP identifier extension");
386     }
387 
388     this(ref TLSDataReader reader, ushort extension_size);
389 
390     string identifier() const { return m_srp_identifier; }
391 
392 
393     override Vector!ubyte serialize() const
394     {
395         Vector!ubyte buf;
396 
397         const(ubyte)* srp_bytes = cast(const(ubyte)*) m_srp_identifier.ptr;
398         
399         appendTlsLengthValue(buf, srp_bytes, m_srp_identifier.length, 1);
400         
401         return buf.move();
402     }
403 
404     override @property bool empty() const { return m_srp_identifier == ""; }
405 private:
406     string m_srp_identifier;
407 }
408 
409 /**
410 * Renegotiation Indication Extension (RFC 5746)
411 */
412 class RenegotiationExtension : Extension
413 {
414 public:
415     static HandshakeExtensionType staticType() { return TLSEXT_SAFE_RENEGOTIATION; }
416 
417     override HandshakeExtensionType type() const { return staticType(); }
418 
419     this() {}
420 
421     this(Vector!ubyte bits)
422     {
423         m_reneg_data = bits.move();
424     }
425 
426     this(ref TLSDataReader reader, ushort extension_size)
427     {
428         m_reneg_data = reader.getRange!ubyte(1, 0, 255);
429         
430         if (m_reneg_data.length + 1 != extension_size)
431             throw new DecodingError("Bad encoding for secure renegotiation extn");
432     }
433 
434     ref const(Vector!ubyte) renegotiationInfo() const { return m_reneg_data; }
435 
436     override Vector!ubyte serialize() const
437     {
438         Vector!ubyte buf;
439         appendTlsLengthValue(buf, m_reneg_data, 1);
440         return buf.move();
441     }
442 
443     override @property bool empty() const { return m_reneg_data.empty; }
444 
445 private:
446     Vector!ubyte m_reneg_data;
447 }
448 
449 /**
450 * Maximum Fragment Length Negotiation Extension (RFC 4366 sec 3.2)
451 */
452 class MaximumFragmentLength : Extension
453 {
454 public:
455     static HandshakeExtensionType staticType() { return TLSEXT_MAX_FRAGMENT_LENGTH; }
456 
457     override HandshakeExtensionType type() const { return staticType(); }
458 
459     override @property bool empty() const { return false; }
460 
461     size_t fragmentSize() const { return m_max_fragment; }
462 
463     override Vector!ubyte serialize() const
464     {
465         static ubyte[size_t] fragment_to_code;
466         if (fragment_to_code.length == 0)
467             fragment_to_code = [ 512: 1, 1024: 2, 2048: 3, 4096: 4 ];
468         
469         auto i = fragment_to_code.get(m_max_fragment, 0);
470         
471         if (i == 0)
472             throw new InvalidArgument("Bad setting " ~ to!string(m_max_fragment) ~ " for maximum fragment size");
473         
474         return Vector!ubyte([i]);
475     }
476 
477     /**
478     * Params:
479     *  max_fragment = specifies what maximum fragment size to
480     *          advertise. Currently must be one of 512, 1024, 2048, or
481     *          4096.
482     */
483     this(size_t max_fragment) 
484     {
485         m_max_fragment = max_fragment;
486     }
487 
488     this(ref TLSDataReader reader, ushort extension_size)
489     {
490         __gshared immutable size_t[] code_to_fragment = [ 0, 512, 1024, 2048, 4096 ];
491         if (extension_size != 1)
492             throw new DecodingError("Bad size for maximum fragment extension");
493         ubyte val = reader.get_byte();
494 
495         if (val < code_to_fragment.length) {
496 
497             auto i = code_to_fragment[val];
498             
499             m_max_fragment = i;
500         }
501         else
502             throw new TLSException(TLSAlert.ILLEGAL_PARAMETER, "Bad value in maximum fragment extension");
503 
504     }
505 
506 private:
507     size_t m_max_fragment;
508 }
509 
510 /**
511 * ALPN (RFC 7301)
512 */
513 class ApplicationLayerProtocolNotification : Extension
514 {
515 public:
516     static HandshakeExtensionType staticType() { return TLSEXT_ALPN; }
517 
518     override HandshakeExtensionType type() const { return staticType(); }
519 
520     ref const(Vector!string) protocols() const { return m_protocols; }
521 
522     /**
523     * Single protocol, used by server
524     */
525     this() {}
526 
527     /**
528     * List of protocols, used by client
529     */
530     this(Vector!string protocols) 
531     {
532         m_protocols = protocols.move(); 
533     }
534 
535     this(string protocol) {
536         m_protocols.length = 1;
537         m_protocols[0] = protocol;
538     }
539 
540     this(ref TLSDataReader reader, ushort extension_size)
541     {
542         if (extension_size == 0)
543             return; // empty extension
544         
545         const ushort name_bytes = reader.get_ushort();
546         
547         size_t bytes_remaining = extension_size - 2;
548 
549         if (name_bytes != bytes_remaining)
550             throw new DecodingError("Bad encoding of ALPN extension, bad length field");
551 
552         while (bytes_remaining)
553         {
554             const string p = reader.getString(1, 0, 255);
555             
556             if (bytes_remaining < p.length + 1)
557                 throw new DecodingError("Bad encoding of ALPN, length field too long");
558             
559             bytes_remaining -= (p.length + 1);
560 			//logDebug("Got protocol: ", p); 
561             m_protocols.pushBack(p);
562         }
563     }
564 
565     ref string singleProtocol() const
566     {
567         if (m_protocols.length != 1)
568             throw new TLSException(TLSAlert.HANDSHAKE_FAILURE, "Server sent " ~ m_protocols.length.to!string ~ " protocols in ALPN extension response");
569         
570         return m_protocols[0];
571     }
572 
573     override Vector!ubyte serialize() const
574     {
575         Vector!ubyte buf = Vector!ubyte(2);
576 
577         foreach (ref p; m_protocols)
578         {
579             if (p.length >= 256)
580                 throw new TLSException(TLSAlert.INTERNAL_ERROR, "ALPN name too long");
581             if (p != "")
582                 appendTlsLengthValue(buf, cast(const(ubyte)*) p.ptr, p.length, 1);
583         }
584         ushort len = cast(ushort)( buf.length - 2 );
585         buf[0] = get_byte!ushort(0, len);
586         buf[1] = get_byte!ushort(1, len);
587 
588         return buf.move();
589     }
590 
591     override @property bool empty() const { return m_protocols.empty; }
592 private:
593     Vector!string m_protocols;
594 }
595 
596 /**
597 * TLSSession Ticket Extension (RFC 5077)
598 */
599 class SessionTicket : Extension
600 {
601 public:
602     static HandshakeExtensionType staticType() { return TLSEXT_SESSION_TICKET; }
603 
604     override HandshakeExtensionType type() const { return staticType(); }
605 
606     /**
607     * Returns: contents of the session ticket
608     */
609     ref const(Vector!ubyte) contents() const { return m_ticket; }
610 
611     /**
612     * Create empty extension, used by both client and server
613     */
614     this() {}
615 
616     /**
617     * Extension with ticket, used by client
618     */
619     this(Vector!ubyte session_ticket)
620     {
621         m_ticket = session_ticket.move();
622     }
623 
624     /**
625     * Deserialize a session ticket
626     */
627     this(ref TLSDataReader reader, ushort extension_size)
628     {
629         m_ticket = reader.getElem!(ubyte, Vector!ubyte)(extension_size);
630     }
631 
632     override Vector!ubyte serialize() const { return m_ticket.dup; }
633 
634     override @property bool empty() const { return false; }
635 private:
636     Vector!ubyte m_ticket;
637 }
638 
639 /**
640 * Supported Elliptic Curves Extension (RFC 4492)
641 */
642 class SupportedEllipticCurves : Extension
643 {
644 public:
645     static HandshakeExtensionType staticType() { return TLSEXT_USABLE_ELLIPTIC_CURVES; }
646 
647     override HandshakeExtensionType type() const { return staticType(); }
648 
649     static string curveIdToName(ushort id)
650     {
651         switch(id)
652         {
653 			/*
654 			 * unsupported 
655 			 */
656 			case 1:
657 				return "sect163k1";
658 			case 2:
659 				return "sect163r1";
660 			case 3:
661 				return "sect163r2";
662 			case 4:
663 				return "sect193r1";
664 			case 5:
665 				return "sect193r2";
666 			case 6:
667 				return "sect233k1";
668 			case 7:
669 				return "sect233r1";
670 			case 8:
671 				return "sect239k1";
672 			case 9:
673 				return "sect283k1";
674 			case 10:
675 				return "sect283r1";
676 			case 11:
677 				return "sect409k1";
678 			case 12:
679 				return "sect409r1";
680 			case 13:
681 				return "sect571k1";
682 			case 14:
683 				return "sect571r1";
684 			/*
685 			 * supported
686 			 */
687             case 15:
688                 return "secp160k1";
689             case 16:
690                 return "secp160r1";
691             case 17:
692                 return "secp160r2";
693             case 18:
694                 return "secp192k1";
695             case 19:
696                 return "secp192r1";
697             case 20:
698                 return "secp224k1";
699             case 21:
700                 return "secp224r1";
701             case 22:
702                 return "secp256k1";
703             case 23:
704                 return "secp256r1";
705             case 24:
706                 return "secp384r1";
707             case 25:
708                 return "secp521r1";
709             case 26:
710                 return "brainpool256r1";
711             case 27:
712                 return "brainpool384r1";
713             case 28:
714                 return "brainpool512r1";
715 			case 29:
716 				return "x25519";
717 			
718             default:
719                 return id.to!string; // something we don't know or support
720         }
721     }
722 
723     static ushort nameToCurveId(in string name)
724     {
725 		/*
726 		 * unsupported 
727 		 */
728 		if (name == "sect163k1")
729 			return 1;
730 		if (name == "sect163r1")
731 			return 2;
732 		if (name == "sect163r2")
733 			return 3;
734 		if (name == "sect193r1")
735 			return 4;
736 		if (name == "sect193r2")
737 			return 5;
738 		if (name == "sect233k1")
739 			return 6;
740 		if (name == "sect233r1")
741 			return 7;
742 		if (name == "sect239k1")
743 			return 8;
744 		if (name == "sect283k1")
745 			return 9;
746 		if (name == "sect283r1")
747 			return 10;
748 		if (name == "sect409k1")
749 			return 11;
750 		if (name == "sect409r1")
751 			return 12;
752 		if (name == "sect571k1")
753 			return 13;
754 		if (name == "sect571r1")
755 			return 14;
756 
757 		/*
758 		 * supported
759 		 */
760         if (name == "secp160k1")
761             return 15;
762         if (name == "secp160r1")
763             return 16;
764         if (name == "secp160r2")
765             return 17;
766         if (name == "secp192k1")
767             return 18;
768         if (name == "secp192r1")
769             return 19;
770         if (name == "secp224k1")
771             return 20;
772         if (name == "secp224r1")
773             return 21;
774         if (name == "secp256k1")
775             return 22;
776         if (name == "secp256r1")
777             return 23;
778         if (name == "secp384r1")
779             return 24;
780         if (name == "secp521r1")
781             return 25;
782         if (name == "brainpool256r1")
783             return 26;
784         if (name == "brainpool384r1")
785             return 27;
786         if (name == "brainpool512r1")
787             return 28;
788 		if (name == "x25519")
789 			return 29;
790         
791         throw new InvalidArgument("name_to_curve_id unknown name " ~ name);
792     }
793 
794     ref const(Vector!string) curves() const { return m_curves; }
795 
796     override Vector!ubyte serialize() const
797     {
798 		Vector!ubyte buf;
799 		buf.reserve(m_curves.length * 2 + 2);
800 		buf.length = 2;
801         
802         for (size_t i = 0; i != m_curves.length; ++i)
803         {
804             const ushort id = nameToCurveId(m_curves[i]);
805 			if (id > 0) {
806 	            buf.pushBack(get_byte(0, id));
807 	            buf.pushBack(get_byte(1, id));
808 			}
809         }
810         
811         buf[0] = get_byte(0, cast(ushort) (buf.length-2));
812         buf[1] = get_byte(1, cast(ushort) (buf.length-2));
813         
814         return buf.move();
815     }
816 
817     this(Vector!string curves) 
818     {
819         m_curves = curves.move();
820     }
821 
822     this(ref TLSDataReader reader, ushort extension_size)
823     {
824         ushort len = reader.get_ushort();
825 		m_curves.reserve(cast(size_t)len);
826 		//logDebug("Got elliptic curves len: ", len, " ext size: ", extension_size);
827         if (len + 2 != extension_size)
828             throw new DecodingError("Inconsistent length field in elliptic curve list");
829         
830         if (len % 2 == 1)
831             throw new DecodingError("Elliptic curve list of strange size");
832         
833         len /= 2;
834         
835         foreach (size_t i; 0 .. len)
836         {
837             const ushort id = reader.get_ushort();
838             const string name = curveIdToName(id);
839 			//logDebug("Got curve name: ", name);
840             
841             if (name != "")
842                 m_curves.pushBack(name);
843         }
844     }
845 
846     override @property bool empty() const { return m_curves.empty; }
847 private:
848     Vector!string m_curves;
849 }
850 
851 /**
852 * Signature Algorithms Extension for TLS 1.2 (RFC 5246)
853 */
854 class SignatureAlgorithms : Extension
855 {
856 public:
857     static HandshakeExtensionType staticType() { return TLSEXT_SIGNATURE_ALGORITHMS; }
858 
859     override HandshakeExtensionType type() const { return staticType(); }
860 
861     static string hashAlgoName(ubyte code)
862     {
863         switch(code)
864         {
865             case 1:
866                 return "MD5";
867                 // code 1 is MD5 - ignore it
868                 
869             case 2:
870                 return "SHA-1";
871             case 3:
872                 return "SHA-224";
873             case 4:
874                 return "SHA-256";
875             case 5:
876                 return "SHA-384";
877             case 6:
878                 return "SHA-512";
879             default:
880                 return "";
881         }
882     }
883 
884     static ubyte hashAlgoCode(in string name)
885     {
886         if (name == "MD5")
887             return 1;
888         
889         if (name == "SHA-1")
890             return 2;
891         
892         if (name == "SHA-224")
893             return 3;
894         
895         if (name == "SHA-256")
896             return 4;
897         
898         if (name == "SHA-384")
899             return 5;
900         
901         if (name == "SHA-512")
902             return 6;
903         
904         throw new InternalError("Unknown hash ID " ~ name ~ " for signature_algorithms");
905     }
906 
907     static string sigAlgoName(ubyte code)
908     {
909         switch(code)
910         {
911             case 1:
912                 return "RSA";
913             case 2:
914                 return "DSA";
915             case 3:
916                 return "ECDSA";
917             default:
918                 return "";
919         }
920     }
921 
922     static ubyte sigAlgoCode(in string name)
923     {
924         if (name == "RSA")
925             return 1;
926         
927         if (name == "DSA")
928             return 2;
929         
930         if (name == "ECDSA")
931             return 3;
932         
933         throw new InternalError("Unknown sig ID " ~ name ~ " for signature_algorithms");
934     }
935 
936     ref const(Vector!( Pair!(string, string)  )) supportedSignatureAlgorthms() const
937     {
938         return m_supported_algos;
939     }
940 
941     override Vector!ubyte serialize() const
942     {
943         Vector!ubyte buf = Vector!ubyte(2);
944         
945         for (size_t i = 0; i != m_supported_algos.length; ++i)
946         {
947             try
948             {
949                 const ubyte hash_code = hashAlgoCode(m_supported_algos[i].first);
950                 const ubyte sig_code = sigAlgoCode(m_supported_algos[i].second);
951                 
952                 buf.pushBack(hash_code);
953                 buf.pushBack(sig_code);
954             }
955             catch (Exception)
956             {}
957         }
958         
959         buf[0] = get_byte(0, cast(ushort) (buf.length-2));
960         buf[1] = get_byte(1, cast(ushort) (buf.length-2));
961         
962         return buf.move();
963     }
964 
965     override @property bool empty() const { return false; }
966 
967     this()(auto const ref Vector!string hashes, auto const ref Vector!string sigs)
968     {
969         for (size_t i = 0; i != hashes.length; ++i)
970             for (size_t j = 0; j != sigs.length; ++j)
971                 m_supported_algos.pushBack(makePair(hashes[i], sigs[j]));
972     }
973     
974     this(ref TLSDataReader reader,
975          ushort extension_size)
976     {
977         ushort len = reader.get_ushort();
978         
979         if (len + 2 != extension_size)
980             throw new DecodingError("Bad encoding on signature algorithms extension");
981         
982         while (len)
983         {
984             const string hash_code = hashAlgoName(reader.get_byte());
985             const string sig_code = sigAlgoName(reader.get_byte());
986             
987             len -= 2;
988             
989             // If not something we know, ignore it completely
990             if (hash_code == "" || sig_code == "")
991                 continue;
992 			//logDebug("Got signature: ", hash_code, " => ",sig_code);
993             m_supported_algos.pushBack(makePair(hash_code, sig_code));
994         }
995     }
996 
997     this(Vector!( Pair!(string, string)  ) algos) 
998     {
999         m_supported_algos = algos.move();
1000     }
1001 
1002 private:
1003     Vector!( Pair!(string, string) ) m_supported_algos;
1004 }
1005 
1006 /**
1007 * Heartbeat Extension (RFC 6520)
1008 */
1009 class HeartbeatSupportIndicator : Extension
1010 {
1011 public:
1012     static HandshakeExtensionType staticType() { return TLSEXT_HEARTBEAT_SUPPORT; }
1013 
1014     override HandshakeExtensionType type() const { return staticType(); }
1015 
1016     bool peerAllowedToSend() const { return m_peer_allowed_to_send; }
1017 
1018     override Vector!ubyte serialize() const
1019     {
1020         Vector!ubyte heartbeat = Vector!ubyte(1);
1021         heartbeat[0] = (m_peer_allowed_to_send ? 1 : 2);
1022         return heartbeat.move();
1023     }
1024 
1025     override @property bool empty() const { return false; }
1026 
1027     this(bool peer_allowed_to_send) 
1028     {
1029         m_peer_allowed_to_send = peer_allowed_to_send; 
1030     }
1031 
1032     this(ref TLSDataReader reader, ushort extension_size)
1033     {
1034         if (extension_size != 1)
1035             throw new DecodingError("Strange size for heartbeat extension");
1036         
1037         const ubyte code = reader.get_byte();
1038         
1039         if (code != 1 && code != 2)
1040             throw new TLSException(TLSAlert.ILLEGAL_PARAMETER, "Unknown heartbeat code " ~ to!string(code));
1041         
1042         m_peer_allowed_to_send = (code == 1);
1043     }
1044 
1045 private:
1046     bool m_peer_allowed_to_send;
1047 }
1048 
1049 /**
1050 * Represents a block of extensions in a hello message
1051 */
1052 struct TLSExtensions
1053 {
1054 public:
1055     Vector!HandshakeExtensionType extensionTypes() const
1056     {
1057 		return m_extensions.types.dup;
1058     }
1059 
1060 
1061     T get(T)() const
1062     {
1063         HandshakeExtensionType type = T.staticType();
1064 
1065         return cast(T)m_extensions.get(type, T.init);
1066     }
1067 
1068     void add(Extension extn)
1069     {
1070         assert(extn);
1071 
1072         auto val = m_extensions.get(extn.type(), null);
1073         if (val) {
1074 			m_extensions.remove(extn.type());
1075 		}
1076         m_extensions.add(extn.type(), extn);
1077     }
1078 
1079     Vector!ubyte serialize() const
1080     {
1081         Vector!ubyte buf = Vector!ubyte(2); // 2 bytes for length field
1082         
1083         foreach (const ref Extension extn; m_extensions.extensions[])
1084         {
1085             if (extn.empty)
1086                 continue;
1087             
1088             const ushort extn_code = extn.type();
1089             const Vector!ubyte extn_val = extn.serialize();
1090             
1091             buf.pushBack(get_byte(0, extn_code));
1092             buf.pushBack(get_byte(1, extn_code));
1093             
1094             buf.pushBack(get_byte(0, cast(ushort) extn_val.length));
1095             buf.pushBack(get_byte(1, cast(ushort) extn_val.length));
1096             
1097             buf ~= extn_val[];
1098         }
1099         
1100         const ushort extn_size = cast(ushort) (buf.length - 2);
1101         
1102         buf[0] = get_byte(0, extn_size);
1103         buf[1] = get_byte(1, extn_size);
1104         
1105         // avoid sending a completely empty extensions block
1106         if (buf.length == 2)
1107             return Vector!ubyte();
1108         
1109         return buf.move();
1110     }
1111 
1112     void deserialize(ref TLSDataReader reader)
1113     {
1114         if (reader.hasRemaining())
1115         {
1116             const ushort all_extn_size = reader.get_ushort();
1117             
1118             if (reader.remainingBytes() != all_extn_size)
1119                 throw new DecodingError("Bad extension size");
1120             
1121             while (reader.hasRemaining())
1122             {
1123                 const ushort extension_code = reader.get_ushort();
1124                 const ushort extension_size = reader.get_ushort();
1125 				//logDebug("Got extension: ", extension_code); 
1126                 Extension extn = makeExtension(reader, extension_code, extension_size);
1127                 
1128                 if (extn)
1129                     this.add(extn);
1130                 else // unknown/unhandled extension
1131                     reader.discardNext(extension_size);
1132             }
1133         }
1134     }
1135 
1136 	void reserve(size_t n) { m_extensions.extensions.reserve(n); }
1137 
1138     this(ref TLSDataReader reader) { deserialize(reader); }
1139 
1140 private:
1141 	HandshakeExtensions m_extensions;
1142 }
1143 
1144 private struct HandshakeExtensions {
1145 private:
1146 	Vector!HandshakeExtensionType types;
1147 	Vector!Extension extensions;
1148 
1149 	Extension get(HandshakeExtensionType type, Extension dflt) const {
1150 		size_t i;
1151 		foreach (HandshakeExtensionType t; types[]) {
1152 			if (t == type)
1153 				return cast() extensions[i];
1154 			i++;
1155 		}
1156 		return dflt;
1157 	}
1158 
1159 	void add(HandshakeExtensionType type, Extension ext)
1160 	{
1161 		types ~= type;
1162 		extensions ~= ext;
1163 	}
1164 
1165 	void remove(HandshakeExtensionType type) {
1166 		size_t i;
1167 		foreach (HandshakeExtensionType t; types[]) {
1168 			if (t == type) {
1169 				Vector!HandshakeExtensionType tmp_types;
1170 				tmp_types.reserve(types.length - 1);
1171 				tmp_types ~= types[0 .. i];
1172 				Vector!Extension tmp_extensions;
1173 				tmp_extensions.reserve(extensions.length - 1);
1174 				tmp_extensions ~= extensions[0 .. i];
1175 				if (i != types.length - 1) {
1176 					tmp_types ~= types[i+1 .. types.length];
1177 					tmp_extensions ~= extensions[i+1 .. extensions.length];
1178 				}
1179 				types[] = tmp_types[];
1180 				extensions[] = tmp_extensions[];
1181 				return;
1182 			}
1183 			i++;
1184 		}
1185 		logError("Could not find a TLS extension we wanted to remove...");
1186 	}
1187 
1188 }
1189 
1190 private:
1191 
1192 Extension makeExtension(ref TLSDataReader reader, ushort code, ushort size)
1193 {
1194     switch(code)
1195     {
1196         case TLSEXT_SERVER_NAME_INDICATION:
1197             return new ServerNameIndicator(reader, size);
1198             
1199 		case TLSEXT_EXTENDED_MASTER_SECRET:
1200 			return new ExtendedMasterSecret(reader, size);
1201 
1202         case TLSEXT_MAX_FRAGMENT_LENGTH:
1203             return new MaximumFragmentLength(reader, size);
1204             
1205         case TLSEXT_SRP_IDENTIFIER:
1206             return new SRPIdentifier(reader, size);
1207             
1208         case TLSEXT_USABLE_ELLIPTIC_CURVES:
1209             return new SupportedEllipticCurves(reader, size);
1210             
1211         case TLSEXT_SAFE_RENEGOTIATION:
1212             return new RenegotiationExtension(reader, size);
1213             
1214         case TLSEXT_SIGNATURE_ALGORITHMS:
1215             return new SignatureAlgorithms(reader, size);
1216             
1217         case TLSEXT_ALPN:
1218             return new ApplicationLayerProtocolNotification(reader, size);
1219             
1220         case TLSEXT_HEARTBEAT_SUPPORT:
1221             return new HeartbeatSupportIndicator(reader, size);
1222             
1223         case TLSEXT_SESSION_TICKET:
1224             return new SessionTicket(reader, size);
1225            
1226 		case TLSEXT_CHANNEL_ID:
1227 			return new ChannelIDSupport(reader, size);
1228 
1229         default:
1230             return null; // not known
1231     }
1232 }