/**
 * gnutls_pkcs11_privkey_import_url:
 * @pkey: The structure to store the parsed key
 * @url: a PKCS 11 url identifying the key
 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
 *
 * This function will "import" a PKCS 11 URL identifying a private
 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
 * in most cases keys cannot be exported, the private key structure
 * is being associated with the available operations on the token.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
                                  const char *url, unsigned int flags)
{
  int ret;
  struct ck_function_list *module;
  struct ck_attribute *attr;
  ck_session_handle_t pks;
  ck_object_handle_t obj;
  struct ck_attribute a[4];
  ck_key_type_t key_type;

  ret = pkcs11_url_to_info (url, &pkey->info);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  pkey->flags = flags;

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
  if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
      *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
  if (!attr || !attr->value_len)
    {
      attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
      if (!attr || !attr->value_len)
        {
          gnutls_assert ();
          return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
        }
    }

  FIND_OBJECT (module, pks, obj, pkey);
  a[0].type = CKA_KEY_TYPE;
  a[0].value = &key_type;
  a[0].value_len = sizeof (key_type);

  if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
    {
      pkey->pk_algorithm = mech_to_pk(key_type);
      if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
        {
          _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
    }

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}
Beispiel #2
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 (0) 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);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	result = 0;

      cleanup:
	if (c2)
		asn1_delete_structure(&c2);
	return result;
}
Beispiel #3
0
/**
 * gnutls_pkcs12_generate_mac:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @pass: The password for the MAC
 *
 * This function will generate a MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
{
	uint8_t salt[8], key[20];
	int result;
	const int iter = 1;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 };
	uint8_t sha_mac[20];

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

	/* Generate the salt.
	 */
	result = _gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt));
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	/* Write the salt into the structure.
	 */
	result =
	    asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt,
			     sizeof(salt));
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* write the iterations
	 */

	if (iter > 1) {
		result =
		    _gnutls_x509_write_uint32(pkcs12->pkcs12,
					      "macData.iterations", iter);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

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

	/* 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_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
				  key, sizeof(key));
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

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

	_gnutls_mac_deinit(&td1, sha_mac);


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

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.parameters",
			     NULL, 0);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.algorithm",
			     HASH_OID_SHA1, 1);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&tmp);
	return result;
}
Beispiel #4
0
/* Encodes the bag into a SafeContents structure, and puts the output in
 * the given datum. Enc is set to non-zero if the data are encrypted;
 */
int
_pkcs12_encode_safe_contents(gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
			     int *enc)
{
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	int result;
	int i;
	const char *oid;

	if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) {
		*enc = 1;
		return 0;	/* ENCRYPTED BAG, do nothing. */
	} else if (enc)
		*enc = 0;

	/* Step 1. Create 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;
	}

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

		oid = bag_to_oid(bag->element[i].type);
		if (oid == NULL) {
			gnutls_assert();
			continue;
		}

		result = asn1_write_value(c2, "", "NEW", 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		/* Copy the bag type.
		 */
		result = asn1_write_value(c2, "?LAST.bagId", oid, 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			result = _gnutls_asn2err(result);
			goto cleanup;
		}

		/* Set empty attributes
		 */
		result =
		    write_attributes(bag, i, c2, "?LAST.bagAttributes");
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}


		/* Copy the Bag Value
		 */

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

			/* in that case encode it to a CertBag or
			 * a CrlBag.
			 */

			result =
			    _pkcs12_encode_crt_bag(bag->element[i].type,
						   &bag->element[i].data,
						   &tmp);

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

			result =
			    _gnutls_x509_write_value(c2, "?LAST.bagValue",
						     &tmp);

			_gnutls_free_datum(&tmp);

		} else {

			result =
			    _gnutls_x509_write_value(c2, "?LAST.bagValue",
						     &bag->element[i].
						     data);
		}

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

	}

	/* Encode the data and copy them into the datum
	 */
	*contents = c2;

	return 0;

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

}
Beispiel #5
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;
	gnutls_datum_t t;
	int count = 0, i, attributes, j;

	/* 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);
		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) {
					result =
					    _gnutls_x509_decode_string
					    (ASN1_ETYPE_OCTET_STRING,
					     attr_val.data, attr_val.size,
					     &t);
					_gnutls_free_datum(&attr_val);
					if (result < 0) {
						gnutls_assert();
						_gnutls_debug_log
						    ("Error decoding PKCS12 Bag Attribute OID '%s'\n",
						     oid);
						continue;
					}

					attr_val.data = t.data;
					attr_val.size = t.size;

					bag->element[i].local_key_id =
					    attr_val;
				} else if (strcmp(oid, FRIENDLY_NAME_OID)
					   == 0) {
					result =
					    _gnutls_x509_decode_string
					    (ASN1_ETYPE_BMP_STRING,
					     attr_val.data, attr_val.size,
					     &t);
					_gnutls_free_datum(&attr_val);
					if (result < 0) {
						gnutls_assert();
						_gnutls_debug_log
						    ("Error decoding PKCS12 Bag Attribute OID '%s'\n",
						     oid);
						continue;
					}

					attr_val.data = t.data;
					attr_val.size = t.size;

					bag->element[i].friendly_name =
					    (char *) t.data;
				} else {
					_gnutls_free_datum(&attr_val);
					_gnutls_debug_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;

}
Beispiel #6
0
static int
write_new_general_name (ASN1_TYPE ext, const char *ext_name,
			gnutls_x509_subject_alt_name_t type,
			const void *data, unsigned int data_size)
{
  const char *str;
  int result;
  char name[128];

  result = asn1_write_value (ext, ext_name, "NEW", 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  switch (type)
    {
    case GNUTLS_SAN_DNSNAME:
      str = "dNSName";
      break;
    case GNUTLS_SAN_RFC822NAME:
      str = "rfc822Name";
      break;
    case GNUTLS_SAN_URI:
      str = "uniformResourceIdentifier";
      break;
    case GNUTLS_SAN_IPADDRESS:
      str = "iPAddress";
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  if (ext_name[0] == 0)
    {				/* no dot */
      _gnutls_str_cpy (name, sizeof (name), "?LAST");
    }
  else
    {
      _gnutls_str_cpy (name, sizeof (name), ext_name);
      _gnutls_str_cat (name, sizeof (name), ".?LAST");
    }

  result = asn1_write_value (ext, name, str, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  _gnutls_str_cat (name, sizeof (name), ".");
  _gnutls_str_cat (name, sizeof (name), str);

  result = asn1_write_value (ext, name, data, data_size);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return _gnutls_asn2err (result);
    }

  return 0;
}
Beispiel #7
0
/**
 * gnutls_openpgp_key_get_name - Extracts the userID
 * @key: the structure that contains the OpenPGP public key.
 * @idx: the index of the ID to extract
 * @buf: a pointer to a structure to hold the name
 * @sizeof_buf: holds the size of 'buf'
 *
 * Extracts the userID from the parsed OpenPGP key.
 *
 * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
 * if the index of the ID does not exist.
 *
 **/
