Example #1
0
/**
 * gnutls_openpgp_crt_verify_ring:
 * @key: the structure that holds the key.
 * @keyring: holds the keyring to check against
 * @flags: unused (should be 0)
 * @verify: will hold the certificate verification output.
 *
 * Verify all signatures in the key, using the given set of keys
 * (keyring).
 *
 * The key verification output will be put in @verify and will be one
 * or more of the #gnutls_certificate_status_t enumerated elements
 * bitwise or'd.
 *
 * %GNUTLS_CERT_INVALID: A signature on the key is invalid.
 *
 * %GNUTLS_CERT_REVOKED: The key has been revoked.
 *
 * Note that this function does not verify using any "web of trust".
 * You may use GnuPG for that purpose, or any other external PGP
 * application.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key,
                                gnutls_openpgp_keyring_t keyring,
                                unsigned int flags, unsigned int *verify)
{
  gnutls_openpgp_keyid_t id;
  cdk_error_t rc;
  int status;

  if (!key || !keyring)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_CERTIFICATE_FOUND;
    }

  *verify = 0;

  rc = cdk_pk_check_sigs (key->knode, keyring->db, &status);
  if (rc == CDK_Error_No_Key)
    {
      rc = GNUTLS_E_NO_CERTIFICATE_FOUND;
      gnutls_assert ();
      return rc;
    }
  else if (rc != CDK_Success)
    {
      _gnutls_x509_log ("cdk_pk_check_sigs: error %d\n", rc);
      rc = _gnutls_map_cdk_rc (rc);
      gnutls_assert ();
      return rc;
    }
  _gnutls_x509_log ("status: %x\n", status);

  if (status & CDK_KEY_INVALID)
    *verify |= GNUTLS_CERT_INVALID;
  if (status & CDK_KEY_REVOKED)
    *verify |= GNUTLS_CERT_REVOKED;
  if (status & CDK_KEY_NOSIGNER)
    *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND;

  /* Check if the key is included in the ring. */
  if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME))
    {
      rc = gnutls_openpgp_crt_get_key_id (key, id);
      if (rc < 0)
        {
          gnutls_assert ();
          return rc;
        }

      rc = gnutls_openpgp_keyring_check_id (keyring, id, 0);
      /* If it exists in the keyring don't treat it as unknown. */
      if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
        *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
    }

  return 0;
}
Example #2
0
/**
 * gnutls_openpgp_privkey_set_preferred_key_id:
 * @key: the structure that contains the OpenPGP public key.
 * @keyid: the selected keyid
 *
 * This allows setting a preferred key id for the given certificate.
 * This key will be used by functions that involve key handling.
 *
 * Returns: On success, 0 is returned, or an error code.
 **/
int
gnutls_openpgp_privkey_set_preferred_key_id (gnutls_openpgp_privkey_t key,
					     const gnutls_openpgp_keyid_t
					     keyid)
{
  int ret;

  if (!key)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* check if the id is valid */
  ret = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
  if (ret < 0)
    {
      _gnutls_x509_log ("the requested subkey does not exist\n");
      gnutls_assert ();
      return ret;
    }

  key->preferred_set = 1;
  memcpy (key->preferred_keyid, keyid, sizeof (gnutls_openpgp_keyid_t));

  return 0;
}
Example #3
0
int
_gnutls_openpgp_get_algo (int cdk_algo)
{
  int algo;

  if (is_RSA (cdk_algo))
    algo = GNUTLS_PK_RSA;
  else if (is_DSA (cdk_algo))
    algo = GNUTLS_PK_DSA;
  else
    {
      _gnutls_x509_log ("Unknown OpenPGP algorithm %d\n", cdk_algo);
      algo = GNUTLS_PK_UNKNOWN;
    }

  return algo;
}
Example #4
0
/**
 * gnutls_x509_dn_import: get opaque DN object from DER RDN sequence
 * @dn: the structure that will hold the imported DN
 * @data: should contain a DER encoded RDN sequence
 *
 * This function parses an RDN sequence and stores the result to a
 * #gnutls_x509_dn_t structure. The structure must have been initialized
 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
 * decode the DN.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.4.0
 **/
