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 }