int
gnutls_openpgp_key_get_name (gnutls_openpgp_key_t key,
			     int idx, char *buf, size_t * sizeof_buf)
{
  cdk_kbnode_t ctx = NULL, p;
  cdk_packet_t pkt = NULL;
  cdk_pkt_userid_t uid = NULL;
  int pos = 0;
  size_t size = 0;
  int rc = 0;

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

  if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key))
    {
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  if (!idx)
    pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID);
  else
    {
      pos = 0;
      while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
	{
	  pkt = cdk_kbnode_get_packet (p);
	  if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx)
	    break;
	}
    }

  if (!pkt)
    {
      rc = GNUTLS_E_INTERNAL_ERROR;
      goto leave;
    }

  uid = pkt->pkt.user_id;

  if (uid->len >= *sizeof_buf)
    {
      gnutls_assert ();
      *sizeof_buf = uid->len + 1;
      rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
      goto leave;
    }

  size = uid->len < *sizeof_buf ? uid->len : *sizeof_buf - 1;
  memcpy (buf, uid->name, size);

  buf[size] = '\0';		/* make sure it's a string */

  if (uid->is_revoked)
    {
      rc = GNUTLS_E_OPENPGP_UID_REVOKED;
      goto leave;
    }

leave:
  return rc;
}
Beispiel #8
0
/**
 * gnutls_x509_crl_import:
 * @crl: The structure to store the parsed CRL.
 * @data: The DER or PEM encoded CRL.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded CRL
 * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
 *
 * If the CRL is PEM encoded it should have a header of "X509 CRL".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_import(gnutls_x509_crl_t crl,
		       const gnutls_datum_t * data,
		       gnutls_x509_crt_fmt_t format)
{
	int result = 0;

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

	_gnutls_free_datum(&crl->der);

	/* If the CRL is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		result =
		    _gnutls_fbase64_decode(PEM_CRL, data->data, data->size,
					   &crl->der);

		if (result < 0) {
			gnutls_assert();
			return result;
		}
	} else {
		result = _gnutls_set_datum(&crl->der, data->data, data->size);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	if (crl->expanded) {
		result = crl_reinit(crl);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}
	crl->expanded = 1;

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

	result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der,
					  "tbsCertList.issuer.rdnSequence",
					  &crl->raw_issuer_dn);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&crl->der);
	return result;
}
Beispiel #9
0
/**
 * gnutls_x509_crl_list_import:
 * @crls: The structures to store the parsed CRLs. Must not be initialized.
 * @crl_max: Initially must hold the maximum number of crls. It will be updated with the number of crls available.
 * @data: The PEM encoded CRLs
 * @format: One of DER or PEM.
 * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags.
 *
 * This function will convert the given PEM encoded CRL list
 * to the native gnutls_x509_crl_t format. The output will be stored
 * in @crls.  They will be automatically initialized.
 *
 * If the Certificate is PEM encoded it should have a header of "X509 CRL".
 *
 * Returns: the number of certificates read or a negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_x509_crl_list_import(gnutls_x509_crl_t * crls,
			    unsigned int *crl_max,
			    const gnutls_datum_t * data,
			    gnutls_x509_crt_fmt_t format,
			    unsigned int flags)
{
	int size;
	const char *ptr;
	gnutls_datum_t tmp;
	int ret, nocopy = 0;
	unsigned int count = 0, j;

	if (format == GNUTLS_X509_FMT_DER) {
		if (*crl_max < 1) {
			*crl_max = 1;
			return GNUTLS_E_SHORT_MEMORY_BUFFER;
		}

		count = 1;	/* import only the first one */

		ret = gnutls_x509_crl_init(&crls[0]);
		if (ret < 0) {
			gnutls_assert();
			goto error;
		}

		ret = gnutls_x509_crl_import(crls[0], data, format);
		if (ret < 0) {
			gnutls_assert();
			goto error;
		}

		*crl_max = 1;
		return 1;
	}

	/* move to the certificate
	 */
	ptr = memmem(data->data, data->size,
		     PEM_CRL_SEP, sizeof(PEM_CRL_SEP) - 1);
	if (ptr == NULL) {
		gnutls_assert();
		return GNUTLS_E_BASE64_DECODING_ERROR;
	}

	count = 0;

	do {
		if (count >= *crl_max) {
			if (!
			    (flags &
			     GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED))
				break;
			else
				nocopy = 1;
		}

		if (!nocopy) {
			ret = gnutls_x509_crl_init(&crls[count]);
			if (ret < 0) {
				gnutls_assert();
				goto error;
			}

			tmp.data = (void *) ptr;
			tmp.size =
			    data->size - (ptr - (char *) data->data);

			ret =
			    gnutls_x509_crl_import(crls[count], &tmp,
						   GNUTLS_X509_FMT_PEM);
			if (ret < 0) {
				gnutls_assert();
				goto error;
			}
		}

		/* now we move ptr after the pem header 
		 */
		ptr++;
		/* find the next certificate (if any)
		 */
		size = data->size - (ptr - (char *) data->data);

		if (size > 0) {
			ptr =
			    memmem(ptr, size, PEM_CRL_SEP,
				   sizeof(PEM_CRL_SEP) - 1);
		} else
			ptr = NULL;

		count++;
	}
	while (ptr != NULL);

	*crl_max = count;

	if (nocopy == 0)
		return count;
	else
		return GNUTLS_E_SHORT_MEMORY_BUFFER;

      error:
	for (j = 0; j < count; j++)
		gnutls_x509_crl_deinit(crls[j]);
	return ret;
}
Beispiel #10
0
/**
 * gnutls_utf8_password_normalize:
 * @password: contain the UTF-8 formatted password
 * @plen: the length of the provided password
 * @out: the result in an null-terminated allocated string
 * @flags: should be zero
 *
 * This function will convert the provided UTF-8 password according
 * to the normalization rules in RFC7613.
 *
 * If the flag %GNUTLS_UTF8_IGNORE_ERRS is specified, any UTF-8 encoding
 * errors will be ignored, and in that case the output will be a copy of the input.
 *
 * Returns: %GNUTLS_E_INVALID_UTF8_STRING on invalid UTF-8 data, or 0 on success.
 *
 * Since: 3.5.7
 **/
