示例#1
0
/* reads the curve from the certificate.
 * params[0-4]. It does NOT set params_nr.
 */
int
_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * params)
{
  int ret;
  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
  char oid[MAX_OID_SIZE];
  int oid_size;
  
  if ((ret = asn1_create_element
       (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (ret);
    }

  ret = asn1_der_decoding (&spk, der, dersize, NULL);

  if (ret != ASN1_SUCCESS)
    {
      gnutls_assert ();
      ret = _gnutls_asn2err (ret);
      goto cleanup;
    }

  /* Read curve */
  /* read the curve */
  oid_size = sizeof(oid);
  ret = asn1_read_value(spk, "namedCurve", oid, &oid_size);
  if (ret != ASN1_SUCCESS)
    {
      gnutls_assert ();
      ret = _gnutls_asn2err (ret);
      goto cleanup;
    }
    
  params->flags = _gnutls_oid_to_ecc_curve(oid);
  if (params->flags == GNUTLS_ECC_CURVE_INVALID)
    {
      _gnutls_debug_log("Curve %s is not supported\n", oid);
      gnutls_assert();
      ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
      goto cleanup;
    }

  ret = _gnutls_ecc_curve_fill_params(params->flags, params);
  if (ret < 0)
    {
      gnutls_assert();
      goto cleanup;
    }

  ret = 0;
  
cleanup:

  asn1_delete_structure (&spk);

  return ret;

}
/**
 * gnutls_x509_privkey_import_ecc_raw:
 * @key: The structure to store the parsed key
 * @curve: holds the curve
 * @x: holds the x
 * @y: holds the y
 * @k: holds the k
 *
 * This function will convert the given elliptic curve parameters to the
 * native #gnutls_x509_privkey_t format.  The output will be stored
 * in @key.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_x509_privkey_import_ecc_raw (gnutls_x509_privkey_t key,
                                    gnutls_ecc_curve_t curve,
                                    const gnutls_datum_t * x,
                                    const gnutls_datum_t * y,
                                    const gnutls_datum_t * k)
{
  int ret;

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

  key->params.flags = curve;

  ret = _gnutls_ecc_curve_fill_params(curve, &key->params);
  if (ret < 0)
    return gnutls_assert_val(ret);

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_X], x->data, x->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_Y], y->data, y->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  if (_gnutls_mpi_scan_nz (&key->params.params[ECC_K], k->data, k->size))
    {
      gnutls_assert ();
      ret = GNUTLS_E_MPI_SCAN_FAILED;
      goto cleanup;
    }
  key->params.params_nr++;

  key->pk_algorithm = GNUTLS_PK_EC;

  return 0;

cleanup:
  gnutls_pk_params_release(&key->params);
  return ret;

}
/* Converts an ECC key to
 * an internal structure (gnutls_private_key)
 */
ASN1_TYPE
_gnutls_privkey_decode_ecc_key (const gnutls_datum_t * raw_key,
                                      gnutls_x509_privkey_t pkey)
{
  int ret;
  ASN1_TYPE pkey_asn;
  unsigned int version;
  char oid[MAX_OID_SIZE];
  int oid_size;
  gnutls_datum out;

  gnutls_pk_params_init(&pkey->params);

  if ((ret =
       asn1_create_element (_gnutls_get_gnutls_asn (),
                            "GNUTLS.ECPrivateKey",
                            &pkey_asn)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return NULL;
    }

  ret = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL);
  if (ret != ASN1_SUCCESS)
    {
      gnutls_assert ();
      goto error;
    }

  ret = _gnutls_x509_read_uint (pkey_asn, "Version", &version);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }

  if (version != 1)
    {
      _gnutls_debug_log("ECC private key version %u is not supported\n", version);
      gnutls_assert();
      goto error;
    }

  /* read the curve */
  oid_size = sizeof(oid);
  ret = asn1_read_value(pkey_asn, "parameters.namedCurve", oid, &oid_size);
  if (ret != ASN1_SUCCESS)
    {
      gnutls_assert ();
      goto error;
    }
    
  pkey->params.flags = _gnutls_oid_to_ecc_curve(oid);
  if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID)
    {
      _gnutls_debug_log("Curve %s is not supported\n", oid);
      gnutls_assert();
      goto error;
    }
    
  ret = _gnutls_ecc_curve_fill_params(pkey->params.flags, &pkey->params);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }

  /* read the public key */
  ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }

  ret = _gnutls_ecc_ansi_x963_import (out.data, out.size, &pkey->params.params[ECC_X],
                                         &pkey->params.params[ECC_Y]);
  
  _gnutls_free_datum(&out);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }
  pkey->params.params_nr += 2;

  /* read the private key */
  ret = _gnutls_x509_read_int (pkey_asn, "privateKey", &pkey->params.params[ECC_K]);
  if (ret < 0)
    {
      gnutls_assert();
      goto error;
    }
  pkey->params.params_nr ++;

  return pkey_asn;

error:
  asn1_delete_structure (&pkey_asn);
  gnutls_pk_params_release (&pkey->params);
  return NULL;

}