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