int gnutls_utf8_password_normalize(const unsigned char *password, unsigned plen,
				   gnutls_datum_t *out, unsigned flags)
{
	size_t ucs4_size = 0, nrm_size = 0;
	size_t final_size = 0;
	uint8_t *final = NULL;
	uint32_t *ucs4 = NULL;
	uint32_t *nrm = NULL;
	uint8_t *nrmu8 = NULL;
	int ret;

	if (plen == 0) {
		out->data = (uint8_t*)gnutls_strdup("");
		out->size = 0;
		if (out->data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		return 0;
	}

	/* check for invalid UTF-8 */
	if (u8_check((uint8_t*)password, plen) != NULL) {
		gnutls_assert();
		if (flags & GNUTLS_UTF8_IGNORE_ERRS) {
 raw_copy:
			out->data = gnutls_malloc(plen+1);
			if (out->data == NULL)
				return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
			out->size = plen;
			memcpy(out->data, password, plen);
			out->data[plen] = 0;
			return 0;
		} else {
			return GNUTLS_E_INVALID_UTF8_STRING;
		}
	}

	/* convert to UTF-32 */
	ucs4 = u8_to_u32((uint8_t*)password, plen, NULL, &ucs4_size);
	if (ucs4 == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_PARSING_ERROR;
		goto fail;
	}

	ret = check_for_valid_freeformclass(ucs4, ucs4_size);
	if (ret < 0) {
		gnutls_assert();
		if (flags & GNUTLS_UTF8_IGNORE_ERRS) {
			free(ucs4);
			goto raw_copy;
		}
		if (ret == GNUTLS_E_INVALID_UTF8_STRING)
			ret = GNUTLS_E_INVALID_PASSWORD_STRING;
		goto fail;
	}

	/* normalize to NFC */
	nrm = u32_normalize(UNINORM_NFC, ucs4, ucs4_size, NULL, &nrm_size);
	if (nrm == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_PASSWORD_STRING;
		goto fail;
	}

	/* convert back to UTF-8 */
	final_size = 0;
	nrmu8 = u32_to_u8(nrm, nrm_size, NULL, &final_size);
	if (nrmu8 == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_PASSWORD_STRING;
		goto fail;
	}

	/* copy to output with null terminator */
	final = gnutls_malloc(final_size+1);
/* reads p,q and g 
 * from the certificate (subjectPublicKey BIT STRING).
 * params[0-2]. It does NOT set params_nr.
 */
static int
_gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * params)
{
  int result;
  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
  
  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.Dss-Parms", &spk)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

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

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

  /* FIXME: If the parameters are not included in the certificate
   * then the issuer's parameters should be used. This is not
   * done yet.
   */

  /* Read p */

  if ((result = _gnutls_x509_read_int (spk, "p", &params->params[0])) < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&spk);
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  /* Read q */

  if ((result = _gnutls_x509_read_int (spk, "q", &params->params[1])) < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&spk);
      _gnutls_mpi_release (&params->params[0]);
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  /* Read g */

  if ((result = _gnutls_x509_read_int (spk, "g", &params->params[2])) < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&spk);
      _gnutls_mpi_release (&params->params[0]);
      _gnutls_mpi_release (&params->params[1]);
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  asn1_delete_structure (&spk);

  return 0;

}
Beispiel #12
0
int
_gnutls_recv_client_certificate (gnutls_session_t session)
{
  gnutls_buffer_st buf;
  int ret = 0;
  int optional;

  if (session->internals.auth_struct->gnutls_process_client_certificate ==
      NULL)
    return 0;

  /* if we have not requested a certificate then just return
   */
  if (session->internals.send_cert_req == 0)
    {
      return 0;
    }

  if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
    optional = MANDATORY_PACKET;
  else
    optional = OPTIONAL_PACKET;

  ret =
    _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, 
      optional, &buf);

  if (ret < 0)
    {
      /* Handle the case of old SSL3 clients who send
       * a warning alert instead of an empty certificate to indicate
       * no certificate.
       */
      if (optional == OPTIONAL_PACKET &&
          ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
          gnutls_protocol_get_version (session) == GNUTLS_SSL3 &&
          gnutls_alert_get (session) == GNUTLS_A_SSL3_NO_CERTIFICATE)
        {

          /* SSL3 does not send an empty certificate,
           * but this alert. So we just ignore it.
           */
          gnutls_assert ();
          return 0;
        }

      /* certificate was required 
       */
      if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
           || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
          && optional == MANDATORY_PACKET)
        {
          gnutls_assert ();
          return GNUTLS_E_NO_CERTIFICATE_FOUND;
        }

      return ret;
    }

  if (ret == 0 && buf.length == 0 && optional == OPTIONAL_PACKET)
    {
      /* Client has not sent the certificate message.
       * well I'm not sure we should accept this
       * behaviour.
       */
      gnutls_assert ();
      ret = 0;
      goto cleanup;
    }
  ret =
    session->internals.
    auth_struct->gnutls_process_client_certificate (session, buf.data,
                                                    buf.length);

  if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND)
    {
      gnutls_assert ();
      goto cleanup;
    }

  /* ok we should expect a certificate verify message now 
   */
  if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET)
    ret = 0;
  else
    session->key->certificate_requested = 1;

