Пример #1
0
Blob
PrivateKey::decrypt(const Blob& cipher) const
{
    if (!key)
        throw CryptoException("Can't decrypt data without private key !");

    unsigned key_len = 0;
    int err = gnutls_privkey_get_pk_algorithm(key, &key_len);
    if (err < 0)
        throw CryptoException("Can't read public key length !");
    if (err != GNUTLS_PK_RSA)
        throw CryptoException("Must be an RSA key");

    unsigned cypher_block_sz = key_len / 8;
    if (cipher.size() % cypher_block_sz)
        throw CryptoException("Unexpected cipher length");

    Blob ret;
    for (auto cb = cipher.cbegin(), ce = cipher.cend(); cb < ce; cb += cypher_block_sz) {
        const gnutls_datum_t dat {(uint8_t*)(&(*cb)), cypher_block_sz};
        gnutls_datum_t out;
        int err = gnutls_privkey_decrypt_data(key, 0, &dat, &out);
        if (err != GNUTLS_E_SUCCESS)
            throw DhtException(std::string("Can't decrypt data: ") + gnutls_strerror(err));
        ret.insert(ret.end(), out.data, out.data+out.size);
        gnutls_free(out.data);
    }
    return ret;
}
Пример #2
0
/* Returns the public key of the private key (if possible)
 */
int
_gnutls_privkey_get_public_mpis(gnutls_privkey_t key,
				gnutls_pk_params_st * params)
{
	int ret;
	gnutls_pk_algorithm_t pk =
	    gnutls_privkey_get_pk_algorithm(key, NULL);

	switch (key->type) {
#ifdef ENABLE_OPENPGP
	case GNUTLS_PRIVKEY_OPENPGP:
		{
			gnutls_pk_params_st tmp_params;
			uint32_t kid[2];
			uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];

			ret =
			    gnutls_openpgp_privkey_get_preferred_key_id
			    (key->key.openpgp, keyid);
			if (ret == 0) {
				KEYID_IMPORT(kid, keyid);
				ret =
				    _gnutls_openpgp_privkey_get_mpis(key->
								     key.
								     openpgp,
								     kid,
								     &tmp_params);
			} else
				ret =
				    _gnutls_openpgp_privkey_get_mpis(key->
								     key.
								     openpgp,
								     NULL,
								     &tmp_params);

			if (ret < 0) {
				gnutls_assert();
				return ret;
			}

			ret = privkey_to_pubkey(pk, &tmp_params, params);

			gnutls_pk_params_release(&tmp_params);
		}

		break;
#endif
	case GNUTLS_PRIVKEY_X509:
		ret = privkey_to_pubkey(pk,
					&key->key.x509->params, params);
		break;
	default:
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	return ret;
}
Пример #3
0
static
int dcrypt_gnutls_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r, const char **error_r)
{
	int ec;

	gnutls_privkey_t priv = (gnutls_privkey_t)priv_key;
	if (gnutls_privkey_get_pk_algorithm(priv, NULL) == GNUTLS_PK_RSA) {
		gnutls_datum_t m,e;
		/* do not extract anything we don't need */
		ec = gnutls_privkey_export_rsa_raw(priv, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL);
		if (ec != GNUTLS_E_SUCCESS) return dcrypt_gnutls_error(ec, error_r);
		gnutls_pubkey_t pub;
		gnutls_pubkey_init(&pub);
		ec = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
		gnutls_free(m.data);
		gnutls_free(e.data);
		if (ec < 0) {
			gnutls_pubkey_deinit(pub);
			return dcrypt_gnutls_error(ec, error_r);
		}
		*pub_key_r = (struct dcrypt_public_key*)pub;
		return 0;
	} else if (gnutls_privkey_get_pk_algorithm(priv, NULL) == GNUTLS_PK_EC) {
		gnutls_ecc_curve_t curve;
		gnutls_datum_t x,y,k;
		ec = gnutls_privkey_export_ecc_raw(priv, &curve, &x, &y, NULL);
		if (ec != GNUTLS_E_SUCCESS) return dcrypt_gnutls_error(ec, error_r);
		gnutls_pubkey_t pub;
		gnutls_pubkey_init(&pub);
		ec = gnutls_pubkey_import_ecc_raw(pub, curve, &x, &y);
		gnutls_free(x.data);
		gnutls_free(y.data);
		if (ec < 0) {
			gnutls_pubkey_deinit(pub);
			return dcrypt_gnutls_error(ec, error_r);
		}
		*pub_key_r = (struct dcrypt_public_key*)pub;
		return 0;
	}

	return -1;
}
Пример #4
0
/**
 * gnutls_pubkey_import_privkey:
 * @key: The public key
 * @pkey: The private key
 * @usage: GNUTLS_KEY_* key usage flags.
 * @flags: should be zero
 *
 * Imports the public key from a private.  This function will import
 * the given public key to the abstract #gnutls_pubkey_t type.
 *
 * Note that in certain keys this operation may not be possible, e.g.,
 * in other than RSA PKCS#11 keys.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pubkey_import_privkey(gnutls_pubkey_t key, gnutls_privkey_t pkey,
			     unsigned int usage, unsigned int flags)
{
	gnutls_pk_params_release(&key->params);
	gnutls_pk_params_init(&key->params);

	key->pk_algorithm =
	    gnutls_privkey_get_pk_algorithm(pkey, &key->bits);

	key->key_usage = usage;

	return _gnutls_privkey_get_public_mpis(pkey, &key->params);
}
Пример #5
0
/* returns error if the certificate has different algorithm than
 * the given key parameters.
 */
