static void
get_certificate (ASN1_TYPE cert_def, unsigned char *der, int der_len)
{
  int result, len, start, end;
  unsigned char str[1024], str2[1024];
  ASN1_TYPE cert2 = ASN1_TYPE_EMPTY;
  char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

  asn1_create_element (cert_def, "PKIX1Implicit88.Certificate", &cert2);

  result = asn1_der_decoding (&cert2, der, der_len, errorDescription);

  if (result != ASN1_SUCCESS)
    {
      printf ("Problems with DER encoding\n");
      return;
    }


  /* issuer */
  get_Name_type (cert_def, cert2, "tbsCertificate.issuer", str);
  printf ("certificate:\nissuer :%s\n", str);
  /* subject */
  get_Name_type (cert_def, cert2, "tbsCertificate.subject", str);
  printf ("subject:%s\n", str);


  /* Verify sign */
  len = sizeof (str) - 1;
  result = asn1_read_value (cert2, "signatureAlgorithm.algorithm", str, &len);

  len = sizeof (str2) - 1;
  result =
    asn1_read_value (cert_def, "PKIX1Implicit88.id-dsa-with-sha1", str2,
		     &len);
  if (!strcmp ((char *) str, (char *) str2))
    {				/* dsa-with-sha */

      result = asn1_der_decoding_startEnd (cert2, der, der_len,
					   "tbsCertificate", &start, &end);

      /* add the lines to calculate the sha on der[start]..der[end] */

      len = sizeof (str) - 1;
      result = asn1_read_value (cert2, "signature", str, &len);

      /* compare the previous value to signature ( with issuer public key) */
    }

  /* Use the next 3 lines to visit the certificate */
  /*   printf("-----------------\n");
     asn1_visit_tree(cert2,"");
     printf("-----------------\n"); */


  /* Clear the "certificate2" structure */
  asn1_delete_structure (&cert2);
}
Exemple #2
0
/* Reads the DER signature from the certificate and allocates space and
 * returns them into signed_data.
 */
int
_gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name,
                            gnutls_datum_t * signature)
{
  int bits, result, len;

  signature->data = NULL;
  signature->size = 0;

  /* Read the signature 
   */
  bits = 0;
  result = asn1_read_value (src, src_name, NULL, &bits);

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

  if (bits % 8 != 0)
    {
      gnutls_assert ();
      result = GNUTLS_E_CERTIFICATE_ERROR;
      goto cleanup;
    }

  len = bits / 8;

  signature->data = gnutls_malloc (len);
  if (signature->data == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_MEMORY_ERROR;
      return result;
    }

  /* read the bit string of the signature
   */
  bits = len;
  result = asn1_read_value (src, src_name, signature->data, &bits);

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

  signature->size = len;

  return 0;

cleanup:
  return result;
}
Exemple #3
0
/* Reads a value from an ASN1 tree, and puts the output
 * in an allocated variable in the given datum.
 * If str is non zero, then the output will be treated as
 * an octet string.
 */
int
_gnutls_x509_read_value (ASN1_TYPE c, const char *root,
			 gnutls_datum_t * ret, int str)
{
  int len = 0, result;
  size_t slen;
  opaque *tmp = NULL;

  result = asn1_read_value (c, root, NULL, &len);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      return result;
    }

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

  result = asn1_read_value (c, root, tmp, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* Extract the OCTET STRING.
   */

  if (str)
    {
      slen = len;
      result = _gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      len = slen;
    }

  ret->data = tmp;
  ret->size = len;

  return 0;

cleanup:
  gnutls_free (tmp);
  return result;

}
Exemple #4
0
/**
 * gnutls_x509_crl_get_extension_info - Get extension id and criticality
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @indx: Specifies which extension OID to send, use zero to get the first one.
 * @oid: a pointer to a structure to hold the OID
 * @sizeof_oid: initially holds the maximum size of @oid, on return
 *   holds actual size of @oid.
 * @critical: output variable with critical flag, may be NULL.
 *
 * This function will return the requested extension OID in the CRL,
 * and the critical flag for it.  The extension OID will be stored as
 * a string in the provided buffer.  Use
 * gnutls_x509_crl_get_extension_data() to extract the data.
 *
 * If the buffer provided is not long enough to hold the output, then
 * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be
 * returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative value in case of an error.  If your have reached the
 *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
 *   will be returned.
 *
 * Since: 2.8.0
 **/
int
gnutls_x509_crl_get_extension_info (gnutls_x509_crl_t crl, int indx,
				    void *oid, size_t * sizeof_oid,
				    int *critical)
{
  int result;
  char str_critical[10];
  char name[ASN1_MAX_NAME_SIZE];
  int len;

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

  snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnID",
	    indx + 1);

  len = *sizeof_oid;
  result = asn1_read_value (crl->crl, name, oid, &len);
  *sizeof_oid = len;

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

  snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.critical",
	    indx + 1);
  len = sizeof (str_critical);
  result = asn1_read_value (crl->crl, name, str_critical, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (critical)
    {
      if (str_critical[0] == 'T')
	*critical = 1;
      else
	*critical = 0;
    }

  return 0;

}
Exemple #5
0
/* this function reads a (small) unsigned integer
 * from asn1 structs. Combines the read and the convertion
 * steps.
 */
int
_gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret)
{
  int len, result;
  opaque *tmpstr;

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

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

  result = asn1_read_value (node, value, tmpstr, &len);

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

  if (len == 1)
    *ret = tmpstr[0];
  else if (len == 2)
    *ret = _gnutls_read_uint16 (tmpstr);
  else if (len == 3)
    *ret = _gnutls_read_uint24 (tmpstr);
  else if (len == 4)
    *ret = _gnutls_read_uint32 (tmpstr);
  else
    {
      gnutls_assert ();
      gnutls_free (tmpstr);
      return GNUTLS_E_INTERNAL_ERROR;
    }

  gnutls_free (tmpstr);

  return 0;
}
Exemple #6
0
time_t
_gnutls_x509_get_time (ASN1_TYPE c2, const char *when)
{
  char ttime[MAX_TIME];
  char name[128];
  time_t c_time = (time_t) - 1;
  int len, result;

  _gnutls_str_cpy (name, sizeof (name), when);

  len = sizeof (ttime) - 1;
  if ((result = asn1_read_value (c2, name, ttime, &len)) < 0)
    {
      gnutls_assert ();
      return (time_t) (-1);
    }

  /* CHOICE */
  if (strcmp (ttime, "generalTime") == 0)
    {

      _gnutls_str_cat (name, sizeof (name), ".generalTime");
      len = sizeof (ttime) - 1;
      result = asn1_read_value (c2, name, ttime, &len);
      if (result == ASN1_SUCCESS)
        c_time = _gnutls_x509_generalTime2gtime (ttime);
    }
  else
    {                           /* UTCTIME */

      _gnutls_str_cat (name, sizeof (name), ".utcTime");
      len = sizeof (ttime) - 1;
      result = asn1_read_value (c2, name, ttime, &len);
      if (result == ASN1_SUCCESS)
        c_time = _gnutls_x509_utcTime2gtime (ttime);
    }

  /* We cannot handle dates after 2031 in 32 bit machines.
   * a time_t of 64bits has to be used.
   */

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return (time_t) (-1);
    }
  return c_time;
}
Exemple #7
0
/**
 * gnutls_x509_crl_get_extension_data - Get the specified extension data
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @indx: Specifies which extension OID to send. Use zero to get the first one.
 * @data: a pointer to a structure to hold the data (may be null)
 * @sizeof_data: initially holds the size of @oid
 *
 * This function will return the requested extension data in the CRL.
 * The extension data will be stored as a string in the provided
 * buffer.
 *
 * Use gnutls_x509_crl_get_extension_info() to extract the OID and
 * critical flag.  Use gnutls_x509_crl_get_extension_by_oid() instead,
 * if you want to get data indexed by the extension OID rather than
 * sequence.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative value in case of an error.  If your have reached the
 *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
 *   will be returned.
 *
 * Since: 2.8.0
 **/
