Blame lib/privkey.c

Packit 549fdc
/*
Packit 549fdc
 * GnuTLS PKCS#11 support
Packit 549fdc
 * Copyright (C) 2010-2014 Free Software Foundation, Inc.
Packit 549fdc
 * Copyright (C) 2012-2015 Nikos Mavrogiannopoulos
Packit 549fdc
 * Copyright (C) 2016-2017 Red Hat, Inc.
Packit 549fdc
 * 
Packit 549fdc
 * Author: Nikos Mavrogiannopoulos
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
#include "gnutls_int.h"
Packit 549fdc
#include <gnutls/pkcs11.h>
Packit 549fdc
#include <stdio.h>
Packit 549fdc
#include <string.h>
Packit 549fdc
#include "errors.h"
Packit 549fdc
#include <datum.h>
Packit 549fdc
#include <pkcs11_int.h>
Packit 549fdc
#include <gnutls/abstract.h>
Packit 549fdc
#include <pk.h>
Packit 549fdc
#include <x509_int.h>
Packit 549fdc
#include <tls-sig.h>
Packit 549fdc
#include <algorithms.h>
Packit 549fdc
#include <fips.h>
Packit 549fdc
#include <system-keys.h>
Packit 549fdc
#include "urls.h"
Packit 549fdc
#include "pkcs11_int.h"
Packit 549fdc
#include <abstract_int.h>
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
privkey_sign_prehashed(gnutls_privkey_t signer,
Packit 549fdc
		       const gnutls_sign_entry_st *se,
Packit 549fdc
		       const gnutls_datum_t * hash_data,
Packit 549fdc
		       gnutls_datum_t * signature,
Packit 549fdc
		       gnutls_x509_spki_st * params, unsigned flags);
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_get_type:
Packit 549fdc
 * @key: should contain a #gnutls_privkey_t type
Packit 549fdc
 *
Packit 549fdc
 * This function will return the type of the private key. This is
Packit 549fdc
 * actually the type of the subsystem used to set this private key.
Packit 549fdc
 *
Packit 549fdc
 * Returns: a member of the #gnutls_privkey_type_t enumeration on
Packit 549fdc
 *   success, or a negative error code on error.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
gnutls_privkey_type_t gnutls_privkey_get_type(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	return key->type;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_get_seed:
Packit 549fdc
 * @key: should contain a #gnutls_privkey_t type
Packit 549fdc
 * @digest: if non-NULL it will contain the digest algorithm used for key generation (if applicable)
Packit 549fdc
 * @seed: where seed will be copied to
Packit 549fdc
 * @seed_size: originally holds the size of @seed, will be updated with actual size
Packit 549fdc
 *
Packit 549fdc
 * This function will return the seed that was used to generate the
Packit 549fdc
 * given private key. That function will succeed only if the key was generated
Packit 549fdc
 * as a provable key.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.5.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_get_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t *digest, void *seed, size_t *seed_size)
Packit 549fdc
{
Packit 549fdc
	if (key->type != GNUTLS_PRIVKEY_X509)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
	return gnutls_x509_privkey_get_seed(key->key.x509, digest, seed, seed_size);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_verify_seed:
Packit 549fdc
 * @key: should contain a #gnutls_privkey_t type
Packit 549fdc
 * @digest: it contains the digest algorithm used for key generation (if applicable)
Packit 549fdc
 * @seed: the seed of the key to be checked with
Packit 549fdc
 * @seed_size: holds the size of @seed
Packit 549fdc
 *
Packit 549fdc
 * This function will verify that the given private key was generated from
Packit 549fdc
 * the provided seed.
Packit 549fdc
 *
Packit 549fdc
 * Returns: In case of a verification failure %GNUTLS_E_PRIVKEY_VERIFICATION_ERROR
Packit 549fdc
 * is returned, and zero or positive code on success.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.5.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_verify_seed(gnutls_privkey_t key, gnutls_digest_algorithm_t digest, const void *seed, size_t seed_size)
Packit 549fdc
{
Packit 549fdc
	if (key->type != GNUTLS_PRIVKEY_X509)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
	return gnutls_x509_privkey_verify_seed(key->key.x509, digest, seed, seed_size);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_get_pk_algorithm:
Packit 549fdc
 * @key: should contain a #gnutls_privkey_t type
Packit 549fdc
 * @bits: If set will return the number of bits of the parameters (may be NULL)
Packit 549fdc
 *
Packit 549fdc
 * This function will return the public key algorithm of a private
Packit 549fdc
 * key and if possible will return a number of bits that indicates
Packit 549fdc
 * the security parameter of the key.
Packit 549fdc
 *
Packit 549fdc
 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
Packit 549fdc
 *   success, or a negative error code on error.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_get_pk_algorithm(gnutls_privkey_t key, unsigned int *bits)
Packit 549fdc
{
Packit 549fdc
	switch (key->type) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
		return gnutls_pkcs11_privkey_get_pk_algorithm(key->key.pkcs11,
Packit 549fdc
							      bits);
Packit 549fdc
#endif
Packit 549fdc
	case GNUTLS_PRIVKEY_X509:
Packit 549fdc
		if (bits) {
Packit 549fdc
			*bits = pubkey_to_bits(&key->key.x509->params);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		return gnutls_x509_privkey_get_pk_algorithm(key->key.x509);
Packit 549fdc
	case GNUTLS_PRIVKEY_EXT:
Packit 549fdc
		if (bits)
Packit 549fdc
			*bits = 0;
Packit 549fdc
		return key->pk_algorithm;
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
privkey_to_pubkey(gnutls_pk_algorithm_t pk,
Packit 549fdc
		  const gnutls_pk_params_st * priv, gnutls_pk_params_st * pub)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	pub->algo = priv->algo;
Packit 549fdc
	pub->pkflags = priv->pkflags;
Packit 549fdc
	pub->curve = priv->curve;
Packit 549fdc
	pub->qbits = priv->qbits;
Packit 549fdc
	memcpy(&pub->spki, &priv->spki, sizeof(gnutls_x509_spki_st));
Packit 549fdc
Packit 549fdc
	switch (pk) {
Packit 549fdc
	case GNUTLS_PK_RSA_PSS:
Packit 549fdc
	case GNUTLS_PK_RSA:
Packit 549fdc
		pub->params[0] = _gnutls_mpi_copy(priv->params[0]);
Packit 549fdc
		pub->params[1] = _gnutls_mpi_copy(priv->params[1]);
Packit 549fdc
Packit 549fdc
		pub->params_nr = RSA_PUBLIC_PARAMS;
Packit 549fdc
Packit 549fdc
		if (pub->params[0] == NULL || pub->params[1] == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_PK_DSA:
Packit 549fdc
		pub->params[0] = _gnutls_mpi_copy(priv->params[0]);
Packit 549fdc
		pub->params[1] = _gnutls_mpi_copy(priv->params[1]);
Packit 549fdc
		pub->params[2] = _gnutls_mpi_copy(priv->params[2]);
Packit 549fdc
		pub->params[3] = _gnutls_mpi_copy(priv->params[3]);
Packit 549fdc
Packit 549fdc
		pub->params_nr = DSA_PUBLIC_PARAMS;
Packit 549fdc
Packit 549fdc
		if (pub->params[0] == NULL || pub->params[1] == NULL ||
Packit 549fdc
		    pub->params[2] == NULL || pub->params[3] == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_PK_ECDSA:
Packit 549fdc
		pub->params[ECC_X] = _gnutls_mpi_copy(priv->params[ECC_X]);
Packit 549fdc
		pub->params[ECC_Y] = _gnutls_mpi_copy(priv->params[ECC_Y]);
Packit 549fdc
Packit 549fdc
		pub->params_nr = ECC_PUBLIC_PARAMS;
Packit 549fdc
Packit 549fdc
		if (pub->params[ECC_X] == NULL || pub->params[ECC_Y] == NULL) {
Packit 549fdc
			gnutls_assert();
Packit 549fdc
			ret = GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
			goto cleanup;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_PK_EDDSA_ED25519:
Packit 549fdc
		ret = _gnutls_set_datum(&pub->raw_pub, priv->raw_pub.data, priv->raw_pub.size);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
 cleanup:
Packit 549fdc
	gnutls_pk_params_release(pub);
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Returns the public key of the private key (if possible)
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_privkey_get_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	switch (key->type) {
Packit 549fdc
	case GNUTLS_PRIVKEY_X509:
Packit 549fdc
		ret = _gnutls_pk_params_copy(params, &key->key.x509->params);
Packit 549fdc
		break;
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11: {
Packit 549fdc
		gnutls_pubkey_t pubkey;
Packit 549fdc
Packit 549fdc
		ret = _pkcs11_privkey_get_pubkey(key->key.pkcs11, &pubkey, 0);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		ret = _gnutls_pubkey_get_mpis(pubkey, params);
Packit 549fdc
		gnutls_pubkey_deinit(pubkey);
Packit 549fdc
Packit 549fdc
		break;
Packit 549fdc
		}
Packit 549fdc
#endif
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
_gnutls_privkey_get_public_mpis(gnutls_privkey_t key,
Packit 549fdc
				gnutls_pk_params_st * params)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_pk_params_st tmp1;
Packit 549fdc
Packit 549fdc
	gnutls_pk_params_init(&tmp1);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_mpis(key, &tmp1);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = privkey_to_pubkey(key->pk_algorithm, &tmp1, params);
Packit 549fdc
Packit 549fdc
	gnutls_pk_params_release(&tmp1);
Packit 549fdc
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		gnutls_assert();
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function retrieves default sign parameters from KEY. */
Packit 549fdc
int
Packit 549fdc
_gnutls_privkey_get_spki_params(gnutls_privkey_t key,
Packit 549fdc
				gnutls_x509_spki_st * params)