int
_gnutls_check_key_cert_match (gnutls_certificate_credentials_t res)
{
  int pk = gnutls_pubkey_get_pk_algorithm(res->certs[res->ncerts-1].cert_list[0].pubkey, NULL);
  int pk2 = gnutls_privkey_get_pk_algorithm (res->pkey[res->ncerts - 1], NULL);

  if (pk2 != pk)
    {
      gnutls_assert ();
      return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
    }

  return 0;
}
Пример #6
0
/*-
 * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key
 * @src: should contain an ASN1_TYPE
 * @issuer: is the certificate of the certificate issuer
 * @issuer_key: holds the issuer's private key
 *
 * This function will sign a CRL or a certificate with the issuer's private key, and
 * will copy the issuer's information into the CRL or certificate.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name,
                        gnutls_digest_algorithm_t dig,
                        gnutls_x509_crt_t issuer, gnutls_privkey_t issuer_key)
{
  int result;
  gnutls_datum_t signature;
  gnutls_datum_t tbs;
  char name[128];

  /* Step 1. Copy the issuer's name into the certificate.
   */
  _gnutls_str_cpy (name, sizeof (name), src_name);
  _gnutls_str_cat (name, sizeof (name), ".issuer");

  result = asn1_copy_node (src, name, issuer->cert, "tbsCertificate.subject");
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  /* Step 1.5. Write the signature stuff in the tbsCertificate.
   */
  _gnutls_str_cpy (name, sizeof (name), src_name);
  _gnutls_str_cat (name, sizeof (name), ".signature");

  result = _gnutls_x509_write_sig_params (src, name,
                                          gnutls_privkey_get_pk_algorithm
                                          (issuer_key, NULL), dig);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* Step 2. Sign the certificate.
   */
  result = _gnutls_x509_get_tbs (src, src_name, &tbs);

  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  result = gnutls_privkey_sign_data (issuer_key, dig, 0, &tbs, &signature);
  gnutls_free (tbs.data);

  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* write the signature (bits)
   */
  result =
    asn1_write_value (src, "signature", signature.data, signature.size * 8);

  _gnutls_free_datum (&signature);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  /* Step 3. Move up and write the AlgorithmIdentifier, which is also
   * the same. 
   */

  result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm",
                                          gnutls_privkey_get_pk_algorithm
                                          (issuer_key, NULL), dig);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  return 0;
}
Пример #7
0
static int
gen_rsa_export_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  gnutls_rsa_params_t rsa_params;
  const bigint_t *rsa_mpis;
  int ret = 0;
  gnutls_pcert_st *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_sign_algorithm_t sign_algo;
  unsigned int bits = 0;

  cred = (gnutls_certificate_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* find the appropriate certificate */
  if ((ret =
       _gnutls_get_selected_cert (session, &apr_cert_list,
                                  &apr_cert_list_length, &apr_pkey)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* abort sending this message if we have a certificate
   * of 512 bits or less.
   */
  gnutls_privkey_get_pk_algorithm (apr_pkey, &bits);
  if (apr_pkey && bits <= 512)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  rsa_params =
    _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
                                        session);
  rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params);
  if (rsa_mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
    }

  if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
                                    sizeof (cert_auth_info_st), 0)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);

  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[0], 0);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[1], 0);
  if (ret < 0)
    return gnutls_assert_val(ret);

  /* Generate the signature. */

  ddata.data = data->data;
  ddata.size = data->length;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
           _gnutls_handshake_sign_data (session, &apr_cert_list[0],
                                        apr_pkey, &ddata, &signature,
                                        &sign_algo)) < 0)
        {
          gnutls_assert ();
          return ret;
        }
    }
  else
    {
      gnutls_assert ();
      return data->length;         /* do not put a signature - ILLEGAL! */
    }

  ret = _gnutls_buffer_append_data_prefix( data, 16, signature.data, signature.size);
  _gnutls_free_datum (&signature);

  if (ret < 0)
    return gnutls_assert_val(ret);

  return data->length;
}
Пример #8
0
/* Returns the public key of the private key (if possible)
 */