int
gnutls_x509_crl_get_extension_data (gnutls_x509_crl_t crl, int indx,
				    void *data, size_t * sizeof_data)
{
  int result, len;
  char name[ASN1_MAX_NAME_SIZE];

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

  snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnValue",
	    indx + 1);

  len = *sizeof_data;
  result = asn1_read_value (crl->crl, name, data, &len);
  *sizeof_data = len;

  if (result == ASN1_ELEMENT_NOT_FOUND)
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
  else if (result < 0)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  return 0;
}
Exemple #8
0
/**
 * gnutls_x509_crl_get_authority_key_id:
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @id: The place where the identifier will be copied
 * @id_size: Holds the size of the result field.
 * @critical: will be non-zero if the extension is marked as critical
 *   (may be null)
 *
 * This function will return the CRL authority's key identifier.  This
 * is obtained by the X.509 Authority Key identifier extension field
 * (2.5.29.35).  Note that this function 
 * only returns the keyIdentifier field of the extension and
 * %GNUTLS_E_X509_UNSUPPORTED_EXTENSION, if the extension contains
 * the name and serial number of the certificate. In that case
 * gnutls_x509_crl_get_authority_key_gn_serial() may be used.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error code in case of an error.
 *
 * Since: 2.8.0
 **/
int
gnutls_x509_crl_get_authority_key_id(gnutls_x509_crl_t crl, void *id,
				     size_t * id_size,
				     unsigned int *critical)
{
	int result, len, ret;
	ASN1_TYPE c2;

	ret = _get_authority_key_id(crl, &c2, critical);
	if (ret < 0)
		return gnutls_assert_val(ret);

	len = *id_size;
	result = asn1_read_value(c2, "keyIdentifier", id, &len);

	*id_size = len;
	asn1_delete_structure(&c2);

	if (result == ASN1_VALUE_NOT_FOUND
	    || result == ASN1_ELEMENT_NOT_FOUND)
		return
		    gnutls_assert_val(GNUTLS_E_X509_UNSUPPORTED_EXTENSION);

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

	return 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;

}
Exemple #10
0
/**
  * gnutls_x509_crq_get_version - This function returns the Certificate request's version number
  * @crq: should contain a gnutls_x509_crq_t structure
  *
  * This function will return the version of the specified Certificate request.
  *
  * Returns a negative value on error.
  *
  **/
int
gnutls_x509_crq_get_version (gnutls_x509_crq_t crq)
{
    opaque version[5];
    int len, result;

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

    len = sizeof (version);
    if ((result =
                asn1_read_value (crq->crq, "certificationRequestInfo.version",
                                 version, &len)) != ASN1_SUCCESS)
    {

        if (result == ASN1_ELEMENT_NOT_FOUND)
            return 1;		/* the DEFAULT version */
        gnutls_assert ();
        return _gnutls_asn2err (result);
    }

    return (int) version[0] + 1;
}
Exemple #11
0
/* Reads a value from an ASN1 tree, and puts the output
 * in an allocated variable in the given datum.
 *
 * Note that this function always allocates one plus
 * the required data size (and places a null byte).
 */
static int
x509_read_value(ASN1_TYPE c, const char *root,
		gnutls_datum_t * ret, unsigned allow_null)
{
	int len = 0, result;
	uint8_t *tmp = NULL;
	unsigned int etype;

	result = asn1_read_value_type(c, root, NULL, &len, &etype);
	if (result == 0 && allow_null == 0 && len == 0) {
		/* don't allow null strings */
		return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR);
	}

	if (result != ASN1_MEM_ERROR) {
		if (result != ASN1_SUCCESS || allow_null == 0 || len != 0) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			return result;
		}
	}

	if (etype == ASN1_ETYPE_BIT_STRING) {
		len = (len + 7)/8;
	}

	tmp = gnutls_malloc((size_t) len + 1);
	if (tmp == NULL) {
		gnutls_assert();
		result = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	if (len > 0) {
		result = asn1_read_value(c, root, tmp, &len);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		if (etype == ASN1_ETYPE_BIT_STRING) {
			ret->size = (len+7) / 8;
		} else {
			ret->size = (unsigned) len;
		}
	} else {
		ret->size = 0;
	}

	tmp[ret->size] = 0;
	ret->data = tmp;

	return 0;

      cleanup:
	gnutls_free(tmp);
	return result;
}
Exemple #12
0
/**
 * gnutls_x509_crl_get_signature - Returns the CRL's signature
 * @crl: should contain a gnutls_x509_crl_t structure
 * @sig: a pointer where the signature part will be copied (may be null).
 * @sizeof_sig: initially holds the size of @sig
 *
 * This function will extract the signature field of a CRL.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value. and a negative value on error.
 **/
int
gnutls_x509_crl_get_signature (gnutls_x509_crl_t crl,
			       char *sig, size_t * sizeof_sig)
{
  int result;
  int bits;
  unsigned int len;

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

  bits = 0;
  result = asn1_read_value (crl->crl, "signature", NULL, &bits);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

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

  len = bits / 8;

  if (*sizeof_sig < len)
    {
      *sizeof_sig = bits / 8;
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  result = asn1_read_value (crl->crl, "signature", sig, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  return 0;
}
Exemple #13
0
/* This function will attempt to return the requested extension OID found in
 * the given X509v3 certificate. 
 *
 * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
 * be returned.
 */
static int get_extension_oid(ASN1_TYPE asn, const char *root,
		  unsigned indx, void *oid, size_t * sizeof_oid)
{
	int k, result, len;
	char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
	char extnID[MAX_OID_SIZE];
	unsigned indx_counter = 0;

	k = 0;
	do {
		k++;

		snprintf(name, sizeof(name), "%s.?%u", root, k);

		_gnutls_str_cpy(name2, sizeof(name2), name);
		_gnutls_str_cat(name2, sizeof(name2), ".extnID");

		len = sizeof(extnID) - 1;
		result = asn1_read_value(asn, name2, extnID, &len);

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

		/* Handle Extension 
		 */
		if (indx == indx_counter++) {
			len = strlen(extnID) + 1;

			if (*sizeof_oid < (unsigned) len) {
				*sizeof_oid = len;
				gnutls_assert();
				return GNUTLS_E_SHORT_MEMORY_BUFFER;
			}

			memcpy(oid, extnID, len);
			*sizeof_oid = len - 1;

			return 0;
		}


	}
	while (1);

	if (result == ASN1_ELEMENT_NOT_FOUND) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	} else {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}
}
Exemple #14
0
int der_decode(const uint8_t *der, unsigned der_size, uint8_t *out, unsigned *out_size, 
	       char *realm, unsigned realm_size, int *error)
{
	int ret, len;
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;

	ret = asn1_create_element(_kkdcp_pkix1_asn, "KKDCP.KDC-PROXY-MESSAGE", &c2);
	if (ret != ASN1_SUCCESS) {
		*error = ret;
		return -1;
	}

	ret = asn1_der_decoding(&c2, der, der_size, NULL);
	if (ret != ASN1_SUCCESS) {
		*error = ret;
		ret = -1;
		goto cleanup;
	}

	len = *out_size;
	ret = asn1_read_value(c2, "kerb-message", out, &len);
	if (ret != ASN1_SUCCESS) {
		*error = ret;
		ret = -1;
		goto cleanup;
	}
	*out_size = len;

	len = realm_size;
	ret = asn1_read_value(c2, "target-domain", realm, &len);
	if (ret != ASN1_SUCCESS) {
		/* no realm was given */
		realm[0] = 0;
	}

	ret = 0;
 cleanup:
	asn1_delete_structure(&c2); 
	return ret;
	
}
Exemple #15
0
/* this function reads an integer
 * from asn1 structs. Combines the read and mpi_scan
 * steps.
 */
int
_gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi)
{
  int result;
  opaque *tmpstr = NULL;
  int tmpstr_size;

  tmpstr_size = 0;
  result = asn1_read_value (node, value, NULL, &tmpstr_size);
  if (result != ASN1_MEM_ERROR)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  tmpstr = gnutls_malloc (tmpstr_size);
  if (tmpstr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  result = asn1_read_value (node, value, tmpstr, &tmpstr_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      gnutls_free (tmpstr);
      return _gnutls_asn2err (result);
    }

  result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size);
  gnutls_free (tmpstr);

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

  return 0;
}
Exemple #16
0
/* Reads a value from an ASN1 tree, then interprets it as the provided
 * type of string and returns the output in an allocated variable.
 *
 * Note that this function always places a null character
 * at the end of a readable string value (which is not accounted into size)
 */
