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

78 Commits

Author SHA1 Message Date
Simon Tatham
a3f22a2cf9 Use the new 'HYBRID' names for the hybrid KEX packets.
draft-kampanakis-curdle-ssh-pq-ke defines the packet names
SSH_MSG_KEX_HYBRID_INIT and SSH_MSG_KEX_HYBRID_REPLY. They have the
same numbers as ECDH_INIT and ECDH_REPLY, and don't change anything
else, so this is just a naming change. But I think it's a good one,
because the post-quantum KEMs are less symmetric than ECDH (they're
much more like Ben's RSA kex in concept, though very different in
detail), and shouldn't try to pretend they're the same kind of thing.
Also this enables logparse.pl to give a warning about the fact that
one string in each packet contains two separate keys glomphed together.

For the latter reason (and also because it's easier in my code
structure) I've also switched to using the HYBRID naming for the
existing NTRU + Curve25519 hybrid method, even though the
Internet-Draft for that one still uses the ECDH names. Sorry, but I
think it's clearer!
2024-12-08 10:42:34 +00:00
Colin Watson
22f8122b13 Suppress syntax warnings on Python 3.12.
Python 3.12 has a new warning for backslash-character pairs that are not
valid escape sequences at the level of string literals, as opposed to in
some interior syntax such as regular expressions
(https://docs.python.org/3/whatsnew/3.12.html#other-language-changes).
Suppress it by using raw strings.
2024-08-01 21:38:07 +01:00
Jacob Nevins
329a4cdd79 authplugin-example.py: Flush stderr.
Python 3's stderr was fully-buffered when non-interactive, unlike
Python 2 and more or less everything else, until 3.9 in 2020(!):
https://bugs.python.org/issue13601

(It would be less faff to sys.stderr.reconfigure(line_buffering=True)
at the start, but that was only added in 3.7, whereas the 'flush'
argument to print() dates back to 3.3, so I chose that to minimise
the risk of version dependencies getting in the way of using this as
a working example.)
2022-10-24 12:52:44 +01:00
Jacob Nevins
538c8fd29c authplugin-example.py: Mention documentation.
(Just in case anyone's entry point is this example, and concludes they
have to reverse-engineer the protocol from the script.)
2022-10-24 12:50:58 +01:00
Simon Tatham
15f097f399 New feature: k-i authentication helper plugins.
In recent months I've had two requests from different people to build
support into PuTTY for automatically handling complicated third-party
auth protocols layered on top of keyboard-interactive - the kind of
thing where you're asked to enter some auth response, and you have to
refer to some external source like a web server to find out what the
right response _is_, which is a pain to do by hand, so you'd prefer it
to be automated in the SSH client.

That seems like a reasonable thing for an end user to want, but I
didn't think it was a good idea to build support for specific
protocols of that kind directly into PuTTY, where there would no doubt
be an ever-lengthening list, and maintenance needed on all of them.

So instead, in collaboration with one of my correspondents, I've
designed and implemented a protocol to be spoken between PuTTY and a
plugin running as a subprocess. The plugin can opt to handle the
keyboard-interactive authentication loop on behalf of the user, in
which case PuTTY passes on all the INFO_REQUEST packets to it, and
lets it make up responses. It can also ask questions of the user if
necessary.

The protocol spec is provided in a documentation appendix. The entire
configuration for the end user consists of providing a full command
line to use as the subprocess.

In the contrib directory I've provided an example plugin written in
Python. It gives a set of fixed responses suitable for getting through
Uppity's made-up k-i system, because that was a reasonable thing I
already had lying around to test against. But it also provides example
code that someone else could pick up and insert their own live
response-provider into the middle of, assuming they were happy with it
being in Python.
2022-09-01 20:43:23 +01:00
Simon Tatham
619bb441ec contrib/gdb.py: add a pretty-printer for ptrlen.
I mostly really like the use of 'ptrlen' in place of zero-terminated
strings in PuTTY, but one place it's awkward is when debuggging
through string-handling code, because gdb won't automatically show me
exactly what a ptrlen points to. Now it does.
2022-05-02 11:07:28 +01:00
Simon Tatham
4ecb40a60d Fix a batch of typos in comments and docs. 2022-01-03 06:40:51 +00:00
Simon Tatham
47c2bc38d1 New script contrib/proveprime.py.
This generates primality certificates for numbers, in the form of
Python / testcrypt code that calls Pockle methods. It factors p-1 by
calling out to the 'yafu' utility, which is a moderately sophisticated
integer factoring tool (including ECC and quadratic sieve methods)
that runs as a standalone command-line program.

Also added a Pockle test generated as output from this script, which
verifies the primality of the three NIST curves' moduli and their
generators' orders. I already had Pockle certificates for the moduli
and orders used in EdDSA, so this completes the set, and it does it
without me having had to do a lot of manual work.
2021-06-12 13:50:51 +01:00
Simon Tatham
334d87251e New script contrib/plinkfs.
This is a small wrapper on 'sshfs' which allows it to use Plink as its
transport. Mostly useful for when I've already got a PuTTY session
open to a given host with connection sharing enabled, and want to
tunnel over that rather than painstakingly re-establishing a separate
connection.
2020-08-04 18:56:47 +01:00
Simon Tatham
1efded20a1 kh2reg: stop using deprecated base64.decodestring.
Python 3 gave me a warning that I should have been using decodebytes
instead.
2020-03-09 19:27:17 +00:00
Simon Tatham
143f8a2d10 kh2reg: fix Python 3 iterator bug with multiple hostnames.
A known_hosts line can have multiple comma-separated hostnames on it,
or more usually a hostname and an IP address.

In the RSA and DSA key handlers, I was making a list of the integer
parameters of the public key by using the 'map' function, and then
iterating over it once per hostname on the line. But in Python 3, the
'map' function returns an iterator, not a list, so after you've
iterated to its end once, it's empty, and iterating over it a second
time stops immediately. As a result, the registry line for the second
hostname was coming out empty.
2020-03-09 19:26:49 +00:00
Simon Tatham
2ec2b796ed Migrate all Python scripts to Python 3.
Most of them are now _mandatory_ P3 scripts, because I'm tired of
maintaining everything to be compatible with both versions.

The current exceptions are gdb.py (which has to live with whatever gdb
gives it), and kh2reg.py (which is actually designed for other people
to use, and some of them might still be stuck on P2 for the moment).
2020-03-04 21:23:49 +00:00
Simon Tatham
a085acbadf Support the new "ssh-ed448" key type.
This is standardised by RFC 8709 at SHOULD level, and for us it's not
too difficult (because we use general-purpose elliptic-curve code). So
let's be up to date for a change, and add it.

This implementation uses all the formats defined in the RFC. But we
also have to choose a wire format for the public+private key blob sent
to an agent, and since the OpenSSH agent protocol is the de facto
standard but not (yet?) handled by the IETF, OpenSSH themselves get to
say what the format for a key should or shouldn't be. So if they don't
support a particular key method, what do you do?

I checked with them, and they agreed that there's an obviously right
format for Ed448 keys, which is to do them exactly like Ed25519 except
that you have a 57-byte string everywhere Ed25519 had a 32-byte
string. So I've done that.
2020-03-02 07:09:08 +00:00
Simon Tatham
5d718ef64b Whitespace rationalisation of entire code base.
The number of people has been steadily increasing who read our source
code with an editor that thinks tab stops are 4 spaces apart, as
opposed to the traditional tty-derived 8 that the PuTTY code expects.

So I've been wondering for ages about just fixing it, and switching to
a spaces-only policy throughout the code. And I recently found out
about 'git blame -w', which should make this change not too disruptive
for the purposes of source-control archaeology; so perhaps now is the
time.

While I'm at it, I've also taken the opportunity to remove all the
trailing spaces from source lines (on the basis that git dislikes
them, and is the only thing that seems to have a strong opinion one
way or the other).
    
Apologies to anyone downstream of this code who has complicated patch
sets to rebase past this change. I don't intend it to be needed again.
2019-09-08 20:29:21 +01:00
Simon Tatham
5f204d1ef1 kh2reg.py: handle OpenSSH hashed hostnames.
Obviously we can't do that by inverting the hash function itself, but
if the user provides one or more host names on the command line that
they're expecting to appear in the file, we can at least compare the
stored hashes against those.
2019-04-21 14:46:12 +01:00
Simon Tatham
0842d4627e kh2reg.py: add -o option to write output to a file.
Generally useful, I always think.
2019-04-21 14:46:12 +01:00
Simon Tatham
ac1dd1bd2e kh2reg.py: switch from getopt to argparse.
This change gives us an automatic --help option, which is always
useful for a script used very rarely. It also makes it that much
easier to add extra options.
2019-04-21 14:46:12 +01:00
Simon Tatham
91333f7c74 kh2reg.py: refactor main program to bottom of file.
Now most of the program consists of function and class definitions,
and the code that activates it all is localised in one place at the
bottom instead of interleaved between the definitions.
2019-04-21 14:46:12 +01:00
Simon Tatham
33d4d223a5 kh2reg.py: work with Python 3. 2019-04-21 14:46:12 +01:00
Simon Tatham
5a508a84a2 kh2reg.py: support ECDSA point compression.
We support it in the ECC code proper these days, as of the bignum
rewrite in commit 25b034ee3. So we should support it in this auxiliary
script too, and fortunately, there's no real difficulty in doing so
because I already had some Python code kicking around in
test/eccref.py for taking modular square roots.
2019-04-21 14:46:12 +01:00
Simon Tatham
98cb60ef8e Replace all uses of Perl <> with <<>>.
I've only just found out that it has the effect of treating the argv
words not as plain filenames, but as arguments to Perl default 'open',
i.e. if they end in | then the text before that is treated as a
command. That's not what was intended in any of these contexts!

Fortunately, in this project it only comes up in non-critical
'contrib' scripts.
2019-01-25 20:20:37 +00:00
Simon Tatham
c3ae739e6d Move eccref.py into the test directory.
The test suite I'm writing for ecc.c will live in that directory and
want to use it to check answers.
2019-01-03 16:56:02 +00:00
Simon Tatham
992f98d5d7 Fix two misstatements of the Montgomery curve equation.
I got it right in all the serious code (or else my Curve25519 key
exchange wouldn't have worked), but I wrote it down wrongly in the
comment in ecc.h, putting the coefficient b on the RHS x term rather
than the LHS y^2. Then I repeated the same error in the point
decompression function in eccref.py.
2019-01-03 15:41:16 +00:00
Simon Tatham
25b034ee39 Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.

The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.

I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.

I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.

sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.

A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.

In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.

Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 14:54:59 +00:00
Simon Tatham
4262ce45ca gdb.py: support functions for container_of and tree234.
The gdb version of container_of can do better than the C function,
because you don't have to specify the structure field name if it can
be inferred from the type of the input expression.

And $list234 can be made to automatically list the contents of each
tree element, not just a pointer to it - just the thing for looking
quickly through sktree or s->channels to find the one you're after.
2018-11-16 19:22:43 +00:00
Simon Tatham
a6f1709c2f Adopt C99 <stdbool.h>'s true/false.
This commit includes <stdbool.h> from defs.h and deletes my
traditional definitions of TRUE and FALSE, but other than that, it's a
100% mechanical search-and-replace transforming all uses of TRUE and
FALSE into the C99-standardised lowercase spellings.

No actual types are changed in this commit; that will come next. This
is just getting the noise out of the way, so that subsequent commits
can have a higher proportion of signal.
2018-11-03 13:45:00 +00:00
Simon Tatham
0bbe87f11e Rewrite some comments with FIXMEs in them.
These are things where no fix was actually necessary in the code, but
the FIXME indicated that the comment itself was either in need of a
rewrite or removal.
2018-10-06 11:57:59 +01:00
Simon Tatham
62f630d4b3 cygtermd: remove all uses of 'FIXME' as program name.
There was a while when I hadn't decided what the name of the program
was going to be, and apparently once I did I never got round to
substituting it back in everywhere.
2018-10-06 11:57:59 +01:00
Simon Tatham
96ec2c2500 Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.

All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.

A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 19:10:23 +01:00
Simon Tatham
734ada9b57 gdb.py: add a 'memdump' command.
This makes it easier for me to examine the contents of binary memory
buffers, while debugging through code that does crypto or packet
marshalling.
2018-06-09 14:20:33 +01:00
Simon Tatham
10a4f1156c Add a GDB Python script to pretty-print Bignum.
I've been playing around with GDB's Python scripting system recently,
and this is a thing I've always thought it would be nice to be able to
do: if you load this script (which, on Ubuntu 18.04's gdb, is as
simple as 'source contrib/gdb.py' at the gdb prompt, or similar), then
variables of type Bignum will be printed as (e.g.) 'Bignum(0x12345)',
or 'Bignum(NULL)' if they're null pointers, or a fallback
representation if they're non-null pointers but gdb can't read
anything sensible from them.
2018-06-04 19:10:57 +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
65acff1f70 logparse.pl: support GSSAPI key exchange messages. 2018-04-26 07:21:28 +01:00
Simon Tatham
f41d365029 logparse.pl: fix a Perl warning.
Used the wrong kind of brackets when initialising the actual hash (as
opposed to hash ref) %disc_reasons. Not sure how I didn't notice the
warning in yesterday's testing!
2018-04-11 19:58:14 +01:00
Simon Tatham
4989447e72 logparse.pl: document the -e option.
I'm increasingly wishing I'd written this parsing program in Python,
and yet another reason why is that using argparse for the command-line
handling makes it a lot harder to forget to write the --help text when
you add an extra option.
2018-04-10 08:12:55 +01:00
Simon Tatham
44dc516810 logparse.pl: option to pass through Event Log entries.
This makes it more feasible to use logparse.pl as an output filter on
a PuTTY SSH log file and discard the original file.

In particular, ever since commit b4fde270c, I've been finding it
useful when testing new code to direct my SSH logs to a named pipe and
have another terminal window give a real-time dump of them by running
'while cat $named_pipe; do :; done'. Now I can replace the 'cat' in
that shell command with 'logparse.pl -ve' and still get the Event Log
messages as well as the unpacked contents of all the packets.
2018-04-09 20:24:41 +01:00
Simon Tatham
ec29d35403 logparse.pl: add verbose dumping for transport protocol.
This includes picking apart the various asymmetric crypto formats
(public keys, signatures, elliptic-curve point encodings) as far as
possible, but since the verbose decoder system in logparse.pl
currently has to work without benefit of statefulness, it's not always
possible - some of the ECC formats depend for their decoding on
everyone remembering _which_ ECC protocol was negotiated by the
KEXINITs.
2018-04-09 20:22:04 +01:00
Simon Tatham
e090e55179 logparse.pl: fix a thinko in &parse.
The type code for an mpint in the input format string is "m", not
"mpint". This hasn't come up yet as far as I can see, but as and when
I add verbose dump routines for packet types that involve asymmetric
crypto, it will.
2018-04-05 18:26:12 +01:00
Simon Tatham
48625ece7d logparse.pl: add a verbose dump system.
This allows me to request a verbose dump of the contents of some
particular packet type, or for all packet types.

Currently, the only packet type for which I've written a verbose dump
function is KEXINIT, but the framework is there to add further verbose
dumpers as and when they're needed.
2018-04-05 18:26:12 +01:00
Simon Tatham
204780080d logparse.pl: more sensible option-parsing.
Switched to Getopt::Long in place of the previous ad-hockery, which
will make it easier to add more (and more complicated) options.
2018-04-05 18:26:12 +01:00
Simon Tatham
6ea9d36ae9 Switch chiark URLs to https. 2017-05-07 16:29:01 +01:00
Simon Tatham
d2653e79ab Fix bug in Poly1305 bigval_final_reduce().
Mark Wooding pointed out that my comment in make1305.py was completely
wrong, and that the stated strategy for reducing a value mod 2^130-5
would not in fact completely reduce all inputs in the range - for the
most obvious reason, namely that the numbers between 2^130-5 and 2^130
would never have anything subtracted at all.

Implemented a replacement strategy which my tests suggest will do the
right thing for all numbers in the expected range that are anywhere
near an integer multiple of the modulus.
2017-04-08 21:27:28 +01:00
Owen Dunn
142a458fee Add blank line at bottom of .reg files we generate
The specification at http://support.microsoft.com/kb/310516 says .reg
files should have a blank line at the end.
2017-03-17 10:11:20 +00:00
Simon Tatham
24da181a01 cygtermd: be more specific in define of _XOPEN_SOURCE.
On Debian stretch, it seems we don't get setpgrp() unless we do not
merely define it, but define it to 500 or greater.
2016-09-19 14:17:26 +01:00
Simon Tatham
cc9d920c78 Rework samplekex.py to use the new -proxycmd.
It now expects its standard input to be connected to the same PuTTY
its standard output is talking to, i.e. expects to be invoked as a
proxy command. It conducts the same sample key exchange as it used to,
but now reads the SSH greeting and first couple of packets back from
PuTTY and minimally checks that they're something like what it was
expecting.

(In the process, I've also fixed a mistake in the Python message code
enumeration, which caused one of those expect() calls to fail.)
2016-05-03 16:51:42 +01:00
Simon Tatham
c722b2f07f Support Ed25519 in kh2reg.py. 2016-03-25 09:58:40 +00:00
Jacob Nevins
a5588cd635 kh2reg.py: remove accidental hard tabs. 2016-03-22 00:43:30 +00:00
Jacob Nevins
7332d0567e Partial update of kh2reg.py for new formats.
Only ECDSA so far, because ed25519 requires real maths to deal with the
compressed point format.
2016-03-22 00:36:19 +00:00
Simon Tatham
70f641f845 Remove some unused variables.
Thanks to @ch3root again for this patch.
2016-01-26 18:36:26 +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