/**
 * gnutls_pkcs11_privkey_generate3:
 * @url: a token URL
 * @pk: the public key algorithm
 * @bits: the security bits
 * @label: a label
 * @cid: The CKA_ID to use for the new object
 * @fmt: the format of output params. PEM or DER
 * @pubkey: will hold the public key (may be %NULL)
 * @key_usage: One of GNUTLS_KEY_*
 * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
 *
 * This function will generate a private key in the specified
 * by the @url token. The private key will be generate within
 * the token and will not be exportable. This function will
 * store the DER-encoded public key in the SubjectPublicKeyInfo format 
 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
 *
 * Note that when generating an elliptic curve key, the curve
 * can be substituted in the place of the bits parameter using the
 * GNUTLS_CURVE_TO_BITS() macro.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int
gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
				unsigned int bits, const char *label,
				const gnutls_datum_t *cid,
				gnutls_x509_crt_fmt_t fmt,
				gnutls_datum_t * pubkey,
				unsigned int key_usage,
				unsigned int flags)
{
	int ret;
	const ck_bool_t tval = 1;
	const ck_bool_t fval = 0;
	struct pkcs11_session_info sinfo;
	struct p11_kit_uri *info = NULL;
	ck_rv_t rv;
	struct ck_attribute a[22], p[22];
	ck_object_handle_t pub_ctx, priv_ctx;
	unsigned long _bits = bits;
	int a_val, p_val;
	struct ck_mechanism mech;
	gnutls_pubkey_t pkey = NULL;
	gnutls_pkcs11_obj_t obj = NULL;
	gnutls_datum_t der = {NULL, 0};
	ck_key_type_t key_type;
	uint8_t id[20];
	struct dsa_params dsa_params;

	PKCS11_CHECK_INIT;
	FIX_KEY_USAGE(pk, key_usage);

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

	ret = pkcs11_url_to_info(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();
		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, &key_type);

	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
		a[a_val].type = CKA_TOKEN;
		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++;
	}

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

		a[a_val].value = (void *) id;
		a[a_val].value_len = sizeof(id);
	} else {
		a[a_val].value = (void *) cid->data;
		a[a_val].value_len = cid->size;
	}

	p[p_val].type = CKA_ID;
	p[p_val].value = a[a_val].value;
	p[p_val].value_len = a[a_val].value_len;
	a_val++;
	p_val++;

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

		p[p_val].type = CKA_SIGN;
		if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
			p[p_val].value = (void *) &tval;
			p[p_val].value_len = sizeof(tval);
		} else {
			p[p_val].value = (void *) &fval;
			p[p_val].value_len = sizeof(fval);
		}
		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++;

		a[a_val].type = CKA_PUBLIC_EXPONENT;
		a[a_val].value = (char*)def_rsa_pub_exp;
		a[a_val].value_len = sizeof(def_rsa_pub_exp);
		a_val++;

		break;
	case GNUTLS_PK_DSA:
		p[p_val].type = CKA_SIGN;
		if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
			p[p_val].value = (void *) &tval;
			p[p_val].value_len = sizeof(tval);
		} else {
			p[p_val].value = (void *) &fval;
			p[p_val].value_len = sizeof(fval);
		}
		p_val++;

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

		ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
					   &dsa_params, a, &a_val);
		if (ret < 0) {
			goto cleanup;
		}

		break;
	case GNUTLS_PK_EC:
		p[p_val].type = CKA_SIGN;
		if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
			p[p_val].value = (void *) &tval;
			p[p_val].value_len = sizeof(tval);
		} else {
			p[p_val].value = (void *) &fval;
			p[p_val].value_len = sizeof(fval);
		}
		p_val++;

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

		if (GNUTLS_BITS_ARE_CURVE(bits)) {
			bits = GNUTLS_BITS_TO_CURVE(bits);
		} else {
			bits = _gnutls_ecc_bits_to_curve(bits);
		}

		ret = _gnutls_x509_write_ecc_params(bits, &der);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		a[a_val].type = CKA_EC_PARAMS;
		a[a_val].value = der.data;
		a[a_val].value_len = der.size;
		a_val++;
		break;
	default:
		ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
		goto cleanup;
	}

	/*
	 * on request, add the CKA_WRAP/CKA_UNWRAP key attribute
	 */
	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
		p[p_val].type = CKA_UNWRAP;
		p[p_val].value = (void*)&tval;
		p[p_val].value_len = sizeof(tval);
		p_val++;
		a[a_val].type = CKA_WRAP;
		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) {
		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(sinfo.module, sinfo.pks, &mech, a,
				      a_val, p, p_val, &pub_ctx, &priv_ctx);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* extract the public key */
	if (pubkey) {

		ret = gnutls_pubkey_init(&pkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pkcs11_obj_init(&obj);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		obj->pk_algorithm = pk;
		obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
		ret =
		    pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub_ctx,
				       key_type, obj);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

      cleanup:
	if (obj != NULL)
		gnutls_pkcs11_obj_deinit(obj);
	if (pkey != NULL)
		gnutls_pubkey_deinit(pkey);

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

	return ret;
}
Example #2
0
/**
 * gnutls_pkcs11_privkey_generate2:
 * @url: a token URL
 * @pk: the public key algorithm
 * @bits: the security bits
 * @label: a label
 * @fmt: the format of output params. PEM or DER.
 * @pubkey: will hold the public key (may be %NULL)
 * @flags: should be zero
 *
 * This function will generate a private key in the specified
 * by the @url token. The private key will be generate within
 * the token and will not be exportable. This function will
 * store the DER-encoded public key in the SubjectPublicKeyInfo format 
 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1.5
 **/
int
gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
				unsigned int bits, const char *label,
				gnutls_x509_crt_fmt_t fmt,
				gnutls_datum_t * pubkey,
				unsigned int flags)
{
	int ret;
	const ck_bool_t tval = 1;
	const ck_bool_t fval = 0;
	struct pkcs11_session_info sinfo;
	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;
	gnutls_pubkey_t pkey = NULL;
	gnutls_pkcs11_obj_t obj = NULL;

	PKCS11_CHECK_INIT;

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

	ret = pkcs11_url_to_info(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();
		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(sinfo.module, sinfo.pks, &mech, a,
				      a_val, p, p_val, &pub, &priv);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}

	/* extract the public key */
	if (pubkey) {
		ret = gnutls_pubkey_init(&pkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pkcs11_obj_init(&obj);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		obj->pk_algorithm = pk;
		obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
		ret =
		    pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub,
				       mech.mechanism, obj->pubkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}


      cleanup:
	if (obj != NULL)
		gnutls_pkcs11_obj_deinit(obj);
	if (pkey != NULL)
		gnutls_pubkey_deinit(pkey);
	if (sinfo.pks != 0)
		pkcs11_close_session(&sinfo);

	return ret;
}
int
_pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
{
	gnutls_pubkey_t pubkey = NULL;
	gnutls_pkcs11_obj_t obj = NULL;
	ck_key_type_t key_type;
	int ret;

	PKCS11_CHECK_INIT_PRIVKEY(pkey);

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

	ret = gnutls_pubkey_init(&pubkey);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs11_obj_init(&obj);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
	obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
	pk_to_genmech(obj->pk_algorithm, &key_type);

	gnutls_pubkey_set_pin_function(pubkey, pkey->pin.cb, pkey->pin.data);

	/* we can only read the public key from RSA keys */
	if (key_type != CKK_RSA) {
		/* try opening the public key object if it exists */
		ret = load_pubkey_obj(pkey, pubkey);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	*pub = pubkey;

	pubkey = NULL;
	ret = 0;

 cleanup:
	if (obj != NULL)
		gnutls_pkcs11_obj_deinit(obj);
	if (pubkey != NULL)
		gnutls_pubkey_deinit(pubkey);

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