diff --git a/binaries/puttycac-0.80.zip b/binaries/puttycac-0.80.zip
deleted file mode 100644
index 677ce44..0000000
Binary files a/binaries/puttycac-0.80.zip and /dev/null differ
diff --git a/binaries/puttycac-0.81.zip b/binaries/puttycac-0.81.zip
new file mode 100644
index 0000000..c7b29e0
Binary files /dev/null and b/binaries/puttycac-0.81.zip differ
diff --git a/binaries/puttycac-64bit-0.80.zip b/binaries/puttycac-64bit-0.80.zip
deleted file mode 100644
index 859c9cd..0000000
Binary files a/binaries/puttycac-64bit-0.80.zip and /dev/null differ
diff --git a/binaries/puttycac-64bit-0.81.zip b/binaries/puttycac-64bit-0.81.zip
new file mode 100644
index 0000000..de7b1f7
Binary files /dev/null and b/binaries/puttycac-64bit-0.81.zip differ
diff --git a/binaries/puttycac-hash.txt b/binaries/puttycac-hash.txt
index 6cba7d9..5bf0d94 100644
--- a/binaries/puttycac-hash.txt
+++ b/binaries/puttycac-hash.txt
@@ -1,39 +1,39 @@
Algorithm Hash Path
--------- ---- ----
-SHA256 A5FBAD48B9FF90747CC6F387978179ECC629A316CB50C9BD3CECE723D6A3D48F x64\pageant.exe
-SHA256 209EA118E3CAB6FC1DB454CEFBFB016A6026AC845EF2C4C5C330F63ABA48E9DC x64\putty.exe
-SHA256 4B09E9889B6C98A3F5CA874375466CBE4BE76451ED76C3BE4A8B313351ADCED1 x64\puttyimp.exe
-SHA256 25F83DCC692D0F63496C6BEBEB1D5FB033B0D6F71A6A7E556B7A5DCBB2A57C7B x86\pageant.exe
-SHA256 95D555525C5881735FF8D19778F19AFF5BFC45E26C2522AFEBC836AA050312CD x86\putty.exe
-SHA256 D383A4BAE9848BCCA20DD8F971A9283C9874A54F6AD0F713084008C00695C434 x86\puttyimp.exe
-SHA256 D2420A55B4CCB1397A84B8247A9DDCD7461FFAD537635A20A063142BF4F62447 puttycac-0.80.zip
-SHA256 80620361FDAE858C28C037BDFA8B4D5709349C0144D2278784A7EAE49ED54B9D puttycac-64bit-0.80.zip
+SHA256 ED0A5A28BA717A21D85A5965A77697CE8D8110BD020DAEE118D35E92C97A1933 x64\pageant.exe
+SHA256 F7DFD9BDC0A9E43415BA1D8DCC355DC612DF43A01E158E91880F79D316B6F795 x64\putty.exe
+SHA256 42A430C5B9D8463BC9454F6A1B276509EB6C5BA9A1832CC83B04C62BCC61694D x64\puttyimp.exe
+SHA256 94FE41845319858751AB9DDD7A686CF5BDDE0D0D6C087A488B1848635A8E531A x86\pageant.exe
+SHA256 C2D1E040B7F1092D62BD3D40BE72A38DE906ACAD88E9F3186872496E02E1A3B4 x86\putty.exe
+SHA256 D7060A95ACEE8EB8D9C8D1A1718DC40463D8FACC8DF06EFE1440610B5F06E0B9 x86\puttyimp.exe
+SHA256 0281C8FE19FE463EE3E66251C483E29C409650D91ED0533D76670E4D0ED2A70E puttycac-0.81.zip
+SHA256 F14EB1946A01490A6FC7D20D023911B5971A680A47485D7F67E754E3801E43B3 puttycac-64bit-0.81.zip
Algorithm Hash Path
--------- ---- ----
-SHA1 7794CCEE7D3FC2B0D576BFBE8C5CF28CE5ACF372 x64\pageant.exe
-SHA1 4B5565FA6F0CC0BE2BE4898FA95A836F6212B01E x64\putty.exe
-SHA1 8532F03364F527D631109134153CB181E9D20554 x64\puttyimp.exe
-SHA1 525C7A3E355186C52730F444C77F9416D5635D4D x86\pageant.exe
-SHA1 1F3D5A63B54105E1972C281F379958326E274D33 x86\putty.exe
-SHA1 880B3646BC1B5B6561D4B491FF066D8306AD28BE x86\puttyimp.exe
-SHA1 746CACD101CFB33E5ECFA02899669F48B033E842 puttycac-0.80.zip
-SHA1 2F8597DE278F103E3F5610A78F55A65D8475550E puttycac-64bit-0.80.zip
+SHA1 4BE7FC935C047157B368E42F79268A0462C52B29 x64\pageant.exe
+SHA1 2DF75CCE7402A8207BE68AB51C935CE39968FD63 x64\putty.exe
+SHA1 FD8D0DC6A300112EEED215B434E1EB833181B5C0 x64\puttyimp.exe
+SHA1 A475B1B92A52B56CDDB123C9A22EE7132D778846 x86\pageant.exe
+SHA1 0ED25CD5143F99295A3628AA5C6251FEED0EE636 x86\putty.exe
+SHA1 9E451AE9BF5FA0C0B098DD9E1FE96F622256799C x86\puttyimp.exe
+SHA1 EA807CE551E765AD6BB716E258C335CFD6BB66A9 puttycac-0.81.zip
+SHA1 D02E5347EE4C1BDCCFF1E1098C202DBD8A24D6AC puttycac-64bit-0.81.zip
Algorithm Hash Path
--------- ---- ----
-MD5 B836929008B30C467371EA895F3049D5 x64\pageant.exe
-MD5 DE268F510E1FE7149F2FB3ADA18E6F3E x64\putty.exe
-MD5 1A49C1D17083D6AA700B88B7A2B4F6E3 x64\puttyimp.exe
-MD5 3F5FD4D66545E99298A385E1B1E6EF19 x86\pageant.exe
-MD5 8DEFFEFF258536386BEBF81A5326AA10 x86\putty.exe
-MD5 740D25FEA0831806C58D49EA90A3CD44 x86\puttyimp.exe
-MD5 F756A80ECF718E3EBF7F604F40FEDADE puttycac-0.80.zip
-MD5 3829581D12A227A6DBC868A3133251A8 puttycac-64bit-0.80.zip
+MD5 3921518A1324D965CA654E64658FAFBC x64\pageant.exe
+MD5 067166F560A45C6661CC9E1B6BD4BC4A x64\putty.exe
+MD5 B3D9B88B47C4AF29AECCF2682A760F9B x64\puttyimp.exe
+MD5 4540651EEF42A34597E8E2C3E8F51712 x86\pageant.exe
+MD5 AF519A08CD09FEC8C3AAFBCE4BB59256 x86\putty.exe
+MD5 AB420A22DBE73D0A9DCA50E30DAFB619 x86\puttyimp.exe
+MD5 35330A737054E008310CA06259493F88 puttycac-0.81.zip
+MD5 EE51607DCC83D8C6B55BC0B849EFD44C puttycac-64bit-0.81.zip
diff --git a/binaries/x64/pageant.exe b/binaries/x64/pageant.exe
index 6fd9417..897ee96 100644
Binary files a/binaries/x64/pageant.exe and b/binaries/x64/pageant.exe differ
diff --git a/binaries/x64/putty.exe b/binaries/x64/putty.exe
index 1fe3a04..a8ed7f0 100644
Binary files a/binaries/x64/putty.exe and b/binaries/x64/putty.exe differ
diff --git a/binaries/x64/puttyimp.exe b/binaries/x64/puttyimp.exe
index 0bb62b8..d0d411e 100644
Binary files a/binaries/x64/puttyimp.exe and b/binaries/x64/puttyimp.exe differ
diff --git a/binaries/x86/pageant.exe b/binaries/x86/pageant.exe
index 16ae1b0..bd91d56 100644
Binary files a/binaries/x86/pageant.exe and b/binaries/x86/pageant.exe differ
diff --git a/binaries/x86/putty.exe b/binaries/x86/putty.exe
index 37d55a1..cc814a1 100644
Binary files a/binaries/x86/putty.exe and b/binaries/x86/putty.exe differ
diff --git a/binaries/x86/puttyimp.exe b/binaries/x86/puttyimp.exe
index d349dcd..5c9c45f 100644
Binary files a/binaries/x86/puttyimp.exe and b/binaries/x86/puttyimp.exe differ
diff --git a/code/Buildscr b/code/Buildscr
index 8c74551..5049e76 100644
--- a/code/Buildscr
+++ b/code/Buildscr
@@ -35,7 +35,7 @@ module putty
ifeq "$(RELEASE)" "" set Ndate $(!builddate)
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -pe 's/(....)(..)(..)/$$1-$$2-$$3/' > date
ifneq "$(Ndate)" "" read Date date
-set Epoch 18707 # update this at every release
+set Epoch 18819 # update this at every release
ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -ne 'use Time::Local; /(....)(..)(..)/ and print timegm(0,0,0,$$3,$$2-1,$$1) / 86400 - $(Epoch)' > days
ifneq "$(Ndate)" "" read Days days
diff --git a/code/cmake/setup.cmake b/code/cmake/setup.cmake
index d81d5a5..1be448d 100644
--- a/code/cmake/setup.cmake
+++ b/code/cmake/setup.cmake
@@ -108,6 +108,14 @@ include_directories(
${platform}
${extra_dirs})
+check_c_source_compiles("
+#define _ISOC11_SOURCE
+#include
+int main(int argc, char **argv) {
+ void *p = aligned_alloc(128, 12345);
+ free(p);
+}" HAVE_ALIGNED_ALLOC)
+
if(PUTTY_DEBUG)
add_compile_definitions(DEBUG)
endif()
diff --git a/code/crypto/CMakeLists.txt b/code/crypto/CMakeLists.txt
index 4b0aa90..edb02ce 100644
--- a/code/crypto/CMakeLists.txt
+++ b/code/crypto/CMakeLists.txt
@@ -30,6 +30,7 @@ add_sources_from_current_dir(crypto
pubkey-pem.c
pubkey-ppk.c
pubkey-ssh1.c
+ rfc6979.c
rsa.c
sha256-common.c
sha256-select.c
diff --git a/code/crypto/dsa.c b/code/crypto/dsa.c
index 71fcd94..1999a1c 100644
--- a/code/crypto/dsa.c
+++ b/code/crypto/dsa.c
@@ -340,117 +340,6 @@ static int dsa_pubkey_bits(const ssh_keyalg *self, ptrlen pub)
return ret;
}
-mp_int *dsa_gen_k(const char *id_string, mp_int *modulus,
- mp_int *private_key,
- unsigned char *digest, int digest_len)
-{
- /*
- * The basic DSA signing algorithm is:
- *
- * - invent a random k between 1 and q-1 (exclusive).
- * - Compute r = (g^k mod p) mod q.
- * - Compute s = k^-1 * (hash + x*r) mod q.
- *
- * This has the dangerous properties that:
- *
- * - if an attacker in possession of the public key _and_ the
- * signature (for example, the host you just authenticated
- * to) can guess your k, he can reverse the computation of s
- * and work out x = r^-1 * (s*k - hash) mod q. That is, he
- * can deduce the private half of your key, and masquerade
- * as you for as long as the key is still valid.
- *
- * - since r is a function purely of k and the public key, if
- * the attacker only has a _range of possibilities_ for k
- * it's easy for him to work through them all and check each
- * one against r; he'll never be unsure of whether he's got
- * the right one.
- *
- * - if you ever sign two different hashes with the same k, it
- * will be immediately obvious because the two signatures
- * will have the same r, and moreover an attacker in
- * possession of both signatures (and the public key of
- * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
- * and from there deduce x as before.
- *
- * - the Bleichenbacher attack on DSA makes use of methods of
- * generating k which are significantly non-uniformly
- * distributed; in particular, generating a 160-bit random
- * number and reducing it mod q is right out.
- *
- * For this reason we must be pretty careful about how we
- * generate our k. Since this code runs on Windows, with no
- * particularly good system entropy sources, we can't trust our
- * RNG itself to produce properly unpredictable data. Hence, we
- * use a totally different scheme instead.
- *
- * What we do is to take a SHA-512 (_big_) hash of the private
- * key x, and then feed this into another SHA-512 hash that
- * also includes the message hash being signed. That is:
- *
- * proto_k = SHA512 ( SHA512(x) || SHA160(message) )
- *
- * This number is 512 bits long, so reducing it mod q won't be
- * noticeably non-uniform. So
- *
- * k = proto_k mod q
- *
- * This has the interesting property that it's _deterministic_:
- * signing the same hash twice with the same key yields the
- * same signature.
- *
- * Despite this determinism, it's still not predictable to an
- * attacker, because in order to repeat the SHA-512
- * construction that created it, the attacker would have to
- * know the private key value x - and by assumption he doesn't,
- * because if he knew that he wouldn't be attacking k!
- *
- * (This trick doesn't, _per se_, protect against reuse of k.
- * Reuse of k is left to chance; all it does is prevent
- * _excessively high_ chances of reuse of k due to entropy
- * problems.)
- *
- * Thanks to Colin Plumb for the general idea of using x to
- * ensure k is hard to guess, and to the Cambridge University
- * Computer Security Group for helping to argue out all the
- * fine details.
- */
- ssh_hash *h;
- unsigned char digest512[64];
-
- /*
- * Hash some identifying text plus x.
- */
- h = ssh_hash_new(&ssh_sha512);
- put_asciz(h, id_string);
- put_mp_ssh2(h, private_key);
- ssh_hash_digest(h, digest512);
-
- /*
- * Now hash that digest plus the message hash.
- */
- ssh_hash_reset(h);
- put_data(h, digest512, sizeof(digest512));
- put_data(h, digest, digest_len);
- ssh_hash_final(h, digest512);
-
- /*
- * Now convert the result into a bignum, and coerce it to the
- * range [2,q), which we do by reducing it mod q-2 and adding 2.
- */
- mp_int *modminus2 = mp_copy(modulus);
- mp_sub_integer_into(modminus2, modminus2, 2);
- mp_int *proto_k = mp_from_bytes_be(make_ptrlen(digest512, 64));
- mp_int *k = mp_mod(proto_k, modminus2);
- mp_free(proto_k);
- mp_free(modminus2);
- mp_add_integer_into(k, k, 2);
-
- smemclr(digest512, sizeof(digest512));
-
- return k;
-}
-
static void dsa_sign(ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs)
{
struct dsa_key *dsa = container_of(key, struct dsa_key, sshk);
@@ -459,8 +348,9 @@ static void dsa_sign(ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs)
hash_simple(&ssh_sha1, data, digest);
- mp_int *k = dsa_gen_k("DSA deterministic k generator", dsa->q, dsa->x,
- digest, sizeof(digest));
+ /* Generate any valid exponent k, using the RFC 6979 deterministic
+ * procedure. */
+ mp_int *k = rfc6979(&ssh_sha1, dsa->q, dsa->x, data);
mp_int *kinv = mp_invert(k, dsa->q); /* k^-1 mod q */
/*
diff --git a/code/crypto/ecc-ssh.c b/code/crypto/ecc-ssh.c
index 35b9630..30dccf2 100644
--- a/code/crypto/ecc-ssh.c
+++ b/code/crypto/ecc-ssh.c
@@ -1126,16 +1126,10 @@ static void ecdsa_sign(ssh_key *key, ptrlen data,
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 = dsa_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;
diff --git a/code/crypto/hmac.c b/code/crypto/hmac.c
index cc25582..afec9ef 100644
--- a/code/crypto/hmac.c
+++ b/code/crypto/hmac.c
@@ -18,9 +18,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);
@@ -64,6 +65,11 @@ static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
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);
@@ -277,3 +283,38 @@ const ssh2_macalg ssh_hmac_sha1_96_buggy = {
.keylen = 16,
.extra = &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.next_message = nullmac_next_message;
+ 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);
+}
diff --git a/code/crypto/rfc6979.c b/code/crypto/rfc6979.c
new file mode 100644
index 0000000..73e5c92
--- /dev/null
+++ b/code/crypto/rfc6979.c
@@ -0,0 +1,359 @@
+/*
+ * Code to generate 'nonce' values for DSA signature algorithms, in a
+ * deterministic way.
+ */
+
+#include "ssh.h"
+#include "mpint.h"
+#include "misc.h"
+
+/*
+ * All DSA-type signature systems depend on a nonce - a random number
+ * generated during the signing operation.
+ *
+ * This nonce is a weak point of DSA and needs careful protection,
+ * for multiple reasons:
+ *
+ * 1. If an attacker in possession of your public key and a single
+ * signature can find out or guess the nonce you used in that
+ * signature, they can immediately recover your _private key_.
+ *
+ * 2. If you reuse the same nonce in two different signatures, this
+ * will be instantly obvious to the attacker (one of the two
+ * values making up the signature will match), and again, they can
+ * immediately recover the private key as soon as they notice this.
+ *
+ * 3. In at least one system, information about your private key is
+ * leaked merely by generating nonces with a significant bias.
+ *
+ * Attacks #1 and #2 work across all of integer DSA, NIST-style ECDSA,
+ * and EdDSA. The details vary, but the headline effects are the same.
+ *
+ * So we must be very careful with our nonces. They must be generated
+ * with uniform distribution, but also, they must avoid depending on
+ * any random number generator that has the slightest doubt about its
+ * reliability.
+ *
+ * In particular, PuTTY's policy is that for this purpose we don't
+ * _even_ trust the PRNG we use for other cryptography. This is mostly
+ * a concern because of Windows, where system entropy sources are
+ * limited and we have doubts about their trustworthiness
+ * - even CryptGenRandom. PuTTY compensates as best it can with its
+ * own ongoing entropy collection, and we trust that for session keys,
+ * but revealing the private key that goes with a long-term public key
+ * is a far worse outcome than revealing one SSH session key, and for
+ * keeping your private key safe, we don't think the available Windows
+ * entropy gives us enough confidence.
+ *
+ * A common strategy these days (although PuTTY was doing it
+ * before it was cool) is to avoid using a PRNG based on
+ * system entropy at all. Instead, you use a deterministic PRNG that
+ * starts from a fixed input seed, and in that input seed you include
+ * the message to be signed and the _private key_.
+ *
+ * Including the private key in the seed is counterintuitive, but does
+ * actually make sense. A deterministic nonce generation strategy must
+ * use _some_ piece of input that the attacker doesn't have, or else
+ * they'd be able to repeat the entire computation and construct the
+ * same nonce you did. And the one thing they don't know is the
+ * private key! So we include that in the seed data (under enough
+ * layers of overcautious hashing to protect it against exposure), and
+ * then they _can't_ repeat the same construction. Moreover, if they
+ * _could_, they'd already know the private key, so they wouldn't need
+ * to perform an attack of this kind at all!
+ *
+ * (This trick doesn't, _per se_, protect against reuse of nonces.
+ * That is left to chance, which is enough, because the space of
+ * nonces is large enough to make it adequately unlikely. But it
+ * avoids escalating the reuse risk due to inadequate entropy.)
+ *
+ * For integer DSA and ECDSA, the system we use for deterministic
+ * generation of k is exactly the one specified in RFC 6979. We
+ * switched to this from the old system that PuTTY used to use before
+ * that RFC came out. The old system had a critical bug: it did not
+ * always generate _enough_ data to get uniform distribution, because
+ * its output was a single SHA-512 hash. We could have fixed that
+ * minimally, by concatenating multiple hashes, but it seemed more
+ * sensible to switch to a system that comes with test vectors.
+ *
+ * One downside of RFC 6979 is that it's based on rejection sampling
+ * (that is, you generate a random number and keep retrying until it's
+ * in range). This makes it play badly with our side-channel test
+ * system, which wants every execution trace of a supposedly
+ * constant-time operation to be the same. To work around this
+ * awkwardness, we break up the algorithm further, into a setup phase
+ * and an 'attempt to generate an output' phase, each of which is
+ * individually constant-time.
+ */
+
+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.
+ *
+ * We do this unconditionally, whether or not the k we just
+ * generated is acceptable. The time cost isn't large compared to
+ * the public-key operation we're going to do next (not to mention
+ * the larger number of these same operations we've already done),
+ * and it makes side-channel testing easier if this function is
+ * constant-time from beginning to end.
+ *
+ * In other rejection-sampling situations, particularly prime
+ * generation, we're not this careful: it's enough to ensure that
+ * _successful_ attempts run in constant time, Failures can do
+ * whatever they like, on the theory that the only information
+ * they _have_ to potentially expose via side channels is
+ * information that was subsequently thrown away without being
+ * used for anything important. (Hence, for example, it's fine to
+ * have multiple different early-exit paths for failures you
+ * detect at different times.)
+ *
+ * But here, the situation is different. Prime generation attempts
+ * are independent of each other. These are not. All our
+ * iterations round this loop use the _same_ secret data set up by
+ * rfc6979_new(), and also, the perturbation step we're about to
+ * compute will be used by the next iteration if there is one. So
+ * it's absolutely _not_ true that a failed iteration deals
+ * exclusively with data that won't contribute to the eventual
+ * output. Hence, we have to be careful about the failures as well
+ * as the successes.
+ *
+ * (Even so, it would be OK to make successes and failures take
+ * different amounts of time, as long as each of those amounts was
+ * consistent. But it's easier for testing to make them the same.)
+ */
+ 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;
+}
diff --git a/code/defs.h b/code/defs.h
index 286e0c9..8b1f271 100644
--- a/code/defs.h
+++ b/code/defs.h
@@ -177,6 +177,8 @@ typedef struct ecdh_key ecdh_key;
typedef struct ecdh_keyalg ecdh_keyalg;
typedef struct NTRUKeyPair NTRUKeyPair;
typedef struct NTRUEncodeSchedule NTRUEncodeSchedule;
+typedef struct RFC6979 RFC6979;
+typedef struct RFC6979Result RFC6979Result;
typedef struct dlgparam dlgparam;
typedef struct dlgcontrol dlgcontrol;
diff --git a/code/doc/html/AppendixA.html b/code/doc/html/AppendixA.html
index e6cb572..3cc8589 100644
--- a/code/doc/html/AppendixA.html
+++ b/code/doc/html/AppendixA.html
@@ -1023,5 +1023,5 @@ A.10.4 How do I pronounce
If you want to provide feedback on this manual or on the PuTTY tools themselves, see the Feedback page.
-[PuTTY release 0.80]