int
gnutls_x509_dn_import (gnutls_x509_dn_t dn, const gnutls_datum_t * data)
{
  int result;
  char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

  result = asn1_der_decoding ((ASN1_TYPE *) &dn,
			      data->data, data->size, err);
  if (result != ASN1_SUCCESS)
    {
      /* couldn't decode DER */
      _gnutls_x509_log ("ASN.1 Decoding error: %s\n", err);
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  return 0;
}
Example #5
0
/**
 * gnutls_pkcs12_import:
 * @pkcs12: The structure to store the parsed PKCS12.
 * @data: The DER or PEM encoded PKCS12.
 * @format: One of DER or PEM
 * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
 *
 * This function will convert the given DER or PEM encoded PKCS12
 * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
 *
 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
		      const gnutls_datum_t * data,
		      gnutls_x509_crt_fmt_t format, unsigned int flags)
{
  int result = 0, need_free = 0;
  gnutls_datum_t _data;
  char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

  _data.data = data->data;
  _data.size = data->size;

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

  /* If the PKCS12 is in PEM format then decode it
   */
  if (format == GNUTLS_X509_FMT_PEM)
    {
      opaque *out;

      result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
				       &out);

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

      _data.data = out;
      _data.size = result;

      need_free = 1;
    }

  result =
    asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str);
  if (result != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (result);
      _gnutls_x509_log ("DER error: %s\n", error_str);
      gnutls_assert ();
      goto cleanup;
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  return 0;

cleanup:
  if (need_free)
    _gnutls_free_datum (&_data);
  return result;
}
Example #6
0
/* Writes the digest information and the digest in a DER encoded
 * structure. The digest info is allocated and stored into the info structure.
 */
static int
encode_ber_digest_info (gnutls_digest_algorithm_t hash,
			const gnutls_datum_t * digest, gnutls_datum_t * info)
{
  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
  int result;
  const char *algo;

  algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
  if (algo == NULL)
    {
      gnutls_assert ();
      _gnutls_x509_log ("Hash algorithm: %d\n", hash);
      return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
    }

  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
				     "GNUTLS.DigestInfo",
				     &dinfo)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  /* Write an ASN.1 NULL in the parameters field.  This matches RFC
     3279 and RFC 4055, although is arguable incorrect from a historic
     perspective (see those documents for more information).
     Regardless of what is correct, this appears to be what most
     implementations do.  */
  result = asn1_write_value (dinfo, "digestAlgorithm.parameters",
			     ASN1_NULL, ASN1_NULL_SIZE);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  info->size = 0;
  asn1_der_coding (dinfo, "", NULL, &info->size, NULL);

  info->data = gnutls_malloc (info->size);
  if (info->data == NULL)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return GNUTLS_E_MEMORY_ERROR;
    }

  result = asn1_der_coding (dinfo, "", info->data, &info->size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  asn1_delete_structure (&dinfo);

  return 0;
}
Example #7
0
/* receive the key exchange message ( n, g, s, B) 
 */
int
_gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  uint8_t n_s;
  uint16_t n_g, n_n, n_b;
  size_t _n_s, _n_g, _n_n, _n_b;
  const uint8_t *data_n;
  const uint8_t *data_g;
  const uint8_t *data_s;
  const uint8_t *data_b;
  int i, ret;
  opaque hd[SRP_MAX_HASH_SIZE];
  char *username, *password;
  ssize_t data_size = _data_size;
  gnutls_srp_client_credentials_t cred;

  cred = (gnutls_srp_client_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);

  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  if (session->internals.srp_username == NULL)
    {
      username = cred->username;
      password = cred->password;
    }
  else
    {
      username = session->internals.srp_username;
      password = session->internals.srp_password;
    }

  if (username == NULL || password == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  i = 0;

  /* Read N 
   */
  DECR_LEN (data_size, 2);
  n_n = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_n);
  data_n = &data[i];
  i += n_n;

  /* Read G 
   */
  DECR_LEN (data_size, 2);
  n_g = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_g);
  data_g = &data[i];
  i += n_g;

  /* Read salt 
   */
  DECR_LEN (data_size, 1);
  n_s = data[i];
  i += 1;

  DECR_LEN (data_size, n_s);
  data_s = &data[i];
  i += n_s;

  /* Read B 
   */
  DECR_LEN (data_size, 2);
  n_b = _gnutls_read_uint16 (&data[i]);
  i += 2;

  DECR_LEN (data_size, n_b);
  data_b = &data[i];
  i += n_b;

  _n_s = n_s;
  _n_g = n_g;
  _n_n = n_n;
  _n_b = n_b;

  if (_gnutls_mpi_scan_nz (&N, data_n, &_n_n) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }


  /* Check if the g and n are from the SRP
   * draft. Otherwise check if N is a prime and G
   * a generator.
   */
  if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0)
    {
      _gnutls_x509_log ("Checking the SRP group parameters.\n");
      if ((ret = group_check_g_n (G, N)) < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
    }

  /* Checks if b % n == 0
   */
  if ((ret = check_b_mod_n (B, N)) < 0)
    {
      gnutls_assert ();
      return ret;
    }


  /* generate x = SHA(s | SHA(U | ":" | p))
   * (or the equivalent using bcrypt)
   */
  if ((ret =
       _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s,
			   &_n_g, hd)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }


  return i;			/* return the processed data
				 * needed in auth_srp_rsa.
				 */
}
Example #8
0
/**
 * gnutls_dh_params_import_pkcs3 - import DH params from a pkcs3 structure
 * @params: A structure where the parameters will be copied to
 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
 * @format: the format of params. PEM or DER.
 *
 * This function will extract the DHParams found in a PKCS3 formatted
 * structure. This is the format generated by "openssl dhparam" tool.
 *
 * If the structure is PEM encoded, it should have a header
 * of "BEGIN DH PARAMETERS".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
 *   otherwise an error code is returned.
 **/
