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:
Diffstat (limited to 'ssh.h')
-rw-r--r--ssh.h375
1 files changed, 313 insertions, 62 deletions
diff --git a/ssh.h b/ssh.h
index 49ab2796..5ecef0cb 100644
--- a/ssh.h
+++ b/ssh.h
@@ -299,9 +299,15 @@ struct ConnectionLayerVtable {
* subsequent channel-opens). */
void (*enable_x_fwd)(ConnectionLayer *cl);
- /* Communicate to the connection layer whether the main session
- * channel currently wants user input. */
+ /* Communicate / query whether the main session channel currently
+ * wants user input. The set function is called by mainchan; the
+ * query function is called by the top-level ssh.c. */
void (*set_wants_user_input)(ConnectionLayer *cl, bool wanted);
+ bool (*get_wants_user_input)(ConnectionLayer *cl);
+
+ /* Notify the connection layer that more data has been added to
+ * the user input queue. */
+ void (*got_user_input)(ConnectionLayer *cl);
};
struct ConnectionLayer {
@@ -371,6 +377,10 @@ static inline void ssh_enable_x_fwd(ConnectionLayer *cl)
{ cl->vt->enable_x_fwd(cl); }
static inline void ssh_set_wants_user_input(ConnectionLayer *cl, bool wanted)
{ cl->vt->set_wants_user_input(cl, wanted); }
+static inline bool ssh_get_wants_user_input(ConnectionLayer *cl)
+{ return cl->vt->get_wants_user_input(cl); }
+static inline void ssh_got_user_input(ConnectionLayer *cl)
+{ cl->vt->got_user_input(cl); }
/* Exports from portfwd.c */
PortFwdManager *portfwdmgr_new(ConnectionLayer *cl);
@@ -397,11 +407,13 @@ LogContext *ssh_get_logctx(Ssh *ssh);
void ssh_throttle_conn(Ssh *ssh, int adjust);
void ssh_got_exitcode(Ssh *ssh, int status);
void ssh_ldisc_update(Ssh *ssh);
+void ssh_check_sendok(Ssh *ssh);
void ssh_got_fallback_cmd(Ssh *ssh);
bool ssh_is_bare(Ssh *ssh);
/* Communications back to ssh.c from the BPP */
void ssh_conn_processed_data(Ssh *ssh);
+void ssh_sendbuffer_changed(Ssh *ssh);
void ssh_check_frozen(Ssh *ssh);
/* Functions to abort the connection, for various reasons. */
@@ -411,6 +423,7 @@ void ssh_proto_error(Ssh *ssh, const char *fmt, ...) PRINTF_LIKE(2, 3);
void ssh_sw_abort(Ssh *ssh, const char *fmt, ...) PRINTF_LIKE(2, 3);
void ssh_sw_abort_deferred(Ssh *ssh, const char *fmt, ...) PRINTF_LIKE(2, 3);
void ssh_user_close(Ssh *ssh, const char *fmt, ...) PRINTF_LIKE(2, 3);
+void ssh_spr_close(Ssh *ssh, SeatPromptResult spr, const char *context);
/* Bit positions in the SSH-1 cipher protocol word */
#define SSH1_CIPHER_IDEA 1
@@ -446,7 +459,7 @@ struct RSAKey {
ssh_key sshk;
};
-struct dss_key {
+struct dsa_key {
mp_int *p, *q, *g, *y, *x;
ssh_key sshk;
};
@@ -502,7 +515,7 @@ struct ec_curve {
};
const ssh_keyalg *ec_alg_by_oid(int len, const void *oid,
- const struct ec_curve **curve);
+ const struct ec_curve **curve);
const unsigned char *ec_alg_oid(const ssh_keyalg *alg, int *oidlen);
extern const int ec_nist_curve_lengths[], n_ec_nist_curve_lengths;
extern const int ec_ed_curve_lengths[], n_ec_ed_curve_lengths;
@@ -529,22 +542,34 @@ struct eddsa_key {
WeierstrassPoint *ecdsa_public(mp_int *private_key, const ssh_keyalg *alg);
EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg);
+typedef enum KeyComponentType {
+ KCT_TEXT, KCT_BINARY, KCT_MPINT
+} KeyComponentType;
+typedef struct key_component {
+ char *name;
+ KeyComponentType type;
+ union {
+ strbuf *str; /* used for KCT_TEXT and KCT_BINARY */
+ mp_int *mp; /* used for KCT_MPINT */
+ };
+} key_component;
typedef struct key_components {
size_t ncomponents, componentsize;
- struct {
- char *name;
- bool is_mp_int;
- union {
- char *text;
- mp_int *mp;
- };
- } *components;
+ key_component *components;
} key_components;
key_components *key_components_new(void);
void key_components_add_text(key_components *kc,
const char *name, const char *value);
+void key_components_add_text_pl(key_components *kc,
+ const char *name, ptrlen value);
+void key_components_add_binary(key_components *kc,
+ const char *name, ptrlen value);
void key_components_add_mp(key_components *kc,
const char *name, mp_int *value);
+void key_components_add_uint(key_components *kc,
+ const char *name, uintmax_t value);
+void key_components_add_copy(key_components *kc,
+ const char *name, const key_component *value);
void key_components_free(key_components *kc);
/*
@@ -572,6 +597,7 @@ bool rsa_verify(RSAKey *key);
void rsa_ssh1_public_blob(BinarySink *bs, RSAKey *key, RsaSsh1Order order);
int rsa_ssh1_public_blob_len(ptrlen data);
void rsa_ssh1_private_blob_agent(BinarySink *bs, RSAKey *key);
+void duprsakey(RSAKey *dst, const RSAKey *src);
void freersapriv(RSAKey *key);
void freersakey(RSAKey *key);
key_components *rsa_components(RSAKey *key);
@@ -603,20 +629,11 @@ mp_int *ssh_rsakex_decrypt(
RSAKey *key, const ssh_hashalg *h, ptrlen ciphertext);
/*
- * SSH2 ECDH key exchange functions
- */
-const char *ssh_ecdhkex_curve_textname(const ssh_kex *kex);
-ecdh_key *ssh_ecdhkex_newkey(const ssh_kex *kex);
-void ssh_ecdhkex_freekey(ecdh_key *key);
-void ssh_ecdhkex_getpublic(ecdh_key *key, BinarySink *bs);
-mp_int *ssh_ecdhkex_getkey(ecdh_key *key, ptrlen remoteKey);
-
-/*
* Helper function for k generation in DSA, reused in ECDSA
*/
-mp_int *dss_gen_k(const char *id_string,
- mp_int *modulus, mp_int *private_key,
- unsigned char *digest, int digest_len);
+mp_int *dsa_gen_k(const char *id_string,
+ mp_int *modulus, mp_int *private_key,
+ unsigned char *digest, int digest_len);
struct ssh_cipher {
const ssh_cipheralg *vt;
@@ -634,6 +651,9 @@ struct ssh_cipheralg {
unsigned long seq);
void (*decrypt_length)(ssh_cipher *, void *blk, int len,
unsigned long seq);
+ /* For ciphers that update their state per logical message
+ * (typically, per unit independently MACed) */
+ void (*next_message)(ssh_cipher *);
const char *ssh2_id;
int blksize;
/* real_keybits is the number of bits of entropy genuinely used by
@@ -678,9 +698,13 @@ static inline void ssh_cipher_encrypt_length(
static inline void ssh_cipher_decrypt_length(
ssh_cipher *c, void *blk, int len, unsigned long seq)
{ c->vt->decrypt_length(c, blk, len, seq); }
+static inline void ssh_cipher_next_message(ssh_cipher *c)
+{ c->vt->next_message(c); }
static inline const struct ssh_cipheralg *ssh_cipher_alg(ssh_cipher *c)
{ return c->vt; }
+void nullcipher_next_message(ssh_cipher *);
+
struct ssh2_ciphers {
int nciphers;
const ssh_cipheralg *const *list;
@@ -698,6 +722,7 @@ struct ssh2_macalg {
void (*setkey)(ssh2_mac *, ptrlen key);
void (*start)(ssh2_mac *);
void (*genresult)(ssh2_mac *, unsigned char *);
+ void (*next_message)(ssh2_mac *);
const char *(*text_name)(ssh2_mac *);
const char *name, *etm_name;
int len, keylen;
@@ -717,18 +742,22 @@ static inline void ssh2_mac_start(ssh2_mac *m)
{ m->vt->start(m); }
static inline void ssh2_mac_genresult(ssh2_mac *m, unsigned char *out)
{ m->vt->genresult(m, out); }
+static inline void ssh2_mac_next_message(ssh2_mac *m)
+{ m->vt->next_message(m); }
static inline const char *ssh2_mac_text_name(ssh2_mac *m)
{ return m->vt->text_name(m); }
static inline const ssh2_macalg *ssh2_mac_alg(ssh2_mac *m)
{ return m->vt; }
-/* Centralised 'methods' for ssh2_mac, defined in sshmac.c. These run
+/* Centralised 'methods' for ssh2_mac, defined in mac.c. These run
* the MAC in a specifically SSH-2 style, i.e. taking account of a
* packet sequence number as well as the data to be authenticated. */
bool ssh2_mac_verresult(ssh2_mac *, const void *);
void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq);
bool ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq);
+void nullmac_next_message(ssh2_mac *m);
+
/* Use a MAC in its raw form, outside SSH-2 context, to MAC a given
* string with a given key in the most obvious way. */
void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output);
@@ -791,11 +820,20 @@ void hash_simple(const ssh_hashalg *alg, ptrlen data, void *output);
struct ssh_kex {
const char *name, *groupname;
- enum { KEXTYPE_DH, KEXTYPE_RSA, KEXTYPE_ECDH, KEXTYPE_GSS } main_type;
+ enum { KEXTYPE_DH, KEXTYPE_RSA, KEXTYPE_ECDH,
+ KEXTYPE_GSS, KEXTYPE_GSS_ECDH } main_type;
const ssh_hashalg *hash;
+ union { /* publicly visible data for each type */
+ const ecdh_keyalg *ecdh_vt; /* for KEXTYPE_ECDH, KEXTYPE_GSS_ECDH */
+ };
const void *extra; /* private to the kex methods */
};
+static inline bool kex_is_gss(const struct ssh_kex *kex)
+{
+ return kex->main_type == KEXTYPE_GSS || kex->main_type == KEXTYPE_GSS_ECDH;
+}
+
struct ssh_kexes {
int nkexes;
const ssh_kex *const *list;
@@ -822,17 +860,34 @@ struct ssh_keyalg {
void (*public_blob)(ssh_key *key, BinarySink *);
void (*private_blob)(ssh_key *key, BinarySink *);
void (*openssh_blob) (ssh_key *key, BinarySink *);
+ 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, const ca_options *opts,
+ BinarySink *error);
+ void (*cert_id_string)(ssh_key *key, BinarySink *);
+ SeatDialogText *(*cert_info)(ssh_key *key);
/* '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);
+ char *(*alg_desc)(const ssh_keyalg *self);
+ bool (*variable_size)(const ssh_keyalg *self);
+ /* 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 */
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 */
+ bool is_certificate; /* is this a certified key type? */
+ const ssh_keyalg *base_alg; /* if so, for what underlying key alg? */
};
static inline ssh_key *ssh_key_new_pub(const ssh_keyalg *self, ptrlen pub)
@@ -858,10 +913,24 @@ static inline void ssh_key_private_blob(ssh_key *key, BinarySink *bs)
{ key->vt->private_blob(key, bs); }
static inline void ssh_key_openssh_blob(ssh_key *key, BinarySink *bs)
{ key->vt->openssh_blob(key, bs); }
+static inline bool ssh_key_has_private(ssh_key *key)
+{ return key->vt->has_private(key); }
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 SeatDialogText *ssh_key_cert_info(ssh_key *key)
+{ return key->vt->cert_info(key); }
+static inline bool ssh_key_check_cert(
+ ssh_key *key, bool host, ptrlen principal, uint64_t time,
+ const ca_options *opts, BinarySink *error)
+{ return key->vt->check_cert(key, host, principal, time, opts, 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)
@@ -870,6 +939,73 @@ 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 unsigned ssh_key_supported_flags(ssh_key *key)
+{ return key->vt->supported_flags(key->vt); }
+static inline unsigned ssh_keyalg_supported_flags(const ssh_keyalg *self)
+{ return self->supported_flags(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 char *ssh_keyalg_desc(const ssh_keyalg *self)
+{ return self->alg_desc(self); }
+static inline bool ssh_keyalg_variable_size(const ssh_keyalg *self)
+{ return self->variable_size(self); }
+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);
+bool nullkey_variable_size_no(const ssh_keyalg *self);
+bool nullkey_variable_size_yes(const ssh_keyalg *self);
+
+/* Utility functions implemented centrally */
+ssh_key *ssh_key_clone(ssh_key *key);
+
+/*
+ * SSH2 ECDH key exchange vtable
+ */
+struct ecdh_key {
+ const ecdh_keyalg *vt;
+};
+struct ecdh_keyalg {
+ /* Unusually, the 'new' method here doesn't directly take a vt
+ * pointer, because it will also need the containing ssh_kex
+ * structure for top-level parameters, and since that contains a
+ * vt pointer anyway, we might as well _only_ pass that. */
+ ecdh_key *(*new)(const ssh_kex *kex, bool is_server);
+ void (*free)(ecdh_key *key);
+ void (*getpublic)(ecdh_key *key, BinarySink *bs);
+ bool (*getkey)(ecdh_key *key, ptrlen remoteKey, BinarySink *bs);
+ char *(*description)(const ssh_kex *kex);
+};
+static inline ecdh_key *ecdh_key_new(const ssh_kex *kex, bool is_server)
+{ return kex->ecdh_vt->new(kex, is_server); }
+static inline void ecdh_key_free(ecdh_key *key)
+{ key->vt->free(key); }
+static inline void ecdh_key_getpublic(ecdh_key *key, BinarySink *bs)
+{ key->vt->getpublic(key, bs); }
+static inline bool ecdh_key_getkey(ecdh_key *key, ptrlen remoteKey,
+ BinarySink *bs)
+{ return key->vt->getkey(key, remoteKey, bs); }
+static inline char *ecdh_keyalg_description(const ssh_kex *kex)
+{ return kex->ecdh_vt->description(kex); }
+
+/*
+ * Suffix on GSSAPI SSH protocol identifiers that indicates Kerberos 5
+ * as the mechanism.
+ *
+ * This suffix is the base64-encoded MD5 hash of the byte sequence
+ * 06 09 2A 86 48 86 F7 12 01 02 02, which in turn is the ASN.1 DER
+ * encoding of the object ID 1.2.840.113554.1.2.2 which designates
+ * Kerberos v5.
+ *
+ * (The same encoded OID, minus the two-byte DER header, is defined in
+ * ssh/pgssapi.c as GSS_MECH_KRB5.)
+ */
+#define GSS_KRB5_OID_HASH "toWM5Slw5Ew8Mqkay+al2g=="
/*
* Enumeration of signature flags from draft-miller-ssh-agent-02
@@ -953,22 +1089,40 @@ extern const ssh_cipheralg ssh_3des_ssh2;
extern const ssh_cipheralg ssh_des;
extern const ssh_cipheralg ssh_des_sshcom_ssh2;
extern const ssh_cipheralg ssh_aes256_sdctr;
-extern const ssh_cipheralg ssh_aes256_sdctr_hw;
+extern const ssh_cipheralg ssh_aes256_sdctr_ni;
+extern const ssh_cipheralg ssh_aes256_sdctr_neon;
extern const ssh_cipheralg ssh_aes256_sdctr_sw;
+extern const ssh_cipheralg ssh_aes256_gcm;
+extern const ssh_cipheralg ssh_aes256_gcm_ni;
+extern const ssh_cipheralg ssh_aes256_gcm_neon;
+extern const ssh_cipheralg ssh_aes256_gcm_sw;
extern const ssh_cipheralg ssh_aes256_cbc;
-extern const ssh_cipheralg ssh_aes256_cbc_hw;
+extern const ssh_cipheralg ssh_aes256_cbc_ni;
+extern const ssh_cipheralg ssh_aes256_cbc_neon;
extern const ssh_cipheralg ssh_aes256_cbc_sw;
extern const ssh_cipheralg ssh_aes192_sdctr;
-extern const ssh_cipheralg ssh_aes192_sdctr_hw;
+extern const ssh_cipheralg ssh_aes192_sdctr_ni;
+extern const ssh_cipheralg ssh_aes192_sdctr_neon;
extern const ssh_cipheralg ssh_aes192_sdctr_sw;
+extern const ssh_cipheralg ssh_aes192_gcm;
+extern const ssh_cipheralg ssh_aes192_gcm_ni;
+extern const ssh_cipheralg ssh_aes192_gcm_neon;
+extern const ssh_cipheralg ssh_aes192_gcm_sw;
extern const ssh_cipheralg ssh_aes192_cbc;
-extern const ssh_cipheralg ssh_aes192_cbc_hw;
+extern const ssh_cipheralg ssh_aes192_cbc_ni;
+extern const ssh_cipheralg ssh_aes192_cbc_neon;
extern const ssh_cipheralg ssh_aes192_cbc_sw;
extern const ssh_cipheralg ssh_aes128_sdctr;
-extern const ssh_cipheralg ssh_aes128_sdctr_hw;
+extern const ssh_cipheralg ssh_aes128_sdctr_ni;
+extern const ssh_cipheralg ssh_aes128_sdctr_neon;
extern const ssh_cipheralg ssh_aes128_sdctr_sw;
+extern const ssh_cipheralg ssh_aes128_gcm;
+extern const ssh_cipheralg ssh_aes128_gcm_ni;
+extern const ssh_cipheralg ssh_aes128_gcm_neon;
+extern const ssh_cipheralg ssh_aes128_gcm_sw;
extern const ssh_cipheralg ssh_aes128_cbc;
-extern const ssh_cipheralg ssh_aes128_cbc_hw;
+extern const ssh_cipheralg ssh_aes128_cbc_ni;
+extern const ssh_cipheralg ssh_aes128_cbc_neon;
extern const ssh_cipheralg ssh_aes128_cbc_sw;
extern const ssh_cipheralg ssh_blowfish_ssh2_ctr;
extern const ssh_cipheralg ssh_blowfish_ssh2;
@@ -981,18 +1135,21 @@ extern const ssh2_ciphers ssh2_aes;
extern const ssh2_ciphers ssh2_blowfish;
extern const ssh2_ciphers ssh2_arcfour;
extern const ssh2_ciphers ssh2_ccp;
+extern const ssh2_ciphers ssh2_aesgcm;
extern const ssh_hashalg ssh_md5;
extern const ssh_hashalg ssh_sha1;
-extern const ssh_hashalg ssh_sha1_hw;
+extern const ssh_hashalg ssh_sha1_ni;
+extern const ssh_hashalg ssh_sha1_neon;
extern const ssh_hashalg ssh_sha1_sw;
extern const ssh_hashalg ssh_sha256;
-extern const ssh_hashalg ssh_sha256_hw;
+extern const ssh_hashalg ssh_sha256_ni;
+extern const ssh_hashalg ssh_sha256_neon;
extern const ssh_hashalg ssh_sha256_sw;
extern const ssh_hashalg ssh_sha384;
-extern const ssh_hashalg ssh_sha384_hw;
+extern const ssh_hashalg ssh_sha384_neon;
extern const ssh_hashalg ssh_sha384_sw;
extern const ssh_hashalg ssh_sha512;
-extern const ssh_hashalg ssh_sha512_hw;
+extern const ssh_hashalg ssh_sha512_neon;
extern const ssh_hashalg ssh_sha512_sw;
extern const ssh_hashalg ssh_sha3_224;
extern const ssh_hashalg ssh_sha3_256;
@@ -1002,8 +1159,21 @@ extern const ssh_hashalg ssh_shake256_114bytes;
extern const ssh_hashalg ssh_blake2b;
extern const ssh_kexes ssh_diffiehellman_group1;
extern const ssh_kexes ssh_diffiehellman_group14;
+extern const ssh_kexes ssh_diffiehellman_group15;
+extern const ssh_kexes ssh_diffiehellman_group16;
+extern const ssh_kexes ssh_diffiehellman_group17;
+extern const ssh_kexes ssh_diffiehellman_group18;
extern const ssh_kexes ssh_diffiehellman_gex;
+extern const ssh_kex ssh_diffiehellman_group1_sha1;
+extern const ssh_kex ssh_diffiehellman_group14_sha256;
+extern const ssh_kex ssh_diffiehellman_group14_sha1;
+extern const ssh_kex ssh_diffiehellman_group15_sha512;
+extern const ssh_kex ssh_diffiehellman_group16_sha512;
+extern const ssh_kex ssh_diffiehellman_group17_sha512;
+extern const ssh_kex ssh_diffiehellman_group18_sha512;
extern const ssh_kexes ssh_gssk5_sha1_kex;
+extern const ssh_kexes ssh_gssk5_sha2_kex;
+extern const ssh_kexes ssh_gssk5_ecdh_kex;
extern const ssh_kexes ssh_rsa_kex;
extern const ssh_kex ssh_ec_kex_curve25519;
extern const ssh_kex ssh_ec_kex_curve448;
@@ -1011,7 +1181,8 @@ extern const ssh_kex ssh_ec_kex_nistp256;
extern const ssh_kex ssh_ec_kex_nistp384;
extern const ssh_kex ssh_ec_kex_nistp521;
extern const ssh_kexes ssh_ecdh_kex;
-extern const ssh_keyalg ssh_dss;
+extern const ssh_kexes ssh_ntru_hybrid_kex;
+extern const ssh_keyalg ssh_dsa;
extern const ssh_keyalg ssh_rsa;
extern const ssh_keyalg ssh_rsa_sha256;
extern const ssh_keyalg ssh_rsa_sha512;
@@ -1020,6 +1191,14 @@ extern const ssh_keyalg ssh_ecdsa_ed448;
extern const ssh_keyalg ssh_ecdsa_nistp256;
extern const ssh_keyalg ssh_ecdsa_nistp384;
extern const ssh_keyalg ssh_ecdsa_nistp521;
+extern const ssh_keyalg opensshcert_ssh_dsa;
+extern const ssh_keyalg opensshcert_ssh_rsa;
+extern const ssh_keyalg opensshcert_ssh_rsa_sha256;
+extern const ssh_keyalg opensshcert_ssh_rsa_sha512;
+extern const ssh_keyalg opensshcert_ssh_ecdsa_ed25519;
+extern const ssh_keyalg opensshcert_ssh_ecdsa_nistp256;
+extern const ssh_keyalg opensshcert_ssh_ecdsa_nistp384;
+extern const ssh_keyalg opensshcert_ssh_ecdsa_nistp521;
extern const ssh2_macalg ssh_hmac_md5;
extern const ssh2_macalg ssh_hmac_sha1;
extern const ssh2_macalg ssh_hmac_sha1_buggy;
@@ -1027,22 +1206,31 @@ extern const ssh2_macalg ssh_hmac_sha1_96;
extern const ssh2_macalg ssh_hmac_sha1_96_buggy;
extern const ssh2_macalg ssh_hmac_sha256;
extern const ssh2_macalg ssh2_poly1305;
+extern const ssh2_macalg ssh2_aesgcm_mac;
+extern const ssh2_macalg ssh2_aesgcm_mac_sw;
+extern const ssh2_macalg ssh2_aesgcm_mac_ref_poly;
+extern const ssh2_macalg ssh2_aesgcm_mac_clmul;
+extern const ssh2_macalg ssh2_aesgcm_mac_neon;
extern const ssh_compression_alg ssh_zlib;
/* Special constructor: BLAKE2b can be instantiated with any hash
* length up to 128 bytes */
ssh_hash *blake2b_new_general(unsigned hashlen);
+/* Special test function for AES-GCM */
+void aesgcm_set_prefix_lengths(ssh2_mac *mac, size_t skip, size_t aad);
+
/*
* On some systems, you have to detect hardware crypto acceleration by
* asking the local OS API rather than OS-agnostically asking the CPU
* itself. If so, then this function should be implemented in each
* platform subdirectory.
*/
-bool platform_aes_hw_available(void);
-bool platform_sha256_hw_available(void);
-bool platform_sha1_hw_available(void);
-bool platform_sha512_hw_available(void);
+bool platform_aes_neon_available(void);
+bool platform_pmull_neon_available(void);
+bool platform_sha256_neon_available(void);
+bool platform_sha1_neon_available(void);
+bool platform_sha512_neon_available(void);
/*
* PuTTY version number formatted as an SSH version string.
@@ -1051,13 +1239,13 @@ extern const char sshver[];
/*
* Gross hack: pscp will try to start SFTP but fall back to scp1 if
- * that fails. This variable is the means by which scp.c can reach
+ * that fails. This variable is the means by which pscp.c can reach
* into the SSH code and find out which one it got.
*/
extern bool ssh_fallback_cmd(Backend *backend);
/*
- * The PRNG type, defined in sshprng.c. Visible data fields are
+ * The PRNG type, defined in prng.c. Visible data fields are
* 'savesize', which suggests how many random bytes you should request
* from a particular PRNG instance to write to putty.rnd, and a
* BinarySink implementation which you can use to write seed data in
@@ -1066,7 +1254,7 @@ extern bool ssh_fallback_cmd(Backend *backend);
struct prng {
size_t savesize;
BinarySink_IMPLEMENTATION;
- /* (also there's a surrounding implementation struct in sshprng.c) */
+ /* (also there's a surrounding implementation struct in prng.c) */
};
prng *prng_new(const ssh_hashalg *hashalg);
void prng_free(prng *p);
@@ -1137,10 +1325,6 @@ struct X11FakeAuth {
ssh_sharing_connstate *share_cs;
share_channel *share_chan;
};
-void *x11_make_greeting(int endian, int protomajor, int protominor,
- int auth_proto, const void *auth_data, int auth_len,
- const char *peer_ip, int peer_port,
- int *outlen);
int x11_authcmp(void *av, void *bv); /* for putting X11FakeAuth in a tree234 */
/*
* x11_setup_display() parses the display variable and fills in an
@@ -1170,7 +1354,7 @@ SockAddr *platform_get_x11_unix_address(const char *path, int displaynum);
/* make up a SockAddr naming the address for displaynum */
char *platform_get_x_display(void);
/* allocated local X display string, if any */
-/* Callbacks in x11.c usable _by_ platform X11 functions */
+/* X11-related helper functions in utils */
/*
* This function does the job of platform_get_x11_auth, provided
* it is told where to find a normally formatted .Xauthority file:
@@ -1189,8 +1373,13 @@ void x11_get_auth_from_authfile(struct X11Display *display,
void x11_format_auth_for_authfile(
BinarySink *bs, SockAddr *addr, int display_no,
ptrlen authproto, ptrlen authdata);
+void *x11_make_greeting(int endian, int protomajor, int protominor,
+ int auth_proto, const void *auth_data, int auth_len,
+ const char *peer_ip, int peer_port,
+ int *outlen);
int x11_identify_auth_proto(ptrlen protoname);
void *x11_dehexify(ptrlen hex, int *outlen);
+bool x11_parse_ip(const char *addr_string, unsigned long *ip);
Channel *agentf_new(SshChannel *c);
@@ -1199,7 +1388,7 @@ dh_ctx *dh_setup_group(const ssh_kex *kex);
dh_ctx *dh_setup_gex(mp_int *pval, mp_int *gval);
int dh_modulus_bit_size(const dh_ctx *ctx);
void dh_cleanup(dh_ctx *);
-mp_int *dh_create_e(dh_ctx *, int nbits);
+mp_int *dh_create_e(dh_ctx *);
const char *dh_validate_f(dh_ctx *, mp_int *f);
mp_int *dh_find_K(dh_ctx *, mp_int *f);
@@ -1211,11 +1400,7 @@ static inline bool is_base64_char(char c)
c == '+' || c == '/' || c == '=');
}
-extern int base64_decode_atom(const char *atom, unsigned char *out);
extern int base64_lines(int datalen);
-extern void base64_encode_atom(const unsigned char *data, int n, char *out);
-extern void base64_encode(FILE *fp, const unsigned char *data, int datalen,
- int cpl);
/* ppk_load_* can return this as an error */
extern ssh2_userkey ssh2_wrong_passphrase;
@@ -1282,6 +1467,9 @@ extern const size_t n_keyalgs;
const ssh_keyalg *find_pubkey_alg(const char *name);
const ssh_keyalg *find_pubkey_alg_len(ptrlen name);
+ptrlen pubkey_blob_to_alg_name(ptrlen blob);
+const ssh_keyalg *pubkey_blob_to_alg(ptrlen blob);
+
/* Convenient wrappers on the LoadedFile mechanism suitable for key files */
LoadedFile *lf_load_keyfile(const Filename *filename, const char **errptr);
LoadedFile *lf_load_keyfile_fp(FILE *fp, const char **errptr);
@@ -1331,12 +1519,36 @@ enum {
};
typedef enum {
+ /* Default fingerprint types strip off a certificate to show you
+ * the fingerprint of the underlying public key */
SSH_FPTYPE_MD5,
SSH_FPTYPE_SHA256,
+ /* Non-default version of each fingerprint type which is 'raw',
+ * giving you the true hash of the public key blob even if it
+ * includes a certificate */
+ SSH_FPTYPE_MD5_CERT,
+ SSH_FPTYPE_SHA256_CERT,
} FingerprintType;
+static inline bool ssh_fptype_is_cert(FingerprintType fptype)
+{
+ return fptype >= SSH_FPTYPE_MD5_CERT;
+}
+static inline FingerprintType ssh_fptype_from_cert(FingerprintType fptype)
+{
+ if (ssh_fptype_is_cert(fptype))
+ fptype -= (SSH_FPTYPE_MD5_CERT - SSH_FPTYPE_MD5);
+ return fptype;
+}
+static inline FingerprintType ssh_fptype_to_cert(FingerprintType fptype)
+{
+ if (!ssh_fptype_is_cert(fptype))
+ fptype += (SSH_FPTYPE_MD5_CERT - SSH_FPTYPE_MD5);
+ return fptype;
+}
+
+#define SSH_N_FPTYPES (SSH_FPTYPE_SHA256_CERT + 1)
#define SSH_FPTYPE_DEFAULT SSH_FPTYPE_SHA256
-#define SSH_N_FPTYPES (SSH_FPTYPE_SHA256 + 1)
FingerprintType ssh2_pick_fingerprint(char **fingerprints,
FingerprintType preferred_type);
@@ -1350,6 +1562,8 @@ void ssh2_write_pubkey(FILE *fp, const char *comment,
int keytype);
char *ssh2_fingerprint_blob(ptrlen, FingerprintType);
char *ssh2_fingerprint(ssh_key *key, FingerprintType);
+char *ssh2_double_fingerprint_blob(ptrlen, FingerprintType);
+char *ssh2_double_fingerprint(ssh_key *key, FingerprintType);
char **ssh2_all_fingerprints_for_blob(ptrlen);
char **ssh2_all_fingerprints(ssh_key *key);
void ssh2_free_all_fingerprints(char **);
@@ -1361,7 +1575,7 @@ bool import_possible(int type);
int import_target_type(int type);
bool import_encrypted(const Filename *filename, int type, char **comment);
bool import_encrypted_s(const Filename *filename, BinarySource *src,
- int type, char **comment);
+ int type, char **comment);
int import_ssh1(const Filename *filename, int type,
RSAKey *key, char *passphrase, const char **errmsg_p);
int import_ssh1_s(BinarySource *src, int type,
@@ -1369,7 +1583,7 @@ int import_ssh1_s(BinarySource *src, int type,
ssh2_userkey *import_ssh2(const Filename *filename, int type,
char *passphrase, const char **errmsg_p);
ssh2_userkey *import_ssh2_s(BinarySource *src, int type,
- char *passphrase, const char **errmsg_p);
+ char *passphrase, const char **errmsg_p);
bool export_ssh1(const Filename *filename, int type,
RSAKey *key, char *passphrase);
bool export_ssh2(const Filename *filename, int type,
@@ -1389,8 +1603,7 @@ void aes256_decrypt_pubkey(const void *key, const void *iv,
void des_encrypt_xdmauth(const void *key, void *blk, int len);
void des_decrypt_xdmauth(const void *key, void *blk, int len);
-void openssh_bcrypt(const char *passphrase,
- const unsigned char *salt, int saltbytes,
+void openssh_bcrypt(ptrlen passphrase, ptrlen salt,
int rounds, unsigned char *out, int outbytes);
/*
@@ -1603,7 +1816,7 @@ enum {
/* TTY modes with opcodes defined consistently in the SSH specs. */
#define TTYMODE_CHAR(name, val, index) SSH_TTYMODE_##name = val,
#define TTYMODE_FLAG(name, val, field, mask) SSH_TTYMODE_##name = val,
- #include "sshttymodes.h"
+ #include "ssh/ttymode-list.h"
#undef TTYMODE_CHAR
#undef TTYMODE_FLAG
@@ -1667,6 +1880,7 @@ void old_keyfile_warning(void);
X(BUG_CHOKES_ON_WINADJ) \
X(BUG_SENDS_LATE_REQUEST_REPLY) \
X(BUG_SSH2_OLDGEX) \
+ X(BUG_REQUIRES_FILTERED_KEXINIT) \
/* end of list */
#define TMP_DECLARE_LOG2_ENUM(thing) log2_##thing,
enum { SSH_IMPL_BUG_LIST(TMP_DECLARE_LOG2_ENUM) };
@@ -1684,9 +1898,14 @@ unsigned alloc_channel_id_general(tree234 *channels, size_t localid_offset);
alloc_channel_id_general(tree, offsetof(type, localid)))
void add_to_commasep(strbuf *buf, const char *data);
+void add_to_commasep_pl(strbuf *buf, ptrlen data);
bool get_commasep_word(ptrlen *list, ptrlen *word);
-int verify_ssh_manual_host_key(Conf *conf, char **fingerprints, ssh_key *key);
+SeatPromptResult verify_ssh_host_key(
+ InteractionReadySeat iseat, Conf *conf, const char *host, int port,
+ ssh_key *key, const char *keytype, char *keystr, const char *keydisp,
+ char **fingerprints, int ca_count,
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
typedef struct ssh_transient_hostkey_cache ssh_transient_hostkey_cache;
ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void);
@@ -1698,3 +1917,35 @@ bool ssh_transient_hostkey_cache_verify(
bool ssh_transient_hostkey_cache_has(
ssh_transient_hostkey_cache *thc, const ssh_keyalg *alg);
bool ssh_transient_hostkey_cache_non_empty(ssh_transient_hostkey_cache *thc);
+
+/*
+ * Protocol definitions for authentication helper plugins
+ */
+
+#define AUTHPLUGIN_MSG_NAMES(X) \
+ X(PLUGIN_INIT, 1) \
+ X(PLUGIN_INIT_RESPONSE, 2) \
+ X(PLUGIN_PROTOCOL, 3) \
+ X(PLUGIN_PROTOCOL_ACCEPT, 4) \
+ X(PLUGIN_PROTOCOL_REJECT, 5) \
+ X(PLUGIN_AUTH_SUCCESS, 6) \
+ X(PLUGIN_AUTH_FAILURE, 7) \
+ X(PLUGIN_INIT_FAILURE, 8) \
+ X(PLUGIN_KI_SERVER_REQUEST, 20) \
+ X(PLUGIN_KI_SERVER_RESPONSE, 21) \
+ X(PLUGIN_KI_USER_REQUEST, 22) \
+ X(PLUGIN_KI_USER_RESPONSE, 23) \
+ /* end of list */
+
+#define PLUGIN_PROTOCOL_MAX_VERSION 2 /* the highest version we speak */
+
+enum {
+ #define ENUMDECL(name, value) name = value,
+ AUTHPLUGIN_MSG_NAMES(ENUMDECL)
+ #undef ENUMDECL
+
+ /* Error codes internal to this implementation, indicating failure
+ * to receive a meaningful packet at all */
+ PLUGIN_NOTYPE = 256, /* packet too short to have a type */
+ PLUGIN_EOF = 257 /* EOF from auth plugin */
+};