Ejemplo n.º 1
0
/* this is _gnutls_handshake_verify_cert_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
                                      gnutls_pcert_st*  cert,
                                      gnutls_datum_t * signature,
                                      gnutls_sign_algorithm_t sign_algo)
{
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_datum_t dconcat;
  gnutls_sign_algorithm_t _sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  hash_algo = handshake_td->algorithm;
  _sign_algo =
    _gnutls_x509_pk_to_sign (pk, hash_algo);

  if (_sign_algo != sign_algo)
    {
      handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
      hash_algo = handshake_td->algorithm;
      _sign_algo =
        _gnutls_x509_pk_to_sign (pk, hash_algo);
      if (sign_algo != _sign_algo)
        {
          gnutls_assert ();
          return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
        }
    }

  ret = _gnutls_hash_copy (&td, handshake_td);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_HASH_FAILED;
    }

  _gnutls_hash_deinit (&td, concat);

  dconcat.data = concat;
  dconcat.size = _gnutls_hash_get_algo_len (hash_algo);

  ret =
    verify_tls_hash (ver, cert, &dconcat, signature, 0, pk);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Ejemplo n.º 2
0
/* Returns a requested by the peer signature algorithm that
 * matches the given certificate's public key algorithm. 
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo(gnutls_session_t session,
			      gnutls_pcert_st * cert)
{
	unsigned i;
	int ret;
	const version_entry_st *ver = get_version(session);
	sig_ext_st *priv;
	extension_priv_data_t epriv;
	unsigned int cert_algo;

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

	cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
					 &epriv);
	priv = epriv;

	if (ret < 0 || !_gnutls_version_has_selectable_sighash(ver)
	    || priv->sign_algorithms_size == 0)
		/* none set, allow SHA-1 only */
	{
		ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
		if (_gnutls_session_sign_algo_enabled(session, ret) < 0)
			goto fail;
		return ret;
	}

	for (i = 0; i < priv->sign_algorithms_size; i++) {
		if (gnutls_sign_get_pk_algorithm(priv->sign_algorithms[i])
		    == cert_algo) {
			if (_gnutls_pubkey_compatible_with_sig
			    (session, cert->pubkey, ver,
			     priv->sign_algorithms[i]) < 0)
				continue;

			if (_gnutls_session_sign_algo_enabled
			    (session, priv->sign_algorithms[i]) < 0)
				continue;

			return priv->sign_algorithms[i];
		}
	}

 fail:
	return GNUTLS_SIGN_UNKNOWN;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/* returns the KX algorithms that are supported by a
 * certificate. (Eg a certificate with RSA params, supports
 * GNUTLS_KX_RSA algorithm).
 * This function also uses the KeyUsage field of the certificate
 * extensions in order to disable unneded algorithms.
 */
int
_gnutls_selected_cert_supported_kx (gnutls_session_t session,
                                    gnutls_kx_algorithm_t * alg,
                                    int *alg_size)
{
  gnutls_kx_algorithm_t kx;
  gnutls_pk_algorithm_t pk, cert_pk;
  gnutls_pcert_st *cert;
  int i;

  if (session->internals.selected_cert_list_length == 0)
    {
      *alg_size = 0;
      return 0;
    }

  cert = &session->internals.selected_cert_list[0];
  cert_pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
  i = 0;

  for (kx = 0; kx < MAX_ALGOS; kx++)
    {
      pk = _gnutls_map_pk_get_pk (kx);
      if (pk == cert_pk)
        {
          /* then check key usage */
          if (_gnutls_check_key_usage (cert, kx) == 0)
            {
              alg[i] = kx;
              i++;
              
              if (i > *alg_size)
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
            }
        }
    }

  if (i == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  *alg_size = i;

  return 0;
}
Ejemplo n.º 5
0
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
				    gnutls_pcert_st * cert,
				    gnutls_datum_t * signature,
				    gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_HASH_SIZE];
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
	const mac_entry_st *me;

	ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_sign_algorithm_set_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.
			      handshake_hash_buffer_prev_len, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

	dconcat.data = concat;
	dconcat.size = _gnutls_hash_get_algo_len(me);

	ret =
	    verify_tls_hash(session, ver, cert, &dconcat, signature, 0,
			    sign_algo, pk);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}
