Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/ssh.h
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2022-04-20 15:06:08 +0300
committerSimon Tatham <anakin@pobox.com>2022-04-25 17:09:31 +0300
commit9f583c4fa8f632c349e6b335a4ab5cd69b0a76f9 (patch)
tree8b2fae27bd675133eee6394fae37518ec61e1e38 /ssh.h
parent34d01e1b654d8c42ebd7f8abc05f5c2693f2a6a1 (diff)
Certificate-specific ssh_key method suite.
Certificate keys don't work the same as normal keys, so the rest of the code is going to have to pay attention to whether a key is a certificate, and if so, treat it differently and do cert-specific stuff to it. So here's a collection of methods for that purpose. With one exception, these methods of ssh_key are not expected to be implemented at all in non-certificate key types: they should only ever be called once you already know you're dealing with a certificate. So most of the new method pointers can be left out of the ssh_keyalg initialisers. The exception is the base_key method, which retrieves the base key of a certificate - the underlying one with the certificate stripped off. It's convenient for non-certificate keys to implement this too, and just return a pointer to themselves. So I've added an implementation in nullkey.c doing that. (The returned pointer doesn't transfer ownership; you have to use the new ssh_key_clone() if you want to keep the base key after freeing the certificate key.) The methods _only_ implemented in certificates: Query methods to return the public key of the CA (for looking up in a list of trusted ones), and to return the key id string (which exists to be written into log files). Obviously, we need a check_cert() method which will verify the CA's actual signature, not to mention checking all the other details like the principal and the validity period. And there's another fiddly method for dealing with the RSA upgrade system, called 'related_alg'. This is quite like alternate_ssh_id, in that its job is to upgrade one key algorithm to a related one with more modern RSA signing flags (or any other similar thing that might later reuse the same mechanism). But where alternate_ssh_id took the actual signing flags as an argument, this takes a pointer to the upgraded base algorithm. So it answers the question "What is to this key algorithm as you are to its base?" - if you call it on opensshcert_ssh_rsa and give it ssh_rsa_sha512, it'll give you back opensshcert_ssh_rsa_sha512. (It's awkward to have to have another of these fiddly methods, and in the longer term I'd like to try to clean up their proliferation a bit. But I even more dislike the alternative of just going through all_keyalgs looking for a cert algorithm with, say, ssh_rsa_sha512 as the base: that approach would work fine now but it would be a lurking time bomb for when all the -cert-v02@ methods appear one day. This way, each certificate type can upgrade itself to the appropriately related version. And at least related_alg is only needed if you _are_ a certificate key type - it's not adding yet another piece of null-method boilerplate to the rest.)
Diffstat (limited to 'ssh.h')
-rw-r--r--ssh.h23
1 files changed, 23 insertions, 0 deletions
diff --git a/ssh.h b/ssh.h
index a57e6328..ecb5074c 100644
--- a/ssh.h
+++ b/ssh.h
@@ -844,11 +844,20 @@ struct ssh_keyalg {
bool (*has_private) (ssh_key *key);
char *(*cache_str) (ssh_key *key);
key_components *(*components) (ssh_key *key);
+ ssh_key *(*base_key) (ssh_key *key); /* does not confer ownership */
+ /* The following methods can be NULL if !is_certificate */
+ void (*ca_public_blob)(ssh_key *key, BinarySink *);
+ bool (*check_cert)(ssh_key *key, bool host, ptrlen principal,
+ uint64_t time, BinarySink *error);
+ void (*cert_id_string)(ssh_key *key, BinarySink *);
/* '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);
const char *(*alternate_ssh_id) (const ssh_keyalg *self, unsigned flags);
+ /* The following methods can be NULL if !is_certificate */
+ const ssh_keyalg *(*related_alg)(const ssh_keyalg *self,
+ const ssh_keyalg *base);
/* Constant data fields giving information about the key type */
const char *ssh_id; /* string identifier in the SSH protocol */
@@ -887,6 +896,16 @@ static inline char *ssh_key_cache_str(ssh_key *key)
{ return key->vt->cache_str(key); }
static inline key_components *ssh_key_components(ssh_key *key)
{ return key->vt->components(key); }
+static inline ssh_key *ssh_key_base_key(ssh_key *key)
+{ return key->vt->base_key(key); }
+static inline void ssh_key_ca_public_blob(ssh_key *key, BinarySink *bs)
+{ key->vt->ca_public_blob(key, bs); }
+static inline void ssh_key_cert_id_string(ssh_key *key, BinarySink *bs)
+{ key->vt->cert_id_string(key, bs); }
+static inline bool ssh_key_check_cert(
+ ssh_key *key, bool host, ptrlen principal, uint64_t time,
+ BinarySink *error)
+{ return key->vt->check_cert(key, host, principal, time, error); }
static inline int ssh_key_public_bits(const ssh_keyalg *self, ptrlen blob)
{ return self->pubkey_bits(self, blob); }
static inline const ssh_keyalg *ssh_key_alg(ssh_key *key)
@@ -902,10 +921,14 @@ static inline const unsigned ssh_keyalg_supported_flags(const ssh_keyalg *self)
static inline const char *ssh_keyalg_alternate_ssh_id(
const ssh_keyalg *self, unsigned flags)
{ return self->alternate_ssh_id(self, flags); }
+static inline const ssh_keyalg *ssh_keyalg_related_alg(
+ const ssh_keyalg *self, const ssh_keyalg *base)
+{ return self->related_alg(self, base); }
/* Stub functions shared between multiple key types */
unsigned nullkey_supported_flags(const ssh_keyalg *self);
const char *nullkey_alternate_ssh_id(const ssh_keyalg *self, unsigned flags);
+ssh_key *nullkey_base_key(ssh_key *key);
/* Utility functions implemented centrally */
ssh_key *ssh_key_clone(ssh_key *key);