From 757f34e051d59995b7225e5c08c70f7f54019ae6 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 5 Aug 2010 13:05:31 +1000 Subject: [PATCH] - djm@cvs.openbsd.org 2010/08/04 06:07:11 [ssh-keygen.1 ssh-keygen.c] Support CA keys in PKCS#11 tokens; feedback and ok markus@ --- ChangeLog | 3 +++ ssh-keygen.1 | 21 +++++++++++++++++--- ssh-keygen.c | 55 ++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 684c5233b..0eec9ed7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,9 @@ commited the wrong version of the hostbased certificate diff; this version replaces some strlc{py,at} verbosity with xasprintf() at the request of markus@ + - djm@cvs.openbsd.org 2010/08/04 06:07:11 + [ssh-keygen.1 ssh-keygen.c] + Support CA keys in PKCS#11 tokens; feedback and ok markus@ 20100903 - (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from diff --git a/ssh-keygen.1 b/ssh-keygen.1 index c4464878d..9acd8f8c9 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.97 2010/07/15 21:20:38 schwarze Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.98 2010/08/04 06:07:11 djm Exp $ .\" .\" -*- nroff -*- .\" @@ -37,7 +37,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 15 2010 $ +.Dd $Mdocdate: August 4 2010 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -215,6 +215,11 @@ the passphrase if the key has one, and for the new comment. .It Fl D Ar pkcs11 Download the RSA public keys provided by the PKCS#11 shared library .Ar pkcs11 . +When used in combination with +.Fl s , +this option indicates that a CA key resides in a PKCS#11 token (see the +.Sx CERTIFICATES +section for details). .It Fl e This option will read a private or public OpenSSH key file and print to stdout the key in one of the formats specified by the @@ -553,7 +558,17 @@ option: .Pp The host certificate will be output to .Pa /path/to/host_key-cert.pub . -In both cases, +.Pp +It is possible to sign using a CA key stored in a PKCS#11 token by +providing the token library using +.Fl D +and identifying the CA key by providing its public half as an argument +to +.Fl s : +.Pp +.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub +.Pp +In all cases, .Ar key_id is a "key identifier" that is logged by the server when the certificate is used for authentication. diff --git a/ssh-keygen.c b/ssh-keygen.c index 4c60a659f..d90b1dfdd 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.196 2010/08/04 05:40:39 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.197 2010/08/04 06:07:11 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -146,6 +146,8 @@ int print_generic = 0; char *key_type_name = NULL; +/* Load key from this PKCS#11 provider */ +char *pkcs11provider = NULL; /* argv0 */ extern char *__progname; @@ -655,7 +657,7 @@ do_print_public(struct passwd *pw) } static void -do_download(struct passwd *pw, char *pkcs11provider) +do_download(struct passwd *pw) { #ifdef ENABLE_PKCS11 Key **keys = NULL; @@ -1318,6 +1320,35 @@ prepare_options_buf(Buffer *c, int which) add_string_option(c, "source-address", certflags_src_addr); } +static Key * +load_pkcs11_key(char *path) +{ +#ifdef ENABLE_PKCS11 + Key **keys = NULL, *public, *private = NULL; + int i, nkeys; + + if ((public = key_load_public(path, NULL)) == NULL) + fatal("Couldn't load CA public key \"%s\"", path); + + nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys); + debug3("%s: %d keys", __func__, nkeys); + if (nkeys <= 0) + fatal("cannot read public key from pkcs11"); + for (i = 0; i < nkeys; i++) { + if (key_equal_public(public, keys[i])) { + private = keys[i]; + continue; + } + key_free(keys[i]); + } + xfree(keys); + key_free(public); + return private; +#else + fatal("no pkcs11 support"); +#endif /* ENABLE_PKCS11 */ +} + static void do_ca_sign(struct passwd *pw, int argc, char **argv) { @@ -1328,11 +1359,6 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) FILE *f; int v00 = 0; /* legacy keys */ - tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); - if ((ca = load_identity(tmp)) == NULL) - fatal("Couldn't load CA key \"%s\"", tmp); - xfree(tmp); - if (key_type_name != NULL) { switch (key_type_from_name(key_type_name)) { case KEY_RSA_CERT_V00: @@ -1352,6 +1378,15 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) } } + pkcs11_init(1); + tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); + if (pkcs11provider != NULL) { + if ((ca = load_pkcs11_key(tmp)) == NULL) + fatal("No PKCS#11 key matching %s found", ca_key_path); + } else if ((ca = load_identity(tmp)) == NULL) + fatal("Couldn't load CA key \"%s\"", tmp); + xfree(tmp); + for (i = 0; i < argc; i++) { /* Split list of principals */ n = 0; @@ -1424,6 +1459,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) key_free(public); xfree(out); } + pkcs11_terminate(); exit(0); } @@ -1725,8 +1761,7 @@ int main(int argc, char **argv) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; - char out_file[MAXPATHLEN], *pkcs11provider = NULL; - char *rr_hostname = NULL; + char out_file[MAXPATHLEN], *rr_hostname = NULL; Key *private, *public; struct passwd *pw; struct stat st; @@ -2001,7 +2036,7 @@ main(int argc, char **argv) } } if (pkcs11provider != NULL) - do_download(pw, pkcs11provider); + do_download(pw); if (do_gen_candidates) { FILE *out = fopen(out_file, "w");