int
gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
                               const gnutls_datum_t * pkcs3_params,
                               gnutls_x509_crt_fmt_t format)
{
    ASN1_TYPE c2;
    int result, need_free = 0;
    gnutls_datum_t _params;

    if (format == GNUTLS_X509_FMT_PEM)
    {
        opaque *out;

        result = _gnutls_fbase64_decode ("DH PARAMETERS",
                                         pkcs3_params->data,
                                         pkcs3_params->size, &out);

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

        _params.data = out;
        _params.size = result;

        need_free = 1;

    }
    else
    {
        _params.data = pkcs3_params->data;
        _params.size = pkcs3_params->size;
    }

    if ((result = asn1_create_element
                  (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
            != ASN1_SUCCESS)
    {
        gnutls_assert ();
        if (need_free != 0)
        {
            gnutls_free (_params.data);
            _params.data = NULL;
        }
        return _gnutls_asn2err (result);
    }

    result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);

    if (need_free != 0)
    {
        gnutls_free (_params.data);
        _params.data = NULL;
    }

    if (result != ASN1_SUCCESS)
    {
        /* couldn't decode DER */

        _gnutls_x509_log ("DHParams: Decoding error %d\n", result);
        gnutls_assert ();
        asn1_delete_structure (&c2);
        return _gnutls_asn2err (result);
    }

    /* Read PRIME
     */
    result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
    if (result < 0)
    {
        asn1_delete_structure (&c2);
        gnutls_assert ();
        return result;
    }

    /* read the generator
     */
    result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
    if (result < 0)
    {
        asn1_delete_structure (&c2);
        _gnutls_mpi_release (&params->params[0]);
        gnutls_assert ();
        return result;
    }

    asn1_delete_structure (&c2);

    return 0;
}
Example #9
0
/* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2
 */
static int
_gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
				    gnutls_cert * cert, gnutls_privkey * pkey,
				    gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;

  handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  hash_algo = handshake_td->algorithm;
  sign_algo = _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo);

  /* The idea here is to try signing with the one of the algorithms
   * that have been initiated at handshake (SHA1, SHA256). If they
   * are not requested by peer... tough luck
   */
  ret = _gnutls_session_sign_algo_requested (session, sign_algo);
  if (sign_algo == GNUTLS_SIGN_UNKNOWN || ret < 0)
    {
      handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
      hash_algo = handshake_td->algorithm;
      sign_algo =
	_gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo);
      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
	{
	  gnutls_assert ();
	  return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
	}

      ret = _gnutls_session_sign_algo_requested (session, sign_algo);
      if (ret < 0)
	{
	  gnutls_assert ();
	  _gnutls_x509_log
	    ("Server did not allow either '%s' or '%s' for signing\n",
	     gnutls_mac_get_name (hash_algo),
	     gnutls_mac_get_name (session->internals.handshake_mac_handle.
				  tls12.sha1.algorithm));
	  return ret;
	}
    }

  _gnutls_x509_log ("sign handshake cert vrfy: picked %s with %s\n",
		    gnutls_sign_algorithm_get_name (sign_algo),
		    gnutls_mac_get_name (hash_algo));

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

  _gnutls_hash_deinit (&td, concat);

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

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

  return sign_algo;
}
Example #10
0
/* Reads and returns the PK algorithm of the given certificate-like
 * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo".
 */
