Exemplo n.º 1
0
/* verifies if the certificate is properly signed.
 * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
 * 
 * 'data' is the signed data
 * 'signature' is the signature!
 */
int
_gnutls_x509_verify_data (gnutls_digest_algorithm_t algo,
                          const gnutls_datum_t * data,
                          const gnutls_datum_t * signature,
                          gnutls_x509_crt_t issuer)
{
  gnutls_pk_params_st issuer_params;
  int ret;

  /* Read the MPI parameters from the issuer's certificate.
   */
  ret =
    _gnutls_x509_crt_get_mpis (issuer, &issuer_params);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    pubkey_verify_data (gnutls_x509_crt_get_pk_algorithm (issuer, NULL), algo,
                        data, signature, &issuer_params);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  /* release all allocated MPIs
   */
  gnutls_pk_params_release(&issuer_params);

  return ret;
}
Exemplo n.º 2
0
/* verifies if the certificate is properly signed.
 * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
 * 
 * 'tbs' is the signed data
 * 'signature' is the signature!
 */
int
_gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
                               const gnutls_datum_t * hash,
                               const gnutls_datum_t * signature,
                               gnutls_x509_crt_t issuer)
{
  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
  int ret, issuer_params_size, i;

  /* Read the MPI parameters from the issuer's certificate.
   */
  issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
  ret =
    _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    pubkey_verify_sig (tbs, hash, signature,
                       gnutls_x509_crt_get_pk_algorithm (issuer, NULL),
                       issuer_params, issuer_params_size);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  /* release all allocated MPIs
   */
  for (i = 0; i < issuer_params_size; i++)
    {
      _gnutls_mpi_release (&issuer_params[i]);
    }

  return ret;
}
Exemplo n.º 3
0
/**
 * gnutls_pubkey_import_x509:
 * @key: The public key
 * @crt: The certificate to be imported
 * @flags: should be zero
 *
 * This function will import the given public key to the abstract
 * #gnutls_pubkey_t type.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt,
			  unsigned int flags)
{
	int ret;

	gnutls_pk_params_release(&key->params);
	/* params initialized in _gnutls_x509_crt_get_mpis */

	key->pk_algorithm =
	    gnutls_x509_crt_get_pk_algorithm(crt, &key->bits);

	ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL);
	if (ret < 0)
		key->key_usage = 0;

	ret = _gnutls_x509_crt_get_mpis(crt, &key->params);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return 0;
}
Exemplo n.º 4
0
/* Checks whether the provided certificates are acceptable
 * according to verification profile specified.
 *
 * @crt: a certificate
 * @issuer: the certificates issuer (allowed to be NULL)
 * @sigalg: the signature algorithm used
 * @flags: the specified verification flags
 */
