Пример #1
0
/**
 * gnutls_pkcs11_copy_x509_privkey2:
 * @token_url: A PKCS #11 URL specifying a token
 * @key: A private key
 * @label: A name to be used for the stored data
 * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
 * @key_usage: One of GNUTLS_KEY_*
 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
 *
 * This function will copy a private key into a PKCS #11 token specified by
 * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
 * unless there is a strong reason not to.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int
gnutls_pkcs11_copy_x509_privkey2(const char *token_url,
				gnutls_x509_privkey_t key,
				const char *label,
				const gnutls_datum_t *cid,
				unsigned int key_usage, unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t id_size;
	uint8_t id[20];
	struct ck_attribute a[32];
	ck_object_class_t class = CKO_PRIVATE_KEY;
	ck_object_handle_t ctx;
	ck_key_type_t type;
	int a_val;
	gnutls_pk_algorithm_t pk;
	gnutls_datum_t p, q, g, y, x;
	gnutls_datum_t m, e, d, u, exp1, exp2;
	struct pkcs11_session_info sinfo;

	PKCS11_CHECK_INIT;

	memset(&p, 0, sizeof(p));
	memset(&q, 0, sizeof(q));
	memset(&g, 0, sizeof(g));
	memset(&y, 0, sizeof(y));
	memset(&x, 0, sizeof(x));
	memset(&m, 0, sizeof(m));
	memset(&e, 0, sizeof(e));
	memset(&d, 0, sizeof(d));
	memset(&u, 0, sizeof(u));
	memset(&exp1, 0, sizeof(exp1));
	memset(&exp2, 0, sizeof(exp2));

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

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	pk = gnutls_x509_privkey_get_pk_algorithm(key);
	FIX_KEY_USAGE(pk, key_usage);

	/* FIXME: copy key usage flags */
	a_val = 0;
	a[a_val].type = CKA_CLASS;
	a[a_val].value = &class;
	a[a_val].value_len = sizeof(class);
	a_val++;

	a[a_val].type = CKA_ID;
	if (cid == NULL || cid->size == 0) {
		id_size = sizeof(id);
		ret = gnutls_x509_privkey_get_key_id(key, 0, id, &id_size);
		if (ret < 0) {
			p11_kit_uri_free(info);
			gnutls_assert();
			return ret;
		}

		a[a_val].value = id;
		a[a_val].value_len = id_size;
	} else {
		a[a_val].value = cid->data;
		a[a_val].value_len = cid->size;
	}
	a_val++;

	a[a_val].type = CKA_SIGN;
	if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
		a[a_val].value = (void*)&tval;
		a[a_val].value_len = sizeof(tval);
	} else {
		a[a_val].value = (void*)&fval;
		a[a_val].value_len = sizeof(fval);
	}
	a_val++;

	if (pk == GNUTLS_PK_RSA) {
		a[a_val].type = CKA_DECRYPT;
		if (key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) {
			a[a_val].value = (void*)&tval;
			a[a_val].value_len = sizeof(tval);
		} else {
			a[a_val].value = (void*)&fval;
			a[a_val].value_len = sizeof(fval);
		}
		a_val++;
	}

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

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

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH) {
		a[a_val].type = CKA_ALWAYS_AUTHENTICATE;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE) {
		a[a_val].type = CKA_EXTRACTABLE;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		(a_val)++;
	} else {
		a[a_val].type = CKA_EXTRACTABLE;
		a[a_val].value = (void *) &fval;
		a[a_val].value_len = sizeof(fval);
		(a_val)++;
	}

	if (label) {
		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) {
		a[a_val].type = CKA_SENSITIVE;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		a_val++;
	} else {
		a[a_val].type = CKA_SENSITIVE;
		a[a_val].value = (void *) &fval;
		a[a_val].value_len = sizeof(fval);
		a_val++;
	}

	switch (pk) {
	case GNUTLS_PK_RSA:
		{

			ret =
			    gnutls_x509_privkey_export_rsa_raw2(key, &m,
								&e, &d, &p,
								&q, &u,
								&exp1,
								&exp2);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			type = CKK_RSA;

			skip_leading_zeros(&m);
			skip_leading_zeros(&e);
			skip_leading_zeros(&d);
			skip_leading_zeros(&p);
			skip_leading_zeros(&q);
			skip_leading_zeros(&u);
			skip_leading_zeros(&exp1);
			skip_leading_zeros(&exp2);

			a[a_val].type = CKA_MODULUS;
			a[a_val].value = m.data;
			a[a_val].value_len = m.size;
			a_val++;

			a[a_val].type = CKA_PUBLIC_EXPONENT;
			a[a_val].value = e.data;
			a[a_val].value_len = e.size;
			a_val++;

			a[a_val].type = CKA_PRIVATE_EXPONENT;
			a[a_val].value = d.data;
			a[a_val].value_len = d.size;
			a_val++;

			a[a_val].type = CKA_PRIME_1;
			a[a_val].value = p.data;
			a[a_val].value_len = p.size;
			a_val++;

			a[a_val].type = CKA_PRIME_2;
			a[a_val].value = q.data;
			a[a_val].value_len = q.size;
			a_val++;

			a[a_val].type = CKA_COEFFICIENT;
			a[a_val].value = u.data;
			a[a_val].value_len = u.size;
			a_val++;

			a[a_val].type = CKA_EXPONENT_1;
			a[a_val].value = exp1.data;
			a[a_val].value_len = exp1.size;
			a_val++;

			a[a_val].type = CKA_EXPONENT_2;
			a[a_val].value = exp2.data;
			a[a_val].value_len = exp2.size;
			a_val++;

			break;
		}
	case GNUTLS_PK_DSA:
		{
			ret =
			    gnutls_x509_privkey_export_dsa_raw(key, &p, &q,
							       &g, &y, &x);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			type = CKK_DSA;

			skip_leading_zeros(&p);
			skip_leading_zeros(&q);
			skip_leading_zeros(&g);
			skip_leading_zeros(&y);
			skip_leading_zeros(&x);

			a[a_val].type = CKA_PRIME;
			a[a_val].value = p.data;
			a[a_val].value_len = p.size;
			a_val++;

			a[a_val].type = CKA_SUBPRIME;
			a[a_val].value = q.data;
			a[a_val].value_len = q.size;
			a_val++;

			a[a_val].type = CKA_BASE;
			a[a_val].value = g.data;
			a[a_val].value_len = g.size;
			a_val++;

			a[a_val].type = CKA_VALUE;
			a[a_val].value = x.data;
			a[a_val].value_len = x.size;
			a_val++;

			break;
		}
	case GNUTLS_PK_EC:
		{
			ret =
			    _gnutls_x509_write_ecc_params(key->params.flags,
							  &p);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret =
			    _gnutls_mpi_dprint(key->params.
						params[ECC_K], &x);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			type = CKK_ECDSA;

			a[a_val].type = CKA_EC_PARAMS;
			a[a_val].value = p.data;
			a[a_val].value_len = p.size;
			a_val++;

			a[a_val].type = CKA_VALUE;
			a[a_val].value = x.data;
			a[a_val].value_len = x.size;
			a_val++;

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

	a[a_val].type = CKA_KEY_TYPE;
	a[a_val].value = &type;
	a[a_val].value_len = sizeof(type);
	a_val++;

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	ret = 0;

      cleanup:
	switch (pk) {
	case GNUTLS_PK_RSA:
		{
			gnutls_free(m.data);
			gnutls_free(e.data);
			gnutls_free(d.data);
			gnutls_free(p.data);
			gnutls_free(q.data);
			gnutls_free(u.data);
			gnutls_free(exp1.data);
			gnutls_free(exp2.data);
			break;
		}
	case GNUTLS_PK_DSA:
		{
			gnutls_free(p.data);
			gnutls_free(q.data);
			gnutls_free(g.data);
			gnutls_free(y.data);
			gnutls_free(x.data);
			break;
		}
	case GNUTLS_PK_EC:
		{
			gnutls_free(p.data);
			gnutls_free(x.data);
			break;
		}
	default:
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		break;
	}

	if (sinfo.pks != 0)
		pkcs11_close_session(&sinfo);

	return ret;

}
Пример #2
0
/**
 * gnutls_pkcs11_copy_attached_extension:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: An X.509 certificate object
 * @data: the attached extension
 * @label: A name to be used for the attached extension (may be %NULL)
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy an the attached extension in @data for
 * the certificate provided in @crt in the PKCS #11 token specified
 * by the URL (typically a trust module). The extension must be in
 * RFC5280 Extension format.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.3.8
 **/
int
gnutls_pkcs11_copy_attached_extension(const char *token_url,
		       gnutls_x509_crt_t crt,
		       gnutls_datum_t *data,
		       const char *label,
		       unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	struct ck_attribute a[MAX_ASIZE];
	ck_object_handle_t ctx;
	unsigned a_vals;
	struct pkcs11_session_info sinfo;
	ck_object_class_t class;
	gnutls_datum_t spki = {NULL, 0};
	
	PKCS11_CHECK_INIT;

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

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	ret = x509_crt_to_raw_pubkey(crt, &spki);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	class = CKO_X_CERTIFICATE_EXTENSION;
	a_vals = 0;
	a[a_vals].type = CKA_CLASS;
	a[a_vals].value = &class;
	a[a_vals++].value_len = sizeof(class);

	a[a_vals].type = CKA_PUBLIC_KEY_INFO;
	a[a_vals].value = spki.data;
	a[a_vals++].value_len = spki.size;

	a[a_vals].type = CKA_VALUE;
	a[a_vals].value = data->data;
	a[a_vals++].value_len = data->size;

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

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

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_vals, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	ret = 0;

      cleanup:
	pkcs11_close_session(&sinfo);
	gnutls_free(spki.data);
	return ret;

}
Пример #3
0
/**
 * gnutls_pkcs11_copy_pubkey:
 * @token_url: A PKCS #11 URL specifying a token
 * @pubkey: The public key to copy
 * @label: The name to be used for the stored data
 * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
 * @key_usage: One of GNUTLS_KEY_*
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a public key object into a PKCS #11 token specified by
 * a URL. Valid flags to mark the key: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.6
 **/
int
gnutls_pkcs11_copy_pubkey(const char *token_url,
			  gnutls_pubkey_t pubkey, const char *label,
			  const gnutls_datum_t *cid,
			  unsigned int key_usage, unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t id_size;
	uint8_t id[20];
	struct ck_attribute a[MAX_ASIZE];
	gnutls_pk_algorithm_t pk;
	ck_object_class_t class = CKO_PUBLIC_KEY;
	ck_object_handle_t ctx;
	unsigned a_val;
	ck_key_type_t type;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

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

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);

	a[1].type = CKA_TOKEN;
	a[1].value = (void *) &tval;
	a[1].value_len = sizeof(tval);

	a_val = 2;

	ret = add_pubkey(pubkey, a, &a_val);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

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

	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
	type = pk_to_key_type(pk);
	FIX_KEY_USAGE(pk, key_usage);

	a[a_val].type = CKA_KEY_TYPE;
	a[a_val].value = &type;
	a[a_val].value_len = sizeof(type);
	a_val++;

	a[a_val].type = CKA_ID;
	if (cid == NULL || cid->size == 0) {
		id_size = sizeof(id);
		ret = gnutls_pubkey_get_key_id(pubkey, 0, id, &id_size);
		if (ret < 0) {
			  gnutls_assert();
			  goto cleanup;
		}

		a[a_val].value = id;
		a[a_val].value_len = id_size;
	} else {
		a[a_val].value = cid->data;
		a[a_val].value_len = cid->size;
	}
	a_val++;

	mark_flags(flags, a, &a_val, sinfo.trusted);

	a[a_val].type = CKA_VERIFY;
	if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
		a[a_val].value = (void*)&tval;
		a[a_val].value_len = sizeof(tval);
	} else {
		a[a_val].value = (void*)&fval;
		a[a_val].value_len = sizeof(fval);
	}
	a_val++;

	if (pk == GNUTLS_PK_RSA) {
		a[a_val].type = CKA_ENCRYPT;
		if (key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) {
			a[a_val].value = (void*)&tval;
			a[a_val].value_len = sizeof(tval);
		} else {
			a[a_val].value = (void*)&fval;
			a[a_val].value_len = sizeof(fval);
		}
		a_val++;
	}

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	clean_pubkey(a, a_val);
	pkcs11_close_session(&sinfo);
	return ret;

}
Пример #4
0
/**
 * gnutls_pkcs11_copy_x509_crt2:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: The certificate to copy
 * @label: The name to be used for the stored data
 * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a certificate into a PKCS #11 token specified by
 * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE,
 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int
gnutls_pkcs11_copy_x509_crt2(const char *token_url,
			    gnutls_x509_crt_t crt, const char *label,
			    const gnutls_datum_t *cid,
			    unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t der_size, id_size, serial_size;
	gnutls_datum_t serial_der = {NULL, 0};
	uint8_t *der = NULL;
	uint8_t serial[128];
	uint8_t id[20];
	struct ck_attribute a[MAX_ASIZE];
	ck_object_class_t class = CKO_CERTIFICATE;
	ck_certificate_type_t type = CKC_X_509;
	ck_object_handle_t ctx;
	unsigned a_val;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

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

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	der_size = 0;
	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
				   &der_size);
	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		goto cleanup;
	}

	der = gnutls_malloc(der_size);
	if (der == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
				   &der_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);

	a[1].type = CKA_ID;
	if (cid == NULL || cid->size == 0) {
		id_size = sizeof(id);
		ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
		if (ret < 0) {
			id_size = sizeof(id);
			ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
			if (ret < 0) {
			  gnutls_assert();
			  goto cleanup;
			}
		}

		a[1].value = id;
		a[1].value_len = id_size;
	} else {
		a[1].value = cid->data;
		a[1].value_len = cid->size;
	}

	a[2].type = CKA_VALUE;
	a[2].value = der;
	a[2].value_len = der_size;
	a[3].type = CKA_TOKEN;
	a[3].value = (void *) &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_CERTIFICATE_TYPE;
	a[4].value = &type;
	a[4].value_len = sizeof(type);
	/* FIXME: copy key usage flags */

	a_val = 5;

	a[a_val].type = CKA_SUBJECT;
	a[a_val].value = crt->raw_dn.data;
	a[a_val].value_len = crt->raw_dn.size;
	a_val++;

	a[a_val].type = CKA_ISSUER;
	a[a_val].value = crt->raw_issuer_dn.data;
	a[a_val].value_len = crt->raw_issuer_dn.size;
	a_val++;

	serial_size = sizeof(serial);
	if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
		ret = _gnutls_x509_ext_gen_number(serial, serial_size, &serial_der);
		if (ret >= 0) {
			a[a_val].type = CKA_SERIAL_NUMBER;
			a[a_val].value = (void *) serial_der.data;
			a[a_val].value_len = serial_der.size;
			a_val++;
		}
	}

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

	mark_flags(flags, a, &a_val, sinfo.trusted);

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	gnutls_free(der);
	gnutls_free(serial_der.data);
	pkcs11_close_session(&sinfo);
	return ret;

}
Пример #5
0
/**
 * gnutls_pkcs11_copy_secret_key:
 * @token_url: A PKCS #11 URL specifying a token
 * @key: The raw key
 * @label: A name to be used for the stored data
 * @key_usage: One of GNUTLS_KEY_*
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a raw secret (symmetric) key into a PKCS #11 
 * token specified by a URL. The key can be marked as sensitive or not.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pkcs11_copy_secret_key(const char *token_url, gnutls_datum_t * key,
			      const char *label,
			      unsigned int key_usage, unsigned int flags
			      /* GNUTLS_PKCS11_OBJ_FLAG_* */ )
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	struct ck_attribute a[12];
	ck_object_class_t class = CKO_SECRET_KEY;
	ck_object_handle_t obj;
	ck_key_type_t keytype = CKK_GENERIC_SECRET;
	ck_bool_t tval = 1;
	int a_val;
	uint8_t id[16];
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

	memset(&sinfo, 0, sizeof(sinfo));

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

	/* generate a unique ID */
	ret = _gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	/* FIXME: copy key usage flags */

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);
	a[1].type = CKA_VALUE;
	a[1].value = key->data;
	a[1].value_len = key->size;
	a[2].type = CKA_TOKEN;
	a[2].value = &tval;
	a[2].value_len = sizeof(tval);
	a[3].type = CKA_PRIVATE;
	a[3].value = &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_KEY_TYPE;
	a[4].value = &keytype;
	a[4].value_len = sizeof(keytype);
	a[5].type = CKA_ID;
	a[5].value = id;
	a[5].value_len = sizeof(id);

	a_val = 6;

	if (label) {
		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)
		tval = 1;
	else
		tval = 0;

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

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	pkcs11_close_session(&sinfo);

	return ret;

}
Пример #6
0
/**
 * gnutls_pkcs11_copy_x509_crt:
 * @token_url: A PKCS #11 URL specifying a token
 * @crt: A certificate
 * @label: A name to be used for the stored data
 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
 *
 * This function will copy a certificate into a PKCS #11 token specified by
 * a URL. The certificate can be marked as trusted or not.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_pkcs11_copy_x509_crt(const char *token_url,
			    gnutls_x509_crt_t crt, const char *label,
			    unsigned int flags)
{
	int ret;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	size_t der_size, id_size;
	uint8_t *der = NULL;
	uint8_t id[20];
	struct ck_attribute a[16];
	ck_object_class_t class = CKO_CERTIFICATE;
	ck_certificate_type_t type = CKC_X_509;
	ck_object_handle_t obj;
	int a_val;
	unsigned long category;
	struct pkcs11_session_info sinfo;
	
	PKCS11_CHECK_INIT;

	memset(&sinfo, 0, sizeof(sinfo));

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

	ret =
	    pkcs11_open_session(&sinfo, NULL, info,
				SESSION_WRITE |
				pkcs11_obj_flags_to_int(flags));
	p11_kit_uri_free(info);

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

	der_size = 0;
	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
				   &der_size);
	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		goto cleanup;
	}

	der = gnutls_malloc(der_size);
	if (der == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret =
	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
				   &der_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	id_size = sizeof(id);
	ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
	if (ret < 0) {
	        id_size = sizeof(id);
		ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
		if (ret < 0) {
		  gnutls_assert();
		  goto cleanup;
                }
	}

	/* FIXME: copy key usage flags */

	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof(class);
	a[1].type = CKA_ID;
	a[1].value = id;
	a[1].value_len = id_size;
	a[2].type = CKA_VALUE;
	a[2].value = der;
	a[2].value_len = der_size;
	a[3].type = CKA_TOKEN;
	a[3].value = (void *) &tval;
	a[3].value_len = sizeof(tval);
	a[4].type = CKA_CERTIFICATE_TYPE;
	a[4].value = &type;
	a[4].value_len = sizeof(type);

	a_val = 5;

	a[a_val].type = CKA_SUBJECT;
	a[a_val].value = crt->raw_dn.data;
	a[a_val].value_len = crt->raw_dn.size;
	a_val++;

	if (label) {
		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_CA) {
		category = 2;
		a[a_val].type = CKA_CERTIFICATE_CATEGORY;
		a[a_val].value = (void *) &category;
		a[a_val].value_len = sizeof(category);
		a_val++;
	}

	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
		a[a_val].type = CKA_TRUSTED;
		a[a_val].value = (void *) &tval;
		a[a_val].value_len = sizeof(tval);
		a_val++;

		a[a_val].type = CKA_PRIVATE;
		a[a_val].value = (void *) &fval;
		a[a_val].value_len = sizeof(fval);
		a_val++;
	} else {
		if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &tval;
			a[a_val].value_len = sizeof(tval);
			a_val++;
		} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
			a[a_val].type = CKA_PRIVATE;
			a[a_val].value = (void *) &fval;
			a[a_val].value_len = sizeof(fval);
			a_val++;
		}
	}

	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* generated! 
	 */

	ret = 0;

      cleanup:
	gnutls_free(der);
	pkcs11_close_session(&sinfo);
	return ret;

}