int
_gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name,
                               unsigned int *bits)
{
    int result;
    opaque *str = NULL;
    int algo;
    char oid[64];
    int len;
    bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
    char name[128];


    _asnstr_append_name (name, sizeof (name), src_name, ".algorithm.algorithm");
    len = sizeof (oid);
    result = asn1_read_value (src, name, oid, &len);

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

    algo = _gnutls_x509_oid2pk_algorithm (oid);
    if (algo == GNUTLS_PK_UNKNOWN)
    {
        _gnutls_x509_log
        ("%s: unknown public key algorithm: %s\n", __func__, oid);
    }

    if (bits == NULL)
    {
        return algo;
    }

    /* Now read the parameters' bits
     */
    _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey");

    len = 0;
    result = asn1_read_value (src, name, NULL, &len);
    if (result != ASN1_MEM_ERROR)
    {
        gnutls_assert ();
        return _gnutls_asn2err (result);
    }

    if (len % 8 != 0)
    {
        gnutls_assert ();
        return GNUTLS_E_CERTIFICATE_ERROR;
    }

    len /= 8;

    str = gnutls_malloc (len);
    if (str == NULL)
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey");

    result = asn1_read_value (src, name, str, &len);

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

    len /= 8;

    switch (algo)
    {
    case GNUTLS_PK_RSA:
    {
        if ((result = _gnutls_x509_read_rsa_params (str, len, params)) < 0)
        {
            gnutls_assert ();
            return result;
        }

        bits[0] = _gnutls_mpi_get_nbits (params[0]);

        _gnutls_mpi_release (&params[0]);
        _gnutls_mpi_release (&params[1]);
    }
    break;
    case GNUTLS_PK_DSA:
    {

        if ((result = _gnutls_x509_read_dsa_pubkey (str, len, params)) < 0)
        {
            gnutls_assert ();
            return result;
        }

        bits[0] = _gnutls_mpi_get_nbits (params[3]);

        _gnutls_mpi_release (&params[3]);
    }
    break;
    }

    gnutls_free (str);
    return algo;
}
Example #11
0
/* Reads the digest information.
 * we use DER here, although we should use BER. It works fine
 * anyway.
 */
static int
decode_ber_digest_info (const gnutls_datum_t * info,
                        gnutls_mac_algorithm_t * hash,
                        opaque * digest, int *digest_size)
{
  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
  int result;
  char str[1024];
  int len;

  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
                                     "GNUTLS.DigestInfo",
                                     &dinfo)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  len = sizeof (str) - 1;
  result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  *hash = _gnutls_x509_oid2mac_algorithm (str);

  if (*hash == GNUTLS_MAC_UNKNOWN)
    {

      _gnutls_x509_log ("verify.c: HASH OID: %s\n", str);

      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return GNUTLS_E_UNKNOWN_ALGORITHM;
    }

  len = sizeof (str) - 1;
  result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
  /* To avoid permitting garbage in the parameters field, either the
     parameters field is not present, or it contains 0x05 0x00. */
  if (!(result == ASN1_ELEMENT_NOT_FOUND ||
        (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
         memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  result = asn1_read_value (dinfo, "digest", digest, digest_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&dinfo);
      return _gnutls_asn2err (result);
    }

  asn1_delete_structure (&dinfo);

  return 0;
}
Example #12
0
/* Parses an X509 DN in the asn1_struct, and puts the output into
 * the string buf. The output is an LDAP encoded DN.
 *
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
 * That is to point in the rndSequence.
 */
int
_gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
		       const char *asn1_rdn_name, char *buf,
		       size_t * sizeof_buf)
{
  gnutls_string out_str;
  int k2, k1, result;
  char tmpbuffer1[MAX_NAME_SIZE];
  char tmpbuffer2[MAX_NAME_SIZE];
  char tmpbuffer3[MAX_NAME_SIZE];
  opaque value[MAX_STRING_LEN], *value2 = NULL;
  char *escaped = NULL;
  const char *ldap_desc;
  char oid[128];
  int len, printable;
  char *string = NULL;
  size_t sizeof_string, sizeof_escaped;

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

  if (buf)
    buf[0] = 0;
  else
    *sizeof_buf = 0;

  _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free);

  k1 = 0;
  do
    {

      k1++;
      /* create a string like "tbsCertList.issuer.rdnSequence.?1"
       */
      if (asn1_rdn_name[0]!=0)
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, k1);
      else
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
      
      len = sizeof (value) - 1;
      result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      if (result != ASN1_VALUE_NOT_FOUND)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      k2 = 0;

      do
	{			/* Move to the attibute type and values
				 */
	  k2++;

          if (tmpbuffer1[0] != 0)
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, k2);
          else
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);

	  /* Try to read the RelativeDistinguishedName attributes.
	   */

	  len = sizeof (value) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  if (result != ASN1_VALUE_NOT_FOUND)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the OID 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");

	  len = sizeof (oid) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  else if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the Value 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");

	  len = 0;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len);

	  value2 = gnutls_malloc (len);
	  if (value2 == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len);

	  if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }
#define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
	  /*   The encodings of adjoining RelativeDistinguishedNames are separated
	   *   by a comma character (',' ASCII 44).
	   */

	  /*   Where there is a multi-valued RDN, the outputs from adjoining
	   *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
	   *   character.
	   */
	  if (k1 != 1)
	    {			/* the first time do not append a comma */
	      if (k2 != 1)
		{		/* adjoining multi-value RDN */
		  STR_APPEND ("+");
		}
	      else
		{
		  STR_APPEND (",");
		}
	    }

	  ldap_desc = oid2ldap_string (oid);
	  printable = _gnutls_x509_oid_data_printable (oid);

	  sizeof_escaped = 2 * len + 1;

	  escaped = gnutls_malloc (sizeof_escaped);
	  if (escaped == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  sizeof_string = 2 * len + 2;	/* in case it is not printable */

	  string = gnutls_malloc (sizeof_string);
	  if (string == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  STR_APPEND (ldap_desc);
	  STR_APPEND ("=");
	  if (printable)
	    result =
	      _gnutls_x509_oid_data2string (oid,
					    value2, len,
					    string, &sizeof_string);
	  else
	    result =
	      _gnutls_x509_data2hex (value2, len, string, &sizeof_string);

	  if (result < 0)
	    {
	      gnutls_assert ();
	      _gnutls_x509_log
		("Found OID: '%s' with value '%s'\n",
		 oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped));
	      goto cleanup;
	    }
	  STR_APPEND (str_escape (string, escaped, sizeof_escaped));
	  gnutls_free (string);
	  string = NULL;

	  gnutls_free (escaped);
	  escaped = NULL;
	  gnutls_free (value2);
	  value2 = NULL;

	}
      while (1);

    }
  while (1);

  if (out_str.length >= (unsigned int) *sizeof_buf)
    {
      gnutls_assert ();
      *sizeof_buf = out_str.length + 1;
      result = GNUTLS_E_SHORT_MEMORY_BUFFER;
      goto cleanup;
    }

  if (buf)
    {
      memcpy (buf, out_str.data, out_str.length);
      buf[out_str.length] = 0;
    }
  *sizeof_buf = out_str.length;

  result = 0;

cleanup:
  gnutls_free (value2);
  gnutls_free (string);
  gnutls_free (escaped);
  _gnutls_string_clear (&out_str);
  return result;
}
Example #13
0
File: pkcs7.c Project: ares89/vlc
/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, 
 * which holds them. If raw is non null then the raw decoded
 * data are copied (they are locally allocated) there.
 */