static unsigned is_level_acceptable(
	gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
	gnutls_sign_algorithm_t sigalg, unsigned flags)
{
	gnutls_certificate_verification_profiles_t profile = GNUTLS_VFLAGS_TO_PROFILE(flags);
	const mac_entry_st *entry;
	int issuer_pkalg = 0, pkalg, ret;
	unsigned bits = 0, issuer_bits = 0, sym_bits = 0;
	gnutls_pk_params_st params;
	gnutls_sec_param_t sp;
	int hash;

	if (profile == 0)
		return 1;

	pkalg = gnutls_x509_crt_get_pk_algorithm(crt, &bits);
	if (pkalg < 0)
		return gnutls_assert_val(0);

	if (issuer) {
		issuer_pkalg = gnutls_x509_crt_get_pk_algorithm(issuer, &issuer_bits);
		if (issuer_pkalg < 0)
			return gnutls_assert_val(0);
	}

	switch (profile) {
		CASE_SEC_PARAM(GNUTLS_PROFILE_VERY_WEAK, GNUTLS_SEC_PARAM_VERY_WEAK);
		CASE_SEC_PARAM(GNUTLS_PROFILE_LOW, GNUTLS_SEC_PARAM_LOW);
		CASE_SEC_PARAM(GNUTLS_PROFILE_LEGACY, GNUTLS_SEC_PARAM_LEGACY);
		CASE_SEC_PARAM(GNUTLS_PROFILE_MEDIUM, GNUTLS_SEC_PARAM_MEDIUM);
		CASE_SEC_PARAM(GNUTLS_PROFILE_HIGH, GNUTLS_SEC_PARAM_HIGH);
		CASE_SEC_PARAM(GNUTLS_PROFILE_ULTRA, GNUTLS_SEC_PARAM_ULTRA);
		case GNUTLS_PROFILE_SUITEB128:
		case GNUTLS_PROFILE_SUITEB192: {
			unsigned curve, issuer_curve;

			/* check suiteB params validity: rfc5759 */

			if (gnutls_x509_crt_get_version(crt) != 3) {
				_gnutls_debug_log("SUITEB: certificate uses an unacceptable version number\n");
				return gnutls_assert_val(0);
			}

			if (sigalg != GNUTLS_SIGN_ECDSA_SHA256 && sigalg != GNUTLS_SIGN_ECDSA_SHA384) {
				_gnutls_debug_log("SUITEB: certificate is not signed using ECDSA-SHA256 or ECDSA-SHA384\n");
				return gnutls_assert_val(0);
			}

			if (pkalg != GNUTLS_PK_EC) {
				_gnutls_debug_log("SUITEB: certificate does not contain ECC parameters\n");
				return gnutls_assert_val(0);
			}

			if (issuer_pkalg != GNUTLS_PK_EC) {
				_gnutls_debug_log("SUITEB: certificate's issuer does not have ECC parameters\n");
				return gnutls_assert_val(0);
			}

			ret = _gnutls_x509_crt_get_mpis(crt, &params);
			if (ret < 0) {
				_gnutls_debug_log("SUITEB: cannot read certificate params\n");
				return gnutls_assert_val(0);
			}

			curve = params.flags;
			gnutls_pk_params_release(&params);

			if (curve != GNUTLS_ECC_CURVE_SECP256R1 &&
				curve != GNUTLS_ECC_CURVE_SECP384R1) {
				_gnutls_debug_log("SUITEB: certificate's ECC params do not contain SECP256R1 or SECP384R1\n");
				return gnutls_assert_val(0);
			}

			if (profile == GNUTLS_PROFILE_SUITEB192) {
				if (curve != GNUTLS_ECC_CURVE_SECP384R1) {
					_gnutls_debug_log("SUITEB192: certificate does not use SECP384R1\n");
					return gnutls_assert_val(0);
				}
			}

			if (issuer != NULL) {
				if (gnutls_x509_crt_get_version(issuer) != 3) {
					_gnutls_debug_log("SUITEB: certificate's issuer uses an unacceptable version number\n");
					return gnutls_assert_val(0);
				}

				ret = _gnutls_x509_crt_get_mpis(issuer, &params);
				if (ret < 0) {
					_gnutls_debug_log("SUITEB: cannot read certificate params\n");
					return gnutls_assert_val(0);
				}

				issuer_curve = params.flags;
				gnutls_pk_params_release(&params);

				if (issuer_curve != GNUTLS_ECC_CURVE_SECP256R1 &&
					issuer_curve != GNUTLS_ECC_CURVE_SECP384R1) {
					_gnutls_debug_log("SUITEB: certificate's issuer ECC params do not contain SECP256R1 or SECP384R1\n");
					return gnutls_assert_val(0);
				}

				if (issuer_curve < curve) {
					_gnutls_debug_log("SUITEB: certificate's issuer ECC params are weaker than the certificate's\n");
					return gnutls_assert_val(0);
				}

				if (sigalg == GNUTLS_SIGN_ECDSA_SHA256 && 
					issuer_curve == GNUTLS_ECC_CURVE_SECP384R1) {
					_gnutls_debug_log("SUITEB: certificate is signed with ECDSA-SHA256 when using SECP384R1\n");
					return gnutls_assert_val(0);
				}
			}

			break;
		}
	}

	return 1;
}
Exemplo n.º 5
0
/* verifies if the certificate is properly signed.
 * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
 * 
 * 'data' is the signed data
 * 'signature' is the signature!
 */
