From 7ea845e48df6d34a333ebbe79380cba0938d02a5 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 12 Feb 2010 09:21:02 +1100 Subject: - markus@cvs.openbsd.org 2010/02/08 10:50:20 [pathnames.h readconf.c readconf.h scp.1 sftp.1 ssh-add.1 ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config.5] replace our obsolete smartcard code with PKCS#11. ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf ssh(1) and ssh-keygen(1) use dlopen(3) directly to talk to a PKCS#11 provider (shared library) while ssh-agent(1) delegates PKCS#11 to a forked a ssh-pkcs11-helper process. PKCS#11 is currently a compile time option. feedback and ok djm@; inspired by patches from Alon Bar-Lev ` --- ssh-pkcs11-client.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 ssh-pkcs11-client.c (limited to 'ssh-pkcs11-client.c') diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c new file mode 100644 index 000000000..6ffdd9364 --- /dev/null +++ b/ssh-pkcs11-client.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2010 Markus Friedl. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "pathnames.h" +#include "xmalloc.h" +#include "buffer.h" +#include "log.h" +#include "misc.h" +#include "key.h" +#include "authfd.h" +#include "atomicio.h" +#include "ssh-pkcs11.h" + +/* borrows code from sftp-server and ssh-agent */ + +int fd = -1; +pid_t pid = -1; + +static void +send_msg(Buffer *m) +{ + u_char buf[4]; + int mlen = buffer_len(m); + + put_u32(buf, mlen); + if (atomicio(vwrite, fd, buf, 4) != 4 || + atomicio(vwrite, fd, buffer_ptr(m), + buffer_len(m)) != buffer_len(m)) + error("write to helper failed"); + buffer_consume(m, mlen); +} + +static int +recv_msg(Buffer *m) +{ + u_int l, len; + u_char buf[1024]; + + if ((len = atomicio(read, fd, buf, 4)) != 4) { + error("read from helper failed: %u", len); + return (0); /* XXX */ + } + len = get_u32(buf); + if (len > 256 * 1024) + fatal("response too long: %u", len); + /* read len bytes into m */ + buffer_clear(m); + while (len > 0) { + l = len; + if (l > sizeof(buf)) + l = sizeof(buf); + if (atomicio(read, fd, buf, l) != l) { + error("response from helper failed."); + return (0); /* XXX */ + } + buffer_append(m, buf, l); + len -= l; + } + return (buffer_get_char(m)); +} + +int +pkcs11_init(int interactive) +{ + return (0); +} + +void +pkcs11_terminate(void) +{ + close(fd); +} + +static int +pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + int padding) +{ + Key key; + u_char *blob, *signature = NULL; + u_int blen, slen = 0; + int ret = -1; + Buffer msg; + + if (padding != RSA_PKCS1_PADDING) + return (-1); + key.type = KEY_RSA; + key.rsa = rsa; + if (key_to_blob(&key, &blob, &blen) == 0) + return -1; + buffer_init(&msg); + buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); + buffer_put_string(&msg, blob, blen); + buffer_put_string(&msg, from, flen); + buffer_put_int(&msg, 0); + xfree(blob); + send_msg(&msg); + + if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) { + signature = buffer_get_string(&msg, &slen); + if (slen <= (u_int)RSA_size(rsa)) { + memcpy(to, signature, slen); + ret = slen; + } + xfree(signature); + } + return (ret); +} + +/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ +static int +wrap_key(RSA *rsa) +{ + static RSA_METHOD helper_rsa; + + memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); + helper_rsa.name = "ssh-pkcs11-helper"; + helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; + RSA_set_method(rsa, &helper_rsa); + return (0); +} + +static int +pkcs11_start_helper(void) +{ + int pair[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { + error("socketpair: %s", strerror(errno)); + return (-1); + } + if ((pid = fork()) == -1) { + error("fork: %s", strerror(errno)); + return (-1); + } else if (pid == 0) { + if ((dup2(pair[1], STDIN_FILENO) == -1) || + (dup2(pair[1], STDOUT_FILENO) == -1)) { + fprintf(stderr, "dup2: %s\n", strerror(errno)); + _exit(1); + } + close(pair[0]); + close(pair[1]); + execlp(_PATH_SSH_PKCS11_HELPER, _PATH_SSH_PKCS11_HELPER, + (char *) 0); + fprintf(stderr, "exec: %s: %s\n", _PATH_SSH_PKCS11_HELPER, + strerror(errno)); + _exit(1); + } + close(pair[1]); + fd = pair[0]; + return (0); +} + +int +pkcs11_add_provider(char *name, char *pin, Key ***keysp) +{ + Key *k; + int i, nkeys; + u_char *blob; + u_int blen; + Buffer msg; + + if (fd < 0 && pkcs11_start_helper() < 0) + return (-1); + + buffer_init(&msg); + buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY); + buffer_put_cstring(&msg, name); + buffer_put_cstring(&msg, pin); + send_msg(&msg); + buffer_clear(&msg); + + if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) { + nkeys = buffer_get_int(&msg); + *keysp = xcalloc(nkeys, sizeof(Key *)); + for (i = 0; i < nkeys; i++) { + blob = buffer_get_string(&msg, &blen); + xfree(buffer_get_string(&msg, NULL)); + k = key_from_blob(blob, blen); + wrap_key(k->rsa); + (*keysp)[i] = k; + xfree(blob); + } + } else { + nkeys = -1; + } + buffer_free(&msg); + return (nkeys); +} + +int +pkcs11_del_provider(char *name) +{ + int ret = -1; + Buffer msg; + + buffer_init(&msg); + buffer_put_char(&msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY); + buffer_put_cstring(&msg, name); + buffer_put_cstring(&msg, ""); + send_msg(&msg); + buffer_clear(&msg); + + if (recv_msg(&msg) == SSH_AGENT_SUCCESS) + ret = 0; + buffer_free(&msg); + return (ret); +} -- cgit v1.2.3 From 8ad0fbd98e5ffd98c25f88881981336508ae90d7 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 12 Feb 2010 09:49:06 +1100 Subject: - (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] Make it compile on OSX --- ChangeLog | 2 ++ ssh-pkcs11-client.c | 6 +++++- ssh-pkcs11-helper.c | 9 +++++++-- ssh-pkcs11.c | 12 +++++++++--- 4 files changed, 23 insertions(+), 6 deletions(-) (limited to 'ssh-pkcs11-client.c') diff --git a/ChangeLog b/ChangeLog index ce4ef1343..f56dad3ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,8 @@ - (djm) [INSTALL Makefile.in README.smartcard configure.ac scard-opensc.c] [scard.c scard.h pkcs11.h scard/Makefile.in scard/Ssh.bin.uu scard/Ssh.java] Remove obsolete smartcard support + - (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] + Make it compile on OSX 20100210 - (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index 6ffdd9364..d376153fa 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -14,8 +14,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "includes.h" + #include -#include +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index f9962709b..464209641 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -14,9 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "includes.h" + #include -#include +#ifdef HAVE_SYS_TIME_H +# include +#endif + +#include "openbsd-compat/sys-queue.h" #include #include diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index f82454329..2f6c9cec8 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -14,14 +14,20 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "includes.h" + #include -#include +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include #include #include +#include "openbsd-compat/sys-queue.h" + #define CRYPTOKI_COMPAT #include "pkcs11.h" @@ -190,14 +196,14 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, CK_ULONG tlen = 0, nfound = 0; CK_RV rv; CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; - CK_BBOOL true = CK_TRUE; + CK_BBOOL true_val = CK_TRUE; CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; CK_ATTRIBUTE key_filter[] = { {CKA_CLASS, &private_key_class, sizeof(private_key_class) }, {CKA_ID, NULL, 0}, - {CKA_SIGN, &true, sizeof(true) } + {CKA_SIGN, &true_val, sizeof(true_val) } }; char *pin, prompt[1024]; int rval = -1; -- cgit v1.2.3 From dfa4156dbd4aa45464b2ea6b867bcaa483bed134 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 12 Feb 2010 10:06:28 +1100 Subject: - (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] Use ssh_get_progname to fill __progname --- ChangeLog | 2 ++ ssh-pkcs11-client.c | 4 ++++ ssh-pkcs11-helper.c | 15 +++++++++++++++ ssh-pkcs11.c | 4 ++++ 4 files changed, 25 insertions(+) (limited to 'ssh-pkcs11-client.c') diff --git a/ChangeLog b/ChangeLog index f56dad3ca..c5dc75262 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,8 @@ Remove obsolete smartcard support - (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] Make it compile on OSX + - (djm) [ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] + Use ssh_get_progname to fill __progname 20100210 - (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index d376153fa..37050e04d 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -16,6 +16,8 @@ #include "includes.h" +#ifdef ENABLE_PKCS11 + #include #ifdef HAVE_SYS_TIME_H # include @@ -231,3 +233,5 @@ pkcs11_del_provider(char *name) buffer_free(&msg); return (ret); } + +#endif /* ENABLE_PKCS11 */ diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index 464209641..3b44f7c30 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -16,6 +16,8 @@ #include "includes.h" +#ifdef ENABLE_PKCS11 + #include #ifdef HAVE_SYS_TIME_H # include @@ -277,6 +279,8 @@ main(int argc, char **argv) extern char *optarg; extern char *__progname; + __progname = ssh_get_progname(argv[0]); + log_init(__progname, log_level, log_facility, log_stderr); in = STDIN_FILENO; @@ -352,3 +356,14 @@ main(int argc, char **argv) process(); } } +#else /* ENABLE_PKCS11 */ +int +main(int argc, char **argv) +{ + extern char *__progname; + + __progname = ssh_get_progname(argv[0]); + log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); + fatal("PKCS#11 support disabled at compile time"); +} +#endif /* ENABLE_PKCS11 */ diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 2f6c9cec8..821e9f840 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -16,6 +16,8 @@ #include "includes.h" +#ifdef ENABLE_PKCS11 + #include #ifdef HAVE_SYS_TIME_H # include @@ -548,3 +550,5 @@ fail: dlclose(handle); return (-1); } + +#endif /* ENABLE_PKCS11 */ -- cgit v1.2.3 From 05abd2c96876b959f4a2f71671652064fcedda0d Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 24 Feb 2010 17:16:08 +1100 Subject: - (djm) [pkcs11.h ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] [ssh-pkcs11.h] Add $OpenBSD$ RCS idents so we can sync portable --- ChangeLog | 4 ++++ pkcs11.h | 1 + ssh-pkcs11-client.c | 1 + ssh-pkcs11-helper.c | 1 + ssh-pkcs11.c | 1 + ssh-pkcs11.h | 1 + 6 files changed, 9 insertions(+) (limited to 'ssh-pkcs11-client.c') diff --git a/ChangeLog b/ChangeLog index 83259b5fd..ac08efa4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +20100224 + - (djm) [pkcs11.h ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c] + [ssh-pkcs11.h] Add $OpenBSD$ RCS idents so we can sync portable + 20100212 - (djm) OpenBSD CVS Sync - djm@cvs.openbsd.org 2010/02/02 22:49:34 diff --git a/pkcs11.h b/pkcs11.h index 223f20ff3..2cde5b3f4 100644 --- a/pkcs11.h +++ b/pkcs11.h @@ -1,3 +1,4 @@ +/* $OpenBSD: pkcs11.h,v 1.2 2010/02/24 06:12:53 djm Exp $ */ /* pkcs11.h Copyright 2006, 2007 g10 Code GmbH Copyright 2006 Andreas Jellinghaus diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index 37050e04d..650c37342 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.2 2010/02/24 06:12:53 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index 3b44f7c30..1684ab0c2 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.3 2010/02/24 06:12:53 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 821e9f840..7536f92a6 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-pkcs11.c,v 1.4 2010/02/24 06:12:53 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h index fae41a7b5..59f456adf 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-pkcs11.h,v 1.2 2010/02/24 06:12:53 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * -- cgit v1.2.3