static int
_decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
                           gnutls_datum_t * raw)
{
  char oid[MAX_OID_SIZE];
  ASN1_TYPE c2;
  opaque *tmp = NULL;
  int tmp_size, len, result;

  len = sizeof (oid) - 1;
  result = asn1_read_value (pkcs7, "contentType", oid, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (strcmp (oid, SIGNED_DATA_OID) != 0)
    {
      gnutls_assert ();
      _gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid);
      return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
    }

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  /* the Signed-data has been created, so
   * decode them.
   */
  tmp_size = 0;
  result = asn1_read_value (pkcs7, "content", NULL, &tmp_size);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  tmp = gnutls_malloc (tmp_size);
  if (tmp == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  result = asn1_read_value (pkcs7, "content", tmp, &tmp_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* tmp, tmp_size hold the data and the size of the CertificateSet structure
   * actually the ANY stuff.
   */

  /* Step 1. In case of a signed structure extract certificate set.
   */

  result = asn1_der_decoding (&c2, tmp, tmp_size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (raw == NULL)
    {
      gnutls_free (tmp);
    }
  else
    {
      raw->data = tmp;
      raw->size = tmp_size;
    }

  *sdata = c2;

  return 0;

cleanup:
  if (c2)
    asn1_delete_structure (&c2);
  gnutls_free (tmp);
  return result;
}
Example #14
0
/* This will encode and write the AttributeTypeAndValue field.
 * 'multi' must be zero if writing an AttributeTypeAndValue, and 1 if Attribute.
 * In all cases only one value is written.
 */
int
_gnutls_x509_encode_and_write_attribute (const char *given_oid,
					 ASN1_TYPE asn1_struct,
					 const char *where,
					 const void *_data,
					 int sizeof_data, int multi)
{
  const char *val_name;
  const opaque *data = _data;
  char tmp[128];
  ASN1_TYPE c2;
  int result;


  /* Find how to encode the data.
   */
  val_name = asn1_find_structure_from_oid (_gnutls_get_pkix (), given_oid);
  if (val_name == NULL)
    {
      gnutls_assert ();
      _gnutls_x509_log ("Cannot find OID: %s\n", given_oid);
      return GNUTLS_E_X509_UNSUPPORTED_OID;
    }

  _gnutls_str_cpy (tmp, sizeof (tmp), "PKIX1.");
  _gnutls_str_cat (tmp, sizeof (tmp), val_name);

  result = asn1_create_element (_gnutls_get_pkix (), tmp, &c2);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  tmp[0] = 0;

  if ((result = _gnutls_x509_oid_data_choice (given_oid)) > 0)
    {
      const char *string_type;
      int i;

      string_type = "printableString";

      /* Check if the data is plain ascii, and use
       * the UTF8 string type if not.
       */
      for (i = 0; i < sizeof_data; i++)
	{
	  if (!isascii (data[i]))
	    {
	      string_type = "utf8String";
	      break;
	    }
	}

      /* if the type is a CHOICE then write the
       * type we'll use.
       */
      result = asn1_write_value (c2, "", string_type, 1);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto error;
	}

      _gnutls_str_cpy (tmp, sizeof (tmp), string_type);
    }

  result = asn1_write_value (c2, tmp, data, sizeof_data);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto error;
    }


  /* write the data (value)
   */

  _gnutls_str_cpy (tmp, sizeof (tmp), where);
  _gnutls_str_cat (tmp, sizeof (tmp), ".value");

  if (multi != 0)
    {				/* if not writing an AttributeTypeAndValue, but an Attribute */
      _gnutls_str_cat (tmp, sizeof (tmp), "s");	/* values */

      result = asn1_write_value (asn1_struct, tmp, "NEW", 1);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto error;
	}

      _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST");

    }

  result = _gnutls_x509_der_encode_and_copy (c2, "", asn1_struct, tmp, 0);
  if (result < 0)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto error;
    }

  /* write the type
   */
  _gnutls_str_cpy (tmp, sizeof (tmp), where);
  _gnutls_str_cat (tmp, sizeof (tmp), ".type");

  result = asn1_write_value (asn1_struct, tmp, given_oid, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto error;
    }

  result = 0;

error:
  asn1_delete_structure (&c2);
  return result;
}
Example #15
0
/* Decodes the SafeContents, and puts the output in
 * the given bag. 
 */
int
_pkcs12_decode_safe_contents (const gnutls_datum_t * content,
			      gnutls_pkcs12_bag_t bag)
{
  char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  int len, result;
  int bag_type;
  gnutls_datum_t attr_val;
  int count = 0, i, attributes, j;
  size_t size;

  /* Step 1. Extract the SEQUENCE.
   */

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
	&c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  result = asn1_der_decoding (&c2, content->data, content->size, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* Count the number of bags
   */
  result = asn1_number_of_elements (c2, "", &count);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);

  for (i = 0; i < bag->bag_elements; i++)
    {

      snprintf (root, sizeof (root), "?%u.bagId", i + 1);

      len = sizeof (oid);
      result = asn1_read_value (c2, root, oid, &len);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      /* Read the Bag type
       */
      bag_type = oid2bag (oid);

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

      /* Read the Bag Value
       */

      snprintf (root, sizeof (root), "?%u.bagValue", i + 1);

      result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

      if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL
	  || bag_type == GNUTLS_BAG_SECRET)
	{
	  gnutls_datum_t tmp = bag->element[i].data;

	  result =
	    _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
	  if (result < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }

	  _gnutls_free_datum (&tmp);
	}

      /* read the bag attributes
       */
      snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);

      result = asn1_number_of_elements (c2, root, &attributes);
      if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      if (attributes < 0)
	attributes = 1;

      if (result != ASN1_ELEMENT_NOT_FOUND)
	for (j = 0; j < attributes; j++)
	  {

	    snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
		      j + 1);

	    result =
	      _gnutls_x509_decode_and_read_attribute (c2, root, oid,
						      sizeof (oid), &attr_val,
						      1, 0);

	    if (result < 0)
	      {
		gnutls_assert ();
		continue;	/* continue in case we find some known attributes */
	      }

	    if (strcmp (oid, KEY_ID_OID) == 0)
	      {
		size = attr_val.size;

		result =
		  _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
						    attr_val.data, &size);
		attr_val.size = size;
		if (result < 0)
		  {
		    _gnutls_free_datum (&attr_val);
		    gnutls_assert ();
		    _gnutls_x509_log
		      ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
		    continue;
		  }
		bag->element[i].local_key_id = attr_val;
	      }
	    else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
	      {
		size = attr_val.size;
		result =
		  _gnutls_x509_decode_octet_string ("BMPString",
						    attr_val.data, size,
						    attr_val.data, &size);
		attr_val.size = size;
		if (result < 0)
		  {
		    _gnutls_free_datum (&attr_val);
		    gnutls_assert ();
		    _gnutls_x509_log
		      ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
		    continue;
		  }
		bag->element[i].friendly_name =
		  ucs2_to_ascii (attr_val.data, attr_val.size);
	      }
	    else
	      {
		_gnutls_free_datum (&attr_val);
		_gnutls_x509_log
		  ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
	      }
	  }


      bag->element[i].type = bag_type;

    }

  asn1_delete_structure (&c2);


  return 0;

