1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00
Commit Graph

81 Commits

Author SHA1 Message Date
Simon Tatham
6dc6392596 Remove obsolete functions.
There are several old functions that the previous commits have removed
all, or nearly all, of the references to. match_ssh_id is superseded
by ptrlen_eq_string; get_ssh_{string,uint32} is yet another replicated
set of decode functions (this time _partly_ centralised into misc.c);
the old APIs for the SSH-1 RSA decode functions are gone (together
with their last couple of holdout clients), as are
ssh{1,2}_{read,write}_bignum and ssh{1,2}_bignum_length.

Particularly odd was the use of ssh1_{read,write}_bignum in the SSH-2
Diffie-Hellman implementation. I'd completely forgotten I did that!
Now replaced with a raw bignum_from_bytes, which is simpler anyway.
2018-06-02 18:24:12 +01:00
Simon Tatham
005ca6b257 Introduce a centralised unmarshaller, 'BinarySource'.
This is the companion to the BinarySink system I introduced a couple
of weeks ago, and provides the same type-genericity which will let me
use the same get_* routines on an SSH packet, an SFTP packet or
anything else that chooses to include an implementing substructure.

However, unlike BinarySink which contained a (one-function) vtable,
BinarySource contains only mutable data fields - so another thing you
might very well want to do is to simply instantiate a bare one without
any containing object at all. I couldn't quite coerce C into letting
me use the same setup macro in both cases, so I've arranged a
BinarySource_INIT you can use on larger implementing objects and a
BinarySource_BARE_INIT you can use on a BinarySource not contained in
anything.

The API follows the general principle that even if decoding fails, the
decode functions will always return _some_ kind of value, with the
same dynamically-allocated-ness they would have used for a completely
successful value. But they also set an error flag in the BinarySource
which can be tested later. So instead of having to decode a 10-field
packet by means of 10 separate 'if (!get_foo(src)) throw error'
clauses, you can just write 10 'variable = get_foo(src)' statements
followed by a single check of get_err(src), and if the error check
fails, you have to do exactly the same set of frees you would have
after a successful decode.
2018-06-02 17:37:22 +01:00
Simon Tatham
7babe66a83 Make lots of generic data parameters into 'void *'.
This is a cleanup I started to notice a need for during the BinarySink
work. It removes a lot of faffing about casting things to char * or
unsigned char * so that some API will accept them, even though lots of
such APIs really take a plain 'block of raw binary data' argument and
don't care what C thinks the signedness of that data might be - they
may well reinterpret it back and forth internally.

So I've tried to arrange for all the function call APIs that ought to
have a void * (or const void *) to have one, and those that need to do
pointer arithmetic on the parameter internally can cast it back at the
top of the function. That saves endless ad-hoc casts at the call
sites.
2018-05-26 09:22:43 +01:00
Simon Tatham
0e3082ee89 New centralised binary-data marshalling system.
I've finally got tired of all the code throughout PuTTY that repeats
the same logic about how to format the SSH binary primitives like
uint32, string, mpint. We've got reasonably organised code in ssh.c
that appends things like that to 'struct Packet'; something similar in
sftp.c which repeats a lot of the work; utility functions in various
places to format an mpint to feed to one or another hash function; and
no end of totally ad-hoc stuff in functions like public key blob
formatters which actually have to _count up_ the size of data
painstakingly, then malloc exactly that much and mess about with
PUT_32BIT.

It's time to bring all of that into one place, and stop repeating
myself in error-prone ways everywhere. The new marshal.h defines a
system in which I centralise all the actual marshalling functions, and
then layer a touch of C macro trickery on top to allow me to (look as
if I) pass a wide range of different types to those functions, as long
as the target type has been set up in the right way to have a write()
function.

This commit adds the new header and source file, and sets up some
general centralised types (strbuf and the various hash-function
contexts like SHA_State), but doesn't use the new calls for anything
yet.

(I've also renamed some internal functions in import.c which were
using the same names that I've just defined macros over. That won't
last long - those functions are going to go away soon, so the changed
names are strictly temporary.)
2018-05-25 14:36:16 +01:00
Tim Kosse
1bfde9dc52 Fix memory leak in bignum_from_decimal
Intermediate result values were not freed.
2017-01-28 14:03:09 +00:00
Simon Tatham
daeeca55a4 Promote 'testbn' to a binary built by the makefiles.
This makes it easier to compile in multiple debugging modes, or on
Windows, without having to constantly paste annoying test-compile
commands out of comments in sshbn.c.