cleanup:
  _gnutls_buffer_clear(&buf);
  return ret;
}
/**
 * gnutls_pkcs11_privkey_generate:
 * @url: a token URL
 * @pk: the public key algorithm
 * @bits: the security bits
 * @label: a label
 * @flags: should be zero
 *
 * This function will generate a private key in the specified
 * by the @url token. The pivate key will be generate within
 * the token and will not be exportable.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_pkcs11_privkey_generate (const char* url, 
  gnutls_pk_algorithm_t pk, unsigned int bits, 
  const char* label, unsigned int flags)
{
  int ret;
  const ck_bool_t tval = 1;
  const ck_bool_t fval = 0;
  struct ck_function_list *module;
  ck_session_handle_t pks = 0;
  struct p11_kit_uri *info = NULL;
  ck_rv_t rv;
  struct ck_attribute a[10], p[10];
  ck_object_handle_t pub, priv;
  unsigned long _bits = bits;
  int a_val, p_val;
  struct ck_mechanism mech;

  ret = pkcs11_url_to_info (url, &info);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret =
    pkcs11_open_session (&module, &pks, info,
                         SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
  p11_kit_uri_free (info);

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

  /* a holds the public key template
   * and p the private key */
  a_val = p_val = 0;
  mech.parameter = NULL;
  mech.parameter_len = 0;
  mech.mechanism = pk_to_genmech(pk);

  switch(pk)
    {
      case GNUTLS_PK_RSA:
        p[p_val].type = CKA_DECRYPT;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_ENCRYPT;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      case GNUTLS_PK_DSA:
        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      case GNUTLS_PK_EC:
        p[p_val].type = CKA_SIGN;
        p[p_val].value = (void*)&tval;
        p[p_val].value_len = sizeof (tval);
        p_val++;

        a[a_val].type = CKA_VERIFY;
        a[a_val].value = (void*)&tval;
        a[a_val].value_len = sizeof (tval);
        a_val++;

        a[a_val].type = CKA_MODULUS_BITS;
        a[a_val].value = &_bits;
        a[a_val].value_len = sizeof (_bits);
        a_val++;
        break;
      default:
        ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        goto cleanup;
    }

  /* a private key is set always as private unless
   * requested otherwise
   */
  if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
    {
      p[p_val].type = CKA_PRIVATE;
      p[p_val].value = (void*)&fval;
      p[p_val].value_len = sizeof(fval);
      p_val++;
    }
  else
    {
      p[p_val].type = CKA_PRIVATE;
      p[p_val].value = (void*)&tval;
      p[p_val].value_len = sizeof (tval);
      p_val++;
    }

  p[p_val].type = CKA_TOKEN;
  p[p_val].value = (void *)&tval;
  p[p_val].value_len = sizeof (tval);
  p_val++;

  if (label)
    {
      p[p_val].type = CKA_LABEL;
      p[p_val].value = (void*)label;
      p[p_val].value_len = strlen (label);
      p_val++;

      a[a_val].type = CKA_LABEL;
      a[a_val].value = (void*)label;
      a[a_val].value_len = strlen (label);
      a_val++;
    }

  if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
    {
      p[p_val].type = CKA_SENSITIVE;
      p[p_val].value = (void*)&tval;
      p[p_val].value_len = sizeof (tval);
      p_val++;
    }
  else
    {
      p[p_val].type = CKA_SENSITIVE;
      p[p_val].value = (void*)&fval;
      p[p_val].value_len = sizeof (fval);
      p_val++;
    }

  rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }
    

cleanup:
  if (pks != 0)
    pkcs11_close_session (module, pks);

  return ret;
}
/*-
 * _gnutls_pkcs11_privkey_decrypt_data:
 * @key: Holds the key
 * @flags: should be 0 for now
 * @ciphertext: holds the data to be signed
 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
 *
 * This function will decrypt the given data using the public key algorithm
 * supported by the private key. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
                                    unsigned int flags,
                                    const gnutls_datum_t * ciphertext,
                                    gnutls_datum_t * plaintext)
{
  ck_rv_t rv;
  int ret;
  struct ck_mechanism mech;
  unsigned long siglen;
  struct ck_function_list *module;
  ck_session_handle_t pks;
  ck_object_handle_t obj;

  FIND_OBJECT (module, pks, obj, key);

  if (key->pk_algorithm != GNUTLS_PK_RSA)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  mech.mechanism = CKM_RSA_PKCS;
  mech.parameter = NULL;
  mech.parameter_len = 0;

  /* Initialize signing operation; using the private key discovered
   * earlier. */
  rv = pkcs11_decrypt_init (module, pks, &mech, obj);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  /* Work out how long the plaintext must be: */
  rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
                         NULL, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  plaintext->data = gnutls_malloc (siglen);
  plaintext->size = siglen;

  rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
                         plaintext->data, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_free (plaintext->data);
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  plaintext->size = siglen;

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}
Beispiel #15
0
static int
set_extension (ASN1_TYPE asn, const char *root,
	       const char *ext_id,
	       const gnutls_datum_t * ext_data, unsigned int critical)
{
  int result;
  int k, len;
  char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
  char extnID[128];

  /* Find the index of the given extension.
   */
  k = 0;
  do
    {
      k++;

      if (root[0] != 0)
	snprintf (name, sizeof (name), "%s.?%u", root, k);
      else
	snprintf (name, sizeof (name), "?%u", k);

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

      /* move to next
       */

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      do
	{

	  _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 (strcmp (extnID, ext_id) == 0)
	    {
	      /* extension was found 
	       */
	      return overwrite_extension (asn, root, k, ext_data, critical);
	    }


	}
      while (0);
    }
  while (1);

  if (result == ASN1_ELEMENT_NOT_FOUND)
    {
      return add_extension (asn, root, ext_id, ext_data, critical);
    }
  else
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }


  return 0;
}
Beispiel #16
0
/**
 * gnutls_x509_crl_iter_crt_serial:
 * @crl: should contain a #gnutls_x509_crl_t structure
 * @iter: A pointer to an iterator (initially the iterator should be %NULL)
 * @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 performs the same as gnutls_x509_crl_get_crt_serial(),
 * but reads sequentially and keeps state in the iterator 
 * between calls. That allows it to provide better performance in sequences 
 * with many elements (50000+).
 *
 * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
 * is returned and the iterator is reset.
 *
 * After use, the iterator must be deinitialized using gnutls_x509_crl_iter_deinit().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_iter_crt_serial(gnutls_x509_crl_t crl,
				gnutls_x509_crl_iter_t *iter,
			        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 || iter == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (*iter == NULL) {
		*iter = gnutls_calloc(1, sizeof(struct gnutls_x509_crl_iter));
		if (*iter == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
	}

	if ((*iter)->rcache == NULL) {
		(*iter)->rcache = asn1_find_node (crl->crl, "tbsCertList.revokedCertificates.?1");
		(*iter)->rcache_idx = 1;
	} else {
		snprintf(serial_name, sizeof(serial_name),
			 "?%d", (*iter)->rcache_idx);
		(*iter)->rcache = asn1_find_node ((*iter)->rcache, serial_name);
	}
	if ((*iter)->rcache == NULL) {
		/* reset */
		(*iter)->rcache = NULL;
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
	}

	snprintf(serial_name, sizeof(serial_name),
		 "?%d.userCertificate", (*iter)->rcache_idx);

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

	*serial_size = _serial_size;
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		if (result == ASN1_ELEMENT_NOT_FOUND) {
			/* reset */
			(*iter)->rcache = NULL;
			return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		}
		return _gnutls_asn2err(result);
	}

	if (t) {
		snprintf(date_name, sizeof(date_name),
			 "?%d.revocationDate", (*iter)->rcache_idx);
		*t = _gnutls_x509_get_time((*iter)->rcache, date_name, 0);
	}

	(*iter)->rcache_idx++;

	return 0;
}
Beispiel #17
0
int
_gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq,
				const char *ext_id,
				const gnutls_datum_t * ext_data,
				unsigned int critical)
{
  unsigned char *extensions = NULL;
  size_t extensions_size = 0;
  gnutls_datum_t der;
  ASN1_TYPE c2;
  int result;

  result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
						 0, NULL, &extensions_size);
  if (result == GNUTLS_E_SHORT_MEMORY_BUFFER)
    {
      extensions = gnutls_malloc (extensions_size);
      if (extensions == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      result = gnutls_x509_crq_get_attribute_by_oid (crq,
						     "1.2.840.113549.1.9.14",
						     0, extensions,
						     &extensions_size);
    }
  if (result < 0)
    {
      if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
	{
	  extensions_size = 0;
	}
      else
	{
	  gnutls_assert ();
	  gnutls_free (extensions);
	  return result;
	}
    }

  result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Extensions", &c2);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      gnutls_free (extensions);
      return _gnutls_asn2err (result);
    }

  if (extensions_size > 0)
    {
      result = asn1_der_decoding (&c2, extensions, extensions_size, NULL);
      gnutls_free (extensions);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  asn1_delete_structure (&c2);
	  return _gnutls_asn2err (result);
	}
    }

  result = set_extension (c2, "", ext_id, ext_data, critical);
  if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&c2);
      return result;
    }

  result = _gnutls_x509_der_encode (c2, "", &der, 0);

  asn1_delete_structure (&c2);

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

  result = gnutls_x509_crq_set_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
						 der.data, der.size);
  gnutls_free (der.data);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }


  return 0;
}
Beispiel #18
0
/* Creates and encodes the CRL Distribution points. data_string should be a name
 * and type holds the type of the name. 
 * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*.
 *
 */
