diff options
-rw-r--r-- | krl.c | 7 | ||||
-rw-r--r-- | monitor.c | 4 | ||||
-rw-r--r-- | monitor_wrap.c | 4 | ||||
-rw-r--r-- | monitor_wrap.h | 5 | ||||
-rw-r--r-- | sk-usbhid.c | 38 | ||||
-rw-r--r-- | ssh-agent.c | 5 | ||||
-rw-r--r-- | ssh-keygen.1 | 22 | ||||
-rw-r--r-- | ssh-keygen.c | 55 | ||||
-rw-r--r-- | ssh-keysign.c | 4 | ||||
-rw-r--r-- | ssh_api.c | 10 | ||||
-rw-r--r-- | sshconnect2.c | 37 | ||||
-rw-r--r-- | sshd.c | 8 | ||||
-rw-r--r-- | sshkey.c | 20 | ||||
-rw-r--r-- | sshkey.h | 11 | ||||
-rw-r--r-- | sshsig.c | 16 | ||||
-rw-r--r-- | sshsig.h | 8 |
16 files changed, 164 insertions, 90 deletions
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* $OpenBSD: krl.c,v 1.50 2020/04/03 05:48:57 djm Exp $ */ | 17 | /* $OpenBSD: krl.c,v 1.51 2020/08/27 01:06:18 djm Exp $ */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | 20 | ||
@@ -812,9 +812,10 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, | |||
812 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 || | 812 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 || |
813 | (r = sshkey_puts(sign_keys[i], buf)) != 0) | 813 | (r = sshkey_puts(sign_keys[i], buf)) != 0) |
814 | goto out; | 814 | goto out; |
815 | 815 | /* XXX support sk-* keys */ | |
816 | if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, | 816 | if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, |
817 | sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL, 0)) != 0) | 817 | sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL, |
818 | NULL, 0)) != 0) | ||
818 | goto out; | 819 | goto out; |
819 | KRL_DBG(("%s: signature sig len %zu", __func__, slen)); | 820 | KRL_DBG(("%s: signature sig len %zu", __func__, slen)); |
820 | if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) | 821 | if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.212 2020/07/07 02:47:21 deraadt Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.213 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -679,7 +679,7 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) | |||
679 | 679 | ||
680 | if ((key = get_hostkey_by_index(keyid)) != NULL) { | 680 | if ((key = get_hostkey_by_index(keyid)) != NULL) { |
681 | if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, | 681 | if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, |
682 | options.sk_provider, compat)) != 0) | 682 | options.sk_provider, NULL, compat)) != 0) |
683 | fatal("%s: sshkey_sign failed: %s", | 683 | fatal("%s: sshkey_sign failed: %s", |
684 | __func__, ssh_err(r)); | 684 | __func__, ssh_err(r)); |
685 | } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && | 685 | } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && |
diff --git a/monitor_wrap.c b/monitor_wrap.c index 001a8fa1c..5e38d83eb 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.117 2019/12/15 18:57:30 djm Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.118 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -216,7 +216,7 @@ mm_choose_dh(int min, int nbits, int max) | |||
216 | int | 216 | int |
217 | mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, | 217 | mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, |
218 | const u_char *data, size_t datalen, const char *hostkey_alg, | 218 | const u_char *data, size_t datalen, const char *hostkey_alg, |
219 | const char *sk_provider, u_int compat) | 219 | const char *sk_provider, const char *sk_pin, u_int compat) |
220 | { | 220 | { |
221 | struct kex *kex = *pmonitor->m_pkex; | 221 | struct kex *kex = *pmonitor->m_pkex; |
222 | struct sshbuf *m; | 222 | struct sshbuf *m; |
diff --git a/monitor_wrap.h b/monitor_wrap.h index 23ab096aa..0db38c206 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.h,v 1.44 2019/11/25 00:51:37 djm Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.h,v 1.45 2020/08/27 01:06:18 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 4 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
@@ -46,7 +46,8 @@ int mm_is_monitor(void); | |||
46 | DH *mm_choose_dh(int, int, int); | 46 | DH *mm_choose_dh(int, int, int); |
47 | #endif | 47 | #endif |
48 | int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, | 48 | int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, |
49 | const u_char *, size_t, const char *, const char *, u_int compat); | 49 | const u_char *, size_t, const char *, const char *, |
50 | const char *, u_int compat); | ||
50 | void mm_inform_authserv(char *, char *); | 51 | void mm_inform_authserv(char *, char *); |
51 | struct passwd *mm_getpwnamallow(struct ssh *, const char *); | 52 | struct passwd *mm_getpwnamallow(struct ssh *, const char *); |
52 | char *mm_auth2_read_banner(void); | 53 | char *mm_auth2_read_banner(void); |
diff --git a/sk-usbhid.c b/sk-usbhid.c index 2a573caa2..1dd834883 100644 --- a/sk-usbhid.c +++ b/sk-usbhid.c | |||
@@ -163,7 +163,8 @@ pick_first_device(void) | |||
163 | /* Check if the specified key handle exists on a given device. */ | 163 | /* Check if the specified key handle exists on a given device. */ |
164 | static int | 164 | static int |
165 | try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, | 165 | try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, |
166 | const char *application, const uint8_t *key_handle, size_t key_handle_len) | 166 | const char *application, const uint8_t *key_handle, size_t key_handle_len, |
167 | uint8_t flags, const char *pin) | ||
167 | { | 168 | { |
168 | fido_assert_t *assert = NULL; | 169 | fido_assert_t *assert = NULL; |
169 | int r = FIDO_ERR_INTERNAL; | 170 | int r = FIDO_ERR_INTERNAL; |
@@ -191,7 +192,7 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, | |||
191 | skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); | 192 | skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); |
192 | goto out; | 193 | goto out; |
193 | } | 194 | } |
194 | r = fido_dev_get_assert(dev, assert, NULL); | 195 | r = fido_dev_get_assert(dev, assert, pin); |
195 | skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); | 196 | skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
196 | if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { | 197 | if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { |
197 | /* U2F tokens may return this */ | 198 | /* U2F tokens may return this */ |
@@ -206,7 +207,8 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, | |||
206 | /* Iterate over configured devices looking for a specific key handle */ | 207 | /* Iterate over configured devices looking for a specific key handle */ |
207 | static fido_dev_t * | 208 | static fido_dev_t * |
208 | find_device(const char *path, const uint8_t *message, size_t message_len, | 209 | find_device(const char *path, const uint8_t *message, size_t message_len, |
209 | const char *application, const uint8_t *key_handle, size_t key_handle_len) | 210 | const char *application, const uint8_t *key_handle, size_t key_handle_len, |
211 | uint8_t flags, const char *pin) | ||
210 | { | 212 | { |
211 | fido_dev_info_t *devlist = NULL; | 213 | fido_dev_info_t *devlist = NULL; |
212 | fido_dev_t *dev = NULL; | 214 | fido_dev_t *dev = NULL; |
@@ -260,7 +262,7 @@ find_device(const char *path, const uint8_t *message, size_t message_len, | |||
260 | continue; | 262 | continue; |
261 | } | 263 | } |
262 | if (try_device(dev, message, message_len, application, | 264 | if (try_device(dev, message, message_len, application, |
263 | key_handle, key_handle_len) == 0) { | 265 | key_handle, key_handle_len, flags, pin) == 0) { |
264 | skdebug(__func__, "found key"); | 266 | skdebug(__func__, "found key"); |
265 | break; | 267 | break; |
266 | } | 268 | } |
@@ -570,19 +572,23 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, | |||
570 | skdebug(__func__, "fido_dev_open: %s", fido_strerr(r)); | 572 | skdebug(__func__, "fido_dev_open: %s", fido_strerr(r)); |
571 | goto out; | 573 | goto out; |
572 | } | 574 | } |
573 | if ((flags & SSH_SK_RESIDENT_KEY) != 0) { | 575 | if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { |
574 | if (check_sk_extensions(dev, "credProtect", &credprot) < 0) { | 576 | if (check_sk_extensions(dev, "credProtect", &credprot) < 0) { |
575 | skdebug(__func__, "check_sk_extensions failed"); | 577 | skdebug(__func__, "check_sk_extensions failed"); |
576 | goto out; | 578 | goto out; |
577 | } | 579 | } |
578 | if (credprot == 0) { | 580 | if (credprot == 0) { |
579 | skdebug(__func__, "refusing to create unprotected " | 581 | skdebug(__func__, "refusing to create unprotected " |
580 | "resident key"); | 582 | "resident/verify-required key"); |
581 | ret = SSH_SK_ERR_UNSUPPORTED; | 583 | ret = SSH_SK_ERR_UNSUPPORTED; |
582 | goto out; | 584 | goto out; |
583 | } | 585 | } |
584 | if ((r = fido_cred_set_prot(cred, | 586 | if ((flags & SSH_SK_USER_VERIFICATION_REQD)) |
585 | FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID)) != FIDO_OK) { | 587 | credprot = FIDO_CRED_PROT_UV_REQUIRED; |
588 | else | ||
589 | credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; | ||
590 | |||
591 | if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { | ||
586 | skdebug(__func__, "fido_cred_set_prot: %s", | 592 | skdebug(__func__, "fido_cred_set_prot: %s", |
587 | fido_strerr(r)); | 593 | fido_strerr(r)); |
588 | ret = fidoerr_to_skerr(r); | 594 | ret = fidoerr_to_skerr(r); |
@@ -826,7 +832,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, | |||
826 | goto out; | 832 | goto out; |
827 | } | 833 | } |
828 | if ((dev = find_device(device, message, sizeof(message), | 834 | if ((dev = find_device(device, message, sizeof(message), |
829 | application, key_handle, key_handle_len)) == NULL) { | 835 | application, key_handle, key_handle_len, flags, pin)) == NULL) { |
830 | skdebug(__func__, "couldn't find device for key handle"); | 836 | skdebug(__func__, "couldn't find device for key handle"); |
831 | goto out; | 837 | goto out; |
832 | } | 838 | } |
@@ -855,8 +861,15 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, | |||
855 | skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); | 861 | skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); |
856 | goto out; | 862 | goto out; |
857 | } | 863 | } |
858 | if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) { | 864 | if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) && |
865 | (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) { | ||
866 | skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); | ||
867 | ret = FIDO_ERR_PIN_REQUIRED; | ||
868 | goto out; | ||
869 | } | ||
870 | if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { | ||
859 | skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); | 871 | skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
872 | ret = fidoerr_to_skerr(r); | ||
860 | goto out; | 873 | goto out; |
861 | } | 874 | } |
862 | if ((response = calloc(1, sizeof(*response))) == NULL) { | 875 | if ((response = calloc(1, sizeof(*response))) == NULL) { |
@@ -978,8 +991,9 @@ read_rks(const char *devpath, const char *pin, | |||
978 | continue; | 991 | continue; |
979 | } | 992 | } |
980 | skdebug(__func__, "Device %s RP \"%s\" slot %zu: " | 993 | skdebug(__func__, "Device %s RP \"%s\" slot %zu: " |
981 | "type %d", devpath, fido_credman_rp_id(rp, i), j, | 994 | "type %d flags 0x%02x prot 0x%02x", devpath, |
982 | fido_cred_type(cred)); | 995 | fido_credman_rp_id(rp, i), j, fido_cred_type(cred), |
996 | fido_cred_flags(cred), fido_cred_prot(cred)); | ||
983 | 997 | ||
984 | /* build response entry */ | 998 | /* build response entry */ |
985 | if ((srk = calloc(1, sizeof(*srk))) == NULL || | 999 | if ((srk = calloc(1, sizeof(*srk))) == NULL || |
diff --git a/ssh-agent.c b/ssh-agent.c index 5f7ac8b91..d24a63089 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.262 2020/07/05 23:59:45 djm Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.263 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -407,9 +407,10 @@ process_sign_request2(SocketEntry *e) | |||
407 | sshkey_type(id->key), fp); | 407 | sshkey_type(id->key), fp); |
408 | } | 408 | } |
409 | } | 409 | } |
410 | /* XXX support PIN required FIDO keys */ | ||
410 | if ((r = sshkey_sign(id->key, &signature, &slen, | 411 | if ((r = sshkey_sign(id->key, &signature, &slen, |
411 | data, dlen, agent_decode_alg(key, flags), | 412 | data, dlen, agent_decode_alg(key, flags), |
412 | id->sk_provider, compat)) != 0) { | 413 | id->sk_provider, NULL, compat)) != 0) { |
413 | error("%s: sshkey_sign: %s", __func__, ssh_err(r)); | 414 | error("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
414 | goto send; | 415 | goto send; |
415 | } | 416 | } |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 9198a511f..7e0558fe1 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.205 2020/07/15 07:50:46 solene Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.206 2020/08/27 01:06:18 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: July 15 2020 $ | 38 | .Dd $Mdocdate: August 27 2020 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -511,6 +511,12 @@ A username to be associated with a resident key, | |||
511 | overriding the empty default username. | 511 | overriding the empty default username. |
512 | Specifying a username may be useful when generating multiple resident keys | 512 | Specifying a username may be useful when generating multiple resident keys |
513 | for the same application name. | 513 | for the same application name. |
514 | .It Cm verify-required | ||
515 | Indicate that this private key should require user verification for | ||
516 | each signature. | ||
517 | Not all FIDO tokens support support this option. | ||
518 | Currently PIN authentication is the only supported verification method, | ||
519 | but other methods may be supported in the future. | ||
514 | .It Cm write-attestation Ns = Ns Ar path | 520 | .It Cm write-attestation Ns = Ns Ar path |
515 | May be used at key generation time to record the attestation certificate | 521 | May be used at key generation time to record the attestation certificate |
516 | returned from FIDO tokens during key generation. | 522 | returned from FIDO tokens during key generation. |
@@ -961,7 +967,7 @@ by | |||
961 | Allows X11 forwarding. | 967 | Allows X11 forwarding. |
962 | .Pp | 968 | .Pp |
963 | .It Ic no-touch-required | 969 | .It Ic no-touch-required |
964 | Do not require signatures made using this key require demonstration | 970 | Do not require signatures made using this key include demonstration |
965 | of user presence (e.g. by having the user touch the authenticator). | 971 | of user presence (e.g. by having the user touch the authenticator). |
966 | This option only makes sense for the FIDO authenticator algorithms | 972 | This option only makes sense for the FIDO authenticator algorithms |
967 | .Cm ecdsa-sk | 973 | .Cm ecdsa-sk |
@@ -974,6 +980,16 @@ The | |||
974 | .Ar address_list | 980 | .Ar address_list |
975 | is a comma-separated list of one or more address/netmask pairs in CIDR | 981 | is a comma-separated list of one or more address/netmask pairs in CIDR |
976 | format. | 982 | format. |
983 | .Pp | ||
984 | .It Ic verify-required | ||
985 | Require signatures made using this key indicate that the user was first | ||
986 | verified. | ||
987 | This option only makes sense for the FIDO authenticator algorithms | ||
988 | .Cm ecdsa-sk | ||
989 | and | ||
990 | .Cm ed25519-sk . | ||
991 | Currently PIN authentication is the only supported verification method, | ||
992 | but other methods may be supported in the future. | ||
977 | .El | 993 | .El |
978 | .Pp | 994 | .Pp |
979 | At present, no standard options are valid for host keys. | 995 | At present, no standard options are valid for host keys. |
diff --git a/ssh-keygen.c b/ssh-keygen.c index cc092368e..89ef9a143 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.415 2020/08/03 02:53:51 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.416 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -589,7 +589,7 @@ do_convert_private_ssh2(struct sshbuf *b) | |||
589 | 589 | ||
590 | /* try the key */ | 590 | /* try the key */ |
591 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), | 591 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), |
592 | NULL, NULL, 0) != 0 || | 592 | NULL, NULL, NULL, 0) != 0 || |
593 | sshkey_verify(key, sig, slen, data, sizeof(data), | 593 | sshkey_verify(key, sig, slen, data, sizeof(data), |
594 | NULL, 0, NULL) != 0) { | 594 | NULL, 0, NULL) != 0) { |
595 | sshkey_free(key); | 595 | sshkey_free(key); |
@@ -1727,7 +1727,8 @@ load_pkcs11_key(char *path) | |||
1727 | static int | 1727 | static int |
1728 | agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, | 1728 | agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, |
1729 | const u_char *data, size_t datalen, | 1729 | const u_char *data, size_t datalen, |
1730 | const char *alg, const char *provider, u_int compat, void *ctx) | 1730 | const char *alg, const char *provider, const char *pin, |
1731 | u_int compat, void *ctx) | ||
1731 | { | 1732 | { |
1732 | int *agent_fdp = (int *)ctx; | 1733 | int *agent_fdp = (int *)ctx; |
1733 | 1734 | ||
@@ -1744,7 +1745,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1744 | u_int n; | 1745 | u_int n; |
1745 | struct sshkey *ca, *public; | 1746 | struct sshkey *ca, *public; |
1746 | char valid[64], *otmp, *tmp, *cp, *out, *comment; | 1747 | char valid[64], *otmp, *tmp, *cp, *out, *comment; |
1747 | char *ca_fp = NULL, **plist = NULL; | 1748 | char *ca_fp = NULL, **plist = NULL, *pin = NULL; |
1748 | struct ssh_identitylist *agent_ids; | 1749 | struct ssh_identitylist *agent_ids; |
1749 | size_t j; | 1750 | size_t j; |
1750 | struct notifier_ctx *notifier = NULL; | 1751 | struct notifier_ctx *notifier = NULL; |
@@ -1785,6 +1786,12 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1785 | } else { | 1786 | } else { |
1786 | /* CA key is assumed to be a private key on the filesystem */ | 1787 | /* CA key is assumed to be a private key on the filesystem */ |
1787 | ca = load_identity(tmp, NULL); | 1788 | ca = load_identity(tmp, NULL); |
1789 | if (sshkey_is_sk(ca) && | ||
1790 | (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { | ||
1791 | if ((pin = read_passphrase("Enter PIN for CA key: ", | ||
1792 | RP_ALLOW_STDIN)) == NULL) | ||
1793 | fatal("%s: couldn't read PIN", __func__); | ||
1794 | } | ||
1788 | } | 1795 | } |
1789 | free(tmp); | 1796 | free(tmp); |
1790 | 1797 | ||
@@ -1844,7 +1851,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1844 | 1851 | ||
1845 | if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { | 1852 | if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { |
1846 | if ((r = sshkey_certify_custom(public, ca, | 1853 | if ((r = sshkey_certify_custom(public, ca, |
1847 | key_type_name, sk_provider, agent_signer, | 1854 | key_type_name, sk_provider, NULL, agent_signer, |
1848 | &agent_fd)) != 0) | 1855 | &agent_fd)) != 0) |
1849 | fatal("Couldn't certify key %s via agent: %s", | 1856 | fatal("Couldn't certify key %s via agent: %s", |
1850 | tmp, ssh_err(r)); | 1857 | tmp, ssh_err(r)); |
@@ -1856,7 +1863,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1856 | sshkey_type(ca), ca_fp); | 1863 | sshkey_type(ca), ca_fp); |
1857 | } | 1864 | } |
1858 | r = sshkey_certify(public, ca, key_type_name, | 1865 | r = sshkey_certify(public, ca, key_type_name, |
1859 | sk_provider); | 1866 | sk_provider, pin); |
1860 | notify_complete(notifier); | 1867 | notify_complete(notifier); |
1861 | if (r != 0) | 1868 | if (r != 0) |
1862 | fatal("Couldn't certify key %s: %s", | 1869 | fatal("Couldn't certify key %s: %s", |
@@ -1890,6 +1897,8 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1890 | if (cert_serial_autoinc) | 1897 | if (cert_serial_autoinc) |
1891 | cert_serial++; | 1898 | cert_serial++; |
1892 | } | 1899 | } |
1900 | if (pin != NULL) | ||
1901 | freezero(pin, strlen(pin)); | ||
1893 | free(ca_fp); | 1902 | free(ca_fp); |
1894 | #ifdef ENABLE_PKCS11 | 1903 | #ifdef ENABLE_PKCS11 |
1895 | pkcs11_terminate(); | 1904 | pkcs11_terminate(); |
@@ -2526,6 +2535,7 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2526 | struct sshbuf *sigbuf = NULL, *abuf = NULL; | 2535 | struct sshbuf *sigbuf = NULL, *abuf = NULL; |
2527 | int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; | 2536 | int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; |
2528 | char *wfile = NULL, *asig = NULL, *fp = NULL; | 2537 | char *wfile = NULL, *asig = NULL, *fp = NULL; |
2538 | char *pin = NULL, *prompt = NULL; | ||
2529 | 2539 | ||
2530 | if (!quiet) { | 2540 | if (!quiet) { |
2531 | if (fd == STDIN_FILENO) | 2541 | if (fd == STDIN_FILENO) |
@@ -2533,17 +2543,25 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2533 | else | 2543 | else |
2534 | fprintf(stderr, "Signing file %s\n", filename); | 2544 | fprintf(stderr, "Signing file %s\n", filename); |
2535 | } | 2545 | } |
2536 | if (signer == NULL && sshkey_is_sk(signkey) && | 2546 | if (signer == NULL && sshkey_is_sk(signkey)) { |
2537 | (signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | 2547 | if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { |
2538 | if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, | 2548 | xasprintf(&prompt, "Enter PIN for %s key: ", |
2539 | SSH_FP_DEFAULT)) == NULL) | 2549 | sshkey_type(signkey)); |
2540 | fatal("%s: sshkey_fingerprint failed", __func__); | 2550 | if ((pin = read_passphrase(prompt, |
2541 | fprintf(stderr, "Confirm user presence for key %s %s\n", | 2551 | RP_ALLOW_STDIN)) == NULL) |
2542 | sshkey_type(signkey), fp); | 2552 | fatal("%s: couldn't read PIN", __func__); |
2543 | free(fp); | 2553 | } |
2554 | if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | ||
2555 | if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, | ||
2556 | SSH_FP_DEFAULT)) == NULL) | ||
2557 | fatal("%s: fingerprint failed", __func__); | ||
2558 | fprintf(stderr, "Confirm user presence for key %s %s\n", | ||
2559 | sshkey_type(signkey), fp); | ||
2560 | free(fp); | ||
2561 | } | ||
2544 | } | 2562 | } |
2545 | if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, fd, sig_namespace, | 2563 | if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, pin, |
2546 | &sigbuf, signer, signer_ctx)) != 0) { | 2564 | fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { |
2547 | error("Signing %s failed: %s", filename, ssh_err(r)); | 2565 | error("Signing %s failed: %s", filename, ssh_err(r)); |
2548 | goto out; | 2566 | goto out; |
2549 | } | 2567 | } |
@@ -2591,7 +2609,10 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2591 | r = 0; | 2609 | r = 0; |
2592 | out: | 2610 | out: |
2593 | free(wfile); | 2611 | free(wfile); |
2612 | free(prompt); | ||
2594 | free(asig); | 2613 | free(asig); |
2614 | if (pin != NULL) | ||
2615 | freezero(pin, strlen(pin)); | ||
2595 | sshbuf_free(abuf); | 2616 | sshbuf_free(abuf); |
2596 | sshbuf_free(sigbuf); | 2617 | sshbuf_free(sigbuf); |
2597 | if (wfd != -1) | 2618 | if (wfd != -1) |
@@ -3554,6 +3575,8 @@ main(int argc, char **argv) | |||
3554 | for (i = 0; i < nopts; i++) { | 3575 | for (i = 0; i < nopts; i++) { |
3555 | if (strcasecmp(opts[i], "no-touch-required") == 0) { | 3576 | if (strcasecmp(opts[i], "no-touch-required") == 0) { |
3556 | sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; | 3577 | sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; |
3578 | } else if (strcasecmp(opts[i], "verify-required") == 0) { | ||
3579 | sk_flags |= SSH_SK_USER_VERIFICATION_REQD; | ||
3557 | } else if (strcasecmp(opts[i], "resident") == 0) { | 3580 | } else if (strcasecmp(opts[i], "resident") == 0) { |
3558 | sk_flags |= SSH_SK_RESIDENT_KEY; | 3581 | sk_flags |= SSH_SK_RESIDENT_KEY; |
3559 | } else if (strncasecmp(opts[i], "device=", 7) == 0) { | 3582 | } else if (strncasecmp(opts[i], "device=", 7) == 0) { |
diff --git a/ssh-keysign.c b/ssh-keysign.c index 3e3ea3e14..7991e0f01 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keysign.c,v 1.63 2019/11/18 16:10:05 naddy Exp $ */ | 1 | /* $OpenBSD: ssh-keysign.c,v 1.64 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -278,7 +278,7 @@ main(int argc, char **argv) | |||
278 | } | 278 | } |
279 | 279 | ||
280 | if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, | 280 | if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, |
281 | NULL, NULL, 0)) != 0) | 281 | NULL, NULL, NULL, 0)) != 0) |
282 | fatal("sshkey_sign failed: %s", ssh_err(r)); | 282 | fatal("sshkey_sign failed: %s", ssh_err(r)); |
283 | free(data); | 283 | free(data); |
284 | 284 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh_api.c,v 1.20 2020/07/01 16:28:31 markus Exp $ */ | 1 | /* $OpenBSD: ssh_api.c,v 1.21 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -54,7 +54,7 @@ int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *, | |||
54 | */ | 54 | */ |
55 | int use_privsep = 0; | 55 | int use_privsep = 0; |
56 | int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, | 56 | int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, |
57 | const u_char *, u_int, const char *, const char *, u_int); | 57 | const u_char *, u_int, const char *, const char *, const char *, u_int); |
58 | 58 | ||
59 | #ifdef WITH_OPENSSL | 59 | #ifdef WITH_OPENSSL |
60 | DH *mm_choose_dh(int, int, int); | 60 | DH *mm_choose_dh(int, int, int); |
@@ -66,8 +66,8 @@ u_int session_id2_len = 0; | |||
66 | 66 | ||
67 | int | 67 | int |
68 | mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, | 68 | mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, |
69 | const u_char *data, u_int datalen, const char *alg, const char *sk_provider, | 69 | const u_char *data, u_int datalen, const char *alg, |
70 | u_int compat) | 70 | const char *sk_provider, const char *sk_pin, u_int compat) |
71 | { | 71 | { |
72 | return (-1); | 72 | return (-1); |
73 | } | 73 | } |
@@ -567,5 +567,5 @@ _ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey, | |||
567 | const u_char *data, size_t dlen, const char *alg) | 567 | const u_char *data, size_t dlen, const char *alg) |
568 | { | 568 | { |
569 | return sshkey_sign(privkey, signature, slen, data, dlen, | 569 | return sshkey_sign(privkey, signature, slen, data, dlen, |
570 | alg, NULL, ssh->compat); | 570 | alg, NULL, NULL, ssh->compat); |
571 | } | 571 | } |
diff --git a/sshconnect2.c b/sshconnect2.c index 74946da0d..347e348c6 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.324 2020/06/27 13:39:09 bket Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.325 2020/08/27 01:06:18 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -1175,7 +1175,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
1175 | struct sshkey *sign_key = NULL, *prv = NULL; | 1175 | struct sshkey *sign_key = NULL, *prv = NULL; |
1176 | int r = SSH_ERR_INTERNAL_ERROR; | 1176 | int r = SSH_ERR_INTERNAL_ERROR; |
1177 | struct notifier_ctx *notifier = NULL; | 1177 | struct notifier_ctx *notifier = NULL; |
1178 | char *fp = NULL; | 1178 | char *fp = NULL, *pin = NULL, *prompt = NULL; |
1179 | 1179 | ||
1180 | *sigp = NULL; | 1180 | *sigp = NULL; |
1181 | *lenp = 0; | 1181 | *lenp = 0; |
@@ -1204,20 +1204,28 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
1204 | goto out; | 1204 | goto out; |
1205 | } | 1205 | } |
1206 | sign_key = prv; | 1206 | sign_key = prv; |
1207 | if (sshkey_is_sk(sign_key) && | 1207 | if (sshkey_is_sk(sign_key)) { |
1208 | (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | 1208 | if ((sign_key->sk_flags & |
1209 | /* XXX match batch mode should just skip these keys? */ | 1209 | SSH_SK_USER_VERIFICATION_REQD)) { |
1210 | if ((fp = sshkey_fingerprint(sign_key, | 1210 | xasprintf(&prompt, "Enter PIN for %s key %s: ", |
1211 | options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) | 1211 | sshkey_type(sign_key), id->filename); |
1212 | fatal("%s: sshkey_fingerprint", __func__); | 1212 | pin = read_passphrase(prompt, 0); |
1213 | notifier = notify_start(options.batch_mode, | 1213 | } |
1214 | "Confirm user presence for key %s %s", | 1214 | if ((sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { |
1215 | sshkey_type(sign_key), fp); | 1215 | /* XXX should batch mode just skip these? */ |
1216 | free(fp); | 1216 | if ((fp = sshkey_fingerprint(sign_key, |
1217 | options.fingerprint_hash, | ||
1218 | SSH_FP_DEFAULT)) == NULL) | ||
1219 | fatal("%s: fingerprint", __func__); | ||
1220 | notifier = notify_start(options.batch_mode, | ||
1221 | "Confirm user presence for key %s %s", | ||
1222 | sshkey_type(sign_key), fp); | ||
1223 | free(fp); | ||
1224 | } | ||
1217 | } | 1225 | } |
1218 | } | 1226 | } |
1219 | if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, | 1227 | if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, |
1220 | alg, options.sk_provider, compat)) != 0) { | 1228 | alg, options.sk_provider, pin, compat)) != 0) { |
1221 | debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); | 1229 | debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
1222 | goto out; | 1230 | goto out; |
1223 | } | 1231 | } |
@@ -1232,6 +1240,9 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
1232 | /* success */ | 1240 | /* success */ |
1233 | r = 0; | 1241 | r = 0; |
1234 | out: | 1242 | out: |
1243 | free(prompt); | ||
1244 | if (pin != NULL) | ||
1245 | freezero(pin, strlen(pin)); | ||
1235 | notify_complete(notifier); | 1246 | notify_complete(notifier); |
1236 | sshkey_free(prv); | 1247 | sshkey_free(prv); |
1237 | return r; | 1248 | return r; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.560 2020/07/03 10:12:26 markus Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.561 2020/08/27 01:06:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -2338,19 +2338,19 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, | |||
2338 | if (use_privsep) { | 2338 | if (use_privsep) { |
2339 | if (privkey) { | 2339 | if (privkey) { |
2340 | if (mm_sshkey_sign(ssh, privkey, signature, slenp, | 2340 | if (mm_sshkey_sign(ssh, privkey, signature, slenp, |
2341 | data, dlen, alg, options.sk_provider, | 2341 | data, dlen, alg, options.sk_provider, NULL, |
2342 | ssh->compat) < 0) | 2342 | ssh->compat) < 0) |
2343 | fatal("%s: privkey sign failed", __func__); | 2343 | fatal("%s: privkey sign failed", __func__); |
2344 | } else { | 2344 | } else { |
2345 | if (mm_sshkey_sign(ssh, pubkey, signature, slenp, | 2345 | if (mm_sshkey_sign(ssh, pubkey, signature, slenp, |
2346 | data, dlen, alg, options.sk_provider, | 2346 | data, dlen, alg, options.sk_provider, NULL, |
2347 | ssh->compat) < 0) | 2347 | ssh->compat) < 0) |
2348 | fatal("%s: pubkey sign failed", __func__); | 2348 | fatal("%s: pubkey sign failed", __func__); |
2349 | } | 2349 | } |
2350 | } else { | 2350 | } else { |
2351 | if (privkey) { | 2351 | if (privkey) { |
2352 | if (sshkey_sign(privkey, signature, slenp, data, dlen, | 2352 | if (sshkey_sign(privkey, signature, slenp, data, dlen, |
2353 | alg, options.sk_provider, ssh->compat) < 0) | 2353 | alg, options.sk_provider, NULL, ssh->compat) < 0) |
2354 | fatal("%s: privkey sign failed", __func__); | 2354 | fatal("%s: privkey sign failed", __func__); |
2355 | } else { | 2355 | } else { |
2356 | if ((r = ssh_agent_sign(auth_sock, pubkey, | 2356 | if ((r = ssh_agent_sign(auth_sock, pubkey, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.110 2020/06/24 15:07:33 markus Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.111 2020/08/27 01:06:19 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -2727,7 +2727,7 @@ int | |||
2727 | sshkey_sign(struct sshkey *key, | 2727 | sshkey_sign(struct sshkey *key, |
2728 | u_char **sigp, size_t *lenp, | 2728 | u_char **sigp, size_t *lenp, |
2729 | const u_char *data, size_t datalen, | 2729 | const u_char *data, size_t datalen, |
2730 | const char *alg, const char *sk_provider, u_int compat) | 2730 | const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) |
2731 | { | 2731 | { |
2732 | int was_shielded = sshkey_is_shielded(key); | 2732 | int was_shielded = sshkey_is_shielded(key); |
2733 | int r2, r = SSH_ERR_INTERNAL_ERROR; | 2733 | int r2, r = SSH_ERR_INTERNAL_ERROR; |
@@ -2766,7 +2766,7 @@ sshkey_sign(struct sshkey *key, | |||
2766 | case KEY_ECDSA_SK_CERT: | 2766 | case KEY_ECDSA_SK_CERT: |
2767 | case KEY_ECDSA_SK: | 2767 | case KEY_ECDSA_SK: |
2768 | r = sshsk_sign(sk_provider, key, sigp, lenp, data, | 2768 | r = sshsk_sign(sk_provider, key, sigp, lenp, data, |
2769 | datalen, compat, /* XXX PIN */ NULL); | 2769 | datalen, compat, sk_pin); |
2770 | break; | 2770 | break; |
2771 | #ifdef WITH_XMSS | 2771 | #ifdef WITH_XMSS |
2772 | case KEY_XMSS: | 2772 | case KEY_XMSS: |
@@ -2888,7 +2888,8 @@ sshkey_drop_cert(struct sshkey *k) | |||
2888 | /* Sign a certified key, (re-)generating the signed certblob. */ | 2888 | /* Sign a certified key, (re-)generating the signed certblob. */ |
2889 | int | 2889 | int |
2890 | sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | 2890 | sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, |
2891 | const char *sk_provider, sshkey_certify_signer *signer, void *signer_ctx) | 2891 | const char *sk_provider, const char *sk_pin, |
2892 | sshkey_certify_signer *signer, void *signer_ctx) | ||
2892 | { | 2893 | { |
2893 | struct sshbuf *principals = NULL; | 2894 | struct sshbuf *principals = NULL; |
2894 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; | 2895 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; |
@@ -3026,7 +3027,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
3026 | 3027 | ||
3027 | /* Sign the whole mess */ | 3028 | /* Sign the whole mess */ |
3028 | if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), | 3029 | if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), |
3029 | sshbuf_len(cert), alg, sk_provider, 0, signer_ctx)) != 0) | 3030 | sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) |
3030 | goto out; | 3031 | goto out; |
3031 | /* Check and update signature_type against what was actually used */ | 3032 | /* Check and update signature_type against what was actually used */ |
3032 | if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) | 3033 | if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) |
@@ -3056,19 +3057,20 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
3056 | static int | 3057 | static int |
3057 | default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, | 3058 | default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, |
3058 | const u_char *data, size_t datalen, | 3059 | const u_char *data, size_t datalen, |
3059 | const char *alg, const char *sk_provider, u_int compat, void *ctx) | 3060 | const char *alg, const char *sk_provider, const char *sk_pin, |
3061 | u_int compat, void *ctx) | ||
3060 | { | 3062 | { |
3061 | if (ctx != NULL) | 3063 | if (ctx != NULL) |
3062 | return SSH_ERR_INVALID_ARGUMENT; | 3064 | return SSH_ERR_INVALID_ARGUMENT; |
3063 | return sshkey_sign(key, sigp, lenp, data, datalen, alg, | 3065 | return sshkey_sign(key, sigp, lenp, data, datalen, alg, |
3064 | sk_provider, compat); | 3066 | sk_provider, sk_pin, compat); |
3065 | } | 3067 | } |
3066 | 3068 | ||
3067 | int | 3069 | int |
3068 | sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg, | 3070 | sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg, |
3069 | const char *sk_provider) | 3071 | const char *sk_provider, const char *sk_pin) |
3070 | { | 3072 | { |
3071 | return sshkey_certify_custom(k, ca, alg, sk_provider, | 3073 | return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin, |
3072 | default_key_sign, NULL); | 3074 | default_key_sign, NULL); |
3073 | } | 3075 | } |
3074 | 3076 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.h,v 1.45 2020/04/08 00:08:46 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.h,v 1.46 2020/08/27 01:06:19 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -200,12 +200,13 @@ size_t sshkey_format_cert_validity(const struct sshkey_cert *, | |||
200 | int sshkey_check_cert_sigtype(const struct sshkey *, const char *); | 200 | int sshkey_check_cert_sigtype(const struct sshkey *, const char *); |
201 | 201 | ||
202 | int sshkey_certify(struct sshkey *, struct sshkey *, | 202 | int sshkey_certify(struct sshkey *, struct sshkey *, |
203 | const char *, const char *); | 203 | const char *, const char *, const char *); |
204 | /* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ | 204 | /* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ |
205 | typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *, | 205 | typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *, |
206 | const u_char *, size_t, const char *, const char *, u_int, void *); | 206 | const u_char *, size_t, const char *, const char *, const char *, |
207 | u_int, void *); | ||
207 | int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, | 208 | int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, |
208 | const char *, sshkey_certify_signer *, void *); | 209 | const char *, const char *, sshkey_certify_signer *, void *); |
209 | 210 | ||
210 | int sshkey_ecdsa_nid_from_name(const char *); | 211 | int sshkey_ecdsa_nid_from_name(const char *); |
211 | int sshkey_curve_name_to_nid(const char *); | 212 | int sshkey_curve_name_to_nid(const char *); |
@@ -234,7 +235,7 @@ int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); | |||
234 | int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); | 235 | int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); |
235 | 236 | ||
236 | int sshkey_sign(struct sshkey *, u_char **, size_t *, | 237 | int sshkey_sign(struct sshkey *, u_char **, size_t *, |
237 | const u_char *, size_t, const char *, const char *, u_int); | 238 | const u_char *, size_t, const char *, const char *, const char *, u_int); |
238 | int sshkey_verify(const struct sshkey *, const u_char *, size_t, | 239 | int sshkey_verify(const struct sshkey *, const u_char *, size_t, |
239 | const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); | 240 | const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); |
240 | int sshkey_check_sigtype(const u_char *, size_t, const char *); | 241 | int sshkey_check_sigtype(const u_char *, size_t, const char *); |
@@ -151,7 +151,7 @@ done: | |||
151 | 151 | ||
152 | static int | 152 | static int |
153 | sshsig_wrap_sign(struct sshkey *key, const char *hashalg, | 153 | sshsig_wrap_sign(struct sshkey *key, const char *hashalg, |
154 | const char *sk_provider, const struct sshbuf *h_message, | 154 | const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message, |
155 | const char *sig_namespace, struct sshbuf **out, | 155 | const char *sig_namespace, struct sshbuf **out, |
156 | sshsig_signer *signer, void *signer_ctx) | 156 | sshsig_signer *signer, void *signer_ctx) |
157 | { | 157 | { |
@@ -185,14 +185,14 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg, | |||
185 | if (signer != NULL) { | 185 | if (signer != NULL) { |
186 | if ((r = signer(key, &sig, &slen, | 186 | if ((r = signer(key, &sig, &slen, |
187 | sshbuf_ptr(tosign), sshbuf_len(tosign), | 187 | sshbuf_ptr(tosign), sshbuf_len(tosign), |
188 | sign_alg, sk_provider, 0, signer_ctx)) != 0) { | 188 | sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) { |
189 | error("Couldn't sign message: %s", ssh_err(r)); | 189 | error("Couldn't sign message: %s", ssh_err(r)); |
190 | goto done; | 190 | goto done; |
191 | } | 191 | } |
192 | } else { | 192 | } else { |
193 | if ((r = sshkey_sign(key, &sig, &slen, | 193 | if ((r = sshkey_sign(key, &sig, &slen, |
194 | sshbuf_ptr(tosign), sshbuf_len(tosign), | 194 | sshbuf_ptr(tosign), sshbuf_len(tosign), |
195 | sign_alg, sk_provider, 0)) != 0) { | 195 | sign_alg, sk_provider, sk_pin, 0)) != 0) { |
196 | error("Couldn't sign message: %s", ssh_err(r)); | 196 | error("Couldn't sign message: %s", ssh_err(r)); |
197 | goto done; | 197 | goto done; |
198 | } | 198 | } |
@@ -430,7 +430,8 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | int | 432 | int |
433 | sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider, | 433 | sshsig_signb(struct sshkey *key, const char *hashalg, |
434 | const char *sk_provider, const char *sk_pin, | ||
434 | const struct sshbuf *message, const char *sig_namespace, | 435 | const struct sshbuf *message, const char *sig_namespace, |
435 | struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) | 436 | struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) |
436 | { | 437 | { |
@@ -445,7 +446,7 @@ sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider, | |||
445 | error("%s: hash_buffer failed: %s", __func__, ssh_err(r)); | 446 | error("%s: hash_buffer failed: %s", __func__, ssh_err(r)); |
446 | goto out; | 447 | goto out; |
447 | } | 448 | } |
448 | if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b, | 449 | if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, |
449 | sig_namespace, out, signer, signer_ctx)) != 0) | 450 | sig_namespace, out, signer, signer_ctx)) != 0) |
450 | goto out; | 451 | goto out; |
451 | /* success */ | 452 | /* success */ |
@@ -558,7 +559,8 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) | |||
558 | } | 559 | } |
559 | 560 | ||
560 | int | 561 | int |
561 | sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider, | 562 | sshsig_sign_fd(struct sshkey *key, const char *hashalg, |
563 | const char *sk_provider, const char *sk_pin, | ||
562 | int fd, const char *sig_namespace, struct sshbuf **out, | 564 | int fd, const char *sig_namespace, struct sshbuf **out, |
563 | sshsig_signer *signer, void *signer_ctx) | 565 | sshsig_signer *signer, void *signer_ctx) |
564 | { | 566 | { |
@@ -573,7 +575,7 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider, | |||
573 | error("%s: hash_file failed: %s", __func__, ssh_err(r)); | 575 | error("%s: hash_file failed: %s", __func__, ssh_err(r)); |
574 | return r; | 576 | return r; |
575 | } | 577 | } |
576 | if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b, | 578 | if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, |
577 | sig_namespace, out, signer, signer_ctx)) != 0) | 579 | sig_namespace, out, signer, signer_ctx)) != 0) |
578 | goto out; | 580 | goto out; |
579 | /* success */ | 581 | /* success */ |
@@ -23,7 +23,8 @@ struct sshsigopt; | |||
23 | struct sshkey_sig_details; | 23 | struct sshkey_sig_details; |
24 | 24 | ||
25 | typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, | 25 | typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, |
26 | const u_char *, size_t, const char *, const char *, u_int, void *); | 26 | const u_char *, size_t, const char *, const char *, const char *, |
27 | u_int, void *); | ||
27 | 28 | ||
28 | /* Buffer-oriented API */ | 29 | /* Buffer-oriented API */ |
29 | 30 | ||
@@ -33,7 +34,7 @@ typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, | |||
33 | * out is populated with the detached signature, or NULL on failure. | 34 | * out is populated with the detached signature, or NULL on failure. |
34 | */ | 35 | */ |
35 | int sshsig_signb(struct sshkey *key, const char *hashalg, | 36 | int sshsig_signb(struct sshkey *key, const char *hashalg, |
36 | const char *sk_provider, const struct sshbuf *message, | 37 | const char *sk_provider, const char *sk_pin, const struct sshbuf *message, |
37 | const char *sig_namespace, struct sshbuf **out, | 38 | const char *sig_namespace, struct sshbuf **out, |
38 | sshsig_signer *signer, void *signer_ctx); | 39 | sshsig_signer *signer, void *signer_ctx); |
39 | 40 | ||
@@ -54,7 +55,8 @@ int sshsig_verifyb(struct sshbuf *signature, | |||
54 | * out is populated with the detached signature, or NULL on failure. | 55 | * out is populated with the detached signature, or NULL on failure. |
55 | */ | 56 | */ |
56 | int sshsig_sign_fd(struct sshkey *key, const char *hashalg, | 57 | int sshsig_sign_fd(struct sshkey *key, const char *hashalg, |
57 | const char *sk_provider, int fd, const char *sig_namespace, | 58 | const char *sk_provider, const char *sk_pin, |
59 | int fd, const char *sig_namespace, | ||
58 | struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); | 60 | struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); |
59 | 61 | ||
60 | /* | 62 | /* |