Packit 549fdc
{
Packit 549fdc
	switch (key->type) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
		break;
Packit 549fdc
#endif
Packit 549fdc
	case GNUTLS_PRIVKEY_EXT:
Packit 549fdc
		break;
Packit 549fdc
	case GNUTLS_PRIVKEY_X509:
Packit 549fdc
		_gnutls_x509_privkey_get_spki_params(key->key.x509, params);
Packit 549fdc
		return 0;
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	memset(params, 0, sizeof(gnutls_x509_spki_st));
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* This function fills in PARAMS with the necessary parameters to sign
Packit 549fdc
 * with PK and DIG. PARAMS must be initialized with
Packit 549fdc
 * _gnutls_privkey_get_spki_params in advance.
Packit 549fdc
 *
Packit 549fdc
 * After calling this function the params structure will
Packit 549fdc
 * be initialized even if the original SubjectPublicKeyInfo was empty.
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
_gnutls_privkey_update_spki_params(gnutls_privkey_t key,
Packit 549fdc
				 gnutls_pk_algorithm_t pk,
Packit 549fdc
				 gnutls_digest_algorithm_t dig,
Packit 549fdc
				 unsigned flags,
Packit 549fdc
				 gnutls_x509_spki_st *params)
Packit 549fdc
{
Packit 549fdc
	unsigned salt_size = 0;
Packit 549fdc
	unsigned bits = 0;
Packit 549fdc
	gnutls_pk_algorithm_t key_pk;
Packit 549fdc
Packit 549fdc
	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS) {
Packit 549fdc
		if (!GNUTLS_PK_IS_RSA(pk))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
		pk = GNUTLS_PK_RSA_PSS;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	key_pk = gnutls_privkey_get_pk_algorithm(key, &bits);
Packit 549fdc
	if ((key_pk != pk) &&
Packit 549fdc
	      !(key_pk == GNUTLS_PK_RSA && pk == GNUTLS_PK_RSA_PSS)) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_CONSTRAINT_ERROR;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (pk == GNUTLS_PK_RSA_PSS) {
Packit 549fdc
		const mac_entry_st *me;
Packit 549fdc
Packit 549fdc
		me = hash_to_entry(dig);
Packit 549fdc
		if (unlikely(me == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
		if (params->pk == GNUTLS_PK_RSA)
Packit 549fdc
			salt_size = 0;
Packit 549fdc
		else if (params->pk == GNUTLS_PK_RSA_PSS) {
Packit 549fdc
			if (params->rsa_pss_dig != GNUTLS_DIG_UNKNOWN && dig != params->rsa_pss_dig) {
Packit 549fdc
				return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
Packit 549fdc
			}
Packit 549fdc
Packit 549fdc
			salt_size = params->salt_size;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		if (flags & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE)
Packit 549fdc
			params->salt_size = 0;
Packit 549fdc
		else
Packit 549fdc
			params->salt_size = _gnutls_find_rsa_pss_salt_size(bits, me, salt_size);
Packit 549fdc
		params->rsa_pss_dig = dig;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	params->pk = pk;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_init:
Packit 549fdc
 * @key: A pointer to the type to be initialized
Packit 549fdc
 *
Packit 549fdc
 * This function will initialize a private key object. The object can
Packit 549fdc
 * be used to generate, import, and perform cryptographic operations
Packit 549fdc
 * on the associated private key.
Packit 549fdc
 *
Packit 549fdc
 * Note that when the underlying private key is a PKCS#11 key (i.e.,
Packit 549fdc
 * when imported with a PKCS#11 URI), the limitations of gnutls_pkcs11_privkey_init()
Packit 549fdc
 * apply to this object as well. In versions of GnuTLS later than 3.5.11 the object
Packit 549fdc
 * is protected using locks and a single %gnutls_privkey_t can be re-used
Packit 549fdc
 * by many threads. However, for performance it is recommended to utilize
Packit 549fdc
 * one object per key per thread.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_init(gnutls_privkey_t * key)
Packit 549fdc
{
Packit 549fdc
	FAIL_IF_LIB_ERROR;
Packit 549fdc
Packit 549fdc
	*key = gnutls_calloc(1, sizeof(struct gnutls_privkey_st));
Packit 549fdc
	if (*key == NULL) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_deinit:
Packit 549fdc
 * @key: The key to be deinitialized
Packit 549fdc
 *
Packit 549fdc
 * This function will deinitialize a private key structure.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
void gnutls_privkey_deinit(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	if (key == NULL)
Packit 549fdc
		return;
Packit 549fdc
Packit 549fdc
	if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
Packit 549fdc
	    || key->flags & GNUTLS_PRIVKEY_IMPORT_COPY)
Packit 549fdc
		switch (key->type) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
		case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
			gnutls_pkcs11_privkey_deinit(key->key.pkcs11);
Packit 549fdc
			break;
Packit 549fdc
#endif
Packit 549fdc
		case GNUTLS_PRIVKEY_X509:
Packit 549fdc
			gnutls_x509_privkey_deinit(key->key.x509);
Packit 549fdc
			break;
Packit 549fdc
		case GNUTLS_PRIVKEY_EXT:
Packit 549fdc
			if (key->key.ext.deinit_func != NULL)
Packit 549fdc
				key->key.ext.deinit_func(key,
Packit 549fdc
							 key->key.ext.userdata);
Packit 549fdc
			break;
Packit 549fdc
		default:
Packit 549fdc
			break;
Packit 549fdc
		}
Packit 549fdc
	gnutls_free(key);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Will erase all private key information, except PIN */
Packit 549fdc
void _gnutls_privkey_cleanup(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	memset(&key->key, 0, sizeof(key->key));
Packit 549fdc
	key->type = 0;
Packit 549fdc
	key->pk_algorithm = 0;
Packit 549fdc
	key->flags = 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* will fail if the private key contains an actual key.
Packit 549fdc
 */
Packit 549fdc
static int check_if_clean(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	if (key->type != 0)
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_pkcs11:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @key: The private key to be imported
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will import the given private key to the abstract
Packit 549fdc
 * #gnutls_privkey_t type.
Packit 549fdc
 *
Packit 549fdc
 * The #gnutls_pkcs11_privkey_t object must not be deallocated
Packit 549fdc
 * during the lifetime of this structure.
Packit 549fdc
 *
Packit 549fdc
 * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
Packit 549fdc
 * and %GNUTLS_PRIVKEY_IMPORT_COPY.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_pkcs11(gnutls_privkey_t pkey,
Packit 549fdc
			     gnutls_pkcs11_privkey_t key, unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = check_if_clean(pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	pkey->key.pkcs11 = key;
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_PKCS11;
Packit 549fdc
	pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(key, NULL);
Packit 549fdc
	pkey->flags = flags;
Packit 549fdc
Packit 549fdc
	if (pkey->pin.data)
Packit 549fdc
		gnutls_pkcs11_privkey_set_pin_function(key, pkey->pin.cb,
Packit 549fdc
						       pkey->pin.data);
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#if 0
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_pkcs11_url:
Packit 549fdc
 * @key: A key of type #gnutls_pubkey_t
Packit 549fdc
 * @url: A PKCS 11 url
Packit 549fdc
 *
Packit 549fdc
 * This function will import a PKCS 11 private key to a #gnutls_private_key_t
Packit 549fdc
 * type.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1.0
Packit 549fdc
 **/
Packit 549fdc
Packit 549fdc
int gnutls_privkey_import_pkcs11_url(gnutls_privkey_t key, const char *url)
Packit 549fdc
{
Packit 549fdc
	int x;
Packit 549fdc
}
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
static
Packit 549fdc
int _gnutls_privkey_import_pkcs11_url(gnutls_privkey_t key, const char *url, unsigned flags)
Packit 549fdc
{
Packit 549fdc
	gnutls_pkcs11_privkey_t pkey;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = gnutls_pkcs11_privkey_init(&pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (key->pin.cb)
Packit 549fdc
		gnutls_pkcs11_privkey_set_pin_function(pkey, key->pin.cb,
Packit 549fdc
						       key->pin.data);
Packit 549fdc
Packit 549fdc
	ret = gnutls_pkcs11_privkey_import_url(pkey, url, flags);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    gnutls_privkey_import_pkcs11(key, pkey,
Packit 549fdc
					 GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
Packit 549fdc
 cleanup:
Packit 549fdc
	gnutls_pkcs11_privkey_deinit(pkey);
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_export_pkcs11:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @key: Location for the key to be exported.
Packit 549fdc
 *
Packit 549fdc
 * Converts the given abstract private key to a #gnutls_pkcs11_privkey_t
Packit 549fdc
 * type. The key must be of type %GNUTLS_PRIVKEY_PKCS11. The key
Packit 549fdc
 * returned in @key must be deinitialized with
Packit 549fdc
 * gnutls_pkcs11_privkey_deinit().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.4.0
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_export_pkcs11(gnutls_privkey_t pkey,
Packit 549fdc
			     gnutls_pkcs11_privkey_t *key)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	if (pkey->type != GNUTLS_PRIVKEY_PKCS11) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = gnutls_pkcs11_privkey_init(key);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = gnutls_pkcs11_privkey_cpy(*key, pkey->key.pkcs11);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_pkcs11_privkey_deinit(*key);
Packit 549fdc
		*key = NULL;
Packit 549fdc
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
#endif				/* ENABLE_PKCS11 */
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_ext:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @pk: The public key algorithm
Packit 549fdc
 * @userdata: private data to be provided to the callbacks
Packit 549fdc
 * @sign_func: callback for signature operations
Packit 549fdc
 * @decrypt_func: callback for decryption operations
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will associate the given callbacks with the
Packit 549fdc
 * #gnutls_privkey_t type. At least one of the two callbacks
Packit 549fdc
 * must be non-null.
Packit 549fdc
 *
Packit 549fdc
 * Note that the signing function is supposed to "raw" sign data, i.e.,
Packit 549fdc
 * without any hashing or preprocessing. In case of RSA the DigestInfo
Packit 549fdc
 * will be provided, and the signing function is expected to do the PKCS #1
Packit 549fdc
 * 1.5 padding and the exponentiation.
Packit 549fdc
 *
Packit 549fdc
 * See also gnutls_privkey_import_ext3().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_ext(gnutls_privkey_t pkey,
Packit 549fdc
			  gnutls_pk_algorithm_t pk,
Packit 549fdc
			  void *userdata,
Packit 549fdc
			  gnutls_privkey_sign_func sign_func,
Packit 549fdc
			  gnutls_privkey_decrypt_func decrypt_func,
Packit 549fdc
			  unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	return gnutls_privkey_import_ext2(pkey, pk, userdata, sign_func,
Packit 549fdc
					  decrypt_func, NULL, flags);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#define PK_IS_OK_FOR_EXT2(pk) \
Packit 549fdc
	((pk == GNUTLS_PK_RSA) || (pk == GNUTLS_PK_ECDSA) || (pk == GNUTLS_PK_DSA))
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_ext2:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @pk: The public key algorithm
Packit 549fdc
 * @userdata: private data to be provided to the callbacks
Packit 549fdc
 * @sign_fn: callback for signature operations
Packit 549fdc
 * @decrypt_fn: callback for decryption operations
Packit 549fdc
 * @deinit_fn: a deinitialization function
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will associate the given callbacks with the
Packit 549fdc
 * #gnutls_privkey_t type. At least one of the two callbacks
Packit 549fdc
 * must be non-null. If a deinitialization function is provided
Packit 549fdc
 * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE.
Packit 549fdc
 *
Packit 549fdc
 * Note that the signing function is supposed to "raw" sign data, i.e.,
Packit 549fdc
 * without any hashing or preprocessing. In case of RSA the DigestInfo
Packit 549fdc
 * will be provided, and the signing function is expected to do the PKCS #1
Packit 549fdc
 * 1.5 padding and the exponentiation.
Packit 549fdc
 *
Packit 549fdc
 * See also gnutls_privkey_import_ext3().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_ext2(gnutls_privkey_t pkey,
Packit 549fdc
			   gnutls_pk_algorithm_t pk,
Packit 549fdc
			   void *userdata,
Packit 549fdc
			   gnutls_privkey_sign_func sign_fn,
Packit 549fdc
			   gnutls_privkey_decrypt_func decrypt_fn,
Packit 549fdc
			   gnutls_privkey_deinit_func deinit_fn,
Packit 549fdc
			   unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = check_if_clean(pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (!PK_IS_OK_FOR_EXT2(pk))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	if (sign_fn == NULL && decrypt_fn == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	pkey->key.ext.sign_func = sign_fn;
Packit 549fdc
	pkey->key.ext.decrypt_func = decrypt_fn;
Packit 549fdc
	pkey->key.ext.deinit_func = deinit_fn;
Packit 549fdc
	pkey->key.ext.userdata = userdata;
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_EXT;
Packit 549fdc
	pkey->pk_algorithm = pk;
Packit 549fdc
	pkey->flags = flags;
Packit 549fdc
Packit 549fdc
	/* Ensure gnutls_privkey_deinit() calls the deinit_func */
Packit 549fdc
	if (deinit_fn)
Packit 549fdc
		pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_ext3:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @userdata: private data to be provided to the callbacks
Packit 549fdc
 * @sign_fn: callback for signature operations
Packit 549fdc
 * @decrypt_fn: callback for decryption operations
Packit 549fdc
 * @deinit_fn: a deinitialization function
Packit 549fdc
 * @info_fn: returns info about the public key algorithm (should not be %NULL)
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will associate the given callbacks with the
Packit 549fdc
 * #gnutls_privkey_t type. At least one of the two callbacks
Packit 549fdc
 * must be non-null. If a deinitialization function is provided
Packit 549fdc
 * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE.
Packit 549fdc
 *
Packit 549fdc
 * Note that the signing function is supposed to "raw" sign data, i.e.,
Packit 549fdc
 * without any hashing or preprocessing. In case of RSA the DigestInfo
Packit 549fdc
 * will be provided, and the signing function is expected to do the PKCS #1
Packit 549fdc
 * 1.5 padding and the exponentiation.
Packit 549fdc
 *
Packit 549fdc
 * The @info_fn must provide information on the algorithms supported by
Packit 549fdc
 * this private key, and should support the flags %GNUTLS_PRIVKEY_INFO_PK_ALGO and
Packit 549fdc
 * %GNUTLS_PRIVKEY_INFO_SIGN_ALGO. It must return -1 on unknown flags.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.4.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_ext3(gnutls_privkey_t pkey,
Packit 549fdc
			   void *userdata,
Packit 549fdc
			   gnutls_privkey_sign_func sign_fn,
Packit 549fdc
			   gnutls_privkey_decrypt_func decrypt_fn,
Packit 549fdc
			   gnutls_privkey_deinit_func deinit_fn,
Packit 549fdc
			   gnutls_privkey_info_func info_fn,
Packit 549fdc
			   unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = check_if_clean(pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (sign_fn == NULL && decrypt_fn == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	if (info_fn == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	pkey->key.ext.sign_func = sign_fn;
Packit 549fdc
	pkey->key.ext.decrypt_func = decrypt_fn;
Packit 549fdc
	pkey->key.ext.deinit_func = deinit_fn;
Packit 549fdc
	pkey->key.ext.info_func = info_fn;
Packit 549fdc
	pkey->key.ext.userdata = userdata;
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_EXT;
Packit 549fdc
	pkey->flags = flags;
Packit 549fdc
Packit 549fdc
	pkey->pk_algorithm = pkey->key.ext.info_func(pkey, GNUTLS_PRIVKEY_INFO_PK_ALGO, pkey->key.ext.userdata);
Packit 549fdc
Packit 549fdc
	if (!PK_IS_OK_FOR_EXT2(pkey->pk_algorithm))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	/* Ensure gnutls_privkey_deinit() calls the deinit_func */
Packit 549fdc
	if (deinit_fn)
Packit 549fdc
		pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_ext4:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @userdata: private data to be provided to the callbacks
Packit 549fdc
 * @sign_data_fn: callback for signature operations (may be %NULL)
Packit 549fdc
 * @sign_hash_fn: callback for signature operations (may be %NULL)
Packit 549fdc
 * @decrypt_fn: callback for decryption operations (may be %NULL)
Packit 549fdc
 * @deinit_fn: a deinitialization function
Packit 549fdc
 * @info_fn: returns info about the public key algorithm (should not be %NULL)
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will associate the given callbacks with the
Packit 549fdc
 * #gnutls_privkey_t type. At least one of the callbacks
Packit 549fdc
 * must be non-null. If a deinitialization function is provided
Packit 549fdc
 * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE.
Packit 549fdc
 *
Packit 549fdc
 * Note that in contrast with the signing function of
Packit 549fdc
 * gnutls_privkey_import_ext3(), the signing functions provided to this
Packit 549fdc
 * function take explicitly the signature algorithm as parameter and
Packit 549fdc
 * different functions are provided to sign the data and hashes.
Packit 549fdc
 *
Packit 549fdc
 * The @sign_hash_fn is to be called to sign pre-hashed data. The input
Packit 549fdc
 * to the callback is the output of the hash (such as SHA256) corresponding
Packit 549fdc
 * to the signature algorithm. For RSA PKCS#1 signatures, the signature
Packit 549fdc
 * algorithm can be set to %GNUTLS_SIGN_RSA_RAW, and in that case the data
Packit 549fdc
 * should be handled as if they were an RSA PKCS#1 DigestInfo structure.
Packit 549fdc
 *
Packit 549fdc
 * The @sign_data_fn is to be called to sign data. The input data will be
Packit 549fdc
 * he data to be signed (and hashed), with the provided signature
Packit 549fdc
 * algorithm. This function is to be used for signature algorithms like
Packit 549fdc
 * Ed25519 which cannot take pre-hashed data as input.
Packit 549fdc
 *
Packit 549fdc
 * When both @sign_data_fn and @sign_hash_fn functions are provided they
Packit 549fdc
 * must be able to operate on all the supported signature algorithms,
Packit 549fdc
 * unless prohibited by the type of the algorithm (e.g., as with Ed25519).
Packit 549fdc
 *
Packit 549fdc
 * The @info_fn must provide information on the signature algorithms supported by
Packit 549fdc
 * this private key, and should support the flags %GNUTLS_PRIVKEY_INFO_PK_ALGO and
Packit 549fdc
 * %GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO. It must return -1 on unknown flags.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.6.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_ext4(gnutls_privkey_t pkey,
Packit 549fdc
                           void *userdata,
Packit 549fdc
                           gnutls_privkey_sign_data_func sign_data_fn,
Packit 549fdc
                           gnutls_privkey_sign_hash_func sign_hash_fn,
Packit 549fdc
                           gnutls_privkey_decrypt_func decrypt_fn,
Packit 549fdc
                           gnutls_privkey_deinit_func deinit_fn,
Packit 549fdc
                           gnutls_privkey_info_func info_fn,
Packit 549fdc
                           unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = check_if_clean(pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (sign_data_fn == NULL && sign_hash_fn == NULL && decrypt_fn == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	if (info_fn == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	pkey->key.ext.sign_data_func = sign_data_fn;
Packit 549fdc
	pkey->key.ext.sign_hash_func = sign_hash_fn;
Packit 549fdc
	pkey->key.ext.decrypt_func = decrypt_fn;
Packit 549fdc
	pkey->key.ext.deinit_func = deinit_fn;
Packit 549fdc
	pkey->key.ext.info_func = info_fn;
Packit 549fdc
	pkey->key.ext.userdata = userdata;
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_EXT;
Packit 549fdc
	pkey->flags = flags;
Packit 549fdc
Packit 549fdc
	pkey->pk_algorithm = pkey->key.ext.info_func(pkey, GNUTLS_PRIVKEY_INFO_PK_ALGO, pkey->key.ext.userdata);
Packit 549fdc
Packit 549fdc
	/* Ensure gnutls_privkey_deinit() calls the deinit_func */
Packit 549fdc
	if (deinit_fn)
Packit 549fdc
		pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_x509:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @key: The private key to be imported
Packit 549fdc
 * @flags: Flags for the import
Packit 549fdc
 *
Packit 549fdc
 * This function will import the given private key to the abstract
Packit 549fdc
 * #gnutls_privkey_t type.
Packit 549fdc
 *
Packit 549fdc
 * The #gnutls_x509_privkey_t object must not be deallocated
Packit 549fdc
 * during the lifetime of this structure.
Packit 549fdc
 *
Packit 549fdc
 * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
Packit 549fdc
 * and %GNUTLS_PRIVKEY_IMPORT_COPY.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_x509(gnutls_privkey_t pkey,
Packit 549fdc
			   gnutls_x509_privkey_t key, unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = check_if_clean(pkey);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) {
Packit 549fdc
		ret = gnutls_x509_privkey_init(&pkey->key.x509);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
		ret = gnutls_x509_privkey_cpy(pkey->key.x509, key);
Packit 549fdc
		if (ret < 0) {
Packit 549fdc
			gnutls_x509_privkey_deinit(pkey->key.x509);
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		}
Packit 549fdc
	} else
Packit 549fdc
		pkey->key.x509 = key;
Packit 549fdc
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_X509;
Packit 549fdc
	pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm(key);
Packit 549fdc
	pkey->flags = flags;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_export_x509:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @key: Location for the key to be exported.
Packit 549fdc
 *
Packit 549fdc
 * Converts the given abstract private key to a #gnutls_x509_privkey_t
Packit 549fdc
 * type. The abstract key must be of type %GNUTLS_PRIVKEY_X509. The input
Packit 549fdc
 * @key must not be initialized. The key returned in @key should be deinitialized
Packit 549fdc
 * using gnutls_x509_privkey_deinit().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.4.0
Packit 549fdc
 */
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_export_x509(gnutls_privkey_t pkey,
Packit 549fdc
			   gnutls_x509_privkey_t *key)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	if (pkey->type != GNUTLS_PRIVKEY_X509) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_init(key);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_cpy(*key, pkey->key.x509);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_x509_privkey_deinit(*key);
Packit 549fdc
		*key = NULL;
Packit 549fdc
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_generate:
Packit 549fdc
 * @pkey: An initialized private key
Packit 549fdc
 * @algo: is one of the algorithms in #gnutls_pk_algorithm_t.
Packit 549fdc
 * @bits: the size of the parameters to generate
Packit 549fdc
 * @flags: Must be zero or flags from #gnutls_privkey_flags_t.
Packit 549fdc
 *
Packit 549fdc
 * This function will generate a random private key. Note that this
Packit 549fdc
 * function must be called on an initialized private key.
Packit 549fdc
 *
Packit 549fdc
 * The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE
Packit 549fdc
 * instructs the key generation process to use algorithms like Shawe-Taylor
Packit 549fdc
 * (from FIPS PUB186-4) which generate provable parameters out of a seed
Packit 549fdc
 * for RSA and DSA keys. See gnutls_privkey_generate2() for more
Packit 549fdc
 * information.
Packit 549fdc
 *
Packit 549fdc
 * Note that when generating an elliptic curve key, the curve
Packit 549fdc
 * can be substituted in the place of the bits parameter using the
Packit 549fdc
 * GNUTLS_CURVE_TO_BITS() macro. The input to the macro is any curve from
Packit 549fdc
 * %gnutls_ecc_curve_t.
Packit 549fdc
 *
Packit 549fdc
 * For DSA keys, if the subgroup size needs to be specified check
Packit 549fdc
 * the GNUTLS_SUBGROUP_TO_BITS() macro.
Packit 549fdc
 *
Packit 549fdc
 * It is recommended to do not set the number of @bits directly, use gnutls_sec_param_to_pk_bits() instead .
Packit 549fdc
 *
Packit 549fdc
 * See also gnutls_privkey_generate2().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.3.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_generate(gnutls_privkey_t pkey,
Packit 549fdc
			gnutls_pk_algorithm_t algo, unsigned int bits,
Packit 549fdc
			unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	return gnutls_privkey_generate2(pkey, algo, bits, flags, NULL, 0);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_generate2:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @algo: is one of the algorithms in #gnutls_pk_algorithm_t.
Packit 549fdc
 * @bits: the size of the modulus
Packit 549fdc
 * @flags: Must be zero or flags from #gnutls_privkey_flags_t.
Packit 549fdc
 * @data: Allow specifying %gnutls_keygen_data_st types such as the seed to be used.
Packit 549fdc
 * @data_size: The number of @data available.
Packit 549fdc
 *
Packit 549fdc
 * This function will generate a random private key. Note that this
Packit 549fdc
 * function must be called on an initialized private key.
Packit 549fdc
 *
Packit 549fdc
 * The flag %GNUTLS_PRIVKEY_FLAG_PROVABLE
Packit 549fdc
 * instructs the key generation process to use algorithms like Shawe-Taylor
Packit 549fdc
 * (from FIPS PUB186-4) which generate provable parameters out of a seed
Packit 549fdc
 * for RSA and DSA keys. On DSA keys the PQG parameters are generated using the
Packit 549fdc
 * seed, while on RSA the two primes. To specify an explicit seed
Packit 549fdc
 * (by default a random seed is used), use the @data with a %GNUTLS_KEYGEN_SEED
Packit 549fdc
 * type.
Packit 549fdc
 *
Packit 549fdc
 * Note that when generating an elliptic curve key, the curve
Packit 549fdc
 * can be substituted in the place of the bits parameter using the
Packit 549fdc
 * GNUTLS_CURVE_TO_BITS() macro.
Packit 549fdc
 *
Packit 549fdc
 * To export the generated keys in memory or in files it is recommended to use the
Packit 549fdc
 * PKCS#8 form as it can handle all key types, and can store additional parameters
Packit 549fdc
 * such as the seed, in case of provable RSA or DSA keys.
Packit 549fdc
 * Generated keys can be exported in memory using gnutls_privkey_export_x509(),
Packit 549fdc
 * and then with gnutls_x509_privkey_export2_pkcs8().
Packit 549fdc
 *
Packit 549fdc
 * If key generation is part of your application, avoid setting the number
Packit 549fdc
 * of bits directly, and instead use gnutls_sec_param_to_pk_bits().
Packit 549fdc
 * That way the generated keys will adapt to the security levels
Packit 549fdc
 * of the underlying GnuTLS library.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.5.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_generate2(gnutls_privkey_t pkey,
Packit 549fdc
			 gnutls_pk_algorithm_t algo, unsigned int bits,
Packit 549fdc
			 unsigned int flags, const gnutls_keygen_data_st *data, unsigned data_size)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_init(&pkey->key.x509);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_generate2(pkey->key.x509, algo, bits, flags, data, data_size);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_x509_privkey_deinit(pkey->key.x509);
Packit 549fdc
		pkey->key.x509 = NULL;
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	pkey->type = GNUTLS_PRIVKEY_X509;
Packit 549fdc
	pkey->pk_algorithm = algo;
Packit 549fdc
	pkey->flags = flags | GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_sign_data:
Packit 549fdc
 * @signer: Holds the key
Packit 549fdc
 * @hash: should be a digest algorithm
Packit 549fdc
 * @flags: Zero or one of %gnutls_privkey_flags_t
Packit 549fdc
 * @data: holds the data to be signed
Packit 549fdc
 * @signature: will contain the signature allocated with gnutls_malloc()
Packit 549fdc
 *
Packit 549fdc
 * This function will sign the given data using a signature algorithm
Packit 549fdc
 * supported by the private key. Signature algorithms are always used
Packit 549fdc
 * together with a hash functions.  Different hash functions may be
Packit 549fdc
 * used for the RSA algorithm, but only the SHA family for the DSA keys.
Packit 549fdc
 *
Packit 549fdc
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
Packit 549fdc
 * the hash algorithm.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 * negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_sign_data(gnutls_privkey_t signer,
Packit 549fdc
			 gnutls_digest_algorithm_t hash,
Packit 549fdc
			 unsigned int flags,
Packit 549fdc
			 const gnutls_datum_t * data,
Packit 549fdc
			 gnutls_datum_t * signature)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_x509_spki_st params;
Packit 549fdc
Packit 549fdc
	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_spki_params(signer, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
Packit 549fdc
					         hash, flags, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return privkey_sign_and_hash_data(signer, _gnutls_pk_to_sign_entry(params.pk, hash), data, signature, &params);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_sign_data2:
Packit 549fdc
 * @signer: Holds the key
Packit 549fdc
 * @algo: The signature algorithm used
Packit 549fdc
 * @flags: Zero or one of %gnutls_privkey_flags_t
Packit 549fdc
 * @data: holds the data to be signed
Packit 549fdc
 * @signature: will contain the signature allocated with gnutls_malloc()
Packit 549fdc
 *
Packit 549fdc
 * This function will sign the given data using the specified signature
Packit 549fdc
 * algorithm. This function is an enhancement of gnutls_privkey_sign_data(),
Packit 549fdc
 * as it allows utilizing a alternative signature algorithm where possible
Packit 549fdc
 * (e.g, use an RSA key with RSA-PSS).
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 * negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.6.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_sign_data2(gnutls_privkey_t signer,
Packit 549fdc
			  gnutls_sign_algorithm_t algo,
Packit 549fdc
			  unsigned int flags,
Packit 549fdc
			  const gnutls_datum_t * data,
Packit 549fdc
			  gnutls_datum_t * signature)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_x509_spki_st params;
Packit 549fdc
	const gnutls_sign_entry_st *e;
Packit 549fdc
Packit 549fdc
	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	e = _gnutls_sign_to_entry(algo);
Packit 549fdc
	if (e == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_spki_params(signer, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_update_spki_params(signer, e->pk, e->hash,
Packit 549fdc
					         flags, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return privkey_sign_and_hash_data(signer, _gnutls_sign_to_entry(algo), data, signature, &params);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_sign_hash2:
Packit 549fdc
 * @signer: Holds the signer's key
Packit 549fdc
 * @algo: The signature algorithm used
Packit 549fdc
 * @flags: Zero or one of %gnutls_privkey_flags_t
Packit 549fdc
 * @hash_data: holds the data to be signed
Packit 549fdc
 * @signature: will contain newly allocated signature
Packit 549fdc
 *
Packit 549fdc
 * This function will sign the given hashed data using a signature algorithm
Packit 549fdc
 * supported by the private key. Signature algorithms are always used
Packit 549fdc
 * together with a hash functions.  Different hash functions may be
Packit 549fdc
 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
Packit 549fdc
 *
Packit 549fdc
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
Packit 549fdc
 * the hash algorithm.
Packit 549fdc
 *
Packit 549fdc
 * The flags may be %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA or %GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS.
Packit 549fdc
 * In the former case this function will ignore @hash_algo and perform a raw PKCS1 signature,
Packit 549fdc
 * and in the latter an RSA-PSS signature will be generated.
Packit 549fdc
 *
Packit 549fdc
 * Note that, not all algorithm support signing already hashed data. When
Packit 549fdc
 * signing with Ed25519, gnutls_privkey_sign_data() should be used.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.6.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
Packit 549fdc
			  gnutls_sign_algorithm_t algo,
Packit 549fdc
			  unsigned int flags,
Packit 549fdc
			  const gnutls_datum_t * hash_data,
Packit 549fdc
			  gnutls_datum_t * signature)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_x509_spki_st params;
Packit 549fdc
	const gnutls_sign_entry_st *se;
Packit 549fdc
Packit 549fdc
	se = _gnutls_sign_to_entry(algo);
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_spki_params(signer, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash,
Packit 549fdc
					         flags, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return privkey_sign_prehashed(signer, se, hash_data, signature, &params, flags);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
privkey_sign_and_hash_data(gnutls_privkey_t signer,
Packit 549fdc
			   const gnutls_sign_entry_st *se,
Packit 549fdc
			   const gnutls_datum_t * data,
Packit 549fdc
			   gnutls_datum_t * signature,
Packit 549fdc
			   gnutls_x509_spki_st * params)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_datum_t digest;
Packit 549fdc
	const mac_entry_st *me;
Packit 549fdc
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	if (_gnutls_pk_is_not_prehashed(se->pk)) {
Packit 549fdc
		return privkey_sign_raw_data(signer, se, data, signature, params);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	me = hash_to_entry(se->hash);
Packit 549fdc
	if (me == NULL)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	ret = pk_hash_data(se->pk, me, NULL, data, &digest);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = pk_prepare_hash(se->pk, me, &digest);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = privkey_sign_raw_data(signer, se, &digest, signature, params);
Packit 549fdc
	_gnutls_free_datum(&digest);
Packit 549fdc
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
Packit 549fdc
 cleanup:
Packit 549fdc
	_gnutls_free_datum(&digest);
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_sign_hash:
Packit 549fdc
 * @signer: Holds the signer's key
Packit 549fdc
 * @hash_algo: The hash algorithm used
Packit 549fdc
 * @flags: Zero or one of %gnutls_privkey_flags_t
Packit 549fdc
 * @hash_data: holds the data to be signed
Packit 549fdc
 * @signature: will contain newly allocated signature
Packit 549fdc
 *
Packit 549fdc
 * This function will sign the given hashed data using a signature algorithm
Packit 549fdc
 * supported by the private key. Signature algorithms are always used
Packit 549fdc
 * together with a hash functions.  Different hash functions may be
Packit 549fdc
 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
Packit 549fdc
 *
Packit 549fdc
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
Packit 549fdc
 * the hash algorithm.
Packit 549fdc
 *
Packit 549fdc
 * The flags may be %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA or %GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS.
Packit 549fdc
 * In the former case this function will ignore @hash_algo and perform a raw PKCS1 signature,
Packit 549fdc
 * and in the latter an RSA-PSS signature will be generated.
Packit 549fdc
 *
Packit 549fdc
 * Note that, not all algorithm support signing already hashed data. When
Packit 549fdc
 * signing with Ed25519, gnutls_privkey_sign_data() should be used.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_sign_hash(gnutls_privkey_t signer,
Packit 549fdc
			 gnutls_digest_algorithm_t hash_algo,
Packit 549fdc
			 unsigned int flags,
Packit 549fdc
			 const gnutls_datum_t * hash_data,
Packit 549fdc
			 gnutls_datum_t * signature)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_x509_spki_st params;
Packit 549fdc
	const gnutls_sign_entry_st *se;
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_spki_params(signer, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
Packit 549fdc
					       hash_algo, flags, &params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	/* legacy callers of this API could use a hash algorithm of 0 (unknown)
Packit 549fdc
	 * to indicate raw hashing. As we now always want to know the signing
Packit 549fdc
	 * algorithm involved, we try discovering the hash algorithm. */
Packit 549fdc
	if (hash_algo == 0 && (params.pk == GNUTLS_PK_DSA || params.pk == GNUTLS_PK_ECDSA)) {
Packit 549fdc
		hash_algo = _gnutls_hash_size_to_sha_hash(hash_data->size);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (params.pk == GNUTLS_PK_RSA && (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)) {
Packit 549fdc
		/* the corresponding signature algorithm is SIGN_RSA_RAW,
Packit 549fdc
		 * irrespective of hash algorithm. */
Packit 549fdc
		se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
Packit 549fdc
	} else {
Packit 549fdc
		se = _gnutls_pk_to_sign_entry(params.pk, hash_algo);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	return privkey_sign_prehashed(signer, se,
Packit 549fdc
				      hash_data, signature, &params, flags);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static int
Packit 549fdc
privkey_sign_prehashed(gnutls_privkey_t signer,
Packit 549fdc
		       const gnutls_sign_entry_st *se,
Packit 549fdc
		       const gnutls_datum_t * hash_data,
Packit 549fdc
		       gnutls_datum_t * signature,
Packit 549fdc
		       gnutls_x509_spki_st * params,
Packit 549fdc
		       unsigned flags)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	gnutls_datum_t digest;
Packit 549fdc
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	if (se->id == GNUTLS_SIGN_RSA_RAW) {
Packit 549fdc
		return privkey_sign_raw_data(signer,
Packit 549fdc
					     se,
Packit 549fdc
					     hash_data, signature,
Packit 549fdc
					     params);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (_gnutls_pk_is_not_prehashed(signer->pk_algorithm)) {
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	digest.data = gnutls_malloc(hash_data->size);
Packit 549fdc
	if (digest.data == NULL) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_MEMORY_ERROR;
Packit 549fdc
	}
Packit 549fdc
	digest.size = hash_data->size;
Packit 549fdc
	memcpy(digest.data, hash_data->data, digest.size);
Packit 549fdc
Packit 549fdc
	ret = pk_prepare_hash(se->pk, hash_to_entry(se->hash), &digest);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = privkey_sign_raw_data(signer,
Packit 549fdc
				    se,
Packit 549fdc
				    &digest, signature,
Packit 549fdc
				    params);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = 0;
Packit 549fdc
Packit 549fdc
 cleanup:
Packit 549fdc
	_gnutls_free_datum(&digest);
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/*-
Packit 549fdc
 * privkey_sign_raw_data:
Packit 549fdc
 * @key: Holds the key
Packit 549fdc
 * @data: holds the data to be signed
Packit 549fdc
 * @signature: will contain the signature allocated with gnutls_malloc()
Packit 549fdc
 * @params: holds the signing parameters
Packit 549fdc
 *
Packit 549fdc
 * This function will sign the given data using a signature algorithm
Packit 549fdc
 * supported by the private key. Note that this is a low-level function
Packit 549fdc
 * and does not apply any preprocessing or hash on the signed data. 
Packit 549fdc
 * For example on an RSA key the input @data should be of the DigestInfo
Packit 549fdc
 * PKCS #1 1.5 format, on RSA-PSS, DSA or ECDSA the input should be a hash output
Packit 549fdc
 * and on Ed25519 the raw data to be signed.
Packit 549fdc
 *
Packit 549fdc
 * Note this function is equivalent to using the %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA
Packit 549fdc
 * flag with gnutls_privkey_sign_hash().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 * negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1.10
Packit 549fdc
 -*/
Packit 549fdc
int
Packit 549fdc
privkey_sign_raw_data(gnutls_privkey_t key,
Packit 549fdc
		      const gnutls_sign_entry_st *se,
Packit 549fdc
		      const gnutls_datum_t * data,
Packit 549fdc
		      gnutls_datum_t * signature,
Packit 549fdc
		      gnutls_x509_spki_st * params)
Packit 549fdc
{
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
	switch (key->type) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
		return _gnutls_pkcs11_privkey_sign(key->key.pkcs11, se,
Packit 549fdc
						   data, signature,
Packit 549fdc
						   params);
Packit 549fdc
#endif
Packit 549fdc
	case GNUTLS_PRIVKEY_X509:
Packit 549fdc
		return _gnutls_pk_sign(se->pk, signature, data,
Packit 549fdc
				       &key->key.x509->params, params);
Packit 549fdc
	case GNUTLS_PRIVKEY_EXT:
Packit 549fdc
		if (unlikely(key->key.ext.sign_data_func == NULL &&
Packit 549fdc
			key->key.ext.sign_hash_func == NULL &&
Packit 549fdc
			key->key.ext.sign_func == NULL))
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
		if (_gnutls_pk_is_not_prehashed(se->pk)) {
Packit 549fdc
			if (!key->key.ext.sign_data_func)
Packit 549fdc
				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
			return key->key.ext.sign_data_func(key, se->id,
Packit 549fdc
							   key->key.ext.userdata,
Packit 549fdc
							   0,
Packit 549fdc
							   data, signature);
Packit 549fdc
		} else if (key->key.ext.sign_hash_func) {
Packit 549fdc
			unsigned int flags = 0;
Packit 549fdc
Packit 549fdc
			if (se->pk == GNUTLS_PK_RSA) {
Packit 549fdc
				se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
Packit 549fdc
			}
Packit 549fdc
Packit 549fdc
			/* se may not be set here if we are doing legacy RSA */
Packit 549fdc
			return key->key.ext.sign_hash_func(key, se->id,
Packit 549fdc
							   key->key.ext.userdata,
Packit 549fdc
							   flags,
Packit 549fdc
							   data, signature);
Packit 549fdc
		} else {
Packit 549fdc
			if (!PK_IS_OK_FOR_EXT2(se->pk))
Packit 549fdc
				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
			return key->key.ext.sign_func(key, key->key.ext.userdata,
Packit 549fdc
						      data, signature);
Packit 549fdc
		}
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_decrypt_data:
Packit 549fdc
 * @key: Holds the key
Packit 549fdc
 * @flags: zero for now
Packit 549fdc
 * @ciphertext: holds the data to be decrypted
Packit 549fdc
 * @plaintext: will contain the decrypted data, allocated with gnutls_malloc()
Packit 549fdc
 *
Packit 549fdc
 * This function will decrypt the given data using the algorithm
Packit 549fdc
 * supported by the private key.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 * negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 2.12.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_decrypt_data(gnutls_privkey_t key,
Packit 549fdc
			    unsigned int flags,
Packit 549fdc
			    const gnutls_datum_t * ciphertext,
Packit 549fdc
			    gnutls_datum_t * plaintext)
Packit 549fdc
{
Packit 549fdc
	switch (key->type) {
Packit 549fdc
	case GNUTLS_PRIVKEY_X509:
Packit 549fdc
		return _gnutls_pk_decrypt(key->pk_algorithm, plaintext,
Packit 549fdc
					  ciphertext, &key->key.x509->params);
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
		return _gnutls_pkcs11_privkey_decrypt_data(key->key.pkcs11,
Packit 549fdc
							   flags,
Packit 549fdc
							   ciphertext,
Packit 549fdc
							   plaintext);
Packit 549fdc
#endif
Packit 549fdc
	case GNUTLS_PRIVKEY_EXT:
Packit 549fdc
		if (key->key.ext.decrypt_func == NULL)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
		return key->key.ext.decrypt_func(key,
Packit 549fdc
						 key->key.ext.userdata,
Packit 549fdc
						 ciphertext, plaintext);
Packit 549fdc
	default:
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_INVALID_REQUEST;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_x509_raw:
Packit 549fdc
 * @pkey: The private key
Packit 549fdc
 * @data: The private key data to be imported
Packit 549fdc
 * @format: The format of the private key
Packit 549fdc
 * @password: A password (optional)
Packit 549fdc
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
Packit 549fdc
 *
Packit 549fdc
 * This function will import the given private key to the abstract
Packit 549fdc
 * #gnutls_privkey_t type. 
Packit 549fdc
 *
Packit 549fdc
 * The supported formats are basic unencrypted key, PKCS8, PKCS12, 
Packit 549fdc
 * and the openssl format.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_import_x509_raw(gnutls_privkey_t pkey,
Packit 549fdc
				   const gnutls_datum_t * data,
Packit 549fdc
				   gnutls_x509_crt_fmt_t format,
Packit 549fdc
				   const char *password, unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	gnutls_x509_privkey_t xpriv;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_init(&xpriv);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	if (pkey->pin.cb) {
Packit 549fdc
		gnutls_x509_privkey_set_pin_function(xpriv, pkey->pin.cb,
Packit 549fdc
						     pkey->pin.data);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = gnutls_x509_privkey_import2(xpriv, data, format, password, flags);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret =
Packit 549fdc
	    gnutls_privkey_import_x509(pkey, xpriv,
Packit 549fdc
				       GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
Packit 549fdc
 cleanup:
Packit 549fdc
	gnutls_x509_privkey_deinit(xpriv);
Packit 549fdc
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_import_url:
Packit 549fdc
 * @key: A key of type #gnutls_privkey_t
Packit 549fdc
 * @url: A PKCS 11 url
Packit 549fdc
 * @flags: should be zero
Packit 549fdc
 *
Packit 549fdc
 * This function will import a PKCS11 or TPM URL as a
Packit 549fdc
 * private key. The supported URL types can be checked
Packit 549fdc
 * using gnutls_url_is_supported().
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.1.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_import_url(gnutls_privkey_t key, const char *url,
Packit 549fdc
			  unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	unsigned i;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	for (i=0;i<_gnutls_custom_urls_size;i++) {
Packit 549fdc
		if (strncmp(url, _gnutls_custom_urls[i].name, _gnutls_custom_urls[i].name_size) == 0) {
Packit 549fdc
			if (_gnutls_custom_urls[i].import_key) {
Packit 549fdc
				ret = _gnutls_custom_urls[i].import_key(key, url, flags);
Packit 549fdc
				goto cleanup;
Packit 549fdc
			}
Packit 549fdc
			break;
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (strncmp(url, PKCS11_URL, PKCS11_URL_SIZE) == 0) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
		ret = _gnutls_privkey_import_pkcs11_url(key, url, flags);
Packit 549fdc
#else
Packit 549fdc
		ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
Packit 549fdc
#endif
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (strncmp(url, TPMKEY_URL, TPMKEY_URL_SIZE) == 0) {
Packit 549fdc
#ifdef HAVE_TROUSERS
Packit 549fdc
		ret = gnutls_privkey_import_tpm_url(key, url, NULL, NULL, 0);
Packit 549fdc
#else
Packit 549fdc
		ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
Packit 549fdc
#endif
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (strncmp(url, SYSTEM_URL, SYSTEM_URL_SIZE) == 0) {
Packit 549fdc
		ret = _gnutls_privkey_import_system_url(key, url);
Packit 549fdc
		goto cleanup;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
 cleanup:
Packit 549fdc
	return ret;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_set_pin_function:
Packit 549fdc
 * @key: A key of type #gnutls_privkey_t
Packit 549fdc
 * @fn: the callback
Packit 549fdc
 * @userdata: data associated with the callback
Packit 549fdc
 *
Packit 549fdc
 * This function will set a callback function to be used when
Packit 549fdc
 * required to access the 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
 **/
Packit 549fdc
void gnutls_privkey_set_pin_function(gnutls_privkey_t key,
Packit 549fdc
				     gnutls_pin_callback_t fn, void *userdata)
Packit 549fdc
{
Packit 549fdc
	key->pin.cb = fn;
Packit 549fdc
	key->pin.data = userdata;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_set_flags:
Packit 549fdc
 * @key: A key of type #gnutls_privkey_t
Packit 549fdc
 * @flags: flags from the %gnutls_privkey_flags
Packit 549fdc
 *
Packit 549fdc
 * This function will set flags for the specified private key, after
Packit 549fdc
 * it is generated. Currently this is useful for the %GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT
Packit 549fdc
 * to allow exporting a "provable" private key in backwards compatible way.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.5.0
Packit 549fdc
 *
Packit 549fdc
 **/
Packit 549fdc
void gnutls_privkey_set_flags(gnutls_privkey_t key,
Packit 549fdc
			      unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	key->flags |= flags;
Packit 549fdc
	if (key->type == GNUTLS_PRIVKEY_X509)
Packit 549fdc
		gnutls_x509_privkey_set_flags(key->key.x509, flags);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_status:
Packit 549fdc
 * @key: Holds the key
Packit 549fdc
 *
Packit 549fdc
 * Checks the status of the private key token. This function
Packit 549fdc
 * is an actual wrapper over gnutls_pkcs11_privkey_status(), and
Packit 549fdc
 * if the private key is a PKCS #11 token it will check whether
Packit 549fdc
 * it is inserted or not.
Packit 549fdc
 *
Packit 549fdc
 * Returns: this function will return non-zero if the token 
Packit 549fdc
 * holding the private key is still available (inserted), and zero otherwise.
Packit 549fdc
 * 
Packit 549fdc
 * Since: 3.1.10
Packit 549fdc
 *
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_status(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	switch (key->type) {
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	case GNUTLS_PRIVKEY_PKCS11:
Packit 549fdc
		return gnutls_pkcs11_privkey_status(key->key.pkcs11);
Packit 549fdc
#endif
Packit 549fdc
	default:
Packit 549fdc
		return 1;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_verify_params:
Packit 549fdc
 * @key: should contain a #gnutls_privkey_t type
Packit 549fdc
 *
Packit 549fdc
 * This function will verify the private key parameters.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.3.0
Packit 549fdc
 **/
Packit 549fdc
int gnutls_privkey_verify_params(gnutls_privkey_t key)
Packit 549fdc
{
Packit 549fdc
	gnutls_pk_params_st params;
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	gnutls_pk_params_init(&params);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_privkey_get_mpis(key, &params);
Packit 549fdc
	if (ret < 0)
Packit 549fdc
		return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
	ret = _gnutls_pk_verify_priv_params(key->pk_algorithm, &params);
Packit 549fdc
Packit 549fdc
	gnutls_pk_params_release(&params);
Packit 549fdc
Packit 549fdc
	if (ret < 0) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return ret;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_get_spki:
Packit 549fdc
 * @privkey: a public key of type #gnutls_privkey_t
Packit 549fdc
 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_privkey_spki_t
Packit 549fdc
 * @flags: must be zero
Packit 549fdc
 *
Packit 549fdc
 * This function will return the public key information if available.
Packit 549fdc
 * The provided @spki must be initialized.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.6.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_get_spki(gnutls_privkey_t privkey, gnutls_x509_spki_t spki, unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	if (privkey == NULL || privkey->type != GNUTLS_PRIVKEY_X509) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (privkey->key.x509->params.spki.pk == GNUTLS_PK_UNKNOWN)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
Packit 549fdc
Packit 549fdc
	memcpy(spki, &privkey->key.x509->params.spki, sizeof(gnutls_x509_spki_st));
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_privkey_set_spki:
Packit 549fdc
 * @privkey: a public key of type #gnutls_privkey_t
Packit 549fdc
 * @spki: a SubjectPublicKeyInfo structure of type #gnutls_privkey_spki_t
Packit 549fdc
 * @flags: must be zero
Packit 549fdc
 *
Packit 549fdc
 * This function will set the public key information.
Packit 549fdc
 * The provided @spki must be initialized.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
Packit 549fdc
 *   negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.6.0
Packit 549fdc
 **/
Packit 549fdc
int
Packit 549fdc
gnutls_privkey_set_spki(gnutls_privkey_t privkey, const gnutls_x509_spki_t spki, unsigned int flags)
Packit 549fdc
{
Packit 549fdc
	if (privkey == NULL || privkey->type != GNUTLS_PRIVKEY_X509) {
Packit 549fdc
		gnutls_assert();
Packit 549fdc
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return gnutls_x509_privkey_set_spki(privkey->key.x509, spki, flags);
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Checks whether the public key given is compatible with the
Packit 549fdc
 * signature algorithm used. The session is only used for audit logging, and
Packit 549fdc
 * it may be null.
Packit 549fdc
 */
Packit 549fdc
unsigned _gnutls_privkey_compatible_with_sig(gnutls_privkey_t privkey,
Packit 549fdc
					     gnutls_sign_algorithm_t sign)
Packit 549fdc
{
Packit 549fdc
	const gnutls_sign_entry_st *se;
Packit 549fdc
Packit 549fdc
	se = _gnutls_sign_to_entry(sign);
Packit 549fdc
	if (unlikely(se == NULL))
Packit 549fdc
		return gnutls_assert_val(0);
Packit 549fdc
Packit 549fdc
	/* Prevent RSA-PSS private keys from negotiating an RSA signature,
Packit 549fdc
	 * and RSA keys which cannot do RSA-PSS (e.g., smart card) from
Packit 549fdc
	 * negotiating RSA-PSS sig.
Packit 549fdc
	 */
Packit 549fdc
	if (privkey->pk_algorithm == GNUTLS_PK_RSA_PSS && se->pk != GNUTLS_PK_RSA_PSS) {
Packit 549fdc
			return 0;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	if (privkey->type == GNUTLS_PRIVKEY_EXT) {
Packit 549fdc
		if (privkey->key.ext.info_func) {
Packit 549fdc
			int ret;
Packit 549fdc
Packit 549fdc
			ret = privkey->key.ext.info_func(privkey,
Packit 549fdc
						     GNUTLS_SIGN_ALGO_TO_FLAGS(sign)|GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO,
Packit 549fdc
						     privkey->key.ext.userdata);
Packit 549fdc
			if (ret != -1)
Packit 549fdc
				return ret;
Packit 549fdc
Packit 549fdc
			/* use the old flag */
Packit 549fdc
			ret = privkey->key.ext.info_func(privkey, GNUTLS_PRIVKEY_INFO_SIGN_ALGO,
Packit 549fdc
						     privkey->key.ext.userdata);
Packit 549fdc
			if (ret == (int)sign)
Packit 549fdc
				return 1;
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		/* This key type is very limited on what it can handle */
Packit 549fdc
		if (!PK_IS_OK_FOR_EXT2(se->pk))
Packit 549fdc
			return gnutls_assert_val(0);
Packit 549fdc
	}
Packit 549fdc
#ifdef ENABLE_PKCS11
Packit 549fdc
	else if (privkey->type == GNUTLS_PRIVKEY_PKCS11) {
Packit 549fdc
		if (privkey->pk_algorithm == GNUTLS_PK_RSA && se->pk == GNUTLS_PK_RSA_PSS) {
Packit 549fdc
			if (!privkey->key.pkcs11->rsa_pss_ok)
Packit 549fdc
				return 0;
Packit 549fdc
		}
Packit 549fdc
	}
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
	return 1;
Packit 549fdc
}