int
_gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
                                 bigint_t * params, int *params_size)
{
  int ret;
  gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL);

  switch (key->type)
    {
#ifdef ENABLE_OPENPGP
    case GNUTLS_PRIVKEY_OPENPGP:
      {
        bigint_t tmp_params[MAX_PRIV_PARAMS_SIZE];
        int tmp_params_size = MAX_PRIV_PARAMS_SIZE;
        uint32_t kid[2], i;
        gnutls_openpgp_keyid_t keyid;

        ret =
          gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp,
                                                       keyid);
        if (ret == 0)
          {
            KEYID_IMPORT (kid, keyid);
            ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid,
                                                    tmp_params,
                                                    &tmp_params_size);
          }
        else
          ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL,
                                                  tmp_params,
                                                  &tmp_params_size);

        if (ret < 0)
          {
            gnutls_assert ();
            return ret;
          }

        ret = privkey_to_pubkey (pk,
                                 tmp_params, tmp_params_size,
                                 params, params_size);

        for (i = 0; i < tmp_params_size; i++)
          _gnutls_mpi_release (&tmp_params[i]);

      }

      break;
#endif
    case GNUTLS_PRIVKEY_X509:
      ret = privkey_to_pubkey (pk,
                               key->key.x509->params,
                               key->key.x509->params_size, params,
                               params_size);
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  return ret;
}
Пример #9
0
/* Generates a signature of all the previous sent packets in the 
 * handshake procedure. 
 * 20040227: now it works for SSL 3.0 as well
 * 20091031: works for TLS 1.2 too!
 *
 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
 */
