-/* $OpenBSD: ssh-dss.c,v 1.44 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.45 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
static int
ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
if (dsa_p == NULL || dsa_q == NULL ||
dsa_g == NULL || dsa_pub_key == NULL)
return SSH_ERR_INTERNAL_ERROR;
- if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
- (r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
+ if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
return r;
}
+static int
+ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ int ret = SSH_ERR_INTERNAL_ERROR;
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
+
+ if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_q) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_g) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ dsa_p = dsa_q = dsa_g = NULL; /* transferred */
+ if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ dsa_pub_key = NULL; /* transferred */
+#ifdef DEBUG_PK
+ DSA_print_fp(stderr, key->dsa, 8);
+#endif
+ /* success */
+ ret = 0;
+ out:
+ BN_clear_free(dsa_p);
+ BN_clear_free(dsa_q);
+ BN_clear_free(dsa_g);
+ BN_clear_free(dsa_pub_key);
+ return ret;
+}
+
int
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
/* .cleanup = */ ssh_dss_cleanup,
/* .equal = */ ssh_dss_equal,
/* .ssh_serialize_public = */ ssh_dss_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
/* .generate = */ ssh_dss_generate,
/* .copy_public = */ ssh_dss_copy_public,
};
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.13 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.14 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
static int
ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
- if ((r = sshkey_ecdsa_funcs.serialize_public(key, b,
- typename, opts)) != 0)
+ if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0)
return r;
if ((r = sshkey_serialize_sk(key, b)) != 0)
return r;
return 0;
}
+static int
+ssh_ecdsa_sk_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ int r;
+
+ if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0)
+ return r;
+ if ((r = sshkey_deserialize_sk(b, key)) != 0)
+ return r;
+ return 0;
+}
+
/*
* Check FIDO/W3C webauthn signatures clientData field against the expected
* format and prepare a hash of it for use in signature verification.
/* .cleanup = */ ssh_ecdsa_sk_cleanup,
/* .equal = */ ssh_ecdsa_sk_equal,
/* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public,
/* .generate = */ NULL,
/* .copy_public = */ ssh_ecdsa_sk_copy_public,
};
-/* $OpenBSD: ssh-ecdsa.c,v 1.21 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.22 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
static int
ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
if (key->ecdsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
- (r = sshbuf_put_cstring(b,
+ if ((r = sshbuf_put_cstring(b,
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(r = sshbuf_put_eckey(b, key->ecdsa)) != 0)
return r;
return 0;
}
+static int
+ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ int ret = SSH_ERR_INTERNAL_ERROR;
+ char *curve = NULL;
+ EC_POINT *q = NULL;
+
+ key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
+ if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
+ ret = SSH_ERR_EC_CURVE_MISMATCH;
+ goto out;
+ }
+ EC_KEY_free(key->ecdsa);
+ if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
+ ret = SSH_ERR_EC_CURVE_INVALID;
+ goto out;
+ }
+ if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
+ ret = SSH_ERR_KEY_INVALID_EC_VALUE;
+ goto out;
+ }
+ if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
+ /* XXX assume it is a allocation error */
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+#ifdef DEBUG_PK
+ sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
+#endif
+ /* success */
+ ret = 0;
+ out:
+ free(curve);
+ EC_POINT_free(q);
+ return ret;
+}
+
/* ARGSUSED */
int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
/* .cleanup = */ ssh_ecdsa_cleanup,
/* .equal = */ ssh_ecdsa_equal,
/* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
/* .generate = */ ssh_ecdsa_generate,
/* .copy_public = */ ssh_ecdsa_copy_public,
};
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.11 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.12 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
static int
ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
- if ((r = sshkey_ed25519_funcs.serialize_public(key, b,
- typename, opts)) != 0)
+ if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0)
return r;
if ((r = sshkey_serialize_sk(key, b)) != 0)
return r;
return 0;
}
+static int
+ssh_ed25519_sk_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ int r;
+
+ if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0)
+ return r;
+ if ((r = sshkey_deserialize_sk(b, key)) != 0)
+ return r;
+ return 0;
+}
+
int
ssh_ed25519_sk_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
/* .cleanup = */ ssh_ed25519_sk_cleanup,
/* .equal = */ ssh_ed25519_sk_equal,
/* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public,
/* .generate = */ NULL,
/* .copy_public = */ ssh_ed25519_sk_copy_public,
};
-/* $OpenBSD: ssh-ed25519.c,v 1.15 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.16 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
static int
ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
if (key->ed25519_pk == NULL)
return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
- (r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0)
+ if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0)
return r;
return 0;
return 0;
}
+static int
+ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ u_char *pk = NULL;
+ size_t len = 0;
+ int r;
+
+ if ((r = sshbuf_get_string(b, &pk, &len)) != 0)
+ return r;
+ if (len != ED25519_PK_SZ) {
+ freezero(pk, len);
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ key->ed25519_pk = pk;
+ return 0;
+}
+
int
ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
/* .cleanup = */ ssh_ed25519_cleanup,
/* .equal = */ ssh_ed25519_equal,
/* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public,
/* .generate = */ ssh_ed25519_generate,
/* .copy_public = */ ssh_ed25519_copy_public,
};
-/* $OpenBSD: ssh-rsa.c,v 1.73 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.74 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
+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 ||
+ (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);
+ if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
+ (min_size > 0 && nbits < min_size))
+ return SSH_ERR_KEY_LENGTH;
+#endif /* WITH_OPENSSL */
+ return 0;
+}
+
+
static u_int
ssh_rsa_size(const struct sshkey *key)
{
static int
ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
const BIGNUM *rsa_n, *rsa_e;
if (key->rsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
- if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
- (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
+ if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_n)) != 0)
return r;
return r;
}
+static int
+ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ int ret = SSH_ERR_INTERNAL_ERROR;
+ BIGNUM *rsa_n = NULL, *rsa_e = NULL;
+
+ 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)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ rsa_n = rsa_e = NULL; /* transferred */
+ if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
+ goto out;
+#ifdef DEBUG_PK
+ RSA_print_fp(stderr, key->rsa, 8);
+#endif
+ /* success */
+ ret = 0;
+ out:
+ BN_clear_free(rsa_n);
+ BN_clear_free(rsa_e);
+ return ret;
+}
+
static const char *
rsa_hash_alg_ident(int hash_alg)
{
/* .cleanup = */ ssh_rsa_cleanup,
/* .equal = */ ssh_rsa_equal,
/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
/* .generate = */ ssh_rsa_generate,
/* .copy_public = */ ssh_rsa_copy_public,
};
-/* $OpenBSD: ssh-xmss.c,v 1.10 2022/10/28 00:41:17 djm Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.11 2022/10/28 00:41:52 djm Exp $*/
/*
* Copyright (c) 2017 Stefan-Lukas Gazdag.
* Copyright (c) 2017 Markus Friedl.
static int
ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
- const char *typename, enum sshkey_serialize_rep opts)
+ enum sshkey_serialize_rep opts)
{
int r;
if (key->xmss_name == NULL || key->xmss_pk == NULL ||
sshkey_xmss_pklen(key) == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
- (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+ if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
(r = sshbuf_put_string(b, key->xmss_pk,
sshkey_xmss_pklen(key))) != 0 ||
(r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
return 0;
}
+static int
+ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
+ struct sshkey *key)
+{
+ size_t len = 0;
+ char *xmss_name = NULL;
+ u_char *pk = NULL;
+ int ret = SSH_ERR_INTERNAL_ERROR;
+
+ if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
+ goto out;
+ if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
+ goto out;
+ if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
+ goto out;
+ if (len == 0 || len != sshkey_xmss_pklen(key)) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ key->xmss_pk = pk;
+ pk = NULL;
+ if (!sshkey_is_cert(key) &&
+ (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
+ goto out;
+ /* success */
+ ret = 0;
+ out:
+ free(xmss_name);
+ freezero(pk, len);
+ return ret;
+}
+
int
ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
/* .cleanup = */ ssh_xmss_cleanup,
/* .equal = */ ssh_xmss_equal,
/* .ssh_serialize_public = */ ssh_xmss_serialize_public,
+ /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
/* .generate = */ sshkey_xmss_generate_private_key,
/* .copy_public = */ ssh_xmss_copy_public,
};
-/* $OpenBSD: sshkey.c,v 1.128 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.129 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
return SSH_ERR_KEY_TYPE_UNKNOWN;
typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
- return impl->funcs->serialize_public(key, b, typename, opts);
+ if ((ret = sshbuf_put_cstring(b, typename)) != 0)
+ return ret;
+ return impl->funcs->serialize_public(key, b, opts);
}
int
}
int
-sshkey_check_rsa_length(const struct sshkey *k, int min_size)
+sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key)
{
-#ifdef WITH_OPENSSL
- const BIGNUM *rsa_n;
- int nbits;
-
- if (k == NULL || k->rsa == 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);
- if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
- (min_size > 0 && nbits < min_size))
- return SSH_ERR_KEY_LENGTH;
-#endif /* WITH_OPENSSL */
+ /* Parse additional security-key application string */
+ if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0)
+ return SSH_ERR_INVALID_FORMAT;
return 0;
}
int allow_cert)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
- char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
+ char *ktype = NULL;
struct sshkey *key = NULL;
- size_t len;
- u_char *pk = NULL;
struct sshbuf *copy;
-#ifdef WITH_OPENSSL
- EC_POINT *q = NULL;
- BIGNUM *rsa_n = NULL, *rsa_e = NULL;
- BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
-#endif /* WITH_OPENSSL */
+ const struct sshkey_impl *impl;
#ifdef DEBUG_PK /* XXX */
sshbuf_dump(b, stderr);
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
goto out;
}
- switch (type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA_CERT:
- /* Skip nonce */
- if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* FALLTHROUGH */
- case KEY_RSA:
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- 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)) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- rsa_n = rsa_e = NULL; /* transferred */
- if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
- goto out;
-#ifdef DEBUG_PK
- RSA_print_fp(stderr, key->rsa, 8);
-#endif
- break;
- case KEY_DSA_CERT:
- /* Skip nonce */
- if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* FALLTHROUGH */
- case KEY_DSA:
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
- sshbuf_get_bignum2(b, &dsa_q) != 0 ||
- sshbuf_get_bignum2(b, &dsa_g) != 0 ||
- sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- dsa_p = dsa_q = dsa_g = NULL; /* transferred */
- if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- dsa_pub_key = NULL; /* transferred */
-#ifdef DEBUG_PK
- DSA_print_fp(stderr, key->dsa, 8);
-#endif
- break;
- case KEY_ECDSA_CERT:
- case KEY_ECDSA_SK_CERT:
- /* Skip nonce */
- if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* FALLTHROUGH */
- case KEY_ECDSA:
- case KEY_ECDSA_SK:
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
- if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
- ret = SSH_ERR_EC_CURVE_MISMATCH;
- goto out;
- }
- EC_KEY_free(key->ecdsa);
- if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
- == NULL) {
- ret = SSH_ERR_EC_CURVE_INVALID;
- goto out;
- }
- if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
- q) != 0) {
- ret = SSH_ERR_KEY_INVALID_EC_VALUE;
- goto out;
- }
- if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
- /* XXX assume it is a allocation error */
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-#ifdef DEBUG_PK
- sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
-#endif
- if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
- /* Parse additional security-key application string */
- if (sshbuf_get_cstring(b, &key->sk_application,
- NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
-#ifdef DEBUG_PK
- fprintf(stderr, "App: %s\n", key->sk_application);
-#endif
- }
- break;
-#endif /* WITH_OPENSSL */
- case KEY_ED25519_CERT:
- case KEY_ED25519_SK_CERT:
- /* Skip nonce */
- if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- /* FALLTHROUGH */
- case KEY_ED25519:
- case KEY_ED25519_SK:
- if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
- goto out;
- if (len != ED25519_PK_SZ) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) {
- /* Parse additional security-key application string */
- if (sshbuf_get_cstring(b, &key->sk_application,
- NULL) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
-#ifdef DEBUG_PK
- fprintf(stderr, "App: %s\n", key->sk_application);
-#endif
- }
- key->ed25519_pk = pk;
- pk = NULL;
- break;
-#ifdef WITH_XMSS
- case KEY_XMSS_CERT:
- /* Skip nonce */
+ if ((impl = sshkey_impl_from_type(type)) == NULL) {
+ ret = SSH_ERR_KEY_TYPE_UNKNOWN;
+ goto out;
+ }
+ if ((key = sshkey_new(type)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshkey_type_is_cert(type)) {
+ /* Skip nonce that preceeds all certificates */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- /* FALLTHROUGH */
- case KEY_XMSS:
- if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
- goto out;
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
- goto out;
- if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
- goto out;
- if (len == 0 || len != sshkey_xmss_pklen(key)) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- key->xmss_pk = pk;
- pk = NULL;
- if (type != KEY_XMSS_CERT &&
- (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
- goto out;
- break;
-#endif /* WITH_XMSS */
- case KEY_UNSPEC:
- default:
- ret = SSH_ERR_KEY_TYPE_UNKNOWN;
- goto out;
}
+ if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0)
+ goto out;
/* Parse certificate potion */
if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
out:
sshbuf_free(copy);
sshkey_free(key);
- free(xmss_name);
free(ktype);
- free(curve);
- free(pk);
-#ifdef WITH_OPENSSL
- EC_POINT_free(q);
- BN_clear_free(rsa_n);
- BN_clear_free(rsa_e);
- BN_clear_free(dsa_p);
- BN_clear_free(dsa_q);
- BN_clear_free(dsa_g);
- BN_clear_free(dsa_pub_key);
-#endif /* WITH_OPENSSL */
return ret;
}
-/* $OpenBSD: sshkey.h,v 1.57 2022/10/28 00:41:17 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.58 2022/10/28 00:41:52 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
void (*cleanup)(struct sshkey *); /* optional */
int (*equal)(const struct sshkey *, const struct sshkey *);
int (*serialize_public)(const struct sshkey *, struct sshbuf *,
- const char *, enum sshkey_serialize_rep);
+ enum sshkey_serialize_rep);
+ int (*deserialize_public)(const char *, struct sshbuf *,
+ struct sshkey *);
int (*generate)(struct sshkey *, int); /* optional */
int (*copy_public)(const struct sshkey *, struct sshkey *);
};
void sshkey_sk_cleanup(struct sshkey *k);
int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b);
int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to);
+int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key);
+#ifdef WITH_OPENSSL
+int check_rsa_length(const RSA *rsa); /* XXX remove */
+#endif
int ssh_rsa_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,