The new binary is compiled into the build directory, but not shipped
by 'make install', just like fuzzterm. Unlike fuzzterm, though, testbn
is also compiled on Windows, for which we didn't already have a
mechanism for building unshipped binaries; I've done the very simplest
thing for the moment, of providing a target in Makefile.vc to delete
them.

In order to comply with the PuTTY makefile system's constraint of
never compiling the same object multiple times with different ifdefs,
I've also moved testbn's main() out into its own source file.
2015-12-16 15:26:31 +00:00
Simon Tatham
c2ec13c7e9 Relegate BignumDblInt to an implementation detail of sshbn.h.
As I mentioned in the previous commit, I'm going to want PuTTY to be
able to run sensibly when compiled with 64-bit Visual Studio,
including handling bignums in 64-bit chunks for speed. Unfortunately,
64-bit VS does not provide any type we can use as BignumDblInt in that
situation (unlike 64-bit gcc and clang, which give us __uint128_t).
The only facilities it provides are compiler intrinsics to access an
add-with-carry operation and a 64x64->128 multiplication (the latter
delivering its product in two separate 64-bit output chunks).

Hence, here's a substantial rework of the bignum code to make it
implement everything in terms of _those_ primitives, rather than
depending throughout on having BignumDblInt available to use ad-hoc.
BignumDblInt does still exist, for the moment, but now it's an
internal implementation detail of sshbn.h, only declared inside a new
set of macros implementing arithmetic primitives, and not accessible
to any code outside sshbn.h (which confirms that I really did catch
all uses of it and remove them).

The resulting code is surprisingly nice-looking, actually. You'd
expect more hassle and roundabout circumlocutions when you drop down
to using a more basic set of primitive operations, but actually, in
many cases it's turned out shorter to write things in terms of the new
BignumADC and BignumMUL macros - because almost all my uses of
BignumDblInt were implementing those operations anyway, taking several
lines at a time, and now they can do each thing in just one line.

The biggest headache was Poly1305: I wasn't able to find any sensible
way to adapt the existing Python script that generates the various
per-int-size implementations of arithmetic mod 2^130-5, and so I had
to rewrite it from scratch instead, with nothing in common with the
old version beyond a handful of comments. But even that seems to have
worked out nicely: the new version has much more legible descriptions
of the high-level algorithms, by virtue of having a 'Multiprecision'
type which wraps up the division into words, and yet Multiprecision's
range analysis allows it to automatically drop out special cases such
as multiplication by 5 being much easier than multiplication by
another multi-word integer.
2015-12-16 14:13:21 +00:00
Simon Tatham
482b4ab872 Rewrite the core divide function to not use DIVMOD_WORD.
DIVMOD_WORD is a portability hazard, because implementing it requires
either a way to get direct access to the x86 DIV instruction or
equivalent (be it inline assembler or a compiler intrinsic), or else
an integer type we can use as BignumDblInt. But I'm starting to think
about porting to 64-bit Visual Studio with a 64-bit BignumInt, and in
that situation neither of those options will be available.

I could write a piece of _out_-of-line x86-64 assembler in a separate
source file and put a function call in DIVMOD_WORD, but instead I've
decided to solve the problem in a more futureproof way: remove
DIVMOD_WORD totally and write a division function that doesn't need it
at all, solving not only today's porting headache but all future ones
in this area.

The new implementation works by precomputing (a good enough
approximation to) the leading word of the reciprocal of the modulus,
and then getting each word of quotient by multiplying by that
reciprocal, where we previously used DIVMOD_WORD to divide by the
leading word of the actual modulus. The reciprocal itself is computed
outside internal_mod() and passed in as a parameter, allowing me to
save time by only computing it once when I'm about to do a modpow.

To some extent this complicates the implementation: the advantage of
DIVMOD_WORD was that it yielded a full word q of quotient every time
it was used, so the subtraction of q*m from the input could be done in
a nicely word-aligned way. But the reciprocal multiply approach yields
_almost_ a full word of quotient, because you have to make the
reciprocal a bit short to avoid overflow at multiplication time. For a
start, this means we have to do fractionally more iterations of the
main loop; but more painfully, we can no longer depend on the
subtraction of q*m at every step being word-aligned, and instead we
have to be prepared to do it at any bit shift.

