version 1.35, 2021/02/26 00:16:58 |
version 1.36, 2021/10/28 02:54:18 |
|
|
free(rks); |
free(rks); |
} |
} |
|
|
|
static void |
|
sshsk_free_resident_key(struct sshsk_resident_key *srk) |
|
{ |
|
if (srk == NULL) |
|
return; |
|
sshkey_free(srk->key); |
|
freezero(srk->user_id, srk->user_id_len); |
|
free(srk); |
|
} |
|
|
|
|
|
void |
|
sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks) |
|
{ |
|
size_t i; |
|
|
|
if (srks == NULL || nsrks == 0) |
|
return; |
|
|
|
for (i = 0; i < nsrks; i++) |
|
sshsk_free_resident_key(srks[i]); |
|
free(srks); |
|
} |
|
|
int |
int |
sshsk_load_resident(const char *provider_path, const char *device, |
sshsk_load_resident(const char *provider_path, const char *device, |
const char *pin, struct sshkey ***keysp, size_t *nkeysp) |
const char *pin, u_int flags, struct sshsk_resident_key ***srksp, |
|
size_t *nsrksp) |
{ |
{ |
struct sshsk_provider *skp = NULL; |
struct sshsk_provider *skp = NULL; |
int r = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
struct sk_resident_key **rks = NULL; |
struct sk_resident_key **rks = NULL; |
size_t i, nrks = 0, nkeys = 0; |
size_t i, nrks = 0, nsrks = 0; |
struct sshkey *key = NULL, **keys = NULL, **tmp; |
struct sshkey *key = NULL; |
uint8_t flags; |
struct sshsk_resident_key *srk = NULL, **srks = NULL, **tmp; |
|
uint8_t sk_flags; |
struct sk_option **opts = NULL; |
struct sk_option **opts = NULL; |
|
|
debug_f("provider \"%s\"%s", provider_path, |
debug_f("provider \"%s\"%s", provider_path, |
(pin != NULL && *pin != '\0') ? ", have-pin": ""); |
(pin != NULL && *pin != '\0') ? ", have-pin": ""); |
|
|
if (keysp == NULL || nkeysp == NULL) |
if (srksp == NULL || nsrksp == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
*keysp = NULL; |
*srksp = NULL; |
*nkeysp = 0; |
*nsrksp = 0; |
|
|
if ((r = make_options(device, NULL, &opts)) != 0) |
if ((r = make_options(device, NULL, &opts)) != 0) |
goto out; |
goto out; |
|
|
goto out; |
goto out; |
} |
} |
for (i = 0; i < nrks; i++) { |
for (i = 0; i < nrks; i++) { |
debug3_f("rk %zu: slot = %zu, alg = %d, application = \"%s\"", |
debug3_f("rk %zu: slot %zu, alg %d, app \"%s\", uidlen %zu", |
i, rks[i]->slot, rks[i]->alg, rks[i]->application); |
i, rks[i]->slot, rks[i]->alg, rks[i]->application, |
|
rks[i]->user_id_len); |
/* XXX need better filter here */ |
/* XXX need better filter here */ |
if (strncmp(rks[i]->application, "ssh:", 4) != 0) |
if (strncmp(rks[i]->application, "ssh:", 4) != 0) |
continue; |
continue; |
|
|
default: |
default: |
continue; |
continue; |
} |
} |
flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY; |
sk_flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY; |
if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD)) |
if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD)) |
flags |= SSH_SK_USER_VERIFICATION_REQD; |
sk_flags |= SSH_SK_USER_VERIFICATION_REQD; |
if ((r = sshsk_key_from_response(rks[i]->alg, |
if ((r = sshsk_key_from_response(rks[i]->alg, |
rks[i]->application, flags, &rks[i]->key, &key)) != 0) |
rks[i]->application, sk_flags, &rks[i]->key, &key)) != 0) |
goto out; |
goto out; |
if ((tmp = recallocarray(keys, nkeys, nkeys + 1, |
if ((srk = calloc(1, sizeof(*srk))) == NULL) { |
|
error_f("calloc failed"); |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
srk->key = key; |
|
key = NULL; /* transferred */ |
|
if ((srk->user_id = calloc(1, rks[i]->user_id_len)) == NULL) { |
|
error_f("calloc failed"); |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
memcpy(srk->user_id, rks[i]->user_id, rks[i]->user_id_len); |
|
srk->user_id_len = rks[i]->user_id_len; |
|
if ((tmp = recallocarray(srks, nsrks, nsrks + 1, |
sizeof(*tmp))) == NULL) { |
sizeof(*tmp))) == NULL) { |
error_f("recallocarray failed"); |
error_f("recallocarray failed"); |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
keys = tmp; |
srks = tmp; |
keys[nkeys++] = key; |
srks[nsrks++] = srk; |
key = NULL; |
srk = NULL; |
/* XXX synthesise comment */ |
/* XXX synthesise comment */ |
} |
} |
/* success */ |
/* success */ |
*keysp = keys; |
*srksp = srks; |
*nkeysp = nkeys; |
*nsrksp = nsrks; |
keys = NULL; |
srks = NULL; |
nkeys = 0; |
nsrks = 0; |
r = 0; |
r = 0; |
out: |
out: |
sshsk_free_options(opts); |
sshsk_free_options(opts); |
sshsk_free(skp); |
sshsk_free(skp); |
sshsk_free_sk_resident_keys(rks, nrks); |
sshsk_free_sk_resident_keys(rks, nrks); |
sshkey_free(key); |
sshkey_free(key); |
if (nkeys != 0) { |
sshsk_free_resident_key(srk); |
for (i = 0; i < nkeys; i++) |
sshsk_free_resident_keys(srks, nsrks); |
sshkey_free(keys[i]); |
|
free(keys); |
|
} |
|
return r; |
return r; |
} |
} |
|
|