Ejemplo n.º 6
0
/* Returns a requested by the peer signature algorithm that
 * matches the given certificate's public key algorithm. 
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert)
{
  unsigned i;
  int ret;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  sig_ext_st *priv;
  extension_priv_data_t epriv;
  unsigned int cert_algo;
  
  cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  ret =
    _gnutls_ext_get_session_data (session,
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
                                  &epriv);
  priv = epriv.ptr;

  if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
      || priv->sign_algorithms_size == 0)
    /* none set, allow SHA-1 only */
    {
      return gnutls_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1);
    }

  for (i = 0; i < priv->sign_algorithms_size; i++)
    {
      if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert_algo)
        {
          if (_gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, priv->sign_algorithms[i]) < 0)
            continue;

          if (_gnutls_session_sign_algo_enabled(session, priv->sign_algorithms[i]) < 0)
            continue;

          return priv->sign_algorithms[i];
        }
    }

  return GNUTLS_SIGN_UNKNOWN;
}
Ejemplo n.º 7
0
/* if the peer's certificate is of 512 bits or less, returns non zero.
 */
int
_gnutls_peers_cert_less_512 (gnutls_session_t session)
{
  gnutls_pcert_st peer_cert;
  int ret;
  cert_auth_info_t info = _gnutls_get_auth_info (session);

  if (info == NULL || info->ncerts == 0)
    {
      gnutls_assert ();
      /* we need this in order to get peer's certificate */
      return 0;
    }

  if ((ret =
       _gnutls_get_auth_info_pcert (&peer_cert,
                                    session->security_parameters.cert_type,
                                    info)) < 0)
    {
      gnutls_assert ();
      return 0;
    }

  if (gnutls_pubkey_get_pk_algorithm(peer_cert.pubkey, NULL) != GNUTLS_PK_RSA)
    {
      gnutls_assert ();
      gnutls_pcert_deinit (&peer_cert);
      return 0;
    }

  if (_gnutls_pubkey_is_over_rsa_512(peer_cert.pubkey) < 0)
    {
      gnutls_pcert_deinit (&peer_cert);
      return 1;
    }

  gnutls_pcert_deinit (&peer_cert);

  return 0;
}
Ejemplo n.º 8
0
Blob
PublicKey::encrypt(const Blob& data) const
{
    if (!pk)
        throw CryptoException("Can't read public key !");

    unsigned key_len = 0;
    int err = gnutls_pubkey_get_pk_algorithm(pk, &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 max_block_sz = key_len / 8 - 11;
    unsigned cypher_block_sz = key_len / 8;
    unsigned block_num = data.empty() ? 1 : 1 + (data.size() - 1) / max_block_sz;

    Blob ret;
    auto eb = data.cbegin();
    auto ee = data.cend();
    for (unsigned i=0; i<block_num; i++) {
        auto blk_sz = std::min<unsigned>(ee - eb, max_block_sz);
        const gnutls_datum_t dat {(uint8_t*)&(*eb), blk_sz};
        gnutls_datum_t encrypted;
        err = gnutls_pubkey_encrypt_data(pk, 0, &dat, &encrypted);
        if (err != GNUTLS_E_SUCCESS)
            throw CryptoException(std::string("Can't encrypt data: ") + gnutls_strerror(err));
        if (encrypted.size != cypher_block_sz)
            throw CryptoException("Unexpected cypherblock size");
        ret.insert(ret.end(), encrypted.data, encrypted.data+encrypted.size);
        eb += blk_sz;
        gnutls_free(encrypted.data);
    }

    return ret;
}
Ejemplo n.º 9
0
void doit(void)
{
	gnutls_x509_privkey_t key;
	gnutls_x509_crt_t crt;
	gnutls_pubkey_t pubkey;
	gnutls_privkey_t privkey;
	gnutls_sign_algorithm_t sign_algo;
	gnutls_datum_t signature;
	gnutls_datum_t signature2;
	int ret;
	size_t i;

	global_init();

	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(6);

	for (i = 0; i < sizeof(key_dat) / sizeof(key_dat[0]); i++) {
		if (debug)
			success("loop %d\n", (int) i);

		ret = gnutls_x509_privkey_init(&key);
		if (ret < 0)
			fail("gnutls_x509_privkey_init\n");

		ret =
		    gnutls_x509_privkey_import(key, &key_dat[i],
						GNUTLS_X509_FMT_PEM);
		if (ret < 0)
			fail("gnutls_x509_privkey_import\n");

		ret = gnutls_pubkey_init(&pubkey);
		if (ret < 0)
			fail("gnutls_privkey_init\n");

		ret = gnutls_privkey_init(&privkey);
		if (ret < 0)
			fail("gnutls_pubkey_init\n");

		ret = gnutls_privkey_import_x509(privkey, key, 0);
		if (ret < 0)
			fail("gnutls_privkey_import_x509\n");

		ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, 0,
						&hash_data, &signature2);
		if (ret < 0)
			fail("gnutls_privkey_sign_hash\n");

		ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
						&raw_data, &signature);
		if (ret < 0)
			fail("gnutls_x509_privkey_sign_hash\n");

		ret = gnutls_x509_crt_init(&crt);
		if (ret < 0)
			fail("gnutls_x509_crt_init\n");

		ret =
		    gnutls_x509_crt_import(crt, &cert_dat[i],
					   GNUTLS_X509_FMT_PEM);
		if (ret < 0)
			fail("gnutls_x509_crt_import\n");

		ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
		if (ret < 0)
			fail("gnutls_x509_pubkey_import\n");

		ret =
		    gnutls_x509_crt_get_signature_algorithm(crt);
		if (ret != GNUTLS_SIGN_RSA_SHA1)
			fail("gnutls_crt_get_signature_algorithm\n");

		ret =
		    gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &hash_data,
					      &signature);
		if (ret < 0)
			fail("gnutls_x509_pubkey_verify_hash2\n");

		ret =
		    gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &hash_data,
					      &signature2);
		if (ret < 0)
			fail("gnutls_x509_pubkey_verify_hash-1 (hashed data)\n");

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
					      &invalid_hash_data,
					      &signature2);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			fail("gnutls_x509_pubkey_verify_hash-2 (hashed data)\n");

		sign_algo =
		    gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm
				      (pubkey, NULL), GNUTLS_DIG_SHA1);

		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						&hash_data, &signature2);
		if (ret < 0)
			fail("gnutls_x509_pubkey_verify_hash2-1 (hashed data)\n");

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						&invalid_hash_data,
						&signature2);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			fail("gnutls_x509_pubkey_verify_hash2-2 (hashed data)\n");

		/* test the raw interface */
		gnutls_free(signature.data);
		signature.data = NULL;

		if (gnutls_pubkey_get_pk_algorithm(pubkey, NULL) ==
		    GNUTLS_PK_RSA) {
			ret =
			    gnutls_privkey_sign_hash(privkey,
						     GNUTLS_DIG_SHA1,
						     GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
						     &hash_data,
						     &signature);
			if (ret < 0)
				fail("gnutls_privkey_sign_hash: %s\n",
				     gnutls_strerror(ret));

			sign_algo =
			    gnutls_pk_to_sign
			    (gnutls_pubkey_get_pk_algorithm(pubkey, NULL),
			     GNUTLS_DIG_SHA1);

			ret =
			    gnutls_pubkey_verify_hash2(pubkey, sign_algo,
							GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA,
							&hash_data,
							&signature);
			if (ret < 0)
				fail("gnutls_pubkey_verify_hash-3 (raw hashed data)\n");

			gnutls_free(signature.data);
			/* test the legacy API */
			ret =
			    gnutls_privkey_sign_raw_data(privkey, 0,
							 &hash_data,
							 &signature);
			if (ret < 0)
				fail("gnutls_privkey_sign_raw_data: %s\n",
				     gnutls_strerror(ret));

			ret =
			    gnutls_pubkey_verify_hash2(pubkey, sign_algo,
							GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA,
							&hash_data,
							&signature);
			if (ret < 0)
				fail("gnutls_pubkey_verify_hash-4 (legacy raw hashed data)\n");
		}
		gnutls_free(signature.data);
		gnutls_free(signature2.data);
		gnutls_x509_privkey_deinit(key);
		gnutls_x509_crt_deinit(crt);
		gnutls_privkey_deinit(privkey);
		gnutls_pubkey_deinit(pubkey);
	}

	gnutls_global_deinit();
}
Ejemplo n.º 10
0
void
pkcs11_test_sign(FILE * outfile, const char *url, unsigned int flags,
	    common_info_st * info)
{
	gnutls_privkey_t privkey;
	gnutls_pubkey_t pubkey;
	int ret;
	gnutls_datum_t data, sig = {NULL, 0};
	int pk;

	pkcs11_common(info);

	FIX(url, outfile, 0, info);

	data.data = (void*)TEST_DATA;
	data.size = sizeof(TEST_DATA)-1;

	ret = gnutls_privkey_init(&privkey);
	if (ret < 0) {
		fprintf(stderr, "Error in %s:%d: %s\n", __func__,
			__LINE__, gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_pubkey_init(&pubkey);
	if (ret < 0) {
		fprintf(stderr, "Error in %s:%d: %s\n", __func__,
			__LINE__, gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_privkey_import_url(privkey, url, flags);
	if (ret < 0) {
		fprintf(stderr, "Cannot import private key: %s\n",
			gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, flags);
	if (ret < 0) {
		fprintf(stderr, "Cannot import public key: %s\n",
			gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &data, &sig);
	if (ret < 0) {
		fprintf(stderr, "Cannot sign data: %s\n",
			gnutls_strerror(ret));
		exit(1);
	}

	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);

	fprintf(stderr, "Verifying against private key parameters... ");
	ret = gnutls_pubkey_verify_data2(pubkey, gnutls_pk_to_sign(pk, GNUTLS_DIG_SHA1),
		0, &data, &sig);
	if (ret < 0) {
		fprintf(stderr, "Cannot verify signed data: %s\n",
			gnutls_strerror(ret));
		exit(1);
	}

	fprintf(stderr, "ok\n");

	/* now try to verify against a public key within the token */
	gnutls_pubkey_deinit(pubkey);
	ret = gnutls_pubkey_init(&pubkey);
	if (ret < 0) {
		fprintf(stderr, "Error in %s:%d: %s\n", __func__,
			__LINE__, gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_pubkey_import_url(pubkey, url, flags);
	if (ret < 0) {
		fprintf(stderr, "Cannot find a corresponding public key object in token: %s\n",
			gnutls_strerror(ret));
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			exit(0);
		exit(1);
	}

	fprintf(stderr, "Verifying against public key in the token... ");
	ret = gnutls_pubkey_verify_data2(pubkey, gnutls_pk_to_sign(pk, GNUTLS_DIG_SHA1),
		0, &data, &sig);
	if (ret < 0) {
		fprintf(stderr, "Cannot verify signed data: %s\n",
			gnutls_strerror(ret));
		exit(1);
	}

	fprintf(stderr, "ok\n");

	gnutls_free(sig.data);
	gnutls_pubkey_deinit(pubkey);
	gnutls_privkey_deinit(privkey);
	UNFIX;
}
Ejemplo n.º 11
0
/**
 * gnutls_pkcs11_copy_pubkey:
 * @token_url: A PKCS #11 URL specifying a token
 * @pubkey: The public key to copy
 * @label: The name to be used for the stored data
 * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
 * @key_usage: One of GNUTLS_KEY_*
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a public key object into a PKCS #11 token specified by
 * a URL. Valid flags to mark the key: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.6
 **/
int
gnutls_pkcs11_copy_pubkey(const char *token_url,
			  gnutls_pubkey_t pubkey, const char *label,
			  const gnutls_datum_t *cid,
			  unsigned int key_usage, unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t id_size;
	uint8_t id[20];
	struct ck_attribute a[MAX_ASIZE];
	gnutls_pk_algorithm_t pk;
	ck_object_class_t class = CKO_PUBLIC_KEY;
	ck_object_handle_t ctx;
	unsigned a_val;
	ck_key_type_t type;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

	ret = pkcs11_url_to_info(token_url, &info, 0);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);

	a[1].type = CKA_TOKEN;
	a[1].value = (void *) &tval;
	a[1].value_len = sizeof(tval);

	a_val = 2;

	ret = add_pubkey(pubkey, a, &a_val);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (label) {
		a[a_val].type = CKA_LABEL;
		a[a_val].value = (void *) label;
		a[a_val].value_len = strlen(label);
		a_val++;
	}

	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
	type = pk_to_key_type(pk);
	FIX_KEY_USAGE(pk, key_usage);

	a[a_val].type = CKA_KEY_TYPE;
	a[a_val].value = &type;
	a[a_val].value_len = sizeof(type);
	a_val++;

	a[a_val].type = CKA_ID;
	if (cid == NULL || cid->size == 0) {
		id_size = sizeof(id);
		ret = gnutls_pubkey_get_key_id(pubkey, 0, id, &id_size);
		if (ret < 0) {
			  gnutls_assert();
			  goto cleanup;
		}

		a[a_val].value = id;
		a[a_val].value_len = id_size;
	} else {
		a[a_val].value = cid->data;
		a[a_val].value_len = cid->size;
	}
	a_val++;

	mark_flags(flags, a, &a_val, sinfo.trusted);

	a[a_val].type = CKA_VERIFY;
	if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
		a[a_val].value = (void*)&tval;
		a[a_val].value_len = sizeof(tval);
	} else {
		a[a_val].value = (void*)&fval;
		a[a_val].value_len = sizeof(fval);
	}
	a_val++;

	if (pk == GNUTLS_PK_RSA) {
		a[a_val].type = CKA_ENCRYPT;
		if (key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) {
			a[a_val].value = (void*)&tval;
			a[a_val].value_len = sizeof(tval);
		} else {
			a[a_val].value = (void*)&fval;
			a[a_val].value_len = sizeof(fval);
		}
		a_val++;
	}

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	clean_pubkey(a, a_val);
	pkcs11_close_session(&sinfo);
	return ret;

}
Ejemplo n.º 12
0
/* Verifies a TLS signature (like the one in the client certificate
 * verify message). 
 */
int
_gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
                                    gnutls_pcert_st *cert,
                                    gnutls_datum_t * signature,
                                    gnutls_sign_algorithm_t sign_algo)
{
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  gnutls_datum_t dconcat;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  _gnutls_handshake_log ("HSK[%p]: verify cert vrfy: using %s\n",
                    session, gnutls_sign_algorithm_get_name (sign_algo));

  if (session->security_parameters.handshake_mac_handle_type ==
      HANDSHAKE_MAC_TYPE_12)
    {
      return _gnutls_handshake_verify_cert_vrfy12 (session, cert, signature,
                                                   sign_algo);
    }
  else if (session->security_parameters.handshake_mac_handle_type !=
           HANDSHAKE_MAC_TYPE_10)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ret =
    _gnutls_hash_copy (&td_md5,
                       &session->internals.handshake_mac_handle.tls10.md5);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    _gnutls_hash_copy (&td_sha,
                       &session->internals.handshake_mac_handle.tls10.sha);
  if (ret < 0)
    {
      gnutls_assert ();
      _gnutls_hash_deinit (&td_md5, NULL);
      return GNUTLS_E_HASH_FAILED;
    }

  if (ver == GNUTLS_SSL3)
    {
      ret = _gnutls_generate_master (session, 1);
      if (ret < 0)
        {
          _gnutls_hash_deinit (&td_md5, NULL);
          _gnutls_hash_deinit (&td_sha, NULL);
          return gnutls_assert_val(ret);
        }

      ret = _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
                                         session->
                                         security_parameters.master_secret,
                                         GNUTLS_MASTER_SIZE);
      if (ret < 0)
        {
          _gnutls_hash_deinit (&td_sha, NULL);
          return gnutls_assert_val(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_md5, concat);
      _gnutls_hash_deinit (&td_sha, &concat[16]);
    }

  dconcat.data = concat;
  dconcat.size = 20 + 16;       /* md5+ sha */

  ret =
    verify_tls_hash (ver, cert, &dconcat, signature, 16,
                        gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL));
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Ejemplo n.º 13
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;
  opaque concat[MAX_SIG_SIZE];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_digest_algorithm_t 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;
    }

  hash_algo = _gnutls_sign_get_hash_algorithm (*sign_algo);

  _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_pubkey_get_pk_algorithm(cert->pubkey, NULL))
    {
    case GNUTLS_PK_RSA:
      if (!_gnutls_version_has_selectable_sighash (ver))
        {
          digest_hd_st td_md5;

          ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_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:
      _gnutls_hash_deinit (&td_sha, concat);

      if ((hash_algo != GNUTLS_DIG_SHA1) && (hash_algo != GNUTLS_DIG_SHA224)
          && (hash_algo != GNUTLS_DIG_SHA256))
        {
          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;

}
Ejemplo n.º 14
0
static int
verify_tls_hash(gnutls_session_t session,
		const version_entry_st * ver, gnutls_pcert_st * cert,
		const gnutls_datum_t * hash_concat,
		gnutls_datum_t * signature, size_t sha1pos,
		gnutls_sign_algorithm_t sign_algo,
		gnutls_pk_algorithm_t pk_algo)
{
	int ret;
	gnutls_datum_t vdata;
	unsigned int key_usage = 0, flags;

	if (cert == NULL) {
		gnutls_assert();
		return GNUTLS_E_CERTIFICATE_ERROR;
	}

	gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);

	/* If the certificate supports signing continue.
	 */
	if (key_usage != 0)
		if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
			gnutls_assert();
			_gnutls_audit_log(session,
					  "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
		}

	if (pk_algo == GNUTLS_PK_UNKNOWN)
		pk_algo =
		    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
	switch (pk_algo) {
	case GNUTLS_PK_RSA:

		vdata.data = hash_concat->data;
		vdata.size = hash_concat->size;

		/* verify signature */
		if (!_gnutls_version_has_selectable_sighash(ver))
			flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
		else
			flags = 0;
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:
		vdata.data = &hash_concat->data[sha1pos];
		vdata.size = hash_concat->size - sha1pos;

		flags = 0;

		break;
	default:
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	gnutls_sign_algorithm_set_server(session, sign_algo);

	ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags,
					 &vdata, signature);

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


	return 0;
}
Ejemplo n.º 15
0
/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
 * Cert is the certificate of the corresponding private key. It is only checked if
 * it supports signing.
 */
static int
sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo,
	      gnutls_pcert_st * cert, gnutls_privkey_t pkey,
	      const gnutls_datum_t * hash_concat,
	      gnutls_datum_t * signature)
{
	const version_entry_st *ver = get_version(session);
	unsigned int key_usage = 0;

	/* If our certificate supports signing
	 */
	if (cert != NULL) {
		gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);

		if (key_usage != 0)
			if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
				gnutls_assert();
				_gnutls_audit_log(session,
						  "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
			}

		/* External signing. Deprecated. To be removed. */
		if (!pkey) {
			int ret;

			if (!session->internals.sign_func)
				return
				    gnutls_assert_val
				    (GNUTLS_E_INSUFFICIENT_CREDENTIALS);

			if (!_gnutls_version_has_selectable_sighash(ver))
				return (*session->internals.sign_func)
				    (session,
				     session->internals.sign_func_userdata,
				     cert->type, &cert->cert, hash_concat,
				     signature);
			else {
				gnutls_datum_t digest;

				ret =
				    _gnutls_set_datum(&digest,
						      hash_concat->data,
						      hash_concat->size);
				if (ret < 0)
					return gnutls_assert_val(ret);

				ret =
				    pk_prepare_hash
				    (gnutls_pubkey_get_pk_algorithm
				     (cert->pubkey, NULL), hash_algo,
				     &digest);
				if (ret < 0) {
					gnutls_assert();
					goto es_cleanup;
				}

				ret = (*session->internals.sign_func)
				    (session,
				     session->internals.sign_func_userdata,
				     cert->type, &cert->cert, &digest,
				     signature);
			      es_cleanup:
				gnutls_free(digest.data);

				return ret;
			}
		}
	}

	if (!_gnutls_version_has_selectable_sighash(ver))
		return gnutls_privkey_sign_raw_data(pkey, 0, hash_concat,
						    signature);
	else
		return gnutls_privkey_sign_hash(pkey, 
						(gnutls_digest_algorithm_t)hash_algo->id,
						0, hash_concat, signature);
}
Ejemplo n.º 16
0
static
void test_sig(gnutls_pk_algorithm_t pk, unsigned hash, unsigned bits)
{
	gnutls_pubkey_t pubkey;
	gnutls_privkey_t privkey;
	gnutls_sign_algorithm_t sign_algo;
	gnutls_datum_t signature;
	const gnutls_datum_t *hash_data;
	int ret;
	unsigned j;

	if (hash == GNUTLS_DIG_SHA1)
		hash_data = &sha1_data;
	else if (hash == GNUTLS_DIG_SHA256)
		hash_data = &sha256_data;
	else
		abort();

	sign_algo =
	    gnutls_pk_to_sign(pk, hash);

	for (j = 0; j < 100; j++) {
		ret = gnutls_pubkey_init(&pubkey);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_privkey_init(&privkey);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_privkey_generate(privkey, pk, bits, 0);
		if (ret < 0)
			ERR(__LINE__);

		ret =
		    gnutls_privkey_sign_hash(privkey, hash,
					     0, hash_data,
					     &signature);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
		if (ret < 0)
			ERR(__LINE__);

		ret =
		    gnutls_pubkey_verify_hash2(pubkey,
						sign_algo, 0,
						hash_data, &signature);
		if (ret < 0)
			ERR(__LINE__);

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey,
						sign_algo, 0,
						&invalid_hash_data,
						&signature);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			ERR(__LINE__);

		sign_algo =
		    gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm
				      (pubkey, NULL), hash);

		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						hash_data, &signature);
		if (ret < 0)
			ERR(__LINE__);

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						&invalid_hash_data,
						&signature);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			ERR(__LINE__);

		/* test the raw interface */
		gnutls_free(signature.data);
		signature.data = NULL;

		if (pk == GNUTLS_PK_RSA) {
			ret =
			    gnutls_privkey_sign_hash(privkey,
						     hash,
						     GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
						     hash_data,
						     &signature);
			if (ret < 0)
				ERR(__LINE__);

			sign_algo =
			    gnutls_pk_to_sign
			    (gnutls_pubkey_get_pk_algorithm
			     (pubkey, NULL), hash);

			ret =
			    gnutls_pubkey_verify_hash2(pubkey,
							sign_algo,
							GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA,
							hash_data,
							&signature);
			if (ret < 0)
				ERR(__LINE__);

		}
		gnutls_free(signature.data);
		gnutls_privkey_deinit(privkey);
		gnutls_pubkey_deinit(pubkey);
	}

}
Ejemplo n.º 17
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 value;
 */
