Log TLS signature_algorithms extension values.
authorKyle Nekritz <knekritz@fb.com>
Fri, 28 Aug 2015 20:35:05 +0000 (13:35 -0700)
committerSara Golemon <sgolemon@fb.com>
Mon, 31 Aug 2015 21:21:10 +0000 (14:21 -0700)
Summary: Provide a folly interface for logging the client supported TLS signature algorithms.

Reviewed By: @siyengar

Differential Revision: D2374528

folly/io/async/AsyncSSLSocket.cpp
folly/io/async/AsyncSSLSocket.h

index e3df3950007603e237f7db3c0ef945538dc739bd..c6dd25b519a3f93b2ec4d2b51ce5d3d2ef55889a 100644 (file)
@@ -1606,13 +1606,30 @@ AsyncSSLSocket::clientHelloParsingCallback(int written, int version,
     if (cursor.totalLength() > 0) {
       uint16_t extensionsLength = cursor.readBE<uint16_t>();
       while (extensionsLength) {
+        TLSExtension extensionType = static_cast<TLSExtension>(
+            cursor.readBE<uint16_t>());
         sock->clientHelloInfo_->
-          clientHelloExtensions_.push_back(cursor.readBE<uint16_t>());
+          clientHelloExtensions_.push_back(extensionType);
         extensionsLength -= 2;
         uint16_t extensionDataLength = cursor.readBE<uint16_t>();
         extensionsLength -= 2;
-        cursor.skip(extensionDataLength);
-        extensionsLength -= extensionDataLength;
+
+        if (extensionType == TLSExtension::SIGNATURE_ALGORITHMS) {
+          cursor.skip(2);
+          extensionDataLength -= 2;
+          while (extensionDataLength) {
+            HashAlgorithm hashAlg = static_cast<HashAlgorithm>(
+                cursor.readBE<uint8_t>());
+            SignatureAlgorithm sigAlg = static_cast<SignatureAlgorithm>(
+                cursor.readBE<uint8_t>());
+            extensionDataLength -= 2;
+            sock->clientHelloInfo_->
+              clientHelloSigAlgs_.emplace_back(hashAlg, sigAlg);
+          }
+        } else {
+          cursor.skip(extensionDataLength);
+          extensionsLength -= extensionDataLength;
+        }
       }
     }
   } catch (std::out_of_range& e) {
index 227e5ea77cc6cd6964a6188f27db9bdc62928da8..31f8b6c47cff8df1e3c968b58ede95ea821df97f 100644 (file)
@@ -601,6 +601,27 @@ class AsyncSSLSocket : public virtual AsyncSocket {
     return folly::join(":", clientHelloInfo_->clientHelloExtensions_);
   }
 
+  std::string getSSLClientSigAlgs() {
+    if (!parseClientHello_) {
+      return "";
+    }
+
+    std::string sigAlgs;
+    sigAlgs.reserve(clientHelloInfo_->clientHelloSigAlgs_.size() * 4);
+    for (size_t i = 0; i < clientHelloInfo_->clientHelloSigAlgs_.size(); i++) {
+      if (i) {
+        sigAlgs.push_back(':');
+      }
+      sigAlgs.append(folly::to<std::string>(
+          clientHelloInfo_->clientHelloSigAlgs_[i].first));
+      sigAlgs.push_back(',');
+      sigAlgs.append(folly::to<std::string>(
+          clientHelloInfo_->clientHelloSigAlgs_[i].second));
+    }
+
+    return sigAlgs;
+  }
+
   /**
    * Get the list of shared ciphers between the server and the client.
    * Works well for only SSLv2, not so good for SSLv3 or TLSv1.
@@ -634,13 +655,64 @@ class AsyncSSLSocket : public virtual AsyncSocket {
   static void clientHelloParsingCallback(int write_p, int version,
       int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 
+  // http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
+  enum class TLSExtension: uint16_t {
+    SERVER_NAME = 0,
+    MAX_FRAGMENT_LENGTH = 1,
+    CLIENT_CERTIFICATE_URL = 2,
+    TRUSTED_CA_KEYS = 3,
+    TRUNCATED_HMAC = 4,
+    STATUS_REQUEST = 5,
+    USER_MAPPING = 6,
+    CLIENT_AUTHZ = 7,
+    SERVER_AUTHZ = 8,
+    CERT_TYPE = 9,
+    SUPPORTED_GROUPS = 10,
+    EC_POINT_FORMATS = 11,
+    SRP = 12,
+    SIGNATURE_ALGORITHMS = 13,
+    USE_SRTP = 14,
+    HEARTBEAT = 15,
+    APPLICATION_LAYER_PROTOCOL_NEGOTIATION = 16,
+    STATUS_REQUEST_V2 = 17,
+    SIGNED_CERTIFICATE_TIMESTAMP = 18,
+    CLIENT_CERTIFICATE_TYPE = 19,
+    SERVER_CERTIFICATE_TYPE = 20,
+    PADDING = 21,
+    ENCRYPT_THEN_MAC = 22,
+    EXTENDED_MASTER_SECRET = 23,
+    SESSION_TICKET = 35,
+    RENEGOTIATION_INFO = 65281
+  };
+
+  // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18
+  enum class HashAlgorithm: uint8_t {
+    NONE = 0,
+    MD5 = 1,
+    SHA1 = 2,
+    SHA224 = 3,
+    SHA256 = 4,
+    SHA384 = 5,
+    SHA512 = 6
+  };
+
+  // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
+  enum class SignatureAlgorithm: uint8_t {
+    ANONYMOUS = 0,
+    RSA = 1,
+    DSA = 2,
+    ECDSA = 3
+  };
+
   struct ClientHelloInfo {
     folly::IOBufQueue clientHelloBuf_;
     uint8_t clientHelloMajorVersion_;
     uint8_t clientHelloMinorVersion_;
     std::vector<uint16_t> clientHelloCipherSuites_;
     std::vector<uint8_t> clientHelloCompressionMethods_;
-    std::vector<uint16_t> clientHelloExtensions_;
+    std::vector<TLSExtension> clientHelloExtensions_;
+    std::vector<
+      std::pair<HashAlgorithm, SignatureAlgorithm>> clientHelloSigAlgs_;
   };
 
   // For unit-tests