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