But the flip side is that once we've implemented that, the rest of the
algorithm becomes a lot less full of horrible special cases: in
particular, we can now completely throw away the horribleness at all
the call sites where we shift the modulus up by a fractional word to
set its top bit, and then have to do a little dance to get the last
few bits of quotient involving a second call to internal_mod.

So there are points both for and against the new implementation in
simplicity terms; but I think on balance it's more comprehensible than
the old one, and a quick timing test suggests it also ends up a touch
faster overall - the new testbn gets through the output of
testdata/bignum.py in 4.034s where the old one took 4.392s.
2015-12-13 14:48:39 +00:00
Simon Tatham
984792e9f4 Add direct tests of division/modulus to testbn.
I'm about to rewrite the division code, so it'll be useful to have a
way to test it directly, particularly one which exercises difficult
cases such as extreme values of the leading word and remainders just
above and below zero.
2015-12-13 14:46:43 +00:00
Simon Tatham
90c7b1562c Fix copy-and-paste error in testbn main program.
I called a 'pow' test line 'mul' in an error message.
2015-12-13 14:46:42 +00:00
Ben Harris
b94a076955 Since we have bn_restore_invariant, we may as well use it more. 2015-10-28 22:08:32 +00:00
Ben Harris
4f34059902 bignum_set_bit: Don't abort if asked to clear an inaccessible bit
All those bits are clear anyway.

Bug found with the help of afl-fuzz.
2015-10-28 22:08:32 +00:00
Simon Tatham
e28b35b0a3 Improve integer-type hygiene in bignum code.
In many places I was using an 'unsigned int', or an implicit int by
virtue of writing an undecorated integer literal, where what was
really wanted was a BignumInt. In particular, this substitution breaks
in any situation where BignumInt is _larger_ than unsigned - which it
is shortly about to be.
2015-06-08 19:23:48 +01:00
Simon Tatham
0aa92c8fa2 Provide a stub random_byte() to make 'testbn' compile again.
The function bignum_random_in_range() is new to sshbn.c since I last
tried to run the bignum test code.
2015-06-08 19:22:55 +01:00
Simon Tatham
2c60070aad Move BignumInt definitions into a header file.
This allows files other than sshbn.c to work with the primitives
necessary to build multi-word arithmetic functions satisfying all of
PuTTY's portability constraints.
2015-06-07 13:50:05 +01:00
Simon Tatham
8dab2c2440 Remove pointless NULL checks in the ECC code.
snew(), and most of the bignum functions, are deliberately written to
fail an assertion and terminate the program rather than return NULL,
so there's no point carefully checking their every return value for
NULL. This removes a huge amount of pointless error-checking code, and
makes the elliptic curve arithmetic almost legible in places :-)

I've kept error checks after modinv(), because that can return NULL if
asked to invert zero. bigsub() can also fail in principle, because our
bignums are non-negative only, but in the couple of cases where it's
used there's a preceding compare that should prevent it, so I've just
added assertions.
2015-05-15 13:35:23 +01:00
Simon Tatham
89da2ddf56 Giant const-correctness patch of doom!
Having found a lot of unfixed constness issues in recent development,
I thought perhaps it was time to get proactive, so I compiled the
whole codebase with -Wwrite-strings. That turned up a huge load of
const problems, which I've fixed in this commit: the Unix build now
goes cleanly through with -Wwrite-strings, and the Windows build is as
close as I could get it (there are some lingering issues due to
occasional Windows API functions like AcquireCredentialsHandle not
having the right constness).

Notable fallout beyond the purely mechanical changing of types:
 - the stuff saved by cmdline_save_param() is now explicitly
   dupstr()ed, and freed in cmdline_run_saved.
 - I couldn't make both string arguments to cmdline_process_param()
   const, because it intentionally writes to one of them in the case
   where it's the argument to -pw (in the vain hope of being at least
   slightly friendly to 'ps'), so elsewhere I had to temporarily
   dupstr() something for the sake of passing it to that function
 - I had to invent a silly parallel version of const_cmp() so I could
   pass const string literals in to lookup functions.
 - stripslashes() in pscp.c and psftp.c has the annoying strchr nature
