diff options
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r-- | ssh-pkcs11.c | 121 |
1 files changed, 95 insertions, 26 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 036ee8115..384ac1edb 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11.c,v 1.39 2019/01/21 02:05:38 djm Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11.c,v 1.40 2019/01/22 12:00:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2014 Pedro Martelletto. All rights reserved. | 4 | * Copyright (c) 2014 Pedro Martelletto. All rights reserved. |
@@ -240,6 +240,85 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, | |||
240 | } | 240 | } |
241 | 241 | ||
242 | static int | 242 | static int |
243 | pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) | ||
244 | { | ||
245 | struct pkcs11_slotinfo *si; | ||
246 | CK_FUNCTION_LIST *f; | ||
247 | char *pin = NULL, prompt[1024]; | ||
248 | CK_RV rv; | ||
249 | |||
250 | if (!k11->provider || !k11->provider->valid) { | ||
251 | error("no pkcs11 (valid) provider found"); | ||
252 | return (-1); | ||
253 | } | ||
254 | |||
255 | f = k11->provider->function_list; | ||
256 | si = &k11->provider->slotinfo[k11->slotidx]; | ||
257 | |||
258 | if (!pkcs11_interactive) { | ||
259 | error("need pin entry%s", | ||
260 | (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? | ||
261 | " on reader keypad" : ""); | ||
262 | return (-1); | ||
263 | } | ||
264 | if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) | ||
265 | verbose("Deferring PIN entry to reader keypad."); | ||
266 | else { | ||
267 | snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", | ||
268 | si->token.label); | ||
269 | if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { | ||
270 | debug("%s: no pin specified", __func__); | ||
271 | return (-1); /* bail out */ | ||
272 | } | ||
273 | } | ||
274 | rv = f->C_Login(si->session, type, (u_char *)pin, | ||
275 | (pin != NULL) ? strlen(pin) : 0); | ||
276 | if (pin != NULL) | ||
277 | freezero(pin, strlen(pin)); | ||
278 | if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { | ||
279 | error("C_Login failed: %lu", rv); | ||
280 | return (-1); | ||
281 | } | ||
282 | si->logged_in = 1; | ||
283 | return (0); | ||
284 | } | ||
285 | |||
286 | static int | ||
287 | pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, | ||
288 | CK_ATTRIBUTE_TYPE type, int *val) | ||
289 | { | ||
290 | struct pkcs11_slotinfo *si; | ||
291 | CK_FUNCTION_LIST *f; | ||
292 | CK_BBOOL flag = 0; | ||
293 | CK_ATTRIBUTE attr; | ||
294 | CK_RV rv; | ||
295 | |||
296 | *val = 0; | ||
297 | |||
298 | if (!k11->provider || !k11->provider->valid) { | ||
299 | error("no pkcs11 (valid) provider found"); | ||
300 | return (-1); | ||
301 | } | ||
302 | |||
303 | f = k11->provider->function_list; | ||
304 | si = &k11->provider->slotinfo[k11->slotidx]; | ||
305 | |||
306 | attr.type = type; | ||
307 | attr.pValue = &flag; | ||
308 | attr.ulValueLen = sizeof(flag); | ||
309 | |||
310 | rv = f->C_GetAttributeValue(si->session, obj, &attr, 1); | ||
311 | if (rv != CKR_OK) { | ||
312 | error("C_GetAttributeValue failed: %lu", rv); | ||
313 | return (-1); | ||
314 | } | ||
315 | *val = flag != 0; | ||
316 | debug("%s: provider %p slot %lu object %lu: attrib %lu = %d", | ||
317 | __func__, k11->provider, k11->slotidx, obj, type, *val); | ||
318 | return (0); | ||
319 | } | ||
320 | |||
321 | static int | ||
243 | pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) | 322 | pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) |
244 | { | 323 | { |
245 | struct pkcs11_slotinfo *si; | 324 | struct pkcs11_slotinfo *si; |
@@ -250,7 +329,8 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) | |||
250 | CK_BBOOL true_val; | 329 | CK_BBOOL true_val; |
251 | CK_MECHANISM mech; | 330 | CK_MECHANISM mech; |
252 | CK_ATTRIBUTE key_filter[3]; | 331 | CK_ATTRIBUTE key_filter[3]; |
253 | char *pin = NULL, prompt[1024]; | 332 | int always_auth = 0; |
333 | int did_login = 0; | ||
254 | 334 | ||
255 | if (!k11->provider || !k11->provider->valid) { | 335 | if (!k11->provider || !k11->provider->valid) { |
256 | error("no pkcs11 (valid) provider found"); | 336 | error("no pkcs11 (valid) provider found"); |
@@ -261,32 +341,11 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) | |||
261 | si = &k11->provider->slotinfo[k11->slotidx]; | 341 | si = &k11->provider->slotinfo[k11->slotidx]; |
262 | 342 | ||
263 | if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { | 343 | if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { |
264 | if (!pkcs11_interactive) { | 344 | if (pkcs11_login(k11, CKU_USER) < 0) { |
265 | error("need pin entry%s", (si->token.flags & | 345 | error("login failed"); |
266 | CKF_PROTECTED_AUTHENTICATION_PATH) ? | ||
267 | " on reader keypad" : ""); | ||
268 | return (-1); | ||
269 | } | ||
270 | if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) | ||
271 | verbose("Deferring PIN entry to reader keypad."); | ||
272 | else { | ||
273 | snprintf(prompt, sizeof(prompt), | ||
274 | "Enter PIN for '%s': ", si->token.label); | ||
275 | pin = read_passphrase(prompt, RP_ALLOW_EOF); | ||
276 | if (pin == NULL) | ||
277 | return (-1); /* bail out */ | ||
278 | } | ||
279 | rv = f->C_Login(si->session, CKU_USER, (u_char *)pin, | ||
280 | (pin != NULL) ? strlen(pin) : 0); | ||
281 | if (pin != NULL) { | ||
282 | explicit_bzero(pin, strlen(pin)); | ||
283 | free(pin); | ||
284 | } | ||
285 | if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { | ||
286 | error("C_Login failed: %lu", rv); | ||
287 | return (-1); | 346 | return (-1); |
288 | } | 347 | } |
289 | si->logged_in = 1; | 348 | did_login = 1; |
290 | } | 349 | } |
291 | 350 | ||
292 | memset(&key_filter, 0, sizeof(key_filter)); | 351 | memset(&key_filter, 0, sizeof(key_filter)); |
@@ -321,6 +380,16 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) | |||
321 | return (-1); | 380 | return (-1); |
322 | } | 381 | } |
323 | 382 | ||
383 | pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE, | ||
384 | &always_auth); /* ignore errors here */ | ||
385 | if (always_auth && !did_login) { | ||
386 | debug("%s: always-auth key", __func__); | ||
387 | if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) { | ||
388 | error("login failed for always-auth key"); | ||
389 | return (-1); | ||
390 | } | ||
391 | } | ||
392 | |||
324 | return (0); | 393 | return (0); |
325 | } | 394 | } |
326 | 395 | ||