int
_gnutls_x509_read_string(ASN1_TYPE c, const char *root,
			 gnutls_datum_t * ret, unsigned int etype)
{
	int len = 0, result;
	size_t slen;
	uint8_t *tmp = NULL;
	unsigned rtype;

	result = asn1_read_value_type(c, root, NULL, &len, &rtype);
	if (result != ASN1_MEM_ERROR) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		return result;
	}

	if (rtype == ASN1_ETYPE_BIT_STRING)
		len /= 8;

	tmp = gnutls_malloc((size_t) len + 1);
	if (tmp == NULL) {
		gnutls_assert();
		result = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	result = asn1_read_value(c, root, tmp, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (rtype == ASN1_ETYPE_BIT_STRING)
		len /= 8;

	/* Extract the STRING.
	 */
	slen = (size_t) len;

	result = _gnutls_x509_decode_string(etype, tmp, slen, ret);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}
	gnutls_free(tmp);

	return 0;

      cleanup:
	gnutls_free(tmp);
	return result;
}
Exemple #17
0
/* Decodes an octet string. Leave string_type null for a normal
 * octet string. Otherwise put something like BMPString, PrintableString
 * etc.
 */
int
_gnutls_x509_decode_octet_string (const char *string_type,
                                  const opaque * der, size_t der_size,
                                  opaque * output, size_t * output_size)
{
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  int result, tmp_output_size;
  char strname[64];

  if (string_type == NULL)
    _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data");
  else
    {
      _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.");
      _gnutls_str_cat (strname, sizeof (strname), string_type);
    }

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), strname, &c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

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

  tmp_output_size = *output_size;
  result = asn1_read_value (c2, "", output, &tmp_output_size);
  *output_size = tmp_output_size;

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

  result = 0;

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

  return result;
}
Exemple #18
0
/* extract the basicConstraints from the DER encoded extension
 */
int
_gnutls_x509_ext_extract_basicConstraints (unsigned int *CA,
                                           int *pathLenConstraint,
                                           uint8_t * extnValue,
                                           int extnValueLen)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  char str[128];
  int len, result;

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &ext)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return _gnutls_asn2err (result);
    }

  if (pathLenConstraint)
    {
      result = _gnutls_x509_read_uint (ext, "pathLenConstraint",
                                       (unsigned int*)pathLenConstraint);
      if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
        *pathLenConstraint = -1;
      else if (result != GNUTLS_E_SUCCESS)
        {
          gnutls_assert ();
          asn1_delete_structure (&ext);
          return _gnutls_asn2err (result);
        }
    }

  /* the default value of cA is false.
   */
  len = sizeof (str) - 1;
  result = asn1_read_value (ext, "cA", str, &len);
  if (result == ASN1_SUCCESS && strcmp (str, "TRUE") == 0)
    *CA = 1;
  else
    *CA = 0;

  asn1_delete_structure (&ext);

  return 0;
}
Exemple #19
0
/* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
 * otherwise.
 *
 * octet_string should be non-zero if we are to decode octet strings after
 * decoding.
 *
 * The output is allocated and stored in value.
 */
int
_gnutls_x509_decode_and_read_attribute(ASN1_TYPE asn1_struct,
				       const char *where, char *oid,
				       int oid_size,
				       gnutls_datum_t * value, int multi,
				       int octet_string)
{
	char tmpbuffer[128];
	int len, result;

	/* Read the OID 
	 */
	_gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where);
	_gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".type");

	len = oid_size - 1;
	result = asn1_read_value(asn1_struct, tmpbuffer, oid, &len);

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

	/* Read the Value 
	 */

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

	if (multi)
		_gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), "s.?1");	/* .values.?1 */

	if (octet_string)
		result =
		    _gnutls_x509_read_string(asn1_struct, tmpbuffer, value,
					     ASN1_ETYPE_OCTET_STRING, 0);
	else
		result =
		    _gnutls_x509_read_value(asn1_struct, tmpbuffer, value);
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	return 0;

}
Exemple #20
0
/**
 * gnutls_x509_crl_get_authority_key_gn_serial:
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
 * @alt: is the place where the alternative name will be copied to
 * @alt_size: holds the size of alt.
 * @alt_type: holds the type of the alternative name (one of gnutls_x509_subject_alt_name_t).
 * @serial: buffer to store the serial number (may be null)
 * @serial_size: Holds the size of the serial field (may be null)
 * @critical: will be non-zero if the extension is marked as critical (may be null)
 *
 * This function will return the X.509 authority key
 * identifier when stored as a general name (authorityCertIssuer) 
 * and serial number.
 *
 * Because more than one general names might be stored
 * @seq can be used as a counter to request them all until 
 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: Returns 0 on success, or an error code.
 *
 * Since: 3.0
 **/
int
gnutls_x509_crl_get_authority_key_gn_serial(gnutls_x509_crl_t crl,
					    unsigned int seq,
					    void *alt,
					    size_t * alt_size,
					    unsigned int *alt_type,
					    void *serial,
					    size_t * serial_size,
					    unsigned int *critical)
{
	int ret, result, len;
	ASN1_TYPE c2;

	ret = _get_authority_key_id(crl, &c2, critical);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_parse_general_name(c2, "authorityCertIssuer", seq, alt,
				       alt_size, alt_type, 0);
	if (ret < 0) {
		ret = gnutls_assert_val(ret);
		goto fail;
	}

	if (serial) {
		len = *serial_size;
		result =
		    asn1_read_value(c2, "authorityCertSerialNumber",
				    serial, &len);

		*serial_size = len;

		if (result < 0) {
			ret = _gnutls_asn2err(result);
			goto fail;
		}

	}

	ret = 0;

      fail:
	asn1_delete_structure(&c2);

	return ret;
}
Exemple #21
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;
  int algo;
  char oid[64];
  int len;
  gnutls_pk_params_st params;
  char name[128];

  gnutls_pk_params_init(&params);

  _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_debug_log
        ("%s: unknown public key algorithm: %s\n", __func__, oid);
    }

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

  /* Now read the parameters' bits 
   */
  result = _gnutls_get_asn_mpis(src, src_name, &params);
  if (result < 0)
    return gnutls_assert_val(result);

  bits[0] = pubkey_to_bits(algo, &params);

  gnutls_pk_params_release(&params);
  return algo;
}
Exemple #22
0
/* Decodes an ECC privateKey from a PKCS8 structure.
 */
static int
_decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};
	unsigned char oid[MAX_OID_SIZE];
	unsigned curve = GNUTLS_ECC_CURVE_INVALID;
	int len, result;

	/* openssl PKCS #8 files with ECC keys place the curve in
	 * privateKeyAlgorithm.parameters instead of the ECPrivateKey.parameters.
	 */
	len = sizeof(oid);
	result =
	    asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters",
			    oid, &len);
	if (result == ASN1_SUCCESS) {
		ret = _gnutls_x509_read_ecc_params(oid, len, &curve);
		if (ret < 0) {
			_gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid);
			curve = GNUTLS_ECC_CURVE_INVALID;
		}
	}

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey, curve);
	_gnutls_free_key_datum(&tmp);

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

	ret = 0;

      error:
	return ret;
}
Exemple #23
0
/**
 * asn1_find_structure_from_oid:
 * @definitions: ASN1 definitions
 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
 *
 * Search the structure that is defined just after an OID definition.
 *
 * Returns: %NULL when @oidValue not found, otherwise the pointer to a
 *   constant string that contains the element name defined just after
 *   the OID.
 **/
