Exemple #1
0
static int
dsa_sign (const gnutls_datum_t * text,
	  bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest;
  gnutls_digest_algorithm_t hash = _gnutls_dsa_q_to_hash (params[1]);

  ret = _gnutls_hash_init (&hd, hash);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (hash);

  if ((ret =
       _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest,
		     signature)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
Exemple #2
0
/* Hashes input data and verifies a DSA signature.
 */
static int
dsa_verify_sig (const gnutls_datum_t * text,
                const gnutls_datum_t * hash,
                const gnutls_datum_t * signature, bigint_t * params,
                int params_len)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  gnutls_datum_t digest;
  digest_hd_st hd;
  gnutls_digest_algorithm_t algo;
  unsigned int hash_len;

  algo = _gnutls_dsa_q_to_hash (params[1], &hash_len);
  if (hash)
    {
      /* SHA1 or better allowed */
      if (!hash->data || hash->size < hash_len)
        {
          gnutls_assert();
          _gnutls_debug_log("Hash size (%d) does not correspond to hash %s", (int)hash->size, gnutls_mac_get_name(algo));
          
          if (hash->size != 20)
            return GNUTLS_E_PK_SIG_VERIFY_FAILED;
        }
      digest = *hash;
    }
  else
    {

      ret = _gnutls_hash_init (&hd, algo);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, _digest);

      digest.data = _digest;
      digest.size = _gnutls_hash_get_algo_len(algo);
    }

  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);

  return ret;
}
Exemple #3
0
int
pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
              bigint_t * params,
              const gnutls_datum_t * data, gnutls_datum_t * digest)
{
  int ret;

  switch (pk)
    {
    case GNUTLS_PK_RSA:
      break;
    case GNUTLS_PK_DSA:
      if (params && hash != _gnutls_dsa_q_to_hash (params[1]))
        {
          gnutls_assert ();
          return GNUTLS_E_INVALID_REQUEST;
        }
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  digest->size = _gnutls_hash_get_algo_len (hash);
  digest->data = gnutls_malloc (digest->size);
  if (digest->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  return 0;

cleanup:
  gnutls_free (digest->data);
  return ret;
}
Exemple #4
0
/**
 * gnutls_pubkey_get_preferred_hash_algorithm:
 * @key: Holds the certificate
 * @hash: The result of the call with the hash algorithm used for signature
 * @mand: If non zero it means that the algorithm MUST use this hash. May be NULL.
 *
 * This function will read the certificate and return the appropriate digest
 * algorithm to use for signing with this certificate. Some certificates (i.e.
 * DSA might not be able to sign without the preferred algorithm).
 *
 * To get the signature algorithm instead of just the hash use gnutls_pk_to_sign()
 * with the algorithm of the certificate/key and the provided @hash.
 *
 * Returns: the 0 if the hash algorithm is found. A negative error code is
 * returned on error.
 *
 * Since: 2.12.0
 **/
int
gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
					   gnutls_digest_algorithm_t *
					   hash, unsigned int *mand)
{
	int ret;
	const mac_entry_st *me;

	if (key == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (mand)
		*mand = 0;

	switch (key->pk_algorithm) {
	case GNUTLS_PK_DSA:
		if (mand)
			*mand = 1;
		/* fallthrough */
	case GNUTLS_PK_EC:

		me = _gnutls_dsa_q_to_hash(key->pk_algorithm, &key->params, NULL);
		if (hash)
			*hash = (gnutls_digest_algorithm_t)me->id;

		ret = 0;
		break;
	case GNUTLS_PK_RSA:
		if (hash)
			*hash = GNUTLS_DIG_SHA256;
		ret = 0;
		break;

	default:
		gnutls_assert();
		ret = GNUTLS_E_INTERNAL_ERROR;
	}

	return ret;
}
Exemple #5
0
/* This will return the appropriate hash to verify the given signature.
 * If signature is NULL it will return an (or the) appropriate hash for
 * the given parameters.
 */
int
_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                               const gnutls_datum_t * signature,
                               gnutls_pk_algorithm pk,
                               bigint_t * issuer_params,
                               unsigned int issuer_params_size)
{
  opaque digest[MAX_HASH_SIZE];
  gnutls_datum_t decrypted;
  int digest_size;
  int ret;

  switch (pk)
    {
    case GNUTLS_PK_DSA:

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

      ret = 0;
      break;
    case GNUTLS_PK_RSA:
      if (signature == NULL)
        {                       /* return a sensible algorithm */
          if (hash)
            *hash = GNUTLS_DIG_SHA256;
          return 0;
        }

      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:

  return ret;

}
Exemple #6
0
static int
_wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
                        const gnutls_datum_t * vdata,
                        const gnutls_datum_t * signature,
                        const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash_len;
  bigint_t tmp[2] = { NULL, NULL };

  switch (algo)
    {
    case GNUTLS_PK_EC: /* ECDSA */
      {
        ecc_key pub;
        struct dsa_signature sig;
        int stat;
        int curve_id = pk_params->flags;

        if (is_supported_curve(curve_id) == 0)
          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        _ecc_params_to_pubkey(pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, curve_id);
        if (ret != 0 || stat != 1)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        _ecc_params_clear( &pub);
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_signature sig;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_public_key pub;
        
        _rsa_params_to_pubkey (pk_params, &pub);

        ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0]));
        if (ret == 0) 
          ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
        else ret = 0;
        
        _gnutls_mpi_release (&tmp[0]);
        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

cleanup:

  return ret;
}
Exemple #7
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
                      gnutls_datum_t * signature,
                      const gnutls_datum_t * vdata,
                      const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash;
  unsigned int hash_len;

  switch (algo)
    {
    case GNUTLS_PK_EC: /* we do ECDSA */
      {
        ecc_key priv;
        struct dsa_signature sig;
        int curve_id = pk_params->flags;

        if (is_supported_curve(curve_id) == 0)
          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);

        _ecc_params_to_privkey(pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret = ecc_sign_hash(vdata->data, hash_len,
                            &sig, NULL, rnd_func, &priv, curve_id);
        if (ret != 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto ecdsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      ecdsa_fail:
        dsa_signature_clear (&sig);
        _ecc_params_clear( &priv);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_private_key priv;
        struct dsa_signature sig;

        memset(&priv, 0, sizeof(priv));
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        _dsa_params_to_privkey (pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret =
          _dsa_sign (&pub, &priv, NULL, rnd_func,
                     hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto dsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      dsa_fail:
        dsa_signature_clear (&sig);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        struct rsa_public_key pub;
        mpz_t s;

        _rsa_params_to_privkey (pk_params, &priv);
        _rsa_params_to_pubkey (pk_params, &pub);
        
        mpz_init(s);

        ret = rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func,
                                vdata->size, vdata->data, s);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto rsa_fail;
          }

        ret = _gnutls_mpi_dprint (s, signature);

rsa_fail:
        mpz_clear(s);

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

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
Exemple #8
0
/* Given a signature and parameters, it should return
 * the hash algorithm used in the signature. This is a kludge
 * but until we deprecate gnutls_pubkey_get_verify_algorithm()
 * we depend on it.
 */
static int wrap_nettle_hash_algorithm (gnutls_pk_algorithm_t pk, 
    const gnutls_datum_t * sig, gnutls_pk_params_st * issuer_params,
    gnutls_digest_algorithm_t* hash_algo)
{
  uint8_t digest[MAX_HASH_SIZE];
  uint8_t digest_info[MAX_HASH_SIZE*3];
  gnutls_datum_t di;
  unsigned digest_size;
  mpz_t s;
  struct rsa_public_key pub;
  int ret;

  mpz_init(s);

  switch (pk)
    {
    case GNUTLS_PK_DSA:
    case GNUTLS_PK_EC:

      if (hash_algo)
        *hash_algo = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL);

      ret = 0;
      break;
    case GNUTLS_PK_RSA:
      if (sig == NULL)
        {                       /* return a sensible algorithm */
          if (hash_algo)
            *hash_algo = GNUTLS_DIG_SHA256;
          return 0;
        }

      _rsa_params_to_pubkey (issuer_params, &pub);

      digest_size = sizeof(digest);
      
      nettle_mpz_set_str_256_u(s, sig->size, sig->data);
      
      digest_size = sizeof (digest_info);
      ret = extract_digest_info( &pub, &digest_size, digest_info, s);
      if (ret == 0)
        {
          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          gnutls_assert ();
          goto cleanup;
        }

      di.data = digest_info;
      di.size = digest_size;
      
      digest_size = sizeof(digest);
      if ((ret =
           decode_ber_digest_info (&di, hash_algo, digest,
                                   &digest_size)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }

      if (digest_size != _gnutls_hash_get_algo_len (*hash_algo))
        {
          gnutls_assert ();
          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          goto cleanup;
        }

      ret = 0;
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
    }

cleanup:
  mpz_clear(s);
  return ret;

}
Exemple #9
0
static int
_wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
                        const gnutls_datum_t * vdata,
                        const gnutls_datum_t * signature,
                        const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash_len;
  bigint_t tmp[2] = { NULL, NULL };

  switch (algo)
    {
    case GNUTLS_PK_EC: /* ECDSA */
      {
        ecc_key pub;
        struct dsa_signature sig;
        int stat;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        _ecc_params_to_pubkey(pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub);
        if (ret != 0 || stat != 1)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        _ecc_params_clear( &pub);
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_signature sig;

        ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        memcpy (&sig.r, tmp[0], sizeof (sig.r));
        memcpy (&sig.s, tmp[1], sizeof (sig.s));

        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          hash_len = vdata->size;

        ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          }
        else
          ret = 0;

        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&tmp[1]);
        break;
      }
    case GNUTLS_PK_RSA:
      {
        bigint_t hash;

        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
          {
            gnutls_assert ();
            return GNUTLS_E_MPI_SCAN_FAILED;
          }

        ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        ret = _int_rsa_verify (pk_params, hash, tmp[0]);
        _gnutls_mpi_release (&tmp[0]);
        _gnutls_mpi_release (&hash);
        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

cleanup:

  return ret;
}
Exemple #10
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
                      gnutls_datum_t * signature,
                      const gnutls_datum_t * vdata,
                      const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash;
  unsigned int hash_len;

  switch (algo)
    {
    case GNUTLS_PK_EC: /* we do ECDSA */
      {
        ecc_key priv;
        struct dsa_signature sig;

        _ecc_params_to_privkey(pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret = ecc_sign_hash(vdata->data, hash_len, 
                            &sig, NULL, rnd_func, &priv);
        if (ret != 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto ecdsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      ecdsa_fail:
        dsa_signature_clear (&sig);
        _ecc_params_clear( &priv);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_private_key priv;
        struct dsa_signature sig;

        memset(&priv, 0, sizeof(priv));
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        _dsa_params_to_privkey (pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret =
          _dsa_sign (&pub, &priv, NULL, rnd_func,
                     hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto dsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      dsa_fail:
        dsa_signature_clear (&sig);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        bigint_t hash, nc, ri;

        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
          {
            gnutls_assert ();
            return GNUTLS_E_MPI_SCAN_FAILED;
          }

        memset(&priv, 0, sizeof(priv));
        _rsa_params_to_privkey (pk_params, &priv);

        nc = rsa_blind (hash, pk_params->params[1] /*e */ ,
                        pk_params->params[0] /*m */ , &ri);

        _gnutls_mpi_release (&hash);

        if (nc == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_MEMORY_ERROR;
            goto rsa_fail;
          }

        rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc));

        rsa_unblind (nc, ri, pk_params->params[0] /*m */ );

        ret = _gnutls_mpi_dprint (nc, signature);

rsa_fail:
        _gnutls_mpi_release (&nc);
        _gnutls_mpi_release (&ri);

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

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
Exemple #11
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;

}
Exemple #12
0
static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params)
{
int ret;
gnutls_datum_t sig = {NULL, 0};
const char const_data[20] = "onetwothreefourfive";
gnutls_datum_t ddata, tmp = {NULL,0};
char* gen_data = NULL;

	if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) {
		unsigned hash_len;

		_gnutls_dsa_q_to_hash(algo, params, &hash_len);
		gen_data = gnutls_malloc(hash_len);
		gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len);

		ddata.data = (void*)gen_data;
		ddata.size = hash_len;
	} else {
		ddata.data = (void*)const_data;
		ddata.size = sizeof(const_data);
	}

	switch (algo) {
	case GNUTLS_PK_RSA:
		ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		if (ddata.size == sig.size && memcmp(ddata.data, sig.data, sig.size) == 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		ret = _gnutls_pk_decrypt(algo, &tmp, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		if (tmp.size != ddata.size || memcmp(tmp.data, ddata.data, tmp.size) != 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}

		free(sig.data);
		sig.data = NULL;

		/* Here we don't know the purpose of the key. Check both
		 * signing and encryption.
		 */
	case GNUTLS_PK_EC: /* we only do keys for ECDSA */
	case GNUTLS_PK_DSA:
		ret = _gnutls_pk_sign(algo, &sig, &ddata, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			goto cleanup;
		}

		ret = _gnutls_pk_verify(algo, &ddata, &sig, params);
		if (ret < 0) {
			ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR);
			gnutls_assert();
			goto cleanup;
		}
		break;

	default:
		ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
		goto cleanup;
	}

	ret = 0;
cleanup:
	if (ret == GNUTLS_E_PK_GENERATION_ERROR) {
		_gnutls_switch_lib_state(LIB_STATE_ERROR);
	}
	gnutls_free(gen_data);
	gnutls_free(sig.data);
	gnutls_free(tmp.data);
	return ret;
}