int
_gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
				gnutls_pcert_st * cert,
				gnutls_privkey_t pkey,
				gnutls_datum_t * signature)
{
	gnutls_datum_t dconcat;
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_privkey_get_pk_algorithm(pkey, NULL);

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	if (_gnutls_version_has_selectable_sighash(ver))
		return _gnutls_handshake_sign_crt_vrfy12(session, cert,
							 pkey, signature);

	ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha,
		     session->internals.handshake_hash_buffer.data,
		     session->internals.handshake_hash_buffer.length);

	if (ver->id == GNUTLS_SSL3) {
		ret = _gnutls_generate_master(session, 1);
		if (ret < 0) {
			gnutls_assert();
			_gnutls_hash_deinit(&td_sha, NULL);
			return ret;
		}

		ret =
		    _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
						      session->security_parameters.
						      master_secret,
						      GNUTLS_MASTER_SIZE);
		if (ret < 0)
			return gnutls_assert_val(ret);
	} else
		_gnutls_hash_deinit(&td_sha, &concat[16]);

	/* ensure 1024 bit DSA keys are used */
	ret =
	    _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
					       GNUTLS_SIGN_UNKNOWN);
	if (ret < 0)
		return gnutls_assert_val(ret);

	switch (pk) {
	case GNUTLS_PK_RSA:
		ret =
		    _gnutls_hash_init(&td_md5,
				      hash_to_entry(GNUTLS_DIG_MD5));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_hash(&td_md5,
			     session->internals.handshake_hash_buffer.data,
			     session->internals.handshake_hash_buffer.
			     length);

		if (ver->id == GNUTLS_SSL3) {
			ret =
			    _gnutls_mac_deinit_ssl3_handshake(&td_md5,
							      concat,
							      session->security_parameters.
							      master_secret,
							      GNUTLS_MASTER_SIZE);
			if (ret < 0)
				return gnutls_assert_val(ret);
		} else
			_gnutls_hash_deinit(&td_md5, concat);

		dconcat.data = concat;
		dconcat.size = 36;
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:

		dconcat.data = &concat[16];
		dconcat.size = 20;
		break;

	default:
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
	}
	ret =
	    sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;
}
Пример #10
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_sign_data(gnutls_session_t session,
			    gnutls_pcert_st * cert, gnutls_privkey_t pkey,
			    gnutls_datum_t * params,
			    gnutls_datum_t * signature,
			    gnutls_sign_algorithm_t * sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	const mac_entry_st *hash_algo;

	*sign_algo = _gnutls_session_get_sign_algo(session, cert);
	if (*sign_algo == GNUTLS_SIGN_UNKNOWN) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	gnutls_sign_algorithm_set_server(session, *sign_algo);

	hash_algo =
	    hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo));
	if (hash_algo == NULL)
		return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);

	_gnutls_handshake_log
	    ("HSK[%p]: signing handshake data: using %s\n", session,
	     gnutls_sign_algorithm_get_name(*sign_algo));

	ret = _gnutls_hash_init(&td_sha, hash_algo);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha, session->security_parameters.client_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, session->security_parameters.server_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, params->data, params->size);

	switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) {
	case GNUTLS_PK_RSA:
		if (!_gnutls_version_has_selectable_sighash(ver)) {
			digest_hd_st td_md5;

			ret =
			    _gnutls_hash_init(&td_md5,
					      hash_to_entry
					      (GNUTLS_DIG_MD5));
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}

			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     client_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     server_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5, params->data, params->size);

			_gnutls_hash_deinit(&td_md5, concat);
			_gnutls_hash_deinit(&td_sha, &concat[16]);

			dconcat.data = concat;
			dconcat.size = 36;
		} else {	/* TLS 1.2 way */

			_gnutls_hash_deinit(&td_sha, concat);

			dconcat.data = concat;
			dconcat.size =
			    _gnutls_hash_get_algo_len(hash_algo);
		}
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:
		_gnutls_hash_deinit(&td_sha, concat);

		if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) {
			gnutls_assert();
			return GNUTLS_E_INTERNAL_ERROR;
		}
		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(hash_algo);
		break;

	default:
		gnutls_assert();
		_gnutls_hash_deinit(&td_sha, NULL);
		return GNUTLS_E_INTERNAL_ERROR;
	}

	ret =
	    sign_tls_hash(session, hash_algo, cert, pkey, &dconcat,
			  signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;

}