diff options
Diffstat (limited to 'ssh.h')
-rw-r--r-- | ssh.h | 375 |
1 files changed, 313 insertions, 62 deletions
@@ -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 */ +}; |