From 9f37e2bc94b485e7eff0c49ccc3ec68ca5101dd3 Mon Sep 17 00:00:00 2001
From: moparisthebest <admin@moparisthebest.com>
Date: Tue, 30 Jun 2015 20:39:49 -0400
Subject: [PATCH 2/2] Add new Curl_base64_decode_nomalloc function

---
 lib/base64.c      | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/curl_base64.h |  2 ++
 lib/vtls/vtls.c   | 30 ++++++++++++----------
 3 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/lib/base64.c b/lib/base64.c
index 6b87eed..ce2df37 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -168,6 +168,82 @@ CURLcode Curl_base64_decode(const char *src,
   return CURLE_OK;
 }
 
+/*
+ * Curl_base64_decode()
+ *
+ * Given a base64 NUL-terminated string at src, decode it and write it
+ * to *out, if it will be less than out_size. Exact size of decoded
+ * data is returned in variable pointed by outlen.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * @unittest: 1302
+ */
+CURLcode Curl_base64_decode_nomalloc(const char *src, size_t out_size,
+                            unsigned char *out, size_t *outlen)
+{
+  size_t srclen = 0;
+  size_t length = 0;
+  size_t padding = 0;
+  size_t i;
+  size_t numQuantums;
+  size_t rawlen = 0;
+  unsigned char *pos;
+
+  *outlen = 0;
+  srclen = strlen(src);
+
+  /* Check the length of the input string is valid */
+  if(!srclen || srclen % 4)
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  /* Find the position of any = padding characters */
+  while((src[length] != '=') && src[length])
+    length++;
+
+  /* A maximum of two = padding characters is allowed */
+  if(src[length] == '=') {
+    padding++;
+    if(src[length + 1] == '=')
+      padding++;
+  }
+
+  /* Check the = padding characters weren't part way through the input */
+  if(length + padding != srclen)
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  /* Calculate the number of quantums */
+  numQuantums = srclen / 4;
+
+  /* Calculate the size of the decoded string */
+  rawlen = (numQuantums * 3) - padding;
+
+  /* If there is not enough room in our buffer, bail out */
+  if(rawlen >= out_size)
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  pos = out;
+
+  /* Decode the quantums */
+  for(i = 0; i < numQuantums; i++) {
+    size_t result = decodeQuantum(pos, src);
+    if(!result)
+      return CURLE_BAD_CONTENT_ENCODING;
+
+    pos += result;
+    src += 4;
+  }
+
+  /* Zero terminate */
+  *pos = '\0';
+
+  /* Return the decoded data */
+  *outlen = rawlen;
+
+  return CURLE_OK;
+}
+
 static CURLcode base64_encode(const char *table64,
                               struct SessionHandle *data,
                               const char *inputbuff, size_t insize,
diff --git a/lib/curl_base64.h b/lib/curl_base64.h
index 92896fe..e9f5b24 100644
--- a/lib/curl_base64.h
+++ b/lib/curl_base64.h
@@ -31,5 +31,7 @@ CURLcode Curl_base64url_encode(struct SessionHandle *data,
 
 CURLcode Curl_base64_decode(const char *src,
                             unsigned char **outptr, size_t *outlen);
+CURLcode Curl_base64_decode_nomalloc(const char *src, size_t out_size,
+                            unsigned char *out, size_t *outlen);
 
 #endif /* HEADER_CURL_BASE64_H */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 01bbc61..7860d95 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -796,11 +796,18 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
     curlssl_sha256sum(pubkey, pubkeylen,
                       sha256sumdigest, SHA256_DIGEST_LENGTH);
 
+    expectedsha256sumdigest = malloc(SHA256_DIGEST_LENGTH + 1);
+    if(!expectedsha256sumdigest) {
+      Curl_safefree(sha256sumdigest);
+      return CURLE_OUT_OF_MEMORY;
+    }
+
     /* it starts with sha256//, copy so we can modify it */
     pinkeylen = strlen(pinnedpubkey) + 1;
     pinkeycopy = malloc(pinkeylen);
     if(!pinkeycopy) {
       Curl_safefree(sha256sumdigest);
+      Curl_safefree(expectedsha256sumdigest);
       return CURLE_OUT_OF_MEMORY;
     }
     memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
@@ -816,19 +823,15 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
         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);
+      pem_read = Curl_base64_decode_nomalloc(begin_pos + 8,
+                                    SHA256_DIGEST_LENGTH + 1,
+                                    expectedsha256sumdigest, &size);
+      /* if valid base64, compare sha256 digests directly */
+      if(!pem_read && SHA256_DIGEST_LENGTH == size &&
+         !memcmp(sha256sumdigest, expectedsha256sumdigest,
+                 SHA256_DIGEST_LENGTH)) {
+        result = CURLE_OK;
+        break;
       }
 
       /*
@@ -841,6 +844,7 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
       }
     } while(end_pos && begin_pos);
     Curl_safefree(sha256sumdigest);
+    Curl_safefree(expectedsha256sumdigest);
     Curl_safefree(pinkeycopy);
     return result;
   }
-- 
1.9.2