static int
_gnutls_x509_verify_data(gnutls_sign_algorithm_t sign,
			 const gnutls_datum_t * data,
			 const gnutls_datum_t * signature,
			 gnutls_x509_crt_t cert,
			 gnutls_x509_crt_t issuer,
			 unsigned vflags)
{
	gnutls_pk_params_st params;
	gnutls_pk_algorithm_t issuer_pk;
	int ret;
	gnutls_x509_spki_st sign_params;
	const gnutls_sign_entry_st *se;

	/* Read the MPI parameters from the issuer's certificate.
	 */
	ret = _gnutls_x509_crt_get_mpis(issuer, &params);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	issuer_pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL);

	se = _gnutls_sign_to_entry(sign);
	if (se == NULL)
		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);

	if (cert != NULL) {
		ret = _gnutls_x509_read_sign_params(cert->cert,
						    "signatureAlgorithm",
						    &sign_params);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = _gnutls_x509_validate_sign_params(issuer_pk,
							issuer->cert,
							"tbsCertificate."
							"subjectPublicKeyInfo."
							"algorithm",
							&sign_params);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		memcpy(&sign_params, &params.spki,
		       sizeof(gnutls_x509_spki_st));

		sign_params.pk = se->pk;
		if (sign_params.pk == GNUTLS_PK_RSA_PSS)
			sign_params.rsa_pss_dig = se->hash;
	}

	ret = pubkey_verify_data(se, hash_to_entry(se->hash), data, signature, &params,
				 &sign_params, vflags);
	if (ret < 0) {
		gnutls_assert();
	}

 cleanup:
	/* release all allocated MPIs
	 */
	gnutls_pk_params_release(&params);

	return ret;
}
Exemplo n.º 6
0
/* Like above but it accepts a parsed certificate instead.
 */
int
_gnutls_x509_crt_to_gcert (gnutls_cert * gcert,
			   gnutls_x509_crt_t cert, unsigned int flags)
{
  int ret = 0;

  memset (gcert, 0, sizeof (gnutls_cert));
  gcert->cert_type = GNUTLS_CRT_X509;

  if (!(flags & CERT_NO_COPY))
    {
#define SMALL_DER 512
      opaque *der;
      size_t der_size = SMALL_DER;

      /* initially allocate a bogus size, just in case the certificate
       * fits in it. That way we minimize the DER encodings performed.
       */
      der = gnutls_malloc (SMALL_DER);
      if (der == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      ret =
	gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der, &der_size);
      if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
	{
	  gnutls_assert ();
	  gnutls_free (der);
	  return ret;
	}

      if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
	{
	  der = gnutls_realloc (der, der_size);
	  if (der == NULL)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	  ret =
	    gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
				    &der_size);
	  if (ret < 0)
	    {
	      gnutls_assert ();
	      gnutls_free (der);
	      return ret;
	    }
	}

      gcert->raw.data = der;
      gcert->raw.size = der_size;
    }
  else
    /* now we have 0 or a bitwise or of things to decode */
    flags ^= CERT_NO_COPY;


  if (flags & CERT_ONLY_EXTENSIONS || flags == 0)
    {
      gnutls_x509_crt_get_key_usage (cert, &gcert->key_usage, NULL);
      gcert->version = gnutls_x509_crt_get_version (cert);
    }
  gcert->subject_pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL);

  if (flags & CERT_ONLY_PUBKEY || flags == 0)
    {
      gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
      ret =
	_gnutls_x509_crt_get_mpis (cert, gcert->params, &gcert->params_size);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
    }

  return 0;

}
Exemplo n.º 7
0
int
_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
			       const gnutls_datum_t * signature,
			       const gnutls_x509_crt_t issuer)
{
  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
  opaque digest[MAX_HASH_SIZE];
  gnutls_datum_t decrypted;
  int issuer_params_size;
  int digest_size;
  int ret, i;

  issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
  ret =
    _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  switch (gnutls_x509_crt_get_pk_algorithm (issuer, NULL))
    {
    case GNUTLS_PK_DSA:

      if (hash)
	*hash = _gnutls_dsa_q_to_hash (issuer_params[1]);

      ret = 0;
      break;

    case GNUTLS_PK_RSA:

      ret =
	_gnutls_pkcs1_rsa_decrypt (&decrypted, signature,
				   issuer_params, issuer_params_size, 1);


      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

      digest_size = sizeof (digest);
      if ((ret =
	   decode_ber_digest_info (&decrypted, hash, digest,
				   &digest_size)) != 0)
	{
	  gnutls_assert ();
	  _gnutls_free_datum (&decrypted);
	  goto cleanup;
	}

      _gnutls_free_datum (&decrypted);
      if (digest_size != _gnutls_hash_get_algo_len (*hash))
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_ASN1_GENERIC_ERROR;
	  goto cleanup;
	}

      ret = 0;
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
    }

cleanup:
  /* release allocated mpis */
  for (i = 0; i < issuer_params_size; i++)
    {
      _gnutls_mpi_release (&issuer_params[i]);
    }

  return ret;

}