vici: Add command to load a private key from a token
PINs are stored in a "hidden" credential set, so that its shared secrets are not exposed via VICI. Since they are not explicitly loaded as shared secrets via VICI a client might consider them as removed secrets and remove them.
This commit is contained in:
@@ -491,6 +491,24 @@ including keys found in other backends.
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### load-token() ###
|
||||||
|
|
||||||
|
Load a private key located on a token into the daemon. Such keys may be listed
|
||||||
|
and unloaded using the _get-keys_ and _unload-key_ commands, respectively (based
|
||||||
|
on the key identifier derived from the public key).
|
||||||
|
|
||||||
|
{
|
||||||
|
handle = <hex-encoded CKA_ID of the private key on token>
|
||||||
|
slot = <optional slot number>
|
||||||
|
module = <optional PKCS#11 module>
|
||||||
|
pin = <optional PIN to access the key, has to be provided via other
|
||||||
|
means if not given>
|
||||||
|
} => {
|
||||||
|
success = <yes or no>
|
||||||
|
errmsg = <error string on failure>
|
||||||
|
id = <hex-encoded SHA-1 key identifier of the public key on success>
|
||||||
|
}
|
||||||
|
|
||||||
### load-shared() ###
|
### load-shared() ###
|
||||||
|
|
||||||
Load a shared IKE PSK, EAP or XAuth secret into the daemon.
|
Load a shared IKE PSK, EAP or XAuth secret into the daemon.
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ struct private_vici_cred_t {
|
|||||||
*/
|
*/
|
||||||
mem_cred_t *creds;
|
mem_cred_t *creds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* separate credential set for token PINs
|
||||||
|
*/
|
||||||
|
mem_cred_t *pins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache CRLs to disk?
|
* cache CRLs to disk?
|
||||||
*/
|
*/
|
||||||
@@ -255,7 +260,7 @@ CALLBACK(unload_key, vici_message_t*,
|
|||||||
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
|
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
|
||||||
{
|
{
|
||||||
chunk_t keyid;
|
chunk_t keyid;
|
||||||
char *hex, *msg = NULL;
|
char buf[BUF_LEN], *hex, *msg = NULL;
|
||||||
|
|
||||||
hex = message->get_str(message, NULL, "id");
|
hex = message->get_str(message, NULL, "id");
|
||||||
if (!hex)
|
if (!hex)
|
||||||
@@ -263,8 +268,13 @@ CALLBACK(unload_key, vici_message_t*,
|
|||||||
return create_reply("key id missing");
|
return create_reply("key id missing");
|
||||||
}
|
}
|
||||||
keyid = chunk_from_hex(chunk_from_str(hex), NULL);
|
keyid = chunk_from_hex(chunk_from_str(hex), NULL);
|
||||||
DBG1(DBG_CFG, "unloaded private key with id %+B", &keyid);
|
snprintf(buf, sizeof(buf), "%+B", &keyid);
|
||||||
if (!this->creds->remove_key(this->creds, keyid))
|
DBG1(DBG_CFG, "unloaded private key with id %s", buf);
|
||||||
|
if (this->creds->remove_key(this->creds, keyid))
|
||||||
|
{ /* also remove any potential PIN associated with this id */
|
||||||
|
this->pins->remove_shared_unique(this->pins, buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
msg = "key not found";
|
msg = "key not found";
|
||||||
}
|
}
|
||||||
@@ -298,6 +308,87 @@ CALLBACK(get_keys, vici_message_t*,
|
|||||||
return builder->finalize(builder);
|
return builder->finalize(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CALLBACK(load_token, vici_message_t*,
|
||||||
|
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
|
||||||
|
{
|
||||||
|
vici_builder_t *builder;
|
||||||
|
private_key_t *key;
|
||||||
|
shared_key_t *shared = NULL;
|
||||||
|
identification_t *owner;
|
||||||
|
mem_cred_t *set = NULL;
|
||||||
|
chunk_t handle, fp;
|
||||||
|
char buf[BUF_LEN], *hex, *module, *pin, *unique = NULL;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
hex = message->get_str(message, NULL, "handle");
|
||||||
|
if (!hex)
|
||||||
|
{
|
||||||
|
return create_reply("keyid missing");
|
||||||
|
}
|
||||||
|
handle = chunk_from_hex(chunk_from_str(hex), NULL);
|
||||||
|
slot = message->get_int(message, -1, "slot");
|
||||||
|
module = message->get_str(message, NULL, "module");
|
||||||
|
pin = message->get_str(message, NULL, "pin");
|
||||||
|
|
||||||
|
if (pin)
|
||||||
|
{ /* provide the pin in a temporary credential set to access the key */
|
||||||
|
shared = shared_key_create(SHARED_PIN, chunk_clone(chunk_from_str(pin)));
|
||||||
|
owner = identification_create_from_encoding(ID_KEY_ID, handle);
|
||||||
|
set = mem_cred_create();
|
||||||
|
set->add_shared(set, shared->get_ref(shared), owner, NULL);
|
||||||
|
lib->credmgr->add_local_set(lib->credmgr, &set->set, FALSE);
|
||||||
|
}
|
||||||
|
if (slot >= 0)
|
||||||
|
{
|
||||||
|
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
||||||
|
BUILD_PKCS11_KEYID, handle,
|
||||||
|
BUILD_PKCS11_SLOT, slot,
|
||||||
|
module ? BUILD_PKCS11_MODULE : BUILD_END, module,
|
||||||
|
BUILD_END);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
||||||
|
BUILD_PKCS11_KEYID, handle,
|
||||||
|
module ? BUILD_PKCS11_MODULE : BUILD_END, module,
|
||||||
|
BUILD_END);
|
||||||
|
}
|
||||||
|
if (set)
|
||||||
|
{
|
||||||
|
lib->credmgr->remove_local_set(lib->credmgr, &set->set);
|
||||||
|
set->destroy(set);
|
||||||
|
}
|
||||||
|
if (!key)
|
||||||
|
{
|
||||||
|
chunk_free(&handle);
|
||||||
|
DESTROY_IF(shared);
|
||||||
|
return create_reply("loading private key from token failed");
|
||||||
|
}
|
||||||
|
builder = vici_builder_create();
|
||||||
|
builder->add_kv(builder, "success", "yes");
|
||||||
|
if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp))
|
||||||
|
{
|
||||||
|
snprintf(buf, sizeof(buf), "%+B", &fp);
|
||||||
|
builder->add_kv(builder, "id", "%s", buf);
|
||||||
|
unique = buf;
|
||||||
|
}
|
||||||
|
if (shared && unique)
|
||||||
|
{ /* use the handle as owner, but the key identifier as unique ID */
|
||||||
|
owner = identification_create_from_encoding(ID_KEY_ID, handle);
|
||||||
|
this->pins->add_shared_unique(this->pins, unique, shared,
|
||||||
|
linked_list_create_with_items(owner, NULL));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DESTROY_IF(shared);
|
||||||
|
}
|
||||||
|
DBG1(DBG_CFG, "loaded %N private key from token", key_type_names,
|
||||||
|
key->get_type(key));
|
||||||
|
this->creds->add_key(this->creds, key);
|
||||||
|
chunk_free(&handle);
|
||||||
|
return builder->finalize(builder);
|
||||||
|
}
|
||||||
|
|
||||||
CALLBACK(shared_owners, bool,
|
CALLBACK(shared_owners, bool,
|
||||||
linked_list_t *owners, vici_message_t *message, char *name, chunk_t value)
|
linked_list_t *owners, vici_message_t *message, char *name, chunk_t value)
|
||||||
{
|
{
|
||||||
@@ -474,6 +565,7 @@ static void manage_commands(private_vici_cred_t *this, bool reg)
|
|||||||
manage_command(this, "load-key", load_key, reg);
|
manage_command(this, "load-key", load_key, reg);
|
||||||
manage_command(this, "unload-key", unload_key, reg);
|
manage_command(this, "unload-key", unload_key, reg);
|
||||||
manage_command(this, "get-keys", get_keys, reg);
|
manage_command(this, "get-keys", get_keys, reg);
|
||||||
|
manage_command(this, "load-token", load_token, reg);
|
||||||
manage_command(this, "load-shared", load_shared, reg);
|
manage_command(this, "load-shared", load_shared, reg);
|
||||||
manage_command(this, "unload-shared", unload_shared, reg);
|
manage_command(this, "unload-shared", unload_shared, reg);
|
||||||
manage_command(this, "get-shared", get_shared, reg);
|
manage_command(this, "get-shared", get_shared, reg);
|
||||||
@@ -492,6 +584,8 @@ METHOD(vici_cred_t, destroy, void,
|
|||||||
|
|
||||||
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
|
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
|
||||||
this->creds->destroy(this->creds);
|
this->creds->destroy(this->creds);
|
||||||
|
lib->credmgr->remove_set(lib->credmgr, &this->pins->set);
|
||||||
|
this->pins->destroy(this->pins);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,6 +610,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
|
|||||||
},
|
},
|
||||||
.dispatcher = dispatcher,
|
.dispatcher = dispatcher,
|
||||||
.creds = mem_cred_create(),
|
.creds = mem_cred_create(),
|
||||||
|
.pins = mem_cred_create(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (lib->settings->get_bool(lib->settings, "%s.cache_crls", FALSE, lib->ns))
|
if (lib->settings->get_bool(lib->settings, "%s.cache_crls", FALSE, lib->ns))
|
||||||
@@ -524,6 +619,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
|
|||||||
DBG1(DBG_CFG, "crl caching to %s enabled", CRL_DIR);
|
DBG1(DBG_CFG, "crl caching to %s enabled", CRL_DIR);
|
||||||
}
|
}
|
||||||
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
|
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
|
||||||
|
lib->credmgr->add_set(lib->credmgr, &this->pins->set);
|
||||||
|
|
||||||
manage_commands(this, TRUE);
|
manage_commands(this, TRUE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user