version 1.11, 2018/09/13 02:08:33 |
version 1.12, 2019/01/20 22:51:37 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* |
/* |
* Copyright (c) 2010 Markus Friedl. All rights reserved. |
* Copyright (c) 2010 Markus Friedl. All rights reserved. |
|
* Copyright (c) 2014 Pedro Martelletto. All rights reserved. |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
#include <unistd.h> |
#include <unistd.h> |
#include <errno.h> |
#include <errno.h> |
|
|
|
#include <openssl/ecdsa.h> |
#include <openssl/rsa.h> |
#include <openssl/rsa.h> |
|
|
#include "pathnames.h" |
#include "pathnames.h" |
|
|
} |
} |
|
|
static int |
static int |
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, |
rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) |
int padding) |
|
{ |
{ |
struct sshkey key; /* XXX */ |
struct sshkey key; /* XXX */ |
u_char *blob, *signature = NULL; |
u_char *blob, *signature = NULL; |
|
|
return (ret); |
return (ret); |
} |
} |
|
|
/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ |
static ECDSA_SIG * |
|
ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, |
|
const BIGNUM *rp, EC_KEY *ec) |
|
{ |
|
struct sshkey key; /* XXX */ |
|
u_char *blob, *signature = NULL; |
|
const u_char *cp; |
|
size_t blen, slen = 0; |
|
ECDSA_SIG *ret = NULL; |
|
struct sshbuf *msg; |
|
int r; |
|
|
|
key.type = KEY_ECDSA; |
|
key.ecdsa = ec; |
|
key.ecdsa_nid = sshkey_ecdsa_key_to_nid(ec); |
|
if (key.ecdsa_nid < 0) { |
|
error("%s: couldn't get curve nid", __func__); |
|
return (NULL); |
|
} |
|
if ((r = sshkey_to_blob(&key, &blob, &blen)) != 0) { |
|
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); |
|
return (NULL); |
|
} |
|
if ((msg = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
|
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || |
|
(r = sshbuf_put_string(msg, blob, blen)) != 0 || |
|
(r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 || |
|
(r = sshbuf_put_u32(msg, 0)) != 0) |
|
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
|
free(blob); |
|
send_msg(msg); |
|
sshbuf_reset(msg); |
|
|
|
if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { |
|
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) |
|
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
|
cp = signature; |
|
ret = d2i_ECDSA_SIG(NULL, &cp, slen); |
|
free(signature); |
|
} |
|
|
|
sshbuf_free(msg); |
|
return (ret); |
|
} |
|
|
|
static RSA_METHOD *helper_rsa; |
|
static EC_KEY_METHOD *helper_ecdsa; |
|
|
|
/* redirect private key crypto operations to the ssh-pkcs11-helper */ |
|
static void |
|
wrap_key(struct sshkey *k) |
|
{ |
|
if (k->type == KEY_RSA) |
|
RSA_set_method(k->rsa, helper_rsa); |
|
else if (k->type == KEY_ECDSA) |
|
EC_KEY_set_method(k->ecdsa, helper_ecdsa); |
|
else |
|
fatal("%s: unknown key type", __func__); |
|
} |
|
|
static int |
static int |
wrap_key(RSA *rsa) |
pkcs11_start_helper_methods(void) |
{ |
{ |
static RSA_METHOD *helper_rsa; |
if (helper_ecdsa != NULL) |
|
return (0); |
|
|
|
int (*orig_sign)(int, const unsigned char *, int, unsigned char *, |
|
unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; |
|
if (helper_ecdsa != NULL) |
|
return (0); |
|
helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); |
|
if (helper_ecdsa == NULL) |
|
return (-1); |
|
EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL); |
|
EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign); |
|
|
if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) |
if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) |
fatal("%s: RSA_meth_dup failed", __func__); |
fatal("%s: RSA_meth_dup failed", __func__); |
if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || |
if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || |
!RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt)) |
!RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt)) |
fatal("%s: failed to prepare method", __func__); |
fatal("%s: failed to prepare method", __func__); |
RSA_set_method(rsa, helper_rsa); |
|
return (0); |
return (0); |
} |
} |
|
|
|
|
{ |
{ |
int pair[2]; |
int pair[2]; |
|
|
|
if (pkcs11_start_helper_methods() == -1) { |
|
error("pkcs11_start_helper_methods failed"); |
|
return (-1); |
|
} |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { |
error("socketpair: %s", strerror(errno)); |
error("socketpair: %s", strerror(errno)); |
return (-1); |
return (-1); |
|
|
pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) |
pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) |
{ |
{ |
struct sshkey *k; |
struct sshkey *k; |
int r; |
int r, type; |
u_char *blob; |
u_char *blob; |
size_t blen; |
size_t blen; |
u_int nkeys, i; |
u_int nkeys, i; |
|
|
send_msg(msg); |
send_msg(msg); |
sshbuf_reset(msg); |
sshbuf_reset(msg); |
|
|
if (recv_msg(msg) == SSH2_AGENT_IDENTITIES_ANSWER) { |
type = recv_msg(msg); |
|
if (type == SSH2_AGENT_IDENTITIES_ANSWER) { |
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) |
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
*keysp = xcalloc(nkeys, sizeof(struct sshkey *)); |
*keysp = xcalloc(nkeys, sizeof(struct sshkey *)); |
|
|
__func__, ssh_err(r)); |
__func__, ssh_err(r)); |
if ((r = sshkey_from_blob(blob, blen, &k)) != 0) |
if ((r = sshkey_from_blob(blob, blen, &k)) != 0) |
fatal("%s: bad key: %s", __func__, ssh_err(r)); |
fatal("%s: bad key: %s", __func__, ssh_err(r)); |
wrap_key(k->rsa); |
wrap_key(k); |
(*keysp)[i] = k; |
(*keysp)[i] = k; |
free(blob); |
free(blob); |
} |
} |
|
} else if (type == SSH2_AGENT_FAILURE) { |
|
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) |
|
nkeys = -1; |
} else { |
} else { |
nkeys = -1; |
nkeys = -1; |
} |
} |