2015-05-15 12:47:44 +01:00
Simon Tatham
9971da40c3 Utility function: bignum_from_decimal. 2015-05-12 12:14:45 +01:00
Chris Staite
7d6bf4a6ca Provide a little-endian version of bignum_from_bytes(). 2015-05-09 15:02:50 +01:00
Simon Tatham
ae4986a433 Do an smemclr(bytes) in bignum_random_in_range.
It's used for sensitive data, so we shouldn't leave it lying around
after free.
2014-12-20 18:51:42 +00:00
Simon Tatham
c46da2f079 Fix memory management in bignum_random_in_range.
We were allocating a new array in which to make up a random number
every time we went round the loop, and not freeing any of them. Now we
allocate a single array to use for all loop iterations, and clear and
free it properly afterwards.

Patch due to Tim Kosse.
2014-12-20 18:51:42 +00:00
Chris Staite
7d1c30cd50 Some extra bignum functions: modsub, lshift, random_in_range. 2014-11-02 18:16:54 +00:00
Simon Tatham
eac7e041f1 Add some missing invariants in bigdiv and bigmod.
The underlying function 'bigdivmod' does not ensure either of its
outputs is normalised, so its callers must do so.
2014-11-01 19:48:47 +00:00
Simon Tatham
ead9081318 One more defensive assert, just to be sure.
[originally from svn r9997]
2013-08-06 16:45:49 +00:00
Simon Tatham
a7cc906df0 The bignum code has two representations of zero, since
bn_restore_invariant (and the many loops that duplicate it) leaves a
single zero word in a bignum representing 0, whereas the constant
'Zero' does not have any data words at all. Cope with this in
bignum_cmp.

(It would be a better plan to decide on one representation and stick
with it, but this is the less disruptive fix for the moment.)

[originally from svn r9996]
2013-08-05 19:50:51 +00:00
Simon Tatham
a7d13e284a Add some more precautionary assertions, just in case anything wildly
out of range manages to get past other recent fixes.

[originally from svn r9995]
2013-08-05 19:50:47 +00:00
Simon Tatham
97db2b6646 Fix memory leaks in the new error return from modinv.
[originally from svn r9992]
2013-08-04 22:33:50 +00:00
Simon Tatham
cb1df53360 Make modinv able to return NULL if its inputs are not coprime, and
check for that return value everywhere it is used.

[originally from svn r9990]
2013-08-04 19:34:07 +00:00
Simon Tatham
5bcb8d6aac More consistently defend against division by zero with assertions. We
now check that all the modular functions (modpow, modinv, modmul,
bigdivmod) have nonzero moduli, and that modinv also has a nonzero
thing to try to invert.

[originally from svn r9987]
2013-08-04 19:33:53 +00:00
Simon Tatham
55e8a268ab Found a lot of places in sshbn.c where for-loops zeroing out memory
just before freeing it really ought to be smemclrs.

[originally from svn r9981]
2013-08-02 19:51:36 +00:00
Simon Tatham
e01104f899 Fix an array-size bug in modmul, and add some tests for it.
[originally from svn r9977]
2013-08-02 06:27:54 +00:00
Simon Tatham
3c443bd2a5 Update the suggested compile command in sshbn.c's test rig.
[originally from svn r9732]
2012-12-22 18:10:08 +00:00
Simon Tatham
f2bbeca400 Fix two gcc warnings about confused printf format strings in the
bignum code's test harness. Thanks to Sup Yut Sum for fixing this in
TortoisePlink and Sven Strickroth for bringing it to my attention.

[originally from svn r9731]
2012-12-22 18:09:02 +00:00
Simon Tatham
aa5bae8916 Introduce a new utility function smemclr(), which memsets things to
zero but does it in such a way that over-clever compilers hopefully
won't helpfully optimise the call away if you do it just before
freeing something or letting it go out of scope. Use this for
(hopefully) every memset whose job is to destroy sensitive data that
might otherwise be left lying around in the process's memory.

[originally from svn r9586]
2012-07-22 19:51:50 +00:00
Simon Tatham
1fda4423e0 Fix Windows compile warnings by adding explicit casts.
[originally from svn r9200]
2011-07-12 18:09:46 +00:00
Simon Tatham
7957ca1153 Rejig the bottom-level loops in internal_mul_* to use pointers instead
of array indices. You'd hope that compilers could automatically turn
the one representation into the other if it was faster to do so, but
apparently not: even on gcc -O3, this source transformation gains over
15% performance.

[originally from svn r9105]
2011-02-22 19:09:27 +00:00
Simon Tatham
77180221bd Move the malloc and free of scratch space out of the internal_mul
routines into their callers, where they'll be done once for a whole
modpow rather than many times within each multiply. Doesn't save much
time as far as I can see - perhaps a couple of percent, one second in
the minute it takes to run the new bignum test suite - but seems like
a sensible idea anyway on general principles.