const char *
asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue)
{
  char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
  char value[ASN1_MAX_NAME_SIZE];
  ASN1_TYPE p;
  int len;
  asn1_retCode result;

  if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL))
    return NULL;		/* ASN1_ELEMENT_NOT_FOUND; */


  strcpy (definitionsName, definitions->name);
  strcat (definitionsName, ".");

  /* search the OBJECT_ID into definitions */
  p = definitions->down;
  while (p)
    {
      if ((type_field (p->type) == TYPE_OBJECT_ID) &&
	  (p->type & CONST_ASSIGN))
	{
	  strcpy (name, definitionsName);
	  strcat (name, p->name);

	  len = ASN1_MAX_NAME_SIZE;
	  result = asn1_read_value (definitions, name, value, &len);

	  if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
	    {
	      p = p->right;
	      if (p == NULL)	/* reach the end of ASN1 definitions */
		return NULL;	/* ASN1_ELEMENT_NOT_FOUND; */

	      return p->name;
	    }
	}
      p = p->right;
    }

  return NULL;			/* ASN1_ELEMENT_NOT_FOUND; */
}
Exemple #24
0
/* Here we only extract the KeyUsage field, from the DER encoded
 * extension.
 */
int
_gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage,
                                   uint8_t * extnValue, int extnValueLen)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  int len, result;
  uint8_t str[2];

  str[0] = str[1] = 0;
  *keyUsage = 0;

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.KeyUsage", &ext)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);

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

  len = sizeof (str);
  result = asn1_read_value (ext, "", str, &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return 0;
    }

  *keyUsage = str[0] | (str[1] << 8);

  asn1_delete_structure (&ext);

  return 0;
}
Exemple #25
0
/* extract an INTEGER from the DER encoded extension
 */
int
_gnutls_x509_ext_extract_number (uint8_t * number,
                                 size_t * _nr_size,
                                 uint8_t * extnValue, int extnValueLen)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  int result;
  int nr_size = *_nr_size;

  /* here it doesn't matter so much that we use CertificateSerialNumber. It is equal
   * to using INTEGER.
   */
  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.CertificateSerialNumber",
        &ext)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return _gnutls_asn2err (result);
    }

  /* the default value of cA is false.
   */
  result = asn1_read_value (ext, "", number, &nr_size);
  if (result != ASN1_SUCCESS)
    result = _gnutls_asn2err (result);
  else
    result = 0;

  *_nr_size = nr_size;

  asn1_delete_structure (&ext);

  return result;
}
Exemple #26
0
/**
 * gnutls_x509_crl_get_version:
 * @crl: should contain a #gnutls_x509_crl_t structure
 *
 * This function will return the version of the specified CRL.
 *
 * Returns: The version number, or a negative error code on error.
 **/
int gnutls_x509_crl_get_version(gnutls_x509_crl_t crl)
{
	uint8_t version[8];
	int len, result;

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

	len = sizeof(version);
	if ((result =
	     asn1_read_value(crl->crl, "tbsCertList.version", version,
			     &len)) != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	return (int) version[0] + 1;
}
Exemple #27
0
/**
 * gnutls_x509_crl_get_crt_serial - get the serial number of a revoked certificate
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @indx: the index of the certificate to extract (starting from 0)
 * @serial: where the serial number will be copied
 * @serial_size: initially holds the size of serial
 * @t: if non null, will hold the time this certificate was revoked
 *
 * This function will retrieve the serial number of the specified, by
 * the index, revoked certificate.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value. and a negative value on error.
 **/
int
gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int indx,
				unsigned char *serial,
				size_t * serial_size, time_t * t)
{

  int result, _serial_size;
  char serial_name[ASN1_MAX_NAME_SIZE];
  char date_name[ASN1_MAX_NAME_SIZE];

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

  snprintf (serial_name, sizeof (serial_name),
	    "tbsCertList.revokedCertificates.?%u.userCertificate", indx + 1);
  snprintf (date_name, sizeof (date_name),
	    "tbsCertList.revokedCertificates.?%u.revocationDate", indx + 1);

  _serial_size = *serial_size;
  result = asn1_read_value (crl->crl, serial_name, serial, &_serial_size);

  *serial_size = _serial_size;
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      if (result == ASN1_ELEMENT_NOT_FOUND)
	return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
      return _gnutls_asn2err (result);
    }

  if (t)
    {
      *t = _gnutls_x509_get_time (crl->crl, date_name);
    }

  return 0;
}
Exemple #28
0
/**
 * gnutls_pkcs12_verify_mac:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @pass: The password for the MAC
 *
 * This function will verify the MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
{
  opaque key[20];
  int result;
  unsigned int iter;
  int len;
  digest_hd_st td1;
  gnutls_datum_t tmp = { NULL, 0 }, salt =
  {
  NULL, 0};
  opaque sha_mac[20];
  opaque sha_mac_orig[20];

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

  /* read the iterations
   */

  result =
    _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
  if (result < 0)
    {
      iter = 1;			/* the default */
    }


  /* Read the salt from the structure.
   */
  result =
    _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* Generate the key.
   */
  result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
					 iter, pass, sizeof (key), key);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  _gnutls_free_datum (&salt);

  /* Get the data to be MACed
   */
  result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  /* MAC the data
   */
  result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  _gnutls_hmac (&td1, tmp.data, tmp.size);
  _gnutls_free_datum (&tmp);

  _gnutls_hmac_deinit (&td1, sha_mac);

  len = sizeof (sha_mac_orig);
  result =
    asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
		     &len);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MAC_VERIFY_FAILED;
    }

  return 0;

