/** * gnutls_certificate_set_x509_key_file: * @res: is a #gnutls_certificate_credentials_t type. * @certfile: is a file that containing the certificate list (path) for * the specified private key, in PKCS7 format, or a list of certificates * @keyfile: is a file that contains the private key * @type: is PEM or DER * * This function sets a certificate/private key pair in the * gnutls_certificate_credentials_t type. This function may be * called more than once, in case multiple keys/certificates exist for * the server. For clients that need to send more than its own end * entity certificate, e.g., also an intermediate CA cert, then the * @certfile must contain the ordered certificate chain. * * Note that the names in the certificate provided will be considered * when selecting the appropriate certificate to use (in case of multiple * certificate/key pairs). * * This function can also accept URLs at @keyfile and @certfile. In that case it * will use the private key and certificate indicated by the URLs. Note * that the supported URLs are the ones indicated by gnutls_url_is_supported(). * * In case the @certfile is provided as a PKCS #11 URL, then the certificate, and its * present issuers in the token are imported (i.e., forming the required trust chain). * * If that function fails to load the @res structure is at an undefined state, it must * not be reused to load other keys or certificates. * * Note that, this function by default returns zero on success and a negative value on error. * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair. * * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior). * * Since: 3.1.11 **/ int gnutls_certificate_set_x509_key_file(gnutls_certificate_credentials_t res, const char *certfile, const char *keyfile, gnutls_x509_crt_fmt_t type) { return gnutls_certificate_set_x509_key_file2(res, certfile, keyfile, type, NULL, 0); }
bool CTlsSocket::SetClientCertificate(fz::native_string const& keyfile, fz::native_string const& certs, fz::native_string const& password) { if (!m_certCredentials) { return false; } int res = gnutls_certificate_set_x509_key_file2(m_certCredentials, fz::to_string(certs).c_str(), fz::to_string(keyfile).c_str(), GNUTLS_X509_FMT_PEM, password.empty() ? 0 : fz::to_utf8(password).c_str(), 0); if (res < 0) { LogError(res, _T("gnutls_certificate_set_x509_key_file2")); Uninit(); return false; } return true; }
static int ma_ssl_set_certs(MYSQL *mysql) { char *certfile= mysql->options.ssl_cert, *keyfile= mysql->options.ssl_key; char *cipher= NULL; int ssl_error= 0; if (mysql->options.ssl_ca) { ssl_error= gnutls_certificate_set_x509_trust_file(GNUTLS_xcred, mysql->options.ssl_ca, GNUTLS_X509_FMT_PEM); if (ssl_error < 0) goto error; } gnutls_certificate_set_verify_function(GNUTLS_xcred, my_verify_callback); /* GNUTLS doesn't support ca_path */ if (keyfile && !certfile) certfile= keyfile; if (certfile && !keyfile) keyfile= certfile; /* set key */ if (certfile || keyfile) { if ((ssl_error= gnutls_certificate_set_x509_key_file2(GNUTLS_xcred, certfile, keyfile, GNUTLS_X509_FMT_PEM, OPT_HAS_EXT_VAL(mysql, ssl_pw) ? mysql->options.extension->ssl_pw : NULL, 0)) < 0) goto error; } return 1; error: if (cipher) my_free(cipher); return ssl_error; }
static CURLcode gtls_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; gnutls_session_t session; int rc; void *ssl_sessionid; size_t ssl_idsize; bool sni = TRUE; /* default is SNI enabled */ #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT static const int cipher_priority[] = { /* These two ciphers were added to GnuTLS as late as ver. 3.0.1, but this code path is only ever used for ver. < 2.12.0. GNUTLS_CIPHER_AES_128_GCM, GNUTLS_CIPHER_AES_256_GCM, */ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_CAMELLIA_128_CBC, GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_CIPHER_3DES_CBC, }; static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; static int protocol_priority[] = { 0, 0, 0, 0 }; #else #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" /* If GnuTLS was compiled without support for SRP it will error out if SRP is requested in the priority string, so treat it specially */ #define GNUTLS_SRP "+SRP" const char* prioritylist; const char *err = NULL; #endif if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ return CURLE_OK; if(!gtls_inited) Curl_gtls_init(); /* GnuTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } #ifdef USE_TLS_SRP if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); rc = gnutls_srp_allocate_client_credentials( &conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_allocate_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_OUT_OF_MEMORY; } rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. srp_client_cred, data->set.ssl.username, data->set.ssl.password); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_BAD_FUNCTION_ARGUMENT; } } #endif if(data->set.ssl.CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, data->set.ssl.CAfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CAfile); } #ifdef HAS_CAPATH if(data->set.ssl.CApath) { /* set the trusted CA cert directory */ rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, data->set.ssl.CApath, GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", data->set.ssl.CAfile, gnutls_strerror(rc)); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", rc, data->set.ssl.CApath); } #endif #ifdef CURL_CA_FALLBACK /* use system ca certificate store as fallback */ if(data->set.ssl.verifypeer && !(data->set.ssl.CAfile || data->set.ssl.CApath)) { gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred); } #endif if(data->set.ssl.CRLfile) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, data->set.ssl.CRLfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", data->set.ssl.CRLfile, gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", rc, data->set.ssl.CRLfile); } /* Initialize TLS session as a client */ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } /* convenient assign */ session = conn->ssl[sockindex].session; if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && #endif sni && (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, strlen(conn->host.name)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); /* Use default priorities */ rc = gnutls_set_default_priority(session); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT rc = gnutls_cipher_set_priority(session, cipher_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; /* Sets the priority on the certificate types supported by gnutls. Priority is higher for types specified before others. After specifying the types you want, you must append a 0. */ rc = gnutls_certificate_type_set_priority(session, cert_type_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; if(data->set.ssl.cipher_list != NULL) { failf(data, "can't pass a custom cipher list to older GnuTLS" " versions"); return CURLE_SSL_CONNECT_ERROR; } switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: protocol_priority[0] = GNUTLS_SSL3; break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: protocol_priority[0] = GNUTLS_TLS1_0; protocol_priority[1] = GNUTLS_TLS1_1; protocol_priority[2] = GNUTLS_TLS1_2; break; case CURL_SSLVERSION_TLSv1_0: protocol_priority[0] = GNUTLS_TLS1_0; break; case CURL_SSLVERSION_TLSv1_1: protocol_priority[0] = GNUTLS_TLS1_1; break; case CURL_SSLVERSION_TLSv1_2: protocol_priority[0] = GNUTLS_TLS1_2; break; case CURL_SSLVERSION_SSLv2: default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; break; } rc = gnutls_protocol_set_priority(session, protocol_priority); if(rc != GNUTLS_E_SUCCESS) { failf(data, "Did you pass a valid GnuTLS cipher list?"); return CURLE_SSL_CONNECT_ERROR; } #else /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; sni = false; break; case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_0: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.0:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_1: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.1:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_2: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.2:" GNUTLS_SRP; break; case CURL_SSLVERSION_SSLv2: default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; break; } rc = gnutls_priority_set_direct(session, prioritylist, &err); if((rc == GNUTLS_E_INVALID_REQUEST) && err) { if(!strcmp(err, GNUTLS_SRP)) { /* This GnuTLS was probably compiled without support for SRP. * Note that fact and try again without it. */ int validprioritylen = curlx_uztosi(err - prioritylist); char *prioritycopy = strdup(prioritylist); if(!prioritycopy) return CURLE_OUT_OF_MEMORY; infof(data, "This GnuTLS does not support SRP\n"); if(validprioritylen) /* Remove the :+SRP */ prioritycopy[validprioritylen - 1] = 0; rc = gnutls_priority_set_direct(session, prioritycopy, &err); free(prioritycopy); } } if(rc != GNUTLS_E_SUCCESS) { failf(data, "Error %d setting GnuTLS cipher list starting with %s", rc, err); return CURLE_SSL_CONNECT_ERROR; } #endif #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { int cur = 0; gnutls_datum_t protocols[2]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; cur++; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1; protocols[cur].size = ALPN_HTTP_1_1_LENGTH; cur++; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); gnutls_alpn_set_protocols(session, protocols, cur, 0); } #endif if(data->set.str[STRING_CERT]) { if(data->set.str[STRING_KEY_PASSWD]) { #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 const unsigned int supported_key_encryption_algorithms = GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 | GNUTLS_PKCS_USE_PBES2_AES_256; rc = gnutls_certificate_set_x509_key_file2( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]), data->set.str[STRING_KEY_PASSWD], supported_key_encryption_algorithms); if(rc != GNUTLS_E_SUCCESS) { failf(data, "error reading X.509 potentially-encrypted key file: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } #else failf(data, "gnutls lacks support for encrypted key files"); return CURLE_SSL_CONNECT_ERROR; #endif } else { rc = gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, data->set.str[STRING_CERT], data->set.str[STRING_KEY] ? data->set.str[STRING_KEY] : data->set.str[STRING_CERT], do_file_type(data->set.str[STRING_CERT_TYPE]) ); if(rc != GNUTLS_E_SUCCESS) { failf(data, "error reading X.509 key or certificate file: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } } #ifdef USE_TLS_SRP /* put the credentials to the current session */ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } else #endif { rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, conn->ssl[sockindex].cred); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); return CURLE_SSL_CONNECT_ERROR; } } /* set the connection handle (file descriptor for the socket) */ gnutls_transport_set_ptr(session, GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); /* register callback functions to send and receive data. */ gnutls_transport_set_push_function(session, Curl_gtls_push); gnutls_transport_set_pull_function(session, Curl_gtls_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); #ifdef HAS_OCSP if(data->set.ssl.verifystatus) { rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; } } #endif /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ infof (data, "SSL re-using session ID\n"); } return CURLE_OK; }
static int qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds, Error **errp) { char *cacert = NULL, *cacrl = NULL, *cert = NULL, *key = NULL, *dhparams = NULL; int ret; int rv = -1; trace_qcrypto_tls_creds_x509_load(creds, creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>"); if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { if (qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_CA_CERT, true, &cacert, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_CA_CRL, false, &cacrl, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_SERVER_CERT, true, &cert, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_SERVER_KEY, true, &key, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_DH_PARAMS, false, &dhparams, errp) < 0) { goto cleanup; } } else { if (qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_CA_CERT, true, &cacert, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_CLIENT_CERT, false, &cert, errp) < 0 || qcrypto_tls_creds_get_path(&creds->parent_obj, QCRYPTO_TLS_CREDS_X509_CLIENT_KEY, false, &key, errp) < 0) { goto cleanup; } } if (creds->sanityCheck && qcrypto_tls_creds_x509_sanity_check(creds, creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, cacert, cert, errp) < 0) { goto cleanup; } ret = gnutls_certificate_allocate_credentials(&creds->data); if (ret < 0) { error_setg(errp, "Cannot allocate credentials: '%s'", gnutls_strerror(ret)); goto cleanup; } ret = gnutls_certificate_set_x509_trust_file(creds->data, cacert, GNUTLS_X509_FMT_PEM); if (ret < 0) { error_setg(errp, "Cannot load CA certificate '%s': %s", cacert, gnutls_strerror(ret)); goto cleanup; } if (cert != NULL && key != NULL) { #if GNUTLS_VERSION_NUMBER >= 0x030111 char *password = NULL; if (creds->passwordid) { password = qcrypto_secret_lookup_as_utf8(creds->passwordid, errp); if (!password) { goto cleanup; } } ret = gnutls_certificate_set_x509_key_file2(creds->data, cert, key, GNUTLS_X509_FMT_PEM, password, 0); g_free(password); #else /* GNUTLS_VERSION_NUMBER < 0x030111 */ if (creds->passwordid) { error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11"); goto cleanup; } ret = gnutls_certificate_set_x509_key_file(creds->data, cert, key, GNUTLS_X509_FMT_PEM); #endif /* GNUTLS_VERSION_NUMBER < 0x030111 */ if (ret < 0) { error_setg(errp, "Cannot load certificate '%s' & key '%s': %s", cert, key, gnutls_strerror(ret)); goto cleanup; } } if (cacrl != NULL) { ret = gnutls_certificate_set_x509_crl_file(creds->data, cacrl, GNUTLS_X509_FMT_PEM); if (ret < 0) { error_setg(errp, "Cannot load CRL '%s': %s", cacrl, gnutls_strerror(ret)); goto cleanup; } } if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams, &creds->parent_obj.dh_params, errp) < 0) { goto cleanup; } gnutls_certificate_set_dh_params(creds->data, creds->parent_obj.dh_params); } rv = 0; cleanup: g_free(cacert); g_free(cacrl); g_free(cert); g_free(key); g_free(dhparams); return rv; }
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { int ret; if (conn == NULL || params == NULL) return -1; if (params->flags & TLS_CONN_EXT_CERT_CHECK) { wpa_printf(MSG_INFO, "GnuTLS: tls_ext_cert_check=1 not supported"); return -1; } if (params->subject_match) { wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported"); return -1; } if (params->altsubject_match) { wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported"); return -1; } os_free(conn->suffix_match); conn->suffix_match = NULL; if (params->suffix_match) { conn->suffix_match = os_strdup(params->suffix_match); if (conn->suffix_match == NULL) return -1; } #if GNUTLS_VERSION_NUMBER >= 0x030300 os_free(conn->domain_match); conn->domain_match = NULL; if (params->domain_match) { conn->domain_match = os_strdup(params->domain_match); if (conn->domain_match == NULL) return -1; } #else /* < 3.3.0 */ if (params->domain_match) { wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported"); return -1; } #endif /* >= 3.3.0 */ conn->flags = params->flags; if (params->openssl_ciphers) { wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported"); return -1; } /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); * to force peer validation(?) */ if (params->ca_cert) { wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format", params->ca_cert); ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); return -1; } } } else if (params->ca_cert_blob) { gnutls_datum_t ca; ca.data = (unsigned char *) params->ca_cert_blob; ca.size = params->ca_cert_blob_len; ret = gnutls_certificate_set_x509_trust_mem( conn->xcred, &ca, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to parse CA cert in DER format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_mem( conn->xcred, &ca, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to parse CA cert in PEM format: %s", gnutls_strerror(ret)); return -1; } } } else if (params->ca_path) { wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported"); return -1; } conn->disable_time_checks = 0; if (params->ca_cert || params->ca_cert_blob) { conn->verify_peer = 1; gnutls_certificate_set_verify_function( conn->xcred, tls_connection_verify_peer); if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); } if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { conn->disable_time_checks = 1; gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); } } if (params->client_cert && params->private_key) { #if GNUTLS_VERSION_NUMBER >= 0x03010b ret = gnutls_certificate_set_x509_key_file2( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd, 0); #else /* private_key_passwd not (easily) supported here */ ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); #endif if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in DER format: %s", gnutls_strerror(ret)); #if GNUTLS_VERSION_NUMBER >= 0x03010b ret = gnutls_certificate_set_x509_key_file2( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM, params->private_key_passwd, 0); #else ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); #endif if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in PEM format: %s", gnutls_strerror(ret)); return ret; } } } else if (params->private_key) { int pkcs12_ok = 0; #ifdef PKCS12_FUNCS /* Try to load in PKCS#12 format */ ret = gnutls_certificate_set_x509_simple_pkcs12_file( conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); return -1; } else pkcs12_ok = 1; #endif /* PKCS12_FUNCS */ if (!pkcs12_ok) { wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " "included"); return -1; } } else if (params->client_cert_blob && params->private_key_blob) { gnutls_datum_t cert, key; cert.data = (unsigned char *) params->client_cert_blob; cert.size = params->client_cert_blob_len; key.data = (unsigned char *) params->private_key_blob; key.size = params->private_key_blob_len; #if GNUTLS_VERSION_NUMBER >= 0x03010b ret = gnutls_certificate_set_x509_key_mem2( conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER, params->private_key_passwd, 0); #else /* private_key_passwd not (easily) supported here */ ret = gnutls_certificate_set_x509_key_mem( conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER); #endif if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in DER format: %s", gnutls_strerror(ret)); #if GNUTLS_VERSION_NUMBER >= 0x03010b ret = gnutls_certificate_set_x509_key_mem2( conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM, params->private_key_passwd, 0); #else /* private_key_passwd not (easily) supported here */ ret = gnutls_certificate_set_x509_key_mem( conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM); #endif if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in PEM format: %s", gnutls_strerror(ret)); return ret; } } } else if (params->private_key_blob) { #ifdef PKCS12_FUNCS gnutls_datum_t key; key.data = (unsigned char *) params->private_key_blob; key.size = params->private_key_blob_len; /* Try to load in PKCS#12 format */ ret = gnutls_certificate_set_x509_simple_pkcs12_mem( conn->xcred, &key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); return -1; } #else /* PKCS12_FUNCS */ wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included"); return -1; #endif /* PKCS12_FUNCS */ } #if GNUTLS_VERSION_NUMBER >= 0x030103 if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) { ret = gnutls_ocsp_status_request_enable_client(conn->session, NULL, 0, NULL); if (ret != GNUTLS_E_SUCCESS) { wpa_printf(MSG_INFO, "GnuTLS: Failed to enable OCSP client"); return -1; } } #else /* 3.1.3 */ if (params->flags & TLS_CONN_REQUIRE_OCSP) { wpa_printf(MSG_INFO, "GnuTLS: OCSP not supported by this version of GnuTLS"); return -1; } #endif /* 3.1.3 */ conn->params_set = 1; ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure credentials: %s", gnutls_strerror(ret)); } return ret; }
void doit(void) { int ret; gnutls_certificate_credentials_t xcred; gnutls_certificate_credentials_t clicred; const char *certfile; const char *ocspfile1; char certname[TMPNAME_SIZE], ocspname1[TMPNAME_SIZE]; time_t t; FILE *fp; global_init(); gnutls_global_set_time_function(mytime); assert(gnutls_certificate_allocate_credentials(&xcred) >= 0); assert(gnutls_certificate_allocate_credentials(&clicred) >= 0); certfile = get_tmpname(certname); fp = fopen(certfile, "wb"); if (fp == NULL) fail("error in fopen\n"); assert(fwrite(server_localhost_ca3_cert_chain_pem, 1, strlen(server_localhost_ca3_cert_chain_pem), fp)>0); assert(fwrite(server_ca3_key_pem, 1, strlen((char*)server_ca3_key_pem), fp)>0); fclose(fp); /* set cert with localhost name */ ret = gnutls_certificate_set_x509_key_file2(xcred, certfile, certfile, GNUTLS_X509_FMT_PEM, NULL, 0); if (ret < 0) fail("set_x509_key_file failed: %s\n", gnutls_strerror(ret)); fp = fopen(certfile, "wb"); if (fp == NULL) fail("error in fopen\n"); assert(fwrite(server_localhost6_ca3_cert_chain_pem, 1, strlen(server_localhost6_ca3_cert_chain_pem), fp)>0); assert(fwrite(server_ca3_key_pem, 1, strlen((char*)server_ca3_key_pem), fp)>0); fclose(fp); gnutls_certificate_set_flags(xcred, GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK); /* set OCSP response */ ocspfile1 = get_tmpname(ocspname1); fp = fopen(ocspfile1, "wb"); if (fp == NULL) fail("error in fopen\n"); assert(fwrite(ocsp_resp1.data, 1, ocsp_resp1.size, fp)>0); fclose(fp); ret = gnutls_certificate_set_ocsp_status_request_file(xcred, ocspfile1, 0); if (ret < 0) fail("ocsp file set failed: %s\n", gnutls_strerror(ret)); t = gnutls_certificate_get_ocsp_expiration(xcred, 0, 0, 0); if (t != 1511689427) fail("error in OCSP validity time: %ld\n", (long int)t); t = gnutls_certificate_get_ocsp_expiration(xcred, 0, 1, 0); if (t != -1) fail("error in OCSP validity time: %ld\n", (long int)t); t = gnutls_certificate_get_ocsp_expiration(xcred, 0, -1, 0); if (t != 1511689427) fail("error in OCSP validity time: %ld\n", (long int)t); /* make sure that our invalid OCSP responses are not considered in verification */ gnutls_certificate_set_verify_flags(clicred, GNUTLS_VERIFY_DISABLE_CRL_CHECKS); if (gnutls_certificate_get_verify_flags(clicred) != GNUTLS_VERIFY_DISABLE_CRL_CHECKS) fail("error in gnutls_certificate_set_verify_flags\n"); ret = gnutls_certificate_set_x509_trust_mem(clicred, &ca3_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("error in setting trust cert: %s\n", gnutls_strerror(ret)); } test_cli_serv(xcred, clicred, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2", "localhost", &ocsp_resp1, check_response, NULL); /* the DNS name of the first cert */ test_cli_serv(xcred, clicred, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3", "localhost", &ocsp_resp1, check_response, NULL); /* the DNS name of the first cert */ gnutls_certificate_free_credentials(xcred); gnutls_certificate_free_credentials(clicred); gnutls_global_deinit(); remove(ocspfile1); remove(certfile); }