int
_gnutls_x509_ext_gen_crl_dist_points (gnutls_x509_subject_alt_name_t
				      type, const void *data,
				      unsigned int data_size,
				      unsigned int reason_flags,
				      gnutls_datum_t * der_ext)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  gnutls_datum_t gnames = { NULL, 0 };
  int result;
  uint8_t reasons[2];

  reasons[0] = reason_flags & 0xff;
  reasons[1] = reason_flags >> 8;

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

  result = asn1_write_value (ext, "", "NEW", 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  if (reason_flags)
    {
      result = asn1_write_value (ext, "?LAST.reasons", reasons, 9);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}
    }
  else
    {
      result = asn1_write_value (ext, "?LAST.reasons", NULL, 0);
      if (result != ASN1_SUCCESS)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}
    }

  result = asn1_write_value (ext, "?LAST.cRLIssuer", NULL, 0);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  /* When used as type CHOICE.
   */
  result = asn1_write_value (ext, "?LAST.distributionPoint", "fullName", 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

#if 0
  /* only needed in old code (where defined as SEQUENCE OF) */
  asn1_write_value (ext,
		    "?LAST.distributionPoint.nameRelativeToCRLIssuer",
		    NULL, 0);
#endif

  result =
    write_new_general_name (ext, "?LAST.distributionPoint.fullName",
			    type, data, data_size);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result = _gnutls_x509_der_encode (ext, "", der_ext, 0);

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

  result = 0;

cleanup:
  _gnutls_free_datum (&gnames);
  asn1_delete_structure (&ext);

  return result;
}
Beispiel #19
0
/**
  * gnutls_openpgp_key_export - This function will export a RAW or BASE64 encoded key
  * @key: Holds the key.
  * @format: One of gnutls_openpgp_key_fmt_t elements.
  * @output_data: will contain the key base64 encoded or raw
  * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters)
  *
  * This function will convert the given key to RAW or Base64 format.
  * If the buffer provided is not long enough to hold the output, then
  * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_openpgp_key_export (gnutls_openpgp_key_t key,
			   gnutls_openpgp_key_fmt_t format,
			   void *output_data, size_t * output_data_size)
{
  int rc;
  size_t input_data_size = *output_data_size;

  rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size);
  if (rc)
    {
      rc = _gnutls_map_cdk_rc (rc);
      gnutls_assert ();
      return rc;
    }

  if (format == GNUTLS_OPENPGP_FMT_BASE64)
    {
      cdk_stream_t s;

      s = cdk_stream_tmp_from_mem (output_data, *output_data_size);
      if (s == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      cdk_stream_tmp_set_mode (s, 1);
      rc = cdk_stream_set_armor_flag (s, CDK_ARMOR_PUBKEY);
      if (rc)
	{
	  rc = _gnutls_map_cdk_rc (rc);
	  gnutls_assert ();
	  cdk_stream_close (s);
	  return rc;
	}


      *output_data_size = input_data_size;

      rc = cdk_stream_read (s, output_data, *output_data_size);
      if (rc == EOF)
	{
	  gnutls_assert ();
	  cdk_stream_close (s);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      *output_data_size = rc;
      if (*output_data_size != cdk_stream_get_length (s))
	{
	  *output_data_size = cdk_stream_get_length (s);
	  cdk_stream_close (s);
	  gnutls_assert ();
	  return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

      cdk_stream_close (s);
    }

  return 0;
}
Beispiel #20
0
/* extract the proxyCertInfo from the DER encoded extension
 */