cleanup:
  _gnutls_free_datum (&tmp);
  _gnutls_free_datum (&salt);
  return result;
}
Exemple #29
0
/**
 * gnutls_pkcs12_set_bag:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @bag: An initialized bag
 *
 * This function will insert a Bag into the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
{
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
  int result;
  int enc = 0, dum = 1;
  char null;

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

  /* Step 1. Check if the pkcs12 structure is empty. In that
   * case generate an empty PFX.
   */
  result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
  if (result == ASN1_VALUE_NOT_FOUND)
    {
      result = create_empty_pfx (pkcs12->pkcs12);
      if (result < 0)
	{
	  gnutls_assert ();
	  return result;
	}
    }

  /* Step 2. decode the authenticatedSafe.
   */
  result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* Step 3. Encode the bag elements into a SafeContents 
   * structure.
   */
  result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
   * structure.
   */
  result = asn1_write_value (c2, "", "NEW", 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (enc)
    result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
  else
    result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (enc)
    {
      /* Encrypted packets are written directly.
       */
      result =
	asn1_write_value (c2, "?LAST.content",
			  bag->element[0].data.data,
			  bag->element[0].data.size);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}
    }
  else
    {
      result =
	_gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
					  "?LAST.content", 1);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }

  asn1_delete_structure (&safe_cont);


  /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
   * structure.
   */
  result =
    _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
				      "authSafe.content", 1);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  asn1_delete_structure (&c2);

  return 0;

cleanup:
  asn1_delete_structure (&c2);
  asn1_delete_structure (&safe_cont);
  return result;
}
Exemple #30
0
/**
 * gnutls_pkcs12_get_bag:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @indx: contains the index of the bag to extract
 * @bag: An initialized bag, where the contents of the bag will be copied
 *
 * This function will return a Bag from the PKCS12 structure.
 *
 * After the last Bag has been read
 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
		       int indx, gnutls_pkcs12_bag_t bag)
{
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  int result, len;
  char root2[ASN1_MAX_NAME_SIZE];
  char oid[MAX_OID_SIZE];

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

  /* Step 1. decode the data.
   */
  result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* Step 2. Parse the AuthenticatedSafe
   */

  snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);

  len = sizeof (oid) - 1;
  result = asn1_read_value (c2, root2, oid, &len);

  if (result == ASN1_ELEMENT_NOT_FOUND)
    {
      result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
      goto cleanup;
    }

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

  /* Not encrypted Bag
   */

  snprintf (root2, sizeof (root2), "?%u.content", indx + 1);

  if (strcmp (oid, DATA_OID) == 0)
    {
      result = _parse_safe_contents (c2, root2, bag);
      goto cleanup;
    }

  /* ENC_DATA_OID needs decryption */

  bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
  bag->bag_elements = 1;

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

  result = 0;

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