Also add public key extraction example to CURLOPT_PINNEDPUBLICKEY doc.
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, NSS and GSKit
-backends.
+Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for NSS and
+wolfSSL/CyaSSL. Other SSL backends not supported.
If this option is used several times, the last one will be used.
-(Added in 7.39.0)
.IP "--cert-status"
(SSL) Tells curl to verify the status of the server certificate by using the
Certificate Status Request (aka. OCSP stapling) TLS extension.
curl_easy_perform(curl);
}
.fi
+.SH PUBLIC KEY EXTRACTION
+If you do not have the server's public key file you can extract it from the
+server's certificate.
+.nf
+openssl x509 -in www.test.com.pem -pubkey -noout > www.test.com.pubkey.pem
+.fi
+The public key is output in PEM format and contains a header, base64 data and a
+footer:
+.nf
+-----BEGIN PUBLIC KEY-----
+[BASE 64 DATA]
+-----END PUBLIC KEY-----
+.fi
.SH AVAILABILITY
-If built TLS enabled. This is currently only implemented in the OpenSSL,
-GnuTLS, NSS and GSKit backends.
-
-Added in libcurl 7.39.0
+Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for
+NSS and wolfSSL/CyaSSL. Other SSL backends not supported.
.SH RETURN VALUE
Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "rawstr.h"
+#include "x509asn1.h"
#include "curl_printf.h"
#include <cyassl/ssl.h>
}
}
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ X509 *x509;
+ const char *x509_der;
+ int x509_der_len;
+ curl_X509certificate x509_parsed;
+ curl_asn1Element *pubkey;
+ CURLcode result;
+
+ x509 = SSL_get_peer_certificate(conssl->handle);
+ if(!x509) {
+ failf(data, "SSL: failed retrieving server certificate");
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len);
+ if(!x509_der) {
+ failf(data, "SSL: failed retrieving ASN.1 server certificate");
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ memset(&x509_parsed, 0, sizeof x509_parsed);
+ Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len);
+
+ pubkey = &x509_parsed.subjectPublicKeyInfo;
+ if(!pubkey->header || pubkey->end <= pubkey->header) {
+ failf(data, "SSL: failed retrieving public key from server certificate");
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ result = Curl_pin_peer_pubkey(data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ (const unsigned char *)pubkey->header,
+ (size_t)(pubkey->end - pubkey->header));
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+
conssl->connecting_state = ssl_connect_3;
infof(data, "SSL connected\n");
#include "curl_setup.h"
-#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS)
+#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
+ defined(USE_CYASSL)
#include <curl/curl.h>
#include "urldata.h"
return CURLE_OK;
}
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL */
#if defined(USE_GSKIT)
#include "curl_setup.h"
-#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS)
+#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
+ defined(USE_CYASSL)
#include "urldata.h"
CURLcode Curl_verifyhost(struct connectdata * conn,
const char * beg, const char * end);
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS */
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL */
#endif /* HEADER_CURL_X509ASN1_H */
" --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/NSS/GSKit only)",
+ "(OpenSSL/GnuTLS/NSS/wolfSSL/CyaSSL/GSKit only)",
" --post301 "
"Do not switch to GET after following a 301 redirect (H)",
" --post302 "
}
elsif ($libcurl =~ /(yassl|wolfssl)/i) {
$has_yassl=1;
+ $has_sslpinning=1;
$ssllib="yassl";
}
elsif ($libcurl =~ /polarssl/i) {