- 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@
This commit is contained in:
Damien Miller 2010-08-05 13:05:31 +10:00
parent 5458c4dd13
commit 757f34e051
3 changed files with 66 additions and 13 deletions

View File

@ -19,6 +19,9 @@
commited the wrong version of the hostbased certificate diff; this commited the wrong version of the hostbased certificate diff; this
version replaces some strlc{py,at} verbosity with xasprintf() at version replaces some strlc{py,at} verbosity with xasprintf() at
the request of markus@ 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 20100903
- (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from - (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from

View File

@ -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 -*- .\" -*- nroff -*-
.\" .\"
@ -37,7 +37,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 .Dt SSH-KEYGEN 1
.Os .Os
.Sh NAME .Sh NAME
@ -215,6 +215,11 @@ the passphrase if the key has one, and for the new comment.
.It Fl D Ar pkcs11 .It Fl D Ar pkcs11
Download the RSA public keys provided by the PKCS#11 shared library Download the RSA public keys provided by the PKCS#11 shared library
.Ar pkcs11 . .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 .It Fl e
This option will read a private or public OpenSSH key file and 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 print to stdout the key in one of the formats specified by the
@ -553,7 +558,17 @@ option:
.Pp .Pp
The host certificate will be output to The host certificate will be output to
.Pa /path/to/host_key-cert.pub . .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 .Ar key_id
is a "key identifier" that is logged by the server when the certificate is a "key identifier" that is logged by the server when the certificate
is used for authentication. is used for authentication.

View File

@ -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 <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -146,6 +146,8 @@ int print_generic = 0;
char *key_type_name = NULL; char *key_type_name = NULL;
/* Load key from this PKCS#11 provider */
char *pkcs11provider = NULL;
/* argv0 */ /* argv0 */
extern char *__progname; extern char *__progname;
@ -655,7 +657,7 @@ do_print_public(struct passwd *pw)
} }
static void static void
do_download(struct passwd *pw, char *pkcs11provider) do_download(struct passwd *pw)
{ {
#ifdef ENABLE_PKCS11 #ifdef ENABLE_PKCS11
Key **keys = NULL; Key **keys = NULL;
@ -1318,6 +1320,35 @@ prepare_options_buf(Buffer *c, int which)
add_string_option(c, "source-address", certflags_src_addr); 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 static void
do_ca_sign(struct passwd *pw, int argc, char **argv) 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; FILE *f;
int v00 = 0; /* legacy keys */ 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) { if (key_type_name != NULL) {
switch (key_type_from_name(key_type_name)) { switch (key_type_from_name(key_type_name)) {
case KEY_RSA_CERT_V00: 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++) { for (i = 0; i < argc; i++) {
/* Split list of principals */ /* Split list of principals */
n = 0; n = 0;
@ -1424,6 +1459,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
key_free(public); key_free(public);
xfree(out); xfree(out);
} }
pkcs11_terminate();
exit(0); exit(0);
} }
@ -1725,8 +1761,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
char out_file[MAXPATHLEN], *pkcs11provider = NULL; char out_file[MAXPATHLEN], *rr_hostname = NULL;
char *rr_hostname = NULL;
Key *private, *public; Key *private, *public;
struct passwd *pw; struct passwd *pw;
struct stat st; struct stat st;
@ -2001,7 +2036,7 @@ main(int argc, char **argv)
} }
} }
if (pkcs11provider != NULL) if (pkcs11provider != NULL)
do_download(pw, pkcs11provider); do_download(pw);
if (do_gen_candidates) { if (do_gen_candidates) {
FILE *out = fopen(out_file, "w"); FILE *out = fopen(out_file, "w");