/*! * Get binary key ID from a key (public or private). */ static int keyid_bin(gnutls_x509_privkey_t key, gnutls_pubkey_t pubkey, dnssec_binary_t *id) { assert(key || pubkey); assert(id); // Flags can be used to enable SHA-2 since GnuTLS 3.4.7. int flags = 0; uint8_t *buffer = alloca(DNSSEC_KEYID_BINARY_SIZE); size_t size = DNSSEC_KEYID_SIZE; int r = key ? gnutls_x509_privkey_get_key_id(key, flags, buffer, &size) : gnutls_pubkey_get_key_id(pubkey, flags, buffer, &size); if (r != GNUTLS_E_SUCCESS || size != DNSSEC_KEYID_BINARY_SIZE) { return DNSSEC_INVALID_KEY_ID; } assert(size == DNSSEC_KEYID_BINARY_SIZE); r = dnssec_binary_resize(id, size); if (r != DNSSEC_EOK) { return r; } memcpy(id->data, buffer, size); return DNSSEC_EOK; }
InfoHash PublicKey::getId() const { InfoHash id; size_t sz = id.size(); if (gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz) != GNUTLS_E_SUCCESS || sz != id.size()) return {}; return id; }
/** * 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; }