cleanup:
  if (c2)
    asn1_delete_structure (&c2);
  return result;

}
Example #16
0
/* This function will convert an attribute value, specified by the OID,
 * to a string. The result will be a null terminated string.
 *
 * res may be null. This will just return the res_size, needed to
 * hold the string.
 */
int
_gnutls_x509_oid_data2string (const char *oid, void *value,
                              int value_size, char *res, size_t * res_size)
{
    char str[MAX_STRING_LEN], tmpname[128];
    const char *ANAME = NULL;
    int CHOICE = -1, len = -1, result;
    ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY;
    char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";

    if (value == NULL || value_size <= 0 || res_size == NULL)
    {
        gnutls_assert ();
        return GNUTLS_E_INVALID_REQUEST;
    }

    if (_gnutls_x509_oid_data_printable (oid) == 0)
    {
        gnutls_assert ();
        return GNUTLS_E_INTERNAL_ERROR;
    }

    ANAME = _gnutls_x509_oid2asn_string (oid);
    CHOICE = _gnutls_x509_oid_data_choice (oid);

    if (ANAME == NULL)
    {
        gnutls_assert ();
        return GNUTLS_E_INTERNAL_ERROR;
    }

    if ((result =
                asn1_create_element (_gnutls_get_pkix (), ANAME,
                                     &tmpasn)) != ASN1_SUCCESS)
    {
        gnutls_assert ();
        return _gnutls_asn2err (result);
    }

    if ((result =
                asn1_der_decoding (&tmpasn, value, value_size,
                                   asn1_err)) != ASN1_SUCCESS)
    {
        gnutls_assert ();
        _gnutls_x509_log ("asn1_der_decoding: %s:%s\n", str, asn1_err);
        asn1_delete_structure (&tmpasn);
        return _gnutls_asn2err (result);
    }

    /* If this is a choice then we read the choice. Otherwise it
     * is the value;
     */
    len = sizeof (str) - 1;
    if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS)
    {   /* CHOICE */
        gnutls_assert ();
        asn1_delete_structure (&tmpasn);
        return _gnutls_asn2err (result);
    }

    if (CHOICE == 0)
    {
        str[len] = 0;

        /* Refuse to deal with strings containing NULs. */
        if (strlen (str) != len)
            return GNUTLS_E_ASN1_DER_ERROR;

        if (res)
            _gnutls_str_cpy (res, *res_size, str);
        *res_size = len;

        asn1_delete_structure (&tmpasn);
    }
    else
    {   /* CHOICE */
        int non_printable = 0, teletex = 0;
        str[len] = 0;

        /* Note that we do not support strings other than
         * UTF-8 (thus ASCII as well).
         */
        if (strcmp (str, "printableString") != 0 &&
                strcmp (str, "ia5String") != 0 && strcmp (str, "utf8String") != 0)
        {
            non_printable = 1;
        }
        if (strcmp (str, "teletexString") == 0)
            teletex = 1;


        _gnutls_str_cpy (tmpname, sizeof (tmpname), str);

        len = sizeof (str) - 1;
        if ((result =
                    asn1_read_value (tmpasn, tmpname, str, &len)) != ASN1_SUCCESS)
        {
            asn1_delete_structure (&tmpasn);
            return _gnutls_asn2err (result);
        }

        asn1_delete_structure (&tmpasn);

        if (teletex != 0)
        {
            int ascii = 0, i;
            /* HACK: if the teletex string contains only ascii
             * characters then treat it as printable.
             */
            for (i = 0; i < len; i++)
                if (!isascii (str[i]))
                    ascii = 1;

            if (ascii == 0)
                non_printable = 0;
        }

        if (non_printable == 0)
        {
            str[len] = 0;

            /* Refuse to deal with strings containing NULs. */
            if (strlen (str) != len)
                return GNUTLS_E_ASN1_DER_ERROR;

            if (res)
                _gnutls_str_cpy (res, *res_size, str);
            *res_size = len;
        }
        else
        {
            result = _gnutls_x509_data2hex (str, len, res, res_size);
            if (result < 0)
            {
                gnutls_assert ();
                return result;
            }
        }
    }

    return 0;
}
Example #17
0
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
 * which holds them. Returns an ASN1_TYPE of authenticatedSafe.
 */
