From f9775a7b676c8878239eafe8c88cc6b9240eda86 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 19 Apr 2022 17:05:36 +0100 Subject: [PATCH] Make ssh_keyalg's supported_flags a method. It's a class method rather than an object method, so it doesn't allow keys with the same algorithm to make different choices about what flags they support. But that's not what I wanted it for: the real purpose is to allow one key algorithm to delegate supported_flags to another, by having its method implementation call the one from the delegate class. (If only C's compile/link model permitted me to initialise a field of one global const struct variable to be a copy of that of another, I wouldn't need the runtime overhead of this method! But object file formats don't let you even specify that.) Most key algorithms support no flags at all, so they all want to use the same implementation of this method. So I've started a file of stubs utils/nullkey.c to contain the common stub version. --- crypto/dsa.c | 1 + crypto/ecc-ssh.c | 5 +++++ crypto/rsa.c | 11 ++++++++--- pageant.c | 2 +- ssh.h | 9 ++++++++- utils/CMakeLists.txt | 1 + utils/nullkey.c | 6 ++++++ 7 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 utils/nullkey.c diff --git a/crypto/dsa.c b/crypto/dsa.c index 43b51c8c..db419141 100644 --- a/crypto/dsa.c +++ b/crypto/dsa.c @@ -498,6 +498,7 @@ const ssh_keyalg ssh_dsa = { .cache_str = dsa_cache_str, .components = dsa_components, .pubkey_bits = dsa_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ssh-dss", .cache_id = "dss", }; diff --git a/crypto/ecc-ssh.c b/crypto/ecc-ssh.c index e57e8bb1..529ef5a3 100644 --- a/crypto/ecc-ssh.c +++ b/crypto/ecc-ssh.c @@ -1257,6 +1257,7 @@ const ssh_keyalg ssh_ecdsa_ed25519 = { .cache_str = eddsa_cache_str, .components = eddsa_components, .pubkey_bits = ec_shared_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ssh-ed25519", .cache_id = "ssh-ed25519", .extra = &sign_extra_ed25519, @@ -1280,6 +1281,7 @@ const ssh_keyalg ssh_ecdsa_ed448 = { .cache_str = eddsa_cache_str, .components = eddsa_components, .pubkey_bits = ec_shared_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ssh-ed448", .cache_id = "ssh-ed448", .extra = &sign_extra_ed448, @@ -1307,6 +1309,7 @@ const ssh_keyalg ssh_ecdsa_nistp256 = { .cache_str = ecdsa_cache_str, .components = ecdsa_components, .pubkey_bits = ec_shared_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ecdsa-sha2-nistp256", .cache_id = "ecdsa-sha2-nistp256", .extra = &sign_extra_nistp256, @@ -1334,6 +1337,7 @@ const ssh_keyalg ssh_ecdsa_nistp384 = { .cache_str = ecdsa_cache_str, .components = ecdsa_components, .pubkey_bits = ec_shared_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ecdsa-sha2-nistp384", .cache_id = "ecdsa-sha2-nistp384", .extra = &sign_extra_nistp384, @@ -1361,6 +1365,7 @@ const ssh_keyalg ssh_ecdsa_nistp521 = { .cache_str = ecdsa_cache_str, .components = ecdsa_components, .pubkey_bits = ec_shared_pubkey_bits, + .supported_flags = nullkey_supported_flags, .ssh_id = "ecdsa-sha2-nistp521", .cache_id = "ecdsa-sha2-nistp521", .extra = &sign_extra_nistp521, diff --git a/crypto/rsa.c b/crypto/rsa.c index 1afa766d..b87f4bd6 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -839,6 +839,11 @@ static char *rsa2_invalid(ssh_key *key, unsigned flags) return NULL; } +static unsigned ssh_rsa_supported_flags(const ssh_keyalg *self) +{ + return SSH_AGENT_RSA_SHA2_256 | SSH_AGENT_RSA_SHA2_512; +} + static const struct ssh2_rsa_extra rsa_extra = { 0 }, rsa_sha256_extra = { SSH_AGENT_RSA_SHA2_256 }, @@ -863,21 +868,21 @@ static const struct ssh2_rsa_extra const ssh_keyalg ssh_rsa = { COMMON_KEYALG_FIELDS, .ssh_id = "ssh-rsa", - .supported_flags = SSH_AGENT_RSA_SHA2_256 | SSH_AGENT_RSA_SHA2_512, + .supported_flags = ssh_rsa_supported_flags, .extra = &rsa_extra, }; const ssh_keyalg ssh_rsa_sha256 = { COMMON_KEYALG_FIELDS, .ssh_id = "rsa-sha2-256", - .supported_flags = 0, + .supported_flags = nullkey_supported_flags, .extra = &rsa_sha256_extra, }; const ssh_keyalg ssh_rsa_sha512 = { COMMON_KEYALG_FIELDS, .ssh_id = "rsa-sha2-512", - .supported_flags = 0, + .supported_flags = nullkey_supported_flags, .extra = &rsa_sha512_extra, }; diff --git a/pageant.c b/pageant.c index e97eacbe..27d6ee91 100644 --- a/pageant.c +++ b/pageant.c @@ -432,7 +432,7 @@ static void signop_coroutine(PageantAsyncOp *pao) signop_unlink(so); } - uint32_t supported_flags = ssh_key_alg(so->pk->skey->key)->supported_flags; + uint32_t supported_flags = ssh_key_supported_flags(so->pk->skey->key); if (so->flags & ~supported_flags) { /* * We MUST reject any message containing flags we don't diff --git a/ssh.h b/ssh.h index 6d808cc1..68a91256 100644 --- a/ssh.h +++ b/ssh.h @@ -834,12 +834,12 @@ struct ssh_keyalg { /* 'Class methods' that don't deal with an ssh_key at all */ int (*pubkey_bits) (const ssh_keyalg *self, ptrlen blob); + unsigned (*supported_flags) (const ssh_keyalg *self); /* Constant data fields giving information about the key type */ const char *ssh_id; /* string identifier in the SSH protocol */ const char *cache_id; /* identifier used in PuTTY's host key cache */ const void *extra; /* private to the public key methods */ - const unsigned supported_flags; /* signature-type flags we understand */ }; static inline ssh_key *ssh_key_new_pub(const ssh_keyalg *self, ptrlen pub) @@ -877,6 +877,13 @@ static inline const char *ssh_key_ssh_id(ssh_key *key) { return key->vt->ssh_id; } static inline const char *ssh_key_cache_id(ssh_key *key) { return key->vt->cache_id; } +static inline const unsigned ssh_key_supported_flags(ssh_key *key) +{ return key->vt->supported_flags(key->vt); } +static inline const unsigned ssh_keyalg_supported_flags(const ssh_keyalg *self) +{ return self->supported_flags(self); } + +/* Stub functions shared between multiple key types */ +unsigned nullkey_supported_flags(const ssh_keyalg *self); /* * SSH2 ECDH key exchange vtable diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 787bcefc..94192f98 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -35,6 +35,7 @@ add_sources_from_current_dir(utils memory.c memxor.c null_lp.c + nullkey.c nullseat.c nullstrcmp.c out_of_memory.c diff --git a/utils/nullkey.c b/utils/nullkey.c new file mode 100644 index 00000000..e8e77d50 --- /dev/null +++ b/utils/nullkey.c @@ -0,0 +1,6 @@ +#include "ssh.h" + +unsigned nullkey_supported_flags(const ssh_keyalg *self) +{ + return 0; +}