Loading docs/curl.1 +2 −1 Original line number Diff line number Diff line Loading @@ -548,7 +548,8 @@ indicating its identity. A public key is extracted from this certificate and if it does not exactly match the public key provided to this option, curl will abort the connection before sending or receiving any data. This is currently only implemented in the OpenSSL, GnuTLS and GSKit backends. This is currently only implemented in the OpenSSL, GnuTLS, NSS and GSKit backends. If this option is used several times, the last one will be used. (Added in 7.39.0) Loading docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3 +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ if(curl) { .fi .SH AVAILABILITY If built TLS enabled. This is currently only implemented in the OpenSSL, GnuTLS and GSKit backends. GnuTLS, NSS and GSKit backends. Added in libcurl 7.39.0 .SH RETURN VALUE Loading lib/vtls/nss.c +53 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ #include <base64.h> #include <cert.h> #include <prerror.h> #include <keyhi.h> /* for SECKEY_DestroyPublicKey() */ #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) Loading Loading @@ -943,6 +944,53 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, return res; } static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, const char *pinnedpubkey) { CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; struct SessionHandle *data = connssl->data; CERTCertificate *cert; if(!pinnedpubkey) /* no pinned public key specified */ return CURLE_OK; /* get peer certificate */ cert = SSL_PeerCertificate(connssl->handle); if(cert) { /* extract public key from peer certificate */ SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); if(pubkey) { /* encode the public key as DER */ 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, cert_der->len); SECITEM_FreeItem(cert_der, PR_TRUE); } SECKEY_DestroyPublicKey(pubkey); } CERT_DestroyCertificate(cert); } /* report the resulting status */ switch(result) { case CURLE_OK: infof(data, "pinned public key verified successfully!\n"); break; case CURLE_SSL_PINNEDPUBKEYNOTMATCH: failf(data, "failed to verify pinned public key"); break; default: /* OOM, etc. */ break; } return result; } /** * * Callback to pick the SSL client certificate. Loading Loading @@ -1806,6 +1854,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); if(result) /* status already printed */ goto error; return CURLE_OK; error: Loading src/tool_help.c +1 −1 Original line number Diff line number Diff line Loading @@ -156,7 +156,7 @@ static const char *const helptext[] = { " --pass PASS Pass phrase for the private key (SSL/SSH)", " --path-as-is Do not squash .. sequences in URL path", " --pinnedpubkey FILE Public key (PEM/DER) to verify peer against " "(OpenSSL/GnuTLS/GSKit only)", "(OpenSSL/GnuTLS/NSS/GSKit only)", " --post301 " "Do not switch to GET after following a 301 redirect (H)", " --post302 " Loading tests/runtests.pl +1 −0 Original line number Diff line number Diff line Loading @@ -2346,6 +2346,7 @@ sub checksystem { } elsif ($libcurl =~ /nss/i) { $has_nss=1; $has_sslpinning=1; $ssllib="NSS"; } elsif ($libcurl =~ /(yassl|wolfssl)/i) { Loading Loading
docs/curl.1 +2 −1 Original line number Diff line number Diff line Loading @@ -548,7 +548,8 @@ indicating its identity. A public key is extracted from this certificate and if it does not exactly match the public key provided to this option, curl will abort the connection before sending or receiving any data. This is currently only implemented in the OpenSSL, GnuTLS and GSKit backends. This is currently only implemented in the OpenSSL, GnuTLS, NSS and GSKit backends. If this option is used several times, the last one will be used. (Added in 7.39.0) Loading
docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3 +1 −1 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ if(curl) { .fi .SH AVAILABILITY If built TLS enabled. This is currently only implemented in the OpenSSL, GnuTLS and GSKit backends. GnuTLS, NSS and GSKit backends. Added in libcurl 7.39.0 .SH RETURN VALUE Loading
lib/vtls/nss.c +53 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ #include <base64.h> #include <cert.h> #include <prerror.h> #include <keyhi.h> /* for SECKEY_DestroyPublicKey() */ #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) Loading Loading @@ -943,6 +944,53 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, return res; } static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, const char *pinnedpubkey) { CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; struct SessionHandle *data = connssl->data; CERTCertificate *cert; if(!pinnedpubkey) /* no pinned public key specified */ return CURLE_OK; /* get peer certificate */ cert = SSL_PeerCertificate(connssl->handle); if(cert) { /* extract public key from peer certificate */ SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); if(pubkey) { /* encode the public key as DER */ 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, cert_der->len); SECITEM_FreeItem(cert_der, PR_TRUE); } SECKEY_DestroyPublicKey(pubkey); } CERT_DestroyCertificate(cert); } /* report the resulting status */ switch(result) { case CURLE_OK: infof(data, "pinned public key verified successfully!\n"); break; case CURLE_SSL_PINNEDPUBKEYNOTMATCH: failf(data, "failed to verify pinned public key"); break; default: /* OOM, etc. */ break; } return result; } /** * * Callback to pick the SSL client certificate. Loading Loading @@ -1806,6 +1854,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); if(result) /* status already printed */ goto error; return CURLE_OK; error: Loading
src/tool_help.c +1 −1 Original line number Diff line number Diff line Loading @@ -156,7 +156,7 @@ static const char *const helptext[] = { " --pass PASS Pass phrase for the private key (SSL/SSH)", " --path-as-is Do not squash .. sequences in URL path", " --pinnedpubkey FILE Public key (PEM/DER) to verify peer against " "(OpenSSL/GnuTLS/GSKit only)", "(OpenSSL/GnuTLS/NSS/GSKit only)", " --post301 " "Do not switch to GET after following a 301 redirect (H)", " --post302 " Loading
tests/runtests.pl +1 −0 Original line number Diff line number Diff line Loading @@ -2346,6 +2346,7 @@ sub checksystem { } elsif ($libcurl =~ /nss/i) { $has_nss=1; $has_sslpinning=1; $ssllib="NSS"; } elsif ($libcurl =~ /(yassl|wolfssl)/i) { Loading