Skip to content

Commit

Permalink
Use a cached version of the URI to refresh objects
Browse files Browse the repository at this point in the history
This allows us to retain better information about the object
and critically things like a PIN passed in the URI to be able
to login to the token after a fork when the PIN is not specified in the
token configuration.

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Nov 30, 2023
1 parent b4728fa commit 02e1cdb
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 3 deletions.
87 changes: 84 additions & 3 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct p11prov_obj {
CK_BBOOL cka_copyable;
CK_BBOOL cka_token;

P11PROV_URI *refresh_uri;

union {
struct p11prov_key key;
struct p11prov_crt crt;
Expand Down Expand Up @@ -999,6 +1001,9 @@ CK_RV p11prov_obj_find(P11PROV_CTX *provctx, P11PROV_SESSION *session,
/* unknown object or other recoverable error to ignore */
continue;
} else if (ret == CKR_OK) {
/* keep a copy of the URI for refreshes as it may contain
* things like a PIN necessary to log in */
obj->refresh_uri = p11prov_copy_uri(uri);
ret = cb(cb_ctx, obj);
}
if (ret != CKR_OK) {
Expand Down Expand Up @@ -1084,13 +1089,86 @@ static P11PROV_OBJ *find_associated_obj(P11PROV_CTX *provctx, P11PROV_OBJ *obj,

static void p11prov_obj_refresh(P11PROV_OBJ *obj)
{
int login_behavior;
bool login = false;
CK_SLOT_ID slotid = CK_UNAVAILABLE_INFORMATION;
P11PROV_SESSION *session = NULL;
CK_SESSION_HANDLE sess = CK_INVALID_HANDLE;
CK_ATTRIBUTE template[3] = { 0 };
CK_ATTRIBUTE *attr;
int anum;
CK_OBJECT_HANDLE handle;
CK_ULONG objcount = 0;
P11PROV_OBJ *tmp = NULL;
tmp = find_associated_obj(obj->ctx, obj, obj->class);
if (!tmp) {
/* nothing we can do, invalid handle it is */
CK_RV ret;

P11PROV_debug("Refresh object %p", obj);

if (obj->class == CKO_PRIVATE_KEY) {
login = true;
}
login_behavior = p11prov_ctx_login_behavior(obj->ctx);
if (login_behavior == PUBKEY_LOGIN_ALWAYS) {
login = true;
}

slotid = p11prov_obj_get_slotid(obj);

ret = p11prov_get_session(obj->ctx, &slotid, NULL, obj->refresh_uri,
CK_UNAVAILABLE_INFORMATION, NULL, NULL, login,
false, &session);

if (ret != CKR_OK) {
P11PROV_debug("Failed to get session to refresh object %p", obj);
return;
}

sess = p11prov_session_handle(session);

anum = 0;
CKATTR_ASSIGN(template[anum], CKA_CLASS, &(obj->class), sizeof(obj->class));
anum++;
/* use CKA_ID if available */
attr = p11prov_obj_get_attr(obj, CKA_ID);
if (attr) {
template[anum] = *attr;
anum++;
}
/* use Label if available */
attr = p11prov_obj_get_attr(obj, CKA_LABEL);
if (attr) {
template[anum] = *attr;
anum++;
}

ret = p11prov_FindObjectsInit(obj->ctx, sess, template, anum);
if (ret != CKR_OK) {
goto done;
}

/* we expect a single entry */
ret = p11prov_FindObjects(obj->ctx, sess, &handle, 1, &objcount);

/* Finalizing is not fatal so ignore result */
p11prov_FindObjectsFinal(obj->ctx, sess);

if (ret != CKR_OK) {
P11PROV_debug("Failed to find refresh object %p", obj);
goto done;
}
if (objcount != 1) {
P11PROV_raise(obj->ctx, ret,
"Too many objects found on refresh (count=%ld)",
objcount);
goto done;
}

ret = p11prov_obj_from_handle(obj->ctx, session, handle, &tmp);
if (ret != CKR_OK) {
P11PROV_raise(obj->ctx, ret, "Failed to get object from handle");
goto done;
}

/* move over all the object data, then free the tmp */
obj->handle = tmp->handle;
obj->cached = tmp->cached;
Expand All @@ -1112,6 +1190,9 @@ static void p11prov_obj_refresh(P11PROV_OBJ *obj)
* cause use-after-free issues */
p11prov_obj_free(tmp);
obj->raf = false;

done:
p11prov_return_session(session);
}

#define SECRET_KEY_ATTRS 2
Expand Down
75 changes: 75 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,15 @@ static int get_pin_file(P11PROV_CTX *ctx, const char *str, size_t len,
return ret;
}

#define COPY_STRUCT_MEMBER(dst, src, _name) \
if ((src)->_name) { \
(dst)->_name = strdup((src)->_name); \
if (!(dst)->_name) { \
p11prov_uri_free((dst)); \
return NULL; \
} \
}

static void p11prov_uri_free_int(P11PROV_URI *uri)
{
OPENSSL_free(uri->library_manufacturer);
Expand Down Expand Up @@ -795,16 +804,33 @@ CK_OBJECT_CLASS p11prov_uri_get_class(P11PROV_URI *uri)
return uri->type;
}

void p11prov_uri_set_class(P11PROV_URI *uri, CK_OBJECT_CLASS class)
{
uri->type = class;
}

CK_ATTRIBUTE p11prov_uri_get_id(P11PROV_URI *uri)
{
return uri->id;
}

void p11prov_uri_set_id(P11PROV_URI *uri, CK_ATTRIBUTE *id)
{
OPENSSL_free(uri->id.pValue);
p11prov_copy_attr(&uri->id, id);
}

CK_ATTRIBUTE p11prov_uri_get_label(P11PROV_URI *uri)
{
return uri->object;
}

void p11prov_uri_set_label(P11PROV_URI *uri, CK_ATTRIBUTE *label)
{
OPENSSL_free(uri->object.pValue);
p11prov_copy_attr(&uri->object, label);
}

char *p11prov_uri_get_serial(P11PROV_URI *uri)
{
return uri->serial;
Expand All @@ -815,6 +841,55 @@ char *p11prov_uri_get_pin(P11PROV_URI *uri)
return uri->pin;
}

CK_SLOT_ID p11prov_uri_get_slot_id(P11PROV_URI *uri)
{
return uri->slot_id;
}

void p11prov_uri_set_slot_id(P11PROV_URI *uri, CK_SLOT_ID slot_id)
{
uri->slot_id = slot_id;
}

P11PROV_URI *p11prov_copy_uri(P11PROV_URI *uri)
{
P11PROV_URI *cu;
CK_RV rv;

cu = OPENSSL_zalloc(sizeof(P11PROV_URI));
if (!cu) {
return NULL;
}

COPY_STRUCT_MEMBER(cu, uri, library_manufacturer)
COPY_STRUCT_MEMBER(cu, uri, library_description)
COPY_STRUCT_MEMBER(cu, uri, token)
COPY_STRUCT_MEMBER(cu, uri, manufacturer)
COPY_STRUCT_MEMBER(cu, uri, model)
COPY_STRUCT_MEMBER(cu, uri, serial)
COPY_STRUCT_MEMBER(cu, uri, slot_description)
COPY_STRUCT_MEMBER(cu, uri, slot_manufacturer)
COPY_STRUCT_MEMBER(cu, uri, pin)

rv = p11prov_copy_attr(&cu->id, &uri->id);
if (rv != CKR_OK) {
p11prov_uri_free(cu);
return NULL;
}

rv = p11prov_copy_attr(&cu->object, &uri->object);
if (rv != CKR_OK) {
p11prov_uri_free(cu);
return NULL;
}

cu->library_version = uri->library_version;
cu->slot_id = uri->slot_id;
cu->type = uri->type;

return cu;
}

CK_RV p11prov_uri_match_token(P11PROV_URI *uri, CK_SLOT_ID slot_id,
CK_SLOT_INFO *slot, CK_TOKEN_INFO *token)
{
Expand Down
6 changes: 6 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,16 @@ P11PROV_URI *p11prov_parse_uri(P11PROV_CTX *ctx, const char *uri);
char *p11prov_key_to_uri(P11PROV_CTX *ctx, P11PROV_OBJ *key);
void p11prov_uri_free(P11PROV_URI *parsed_uri);
CK_OBJECT_CLASS p11prov_uri_get_class(P11PROV_URI *uri);
void p11prov_uri_set_class(P11PROV_URI *uri, CK_OBJECT_CLASS class);
CK_ATTRIBUTE p11prov_uri_get_id(P11PROV_URI *uri);
void p11prov_uri_set_id(P11PROV_URI *uri, CK_ATTRIBUTE *id);
CK_ATTRIBUTE p11prov_uri_get_label(P11PROV_URI *uri);
void p11prov_uri_set_label(P11PROV_URI *uri, CK_ATTRIBUTE *label);
char *p11prov_uri_get_serial(P11PROV_URI *uri);
char *p11prov_uri_get_pin(P11PROV_URI *uri);
CK_SLOT_ID p11prov_uri_get_slot_id(P11PROV_URI *uri);
void p11prov_uri_set_slot_id(P11PROV_URI *uri, CK_SLOT_ID slot_id);
P11PROV_URI *p11prov_copy_uri(P11PROV_URI *uri);
CK_RV p11prov_uri_match_token(P11PROV_URI *uri, CK_SLOT_ID slot_id,
CK_SLOT_INFO *slot, CK_TOKEN_INFO *token);
int p11prov_get_pin(P11PROV_CTX *ctx, const char *in, char **out);
Expand Down

0 comments on commit 02e1cdb

Please sign in to comment.