int
_gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint,
					char **policyLanguage,
					char **policy,
					size_t * sizeof_policy,
					opaque * extnValue, int extnValueLen)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  int result;
  gnutls_datum_t value;

  if ((result = asn1_create_element
       (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &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, "pCPathLenConstraint",
				       pathLenConstraint);
      if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
	*pathLenConstraint = -1;
      else if (result != GNUTLS_E_SUCCESS)
	{
	  asn1_delete_structure (&ext);
	  return _gnutls_asn2err (result);
	}
    }

  result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage",
				    &value, 0);
  if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return result;
    }

  if (policyLanguage)
    *policyLanguage = gnutls_strdup (value.data);

  result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0);
  if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
    {
      if (policy)
	*policy = NULL;
      if (sizeof_policy)
	*sizeof_policy = 0;
    }
  else if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return result;
    }
  else
    {
      if (policy)
	*policy = value.data;
      if (sizeof_policy)
	*sizeof_policy = value.size;
    }

  asn1_delete_structure (&ext);

  return 0;
}
Beispiel #21
0
static int
write_attributes(gnutls_pkcs12_bag_t bag, int elem,
		 ASN1_TYPE c2, const char *where)
{
	int result;
	char root[128];

	/* If the bag attributes are empty, then write
	 * nothing to the attribute field.
	 */
	if (bag->element[elem].friendly_name == NULL &&
	    bag->element[elem].local_key_id.data == NULL) {
		/* no attributes
		 */
		result = asn1_write_value(c2, where, NULL, 0);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		return 0;
	}

	if (bag->element[elem].local_key_id.data != NULL) {

		/* Add a new Attribute
		 */
		result = asn1_write_value(c2, where, "NEW", 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		_gnutls_str_cpy(root, sizeof(root), where);
		_gnutls_str_cat(root, sizeof(root), ".?LAST");

		result =
		    _gnutls_x509_encode_and_write_attribute(KEY_ID_OID, c2,
							    root,
							    bag->element
							    [elem].
							    local_key_id.data,
							    bag->element
							    [elem].
							    local_key_id.size,
							    1);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	if (bag->element[elem].friendly_name != NULL) {
		uint8_t *name;
		int size, i;
		const char *p;

		/* Add a new Attribute
		 */
		result = asn1_write_value(c2, where, "NEW", 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		/* convert name to BMPString
		 */
		size = strlen(bag->element[elem].friendly_name) * 2;
		name = gnutls_malloc(size);

		if (name == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		p = bag->element[elem].friendly_name;
		for (i = 0; i < size; i += 2) {
			name[i] = 0;
			name[i + 1] = *p;
			p++;
		}

		_gnutls_str_cpy(root, sizeof(root), where);
		_gnutls_str_cat(root, sizeof(root), ".?LAST");

		result =
		    _gnutls_x509_encode_and_write_attribute
		    (FRIENDLY_NAME_OID, c2, root, name, size, 1);

		gnutls_free(name);

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

	return 0;
}
Beispiel #22
0
/* generate the proxyCertInfo in a DER encoded extension
 */
int
_gnutls_x509_ext_gen_proxyCertInfo (int pathLenConstraint,
				    const char *policyLanguage,
				    const char *policy,
				    size_t sizeof_policy,
				    gnutls_datum_t * der_ext)
{
  ASN1_TYPE ext = ASN1_TYPE_EMPTY;
  int result;

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

  if (pathLenConstraint < 0)
    {
      result = asn1_write_value (ext, "pCPathLenConstraint", NULL, 0);
      if (result < 0)
	result = _gnutls_asn2err (result);
    }
  else
    result = _gnutls_x509_write_uint32 (ext, "pCPathLenConstraint",
					pathLenConstraint);
  if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return result;
    }

  result = asn1_write_value (ext, "proxyPolicy.policyLanguage",
			     policyLanguage, 1);
  if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return _gnutls_asn2err (result);
    }

  result = asn1_write_value (ext, "proxyPolicy.policy",
			     policy, sizeof_policy);
  if (result < 0)
    {
      gnutls_assert ();
      asn1_delete_structure (&ext);
      return _gnutls_asn2err (result);
    }

  result = _gnutls_x509_der_encode (ext, "", der_ext, 0);

  asn1_delete_structure (&ext);

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

  return 0;
}
Beispiel #23
0
/**
 * gnutls_pkcs12_simple_parse:
 * @p12: the PKCS12 blob.
 * @password: optional password used to decrypt PKCS12 blob, bags and keys.
 * @key: a structure to store the parsed private key.
 * @chain: the corresponding to key certificate chain (may be %NULL)
 * @chain_len: will be updated with the number of additional (may be %NULL)
 * @extra_certs: optional pointer to receive an array of additional
 *               certificates found in the PKCS12 blob (may be %NULL).
 * @extra_certs_len: will be updated with the number of additional
 *                   certs (may be %NULL).
 * @crl: an optional structure to store the parsed CRL (may be %NULL).
 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
 *
 * This function parses a PKCS12 blob in @p12blob and extracts the
 * private key, the corresponding certificate chain, and any additional
 * certificates and a CRL.
 *
 * The @extra_certs_ret and @extra_certs_len parameters are optional
 * and both may be set to %NULL. If either is non-%NULL, then both must
 * be set.
 * 
 * Encrypted PKCS12 bags and PKCS8 private keys are supported.  However,
 * only password based security, and the same password for all
 * operations, are supported.
 *
 * A PKCS12 file may contain many keys and/or certificates, and there
 * is no way to identify which key/certificate pair you want.  You
 * should make sure the PKCS12 file only contain one key/certificate
 * pair and/or one CRL.
 *
 * It is believed that the limitations of this function are acceptable
 * for common usage, and that any more flexibility would introduce
 * complexity that would make it harder to use this functionality at
 * all.
 *
 * If the provided structure has encrypted fields but no password
 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
 *
 * Note that normally the chain constructed does not include self signed
 * certificates, to comply with TLS' requirements. If, however, the flag 
 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
 * self signed certificates will be included in the chain.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1
 **/
int
gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12,
			   const char *password,
			   gnutls_x509_privkey_t * key,
			   gnutls_x509_crt_t ** chain,
			   unsigned int *chain_len,
			   gnutls_x509_crt_t ** extra_certs,
			   unsigned int *extra_certs_len,
			   gnutls_x509_crl_t * crl, unsigned int flags)
{
	gnutls_pkcs12_bag_t bag = NULL;
	gnutls_x509_crt_t *_extra_certs = NULL;
	unsigned int _extra_certs_len = 0;
	gnutls_x509_crt_t *_chain = NULL;
	unsigned int _chain_len = 0;
	int idx = 0;
	int ret;
	size_t cert_id_size = 0;
	size_t key_id_size = 0;
	uint8_t cert_id[20];
	uint8_t key_id[20];
	int privkey_ok = 0;
	unsigned int i;

	*key = NULL;

	if (crl)
		*crl = NULL;

	/* find the first private key */
	for (;;) {
		int elements_in_bag;
		int i;

		ret = gnutls_pkcs12_bag_init(&bag);
		if (ret < 0) {
			bag = NULL;
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_get_bag(p12, idx, bag);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_bag_get_type(bag, 0);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		if (ret == GNUTLS_BAG_ENCRYPTED) {
			if (password == NULL) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_DECRYPTION_FAILED);
				goto done;
			}

			ret = gnutls_pkcs12_bag_decrypt(bag, password);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}
		}

		elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
		if (elements_in_bag < 0) {
			gnutls_assert();
			goto done;
		}

		for (i = 0; i < elements_in_bag; i++) {
			int type;
			gnutls_datum_t data;

			type = gnutls_pkcs12_bag_get_type(bag, i);
			if (type < 0) {
				gnutls_assert();
				goto done;
			}

			ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}

			switch (type) {
			case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
				if (password == NULL) {
					ret =
					    gnutls_assert_val
					    (GNUTLS_E_DECRYPTION_FAILED);
					goto done;
				}

				/* fallthrough */
			case GNUTLS_BAG_PKCS8_KEY:
				if (*key != NULL) {	/* too simple to continue */
					gnutls_assert();
					break;
				}

				ret = gnutls_x509_privkey_init(key);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret = gnutls_x509_privkey_import_pkcs8
				    (*key, &data, GNUTLS_X509_FMT_DER,
				     password,
				     type ==
				     GNUTLS_BAG_PKCS8_KEY ?
				     GNUTLS_PKCS_PLAIN : 0);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_privkey_deinit(*key);
					goto done;
				}

				key_id_size = sizeof(key_id);
				ret =
				    gnutls_x509_privkey_get_key_id(*key, 0,
								   key_id,
								   &key_id_size);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_privkey_deinit(*key);
					goto done;
				}

				privkey_ok = 1;	/* break */
				break;
			default:
				break;
			}
		}

		idx++;
		gnutls_pkcs12_bag_deinit(bag);

		if (privkey_ok != 0)	/* private key was found */
			break;
	}

	if (privkey_ok == 0) {	/* no private key */
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	/* now find the corresponding certificate 
	 */
	idx = 0;
	bag = NULL;
	for (;;) {
		int elements_in_bag;
		int i;

		ret = gnutls_pkcs12_bag_init(&bag);
		if (ret < 0) {
			bag = NULL;
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_get_bag(p12, idx, bag);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_bag_get_type(bag, 0);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		if (ret == GNUTLS_BAG_ENCRYPTED) {
			ret = gnutls_pkcs12_bag_decrypt(bag, password);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}
		}

		elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
		if (elements_in_bag < 0) {
			gnutls_assert();
			goto done;
		}

		for (i = 0; i < elements_in_bag; i++) {
			int type;
			gnutls_datum_t data;
			gnutls_x509_crt_t this_cert;

			type = gnutls_pkcs12_bag_get_type(bag, i);
			if (type < 0) {
				gnutls_assert();
				goto done;
			}

			ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}

			switch (type) {
			case GNUTLS_BAG_CERTIFICATE:
				ret = gnutls_x509_crt_init(&this_cert);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret =
				    gnutls_x509_crt_import(this_cert,
							   &data,
							   GNUTLS_X509_FMT_DER);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crt_deinit(this_cert);
					goto done;
				}

				/* check if the key id match */
				cert_id_size = sizeof(cert_id);
				ret =
				    gnutls_x509_crt_get_key_id(this_cert,
							       0, cert_id,
							       &cert_id_size);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crt_deinit(this_cert);
					goto done;
				}

				if (memcmp(cert_id, key_id, cert_id_size) != 0) {	/* they don't match - skip the certificate */
					if (extra_certs) {
						_extra_certs =
						    gnutls_realloc_fast
						    (_extra_certs,
						     sizeof(_extra_certs
							    [0]) *
						     ++_extra_certs_len);
						if (!_extra_certs) {
							gnutls_assert();
							ret =
							    GNUTLS_E_MEMORY_ERROR;
							goto done;
						}
						_extra_certs
						    [_extra_certs_len -
						     1] = this_cert;
						this_cert = NULL;
					} else {
						gnutls_x509_crt_deinit
						    (this_cert);
					}
				} else {
					if (chain && _chain_len == 0) {
						_chain =
						    gnutls_malloc(sizeof
								  (_chain
								   [0]) *
								  (++_chain_len));
						if (!_chain) {
							gnutls_assert();
							ret =
							    GNUTLS_E_MEMORY_ERROR;
							goto done;
						}
						_chain[_chain_len - 1] =
						    this_cert;
						this_cert = NULL;
					} else {
						gnutls_x509_crt_deinit
						    (this_cert);
					}
				}
				break;

			case GNUTLS_BAG_CRL:
				if (crl == NULL || *crl != NULL) {
					gnutls_assert();
					break;
				}

				ret = gnutls_x509_crl_init(crl);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret =
				    gnutls_x509_crl_import(*crl, &data,
							   GNUTLS_X509_FMT_DER);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crl_deinit(*crl);
					goto done;
				}
				break;

			case GNUTLS_BAG_ENCRYPTED:
				/* XXX Bother to recurse one level down?  Unlikely to
				   use the same password anyway. */
			case GNUTLS_BAG_EMPTY:
			default:
				break;
			}
		}

		idx++;
		gnutls_pkcs12_bag_deinit(bag);
	}

	if (chain != NULL) {
		if (_chain_len != 1) {
			ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
			goto done;
		}

		ret =
		    make_chain(&_chain, &_chain_len, &_extra_certs,
			       &_extra_certs_len, flags);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}
	}

	ret = 0;

      done:
	if (bag)
		gnutls_pkcs12_bag_deinit(bag);

	if (ret < 0) {
		if (*key)
			gnutls_x509_privkey_deinit(*key);
		if (_extra_certs_len && _extra_certs != NULL) {
			for (i = 0; i < _extra_certs_len; i++)
				gnutls_x509_crt_deinit(_extra_certs[i]);
			gnutls_free(_extra_certs);
		}
		if (_chain_len && _chain != NULL) {
			for (i = 0; i < _chain_len; i++)
				gnutls_x509_crt_deinit(_chain[i]);
			gnutls_free(_chain);
		}

		return ret;
	}

	if (extra_certs && _extra_certs_len > 0) {
		*extra_certs = _extra_certs;
		*extra_certs_len = _extra_certs_len;
	} else {
		if (extra_certs) {
			*extra_certs = NULL;
			*extra_certs_len = 0;
		}
		for (i = 0; i < _extra_certs_len; i++)
			gnutls_x509_crt_deinit(_extra_certs[i]);
		gnutls_free(_extra_certs);
	}

	if (chain != NULL) {
		*chain = _chain;
		*chain_len = _chain_len;
	}

	return ret;
}
Beispiel #24
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,
		   int indx, void *oid, size_t * sizeof_oid)
{
  int k, result, len;
  char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
  char str[1024];
  char extnID[128];
  int indx_counter = 0;

  k = 0;
  do
    {
      k++;

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

      len = sizeof (str) - 1;
      result = asn1_read_value (asn, name, str, &len);

      /* move to next
       */

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      do
	{

	  _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 (0);
    }
  while (1);

  if (result == ASN1_ELEMENT_NOT_FOUND)
    {
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }
  else
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }
}
Beispiel #25
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_debug_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_string(pkcs12, "authSafe.content",
				     &auth_safe, ASN1_ETYPE_OCTET_STRING);
	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_debug_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;
}
Beispiel #26
0
/* This function will attempt to set the requested extension in
 * the given X509v3 certificate. 
 *
 * Critical will be either 0 or 1.
 */