static int
_decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
			  gnutls_datum_t * raw)
{
  char oid[MAX_OID_SIZE];
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  gnutls_datum_t auth_safe = { NULL, 0 };
  int len, result;
  char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

  len = sizeof (oid) - 1;
  result = asn1_read_value (pkcs12, "authSafe.contentType", oid, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (strcmp (oid, DATA_OID) != 0)
    {
      gnutls_assert ();
      _gnutls_x509_log ("Unknown PKCS12 Content OID '%s'\n", oid);
      return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
    }

  /* Step 1. Read the content data
   */

  result =
    _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  /* Step 2. Extract the authenticatedSafe.
   */

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
	&c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  result = asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, error_str);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      _gnutls_x509_log ("DER error: %s\n", error_str);
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (raw == NULL)
    {
      _gnutls_free_datum (&auth_safe);
    }
  else
    {
      raw->data = auth_safe.data;
      raw->size = auth_safe.size;
    }

  if (authen_safe)
    *authen_safe = c2;
  else
    asn1_delete_structure (&c2);

  return 0;

cleanup:
  if (c2)
    asn1_delete_structure (&c2);
  _gnutls_free_datum (&auth_safe);
  return result;
}
Example #18
0
int
_gnutls_proc_rsa_client_kx (gnutls_session_t session, opaque * data,
			    size_t _data_size)
{
  gnutls_datum_t plaintext;
  gnutls_datum_t ciphertext;
  int ret, dsize;
  bigint_t *params;
  int params_len;
  int randomize_key = 0;
  ssize_t data_size = _data_size;

  if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
    {
      /* SSL 3.0 
       */
      ciphertext.data = data;
      ciphertext.size = data_size;
    }
  else
    {
      /* TLS 1.0
       */
      DECR_LEN (data_size, 2);
      ciphertext.data = &data[2];
      dsize = _gnutls_read_uint16 (data);

      if (dsize != data_size)
	{
	  gnutls_assert ();
	  return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}
      ciphertext.size = dsize;
    }

  ret = _gnutls_get_private_rsa_params (session, &params, &params_len);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, params_len, 2);	/* btype==2 */

  if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
    {
      /* In case decryption fails then don't inform
       * the peer. Just use a random key. (in order to avoid
       * attack against pkcs-1 formating).
       */
      gnutls_assert ();
      _gnutls_x509_log ("auth_rsa: Possible PKCS #1 format attack\n");
      randomize_key = 1;
    }
  else
    {
      /* If the secret was properly formatted, then
       * check the version number.
       */
      if (_gnutls_get_adv_version_major (session) != plaintext.data[0]
	  || _gnutls_get_adv_version_minor (session) != plaintext.data[1])
	{
	  /* No error is returned here, if the version number check
	   * fails. We proceed normally.
	   * That is to defend against the attack described in the paper
	   * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
	   * Ondej Pokorny and Tomas Rosa.
	   */
	  gnutls_assert ();
	  _gnutls_x509_log
	    ("auth_rsa: Possible PKCS #1 version check format attack\n");
	}
    }

  if (randomize_key != 0)
    {
      session->key->key.size = GNUTLS_MASTER_SIZE;
      session->key->key.data = gnutls_malloc (session->key->key.size);
      if (session->key->key.data == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      /* we do not need strong random numbers here.
       */
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data,
			 session->key->key.size);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

    }
  else
    {
      session->key->key.data = plaintext.data;
      session->key->key.size = plaintext.size;
    }

  /* This is here to avoid the version check attack
   * discussed above.
   */
  session->key->key.data[0] = _gnutls_get_adv_version_major (session);
  session->key->key.data[1] = _gnutls_get_adv_version_minor (session);

  return 0;
}