[originally from svn r9103]
2011-02-21 19:47:28 +00:00
Simon Tatham
15d7f8bb3e Add tests of modpow.
[originally from svn r9100]
2011-02-20 15:27:48 +00:00
Simon Tatham
1b47322c3b Nearly forgot. Reinstate the original unoptimised modpow, as a
fallback for when Montgomery is inapplicable.

(I may also at some point switch to using it for small exponents, if
speed testing should reveal that there's a noticeable threshold beyond
which preparing the Montgomery setup is uneconomical.)

[originally from svn r9099]
2011-02-20 15:14:02 +00:00
Simon Tatham
260cee498e Fix bug in Karatsuba multiplication, which affected propagation of a
carry by more than one word. Now the current set of test cases all
pass again.

[originally from svn r9098]
2011-02-20 15:06:39 +00:00
Simon Tatham
01d365b626 Beginnings of a test suite for the bignum code. The output of
testdata/bignum.py is twice the size of the rest of the PuTTY source
put together, so I'm not checking it in.

This reveals bugs in the new multiplication code, which I have yet to
fix.

[originally from svn r9097]
2011-02-20 14:59:00 +00:00
Simon Tatham
fa85085640 Implement the Chinese Remainder Theorem optimisation for speeding up
RSA private key operations by making use of the fact that we know the
factors of the modulus.

[originally from svn r9095]
2011-02-18 08:25:39 +00:00
Simon Tatham
61875b87e3 Implement the Montgomery technique for speeding up modular
exponentiation by replacing the modulo operation by a cleverly chosen
multiplication. This was not worth doing in the previous state of the
code (because my multiply was about as slow as my modulo), but now
that multiplication has been sped up by the Karatsuba optimisation,
Montgomery becomes worthwhile.

[originally from svn r9094]
2011-02-18 08:25:38 +00:00
Simon Tatham
d9c3353176 Implement the Karatsuba technique for recursive divide-and-conquer
optimisation of large multiplies.

[originally from svn r9093]
2011-02-18 08:25:37 +00:00
Simon Tatham
8b4c50be45 Add some appropriate bignum typedefs for generic 64-bit systems,
setting BignumInt to 32 bits. gcc defines _LP64 on x86-64 and
presumably on other 64-bit architectures, so I've conditioned my
defines on that in the hope that they won't need redoing for the next
few such architectures.

I've also added a set for _LLP64, but it's untested as yet.

[originally from svn r9092]
2011-02-18 08:25:36 +00:00
Simon Tatham
42801b7e9e Get rid of all the MSVC warnings.
[originally from svn r7086]
2007-01-09 18:24:07 +00:00
Jacob Nevins
d75ab2b509 Robert Evans spotted that bignum_decimal() failed to cope with being given
a zero input.
This shouldn't matter for PuTTY, as these routines are only used in PuTTYgen,
to output SSH-1 format public key exponents/moduli, which should be nonzero.

[originally from svn r6731]
2006-06-17 12:02:03 +00:00
Jacob Nevins
d8b7de5435 Improvements from Spyros Blanas to the MSVC optimisations of r6469:
don't do a function call for each divmod, and don't rely on details of
the calling convention.
(This didn't actually make any measurable difference to runtime in any
of my tests, but we may as well keep it as it's neater.)
Also document some general caveats of the divmod macro.

[originally from svn r6475]
[r6469 == d72e4b718c]
2005-12-06 23:18:27 +00:00
Jacob Nevins
d72e4b718c An MSVC version of the 16->32-bit bignum optimisation, derived from part of
a patch by Lionel Fourquaux. Seems to be about a factor of four improvement
(see wishlist item for details).
I don't claim to understand this in detail, so I can't vouch for its
correctness, but it didn't fall over immediately. It also produces some
compiler warnings, unfortunately.

[originally from svn r6469]
[this svn revision also touched putty-wishlist]
2005-11-23 21:26:05 +00:00
Jacob Nevins
5aa719d16e Consistently use a single notation to refer to SSH protocol versions, as
discussed. Use Barrett and Silverman's convention of "SSH-1" for SSH protocol
version 1 and "SSH-2" for protocol 2 ("SSH1"/"SSH2" refer to ssh.com
implementations in this scheme). <http://www.snailbook.com/terms.html>

[originally from svn r5480]
2005-03-10 16:36:05 +00:00