diff options
author | djm@openbsd.org <djm@openbsd.org> | 2023-12-18 15:46:56 +0100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2023-12-18 15:52:55 +0100 |
commit | 4448a2938abc76e6bd33ba09b2ec17a216dfb491 (patch) | |
tree | 1b2ef94eda1b9139e580dbd4dde416fb831b4602 /ssh-pkcs11-client.c | |
parent | upstream: apply destination constraints to all p11 keys (diff) | |
download | openssh-4448a2938abc76e6bd33ba09b2ec17a216dfb491.tar.xz openssh-4448a2938abc76e6bd33ba09b2ec17a216dfb491.zip |
upstream: Make it possible to load certs from PKCS#11 tokens
Adds a protocol extension to allow grafting certificates supplied by
ssh-add to keys loaded from PKCS#11 tokens in the agent.
feedback/ok markus@
OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f
Diffstat (limited to 'ssh-pkcs11-client.c')
-rw-r--r-- | ssh-pkcs11-client.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index 061b0681e..82e86a518 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.19 2023/12/18 14:46:56 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. @@ -426,6 +426,60 @@ wrap_key(struct helper *helper, struct sshkey *k) helper->path, helper->nrsa, helper->nec); } +/* + * Make a private PKCS#11-backed certificate by grafting a previously-loaded + * PKCS#11 private key and a public certificate key. + */ +int +pkcs11_make_cert(const struct sshkey *priv, + const struct sshkey *certpub, struct sshkey **certprivp) +{ + struct helper *helper = NULL; + struct sshkey *ret; + int r; + + debug3_f("private key type %s cert type %s", sshkey_type(priv), + sshkey_type(certpub)); + *certprivp = NULL; + if (!sshkey_is_cert(certpub) || sshkey_is_cert(priv) || + !sshkey_equal_public(priv, certpub)) { + error_f("private key %s doesn't match cert %s", + sshkey_type(priv), sshkey_type(certpub)); + return SSH_ERR_INVALID_ARGUMENT; + } + *certprivp = NULL; + if (priv->type == KEY_RSA) { + if ((helper = helper_by_rsa(priv->rsa)) == NULL || + helper->fd == -1) + fatal_f("no helper for PKCS11 RSA key"); + if ((r = sshkey_from_private(priv, &ret)) != 0) + fatal_fr(r, "copy key"); + RSA_set_method(ret->rsa, helper->rsa_meth); + if (helper->nrsa++ >= INT_MAX) + fatal_f("RSA refcount error"); + } else if (priv->type == KEY_ECDSA) { + if ((helper = helper_by_ec(priv->ecdsa)) == NULL || + helper->fd == -1) + fatal_f("no helper for PKCS11 EC key"); + if ((r = sshkey_from_private(priv, &ret)) != 0) + fatal_fr(r, "copy key"); + EC_KEY_set_method(ret->ecdsa, helper->ec_meth); + if (helper->nec++ >= INT_MAX) + fatal_f("EC refcount error"); + } else + fatal_f("unknown key type %s", sshkey_type(priv)); + + ret->flags |= SSHKEY_FLAG_EXT; + if ((r = sshkey_to_certified(ret)) != 0 || + (r = sshkey_cert_copy(certpub, ret)) != 0) + fatal_fr(r, "graft certificate"); + debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", + helper->path, helper->nrsa, helper->nec); + /* success */ + *certprivp = ret; + return 0; +} + static int pkcs11_start_helper_methods(struct helper *helper) { |