|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2002-2016 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
* Copyright (C) 2016-2017 Red Hat, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "auth.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include "extensions.h"
|
|
Packit |
549fdc |
#include <auth/cert.h>
|
|
Packit |
549fdc |
#include "dh.h"
|
|
Packit |
549fdc |
#include "num.h"
|
|
Packit |
549fdc |
#include "datum.h"
|
|
Packit |
549fdc |
#include <pk.h>
|
|
Packit |
549fdc |
#include <algorithms.h>
|
|
Packit |
549fdc |
#include <global.h>
|
|
Packit |
549fdc |
#include <record.h>
|
|
Packit |
549fdc |
#include <tls-sig.h>
|
|
Packit |
549fdc |
#include <state.h>
|
|
Packit |
549fdc |
#include <pk.h>
|
|
Packit |
549fdc |
#include "str.h"
|
|
Packit |
549fdc |
#include <debug.h>
|
|
Packit |
549fdc |
#include <x509_b64.h>
|
|
Packit |
549fdc |
#include <x509.h>
|
|
Packit |
549fdc |
#include <gnutls/ocsp.h>
|
|
Packit |
549fdc |
#include "x509/common.h"
|
|
Packit |
549fdc |
#include "x509/x509_int.h"
|
|
Packit |
549fdc |
#include <str_array.h>
|
|
Packit |
549fdc |
#include <gnutls/x509.h>
|
|
Packit |
549fdc |
#include "read-file.h"
|
|
Packit |
549fdc |
#include "system-keys.h"
|
|
Packit |
549fdc |
#include "urls.h"
|
|
Packit |
549fdc |
#ifdef _WIN32
|
|
Packit |
549fdc |
#include <wincrypt.h>
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* some x509 certificate parsing functions.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
certificate_credential_append_crt_list(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
gnutls_str_array_t names,
|
|
Packit |
549fdc |
gnutls_pcert_st * crt, int nr);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define CRED_RET_SUCCESS(cred) \
|
|
Packit |
549fdc |
if (cred->flags & GNUTLS_CERTIFICATE_API_V2) { \
|
|
Packit |
549fdc |
return cred->ncerts-1; \
|
|
Packit |
549fdc |
} else { \
|
|
Packit |
549fdc |
return 0; \
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* fifteen days */
|
|
Packit |
549fdc |
#define MAX_OCSP_VALIDITY_SECS (15*60*60*24)
|
|
Packit |
549fdc |
#ifdef ENABLE_OCSP
|
|
Packit |
549fdc |
/* If the certificate is revoked status will be GNUTLS_CERT_REVOKED.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns:
|
|
Packit |
549fdc |
* Zero on success, a negative error code otherwise.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
|
|
Packit |
549fdc |
gnutls_x509_trust_list_t tl,
|
|
Packit |
549fdc |
unsigned verify_flags,
|
|
Packit |
549fdc |
gnutls_x509_crt_t *cand_issuers, unsigned cand_issuers_size,
|
|
Packit |
549fdc |
gnutls_datum_t * data, unsigned int *ostatus)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_ocsp_resp_t resp;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
unsigned int status, cert_status;
|
|
Packit |
549fdc |
time_t rtime, vtime, ntime, now;
|
|
Packit |
549fdc |
int check_failed = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
now = gnutls_time(0);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_init(&resp);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_import(resp, data);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"There was an error parsing the OCSP response: %s.\n",
|
|
Packit |
549fdc |
gnutls_strerror(ret));
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_check_crt(resp, 0, cert);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"Got OCSP response with an unrelated certificate.\n");
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Attempt to verify against our trusted list */
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_verify(resp, tl, &status, verify_flags);
|
|
Packit |
549fdc |
if ((ret < 0 || status != 0) && cand_issuers_size > 0) {
|
|
Packit |
549fdc |
/* Attempt to verify against the certificate list provided by the server */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[0], &status, verify_flags);
|
|
Packit |
549fdc |
/* if verification fails attempt to find whether any of the other
|
|
Packit |
549fdc |
* bundled CAs is an issuer of the OCSP response */
|
|
Packit |
549fdc |
if ((ret < 0 || status != 0) && cand_issuers_size > 1) {
|
|
Packit |
549fdc |
int ret2;
|
|
Packit |
549fdc |
unsigned status2, i;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i=1;i
|
|
Packit |
549fdc |
ret2 = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[i], &status2, verify_flags);
|
|
Packit |
549fdc |
if (ret2 >= 0 && status2 == 0) {
|
|
Packit |
549fdc |
status = status2;
|
|
Packit |
549fdc |
ret = ret2;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* do not consider revocation data if response was not verified */
|
|
Packit |
549fdc |
if (status != 0) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
|
|
Packit |
549fdc |
&cert_status, &vtime, &ntime,
|
|
Packit |
549fdc |
&rtime, NULL);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"There was an error parsing the OCSP response: %s.\n",
|
|
Packit |
549fdc |
gnutls_strerror(ret));
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"The certificate was revoked via OCSP\n");
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_REVOKED;
|
|
Packit |
549fdc |
ret = gnutls_assert_val(0);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Report but do not fail on the following errors. That is
|
|
Packit |
549fdc |
* because including the OCSP response in the handshake shouldn't
|
|
Packit |
549fdc |
* cause more problems that not including it.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if (ntime == -1) {
|
|
Packit |
549fdc |
if (now - vtime > MAX_OCSP_VALIDITY_SECS) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"The OCSP response is old\n");
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
/* there is a newer OCSP answer, don't trust this one */
|
|
Packit |
549fdc |
if (ntime < now) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session,
|
|
Packit |
549fdc |
"There is a newer OCSP response but was not provided by the server\n");
|
|
Packit |
549fdc |
check_failed = 1;
|
|
Packit |
549fdc |
*ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
if (check_failed == 0)
|
|
Packit |
549fdc |
session->internals.ocsp_check_ok = 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_ocsp_resp_deinit(resp);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define CLEAR_CERTS for(x=0;x
|
|
Packit |
549fdc |
if (peer_certificate_list[x]) \
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(peer_certificate_list[x]); \
|
|
Packit |
549fdc |
} \
|
|
Packit |
549fdc |
gnutls_free( peer_certificate_list)
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#ifdef ENABLE_OCSP
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_x509_crt_t cert,
|
|
Packit |
549fdc |
unsigned int * ocsp_status)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_x509_tlsfeatures_t tlsfeatures;
|
|
Packit |
549fdc |
int i, ret;
|
|
Packit |
549fdc |
unsigned feature;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* RFC 7633: If cert has TLS feature GNUTLS_EXTENSION_STATUS_REQUEST, stapling is mandatory.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* At this point, we know that we did not get the certificate status.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* To proceed, first check whether we have requested the certificate status
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if (_gnutls_extension_list_check(session, GNUTLS_EXTENSION_STATUS_REQUEST) < 0) {
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_tlsfeatures_init(&tlsfeatures);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* We have requested the status, now check whether the certificate mandates a response */
|
|
Packit |
549fdc |
if (gnutls_x509_crt_get_tlsfeatures(cert, tlsfeatures, 0, NULL) == 0) {
|
|
Packit |
549fdc |
for (i = 0;; ++i) {
|
|
Packit |
549fdc |
ret = gnutls_x509_tlsfeatures_get(tlsfeatures, i, &feature);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (feature == GNUTLS_EXTENSION_STATUS_REQUEST) {
|
|
Packit |
549fdc |
/* We sent a status request, the certificate mandates a reply, but we did not get any. */
|
|
Packit |
549fdc |
*ocsp_status |= GNUTLS_CERT_MISSING_OCSP_STATUS;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
gnutls_x509_tlsfeatures_deinit(tlsfeatures);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*-
|
|
Packit |
549fdc |
* _gnutls_x509_cert_verify_peers - return the peer's certificate status
|
|
Packit |
549fdc |
* @session: is a gnutls session
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.).
|
|
Packit |
549fdc |
* The return value (status) should be one of the gnutls_certificate_status_t enumerated elements.
|
|
Packit |
549fdc |
* However you must also check the peer's name in order to check if the verified certificate belongs to the
|
|
Packit |
549fdc |
* actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
|
|
Packit |
549fdc |
-*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_x509_cert_verify_peers(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_typed_vdata_st * data,
|
|
Packit |
549fdc |
unsigned int elements,
|
|
Packit |
549fdc |
unsigned int *status)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
cert_auth_info_t info;
|
|
Packit |
549fdc |
gnutls_certificate_credentials_t cred;
|
|
Packit |
549fdc |
gnutls_x509_crt_t *peer_certificate_list;
|
|
Packit |
549fdc |
gnutls_datum_t resp;
|
|
Packit |
549fdc |
int peer_certificate_list_size, i, x, ret;
|
|
Packit |
549fdc |
gnutls_x509_crt_t *cand_issuers = NULL;
|
|
Packit |
549fdc |
unsigned cand_issuers_size = 0;
|
|
Packit |
549fdc |
unsigned int ocsp_status = 0;
|
|
Packit |
549fdc |
unsigned int verify_flags;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* No OCSP check so far */
|
|
Packit |
549fdc |
session->internals.ocsp_check_ok = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit |
549fdc |
if (info == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cred = (gnutls_certificate_credentials_t)
|
|
Packit |
549fdc |
_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit |
549fdc |
if (cred == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (info->raw_certificate_list == NULL || info->ncerts == 0)
|
|
Packit |
549fdc |
return GNUTLS_E_NO_CERTIFICATE_FOUND;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (info->ncerts > cred->verify_depth && cred->verify_depth > 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_CONSTRAINT_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
verify_flags =
|
|
Packit |
549fdc |
cred->verify_flags | session->internals.additional_verify_flags;
|
|
Packit |
549fdc |
/* generate a list of gnutls_certs based on the auth info
|
|
Packit |
549fdc |
* raw certs.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
peer_certificate_list_size = info->ncerts;
|
|
Packit |
549fdc |
peer_certificate_list =
|
|
Packit |
549fdc |
gnutls_calloc(peer_certificate_list_size,
|
|
Packit |
549fdc |
sizeof(gnutls_x509_crt_t));
|
|
Packit |
549fdc |
if (peer_certificate_list == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < peer_certificate_list_size; i++) {
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&peer_certificate_list[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_crt_import(peer_certificate_list[i],
|
|
Packit |
549fdc |
&info->raw_certificate_list[i],
|
|
Packit |
549fdc |
GNUTLS_X509_FMT_DER);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Use the OCSP extension if any */
|
|
Packit |
549fdc |
#ifdef ENABLE_OCSP
|
|
Packit |
549fdc |
if (verify_flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS)
|
|
Packit |
549fdc |
goto skip_ocsp;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_ocsp_status_request_get(session, &resp);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
ret = _gnutls_ocsp_verify_mandatory_stapling(session, peer_certificate_list[0], &ocsp_status);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
goto skip_ocsp;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (peer_certificate_list_size > 1) {
|
|
Packit |
549fdc |
cand_issuers = &peer_certificate_list[1];
|
|
Packit |
549fdc |
cand_issuers_size = peer_certificate_list_size-1;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
check_ocsp_response(session, peer_certificate_list[0], cred->tlist,
|
|
Packit |
549fdc |
verify_flags, cand_issuers,
|
|
Packit |
549fdc |
cand_issuers_size, &resp, &ocsp_status);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
skip_ocsp:
|
|
Packit |
549fdc |
/* Verify certificate
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_trust_list_verify_crt2(cred->tlist,
|
|
Packit |
549fdc |
peer_certificate_list,
|
|
Packit |
549fdc |
peer_certificate_list_size,
|
|
Packit |
549fdc |
data, elements,
|
|
Packit |
549fdc |
verify_flags, status, NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CLEAR_CERTS;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*status |= ocsp_status;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int str_array_append_idna(gnutls_str_array_t * head, const char *name, size_t size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_datum_t ahost;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* convert the provided hostname to ACE-Labels domain. */
|
|
Packit |
549fdc |
ret = gnutls_idna_map(name, size, &ahost, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
_gnutls_debug_log("unable to convert hostname %s to IDNA format\n", name);
|
|
Packit |
549fdc |
/* insert the raw name */
|
|
Packit |
549fdc |
return _gnutls_str_array_append(head, name, size);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_str_array_append(head, (char*)ahost.data, ahost.size);
|
|
Packit |
549fdc |
gnutls_free(ahost.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Returns the name of the certificate of a null name
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int get_x509_name(gnutls_x509_crt_t crt, gnutls_str_array_t * names)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t max_size;
|
|
Packit |
549fdc |
int i, ret = 0, ret2;
|
|
Packit |
549fdc |
char name[MAX_CN];
|
|
Packit |
549fdc |
unsigned have_dns_name = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; !(ret < 0); i++) {
|
|
Packit |
549fdc |
max_size = sizeof(name);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_crt_get_subject_alt_name(crt, i, name,
|
|
Packit |
549fdc |
&max_size, NULL);
|
|
Packit |
549fdc |
if (ret == GNUTLS_SAN_DNSNAME) {
|
|
Packit |
549fdc |
have_dns_name = 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret2 =
|
|
Packit |
549fdc |
str_array_append_idna(names, name,
|
|
Packit |
549fdc |
max_size);
|
|
Packit |
549fdc |
if (ret2 < 0) {
|
|
Packit |
549fdc |
_gnutls_str_array_clear(names);
|
|
Packit |
549fdc |
return gnutls_assert_val(ret2);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (have_dns_name == 0) {
|
|
Packit |
549fdc |
max_size = sizeof(name);
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_crt_get_dn_by_oid(crt, OID_X520_COMMON_NAME, 0, 0,
|
|
Packit |
549fdc |
name, &max_size);
|
|
Packit |
549fdc |
if (ret >= 0) {
|
|
Packit |
549fdc |
ret = str_array_append_idna(names, name, max_size);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
_gnutls_str_array_clear(names);
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a DER encoded certificate list from memory and stores it to a
|
|
Packit |
549fdc |
* gnutls_cert structure. Returns the number of certificates parsed.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
parse_der_cert_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
const void *input_cert, int input_cert_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_datum_t tmp;
|
|
Packit |
549fdc |
gnutls_x509_crt_t crt;
|
|
Packit |
549fdc |
gnutls_pcert_st *ccert;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_str_array_t names;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_str_array_init(&names);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ccert = gnutls_malloc(sizeof(*ccert));
|
|
Packit |
549fdc |
if (ccert == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
tmp.data = (uint8_t *) input_cert;
|
|
Packit |
549fdc |
tmp.size = input_cert_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_import(crt, &tmp, GNUTLS_X509_FMT_DER);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = get_x509_name(crt, &names);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_pcert_import_x509(ccert, crt, 0);
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = certificate_credential_append_crt_list(res, key, names, ccert, 1);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
_gnutls_str_array_clear(&names);
|
|
Packit |
549fdc |
gnutls_free(ccert);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a base64 encoded certificate list from memory and stores it to
|
|
Packit |
549fdc |
* a gnutls_cert structure. Returns the number of certificate parsed.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
parse_pem_cert_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
const char *input_cert, int input_cert_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int size;
|
|
Packit |
549fdc |
const char *ptr;
|
|
Packit |
549fdc |
gnutls_datum_t tmp;
|
|
Packit |
549fdc |
int ret, count, i;
|
|
Packit |
549fdc |
unsigned ncerts = 0;
|
|
Packit |
549fdc |
gnutls_pcert_st *pcerts = NULL;
|
|
Packit |
549fdc |
gnutls_str_array_t names;
|
|
Packit |
549fdc |
gnutls_x509_crt_t unsorted[DEFAULT_MAX_VERIFY_DEPTH];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_str_array_init(&names);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* move to the certificate
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ptr = memmem(input_cert, input_cert_size,
|
|
Packit |
549fdc |
PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1);
|
|
Packit |
549fdc |
if (ptr == NULL)
|
|
Packit |
549fdc |
ptr = memmem(input_cert, input_cert_size,
|
|
Packit |
549fdc |
PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ptr == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_BASE64_DECODING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
size = input_cert_size - (ptr - input_cert);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
count = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
do {
|
|
Packit |
549fdc |
tmp.data = (void *) ptr;
|
|
Packit |
549fdc |
tmp.size = size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&unsorted[count]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_import(unsorted[count], &tmp, GNUTLS_X509_FMT_PEM);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
count++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* now we move ptr after the pem header
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ptr++;
|
|
Packit |
549fdc |
size--;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* find the next certificate (if any)
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (size > 0) {
|
|
Packit |
549fdc |
char *ptr3;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ptr3 =
|
|
Packit |
549fdc |
memmem(ptr, size, PEM_CERT_SEP,
|
|
Packit |
549fdc |
sizeof(PEM_CERT_SEP) - 1);
|
|
Packit |
549fdc |
if (ptr3 == NULL)
|
|
Packit |
549fdc |
ptr3 = memmem(ptr, size, PEM_CERT_SEP2,
|
|
Packit |
549fdc |
sizeof(PEM_CERT_SEP2) - 1);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ptr = ptr3;
|
|
Packit |
549fdc |
size = input_cert_size - (ptr - input_cert);
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
ptr = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
while (ptr != NULL && count < DEFAULT_MAX_VERIFY_DEPTH);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
get_x509_name(unsorted[0], &names);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count);
|
|
Packit |
549fdc |
if (pcerts == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ncerts = count;
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_pcert_import_x509_list(pcerts, unsorted, &ncerts, GNUTLS_X509_CRT_LIST_SORT);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_free(pcerts);
|
|
Packit |
549fdc |
pcerts = NULL;
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
certificate_credential_append_crt_list(res, key, names, pcerts,
|
|
Packit |
549fdc |
ncerts);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < count; i++)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(unsorted[i]);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ncerts;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
_gnutls_str_array_clear(&names);
|
|
Packit |
549fdc |
for (i = 0; i < count; i++)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(unsorted[i]);
|
|
Packit |
549fdc |
if (pcerts) {
|
|
Packit |
549fdc |
for (i = 0; i < count; i++)
|
|
Packit |
549fdc |
gnutls_pcert_deinit(&pcerts[i]);
|
|
Packit |
549fdc |
gnutls_free(pcerts);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a DER or PEM certificate from memory
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_cert_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
const void *cert,
|
|
Packit |
549fdc |
int cert_size, gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (type == GNUTLS_X509_FMT_DER)
|
|
Packit |
549fdc |
ret = parse_der_cert_mem(res, key, cert, cert_size);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
ret = parse_pem_cert_mem(res, key, cert, cert_size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int tmp_pin_cb(void *userdata, int attempt, const char *token_url,
|
|
Packit |
549fdc |
const char *token_label, unsigned int flags,
|
|
Packit |
549fdc |
char *pin, size_t pin_max)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const char *tmp_pin = userdata;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (attempt == 0) {
|
|
Packit |
549fdc |
snprintf(pin, pin_max, "%s", tmp_pin);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return -1;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a PEM encoded PKCS-1 RSA/DSA private key from memory. Type
|
|
Packit |
549fdc |
* indicates the certificate format.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* It returns the private key read in @rkey.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_key_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const void *key, int key_size, gnutls_x509_crt_fmt_t type,
|
|
Packit |
549fdc |
const char *pass, unsigned int flags,
|
|
Packit |
549fdc |
gnutls_privkey_t *rkey)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_datum_t tmp;
|
|
Packit |
549fdc |
gnutls_privkey_t privkey;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (key) {
|
|
Packit |
549fdc |
tmp.data = (uint8_t *) key;
|
|
Packit |
549fdc |
tmp.size = key_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_privkey_init(&privkey);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->pin.cb) {
|
|
Packit |
549fdc |
gnutls_privkey_set_pin_function(privkey,
|
|
Packit |
549fdc |
res->pin.cb,
|
|
Packit |
549fdc |
res->pin.data);
|
|
Packit |
549fdc |
} else if (pass != NULL) {
|
|
Packit |
549fdc |
snprintf(res->pin_tmp, sizeof(res->pin_tmp), "%s",
|
|
Packit |
549fdc |
pass);
|
|
Packit |
549fdc |
gnutls_privkey_set_pin_function(privkey,
|
|
Packit |
549fdc |
tmp_pin_cb,
|
|
Packit |
549fdc |
res->pin_tmp);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_privkey_import_x509_raw(privkey, &tmp, type,
|
|
Packit |
549fdc |
pass, flags);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_privkey_deinit(privkey);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*rkey = privkey;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a private key from a token.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_key_url(gnutls_certificate_credentials_t res, const char *url, gnutls_privkey_t *rkey)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_privkey_t pkey = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* allocate space for the pkey list
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret = gnutls_privkey_init(&pkey);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->pin.cb)
|
|
Packit |
549fdc |
gnutls_privkey_set_pin_function(pkey, res->pin.cb,
|
|
Packit |
549fdc |
res->pin.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_privkey_import_url(pkey, url, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*rkey = pkey;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
if (pkey)
|
|
Packit |
549fdc |
gnutls_privkey_deinit(pkey);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define MAX_PKCS11_CERT_CHAIN 8
|
|
Packit |
549fdc |
/* Reads a certificate key from a token.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *url)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_x509_crt_t crt = NULL;
|
|
Packit |
549fdc |
gnutls_pcert_st *ccert = NULL;
|
|
Packit |
549fdc |
gnutls_str_array_t names;
|
|
Packit |
549fdc |
gnutls_datum_t t = {NULL, 0};
|
|
Packit |
549fdc |
unsigned i, count = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_str_array_init(&names);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN);
|
|
Packit |
549fdc |
if (ccert == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->pin.cb)
|
|
Packit |
549fdc |
gnutls_x509_crt_set_pin_function(crt, res->pin.cb,
|
|
Packit |
549fdc |
res->pin.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_import_url(crt, url, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_crt_import_url(crt, url,
|
|
Packit |
549fdc |
GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = get_x509_name(crt, &names);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Try to load the whole certificate chain from the PKCS #11 token */
|
|
Packit |
549fdc |
for (i=0;i
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_check_issuer(crt, crt);
|
|
Packit |
549fdc |
if (i > 0 && ret != 0) {
|
|
Packit |
549fdc |
/* self signed */
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_pcert_import_x509(&ccert[i], crt, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
count++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_get_raw_issuer(url, crt, &t, 0);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
crt = NULL;
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_import(crt, &t, GNUTLS_X509_FMT_DER);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
gnutls_free(t.data);
|
|
Packit |
549fdc |
t.data = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = certificate_credential_append_crt_list(res, key, names, ccert, count);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (crt != NULL)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
if (crt != NULL)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
gnutls_free(t.data);
|
|
Packit |
549fdc |
_gnutls_str_array_clear(&names);
|
|
Packit |
549fdc |
gnutls_free(ccert);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads a certificate file
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_cert_file(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
const char *certfile, gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t size;
|
|
Packit |
549fdc |
char *data;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (gnutls_url_is_supported(certfile)) {
|
|
Packit |
549fdc |
return read_cert_url(res, key, certfile);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
data = read_binary_file(certfile, &size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_FILE_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = read_cert_mem(res, key, data, size, type);
|
|
Packit |
549fdc |
free(data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads PKCS-1 RSA private key file or a DSA file (in the format openssl
|
|
Packit |
549fdc |
* stores it).
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
read_key_file(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const char *keyfile, gnutls_x509_crt_fmt_t type,
|
|
Packit |
549fdc |
const char *pass, unsigned int flags,
|
|
Packit |
549fdc |
gnutls_privkey_t *rkey)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t size;
|
|
Packit |
549fdc |
char *data;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (_gnutls_url_is_known(keyfile)) {
|
|
Packit |
549fdc |
if (gnutls_url_is_supported(keyfile)) {
|
|
Packit |
549fdc |
/* if no PIN function is specified, and we have a PIN,
|
|
Packit |
549fdc |
* specify one */
|
|
Packit |
549fdc |
if (pass != NULL && res->pin.cb == NULL) {
|
|
Packit |
549fdc |
snprintf(res->pin_tmp, sizeof(res->pin_tmp), "%s", pass);
|
|
Packit |
549fdc |
gnutls_certificate_set_pin_function(res, tmp_pin_cb, res->pin_tmp);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return read_key_url(res, keyfile, rkey);
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
return
|
|
Packit |
549fdc |
gnutls_assert_val
|
|
Packit |
549fdc |
(GNUTLS_E_UNIMPLEMENTED_FEATURE);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
data = read_binary_file(keyfile, &size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_FILE_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = read_key_mem(res, data, size, type, pass, flags, rkey);
|
|
Packit |
549fdc |
free(data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @cert: contains a certificate list (path) for the specified private key
|
|
Packit |
549fdc |
* @key: is the private key, or %NULL
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be called
|
|
Packit |
549fdc |
* more than once, in case multiple keys/certificates exist for the
|
|
Packit |
549fdc |
* server.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the keyUsage (2.5.29.15) PKIX extension in X.509 certificates
|
|
Packit |
549fdc |
* is supported. This means that certificates intended for signing cannot
|
|
Packit |
549fdc |
* be used for ciphersuites that require encryption.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If the certificate and the private key are given in PEM encoding
|
|
Packit |
549fdc |
* then the strings that hold their values must be null terminated.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The @key may be %NULL if you are using a sign callback, see
|
|
Packit |
549fdc |
* gnutls_sign_callback_set().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const gnutls_datum_t * cert,
|
|
Packit |
549fdc |
const gnutls_datum_t * key,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return gnutls_certificate_set_x509_key_mem2(res, cert, key, type,
|
|
Packit |
549fdc |
NULL, 0);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem2:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @cert: contains a certificate list (path) for the specified private key
|
|
Packit |
549fdc |
* @key: is the private key, or %NULL
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
* @pass: is the key's password
|
|
Packit |
549fdc |
* @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be called
|
|
Packit |
549fdc |
* more than once, in case multiple keys/certificates exist for the
|
|
Packit |
549fdc |
* server.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the keyUsage (2.5.29.15) PKIX extension in X.509 certificates
|
|
Packit |
549fdc |
* is supported. This means that certificates intended for signing cannot
|
|
Packit |
549fdc |
* be used for ciphersuites that require encryption.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If the certificate and the private key are given in PEM encoding
|
|
Packit |
549fdc |
* then the strings that hold their values must be null terminated.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The @key may be %NULL if you are using a sign callback, see
|
|
Packit |
549fdc |
* gnutls_sign_callback_set().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key_mem2(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const gnutls_datum_t * cert,
|
|
Packit |
549fdc |
const gnutls_datum_t * key,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type,
|
|
Packit |
549fdc |
const char *pass, unsigned int flags)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_privkey_t rkey;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* this should be first
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if ((ret = read_key_mem(res, key ? key->data : NULL,
|
|
Packit |
549fdc |
key ? key->size : 0, type, pass,
|
|
Packit |
549fdc |
flags, &rkey)) < 0)
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((ret = read_cert_mem(res, rkey, cert->data, cert->size, type)) < 0) {
|
|
Packit |
549fdc |
gnutls_privkey_deinit(rkey);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->ncerts++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (key && (ret = _gnutls_check_key_cert_match(res)) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CRED_RET_SUCCESS(res);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
certificate_credential_append_crt_list(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_privkey_t key,
|
|
Packit |
549fdc |
gnutls_str_array_t names,
|
|
Packit |
549fdc |
gnutls_pcert_st * crt, int nr)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
res->sorted_cert_idx = gnutls_realloc_fast(res->sorted_cert_idx,
|
|
Packit |
549fdc |
(1 + res->ncerts) *
|
|
Packit |
549fdc |
sizeof(unsigned int));
|
|
Packit |
549fdc |
if (res->sorted_cert_idx == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->certs = gnutls_realloc_fast(res->certs,
|
|
Packit |
549fdc |
(1 + res->ncerts) *
|
|
Packit |
549fdc |
sizeof(certs_st));
|
|
Packit |
549fdc |
if (res->certs == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memset(&res->certs[res->ncerts], 0, sizeof(res->certs[0]));
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->certs[res->ncerts].cert_list = crt;
|
|
Packit |
549fdc |
res->certs[res->ncerts].cert_list_length = nr;
|
|
Packit |
549fdc |
res->certs[res->ncerts].names = names;
|
|
Packit |
549fdc |
res->certs[res->ncerts].pkey = key;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* move RSA-PSS certificates before any RSA key.
|
|
Packit |
549fdc |
* Note that we cannot assume that any previous pointers
|
|
Packit |
549fdc |
* to sorted list are ok, due to the realloc in res->certs. */
|
|
Packit |
549fdc |
if (crt->pubkey->params.algo == GNUTLS_PK_RSA_PSS) {
|
|
Packit |
549fdc |
unsigned i,ridx;
|
|
Packit |
549fdc |
unsigned tmp;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i=0;i<res->ncerts;i++) {
|
|
Packit |
549fdc |
ridx = res->sorted_cert_idx[i];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->certs[ridx].cert_list->pubkey->params.algo == GNUTLS_PK_RSA) {
|
|
Packit |
549fdc |
tmp = ridx;
|
|
Packit |
549fdc |
res->sorted_cert_idx[i] = res->ncerts;
|
|
Packit |
549fdc |
res->sorted_cert_idx[res->ncerts] = tmp;
|
|
Packit |
549fdc |
goto finish;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* otherwise append it normally on the end */
|
|
Packit |
549fdc |
res->sorted_cert_idx[res->ncerts] = res->ncerts;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
finish:
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @cert_list: contains a certificate list (path) for the specified private key
|
|
Packit |
549fdc |
* @cert_list_size: holds the size of the certificate list
|
|
Packit |
549fdc |
* @key: is a #gnutls_x509_privkey_t key
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be
|
|
Packit |
549fdc |
* called more than once, in case multiple keys/certificates exist for
|
|
Packit |
549fdc |
* the server. For clients that wants to send more than their own end
|
|
Packit |
549fdc |
* entity certificate (e.g., also an intermediate CA cert) then put
|
|
Packit |
549fdc |
* the certificate chain in @cert_list.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the certificates and keys provided, can be safely deinitialized
|
|
Packit |
549fdc |
* after this function is called.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If that function fails to load the @res type is at an undefined state, it must
|
|
Packit |
549fdc |
* not be reused to load other keys or certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_x509_crt_t * cert_list,
|
|
Packit |
549fdc |
int cert_list_size,
|
|
Packit |
549fdc |
gnutls_x509_privkey_t key)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_privkey_t pkey;
|
|
Packit |
549fdc |
gnutls_pcert_st *pcerts = NULL;
|
|
Packit |
549fdc |
gnutls_str_array_t names;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_str_array_init(&names);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* this should be first
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret = gnutls_privkey_init(&pkey);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->pin.cb)
|
|
Packit |
549fdc |
gnutls_privkey_set_pin_function(pkey, res->pin.cb,
|
|
Packit |
549fdc |
res->pin.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_privkey_import_x509(pkey, key,
|
|
Packit |
549fdc |
GNUTLS_PRIVKEY_IMPORT_COPY);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* load certificates */
|
|
Packit |
549fdc |
pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size);
|
|
Packit |
549fdc |
if (pcerts == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = get_x509_name(cert_list[0], &names);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_pcert_import_x509_list(pcerts, cert_list, (unsigned int*)&cert_list_size,
|
|
Packit |
549fdc |
GNUTLS_X509_CRT_LIST_SORT);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
certificate_credential_append_crt_list(res, pkey, names, pcerts,
|
|
Packit |
549fdc |
cert_list_size);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->ncerts++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* after this point we do not deinitialize anything on failure to avoid
|
|
Packit |
549fdc |
* double freeing. We intentionally keep everything as the credentials state
|
|
Packit |
549fdc |
* is documented to be on undefined state. */
|
|
Packit |
549fdc |
if ((ret = _gnutls_check_key_cert_match(res)) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CRED_RET_SUCCESS(res);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
gnutls_free(pcerts);
|
|
Packit |
549fdc |
_gnutls_str_array_clear(&names);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_get_x509_key:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @index: The index of the key to obtain.
|
|
Packit |
549fdc |
* @key: Location to store the key.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Obtains a X.509 private key that has been stored in @res with one of
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key(), gnutls_certificate_set_key(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file2(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem(), or
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem2(). The returned key must be deallocated
|
|
Packit |
549fdc |
* with gnutls_x509_privkey_deinit() when no longer needed.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The @index matches the return value of gnutls_certificate_set_x509_key() and friends
|
|
Packit |
549fdc |
* functions, when the %GNUTLS_CERTIFICATE_API_V2 flag is set.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If there is no key with the given index,
|
|
Packit |
549fdc |
* %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. If the key with the
|
|
Packit |
549fdc |
* given index is not a X.509 key, %GNUTLS_E_INVALID_REQUEST is returned.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.4.0
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_get_x509_key(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
unsigned index,
|
|
Packit |
549fdc |
gnutls_x509_privkey_t *key)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (index >= res->ncerts) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return gnutls_privkey_export_x509(res->certs[index].pkey, key);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_get_x509_crt:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @index: The index of the certificate list to obtain.
|
|
Packit |
549fdc |
* @crt_list: Where to store the certificate list.
|
|
Packit |
549fdc |
* @crt_list_size: Will hold the number of certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Obtains a X.509 certificate list that has been stored in @res with one of
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key(), gnutls_certificate_set_key(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file2(),
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem(), or
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_mem2(). Each certificate in the returned
|
|
Packit |
549fdc |
* certificate list must be deallocated with gnutls_x509_crt_deinit(), and the
|
|
Packit |
549fdc |
* list itself must be freed with gnutls_free().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The @index matches the return value of gnutls_certificate_set_x509_key() and friends
|
|
Packit |
549fdc |
* functions, when the %GNUTLS_CERTIFICATE_API_V2 flag is set.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If there is no certificate with the given index,
|
|
Packit |
549fdc |
* %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. If the certificate
|
|
Packit |
549fdc |
* with the given index is not a X.509 certificate, %GNUTLS_E_INVALID_REQUEST
|
|
Packit |
549fdc |
* is returned. The returned certificates must be deinitialized after
|
|
Packit |
549fdc |
* use, and the @crt_list pointer must be freed using gnutls_free().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.4.0
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_get_x509_crt(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
unsigned index,
|
|
Packit |
549fdc |
gnutls_x509_crt_t **crt_list,
|
|
Packit |
549fdc |
unsigned *crt_list_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
unsigned i;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (index >= res->ncerts) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*crt_list_size = res->certs[index].cert_list_length;
|
|
Packit |
549fdc |
*crt_list = gnutls_malloc(
|
|
Packit |
549fdc |
res->certs[index].cert_list_length * sizeof (gnutls_x509_crt_t));
|
|
Packit |
549fdc |
if (*crt_list == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < res->certs[index].cert_list_length; ++i) {
|
|
Packit |
549fdc |
ret = gnutls_pcert_export_x509(&res->certs[index].cert_list[i], &(*crt_list)[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
while (i--)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit((*crt_list)[i]);
|
|
Packit |
549fdc |
gnutls_free(*crt_list);
|
|
Packit |
549fdc |
*crt_list = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_key:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @names: is an array of DNS name of the certificate (NULL if none)
|
|
Packit |
549fdc |
* @names_size: holds the size of the names list
|
|
Packit |
549fdc |
* @pcert_list: contains a certificate list (path) for the specified private key
|
|
Packit |
549fdc |
* @pcert_list_size: holds the size of the certificate list
|
|
Packit |
549fdc |
* @key: is a #gnutls_privkey_t key
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be
|
|
Packit |
549fdc |
* called more than once, in case multiple keys/certificates exist for
|
|
Packit |
549fdc |
* the server. For clients that want to send more than their own end-
|
|
Packit |
549fdc |
* entity certificate (e.g., also an intermediate CA cert), the full
|
|
Packit |
549fdc |
* certificate chain must be provided in @pcert_list.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the @key and the elements of @pcert_list will become part of the credentials
|
|
Packit |
549fdc |
* structure and must not be deallocated. They will be automatically deallocated
|
|
Packit |
549fdc |
* when the @res structure is deinitialized.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If that function fails to load the @res structure is at an undefined state, it must
|
|
Packit |
549fdc |
* not be reused to load other keys or certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_key(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const char **names,
|
|
Packit |
549fdc |
int names_size,
|
|
Packit |
549fdc |
gnutls_pcert_st * pcert_list,
|
|
Packit |
549fdc |
int pcert_list_size, gnutls_privkey_t key)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret, i;
|
|
Packit |
549fdc |
gnutls_str_array_t str_names;
|
|
Packit |
549fdc |
gnutls_pcert_st *new_pcert_list;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_str_array_init(&str_names);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (names != NULL && names_size > 0) {
|
|
Packit |
549fdc |
for (i = 0; i < names_size; i++) {
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
str_array_append_idna(&str_names, names[i],
|
|
Packit |
549fdc |
strlen(names[i]));
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(ret);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else if (names == NULL && pcert_list[0].type == GNUTLS_CRT_X509) {
|
|
Packit |
549fdc |
gnutls_x509_crt_t crt;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_import(crt, &pcert_list[0].cert, GNUTLS_X509_FMT_DER);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = get_x509_name(crt, &str_names);
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->pin.cb)
|
|
Packit |
549fdc |
gnutls_privkey_set_pin_function(key, res->pin.cb,
|
|
Packit |
549fdc |
res->pin.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
new_pcert_list = gnutls_malloc(sizeof(gnutls_pcert_st) * pcert_list_size);
|
|
Packit |
549fdc |
if (new_pcert_list == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
memcpy(new_pcert_list, pcert_list, sizeof(gnutls_pcert_st) * pcert_list_size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
certificate_credential_append_crt_list(res, key, str_names,
|
|
Packit |
549fdc |
new_pcert_list,
|
|
Packit |
549fdc |
pcert_list_size);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_free(new_pcert_list);
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->ncerts++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Unlike gnutls_certificate_set_x509_key, we deinitialize everything
|
|
Packit |
549fdc |
* local after a failure. That is because the caller is responsible for
|
|
Packit |
549fdc |
* freeing these values after a failure, and if we keep references we
|
|
Packit |
549fdc |
* lead to double freeing */
|
|
Packit |
549fdc |
if ((ret = _gnutls_check_key_cert_match(res)) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_free(new_pcert_list);
|
|
Packit |
549fdc |
res->ncerts--;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CRED_RET_SUCCESS(res);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
_gnutls_str_array_clear(&str_names);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_trust_list:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @tlist: is a #gnutls_x509_trust_list_t type
|
|
Packit |
549fdc |
* @flags: must be zero
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a trust list in the gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the @tlist will become part of the credentials
|
|
Packit |
549fdc |
* structure and must not be deallocated. It will be automatically deallocated
|
|
Packit |
549fdc |
* when the @res structure is deinitialized.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.2.2
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_certificate_set_trust_list(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_x509_trust_list_t tlist,
|
|
Packit |
549fdc |
unsigned flags)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_x509_trust_list_deinit(res->tlist, 1);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->tlist = tlist;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_get_trust_list:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @tlist: Location where to store the trust list.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Obtains the list of trusted certificates stored in @res and writes a
|
|
Packit |
549fdc |
* pointer to it to the location @tlist. The pointer will point to memory
|
|
Packit |
549fdc |
* internal to @res, and must not be deinitialized. It will be automatically
|
|
Packit |
549fdc |
* deallocated when the @res structure is deinitialized.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
gnutls_certificate_get_trust_list(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_x509_trust_list_t *tlist)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
*tlist = res->tlist;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @certfile: is a file that containing the certificate list (path) for
|
|
Packit |
549fdc |
* the specified private key, in PKCS7 format, or a list of certificates
|
|
Packit |
549fdc |
* @keyfile: is a file that contains the private key
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be
|
|
Packit |
549fdc |
* called more than once, in case multiple keys/certificates exist for
|
|
Packit |
549fdc |
* the server. For clients that need to send more than its own end
|
|
Packit |
549fdc |
* entity certificate, e.g., also an intermediate CA cert, then the
|
|
Packit |
549fdc |
* @certfile must contain the ordered certificate chain.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the names in the certificate provided will be considered
|
|
Packit |
549fdc |
* when selecting the appropriate certificate to use (in case of multiple
|
|
Packit |
549fdc |
* certificate/key pairs).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function can also accept URLs at @keyfile and @certfile. In that case it
|
|
Packit |
549fdc |
* will use the private key and certificate indicated by the URLs. Note
|
|
Packit |
549fdc |
* that the supported URLs are the ones indicated by gnutls_url_is_supported().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case the @certfile is provided as a PKCS #11 URL, then the certificate, and its
|
|
Packit |
549fdc |
* present issuers in the token are imported (i.e., forming the required trust chain).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If that function fails to load the @res structure is at an undefined state, it must
|
|
Packit |
549fdc |
* not be reused to load other keys or certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.1.11
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key_file(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const char *certfile,
|
|
Packit |
549fdc |
const char *keyfile,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return gnutls_certificate_set_x509_key_file2(res, certfile,
|
|
Packit |
549fdc |
keyfile, type, NULL,
|
|
Packit |
549fdc |
0);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_key_file2:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @certfile: is a file that containing the certificate list (path) for
|
|
Packit |
549fdc |
* the specified private key, in PKCS7 format, or a list of certificates
|
|
Packit |
549fdc |
* @keyfile: is a file that contains the private key
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
* @pass: is the password of the key
|
|
Packit |
549fdc |
* @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair in the
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t type. This function may be
|
|
Packit |
549fdc |
* called more than once, in case multiple keys/certificates exist for
|
|
Packit |
549fdc |
* the server. For clients that need to send more than its own end
|
|
Packit |
549fdc |
* entity certificate, e.g., also an intermediate CA cert, then the
|
|
Packit |
549fdc |
* @certfile must contain the ordered certificate chain.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the names in the certificate provided will be considered
|
|
Packit |
549fdc |
* when selecting the appropriate certificate to use (in case of multiple
|
|
Packit |
549fdc |
* certificate/key pairs).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function can also accept URLs at @keyfile and @certfile. In that case it
|
|
Packit |
549fdc |
* will use the private key and certificate indicated by the URLs. Note
|
|
Packit |
549fdc |
* that the supported URLs are the ones indicated by gnutls_url_is_supported().
|
|
Packit |
549fdc |
* Before GnuTLS 3.4.0 when a URL was specified, the @pass part was ignored and a
|
|
Packit |
549fdc |
* PIN callback had to be registered, this is no longer the case in current releases.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case the @certfile is provided as a PKCS #11 URL, then the certificate, and its
|
|
Packit |
549fdc |
* present issuers in the token are imported (i.e., forming the required trust chain).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If that function fails to load the @res structure is at an undefined state, it must
|
|
Packit |
549fdc |
* not be reused to load other keys or certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key_file2(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const char *certfile,
|
|
Packit |
549fdc |
const char *keyfile,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type,
|
|
Packit |
549fdc |
const char *pass, unsigned int flags)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_privkey_t rkey;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* this should be first
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if ((ret = read_key_file(res, keyfile, type, pass, flags, &rkey)) < 0)
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((ret = read_cert_file(res, rkey, certfile, type)) < 0) {
|
|
Packit |
549fdc |
gnutls_privkey_deinit(rkey);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
res->ncerts++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((ret = _gnutls_check_key_cert_match(res)) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
CRED_RET_SUCCESS(res);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_trust_mem:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @ca: is a list of trusted CAs or a DER certificate
|
|
Packit |
549fdc |
* @type: is DER or PEM
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CAs in order to verify client or
|
|
Packit |
549fdc |
* server certificates. In case of a client this is not required to be
|
|
Packit |
549fdc |
* called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2(). This function may be called
|
|
Packit |
549fdc |
* multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case of a server the CAs set here will be sent to the client if
|
|
Packit |
549fdc |
* a certificate request is sent. This can be disabled using
|
|
Packit |
549fdc |
* gnutls_certificate_send_x509_rdn_sequence().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the number of certificates processed or a negative error code
|
|
Packit |
549fdc |
* on error.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_trust_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const gnutls_datum_t * ca,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_trust_list_add_trust_mem(res->tlist, ca, NULL,
|
|
Packit |
549fdc |
type, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_trust:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @ca_list: is a list of trusted CAs
|
|
Packit |
549fdc |
* @ca_list_size: holds the size of the CA list
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CAs in order to verify client
|
|
Packit |
549fdc |
* or server certificates. In case of a client this is not required
|
|
Packit |
549fdc |
* to be called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2().
|
|
Packit |
549fdc |
* This function may be called multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case of a server the CAs set here will be sent to the client if
|
|
Packit |
549fdc |
* a certificate request is sent. This can be disabled using
|
|
Packit |
549fdc |
* gnutls_certificate_send_x509_rdn_sequence().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the number of certificates processed or a negative error code
|
|
Packit |
549fdc |
* on error.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_trust(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_x509_crt_t * ca_list,
|
|
Packit |
549fdc |
int ca_list_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret, i, j;
|
|
Packit |
549fdc |
gnutls_x509_crt_t new_list[ca_list_size];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < ca_list_size; i++) {
|
|
Packit |
549fdc |
ret = gnutls_x509_crt_init(&new_list[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_x509_crt_cpy(new_list[i], ca_list[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_trust_list_add_cas(res->tlist, new_list,
|
|
Packit |
549fdc |
ca_list_size, GNUTLS_TL_USE_IN_TLS);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
for (j = 0; j < i; j++)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(new_list[j]);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_trust_file:
|
|
Packit |
549fdc |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @cafile: is a file containing the list of trusted CAs (DER or PEM list)
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CAs in order to verify client or
|
|
Packit |
549fdc |
* server certificates. In case of a client this is not required to
|
|
Packit |
549fdc |
* be called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2(). This function may be called
|
|
Packit |
549fdc |
* multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case of a server the names of the CAs set here will be sent to
|
|
Packit |
549fdc |
* the client if a certificate request is sent. This can be disabled
|
|
Packit |
549fdc |
* using gnutls_certificate_send_x509_rdn_sequence().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function can also accept URLs. In that case it
|
|
Packit |
549fdc |
* will import all certificates that are marked as trusted. Note
|
|
Packit |
549fdc |
* that the supported URLs are the ones indicated by gnutls_url_is_supported().
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the number of certificates processed
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_trust_file(gnutls_certificate_credentials_t
|
|
Packit |
549fdc |
cred, const char *cafile,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_trust_list_add_trust_file(cred->tlist, cafile, NULL,
|
|
Packit |
549fdc |
type, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_trust_dir:
|
|
Packit |
549fdc |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @ca_dir: is a directory containing the list of trusted CAs (DER or PEM list)
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CAs present in the directory in order to
|
|
Packit |
549fdc |
* verify client or server certificates. This function is identical
|
|
Packit |
549fdc |
* to gnutls_certificate_set_x509_trust_file() but loads all certificates
|
|
Packit |
549fdc |
* in a directory.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the number of certificates processed
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.3.6
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_trust_dir(gnutls_certificate_credentials_t cred,
|
|
Packit |
549fdc |
const char *ca_dir,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_trust_list_add_trust_dir(cred->tlist, ca_dir, NULL,
|
|
Packit |
549fdc |
type, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_system_trust:
|
|
Packit |
549fdc |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the system's default trusted CAs in order to
|
|
Packit |
549fdc |
* verify client or server certificates.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In the case the system is currently unsupported %GNUTLS_E_UNIMPLEMENTED_FEATURE
|
|
Packit |
549fdc |
* is returned.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: the number of certificates processed or a negative error code
|
|
Packit |
549fdc |
* on error.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.0.20
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_system_trust(gnutls_certificate_credentials_t
|
|
Packit |
549fdc |
cred)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return gnutls_x509_trust_list_add_system_trust(cred->tlist,
|
|
Packit |
549fdc |
GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_crl_mem:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @CRL: is a list of trusted CRLs. They should have been verified before.
|
|
Packit |
549fdc |
* @type: is DER or PEM
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CRLs in order to verify client or
|
|
Packit |
549fdc |
* server certificates. In case of a client this is not required to
|
|
Packit |
549fdc |
* be called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2(). This function may be called
|
|
Packit |
549fdc |
* multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: number of CRLs processed, or a negative error code on error.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_crl_mem(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const gnutls_datum_t * CRL,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_trust_list_add_trust_mem(res->tlist, NULL, CRL,
|
|
Packit |
549fdc |
type, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_crl:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @crl_list: is a list of trusted CRLs. They should have been verified before.
|
|
Packit |
549fdc |
* @crl_list_size: holds the size of the crl_list
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CRLs in order to verify client or
|
|
Packit |
549fdc |
* server certificates. In case of a client this is not required to
|
|
Packit |
549fdc |
* be called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2(). This function may be called
|
|
Packit |
549fdc |
* multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: number of CRLs processed, or a negative error code on error.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_crl(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
gnutls_x509_crl_t * crl_list,
|
|
Packit |
549fdc |
int crl_list_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret, i, j;
|
|
Packit |
549fdc |
gnutls_x509_crl_t new_crl[crl_list_size];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < crl_list_size; i++) {
|
|
Packit |
549fdc |
ret = gnutls_x509_crl_init(&new_crl[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_x509_crl_cpy(new_crl[i], crl_list[i]);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_x509_trust_list_add_crls(res->tlist, new_crl,
|
|
Packit |
549fdc |
crl_list_size, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
for (j = 0; j < i; j++)
|
|
Packit |
549fdc |
gnutls_x509_crl_deinit(new_crl[j]);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_crl_file:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @crlfile: is a file containing the list of verified CRLs (DER or PEM list)
|
|
Packit |
549fdc |
* @type: is PEM or DER
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function adds the trusted CRLs in order to verify client or server
|
|
Packit |
549fdc |
* certificates. In case of a client this is not required
|
|
Packit |
549fdc |
* to be called if the certificates are not verified using
|
|
Packit |
549fdc |
* gnutls_certificate_verify_peers2().
|
|
Packit |
549fdc |
* This function may be called multiple times.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: number of CRLs processed or a negative error code on error.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_crl_file(gnutls_certificate_credentials_t res,
|
|
Packit |
549fdc |
const char *crlfile,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_x509_trust_list_add_trust_file(res->tlist, NULL, crlfile,
|
|
Packit |
549fdc |
type, GNUTLS_TL_USE_IN_TLS, 0);
|
|
Packit |
549fdc |
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include <gnutls/pkcs12.h>
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_simple_pkcs12_file:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @pkcs12file: filename of file containing PKCS#12 blob.
|
|
Packit |
549fdc |
* @type: is PEM or DER of the @pkcs12file.
|
|
Packit |
549fdc |
* @password: optional password used to decrypt PKCS#12 file, bags and keys.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair and/or a CRL in
|
|
Packit |
549fdc |
* the gnutls_certificate_credentials_t type. This function may
|
|
Packit |
549fdc |
* be called more than once (in case multiple keys/certificates exist
|
|
Packit |
549fdc |
* for the server).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* PKCS#12 files with a MAC, encrypted bags and PKCS #8
|
|
Packit |
549fdc |
* private keys are supported. However,
|
|
Packit |
549fdc |
* only password based security, and the same password for all
|
|
Packit |
549fdc |
* operations, are supported.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* PKCS#12 file may contain many keys and/or certificates, and this
|
|
Packit |
549fdc |
* function will try to auto-detect based on the key ID the certificate
|
|
Packit |
549fdc |
* and key pair to use. If the PKCS#12 file contain the issuer of
|
|
Packit |
549fdc |
* the selected certificate, it will be appended to the certificate
|
|
Packit |
549fdc |
* to form a chain.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If more than one private keys are stored in the PKCS#12 file,
|
|
Packit |
549fdc |
* then only one key will be read (and it is undefined which one).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* It is believed that the limitations of this function is acceptable
|
|
Packit |
549fdc |
* for most usage, and that any more flexibility would introduce
|
|
Packit |
549fdc |
* complexity that would make it harder to use this functionality at
|
|
Packit |
549fdc |
* all.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_simple_pkcs12_file
|
|
Packit |
549fdc |
(gnutls_certificate_credentials_t res, const char *pkcs12file,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type, const char *password) {
|
|
Packit |
549fdc |
gnutls_datum_t p12blob;
|
|
Packit |
549fdc |
size_t size;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p12blob.data = (void *) read_binary_file(pkcs12file, &size);
|
|
Packit |
549fdc |
p12blob.size = (unsigned int) size;
|
|
Packit |
549fdc |
if (p12blob.data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_FILE_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_simple_pkcs12_mem(res, &p12blob,
|
|
Packit |
549fdc |
type, password);
|
|
Packit |
549fdc |
free(p12blob.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_set_x509_simple_pkcs12_mem:
|
|
Packit |
549fdc |
* @res: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @p12blob: the PKCS#12 blob.
|
|
Packit |
549fdc |
* @type: is PEM or DER of the @pkcs12file.
|
|
Packit |
549fdc |
* @password: optional password used to decrypt PKCS#12 file, bags and keys.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function sets a certificate/private key pair and/or a CRL in
|
|
Packit |
549fdc |
* the gnutls_certificate_credentials_t type. This function may
|
|
Packit |
549fdc |
* be called more than once (in case multiple keys/certificates exist
|
|
Packit |
549fdc |
* for the server).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However,
|
|
Packit |
549fdc |
* only password based security, and the same password for all
|
|
Packit |
549fdc |
* operations, are supported.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* PKCS#12 file may contain many keys and/or certificates, and this
|
|
Packit |
549fdc |
* function will try to auto-detect based on the key ID the certificate
|
|
Packit |
549fdc |
* and key pair to use. If the PKCS#12 file contain the issuer of
|
|
Packit |
549fdc |
* the selected certificate, it will be appended to the certificate
|
|
Packit |
549fdc |
* to form a chain.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If more than one private keys are stored in the PKCS#12 file,
|
|
Packit |
549fdc |
* then only one key will be read (and it is undefined which one).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* It is believed that the limitations of this function is acceptable
|
|
Packit |
549fdc |
* for most usage, and that any more flexibility would introduce
|
|
Packit |
549fdc |
* complexity that would make it harder to use this functionality at
|
|
Packit |
549fdc |
* all.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that, this function by default returns zero on success and a negative value on error.
|
|
Packit |
549fdc |
* Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
|
|
Packit |
549fdc |
* it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.8.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_simple_pkcs12_mem
|
|
Packit |
549fdc |
(gnutls_certificate_credentials_t res, const gnutls_datum_t * p12blob,
|
|
Packit |
549fdc |
gnutls_x509_crt_fmt_t type, const char *password) {
|
|
Packit |
549fdc |
gnutls_pkcs12_t p12;
|
|
Packit |
549fdc |
gnutls_x509_privkey_t key = NULL;
|
|
Packit |
549fdc |
gnutls_x509_crt_t *chain = NULL;
|
|
Packit |
549fdc |
gnutls_x509_crl_t crl = NULL;
|
|
Packit |
549fdc |
unsigned int chain_size = 0, i;
|
|
Packit |
549fdc |
int ret, idx;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_pkcs12_init(&p12);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_pkcs12_import(p12, p12blob, type, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_pkcs12_deinit(p12);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (password) {
|
|
Packit |
549fdc |
ret = gnutls_pkcs12_verify_mac(p12, password);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_pkcs12_deinit(p12);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_pkcs12_simple_parse(p12, password, &key, &chain,
|
|
Packit |
549fdc |
&chain_size, NULL, NULL, &crl, 0);
|
|
Packit |
549fdc |
gnutls_pkcs12_deinit(p12);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (key && chain) {
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
gnutls_certificate_set_x509_key(res, chain, chain_size,
|
|
Packit |
549fdc |
key);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto done;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
idx = ret;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
goto done;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (crl) {
|
|
Packit |
549fdc |
ret = gnutls_certificate_set_x509_crl(res, &crl, 1);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto done;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (res->flags & GNUTLS_CERTIFICATE_API_V2)
|
|
Packit |
549fdc |
ret = idx;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
done:
|
|
Packit |
549fdc |
if (chain) {
|
|
Packit |
549fdc |
for (i = 0; i < chain_size; i++)
|
|
Packit |
549fdc |
gnutls_x509_crt_deinit(chain[i]);
|
|
Packit |
549fdc |
gnutls_free(chain);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (key)
|
|
Packit |
549fdc |
gnutls_x509_privkey_deinit(key);
|
|
Packit |
549fdc |
if (crl)
|
|
Packit |
549fdc |
gnutls_x509_crl_deinit(crl);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_free_crls:
|
|
Packit |
549fdc |
* @sc: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will delete all the CRLs associated
|
|
Packit |
549fdc |
* with the given credentials.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void gnutls_certificate_free_crls(gnutls_certificate_credentials_t sc)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
/* do nothing for now */
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_certificate_credentials_t:
|
|
Packit |
549fdc |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
549fdc |
* @fn: A PIN callback
|
|
Packit |
549fdc |
* @userdata: Data to be passed in the callback
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will set a callback function to be used when
|
|
Packit |
549fdc |
* required to access a protected object. This function overrides any other
|
|
Packit |
549fdc |
* global PIN functions.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that this function must be called right after initialization
|
|
Packit |
549fdc |
* to have effect.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.1.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
void gnutls_certificate_set_pin_function(gnutls_certificate_credentials_t
|
|
Packit |
549fdc |
cred, gnutls_pin_callback_t fn,
|
|
Packit |
549fdc |
void *userdata)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
cred->pin.cb = fn;
|
|
Packit |
549fdc |
cred->pin.data = userdata;
|
|
Packit |
549fdc |
}
|