mirror of git://anongit.mindrot.org/openssh.git
upstream: Convert RSA and ECDSA key to the libcrypto EVP_PKEY API.
DSA remains unconverted as it will be removed within six months. Based on patches originally from Dmitry Belyavskiy, but significantly reworked based on feedback from Bob Beck, Joel Sing and especially Theo Buehler (apologies to anyone I've missed). ok tb@ OpenBSD-Commit-ID: d098744e89f1dc7e5952a6817bef234eced648b5
This commit is contained in:
parent
0af06e2c5b
commit
7bdfc20516
9
packet.c
9
packet.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: packet.c,v 1.315 2024/05/31 08:49:35 djm Exp $ */
|
||||
/* $OpenBSD: packet.c,v 1.316 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -2650,8 +2650,13 @@ sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
|
|||
{
|
||||
return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
|
||||
}
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
|
||||
int
|
||||
sshpkt_put_ec_pkey(struct ssh *ssh, EVP_PKEY *pkey)
|
||||
{
|
||||
return sshbuf_put_ec_pkey(ssh->state->outgoing_packet, pkey);
|
||||
}
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
|
||||
int
|
||||
sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v)
|
||||
|
|
6
packet.h
6
packet.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: packet.h,v 1.98 2024/05/17 06:42:04 jsg Exp $ */
|
||||
/* $OpenBSD: packet.h,v 1.99 2024/08/15 00:51:51 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -20,6 +20,7 @@
|
|||
|
||||
#ifdef WITH_OPENSSL
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/evp.h>
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
# include <openssl/ec.h>
|
||||
# else /* OPENSSL_HAS_ECC */
|
||||
|
@ -32,6 +33,7 @@
|
|||
# define EC_KEY void
|
||||
# define EC_GROUP void
|
||||
# define EC_POINT void
|
||||
# define EVP_PKEY void
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#include <signal.h>
|
||||
|
@ -191,6 +193,7 @@ int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len);
|
|||
int sshpkt_put_cstring(struct ssh *ssh, const void *v);
|
||||
int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v);
|
||||
int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g);
|
||||
int sshpkt_put_ec_pkey(struct ssh *ssh, EVP_PKEY *pkey);
|
||||
int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v);
|
||||
|
||||
int sshpkt_get(struct ssh *ssh, void *valp, size_t len);
|
||||
|
@ -213,6 +216,7 @@ const u_char *sshpkt_ptr(struct ssh *, size_t *lenp);
|
|||
# undef EC_KEY
|
||||
# undef EC_GROUP
|
||||
# undef EC_POINT
|
||||
# undef EVP_PKEY
|
||||
#elif !defined(OPENSSL_HAS_ECC)
|
||||
# undef EC_KEY
|
||||
# undef EC_GROUP
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.18 2023/03/08 04:43:12 guenther Exp $ */
|
||||
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.19 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
|
@ -237,11 +237,13 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
|
|||
struct sshkey_sig_details **detailsp)
|
||||
{
|
||||
ECDSA_SIG *esig = NULL;
|
||||
EVP_MD_CTX *md_ctx = NULL;
|
||||
BIGNUM *sig_r = NULL, *sig_s = NULL;
|
||||
u_char sig_flags;
|
||||
u_char msghash[32], apphash[32], sighash[32];
|
||||
u_char msghash[32], apphash[32];
|
||||
u_int sig_counter;
|
||||
int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
u_char *sigb = NULL, *cp;
|
||||
int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR, len = 0;
|
||||
struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL;
|
||||
struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL;
|
||||
char *ktype = NULL, *webauthn_origin = NULL;
|
||||
|
@ -252,7 +254,7 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
|
|||
|
||||
if (detailsp != NULL)
|
||||
*detailsp = NULL;
|
||||
if (key == NULL || key->ecdsa == NULL ||
|
||||
if (key == NULL || key->pkey == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ECDSA_SK ||
|
||||
sig == NULL || siglen == 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
@ -363,21 +365,43 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
|
|||
(ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 ||
|
||||
(ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0)
|
||||
goto out;
|
||||
/* Signature is over H(original_signed) */
|
||||
if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed,
|
||||
sighash, sizeof(sighash))) != 0)
|
||||
goto out;
|
||||
details->sk_counter = sig_counter;
|
||||
details->sk_flags = sig_flags;
|
||||
#ifdef DEBUG_SK
|
||||
fprintf(stderr, "%s: signed buf:\n", __func__);
|
||||
sshbuf_dump(original_signed, stderr);
|
||||
fprintf(stderr, "%s: signed hash:\n", __func__);
|
||||
sshbuf_dump_data(sighash, sizeof(sighash), stderr);
|
||||
#endif
|
||||
|
||||
if ((md_ctx = EVP_MD_CTX_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) {
|
||||
len = 0;
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((sigb = calloc(1, len)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
cp = sigb; /* ASN1_item_i2d increments the pointer past the object */
|
||||
if (i2d_ECDSA_SIG(esig, &cp) != len) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_SK
|
||||
fprintf(stderr, "%s: signed hash:\n", __func__);
|
||||
sshbuf_dump_data(sigb, len, stderr);
|
||||
#endif
|
||||
/* Verify it */
|
||||
switch (ECDSA_do_verify(sighash, sizeof(sighash), esig, key->ecdsa)) {
|
||||
if (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL,
|
||||
key->pkey) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
switch (EVP_DigestVerify(md_ctx, sigb, len,
|
||||
sshbuf_ptr(original_signed), sshbuf_len(original_signed))) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -397,7 +421,6 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
|
|||
explicit_bzero(&sig_flags, sizeof(sig_flags));
|
||||
explicit_bzero(&sig_counter, sizeof(sig_counter));
|
||||
explicit_bzero(msghash, sizeof(msghash));
|
||||
explicit_bzero(sighash, sizeof(msghash));
|
||||
explicit_bzero(apphash, sizeof(apphash));
|
||||
sshkey_sig_details_free(details);
|
||||
sshbuf_free(webauthn_wrapper);
|
||||
|
@ -410,6 +433,8 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
|
|||
BN_clear_free(sig_r);
|
||||
BN_clear_free(sig_s);
|
||||
free(ktype);
|
||||
freezero(sigb, len);
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
264
ssh-ecdsa.c
264
ssh-ecdsa.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-ecdsa.c,v 1.26 2023/03/08 04:43:12 guenther Exp $ */
|
||||
/* $OpenBSD: ssh-ecdsa.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
|
@ -45,6 +45,61 @@
|
|||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
int
|
||||
sshkey_ecdsa_fixup_group(EVP_PKEY *k)
|
||||
{
|
||||
int nids[] = {
|
||||
NID_X9_62_prime256v1,
|
||||
NID_secp384r1,
|
||||
#ifdef OPENSSL_HAS_NISTP521
|
||||
NID_secp521r1,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
int nid = -1;
|
||||
u_int i;
|
||||
const EC_GROUP *g;
|
||||
EC_KEY *ec = NULL;
|
||||
EC_GROUP *eg = NULL;
|
||||
|
||||
if ((ec = EVP_PKEY_get1_EC_KEY(k)) == NULL ||
|
||||
(g = EC_KEY_get0_group(ec)) == NULL)
|
||||
goto out;
|
||||
/*
|
||||
* The group may be stored in a ASN.1 encoded private key in one of two
|
||||
* ways: as a "named group", which is reconstituted by ASN.1 object ID
|
||||
* or explicit group parameters encoded into the key blob. Only the
|
||||
* "named group" case sets the group NID for us, but we can figure
|
||||
* it out for the other case by comparing against all the groups that
|
||||
* are supported.
|
||||
*/
|
||||
if ((nid = EC_GROUP_get_curve_name(g)) > 0)
|
||||
goto out;
|
||||
nid = -1;
|
||||
for (i = 0; nids[i] != -1; i++) {
|
||||
if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
|
||||
goto out;
|
||||
if (EC_GROUP_cmp(g, eg, NULL) == 0)
|
||||
break;
|
||||
EC_GROUP_free(eg);
|
||||
eg = NULL;
|
||||
}
|
||||
if (nids[i] == -1)
|
||||
goto out;
|
||||
|
||||
/* Use the group with the NID attached */
|
||||
EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
|
||||
if (EC_KEY_set_group(ec, eg) != 1 ||
|
||||
EVP_PKEY_set1_EC_KEY(k, ec) != 1)
|
||||
goto out;
|
||||
/* success */
|
||||
nid = nids[i];
|
||||
out:
|
||||
EC_KEY_free(ec);
|
||||
EC_GROUP_free(eg);
|
||||
return nid;
|
||||
}
|
||||
|
||||
static u_int
|
||||
ssh_ecdsa_size(const struct sshkey *key)
|
||||
{
|
||||
|
@ -65,30 +120,16 @@ ssh_ecdsa_size(const struct sshkey *key)
|
|||
static void
|
||||
ssh_ecdsa_cleanup(struct sshkey *k)
|
||||
{
|
||||
EC_KEY_free(k->ecdsa);
|
||||
k->ecdsa = NULL;
|
||||
EVP_PKEY_free(k->pkey);
|
||||
k->pkey = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
{
|
||||
const EC_GROUP *grp_a, *grp_b;
|
||||
const EC_POINT *pub_a, *pub_b;
|
||||
|
||||
if (a->ecdsa == NULL || b->ecdsa == NULL)
|
||||
if (a->pkey == NULL || b->pkey == NULL)
|
||||
return 0;
|
||||
if ((grp_a = EC_KEY_get0_group(a->ecdsa)) == NULL ||
|
||||
(grp_b = EC_KEY_get0_group(b->ecdsa)) == NULL)
|
||||
return 0;
|
||||
if ((pub_a = EC_KEY_get0_public_key(a->ecdsa)) == NULL ||
|
||||
(pub_b = EC_KEY_get0_public_key(b->ecdsa)) == NULL)
|
||||
return 0;
|
||||
if (EC_GROUP_cmp(grp_a, grp_b, NULL) != 0)
|
||||
return 0;
|
||||
if (EC_POINT_cmp(grp_a, pub_a, pub_b, NULL) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return EVP_PKEY_cmp(a->pkey, b->pkey) == 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -97,11 +138,11 @@ ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
|||
{
|
||||
int r;
|
||||
|
||||
if (key->ecdsa == NULL)
|
||||
if (key->pkey == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((r = sshbuf_put_cstring(b,
|
||||
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
|
||||
(r = sshbuf_put_eckey(b, key->ecdsa)) != 0)
|
||||
(r = sshbuf_put_ec_pkey(b, key->pkey)) != 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
|
@ -118,7 +159,7 @@ ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
|
|||
return r;
|
||||
}
|
||||
if ((r = sshbuf_put_bignum2(b,
|
||||
EC_KEY_get0_private_key(key->ecdsa))) != 0)
|
||||
EC_KEY_get0_private_key(EVP_PKEY_get0_EC_KEY(key->pkey)))) != 0)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,31 +167,64 @@ ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
|
|||
static int
|
||||
ssh_ecdsa_generate(struct sshkey *k, int bits)
|
||||
{
|
||||
EC_KEY *private;
|
||||
EVP_PKEY *res = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
|
||||
|
||||
if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (EC_KEY_generate_key(private) != 1) {
|
||||
EC_KEY_free(private);
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
if (EVP_PKEY_keygen_init(ctx) <= 0 ||
|
||||
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, k->ecdsa_nid) <= 0 ||
|
||||
EVP_PKEY_keygen(ctx, &res) <= 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
|
||||
k->ecdsa = private;
|
||||
return 0;
|
||||
/* success */
|
||||
k->pkey = res;
|
||||
res = NULL;
|
||||
ret = 0;
|
||||
out:
|
||||
EVP_PKEY_free(res);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
{
|
||||
const EC_KEY *ec_from;
|
||||
EC_KEY *ec_to = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
ec_from = EVP_PKEY_get0_EC_KEY(from->pkey);
|
||||
if (ec_from == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
to->ecdsa_nid = from->ecdsa_nid;
|
||||
if ((to->ecdsa = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL)
|
||||
if ((ec_to = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (EC_KEY_set_public_key(to->ecdsa,
|
||||
EC_KEY_get0_public_key(from->ecdsa)) != 1)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR; /* caller will free k->ecdsa */
|
||||
return 0;
|
||||
if (EC_KEY_set_public_key(ec_to,
|
||||
EC_KEY_get0_public_key(ec_from)) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
EVP_PKEY_free(to->pkey);
|
||||
if ((to->pkey = EVP_PKEY_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_set1_EC_KEY(to->pkey, ec_to) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
EC_KEY_free(ec_to);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -159,6 +233,8 @@ ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
|
|||
{
|
||||
int r;
|
||||
char *curve = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EC_KEY *ec = NULL;
|
||||
|
||||
if ((key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype)) == -1)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
@ -168,31 +244,39 @@ ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
|
|||
r = SSH_ERR_EC_CURVE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
EC_KEY_free(key->ecdsa);
|
||||
key->ecdsa = NULL;
|
||||
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
|
||||
if ((ec = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get_eckey(b, key->ecdsa)) != 0)
|
||||
if ((r = sshbuf_get_eckey(b, ec)) != 0)
|
||||
goto out;
|
||||
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
|
||||
EC_KEY_get0_public_key(key->ecdsa)) != 0) {
|
||||
if (sshkey_ec_validate_public(EC_KEY_get0_group(ec),
|
||||
EC_KEY_get0_public_key(ec)) != 0) {
|
||||
r = SSH_ERR_KEY_INVALID_EC_VALUE;
|
||||
goto out;
|
||||
}
|
||||
if ((pkey = EVP_PKEY_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
EVP_PKEY_free(key->pkey);
|
||||
key->pkey = pkey;
|
||||
pkey = NULL;
|
||||
/* success */
|
||||
r = 0;
|
||||
#ifdef DEBUG_PK
|
||||
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa),
|
||||
EC_KEY_get0_public_key(key->ecdsa));
|
||||
sshkey_dump_ec_point(
|
||||
EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key->pkey)),
|
||||
EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(key->pkey)));
|
||||
#endif
|
||||
out:
|
||||
EC_KEY_free(ec);
|
||||
EVP_PKEY_free(pkey);
|
||||
free(curve);
|
||||
if (r != 0) {
|
||||
EC_KEY_free(key->ecdsa);
|
||||
key->ecdsa = NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -202,6 +286,7 @@ ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b,
|
|||
{
|
||||
int r;
|
||||
BIGNUM *exponent = NULL;
|
||||
EC_KEY *ec = NULL;
|
||||
|
||||
if (!sshkey_is_cert(key)) {
|
||||
if ((r = ssh_ecdsa_deserialize_public(ktype, b, key)) != 0)
|
||||
|
@ -209,16 +294,25 @@ ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b,
|
|||
}
|
||||
if ((r = sshbuf_get_bignum2(b, &exponent)) != 0)
|
||||
goto out;
|
||||
if (EC_KEY_set_private_key(key->ecdsa, exponent) != 1) {
|
||||
if ((ec = EVP_PKEY_get1_EC_KEY(key->pkey)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshkey_ec_validate_private(key->ecdsa)) != 0)
|
||||
if (EC_KEY_set_private_key(ec, exponent) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshkey_ec_validate_private(ec)) != 0)
|
||||
goto out;
|
||||
if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
BN_clear_free(exponent);
|
||||
EC_KEY_free(ec);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -229,34 +323,35 @@ ssh_ecdsa_sign(struct sshkey *key,
|
|||
const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
|
||||
{
|
||||
ECDSA_SIG *esig = NULL;
|
||||
unsigned char *sigb = NULL;
|
||||
const unsigned char *psig;
|
||||
const BIGNUM *sig_r, *sig_s;
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH];
|
||||
size_t len, hlen;
|
||||
size_t slen = 0;
|
||||
struct sshbuf *b = NULL, *bb = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
int len = 0, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (lenp != NULL)
|
||||
*lenp = 0;
|
||||
if (sigp != NULL)
|
||||
*sigp = NULL;
|
||||
|
||||
if (key == NULL || key->ecdsa == NULL ||
|
||||
if (key == NULL || key->pkey == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ECDSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
|
||||
(hlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, dlen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
|
||||
if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sigb, &slen,
|
||||
data, dlen)) != 0)
|
||||
goto out;
|
||||
|
||||
if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) {
|
||||
psig = sigb;
|
||||
if ((esig = d2i_ECDSA_SIG(NULL, &psig, slen)) == NULL) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
|
@ -280,7 +375,7 @@ ssh_ecdsa_sign(struct sshkey *key,
|
|||
*lenp = len;
|
||||
ret = 0;
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
freezero(sigb, slen);
|
||||
sshbuf_free(b);
|
||||
sshbuf_free(bb);
|
||||
ECDSA_SIG_free(esig);
|
||||
|
@ -295,20 +390,18 @@ ssh_ecdsa_verify(const struct sshkey *key,
|
|||
{
|
||||
ECDSA_SIG *esig = NULL;
|
||||
BIGNUM *sig_r = NULL, *sig_s = NULL;
|
||||
int hash_alg;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH];
|
||||
size_t hlen;
|
||||
int hash_alg, len = 0;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
struct sshbuf *b = NULL, *sigbuf = NULL;
|
||||
char *ktype = NULL;
|
||||
unsigned char *sigb = NULL, *cp;
|
||||
|
||||
if (key == NULL || key->ecdsa == NULL ||
|
||||
if (key == NULL || key->pkey == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_ECDSA ||
|
||||
sig == NULL || siglen == 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
|
||||
(hlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
/* fetch signature */
|
||||
|
@ -334,6 +427,11 @@ ssh_ecdsa_verify(const struct sshkey *key,
|
|||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(sigbuf) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((esig = ECDSA_SIG_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
|
@ -344,28 +442,26 @@ ssh_ecdsa_verify(const struct sshkey *key,
|
|||
}
|
||||
sig_r = sig_s = NULL; /* transferred */
|
||||
|
||||
if (sshbuf_len(sigbuf) != 0) {
|
||||
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, dlen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0:
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto out;
|
||||
default:
|
||||
if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) {
|
||||
len = 0;
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((sigb = calloc(1, len)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
cp = sigb; /* ASN1_item_i2d increments the pointer past the object */
|
||||
if (i2d_ECDSA_SIG(esig, &cp) != len) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = sshkey_pkey_digest_verify(key->pkey, hash_alg,
|
||||
data, dlen, sigb, len)) != 0)
|
||||
goto out;
|
||||
/* success */
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
freezero(sigb, len);
|
||||
sshbuf_free(sigbuf);
|
||||
sshbuf_free(b);
|
||||
ECDSA_SIG_free(esig);
|
||||
|
|
61
ssh-keygen.c
61
ssh-keygen.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-keygen.c,v 1.472 2024/01/11 01:45:36 djm Exp $ */
|
||||
/* $OpenBSD: ssh-keygen.c,v 1.473 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -375,7 +375,8 @@ do_convert_to_pkcs8(struct sshkey *k)
|
|||
{
|
||||
switch (sshkey_type_plain(k->type)) {
|
||||
case KEY_RSA:
|
||||
if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
|
||||
if (!PEM_write_RSA_PUBKEY(stdout,
|
||||
EVP_PKEY_get0_RSA(k->pkey)))
|
||||
fatal("PEM_write_RSA_PUBKEY failed");
|
||||
break;
|
||||
#ifdef WITH_DSA
|
||||
|
@ -386,7 +387,8 @@ do_convert_to_pkcs8(struct sshkey *k)
|
|||
#endif
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA:
|
||||
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
|
||||
if (!PEM_write_EC_PUBKEY(stdout,
|
||||
EVP_PKEY_get0_EC_KEY(k->pkey)))
|
||||
fatal("PEM_write_EC_PUBKEY failed");
|
||||
break;
|
||||
#endif
|
||||
|
@ -401,7 +403,8 @@ do_convert_to_pem(struct sshkey *k)
|
|||
{
|
||||
switch (sshkey_type_plain(k->type)) {
|
||||
case KEY_RSA:
|
||||
if (!PEM_write_RSAPublicKey(stdout, k->rsa))
|
||||
if (!PEM_write_RSAPublicKey(stdout,
|
||||
EVP_PKEY_get0_RSA(k->pkey)))
|
||||
fatal("PEM_write_RSAPublicKey failed");
|
||||
break;
|
||||
#ifdef WITH_DSA
|
||||
|
@ -412,7 +415,8 @@ do_convert_to_pem(struct sshkey *k)
|
|||
#endif
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA:
|
||||
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
|
||||
if (!PEM_write_EC_PUBKEY(stdout,
|
||||
EVP_PKEY_get0_EC_KEY(k->pkey)))
|
||||
fatal("PEM_write_EC_PUBKEY failed");
|
||||
break;
|
||||
#endif
|
||||
|
@ -490,6 +494,8 @@ do_convert_private_ssh2(struct sshbuf *b)
|
|||
#endif
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
|
||||
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
|
||||
BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
|
||||
RSA *rsa = NULL;
|
||||
|
||||
if ((r = sshbuf_get_u32(b, &magic)) != 0)
|
||||
fatal_fr(r, "parse magic");
|
||||
|
@ -584,15 +590,25 @@ do_convert_private_ssh2(struct sshbuf *b)
|
|||
buffer_get_bignum_bits(b, rsa_iqmp);
|
||||
buffer_get_bignum_bits(b, rsa_q);
|
||||
buffer_get_bignum_bits(b, rsa_p);
|
||||
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
|
||||
if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
|
||||
rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
|
||||
fatal_fr(r, "generate RSA CRT parameters");
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal_f("EVP_PKEY_new failed");
|
||||
if ((rsa = RSA_new()) == NULL)
|
||||
fatal_f("RSA_new failed");
|
||||
if (!RSA_set0_key(rsa, rsa_n, rsa_e, rsa_d))
|
||||
fatal_f("RSA_set0_key failed");
|
||||
rsa_n = rsa_e = rsa_d = NULL; /* transferred */
|
||||
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
|
||||
if (!RSA_set0_factors(rsa, rsa_p, rsa_q))
|
||||
fatal_f("RSA_set0_factors failed");
|
||||
rsa_p = rsa_q = NULL; /* transferred */
|
||||
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
|
||||
fatal_fr(r, "generate RSA parameters");
|
||||
BN_clear_free(rsa_iqmp);
|
||||
if (RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp) != 1)
|
||||
fatal_f("RSA_set0_crt_params failed");
|
||||
rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL;
|
||||
if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
|
||||
fatal_f("EVP_PKEY_set1_RSA failed");
|
||||
RSA_free(rsa);
|
||||
alg = "rsa-sha2-256";
|
||||
break;
|
||||
}
|
||||
|
@ -712,7 +728,8 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
|
|||
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||
fatal("sshkey_new failed");
|
||||
(*k)->type = KEY_RSA;
|
||||
(*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
|
||||
(*k)->pkey = pubkey;
|
||||
pubkey = NULL;
|
||||
break;
|
||||
#ifdef WITH_DSA
|
||||
case EVP_PKEY_DSA:
|
||||
|
@ -726,9 +743,11 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
|
|||
case EVP_PKEY_EC:
|
||||
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||
fatal("sshkey_new failed");
|
||||
if (((*k)->ecdsa_nid = sshkey_ecdsa_fixup_group(pubkey)) == -1)
|
||||
fatal("sshkey_ecdsa_fixup_group failed");
|
||||
(*k)->type = KEY_ECDSA;
|
||||
(*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
|
||||
(*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
|
||||
(*k)->pkey = pubkey;
|
||||
pubkey = NULL;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -750,8 +769,12 @@ do_convert_from_pem(struct sshkey **k, int *private)
|
|||
if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
|
||||
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||
fatal("sshkey_new failed");
|
||||
if (((*k)->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal("EVP_PKEY_new failed");
|
||||
(*k)->type = KEY_RSA;
|
||||
(*k)->rsa = rsa;
|
||||
if (EVP_PKEY_set1_RSA((*k)->pkey, rsa) != 1)
|
||||
fatal("EVP_PKEY_set1_RSA failed");
|
||||
RSA_free(rsa);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
@ -799,13 +822,15 @@ do_convert_from(struct passwd *pw)
|
|||
#endif
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA:
|
||||
ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL,
|
||||
NULL, 0, NULL, NULL);
|
||||
ok = PEM_write_ECPrivateKey(stdout,
|
||||
EVP_PKEY_get0_EC_KEY(k->pkey), NULL, NULL, 0,
|
||||
NULL, NULL);
|
||||
break;
|
||||
#endif
|
||||
case KEY_RSA:
|
||||
ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
|
||||
NULL, 0, NULL, NULL);
|
||||
ok = PEM_write_RSAPrivateKey(stdout,
|
||||
EVP_PKEY_get0_RSA(k->pkey), NULL, NULL, 0,
|
||||
NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
fatal_f("unsupported key type %s", sshkey_type(k));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11-client.c,v 1.19 2023/12/18 14:46:56 djm Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11-client.c,v 1.20 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
|
||||
|
@ -264,14 +264,17 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
|
|||
debug3_f("signing with PKCS11 provider %s", helper->path);
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
goto fail;
|
||||
key = sshkey_new(KEY_UNSPEC);
|
||||
if (key == NULL) {
|
||||
if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
|
||||
error_f("sshkey_new failed");
|
||||
goto fail;
|
||||
}
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL ||
|
||||
EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
|
||||
error_f("pkey setup failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key->type = KEY_RSA;
|
||||
RSA_up_ref(rsa);
|
||||
key->rsa = rsa;
|
||||
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
|
||||
error_fr(r, "encode key");
|
||||
goto fail;
|
||||
|
@ -339,21 +342,22 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
|||
if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1)
|
||||
fatal_f("no helper for PKCS11 key");
|
||||
debug3_f("signing with PKCS11 provider %s", helper->path);
|
||||
nid = sshkey_ecdsa_key_to_nid(ec);
|
||||
if (nid < 0) {
|
||||
error_f("couldn't get curve nid");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key = sshkey_new(KEY_UNSPEC);
|
||||
if (key == NULL) {
|
||||
if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
|
||||
error_f("sshkey_new failed");
|
||||
goto fail;
|
||||
}
|
||||
key->ecdsa = ec;
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL ||
|
||||
EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) {
|
||||
error("pkey setup failed");
|
||||
goto fail;
|
||||
}
|
||||
if ((nid = sshkey_ecdsa_pkey_to_nid(key->pkey)) < 0) {
|
||||
error("couldn't get curve nid");
|
||||
goto fail;
|
||||
}
|
||||
key->ecdsa_nid = nid;
|
||||
key->type = KEY_ECDSA;
|
||||
EC_KEY_up_ref(ec);
|
||||
|
||||
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
|
||||
error_fr(r, "encode key");
|
||||
|
@ -408,16 +412,31 @@ ecdsa_do_finish(EC_KEY *ec)
|
|||
static void
|
||||
wrap_key(struct helper *helper, struct sshkey *k)
|
||||
{
|
||||
RSA *rsa = NULL;
|
||||
EC_KEY *ecdsa = NULL;
|
||||
|
||||
debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path);
|
||||
if (k->type == KEY_RSA) {
|
||||
RSA_set_method(k->rsa, helper->rsa_meth);
|
||||
if ((rsa = EVP_PKEY_get1_RSA(k->pkey)) == NULL)
|
||||
fatal_f("no RSA key");
|
||||
if (RSA_set_method(rsa, helper->rsa_meth) != 1)
|
||||
fatal_f("RSA_set_method failed");
|
||||
if (helper->nrsa++ >= INT_MAX)
|
||||
fatal_f("RSA refcount error");
|
||||
if (EVP_PKEY_set1_RSA(k->pkey, rsa) != 1)
|
||||
fatal_f("EVP_PKEY_set1_RSA failed");
|
||||
RSA_free(rsa);
|
||||
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
} else if (k->type == KEY_ECDSA) {
|
||||
EC_KEY_set_method(k->ecdsa, helper->ec_meth);
|
||||
if ((ecdsa = EVP_PKEY_get1_EC_KEY(k->pkey)) == NULL)
|
||||
fatal_f("no ECDSA key");
|
||||
if (EC_KEY_set_method(ecdsa, helper->ec_meth) != 1)
|
||||
fatal_f("EC_KEY_set_method failed");
|
||||
if (helper->nec++ >= INT_MAX)
|
||||
fatal_f("EC refcount error");
|
||||
if (EVP_PKEY_set1_EC_KEY(k->pkey, ecdsa) != 1)
|
||||
fatal_f("EVP_PKEY_set1_EC_KEY failed");
|
||||
EC_KEY_free(ecdsa);
|
||||
#endif
|
||||
} else
|
||||
fatal_f("unknown key type");
|
||||
|
@ -437,6 +456,10 @@ pkcs11_make_cert(const struct sshkey *priv,
|
|||
struct helper *helper = NULL;
|
||||
struct sshkey *ret;
|
||||
int r;
|
||||
RSA *rsa_priv = NULL, *rsa_cert = NULL;
|
||||
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
EC_KEY *ec_priv = NULL, *ec_cert = NULL;
|
||||
#endif
|
||||
|
||||
debug3_f("private key type %s cert type %s", sshkey_type(priv),
|
||||
sshkey_type(certpub));
|
||||
|
@ -449,24 +472,42 @@ pkcs11_make_cert(const struct sshkey *priv,
|
|||
}
|
||||
*certprivp = NULL;
|
||||
if (priv->type == KEY_RSA) {
|
||||
if ((helper = helper_by_rsa(priv->rsa)) == NULL ||
|
||||
if ((rsa_priv = EVP_PKEY_get1_RSA(priv->pkey)) == NULL)
|
||||
fatal_f("no RSA pkey");
|
||||
if ((helper = helper_by_rsa(rsa_priv)) == 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 ((rsa_cert = EVP_PKEY_get1_RSA(ret->pkey)) == NULL)
|
||||
fatal_f("no RSA cert pkey");
|
||||
if (RSA_set_method(rsa_cert, helper->rsa_meth) != 1)
|
||||
fatal_f("RSA_set_method failed");
|
||||
if (helper->nrsa++ >= INT_MAX)
|
||||
fatal_f("RSA refcount error");
|
||||
if (EVP_PKEY_set1_RSA(ret->pkey, rsa_cert) != 1)
|
||||
fatal_f("EVP_PKEY_set1_RSA failed");
|
||||
RSA_free(rsa_priv);
|
||||
RSA_free(rsa_cert);
|
||||
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
} else if (priv->type == KEY_ECDSA) {
|
||||
if ((helper = helper_by_ec(priv->ecdsa)) == NULL ||
|
||||
if ((ec_priv = EVP_PKEY_get1_EC_KEY(priv->pkey)) == NULL)
|
||||
fatal_f("no EC pkey");
|
||||
if ((helper = helper_by_ec(ec_priv)) == 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 ((ec_cert = EVP_PKEY_get1_EC_KEY(ret->pkey)) == NULL)
|
||||
fatal_f("no EC cert pkey");
|
||||
if (EC_KEY_set_method(ec_cert, helper->ec_meth) != 1)
|
||||
fatal_f("EC_KEY_set_method failed");
|
||||
if (helper->nec++ >= INT_MAX)
|
||||
fatal_f("EC refcount error");
|
||||
if (EVP_PKEY_set1_EC_KEY(ret->pkey, ec_cert) != 1)
|
||||
fatal_f("EVP_PKEY_set1_EC_KEY failed");
|
||||
EC_KEY_free(ec_priv);
|
||||
EC_KEY_free(ec_cert);
|
||||
#endif
|
||||
} else
|
||||
fatal_f("unknown key type %s", sshkey_type(priv));
|
||||
|
@ -485,7 +526,7 @@ pkcs11_make_cert(const struct sshkey *priv,
|
|||
static int
|
||||
pkcs11_start_helper_methods(struct helper *helper)
|
||||
{
|
||||
RSA_METHOD *rsa_meth;
|
||||
RSA_METHOD *rsa_meth = NULL;
|
||||
EC_KEY_METHOD *ec_meth = NULL;
|
||||
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
int (*ec_init)(EC_KEY *key);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11-helper.c,v 1.26 2021/11/18 03:31:44 djm Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11-helper.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
*
|
||||
|
@ -45,6 +45,9 @@
|
|||
#ifdef ENABLE_PKCS11
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
/* borrows code from sftp-server and ssh-agent */
|
||||
|
||||
|
@ -185,10 +188,13 @@ static void
|
|||
process_sign(void)
|
||||
{
|
||||
u_char *blob, *data, *signature = NULL;
|
||||
size_t blen, dlen, slen = 0;
|
||||
int r, ok = -1;
|
||||
struct sshkey *key, *found;
|
||||
size_t blen, dlen;
|
||||
u_int slen = 0;
|
||||
int len, r, ok = -1;
|
||||
struct sshkey *key = NULL, *found;
|
||||
struct sshbuf *msg;
|
||||
RSA *rsa = NULL;
|
||||
EC_KEY *ecdsa = NULL;
|
||||
|
||||
/* XXX support SHA2 signature flags */
|
||||
if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
|
||||
|
@ -198,41 +204,47 @@ process_sign(void)
|
|||
|
||||
if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
|
||||
fatal_fr(r, "decode key");
|
||||
else {
|
||||
if ((found = lookup_key(key)) != NULL) {
|
||||
if ((found = lookup_key(key)) == NULL)
|
||||
goto reply;
|
||||
|
||||
/* XXX use pkey API properly for signing */
|
||||
switch (key->type) {
|
||||
#ifdef WITH_OPENSSL
|
||||
int ret;
|
||||
|
||||
if (key->type == KEY_RSA) {
|
||||
slen = RSA_size(key->rsa);
|
||||
signature = xmalloc(slen);
|
||||
ret = RSA_private_encrypt(dlen, data, signature,
|
||||
found->rsa, RSA_PKCS1_PADDING);
|
||||
if (ret != -1) {
|
||||
slen = ret;
|
||||
ok = 0;
|
||||
}
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
} else if (key->type == KEY_ECDSA) {
|
||||
u_int xslen = ECDSA_size(key->ecdsa);
|
||||
|
||||
signature = xmalloc(xslen);
|
||||
/* "The parameter type is ignored." */
|
||||
ret = ECDSA_sign(-1, data, dlen, signature,
|
||||
&xslen, found->ecdsa);
|
||||
if (ret != 0)
|
||||
ok = 0;
|
||||
else
|
||||
error_f("ECDSA_sign returned %d", ret);
|
||||
slen = xslen;
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
} else
|
||||
error_f("don't know how to sign with key "
|
||||
"type %d", (int)key->type);
|
||||
#endif /* WITH_OPENSSL */
|
||||
case KEY_RSA:
|
||||
if ((rsa = EVP_PKEY_get1_RSA(found->pkey)) == NULL)
|
||||
fatal_f("no RSA in pkey");
|
||||
if ((len = RSA_size(rsa)) < 0)
|
||||
fatal_f("bad RSA length");
|
||||
signature = xmalloc(len);
|
||||
if ((len = RSA_private_encrypt(dlen, data, signature,
|
||||
rsa, RSA_PKCS1_PADDING)) < 0) {
|
||||
error_f("RSA_private_encrypt failed");
|
||||
goto reply;
|
||||
}
|
||||
sshkey_free(key);
|
||||
slen = (u_int)len;
|
||||
break;
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA:
|
||||
if ((ecdsa = EVP_PKEY_get1_EC_KEY(found->pkey)) == NULL)
|
||||
fatal_f("no ECDSA in pkey");
|
||||
if ((len = ECDSA_size(ecdsa)) < 0)
|
||||
fatal_f("bad ECDSA length");
|
||||
slen = (u_int)len;
|
||||
signature = xmalloc(slen);
|
||||
/* "The parameter type is ignored." */
|
||||
if (!ECDSA_sign(-1, data, dlen, signature, &slen, ecdsa)) {
|
||||
error_f("ECDSA_sign failed");
|
||||
goto reply;
|
||||
}
|
||||
break;
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
default:
|
||||
fatal_f("unsupported key type %d", key->type);
|
||||
}
|
||||
/* success */
|
||||
ok = 0;
|
||||
reply:
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal_f("sshbuf_new failed");
|
||||
if (ok == 0) {
|
||||
|
@ -243,6 +255,9 @@ process_sign(void)
|
|||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
|
||||
fatal_fr(r, "compose failure response");
|
||||
}
|
||||
sshkey_free(key);
|
||||
RSA_free(rsa);
|
||||
EC_KEY_free(ecdsa);
|
||||
free(data);
|
||||
free(blob);
|
||||
free(signature);
|
||||
|
|
42
ssh-pkcs11.c
42
ssh-pkcs11.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-pkcs11.c,v 1.62 2024/04/02 12:22:38 deraadt Exp $ */
|
||||
/* $OpenBSD: ssh-pkcs11.c,v 1.63 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
|
||||
|
@ -502,8 +502,10 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
|||
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
||||
}
|
||||
|
||||
RSA_set_method(rsa, rsa_method);
|
||||
RSA_set_ex_data(rsa, rsa_idx, k11);
|
||||
if (RSA_set_method(rsa, rsa_method) != 1)
|
||||
fatal_f("RSA_set_method failed");
|
||||
if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1)
|
||||
fatal_f("RSA_set_ex_data failed");
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -615,8 +617,10 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
|||
k11->keyid = xmalloc(k11->keyid_len);
|
||||
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
||||
}
|
||||
EC_KEY_set_method(ec, ec_key_method);
|
||||
EC_KEY_set_ex_data(ec, ec_key_idx, k11);
|
||||
if (EC_KEY_set_method(ec, ec_key_method) != 1)
|
||||
fatal_f("EC_KEY_set_method failed");
|
||||
if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1)
|
||||
fatal_f("EC_KEY_set_ex_data failed");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -803,11 +807,14 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
key->ecdsa = ec;
|
||||
EVP_PKEY_free(key->pkey);
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal("EVP_PKEY_new failed");
|
||||
if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1)
|
||||
fatal("EVP_PKEY_set1_EC_KEY failed");
|
||||
key->ecdsa_nid = nid;
|
||||
key->type = KEY_ECDSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
ec = NULL; /* now owned by key */
|
||||
|
||||
fail:
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -899,10 +906,13 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
key->rsa = rsa;
|
||||
EVP_PKEY_free(key->pkey);
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal("EVP_PKEY_new failed");
|
||||
if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
|
||||
fatal("EVP_PKEY_set1_RSA failed");
|
||||
key->type = KEY_RSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
rsa = NULL; /* now owned by key */
|
||||
|
||||
fail:
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -1014,10 +1024,13 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
|||
goto out;
|
||||
}
|
||||
|
||||
key->rsa = rsa;
|
||||
EVP_PKEY_free(key->pkey);
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal("EVP_PKEY_new failed");
|
||||
if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
|
||||
fatal("EVP_PKEY_set1_RSA failed");
|
||||
key->type = KEY_RSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
rsa = NULL; /* now owned by key */
|
||||
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
|
||||
if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
|
||||
|
@ -1044,11 +1057,14 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
|||
goto out;
|
||||
}
|
||||
|
||||
key->ecdsa = ec;
|
||||
EVP_PKEY_free(key->pkey);
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL)
|
||||
fatal("EVP_PKEY_new failed");
|
||||
if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1)
|
||||
fatal("EVP_PKEY_set1_EC_KEY failed");
|
||||
key->ecdsa_nid = nid;
|
||||
key->type = KEY_ECDSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
ec = NULL; /* now owned by key */
|
||||
#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
} else {
|
||||
error("unknown certificate key type");
|
||||
|
|
389
ssh-rsa.c
389
ssh-rsa.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-rsa.c,v 1.79 2023/03/05 05:34:09 dtucker Exp $ */
|
||||
/* $OpenBSD: ssh-rsa.c,v 1.80 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
|
||||
*
|
||||
|
@ -36,23 +36,18 @@
|
|||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
|
||||
|
||||
static u_int
|
||||
ssh_rsa_size(const struct sshkey *key)
|
||||
ssh_rsa_size(const struct sshkey *k)
|
||||
{
|
||||
const BIGNUM *rsa_n;
|
||||
|
||||
if (key->rsa == NULL)
|
||||
if (k->pkey == NULL)
|
||||
return 0;
|
||||
RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
|
||||
return BN_num_bits(rsa_n);
|
||||
return EVP_PKEY_bits(k->pkey);
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_rsa_alloc(struct sshkey *k)
|
||||
{
|
||||
if ((k->rsa = RSA_new()) == NULL)
|
||||
if ((k->pkey = EVP_PKEY_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,29 +55,16 @@ ssh_rsa_alloc(struct sshkey *k)
|
|||
static void
|
||||
ssh_rsa_cleanup(struct sshkey *k)
|
||||
{
|
||||
RSA_free(k->rsa);
|
||||
k->rsa = NULL;
|
||||
EVP_PKEY_free(k->pkey);
|
||||
k->pkey = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
{
|
||||
const BIGNUM *rsa_e_a, *rsa_n_a;
|
||||
const BIGNUM *rsa_e_b, *rsa_n_b;
|
||||
|
||||
if (a->rsa == NULL || b->rsa == NULL)
|
||||
if (a->pkey == NULL || b->pkey == NULL)
|
||||
return 0;
|
||||
RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
|
||||
RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
|
||||
if (rsa_e_a == NULL || rsa_e_b == NULL)
|
||||
return 0;
|
||||
if (rsa_n_a == NULL || rsa_n_b == NULL)
|
||||
return 0;
|
||||
if (BN_cmp(rsa_e_a, rsa_e_b) != 0)
|
||||
return 0;
|
||||
if (BN_cmp(rsa_n_a, rsa_n_b) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
return EVP_PKEY_cmp(a->pkey, b->pkey) == 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -91,10 +73,14 @@ ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
|||
{
|
||||
int r;
|
||||
const BIGNUM *rsa_n, *rsa_e;
|
||||
const RSA *rsa;
|
||||
|
||||
if (key->rsa == NULL)
|
||||
if (key->pkey == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
|
||||
if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
|
||||
if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, rsa_n)) != 0)
|
||||
return r;
|
||||
|
@ -108,10 +94,13 @@ ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
|
|||
{
|
||||
int r;
|
||||
const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
|
||||
const RSA *rsa;
|
||||
|
||||
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
|
||||
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
|
||||
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
|
||||
if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
|
||||
RSA_get0_factors(rsa, &rsa_p, &rsa_q);
|
||||
RSA_get0_crt_params(rsa, NULL, NULL, &rsa_iqmp);
|
||||
|
||||
if (!sshkey_is_cert(key)) {
|
||||
/* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
|
||||
|
@ -131,28 +120,36 @@ ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
|
|||
static int
|
||||
ssh_rsa_generate(struct sshkey *k, int bits)
|
||||
{
|
||||
RSA *private = NULL;
|
||||
BIGNUM *f4 = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *res = NULL;
|
||||
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
|
||||
bits > SSHBUF_MAX_BIGNUM * 8)
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
|
||||
|
||||
if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (!BN_set_word(f4, RSA_F4) ||
|
||||
!RSA_generate_key_ex(private, bits, f4, NULL)) {
|
||||
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
k->rsa = private;
|
||||
private = NULL;
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) {
|
||||
ret = SSH_ERR_KEY_LENGTH;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
k->pkey = res;
|
||||
ret = 0;
|
||||
out:
|
||||
RSA_free(private);
|
||||
BN_free(f4);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -162,21 +159,33 @@ ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
|
|||
const BIGNUM *rsa_n, *rsa_e;
|
||||
BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
const RSA *rsa_from;
|
||||
RSA *rsa_to = NULL;
|
||||
|
||||
RSA_get0_key(from->rsa, &rsa_n, &rsa_e, NULL);
|
||||
if ((rsa_from = EVP_PKEY_get0_RSA(from->pkey)) == NULL ||
|
||||
(rsa_to = RSA_new()) == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
RSA_get0_key(rsa_from, &rsa_n, &rsa_e, NULL);
|
||||
if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
|
||||
(rsa_e_dup = BN_dup(rsa_e)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (!RSA_set0_key(to->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
|
||||
if (!RSA_set0_key(rsa_to, rsa_n_dup, rsa_e_dup, NULL)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_n_dup = rsa_e_dup = NULL; /* transferred */
|
||||
|
||||
if (EVP_PKEY_set1_RSA(to->pkey, rsa_to) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
RSA_free(rsa_to);
|
||||
BN_clear_free(rsa_n_dup);
|
||||
BN_clear_free(rsa_e_dup);
|
||||
return r;
|
||||
|
@ -188,25 +197,34 @@ ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
|
|||
{
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL;
|
||||
RSA *rsa = NULL;
|
||||
|
||||
if ((rsa = RSA_new()) == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
|
||||
if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
|
||||
sshbuf_get_bignum2(b, &rsa_n) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
|
||||
if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_n = rsa_e = NULL; /* transferred */
|
||||
if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, key->rsa, 8);
|
||||
RSA_print_fp(stderr, rsa, 8);
|
||||
#endif
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
RSA_free(rsa);
|
||||
BN_clear_free(rsa_n);
|
||||
BN_clear_free(rsa_e);
|
||||
return ret;
|
||||
|
@ -219,13 +237,25 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
|
|||
int r;
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
|
||||
BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
|
||||
BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
|
||||
RSA *rsa = NULL;
|
||||
|
||||
/* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */
|
||||
if (!sshkey_is_cert(key)) {
|
||||
if (sshkey_is_cert(key)) {
|
||||
/* sshkey_private_deserialize already has pubkey from cert */
|
||||
if ((rsa = EVP_PKEY_get1_RSA(key->pkey)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if ((rsa = RSA_new()) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* Note: can't reuse ssh_rsa_deserialize_public: e,n vs. n,e */
|
||||
if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
|
||||
(r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
|
||||
goto out;
|
||||
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
|
||||
if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
@ -236,33 +266,46 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
|
|||
(r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
|
||||
(r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
|
||||
goto out;
|
||||
if (!RSA_set0_key(key->rsa, NULL, NULL, rsa_d)) {
|
||||
if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
|
||||
rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
|
||||
goto out;
|
||||
if (!RSA_set0_key(rsa, NULL, NULL, rsa_d)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_d = NULL; /* transferred */
|
||||
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) {
|
||||
if (!RSA_set0_factors(rsa, rsa_p, rsa_q)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_p = rsa_q = NULL; /* transferred */
|
||||
if ((r = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
|
||||
goto out;
|
||||
if (RSA_blinding_on(key->rsa, NULL) != 1) {
|
||||
if (!RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL;
|
||||
if (RSA_blinding_on(rsa, NULL) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
RSA_free(rsa);
|
||||
BN_clear_free(rsa_n);
|
||||
BN_clear_free(rsa_e);
|
||||
BN_clear_free(rsa_d);
|
||||
BN_clear_free(rsa_p);
|
||||
BN_clear_free(rsa_q);
|
||||
BN_clear_free(rsa_iqmp);
|
||||
BN_clear_free(rsa_dmp1);
|
||||
BN_clear_free(rsa_dmq1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -317,45 +360,23 @@ rsa_hash_id_from_keyname(const char *alg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
rsa_hash_alg_nid(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
return NID_sha1;
|
||||
case SSH_DIGEST_SHA256:
|
||||
return NID_sha256;
|
||||
case SSH_DIGEST_SHA512:
|
||||
return NID_sha512;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
|
||||
ssh_rsa_complete_crt_parameters(const BIGNUM *rsa_d, const BIGNUM *rsa_p,
|
||||
const BIGNUM *rsa_q, const BIGNUM *rsa_iqmp, BIGNUM **rsa_dmp1,
|
||||
BIGNUM **rsa_dmq1)
|
||||
{
|
||||
const BIGNUM *rsa_p, *rsa_q, *rsa_d;
|
||||
BIGNUM *aux = NULL, *d_consttime = NULL;
|
||||
BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int r;
|
||||
|
||||
if (key == NULL || key->rsa == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_RSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
|
||||
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
|
||||
|
||||
*rsa_dmq1 = *rsa_dmp1 = NULL;
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((aux = BN_new()) == NULL ||
|
||||
(rsa_dmq1 = BN_new()) == NULL ||
|
||||
(rsa_dmp1 = BN_new()) == NULL)
|
||||
(*rsa_dmq1 = BN_new()) == NULL ||
|
||||
(*rsa_dmp1 = BN_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((d_consttime = BN_dup(rsa_d)) == NULL ||
|
||||
(rsa_iqmp = BN_dup(iqmp)) == NULL) {
|
||||
if ((d_consttime = BN_dup(rsa_d)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -363,25 +384,17 @@ ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
|
|||
BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
|
||||
|
||||
if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) ||
|
||||
(BN_mod(*rsa_dmq1, d_consttime, aux, ctx) == 0) ||
|
||||
(BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) {
|
||||
(BN_mod(*rsa_dmp1, d_consttime, aux, ctx) == 0)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
BN_clear_free(aux);
|
||||
BN_clear_free(d_consttime);
|
||||
BN_clear_free(rsa_dmp1);
|
||||
BN_clear_free(rsa_dmq1);
|
||||
BN_clear_free(rsa_iqmp);
|
||||
BN_CTX_free(ctx);
|
||||
return r;
|
||||
}
|
||||
|
@ -393,11 +406,10 @@ ssh_rsa_sign(struct sshkey *key,
|
|||
const u_char *data, size_t datalen,
|
||||
const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
|
||||
{
|
||||
const BIGNUM *rsa_n;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
|
||||
size_t slen = 0;
|
||||
u_int hlen, len;
|
||||
int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
u_char *sig = NULL;
|
||||
size_t diff, len = 0;
|
||||
int slen = 0;
|
||||
int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
struct sshbuf *b = NULL;
|
||||
|
||||
if (lenp != NULL)
|
||||
|
@ -409,41 +421,28 @@ ssh_rsa_sign(struct sshkey *key,
|
|||
hash_alg = SSH_DIGEST_SHA1;
|
||||
else
|
||||
hash_alg = rsa_hash_id_from_keyname(alg);
|
||||
if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
|
||||
|
||||
if (key == NULL || key->pkey == NULL || hash_alg == -1 ||
|
||||
sshkey_type_plain(key->type) != KEY_RSA)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
|
||||
if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
slen = RSA_size(key->rsa);
|
||||
slen = EVP_PKEY_size(key->pkey);
|
||||
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
|
||||
/* hash the data */
|
||||
nid = rsa_hash_alg_nid(hash_alg);
|
||||
if ((hlen = ssh_digest_bytes(hash_alg)) == 0)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sig, &len,
|
||||
data, datalen)) < 0)
|
||||
goto out;
|
||||
|
||||
if ((sig = malloc(slen)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if (len < slen) {
|
||||
size_t diff = slen - len;
|
||||
if (len < (size_t)slen) {
|
||||
diff = slen - len;
|
||||
memmove(sig + diff, sig, len);
|
||||
explicit_bzero(sig, diff);
|
||||
} else if (len > slen) {
|
||||
} else if (len > (size_t)slen) {
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* encode signature */
|
||||
if ((b = sshbuf_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
|
@ -464,7 +463,6 @@ ssh_rsa_sign(struct sshkey *key,
|
|||
*lenp = len;
|
||||
ret = 0;
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
freezero(sig, slen);
|
||||
sshbuf_free(b);
|
||||
return ret;
|
||||
|
@ -476,19 +474,17 @@ ssh_rsa_verify(const struct sshkey *key,
|
|||
const u_char *data, size_t dlen, const char *alg, u_int compat,
|
||||
struct sshkey_sig_details **detailsp)
|
||||
{
|
||||
const BIGNUM *rsa_n;
|
||||
char *sigtype = NULL;
|
||||
int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
size_t len = 0, diff, modlen, hlen;
|
||||
size_t len = 0, diff, modlen, rsasize;
|
||||
struct sshbuf *b = NULL;
|
||||
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
|
||||
|
||||
if (key == NULL || key->rsa == NULL ||
|
||||
if (key == NULL || key->pkey == NULL ||
|
||||
sshkey_type_plain(key->type) != KEY_RSA ||
|
||||
sig == NULL || siglen == 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
|
||||
if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
|
||||
if ((b = sshbuf_from(sig, siglen)) == NULL)
|
||||
|
@ -524,7 +520,7 @@ ssh_rsa_verify(const struct sshkey *key,
|
|||
goto out;
|
||||
}
|
||||
/* RSA_verify expects a signature of RSA_size */
|
||||
modlen = RSA_size(key->rsa);
|
||||
modlen = EVP_PKEY_size(key->pkey);
|
||||
if (len > modlen) {
|
||||
ret = SSH_ERR_KEY_BITS_MISMATCH;
|
||||
goto out;
|
||||
|
@ -540,16 +536,16 @@ ssh_rsa_verify(const struct sshkey *key,
|
|||
explicit_bzero(sigblob, diff);
|
||||
len = modlen;
|
||||
}
|
||||
if ((hlen = ssh_digest_bytes(hash_alg)) == 0) {
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
rsasize = EVP_PKEY_size(key->pkey);
|
||||
if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
|
||||
len == 0 || len > rsasize) {
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = ssh_digest_memory(hash_alg, data, dlen,
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
ret = sshkey_pkey_digest_verify(key->pkey, hash_alg, data, dlen,
|
||||
sigblob, len);
|
||||
|
||||
ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len,
|
||||
key->rsa);
|
||||
out:
|
||||
freezero(sigblob, len);
|
||||
free(sigtype);
|
||||
|
@ -558,125 +554,6 @@ ssh_rsa_verify(const struct sshkey *key,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* See:
|
||||
* http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
|
||||
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
|
||||
*/
|
||||
|
||||
/*
|
||||
* id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
|
||||
* oiw(14) secsig(3) algorithms(2) 26 }
|
||||
*/
|
||||
static const u_char id_sha1[] = {
|
||||
0x30, 0x21, /* type Sequence, length 0x21 (33) */
|
||||
0x30, 0x09, /* type Sequence, length 0x09 */
|
||||
0x06, 0x05, /* type OID, length 0x05 */
|
||||
0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
|
||||
0x05, 0x00, /* NULL */
|
||||
0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
|
||||
};
|
||||
|
||||
/*
|
||||
* See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
|
||||
* id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
|
||||
* id-sha256(1) }
|
||||
*/
|
||||
static const u_char id_sha256[] = {
|
||||
0x30, 0x31, /* type Sequence, length 0x31 (49) */
|
||||
0x30, 0x0d, /* type Sequence, length 0x0d (13) */
|
||||
0x06, 0x09, /* type OID, length 0x09 */
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
|
||||
0x05, 0x00, /* NULL */
|
||||
0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
|
||||
};
|
||||
|
||||
/*
|
||||
* See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
|
||||
* id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
|
||||
* id-sha256(3) }
|
||||
*/
|
||||
static const u_char id_sha512[] = {
|
||||
0x30, 0x51, /* type Sequence, length 0x51 (81) */
|
||||
0x30, 0x0d, /* type Sequence, length 0x0d (13) */
|
||||
0x06, 0x09, /* type OID, length 0x09 */
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
|
||||
0x05, 0x00, /* NULL */
|
||||
0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
|
||||
};
|
||||
|
||||
static int
|
||||
rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
|
||||
{
|
||||
switch (hash_alg) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
*oidp = id_sha1;
|
||||
*oidlenp = sizeof(id_sha1);
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
*oidp = id_sha256;
|
||||
*oidlenp = sizeof(id_sha256);
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
*oidp = id_sha512;
|
||||
*oidlenp = sizeof(id_sha512);
|
||||
break;
|
||||
default:
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
|
||||
u_char *sigbuf, size_t siglen, RSA *rsa)
|
||||
{
|
||||
size_t rsasize = 0, oidlen = 0, hlen = 0;
|
||||
int ret, len, oidmatch, hashmatch;
|
||||
const u_char *oid = NULL;
|
||||
u_char *decrypted = NULL;
|
||||
|
||||
if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
|
||||
return ret;
|
||||
ret = SSH_ERR_INTERNAL_ERROR;
|
||||
hlen = ssh_digest_bytes(hash_alg);
|
||||
if (hashlen != hlen) {
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
rsasize = RSA_size(rsa);
|
||||
if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
|
||||
siglen == 0 || siglen > rsasize) {
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
if ((decrypted = malloc(rsasize)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto done;
|
||||
}
|
||||
if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
|
||||
RSA_PKCS1_PADDING)) < 0) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (len < 0 || (size_t)len != hlen + oidlen) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto done;
|
||||
}
|
||||
oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
|
||||
hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
|
||||
if (!oidmatch || !hashmatch) {
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
done:
|
||||
freezero(decrypted, rsasize);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
|
||||
/* .size = */ ssh_rsa_size,
|
||||
/* .alloc = */ ssh_rsa_alloc,
|
||||
|
|
29
ssh-sk.c
29
ssh-sk.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-sk.c,v 1.40 2023/07/19 14:02:27 djm Exp $ */
|
||||
/* $OpenBSD: ssh-sk.c,v 1.41 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2019 Google LLC
|
||||
*
|
||||
|
@ -32,6 +32,7 @@
|
|||
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/evp.h>
|
||||
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
|
||||
|
||||
#include "log.h"
|
||||
|
@ -207,7 +208,9 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
|
|||
{
|
||||
struct sshkey *key = NULL;
|
||||
struct sshbuf *b = NULL;
|
||||
EC_KEY *ecdsa = NULL;
|
||||
EC_POINT *q = NULL;
|
||||
const EC_GROUP *g = NULL;
|
||||
int r;
|
||||
|
||||
*keyp = NULL;
|
||||
|
@ -217,8 +220,9 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
|
|||
goto out;
|
||||
}
|
||||
key->ecdsa_nid = NID_X9_62_prime256v1;
|
||||
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
|
||||
(q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL ||
|
||||
if ((ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
|
||||
(g = EC_KEY_get0_group(ecdsa)) == NULL ||
|
||||
(q = EC_POINT_new(g)) == NULL ||
|
||||
(b = sshbuf_new()) == NULL) {
|
||||
error_f("allocation failed");
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
|
@ -229,30 +233,41 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
|
|||
error_fr(r, "sshbuf_put_string");
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) {
|
||||
if ((r = sshbuf_get_ec(b, q, g)) != 0) {
|
||||
error_fr(r, "parse");
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
|
||||
if (sshkey_ec_validate_public(g, q) != 0) {
|
||||
error("Authenticator returned invalid ECDSA key");
|
||||
r = SSH_ERR_KEY_INVALID_EC_VALUE;
|
||||
goto out;
|
||||
}
|
||||
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
|
||||
if (EC_KEY_set_public_key(ecdsa, q) != 1) {
|
||||
/* XXX assume it is a allocation error */
|
||||
error_f("allocation failed");
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((key->pkey = EVP_PKEY_new()) == NULL) {
|
||||
error_f("allocation failed");
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_set1_EC_KEY(key->pkey, ecdsa) != 1) {
|
||||
error_f("Assigning EC_KEY failed");
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
*keyp = key;
|
||||
key = NULL; /* transferred */
|
||||
r = 0;
|
||||
out:
|
||||
EC_POINT_free(q);
|
||||
sshkey_free(key);
|
||||
sshbuf_free(b);
|
||||
EC_KEY_free(ecdsa);
|
||||
EC_POINT_free(q);
|
||||
return r;
|
||||
}
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshbuf-getput-crypto.c,v 1.11 2024/02/01 02:37:33 djm Exp $ */
|
||||
/* $OpenBSD: sshbuf-getput-crypto.c,v 1.12 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller
|
||||
*
|
||||
|
@ -177,4 +177,13 @@ sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
|
|||
EC_KEY_get0_group(v));
|
||||
}
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
int
|
||||
sshbuf_put_ec_pkey(struct sshbuf *buf, EVP_PKEY *pkey)
|
||||
{
|
||||
const EC_KEY *ec;
|
||||
|
||||
if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
return sshbuf_put_eckey(buf, ec);
|
||||
}
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
|
4
sshbuf.h
4
sshbuf.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshbuf.h,v 1.28 2022/12/02 04:40:27 djm Exp $ */
|
||||
/* $OpenBSD: sshbuf.h,v 1.29 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Damien Miller
|
||||
*
|
||||
|
@ -23,6 +23,7 @@
|
|||
#include <stdio.h>
|
||||
#ifdef WITH_OPENSSL
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/evp.h>
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
# include <openssl/ec.h>
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
|
@ -223,6 +224,7 @@ int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g);
|
|||
int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v);
|
||||
int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g);
|
||||
int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v);
|
||||
int sshbuf_put_ec_pkey(struct sshbuf *buf, EVP_PKEY *pkey);
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
|
|
231
sshkey.c
231
sshkey.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshkey.c,v 1.142 2024/01/11 01:45:36 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.c,v 1.143 2024/08/15 00:51:51 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
|
@ -481,6 +481,98 @@ sshkey_type_certified(int type)
|
|||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
static const EVP_MD *
|
||||
ssh_digest_to_md(int hash_alg)
|
||||
{
|
||||
switch (hash_alg) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
return EVP_sha1();
|
||||
case SSH_DIGEST_SHA256:
|
||||
return EVP_sha256();
|
||||
case SSH_DIGEST_SHA384:
|
||||
return EVP_sha384();
|
||||
case SSH_DIGEST_SHA512:
|
||||
return EVP_sha512();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
sshkey_pkey_digest_sign(EVP_PKEY *pkey, int hash_alg, u_char **sigp,
|
||||
size_t *lenp, const u_char *data, size_t datalen)
|
||||
{
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
u_char *sig = NULL;
|
||||
int ret;
|
||||
size_t slen;
|
||||
const EVP_MD *evpmd;
|
||||
|
||||
*sigp = NULL;
|
||||
*lenp = 0;
|
||||
|
||||
slen = EVP_PKEY_size(pkey);
|
||||
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM ||
|
||||
(evpmd = ssh_digest_to_md(hash_alg)) == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
if ((sig = malloc(slen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
if ((ctx = EVP_MD_CTX_new()) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (EVP_DigestSignInit(ctx, NULL, evpmd, NULL, pkey) != 1 ||
|
||||
EVP_DigestSign(ctx, sig, &slen, data, datalen) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*sigp = sig;
|
||||
*lenp = slen;
|
||||
/* Now owned by the caller */
|
||||
sig = NULL;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
free(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
sshkey_pkey_digest_verify(EVP_PKEY *pkey, int hash_alg, const u_char *data,
|
||||
size_t datalen, u_char *sigbuf, size_t siglen)
|
||||
{
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
const EVP_MD *evpmd;
|
||||
|
||||
if ((evpmd = ssh_digest_to_md(hash_alg)) == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((ctx = EVP_MD_CTX_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if (EVP_DigestVerifyInit(ctx, NULL, evpmd, NULL, pkey) != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
switch (EVP_DigestVerify(ctx, sigbuf, siglen, data, datalen)) {
|
||||
case 1:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0:
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
break;
|
||||
default:
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* XXX: these are really begging for a table-driven approach */
|
||||
int
|
||||
sshkey_curve_name_to_nid(const char *name)
|
||||
|
@ -1331,14 +1423,12 @@ int
|
|||
sshkey_check_rsa_length(const struct sshkey *k, int min_size)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
const BIGNUM *rsa_n;
|
||||
int nbits;
|
||||
|
||||
if (k == NULL || k->rsa == NULL ||
|
||||
if (k == NULL || k->pkey == NULL ||
|
||||
(k->type != KEY_RSA && k->type != KEY_RSA_CERT))
|
||||
return 0;
|
||||
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
|
||||
nbits = BN_num_bits(rsa_n);
|
||||
nbits = EVP_PKEY_bits(k->pkey);
|
||||
if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
|
||||
(min_size > 0 && nbits < min_size))
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
|
@ -1346,53 +1436,26 @@ sshkey_check_rsa_length(const struct sshkey *k, int min_size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
|
||||
int
|
||||
sshkey_ecdsa_key_to_nid(EC_KEY *k)
|
||||
sshkey_ecdsa_key_to_nid(const EC_KEY *k)
|
||||
{
|
||||
EC_GROUP *eg;
|
||||
int nids[] = {
|
||||
NID_X9_62_prime256v1,
|
||||
NID_secp384r1,
|
||||
# ifdef OPENSSL_HAS_NISTP521
|
||||
NID_secp521r1,
|
||||
# endif /* OPENSSL_HAS_NISTP521 */
|
||||
-1
|
||||
};
|
||||
const EC_GROUP *g;
|
||||
int nid;
|
||||
u_int i;
|
||||
const EC_GROUP *g = EC_KEY_get0_group(k);
|
||||
|
||||
/*
|
||||
* The group may be stored in a ASN.1 encoded private key in one of two
|
||||
* ways: as a "named group", which is reconstituted by ASN.1 object ID
|
||||
* or explicit group parameters encoded into the key blob. Only the
|
||||
* "named group" case sets the group NID for us, but we can figure
|
||||
* it out for the other case by comparing against all the groups that
|
||||
* are supported.
|
||||
*/
|
||||
if ((nid = EC_GROUP_get_curve_name(g)) > 0)
|
||||
return nid;
|
||||
for (i = 0; nids[i] != -1; i++) {
|
||||
if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
|
||||
return -1;
|
||||
if (EC_GROUP_cmp(g, eg, NULL) == 0)
|
||||
break;
|
||||
EC_GROUP_free(eg);
|
||||
}
|
||||
if (nids[i] != -1) {
|
||||
/* Use the group with the NID attached */
|
||||
EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
|
||||
if (EC_KEY_set_group(k, eg) != 1) {
|
||||
EC_GROUP_free(eg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return nids[i];
|
||||
if (k == NULL || (g = EC_KEY_get0_group(k)) == NULL)
|
||||
return -1;
|
||||
if ((nid = EC_GROUP_get_curve_name(g)) <= 0)
|
||||
return -1;
|
||||
return nid;
|
||||
}
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
int
|
||||
sshkey_ecdsa_pkey_to_nid(EVP_PKEY *pkey)
|
||||
{
|
||||
return sshkey_ecdsa_key_to_nid(EVP_PKEY_get0_EC_KEY(pkey));
|
||||
}
|
||||
#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
|
||||
|
||||
int
|
||||
sshkey_generate(int type, u_int bits, struct sshkey **keyp)
|
||||
|
@ -3226,10 +3289,6 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
|
|||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshkey_unshield_private(key)) != 0)
|
||||
goto out;
|
||||
|
||||
|
@ -3240,6 +3299,10 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
|
|||
success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
|
||||
cipher, passphrase, len, NULL, NULL);
|
||||
} else {
|
||||
if ((pkey = EVP_PKEY_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
success = EVP_PKEY_set1_DSA(pkey, key->dsa);
|
||||
}
|
||||
break;
|
||||
|
@ -3247,19 +3310,25 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
|
|||
#ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA:
|
||||
if (format == SSHKEY_PRIVATE_PEM) {
|
||||
success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
|
||||
success = PEM_write_bio_ECPrivateKey(bio,
|
||||
EVP_PKEY_get0_EC_KEY(key->pkey),
|
||||
cipher, passphrase, len, NULL, NULL);
|
||||
} else {
|
||||
success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
|
||||
pkey = key->pkey;
|
||||
EVP_PKEY_up_ref(key->pkey);
|
||||
success = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case KEY_RSA:
|
||||
if (format == SSHKEY_PRIVATE_PEM) {
|
||||
success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
|
||||
success = PEM_write_bio_RSAPrivateKey(bio,
|
||||
EVP_PKEY_get0_RSA(key->pkey),
|
||||
cipher, passphrase, len, NULL, NULL);
|
||||
} else {
|
||||
success = EVP_PKEY_set1_RSA(pkey, key->rsa);
|
||||
pkey = key->pkey;
|
||||
EVP_PKEY_up_ref(key->pkey);
|
||||
success = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -3428,6 +3497,8 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
struct sshkey *prv = NULL;
|
||||
BIO *bio = NULL;
|
||||
int r;
|
||||
RSA *rsa = NULL;
|
||||
EC_KEY *ecdsa = NULL;
|
||||
|
||||
if (keyp != NULL)
|
||||
*keyp = NULL;
|
||||
|
@ -3461,15 +3532,21 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
prv->rsa = EVP_PKEY_get1_RSA(pk);
|
||||
prv->type = KEY_RSA;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, prv->rsa, 8);
|
||||
#endif
|
||||
if (RSA_blinding_on(prv->rsa, NULL) != 1) {
|
||||
if ((rsa = EVP_PKEY_get1_RSA(pk)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
prv->type = KEY_RSA;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, rsa, 8);
|
||||
#endif
|
||||
if (RSA_blinding_on(rsa, NULL) != 1 ||
|
||||
EVP_PKEY_set1_RSA(pk, rsa) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
EVP_PKEY_up_ref(pk);
|
||||
prv->pkey = pk;
|
||||
if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
|
||||
goto out;
|
||||
#ifdef WITH_DSA
|
||||
|
@ -3492,21 +3569,25 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
|
||||
if ((prv->ecdsa_nid = sshkey_ecdsa_fixup_group(pk)) == -1 ||
|
||||
(ecdsa = EVP_PKEY_get1_EC_KEY(pk)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
prv->type = KEY_ECDSA;
|
||||
prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
|
||||
if (prv->ecdsa_nid == -1 ||
|
||||
sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
|
||||
sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
|
||||
EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
|
||||
sshkey_ec_validate_private(prv->ecdsa) != 0) {
|
||||
if (sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
|
||||
sshkey_ec_validate_public(EC_KEY_get0_group(ecdsa),
|
||||
EC_KEY_get0_public_key(ecdsa)) != 0 ||
|
||||
sshkey_ec_validate_private(ecdsa) != 0) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
# ifdef DEBUG_PK
|
||||
if (prv != NULL && prv->ecdsa != NULL)
|
||||
sshkey_dump_ec_key(prv->ecdsa);
|
||||
# endif
|
||||
EVP_PKEY_up_ref(pk);
|
||||
prv->pkey = pk;
|
||||
#ifdef DEBUG_PK
|
||||
if (prv != NULL && prv->pkey != NULL)
|
||||
sshkey_dump_ec_key(EVP_PKEY_get0_EC_KEY(prv->pkey));
|
||||
#endif
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
#ifdef OPENSSL_HAS_ED25519
|
||||
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_ED25519 &&
|
||||
|
@ -3541,9 +3622,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
/* Append the public key to our private key */
|
||||
memcpy(prv->ed25519_sk + (ED25519_SK_SZ - ED25519_PK_SZ),
|
||||
prv->ed25519_pk, ED25519_PK_SZ);
|
||||
# ifdef DEBUG_PK
|
||||
#ifdef DEBUG_PK
|
||||
sshbuf_dump_data(prv->ed25519_sk, ED25519_SK_SZ, stderr);
|
||||
# endif
|
||||
#endif
|
||||
#endif /* OPENSSL_HAS_ED25519 */
|
||||
} else {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
|
@ -3557,6 +3638,8 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
|||
out:
|
||||
BIO_free(bio);
|
||||
EVP_PKEY_free(pk);
|
||||
RSA_free(rsa);
|
||||
EC_KEY_free(ecdsa);
|
||||
sshkey_free(prv);
|
||||
return r;
|
||||
}
|
||||
|
|
26
sshkey.h
26
sshkey.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sshkey.h,v 1.63 2024/05/17 06:42:04 jsg Exp $ */
|
||||
/* $OpenBSD: sshkey.h,v 1.64 2024/08/15 00:51:51 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
|
@ -31,6 +31,7 @@
|
|||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/evp.h>
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
# include <openssl/ec.h>
|
||||
# include <openssl/ecdsa.h>
|
||||
|
@ -47,6 +48,7 @@
|
|||
# define EC_KEY void
|
||||
# define EC_GROUP void
|
||||
# define EC_POINT void
|
||||
# define EVP_PKEY void
|
||||
#define SSH_OPENSSL_VERSION "without OpenSSL"
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
|
@ -125,13 +127,12 @@ struct sshkey_cert {
|
|||
struct sshkey {
|
||||
int type;
|
||||
int flags;
|
||||
/* KEY_RSA */
|
||||
RSA *rsa;
|
||||
/* KEY_DSA */
|
||||
DSA *dsa;
|
||||
/* KEY_ECDSA and KEY_ECDSA_SK */
|
||||
int ecdsa_nid; /* NID of curve */
|
||||
EC_KEY *ecdsa;
|
||||
/* libcrypto-backed keys */
|
||||
EVP_PKEY *pkey;
|
||||
/* KEY_ED25519 and KEY_ED25519_SK */
|
||||
u_char *ed25519_sk;
|
||||
u_char *ed25519_pk;
|
||||
|
@ -258,7 +259,8 @@ int sshkey_curve_name_to_nid(const char *);
|
|||
const char * sshkey_curve_nid_to_name(int);
|
||||
u_int sshkey_curve_nid_to_bits(int);
|
||||
int sshkey_ecdsa_bits_to_nid(int);
|
||||
int sshkey_ecdsa_key_to_nid(EC_KEY *);
|
||||
int sshkey_ecdsa_key_to_nid(const EC_KEY *);
|
||||
int sshkey_ecdsa_pkey_to_nid(EVP_PKEY *);
|
||||
int sshkey_ec_nid_to_hash_alg(int nid);
|
||||
int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
||||
int sshkey_ec_validate_private(const EC_KEY *);
|
||||
|
@ -287,6 +289,12 @@ int sshkey_check_sigtype(const u_char *, size_t, const char *);
|
|||
const char *sshkey_sigalg_by_name(const char *);
|
||||
int sshkey_get_sigtype(const u_char *, size_t, char **);
|
||||
|
||||
/* Signing and verification backend for libcrypto-backed keys */
|
||||
int sshkey_pkey_digest_sign(EVP_PKEY*, int, u_char **,
|
||||
size_t *, const u_char *, size_t);
|
||||
int sshkey_pkey_digest_verify(EVP_PKEY *, int, const u_char *,
|
||||
size_t, u_char *, size_t);
|
||||
|
||||
/* for debug */
|
||||
void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
|
||||
void sshkey_dump_ec_key(const EC_KEY *);
|
||||
|
@ -310,7 +318,8 @@ int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
|
|||
|
||||
int sshkey_check_rsa_length(const struct sshkey *, int);
|
||||
/* XXX should be internal, but used by ssh-keygen */
|
||||
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
|
||||
int ssh_rsa_complete_crt_parameters(const BIGNUM *, const BIGNUM *,
|
||||
const BIGNUM *, const BIGNUM *, BIGNUM **, BIGNUM **);
|
||||
|
||||
/* stateful keys (e.g. XMSS) */
|
||||
int sshkey_set_filename(struct sshkey *, const char *);
|
||||
|
@ -321,6 +330,10 @@ int sshkey_private_serialize_maxsign(struct sshkey *key,
|
|||
|
||||
void sshkey_sig_details_free(struct sshkey_sig_details *);
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
int sshkey_ecdsa_fixup_group(EVP_PKEY *k); /* ssh-ecdsa.c */
|
||||
#endif
|
||||
|
||||
#ifdef SSHKEY_INTERNAL
|
||||
int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b);
|
||||
void sshkey_sk_cleanup(struct sshkey *k);
|
||||
|
@ -341,6 +354,7 @@ int check_rsa_length(const RSA *rsa); /* XXX remove */
|
|||
# undef EC_KEY
|
||||
# undef EC_GROUP
|
||||
# undef EC_POINT
|
||||
# undef EVP_PKEY
|
||||
#elif !defined(OPENSSL_HAS_ECC)
|
||||
# undef EC_KEY
|
||||
# undef EC_GROUP
|
||||
|
|
Loading…
Reference in New Issue