/** * gnutls_certificate_set_x509_key_mem: * @res: is a #gnutls_certificate_credentials_t type. * @cert: contains a certificate list (path) for the specified private key * @key: is the private key, or %NULL * @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. * * Note that the keyUsage (2.5.29.15) PKIX extension in X.509 certificates * is supported. This means that certificates intended for signing cannot * be used for ciphersuites that require encryption. * * If the certificate and the private key are given in PEM encoding * then the strings that hold their values must be null terminated. * * The @key may be %NULL if you are using a sign callback, see * gnutls_sign_callback_set(). * * 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). * **/ int gnutls_certificate_set_x509_key_mem(gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type) { return gnutls_certificate_set_x509_key_mem2(res, cert, key, type, NULL, 0); }
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; }