aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/vtls/mbedtls.c115
1 files changed, 66 insertions, 49 deletions
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 05af46212..26959e041 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -148,45 +148,7 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
- RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
-
-static int
-mbedtls_verify_pinned_crt(void *p, mbedtls_x509_crt *crt,
- int depth, unsigned int *flags)
-{
- struct SessionHandle *data = p;
- unsigned char pubkey[PUB_DER_MAX_BYTES];
- int ret;
- int size;
- char *pinned_cert = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
-
- /* Skip intermediate and root certificates */
- if(depth) {
- return 0;
- }
-
- if(pinned_cert == NULL || crt == NULL) {
- *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
- return 1;
- }
-
- /* Extract pubkey */
- size = mbedtls_pk_write_pubkey_der(&crt->pk, pubkey, PUB_DER_MAX_BYTES);
- if(size <= 0) {
- *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
- return 1;
- }
-
- /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
- ret = Curl_pin_peer_pubkey(data, pinned_cert,
- &pubkey[PUB_DER_MAX_BYTES - size], size);
- if(ret == CURLE_OK) {
- return 0;
- }
-
- *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
- return 1;
-}
+ RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
static Curl_recv mbedtls_recv;
static Curl_send mbedtls_send;
@@ -455,7 +417,7 @@ mbedtls_connect_step2(struct connectdata *conn,
int ret;
struct SessionHandle *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
- char buffer[1024];
+ const mbedtls_x509_crt *peercert;
#ifdef HAS_ALPN
const char* next_protocol;
@@ -510,13 +472,72 @@ mbedtls_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- if(mbedtls_ssl_get_peer_cert(&(connssl->ssl))) {
- /* If the session was resumed, there will be no peer certs */
- memset(buffer, 0, sizeof(buffer));
+ peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
- if(mbedtls_x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
- mbedtls_ssl_get_peer_cert(&(connssl->ssl))) != -1)
+ if(peercert && data->set.verbose) {
+ const size_t bufsize = 16384;
+ char *buffer = malloc(bufsize);
+
+ if(!buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
infof(data, "Dumping cert info:\n%s\n", buffer);
+ else
+ infof(data, "Unable to dump certificate information.\n");
+
+ free(buffer);
+ }
+
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ int size;
+ CURLcode result;
+ mbedtls_x509_crt *p;
+ unsigned char pubkey[PUB_DER_MAX_BYTES];
+
+ if(!peercert || !peercert->raw.p || !peercert->raw.len) {
+ failf(data, "Failed due to missing peer certificate");
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ p = calloc(1, sizeof(*p));
+
+ if(!p)
+ return CURLE_OUT_OF_MEMORY;
+
+ mbedtls_x509_crt_init(p);
+
+ /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
+ needs a non-const key, for now.
+ https://github.com/ARMmbed/mbedtls/issues/396 */
+ if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
+ failf(data, "Failed copying peer certificate");
+ mbedtls_x509_crt_free(p);
+ free(p);
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
+
+ if(size <= 0) {
+ failf(data, "Failed copying public key from peer certificate");
+ mbedtls_x509_crt_free(p);
+ free(p);
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
+ result = Curl_pin_peer_pubkey(data,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ &pubkey[PUB_DER_MAX_BYTES - size], size);
+ if(result) {
+ mbedtls_x509_crt_free(p);
+ free(p);
+ return result;
+ }
+
+ mbedtls_x509_crt_free(p);
+ free(p);
}
#ifdef HAS_ALPN
@@ -683,10 +704,6 @@ mbedtls_connect_common(struct connectdata *conn,
long timeout_ms;
int what;
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
- mbedtls_ssl_conf_verify(&connssl->config, mbedtls_verify_pinned_crt, data);
- }
-
/* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) {
*done = TRUE;