static int
add_extension (ASN1_TYPE asn, const char *root, const char *extension_id,
	       const gnutls_datum_t * ext_data, unsigned int critical)
{
  int result;
  const char *str;
  char name[ASN1_MAX_NAME_SIZE];

  snprintf (name, sizeof (name), "%s", root);

  /* Add a new extension in the list.
   */
  result = asn1_write_value (asn, name, "NEW", 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (root[0] != 0)
    snprintf (name, sizeof (name), "%s.?LAST.extnID", root);
  else
    snprintf (name, sizeof (name), "?LAST.extnID");

  result = asn1_write_value (asn, name, extension_id, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (critical == 0)
    str = "FALSE";
  else
    str = "TRUE";

  if (root[0] != 0)
    snprintf (name, sizeof (name), "%s.?LAST.critical", root);
  else
    snprintf (name, sizeof (name), "?LAST.critical");

  result = asn1_write_value (asn, name, str, 1);
  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if (root[0] != 0)
    snprintf (name, sizeof (name), "%s.?LAST.extnValue", root);
  else
    snprintf (name, sizeof (name), "?LAST.extnValue");

  result = _gnutls_x509_write_value (asn, name, ext_data, 0);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  return 0;
}
Beispiel #27
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 (0) 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;
}
Beispiel #28
0
static int
get_extension (ASN1_TYPE asn, const char *root,
	       const char *extension_id, int indx,
	       gnutls_datum_t * ret, unsigned int *_critical)
{
  int k, result, len;
  char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
  char str[1024];
  char str_critical[10];
  int critical = 0;
  char extnID[128];
  gnutls_datum_t value;
  int indx_counter = 0;

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

  k = 0;
  do
    {
      k++;

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

      len = sizeof (str) - 1;
      result = asn1_read_value (asn, name, str, &len);

      /* move to next
       */

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      do
	{

	  _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 (strcmp (extnID, extension_id) == 0 && indx == indx_counter++)
	    {
	      /* extension was found 
	       */

	      /* read the critical status.
	       */
	      _gnutls_str_cpy (name2, sizeof (name2), name);
	      _gnutls_str_cat (name2, sizeof (name2), ".critical");

	      len = sizeof (str_critical);
	      result = asn1_read_value (asn, name2, str_critical, &len);

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

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

	      /* read the value.
	       */
	      _gnutls_str_cpy (name2, sizeof (name2), name);
	      _gnutls_str_cat (name2, sizeof (name2), ".extnValue");

	      result = _gnutls_x509_read_value (asn, name2, &value, 0);
	      if (result < 0)
		{
		  gnutls_assert ();
		  return result;
		}

	      ret->data = value.data;
	      ret->size = value.size;

	      if (_critical)
		*_critical = critical;

	      return 0;
	    }


	}
      while (0);
    }
  while (1);

  if (result == ASN1_ELEMENT_NOT_FOUND)
    {
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }
  else
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }
}
Beispiel #29
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 (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
{
	uint8_t key[20];
	int result;
	unsigned int iter;
	int len;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 }, salt = {
	NULL, 0};
	uint8_t sha_mac[20];
	uint8_t 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);
	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_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
				  key, sizeof(key));
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

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

	_gnutls_mac_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;
}
/*-
 * _gnutls_pkcs11_privkey_sign_hash:
 * @key: Holds the key
 * @hash: holds the data to be signed (should be output of a hash)
 * @signature: will contain the signature allocated with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. It is assumed that the given data
 * are the output of a hash function.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
                                  const gnutls_datum_t * hash,
                                  gnutls_datum_t * signature)
{
  ck_rv_t rv;
  int ret;
  struct ck_mechanism mech;
  unsigned long siglen;
  struct ck_function_list *module;
  ck_session_handle_t pks;
  ck_object_handle_t obj;

  FIND_OBJECT (module, pks, obj, key);

  mech.mechanism = pk_to_mech(key->pk_algorithm);
  mech.parameter = NULL;
  mech.parameter_len = 0;

  /* Initialize signing operation; using the private key discovered
   * earlier. */
  rv = pkcs11_sign_init (module, pks, &mech, obj);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  /* Work out how long the signature must be: */
  rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  signature->data = gnutls_malloc (siglen);
  signature->size = siglen;

  rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_free (signature->data);
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  signature->size = siglen;
  
  if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA)
    {
      bigint_t r,s;

      if (siglen % 2 != 0)
        {
          gnutls_assert();
          ret = GNUTLS_E_PK_SIGN_FAILED;
          goto cleanup;
        }

      ret = read_rs(&r, &s, signature->data, signature->size);
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
      
      gnutls_free(signature->data);
      ret = _gnutls_encode_ber_rs (signature, r, s);
      _gnutls_mpi_release(&r);
      _gnutls_mpi_release(&s);
      
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
    }

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}