int
_gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
                                  gnutls_pcert_st* cert, gnutls_privkey_t pkey,
                                  gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  if (session->security_parameters.handshake_mac_handle_type ==
      HANDSHAKE_MAC_TYPE_12)
    {
      return _gnutls_handshake_sign_cert_vrfy12 (session, cert, pkey,
                                                 signature);
    }
  else if (session->security_parameters.handshake_mac_handle_type !=
           HANDSHAKE_MAC_TYPE_10)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ret =
    _gnutls_hash_copy (&td_sha,
                       &session->internals.handshake_mac_handle.tls10.sha);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (ver == 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(cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN);
  if (ret < 0)
    return gnutls_assert_val(ret);

  switch (pk)
    {
    case GNUTLS_PK_RSA:
      ret =
        _gnutls_hash_copy (&td_md5,
                           &session->internals.handshake_mac_handle.tls10.
                           md5);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      if (ver == 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:

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

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

  return ret;
}
Ejemplo n.º 18
0
static int add_pubkey(gnutls_pubkey_t pubkey, struct ck_attribute *a, unsigned *a_val)
{
	gnutls_pk_algorithm_t pk;
	int ret;

	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);

	switch (pk) {
	case GNUTLS_PK_RSA: {
		gnutls_datum_t m, e;

		ret = gnutls_pubkey_export_rsa_raw(pubkey, &m, &e);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		/* PKCS#11 defines integers as unsigned having most significant byte
		 * first, e.g., 32768 = 0x80 0x00. This is interpreted literraly by
		 * some HSMs which do not accept an integer with a leading zero */
		skip_leading_zeros(&m);
		skip_leading_zeros(&e);

		a[*a_val].type = CKA_MODULUS;
		a[*a_val].value = m.data;
		a[*a_val].value_len = m.size;
		(*a_val)++;

		a[*a_val].type = CKA_PUBLIC_EXPONENT;
		a[*a_val].value = e.data;
		a[*a_val].value_len = e.size;
		(*a_val)++;
		break;
	}
	case GNUTLS_PK_DSA: {
		gnutls_datum_t p, q, g, y;

		ret = gnutls_pubkey_export_dsa_raw(pubkey, &p, &q, &g, &y);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		skip_leading_zeros(&p);
		skip_leading_zeros(&q);
		skip_leading_zeros(&g);
		skip_leading_zeros(&y);

		a[*a_val].type = CKA_PRIME;
		a[*a_val].value = p.data;
		a[*a_val].value_len = p.size;
		(*a_val)++;

		a[*a_val].type = CKA_SUBPRIME;
		a[*a_val].value = q.data;
		a[*a_val].value_len = q.size;
		(*a_val)++;

		a[*a_val].type = CKA_BASE;
		a[*a_val].value = g.data;
		a[*a_val].value_len = g.size;
		(*a_val)++;

		a[*a_val].type = CKA_VALUE;
		a[*a_val].value = y.data;
		a[*a_val].value_len = y.size;
		(*a_val)++;
		break;
	}
	case GNUTLS_PK_EC: {
		gnutls_datum_t params, point;

		ret = gnutls_pubkey_export_ecc_x962(pubkey, &params, &point);
		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		a[*a_val].type = CKA_EC_PARAMS;
		a[*a_val].value = params.data;
		a[*a_val].value_len = params.size;
		(*a_val)++;

		a[*a_val].type = CKA_EC_POINT;
		a[*a_val].value = point.data;
		a[*a_val].value_len = point.size;
		(*a_val)++;
		break;
	}
	default:
		_gnutls_debug_log("requested writing public key of unsupported type %u\n", (unsigned)pk);
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
	}

	return 0;
}
Ejemplo n.º 19
0
/* Verifies a TLS signature (like the one in the client certificate
 * verify message). 
 */
int
_gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
				  gnutls_pcert_st * cert,
				  gnutls_datum_t * signature,
				  gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);

	_gnutls_handshake_log("HSK[%p]: verify cert vrfy: using %s\n",
			      session,
			      gnutls_sign_algorithm_get_name(sign_algo));

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

	if (_gnutls_version_has_selectable_sighash(ver))
		return _gnutls_handshake_verify_crt_vrfy12(session, cert,
							   signature,
							   sign_algo);

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

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

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

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

		ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat,
							session->security_parameters.
							master_secret,
							GNUTLS_MASTER_SIZE);
		if (ret < 0) {
			_gnutls_hash_deinit(&td_sha, NULL);
			return gnutls_assert_val(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_md5, concat);
		_gnutls_hash_deinit(&td_sha, &concat[16]);
	}

	dconcat.data = concat;
	dconcat.size = 20 + 16;	/* md5+ sha */

	ret =
	    verify_tls_hash(session, ver, cert, &dconcat, signature, 16,
			    GNUTLS_SIGN_UNKNOWN,
			    gnutls_pubkey_get_pk_algorithm(cert->pubkey,
							   NULL));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;
}
Ejemplo n.º 20
0
void
doit (void)
{
  gnutls_x509_privkey_t key;
  gnutls_x509_crt_t crt;
  gnutls_pubkey_t pubkey;
  gnutls_privkey_t privkey;
  gnutls_digest_algorithm_t hash_algo;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_datum_t signature;
  gnutls_datum_t signature2;
  int ret;
  size_t i;

  gnutls_global_init ();

  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (6);

  for (i = 0; i < sizeof (key_dat) / sizeof (key_dat[0]); i++)
    {
      if (debug)
        success ("loop %d\n", (int) i);

      ret = gnutls_x509_privkey_init (&key);
      if (ret < 0)
        fail ("gnutls_x509_privkey_init\n");

      ret =
        gnutls_x509_privkey_import (key, &key_dat[i], GNUTLS_X509_FMT_PEM);
      if (ret < 0)
        fail ("gnutls_x509_privkey_import\n");

      ret = gnutls_pubkey_init (&pubkey);
      if (ret < 0)
        fail ("gnutls_privkey_init\n");

      ret = gnutls_privkey_init (&privkey);
      if (ret < 0)
        fail ("gnutls_pubkey_init\n");

      ret = gnutls_privkey_import_x509 (privkey, key, 0);
      if (ret < 0)
        fail ("gnutls_privkey_import_x509\n");

      ret = gnutls_privkey_sign_hash (privkey, GNUTLS_DIG_SHA1, 0,
				      &hash_data, &signature2);
      if (ret < 0)
        fail ("gnutls_privkey_sign_hash\n");

      ret = gnutls_privkey_sign_data (privkey, GNUTLS_DIG_SHA1, 0,
				      &raw_data, &signature);
      if (ret < 0)
        fail ("gnutls_x509_privkey_sign_hash\n");

      ret = gnutls_x509_crt_init (&crt);
      if (ret < 0)
        fail ("gnutls_x509_crt_init\n");

      ret = gnutls_x509_crt_import (crt, &cert_dat[i], GNUTLS_X509_FMT_PEM);
      if (ret < 0)
        fail ("gnutls_x509_crt_import\n");

      ret =
        gnutls_pubkey_import_x509 (pubkey, crt, 0);
      if (ret < 0)
        fail ("gnutls_x509_pubkey_import\n");

      ret =
        gnutls_pubkey_get_verify_algorithm (pubkey, &signature, &hash_algo);
      if (ret < 0 || hash_algo != GNUTLS_DIG_SHA1)
        fail ("gnutls_x509_crt_get_verify_algorithm\n");

      ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature);
      if (ret < 0)
        fail ("gnutls_x509_pubkey_verify_hash\n");

      ret =
        gnutls_pubkey_get_verify_algorithm (pubkey, &signature2, &hash_algo);
      if (ret < 0 || hash_algo != GNUTLS_DIG_SHA1)
        fail ("gnutls_x509_crt_get_verify_algorithm (hashed data)\n");

      ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature2);
      if (ret < 0)
        fail ("gnutls_x509_pubkey_verify_hash-1 (hashed data)\n");

      /* should fail */
      ret = gnutls_pubkey_verify_hash (pubkey, 0, &invalid_hash_data, &signature2);
      if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
        fail ("gnutls_x509_pubkey_verify_hash-2 (hashed data)\n");
        
      sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm(pubkey, NULL),
                                    GNUTLS_DIG_SHA1);

      ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &hash_data, &signature2);
      if (ret < 0)
        fail ("gnutls_x509_pubkey_verify_hash2-1 (hashed data)\n");

      /* should fail */
      ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &invalid_hash_data, &signature2);
      if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
        fail ("gnutls_x509_pubkey_verify_hash2-2 (hashed data)\n");


      gnutls_free(signature.data);
      gnutls_free(signature2.data);
      gnutls_x509_privkey_deinit (key);
      gnutls_x509_crt_deinit (crt);
      gnutls_privkey_deinit (privkey);
      gnutls_pubkey_deinit (pubkey);
    }

  gnutls_global_deinit ();
}
Ejemplo n.º 21
0
static int
verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert,
                    const gnutls_datum_t * hash_concat,
                    gnutls_datum_t * signature, size_t sha1pos,
                    gnutls_pk_algorithm_t pk_algo)
{
  int ret;
  gnutls_datum_t vdata;
  unsigned int key_usage = 0, flags;

  if (cert == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_CERTIFICATE_ERROR;
    }

  gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);

  /* If the certificate supports signing continue.
   */
  if (key_usage != 0)
    if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
      {
        gnutls_assert ();
        return GNUTLS_E_KEY_USAGE_VIOLATION;
      }

  if (pk_algo == GNUTLS_PK_UNKNOWN)
    pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
  switch (pk_algo)
    {
    case GNUTLS_PK_RSA:

      vdata.data = hash_concat->data;
      vdata.size = hash_concat->size;

      /* verify signature */
      if (!_gnutls_version_has_selectable_sighash (ver))
        flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
      else
        flags = 0;


      break;
    case GNUTLS_PK_DSA:

      vdata.data = &hash_concat->data[sha1pos];
      vdata.size = hash_concat->size - sha1pos;

      flags = 0;

      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ret = gnutls_pubkey_verify_hash(cert->pubkey, flags, &vdata,
    signature);

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


  return 0;
}