]> granicus.if.org Git - curl/commitdiff
ssl: add server cert's "sha256//" hash to verbose
authorDaniel Hwang <danielleehwang@gmail.com>
Sat, 12 Sep 2015 21:35:12 +0000 (14:35 -0700)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 19 Sep 2015 21:17:39 +0000 (23:17 +0200)
Add a "pinnedpubkey" section to the "Server Certificate" verbose

Bug: https://github.com/bagder/curl/issues/410
Reported-by: W. Mark Kubacki
Closes #430
Closes #410

lib/vtls/cyassl.c
lib/vtls/gskit.c
lib/vtls/gtls.c
lib/vtls/nss.c
lib/vtls/openssl.c
lib/vtls/vtls.c
lib/vtls/vtls.h

index 3ded7f11d5828716785c7b4c436f580fcef3e938..052996e14637a3c4dba061b912a6b44f4e19814b 100644 (file)
@@ -434,7 +434,8 @@ cyassl_connect_step2(struct connectdata *conn,
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
     }
 
-    result = Curl_pin_peer_pubkey(data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+    result = Curl_pin_peer_pubkey(data,
+                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
                                   (const unsigned char *)pubkey->header,
                                   (size_t)(pubkey->end - pubkey->header));
     if(result) {
index d884bd4c4d1a426ffca4a6b378a931e47a8ba3b9..a5b7ea2033e9e64c83983ea4f44b595d006f0390 100644 (file)
@@ -874,7 +874,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
     Curl_parseX509(&x509, cert, certend);
     p = &x509.subjectPublicKeyInfo;
-    result = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header);
+    result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
     if(result) {
       failf(data, "SSL: public key does not match pinned public key!");
       return result;
index c54dfc1d2e158be915d4e926c9cc9bf2319ec05d..5f7041a3069cb606b4e773c7f3dfa19f557650c2 100644 (file)
@@ -724,7 +724,8 @@ gtls_connect_step1(struct connectdata *conn,
   return CURLE_OK;
 }
 
-static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,
+static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
+                                    gnutls_x509_crt_t cert,
                                     const char *pinnedpubkey)
 {
   /* Scratch */
@@ -769,7 +770,7 @@ static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,
     /* End Gyrations */
 
     /* The one good exit point */
-    result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
+    result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
   } while(0);
 
   if(NULL != key)
@@ -1152,7 +1153,7 @@ gtls_connect_step3(struct connectdata *conn,
 
   ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   if(ptr) {
-    result = pkp_pin_peer_pubkey(x509_cert, ptr);
+    result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
     if(result != CURLE_OK) {
       failf(data, "SSL: public key does not match pinned public key!");
       gnutls_x509_crt_deinit(x509_cert);
index 09214a52b6cf7d156914654189b391e0ea0685f3..c8bd0cef6077a1c7c4df3279b1f8722efa28c853 100644 (file)
@@ -973,8 +973,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
       SECItem *cert_der = PK11_DEREncodePublicKey(pubkey);
       if(cert_der) {
         /* compare the public key with the pinned public key */
-        result = Curl_pin_peer_pubkey(pinnedpubkey,
-                                      cert_der->data,
+        result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data,
                                       cert_der->len);
         SECITEM_FreeItem(cert_der, PR_TRUE);
       }
index a5103cd42558b4a01e9272bace35409702f7e459..998ab2bacd67a5a6749c8d2929b7656757a4f6e6 100644 (file)
@@ -2420,7 +2420,8 @@ static CURLcode get_cert_chain(struct connectdata *conn,
  * Heavily modified from:
  * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
  */
-static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
+static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data, X509* cert,
+                                    const char *pinnedpubkey)
 {
   /* Scratch */
   int len1 = 0, len2 = 0;
@@ -2465,7 +2466,7 @@ static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
     /* End Gyrations */
 
     /* The one good exit point */
-    result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
+    result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
   } while(0);
 
   /* https://www.openssl.org/docs/crypto/buffer.html */
@@ -2629,7 +2630,7 @@ static CURLcode servercert(struct connectdata *conn,
 
   ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   if(!result && ptr) {
-    result = pkp_pin_peer_pubkey(connssl->server_cert, ptr);
+    result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
     if(result)
       failf(data, "SSL: public key does not match pinned public key!");
   }
index 01bbc613095d1ba806069881387b7fbef2994617..692ff5c9eba78d357fc2e3f67b59a33f50c6df31 100644 (file)
@@ -765,7 +765,8 @@ static CURLcode pubkey_pem_to_der(const char *pem,
  * Generic pinned public key check.
  */
 
-CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
+CURLcode Curl_pin_peer_pubkey(struct SessionHandle *data,
+                              const char *pinnedpubkey,
                               const unsigned char *pubkey, size_t pubkeylen)
 {
   FILE *fp;
@@ -775,9 +776,10 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
   CURLcode pem_read;
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
 #ifdef curlssl_sha256sum
-  size_t pinkeylen;
-  char *pinkeycopy, *begin_pos, *end_pos;
-  unsigned char *sha256sumdigest = NULL, *expectedsha256sumdigest = NULL;
+  CURLcode encode;
+  size_t encodedlen, pinkeylen;
+  char *encoded, *pinkeycopy, *begin_pos, *end_pos;
+  unsigned char *sha256sumdigest = NULL;
 #endif
 
   /* if a path wasn't specified, don't pin */
@@ -796,11 +798,21 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
     curlssl_sha256sum(pubkey, pubkeylen,
                       sha256sumdigest, SHA256_DIGEST_LENGTH);
 
+    encode = Curl_base64_encode(data, (char *)sha256sumdigest,
+                                SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
+    Curl_safefree(sha256sumdigest);
+
+    if(!encode) {
+      infof(data, "\t pinnedpubkey: sha256//%s\n", encoded);
+    }
+    else
+      return encode;
+
     /* it starts with sha256//, copy so we can modify it */
     pinkeylen = strlen(pinnedpubkey) + 1;
     pinkeycopy = malloc(pinkeylen);
     if(!pinkeycopy) {
-      Curl_safefree(sha256sumdigest);
+      Curl_safefree(encoded);
       return CURLE_OUT_OF_MEMORY;
     }
     memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
@@ -815,20 +827,11 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
       if(end_pos)
         end_pos[0] = '\0';
 
-      /* decode base64 pinnedpubkey, 8 is length of "sha256//" */
-      pem_read = Curl_base64_decode(begin_pos + 8,
-                                    &expectedsha256sumdigest, &size);
-      /* if not valid base64, don't bother comparing or freeing */
-      if(!pem_read) {
-        /* compare sha256 digests directly */
-        if(SHA256_DIGEST_LENGTH == size &&
-           !memcmp(sha256sumdigest, expectedsha256sumdigest,
-                   SHA256_DIGEST_LENGTH)) {
-          result = CURLE_OK;
-          Curl_safefree(expectedsha256sumdigest);
-          break;
-        }
-        Curl_safefree(expectedsha256sumdigest);
+      /* compare base64 sha256 digests, 8 is the length of "sha256//" */
+      if(encodedlen == strlen(begin_pos + 8) &&
+         !memcmp(encoded, begin_pos + 8, encodedlen)) {
+        result = CURLE_OK;
+        break;
       }
 
       /*
@@ -840,7 +843,7 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
         begin_pos = strstr(end_pos, "sha256//");
       }
     } while(end_pos && begin_pos);
-    Curl_safefree(sha256sumdigest);
+    Curl_safefree(encoded);
     Curl_safefree(pinkeycopy);
     return result;
   }
index 2349e5b93b53e44df414be893c1ec60999a4e10e..d6224903a663c1dd6c4c3f5491da78c68557bbd9 100644 (file)
@@ -117,7 +117,8 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                          unsigned char *md5sum, /* output */
                          size_t md5len);
 /* Check pinned public key. */
-CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
+CURLcode Curl_pin_peer_pubkey(struct SessionHandle *data,
+                              const char *pinnedpubkey,
                               const unsigned char *pubkey, size_t pubkeylen);
 
 bool Curl_ssl_cert_status_request(void);