|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Copyright (C) 2017 - 2018 ARPA2 project
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Author: Tom Vrancken (dev@tomvrancken.nl)
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This file is part of GnuTLS.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
aea12f |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
aea12f |
* the License, or (at your option) any later version.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
aea12f |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aea12f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aea12f |
* Lesser General Public License for more details.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
#include <gnutls/gnutls.h>
|
|
Packit |
aea12f |
#include "datum.h"
|
|
Packit |
aea12f |
#include "auth/cert.h"
|
|
Packit |
aea12f |
#include "x509.h"
|
|
Packit |
aea12f |
#include "cert-cred.h"
|
|
Packit |
aea12f |
#include "read-file.h"
|
|
Packit |
aea12f |
#include <stdint.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_certificate_set_rawpk_key_mem:
|
|
Packit |
aea12f |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
aea12f |
* @spki: contains a raw public key in
|
|
Packit |
aea12f |
* PKIX.SubjectPublicKeyInfo format.
|
|
Packit |
aea12f |
* @pkey: contains a raw private key.
|
|
Packit |
aea12f |
* @format: encoding of the keys. DER or PEM.
|
|
Packit |
aea12f |
* @pass: an optional password to unlock the private key pkey.
|
|
Packit |
aea12f |
* @key_usage: An ORed sequence of %GNUTLS_KEY_* flags.
|
|
Packit |
aea12f |
* @names: is an array of DNS names belonging to the public-key (NULL if none).
|
|
Packit |
aea12f |
* @names_length: holds the length of the names list.
|
|
Packit |
aea12f |
* @flags: an ORed sequence of #gnutls_pkcs_encrypt_flags_t.
|
|
Packit |
aea12f |
* These apply to the private key pkey.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function sets a public/private keypair in the
|
|
Packit |
aea12f |
* #gnutls_certificate_credentials_t type to be used for authentication
|
|
Packit |
aea12f |
* and/or encryption. @spki and @privkey should match otherwise set
|
|
Packit |
aea12f |
* signatures cannot be validated. In case of no match this function
|
|
Packit |
aea12f |
* returns %GNUTLS_E_CERTIFICATE_KEY_MISMATCH. This function should
|
|
Packit |
aea12f |
* be called once for the client because there is currently no mechanism
|
|
Packit |
aea12f |
* to determine which raw public-key to select for the peer when there
|
|
Packit |
aea12f |
* are multiple present. Multiple raw public keys for the server can be
|
|
Packit |
aea12f |
* distinghuished by setting the @names.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note here that @spki is a raw public-key as defined
|
|
Packit |
aea12f |
* in RFC7250. It means that there is no surrounding certificate that
|
|
Packit |
aea12f |
* holds the public key and that there is therefore no direct mechanism
|
|
Packit |
aea12f |
* to prove the authenticity of this key. The keypair can be used during
|
|
Packit |
aea12f |
* a TLS handshake but its authenticity should be established via a
|
|
Packit |
aea12f |
* different mechanism (e.g. TOFU or known fingerprint).
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The supported formats are basic unencrypted key, PKCS8, PKCS12,
|
|
Packit |
aea12f |
* and the openssl format and will be autodetected.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If the raw public-key and the private key are given in PEM encoding
|
|
Packit |
aea12f |
* then the strings that hold their values must be null terminated.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Key usage (as defined by X.509 extension (2.5.29.15)) can be explicitly
|
|
Packit |
aea12f |
* set because there is no certificate structure around the key to define
|
|
Packit |
aea12f |
* this value. See for more info gnutls_x509_crt_get_key_usage().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note that, this function by default returns zero on success and a
|
|
Packit |
aea12f |
* negative value on error. Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2
|
|
Packit |
aea12f |
* is set using gnutls_certificate_set_flags() it returns an index
|
|
Packit |
aea12f |
* (greater or equal to zero). That index can be used in other functions
|
|
Packit |
aea12f |
* to refer to the added key-pair.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, in case the
|
|
Packit |
aea12f |
* key pair does not match %GNUTLS_E_CERTIFICATE_KEY_MISMATCH is returned,
|
|
Packit |
aea12f |
* in other erroneous cases a different negative error code is returned.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.6.6
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int gnutls_certificate_set_rawpk_key_mem(gnutls_certificate_credentials_t cred,
|
|
Packit |
aea12f |
const gnutls_datum_t* spki,
|
|
Packit |
aea12f |
const gnutls_datum_t* pkey,
|
|
Packit |
aea12f |
gnutls_x509_crt_fmt_t format,
|
|
Packit |
aea12f |
const char* pass,
|
|
Packit |
aea12f |
unsigned int key_usage,
|
|
Packit |
aea12f |
const char **names,
|
|
Packit |
aea12f |
unsigned int names_length,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
gnutls_privkey_t privkey;
|
|
Packit |
aea12f |
gnutls_pcert_st* pcert;
|
|
Packit |
aea12f |
gnutls_str_array_t str_names;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (pkey == NULL || spki == NULL) {
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Import our private key. This function does all the necessary
|
|
Packit |
aea12f |
* inits, checks and imports. */
|
|
Packit |
aea12f |
ret = _gnutls_read_key_mem(cred, pkey->data, pkey->size,
|
|
Packit |
aea12f |
format, pass, flags, &privkey);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* We now convert our raw public key to a parsed certificate (pcert) structure */
|
|
Packit |
aea12f |
pcert = gnutls_calloc(1, sizeof(*pcert));
|
|
Packit |
aea12f |
if (pcert == NULL) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
// Import our raw public key to the pcert structure
|
|
Packit |
aea12f |
ret = gnutls_pcert_import_rawpk_raw(pcert, spki,
|
|
Packit |
aea12f |
format, key_usage, 0);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Process the names, if any */
|
|
Packit |
aea12f |
_gnutls_str_array_init(&str_names);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (names != NULL && names_length > 0) {
|
|
Packit |
aea12f |
for (i = 0; i < names_length; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_str_array_append_idna(&str_names, names[i],
|
|
Packit |
aea12f |
strlen(names[i]));
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
_gnutls_str_array_clear(&str_names);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Now that we have converted the key material to our internal structures
|
|
Packit |
aea12f |
* we can now add them to the credentials structure */
|
|
Packit |
aea12f |
ret = _gnutls_certificate_credential_append_keypair(cred, privkey, str_names, pcert, 1);
|
|
Packit |
aea12f |
// Check for errors
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
gnutls_pcert_deinit(pcert);
|
|
Packit |
aea12f |
gnutls_free(pcert);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
// Successfully added a certificate
|
|
Packit |
aea12f |
cred->ncerts++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Check whether the key pair matches.
|
|
Packit |
aea12f |
* After this point we do not deinitialize anything on failure to avoid
|
|
Packit |
aea12f |
* double freeing. We intentionally keep everything as the credentials state
|
|
Packit |
aea12f |
* is documented to be in undefined state. */
|
|
Packit |
aea12f |
if ((ret = _gnutls_check_key_cert_match(cred)) < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
CRED_RET_SUCCESS(cred);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_certificate_set_rawpk_key_file:
|
|
Packit |
aea12f |
* @cred: is a #gnutls_certificate_credentials_t type.
|
|
Packit |
aea12f |
* @rawpkfile: contains a raw public key in
|
|
Packit |
aea12f |
* PKIX.SubjectPublicKeyInfo format.
|
|
Packit |
aea12f |
* @privkeyfile: contains a file path to a private key.
|
|
Packit |
aea12f |
* @format: encoding of the keys. DER or PEM.
|
|
Packit |
aea12f |
* @pass: an optional password to unlock the private key privkeyfile.
|
|
Packit |
aea12f |
* @key_usage: an ORed sequence of %GNUTLS_KEY_* flags.
|
|
Packit |
aea12f |
* @names: is an array of DNS names belonging to the public-key (NULL if none).
|
|
Packit |
aea12f |
* @names_length: holds the length of the names list.
|
|
Packit |
aea12f |
* @privkey_flags: an ORed sequence of #gnutls_pkcs_encrypt_flags_t.
|
|
Packit |
aea12f |
* These apply to the private key pkey.
|
|
Packit |
aea12f |
* @pkcs11_flags: one of gnutls_pkcs11_obj_flags. These apply to URLs.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function sets a public/private keypair read from file in the
|
|
Packit |
aea12f |
* #gnutls_certificate_credentials_t type to be used for authentication
|
|
Packit |
aea12f |
* and/or encryption. @spki and @privkey should match otherwise set
|
|
Packit |
aea12f |
* signatures cannot be validated. In case of no match this function
|
|
Packit |
aea12f |
* returns %GNUTLS_E_CERTIFICATE_KEY_MISMATCH. This function should
|
|
Packit |
aea12f |
* be called once for the client because there is currently no mechanism
|
|
Packit |
aea12f |
* to determine which raw public-key to select for the peer when there
|
|
Packit |
aea12f |
* are multiple present. Multiple raw public keys for the server can be
|
|
Packit |
aea12f |
* distinghuished by setting the @names.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note here that @spki is a raw public-key as defined
|
|
Packit |
aea12f |
* in RFC7250. It means that there is no surrounding certificate that
|
|
Packit |
aea12f |
* holds the public key and that there is therefore no direct mechanism
|
|
Packit |
aea12f |
* to prove the authenticity of this key. The keypair can be used during
|
|
Packit |
aea12f |
* a TLS handshake but its authenticity should be established via a
|
|
Packit |
aea12f |
* different mechanism (e.g. TOFU or known fingerprint).
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The supported formats are basic unencrypted key, PKCS8, PKCS12,
|
|
Packit |
aea12f |
* and the openssl format and will be autodetected.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If the raw public-key and the private key are given in PEM encoding
|
|
Packit |
aea12f |
* then the strings that hold their values must be null terminated.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Key usage (as defined by X.509 extension (2.5.29.15)) can be explicitly
|
|
Packit |
aea12f |
* set because there is no certificate structure around the key to define
|
|
Packit |
aea12f |
* this value. See for more info gnutls_x509_crt_get_key_usage().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note that, this function by default returns zero on success and a
|
|
Packit |
aea12f |
* negative value on error. Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2
|
|
Packit |
aea12f |
* is set using gnutls_certificate_set_flags() it returns an index
|
|
Packit |
aea12f |
* (greater or equal to zero). That index can be used in other functions
|
|
Packit |
aea12f |
* to refer to the added key-pair.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, in case the
|
|
Packit |
aea12f |
* key pair does not match %GNUTLS_E_CERTIFICATE_KEY_MISMATCH is returned,
|
|
Packit |
aea12f |
* in other erroneous cases a different negative error code is returned.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.6.6
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
int gnutls_certificate_set_rawpk_key_file(gnutls_certificate_credentials_t cred,
|
|
Packit |
aea12f |
const char* rawpkfile,
|
|
Packit |
aea12f |
const char* privkeyfile,
|
|
Packit |
aea12f |
gnutls_x509_crt_fmt_t format,
|
|
Packit |
aea12f |
const char *pass,
|
|
Packit |
aea12f |
unsigned int key_usage,
|
|
Packit |
aea12f |
const char **names,
|
|
Packit |
aea12f |
unsigned int names_length,
|
|
Packit |
aea12f |
unsigned int privkey_flags,
|
|
Packit |
aea12f |
unsigned int pkcs11_flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
gnutls_privkey_t privkey;
|
|
Packit |
aea12f |
gnutls_pubkey_t pubkey;
|
|
Packit |
aea12f |
gnutls_pcert_st* pcert;
|
|
Packit |
aea12f |
gnutls_str_array_t str_names;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (rawpkfile == NULL || privkeyfile == NULL) {
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Import our private key. This function does all the necessary
|
|
Packit |
aea12f |
* inits, checks and imports. */
|
|
Packit |
aea12f |
ret = _gnutls_read_key_file(cred, privkeyfile, format, pass, privkey_flags, &privkey);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pcert = gnutls_calloc(1, sizeof(*pcert));
|
|
Packit |
aea12f |
if (pcert == NULL) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Check whether we are importing our raw public-key from a URL
|
|
Packit |
aea12f |
* or from a regular file.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
if (gnutls_url_is_supported(rawpkfile)) {
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_pubkey_init(&pubkey);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_pubkey_import_url(pubkey, rawpkfile, pkcs11_flags);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
gnutls_pubkey_deinit(pubkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_pcert_import_rawpk(pcert, pubkey, 0);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
gnutls_pubkey_deinit(pubkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else {
|
|
Packit Service |
991b93 |
gnutls_datum_t rawpubkey; // to hold rawpk data from file
|
|
Packit Service |
991b93 |
size_t key_size;
|
|
Packit Service |
991b93 |
|
|
Packit |
aea12f |
/* Read our raw public-key into memory from file */
|
|
Packit Service |
991b93 |
rawpubkey.data = (void*) read_file(rawpkfile,
|
|
Packit Service |
991b93 |
RF_BINARY | RF_SENSITIVE,
|
|
Packit Service |
991b93 |
&key_size);
|
|
Packit |
aea12f |
if (rawpubkey.data == NULL) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
rawpubkey.size = key_size; // Implicit type casting
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* We now convert our raw public key that we've loaded into memory to
|
|
Packit |
aea12f |
* a parsed certificate (pcert) structure. Note that rawpubkey will
|
|
Packit |
aea12f |
* be copied into pcert. Therefore we can directly cleanup rawpubkey.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret = gnutls_pcert_import_rawpk_raw(pcert, &rawpubkey,
|
|
Packit |
aea12f |
format, key_usage, 0);
|
|
Packit |
aea12f |
|
|
Packit Service |
991b93 |
zeroize_key(rawpubkey.data, rawpubkey.size);
|
|
Packit Service |
991b93 |
free(rawpubkey.data);
|
|
Packit Service |
991b93 |
rawpubkey.size = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Process the names, if any */
|
|
Packit |
aea12f |
_gnutls_str_array_init(&str_names);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (names != NULL && names_length > 0) {
|
|
Packit |
aea12f |
for (i = 0; i < names_length; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_str_array_append_idna(&str_names, names[i],
|
|
Packit |
aea12f |
strlen(names[i]));
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
_gnutls_str_array_clear(&str_names);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Now that we have converted the key material to our internal structures
|
|
Packit |
aea12f |
* we can now add them to the credentials structure */
|
|
Packit |
aea12f |
ret = _gnutls_certificate_credential_append_keypair(cred, privkey, str_names, pcert, 1);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_privkey_deinit(privkey);
|
|
Packit |
aea12f |
gnutls_pcert_deinit(pcert);
|
|
Packit |
aea12f |
gnutls_free(pcert);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
// Successfully added a certificate
|
|
Packit |
aea12f |
cred->ncerts++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Check whether the key pair matches.
|
|
Packit |
aea12f |
* After this point we do not deinitialize anything on failure to avoid
|
|
Packit |
aea12f |
* double freeing. We intentionally keep everything as the credentials state
|
|
Packit |
aea12f |
* is documented to be in undefined state. */
|
|
Packit |
aea12f |
if ((ret = _gnutls_check_key_cert_match(cred)) < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
CRED_RET_SUCCESS(cred);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|