Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:ecsos:branches:OBS_Maintained:filezilla
filezilla.openSUSE_Backports_SLE-15-SP5_Update
filezilla-putty.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File filezilla-putty.patch of Package filezilla.openSUSE_Backports_SLE-15-SP5_Update
Index: filezilla-3.54.1/src/putty/Makefile.am =================================================================== --- filezilla-3.54.1.orig/src/putty/Makefile.am +++ filezilla-3.54.1/src/putty/Makefile.am @@ -10,6 +10,7 @@ libfzputtycommon_a_SOURCES = \ memory.c \ misc.c \ mpint.c \ + rfc6979.c \ sshaes.c \ sshauxcrypt.c \ sshbcrypt.c \ Index: filezilla-3.54.1/src/putty/defs.h =================================================================== --- filezilla-3.54.1.orig/src/putty/defs.h +++ filezilla-3.54.1/src/putty/defs.h @@ -141,6 +141,8 @@ typedef struct ssh_cipher ssh_cipher; typedef struct ssh2_ciphers ssh2_ciphers; typedef struct dh_ctx dh_ctx; typedef struct ecdh_key ecdh_key; +typedef struct RFC6979 RFC6979; +typedef struct RFC6979Result RFC6979Result; typedef struct dlgparam dlgparam; Index: filezilla-3.54.1/src/putty/rfc6979.c =================================================================== --- /dev/null +++ filezilla-3.54.1/src/putty/rfc6979.c @@ -0,0 +1,250 @@ +/* + * Code to generate 'nonce' values for DSA signature algorithms, in a + * deterministic way. + */ + +#include "ssh.h" +#include "mpint.h" +#include "misc.h" + +struct RFC6979 { + /* + * Size of the cyclic group over which we're doing DSA. + * Equivalently, the multiplicative order of g (for integer DSA) + * or the curve's base point (for ECDSA). For integer DSA this is + * also the same thing as the small prime q from the key + * parameters. + * + * This pointer is not owned. Freeing this structure will not free + * it, and freeing the pointed-to integer before freeing this + * structure will make this structure dangerous to use. + */ + mp_int *q; + + /* + * The private key integer, which is always the discrete log of + * the public key with respect to the group generator. + * + * This pointer is not owned. Freeing this structure will not free + * it, and freeing the pointed-to integer before freeing this + * structure will make this structure dangerous to use. + */ + mp_int *x; + + /* + * Cached values derived from q: its length in bits, and in bytes. + */ + size_t qbits, qbytes; + + /* + * Reusable hash and MAC objects. + */ + ssh_hash *hash; + ssh2_mac *mac; + + /* + * Cached value: the output length of the hash. + */ + size_t hlen; + + /* + * The byte string V used in the algorithm. + */ + unsigned char V[MAX_HASH_LEN]; + + /* + * The string T to use during each attempt, and how many + * hash-sized blocks to fill it with. + */ + size_t T_nblocks; + unsigned char *T; +}; + +static mp_int *bits2int(ptrlen b, RFC6979 *s) +{ + if (b.len > s->qbytes) + b.len = s->qbytes; + mp_int *x = mp_from_bytes_be(b); + + /* + * Rationale for using mp_rshift_fixed_into and not + * mp_rshift_safe_into: the shift count is derived from the + * difference between the length of the modulus q, and the length + * of the input bit string, i.e. between the _sizes_ of things + * involved in the protocol. But the sizes aren't secret. Only the + * actual values of integers and bit strings of those sizes are + * secret. So it's OK for the shift count to be known to an + * attacker - they'd know it anyway just from which DSA algorithm + * we were using. + */ + if (b.len * 8 > s->qbits) + mp_rshift_fixed_into(x, x, b.len * 8 - s->qbits); + + return x; +} + +static void BinarySink_put_int2octets(BinarySink *bs, mp_int *x, RFC6979 *s) +{ + mp_int *x_mod_q = mp_mod(x, s->q); + for (size_t i = s->qbytes; i-- > 0 ;) + put_byte(bs, mp_get_byte(x_mod_q, i)); + mp_free(x_mod_q); +} + +static void BinarySink_put_bits2octets(BinarySink *bs, ptrlen b, RFC6979 *s) +{ + mp_int *x = bits2int(b, s); + BinarySink_put_int2octets(bs, x, s); + mp_free(x); +} + +#define put_int2octets(bs, x, s) \ + BinarySink_put_int2octets(BinarySink_UPCAST(bs), x, s) +#define put_bits2octets(bs, b, s) \ + BinarySink_put_bits2octets(BinarySink_UPCAST(bs), b, s) + +RFC6979 *rfc6979_new(const ssh_hashalg *hashalg, mp_int *q, mp_int *x) +{ + /* Make the state structure. */ + RFC6979 *s = snew(RFC6979); + s->q = q; + s->x = x; + s->qbits = mp_get_nbits(q); + s->qbytes = (s->qbits + 7) >> 3; + s->hash = ssh_hash_new(hashalg); + s->mac = hmac_new_from_hash(hashalg); + s->hlen = hashalg->hlen; + + /* In each attempt, we concatenate enough hash blocks to be + * greater than qbits in size. */ + size_t hbits = 8 * s->hlen; + s->T_nblocks = (s->qbits + hbits - 1) / hbits; + s->T = snewn(s->T_nblocks * s->hlen, unsigned char); + + return s; +} + +void rfc6979_setup(RFC6979 *s, ptrlen message) +{ + unsigned char h1[MAX_HASH_LEN]; + unsigned char K[MAX_HASH_LEN]; + + /* 3.2 (a): hash the message to get h1. */ + ssh_hash_reset(s->hash); + put_datapl(s->hash, message); + ssh_hash_digest(s->hash, h1); + + /* 3.2 (b): set V to a sequence of 0x01 bytes the same size as the + * hash function's output. */ + memset(s->V, 1, s->hlen); + + /* 3.2 (c): set the initial HMAC key K to all zeroes, again the + * same size as the hash function's output. */ + memset(K, 0, s->hlen); + ssh2_mac_setkey(s->mac, make_ptrlen(K, s->hlen)); + + /* 3.2 (d): compute the MAC of V, the private key, and h1, with + * key K, making a new key to replace K. */ + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + put_byte(s->mac, 0); + put_int2octets(s->mac, s->x, s); + put_bits2octets(s->mac, make_ptrlen(h1, s->hlen), s); + ssh2_mac_genresult(s->mac, K); + ssh2_mac_setkey(s->mac, make_ptrlen(K, s->hlen)); + + /* 3.2 (e): replace V with its HMAC using the new K. */ + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + ssh2_mac_genresult(s->mac, s->V); + + /* 3.2 (f): repeat step (d), only using the new K in place of the + * initial all-zeroes one, and with the extra byte in the middle + * of the MAC preimage being 1 rather than 0. */ + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + put_byte(s->mac, 1); + put_int2octets(s->mac, s->x, s); + put_bits2octets(s->mac, make_ptrlen(h1, s->hlen), s); + ssh2_mac_genresult(s->mac, K); + ssh2_mac_setkey(s->mac, make_ptrlen(K, s->hlen)); + + /* 3.2 (g): repeat step (e), using the again-replaced K. */ + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + ssh2_mac_genresult(s->mac, s->V); + + smemclr(h1, sizeof(h1)); + smemclr(K, sizeof(K)); +} + +RFC6979Result rfc6979_attempt(RFC6979 *s) +{ + RFC6979Result result; + + /* 3.2 (h) 1: set T to the empty string */ + /* 3.2 (h) 2: make lots of output by concatenating MACs of V */ + for (size_t i = 0; i < s->T_nblocks; i++) { + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + ssh2_mac_genresult(s->mac, s->V); + memcpy(s->T + i * s->hlen, s->V, s->hlen); + } + + /* 3.2 (h) 3: if we have a number in [1, q-1], return it ... */ + result.k = bits2int(make_ptrlen(s->T, s->T_nblocks * s->hlen), s); + result.ok = mp_hs_integer(result.k, 1) & ~mp_cmp_hs(result.k, s->q); + + /* + * Perturb K and regenerate V ready for the next attempt. + */ + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + put_byte(s->mac, 0); + unsigned char K[MAX_HASH_LEN]; + ssh2_mac_genresult(s->mac, K); + ssh2_mac_setkey(s->mac, make_ptrlen(K, s->hlen)); + smemclr(K, sizeof(K)); + + ssh2_mac_start(s->mac); + put_data(s->mac, s->V, s->hlen); + ssh2_mac_genresult(s->mac, s->V); + + return result; +} + +void rfc6979_free(RFC6979 *s) +{ + /* We don't free s->q or s->x: our caller still owns those. */ + + ssh_hash_free(s->hash); + ssh2_mac_free(s->mac); + smemclr(s->T, s->T_nblocks * s->hlen); + sfree(s->T); + + /* Clear the whole structure before freeing. Most fields aren't + * sensitive (pointers or well-known length values), but V is, and + * it's easier to clear the whole lot than fiddle about + * identifying the sensitive fields. */ + smemclr(s, sizeof(*s)); + + sfree(s); +} + +mp_int *rfc6979( + const ssh_hashalg *hashalg, mp_int *q, mp_int *x, ptrlen message) +{ + RFC6979 *s = rfc6979_new(hashalg, q, x); + rfc6979_setup(s, message); + RFC6979Result result; + while (true) { + result = rfc6979_attempt(s); + if (result.ok) + break; + else + mp_free(result.k); + } + rfc6979_free(s); + return result.k; +} + Index: filezilla-3.54.1/src/putty/ssh.h =================================================================== --- filezilla-3.54.1.orig/src/putty/ssh.h +++ filezilla-3.54.1/src/putty/ssh.h @@ -589,11 +589,18 @@ void ssh_ecdhkex_getpublic(ecdh_key *key mp_int *ssh_ecdhkex_getkey(ecdh_key *key, ptrlen remoteKey); /* - * Helper function for k generation in DSA, reused in ECDSA + * System for generating k in DSA and ECDSA. */ -mp_int *dss_gen_k(const char *id_string, - mp_int *modulus, mp_int *private_key, - unsigned char *digest, int digest_len); +struct RFC6979Result { + mp_int *k; + unsigned ok; +}; +RFC6979 *rfc6979_new(const ssh_hashalg *hashalg, mp_int *q, mp_int *x); +void rfc6979_setup(RFC6979 *s, ptrlen message); +RFC6979Result rfc6979_attempt(RFC6979 *s); +void rfc6979_free(RFC6979 *s); +mp_int *rfc6979(const ssh_hashalg *hashalg, mp_int *modulus, + mp_int *private_key, ptrlen message); struct ssh_cipher { const ssh_cipheralg *vt; @@ -710,6 +717,11 @@ bool ssh2_mac_verify(ssh2_mac *, const v * string with a given key in the most obvious way. */ void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output); +/* Constructor that makes an HMAC object given just a MAC. This object + * will have empty 'name' and 'etm_name' fields, so it's not suitable + * for use in SSH. It's used as a subroutine in RFC 6979. */ +ssh2_mac *hmac_new_from_hash(const ssh_hashalg *hash); + struct ssh_hash { const ssh_hashalg *vt; BinarySink_DELEGATE_IMPLEMENTATION; @@ -954,6 +966,8 @@ extern const ssh2_macalg ssh_hmac_sha1_b 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 ssh_hmac_sha384; +extern const ssh2_macalg ssh_hmac_sha512; extern const ssh2_macalg ssh2_poly1305; extern const ssh_compression_alg ssh_zlib; Index: filezilla-3.54.1/src/putty/sshdss.c =================================================================== --- filezilla-3.54.1.orig/src/putty/sshdss.c +++ filezilla-3.54.1/src/putty/sshdss.c @@ -436,8 +436,9 @@ static void dss_sign(ssh_key *key, ptrle hash_simple(&ssh_sha1, data, digest); - mp_int *k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x, - digest, sizeof(digest)); + /* Generate any valid exponent k, using the RFC 6979 deterministic + * procedure. */ + mp_int *k = rfc6979(&ssh_sha1, dss->q, dss->x, data); mp_int *kinv = mp_invert(k, dss->q); /* k^-1 mod q */ /* Index: filezilla-3.54.1/src/putty/sshecc.c =================================================================== --- filezilla-3.54.1.orig/src/putty/sshecc.c +++ filezilla-3.54.1/src/putty/sshecc.c @@ -997,16 +997,10 @@ static void ecdsa_sign(ssh_key *key, ptr mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data); - /* Generate k between 1 and curve->n, using the same deterministic - * k generation system we use for conventional DSA. */ - mp_int *k; - { - unsigned char digest[20]; - hash_simple(&ssh_sha1, data, digest); - k = dss_gen_k( - "ECDSA deterministic k generator", ek->curve->w.G_order, - ek->privateKey, digest, sizeof(digest)); - } + /* Generate any valid exponent k, using the RFC 6979 deterministic + * procedure. */ + mp_int *k = rfc6979( + extra->hash, ek->curve->w.G_order, ek->privateKey, data); WeierstrassPoint *kG = ecc_weierstrass_multiply(ek->curve->w.G, k); mp_int *x; @@ -1156,7 +1150,7 @@ static const unsigned char nistp256_oid[ }; const struct ecsign_extra sign_extra_nistp256 = { ec_p256, &ssh_sha256, - nistp256_oid, lenof(nistp256_oid), + nistp256_oid, lenof(nistp256_oid), "NIST p256", }; const ssh_keyalg ssh_ecdsa_nistp256 = { ecdsa_new_pub, @@ -1186,7 +1180,7 @@ static const unsigned char nistp384_oid[ }; const struct ecsign_extra sign_extra_nistp384 = { ec_p384, &ssh_sha384, - nistp384_oid, lenof(nistp384_oid), + nistp384_oid, lenof(nistp384_oid), "NIST p384", }; const ssh_keyalg ssh_ecdsa_nistp384 = { ecdsa_new_pub, @@ -1216,7 +1210,7 @@ static const unsigned char nistp521_oid[ }; const struct ecsign_extra sign_extra_nistp521 = { ec_p521, &ssh_sha512, - nistp521_oid, lenof(nistp521_oid), + nistp521_oid, lenof(nistp521_oid), "NIST p521", }; const ssh_keyalg ssh_ecdsa_nistp521 = { ecdsa_new_pub, Index: filezilla-3.54.1/src/putty/sshhmac.c =================================================================== --- filezilla-3.54.1.orig/src/putty/sshhmac.c +++ filezilla-3.54.1/src/putty/sshhmac.c @@ -19,9 +19,10 @@ struct hmac_extra { const char *suffix, *annotation; }; -static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher) +/* Most of hmac_new(). Takes the actual 'struct hmac' as a parameter, + * because sometimes it will have been allocated in a special way. */ +static ssh2_mac *hmac_new_inner(struct hmac *ctx, const ssh2_macalg *alg) { - struct hmac *ctx = snew(struct hmac); const struct hmac_extra *extra = (const struct hmac_extra *)alg->extra; ctx->h_outer = ssh_hash_new(extra->hashalg_base); @@ -66,6 +67,11 @@ static ssh2_mac *hmac_new(const ssh2_mac return &ctx->mac; } +static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher) +{ + return hmac_new_inner(snew(struct hmac), alg); /* cipher isn't needed */ +} + static void hmac_free(ssh2_mac *mac) { struct hmac *ctx = container_of(mac, struct hmac, mac); @@ -242,3 +248,37 @@ const ssh2_macalg ssh_hmac_sha1_96_buggy "hmac-sha1-96", NULL, 12, 16, &ssh_hmac_sha1_96_buggy_extra, }; + +ssh2_mac *hmac_new_from_hash(const ssh_hashalg *hash) +{ + /* + * Construct a custom ssh2_macalg, derived directly from the + * provided hash vtable. It's included in the same memory + * allocation as the struct hmac, so that it all gets freed + * together. + */ + + struct alloc { + struct hmac hmac; + ssh2_macalg alg; + struct hmac_extra extra; + }; + + struct alloc *alloc = snew(struct alloc); + alloc->alg.new = hmac_new; + alloc->alg.free = hmac_free; + alloc->alg.setkey = hmac_key; + alloc->alg.start = hmac_start; + alloc->alg.genresult = hmac_genresult; + alloc->alg.text_name = hmac_text_name; + alloc->alg.name = NULL; + alloc->alg.etm_name = NULL; + alloc->alg.len = hash->hlen; + alloc->alg.keylen = hash->hlen; + alloc->alg.extra = &alloc->extra; + alloc->extra.hashalg_base = hash; + alloc->extra.suffix = ""; + alloc->extra.annotation = NULL; + + return hmac_new_inner(&alloc->hmac, &alloc->alg); +}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor