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

86 Commits

Author SHA1 Message Date
Simon Tatham
82661b7bf2 Server prep: extra RSA crypto primitives.
I've written the decryption side of the PKCS#1 encryption used in
SSH-1, and also the RSAES-OAEP system used by SSH-2 RSA kex. Also, the
RSA kex structures now each come with an 'extra' pointer giving the
minimum key length.
2018-10-21 10:02:10 +01:00
Simon Tatham
9396fcc9f7 Rename FROMFIELD to 'container_of'.
Ian Jackson points out that the Linux kernel has a macro of this name
with the same purpose, and suggests that it's a good idea to use the
same name as they do, so that at least some people reading one code
base might recognise it from the other.

I never really thought very hard about what order FROMFIELD's
parameters should go in, and therefore I'm pleasantly surprised to
find that my order agrees with the kernel's, so I don't have to
permute every call site as part of making this change :-)
2018-10-06 07:28:51 +01:00
Simon Tatham
4f9a90fc1a Turn SSH hashes into a classoid.
The new version of ssh_hash has the same nice property as ssh2_mac,
that I can make the generic interface object type function directly as
a BinarySink so that clients don't have to call h->sink() and worry
about the separate sink object they get back from that.
2018-09-19 23:08:07 +01:00
Simon Tatham
06a14fe8b8 Reorganise ssh_keyalg and use it as a vtable.
After Pavel Kryukov pointed out that I have to put _something_ in the
'ssh_key' structure, I thought of an actually useful thing to put
there: why not make it store a pointer to the ssh_keyalg structure?
Then ssh_key becomes a classoid - or perhaps 'traitoid' is a closer
analogy - in the same style as Socket and Plug. And just like Socket
and Plug, I've also arranged a system of wrapper macros that avoid the
need to mention the 'object' whose method you're invoking twice at
each call site.

The new vtable pointer directly replaces an existing field of struct
ec_key (which was usable by several different ssh_keyalgs, so it
already had to store a pointer to the currently active one), and also
replaces the 'alg' field of the ssh2_userkey structure that wraps up a
cryptographic key with its comment field.

I've also taken the opportunity to clean things up a bit in general:
most of the methods now have new and clearer names (e.g. you'd never
know that 'newkey' made a public-only key while 'createkey' made a
public+private key pair unless you went and looked it up, but now
they're called 'new_pub' and 'new_priv' you might be in with a
chance), and I've completely removed the openssh_private_npieces field
after realising that it was duplicating information that is actually
_more_ conveniently obtained by calling the new_priv_openssh method
(formerly openssh_createkey) and throwing away the result.
2018-06-03 15:15:51 +01:00
Simon Tatham
7f56e1e365 Remove 'keystr' parameter in get_rsa_ssh1_pub.
This parameter returned a substring of the input, which was used for
two purposes. Firstly, it was used to hash the host and server keys
during the initial SSH-1 key setup phase; secondly, it was used to
check the keys in Pageant against the public key blob of a key
specified on the command line.

Unfortunately, those two purposes didn't agree! The first one needs
just the bare key modulus bytes (without even the SSH-1 mpint length
header); the second needs the entire key blob. So, actually, it seems
to have never worked in SSH-1 to say 'putty -i keyfile' and have PuTTY
find that key in Pageant and not have to ask for the passphrase to
decrypt the version on disk.

Fixed by removing that parameter completely, which simplifies all the
_other_ call sites, and replacing it by custom code in those two
places that each does the actually right thing.
2018-06-03 08:24:59 +01:00
Simon Tatham
ff11e10d62 Rename rsa_public_blob_len to mention SSH-1.
It's yet another function with an outdatedly vague name.
2018-06-03 08:12:57 +01:00
Simon Tatham
ae3863679d Give rsa_fingerprint() a new name and API.
It's an SSH-1 specific function, so it should have a name reflecting
that, and it didn't. Also it had one of those outdated APIs involving
passing it a client-allocated buffer and size. Now it has a sensible
name, and internally it constructs the output string using a strbuf
and returns it dynamically allocated.
2018-06-03 08:08:53 +01:00
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
ae3edcdfc0 Clean up ssh_keyalg APIs and implementations.
Quite a few of the function pointers in the ssh_keyalg vtable now take
ptrlen arguments in place of separate pointer and length pairs.
Meanwhile, the various key types' implementations of those functions
now work by initialising a BinarySource with the input ptrlen and
using the new decode functions to walk along it.

One exception is the openssh_createkey method which reads a private
key in the wire format used by OpenSSH's SSH-2 agent protocol, which
has to consume a prefix of a larger data stream, and tell the caller
how much of that data was the private key. That function now takes an
actual BinarySource, and passes that directly to the decode functions,
so that on return the caller finds that the BinarySource's read
pointer has been advanced exactly past the private key.

This let me throw away _several_ reimplementations of mpint-reading
functions, one in each of sshrsa, sshdss.c and sshecc.c. Worse still,
they didn't all have exactly the SSH-2 semantics, because the thing in
sshrsa.c whose name suggested it was an mpint-reading function
actually tolerated the wrong number of leading zero bytes, which it
had to be able to do to cope with the "ssh-rsa" signature format which
contains a thing that isn't quite an SSH-2 mpint. Now that deviation
is clearly commented!
2018-06-02 18:00:59 +01:00
Simon Tatham
7d8312e71f Rewrite SSH-1 RSA handling functions using BinarySource.
The SSH-1 RSA key reading functions now have BinarySource-shaped get_*
forms, although for the moment I'm still supporting the old API as a
wrapper on the new one, because I haven't switched over the client
code yet. Also, rsa_public_blob_len uses the new system internally,
although its API is unchanged.
2018-06-02 17:42:28 +01:00
Simon Tatham
619f6722d8 Move null pointer checks to before FROMFIELD.
This fixes an oversight in commit 0fc2d3b45: if a key creation
function returns a null 'ssh_key *', then adjusting the pointer's
address using FROMFIELD is a mistake, both in technical C terms
(undefined behaviour) and practically speaking because it will foil
the subsequent check against NULL. Instead, if we're going to check a
pointer against NULL, we must do it _before_ applying this kind of
address-adjusting type conversion.
2018-05-31 18:50:18 +01:00
Simon Tatham
0fc2d3b455 Invent a struct type for polymorphic SSH key data.
During last week's work, I made a mistake in which I got the arguments
backwards in one of the key-blob-generating functions - mistakenly
swapped the 'void *' key instance with the 'BinarySink *' output
destination - and I didn't spot the mistake until run time, because in
C you can implicitly convert both to and from void * and so there was
no compile-time failure of type checking.

Now that I've introduced the FROMFIELD macro that downcasts a pointer
to one field of a structure to retrieve a pointer to the whole
structure, I think I might start using that more widely to indicate
this kind of polymorphic subtyping. So now all the public-key
functions in the struct ssh_signkey vtable handle their data instance
in the form of a pointer to a subfield of a new zero-sized structure
type 'ssh_key', which outside the key implementations indicates 'this
is some kind of key instance but it could be of any type'; they
downcast that pointer internally using FROMFIELD in place of the
previous ordinary C cast, and return one by returning &foo->sshk for
whatever foo they've just made up.

The sshk member is not at the beginning of the structure, which means
all those FROMFIELDs and &key->sshk are actually adding and
subtracting an offset. Of course I could have put the member at the
start anyway, but I had the idea that it's actually a feature _not_ to
have the two types start at the same address, because it means you
should notice earlier rather than later if you absentmindedly cast
from one to the other directly rather than by the approved method (in
particular, if you accidentally assign one through a void * and back
without even _noticing_ you perpetrated a cast). In particular, this
enforces that you can't sfree() the thing even once without realising
you should instead of called the right freekey function. (I found
several bugs by this method during initial testing, so I think it's
already proved its worth!)

While I'm here, I've also renamed the vtable structure ssh_signkey to
ssh_keyalg, because it was a confusing name anyway - it describes the
_algorithm_ for handling all keys of that type, not a specific key. So
ssh_keyalg is the collection of code, and ssh_key is one instance of
the data it handles.
2018-05-27 15:28:54 +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
e27ddf6d28 Make ssh_hash and ssh_mac expose a BinarySink.
Just as I did a few commits ago with the low-level SHA_Bytes type
functions, the ssh_hash and ssh_mac abstract types now no longer have
a direct foo->bytes() update method at all. Instead, each one has a
foo->sink() function that returns a BinarySink with the same lifetime
as the hash context, and then the caller can feed data into that in
the usual way.

This lets me get rid of a couple more duplicate marshalling routines
in ssh.c: hash_string(), hash_uint32(), hash_mpint().
2018-05-25 14:36:16 +01:00
Simon Tatham
67de463cca Change ssh.h crypto APIs to output to BinarySink.
This affects all the functions that generate public and private key
and signature blobs of all kinds, plus ssh_ecdhkex_getpublic. Instead
of returning a bare block of memory and taking an extra 'int *length'
parameter, all these functions now write to a BinarySink, and it's the
caller's job to have prepared an appropriate one where they want the
output to go (usually a strbuf).

The main value of this change is that those blob-generation functions
were chock full of ad-hoc length-counting and data marshalling. You
have only to look at rsa2_{public,private}_blob, for example, to see
the kind of thing I was keen to get rid of!
2018-05-25 14:36:16 +01:00
Simon Tatham
4988fd410c Replace all uses of SHA*_Bytes / MD5Update.
In fact, those functions don't even exist any more. The only way to
get data into a primitive hash state is via the new put_* system. Of
course, that means put_data() is a viable replacement for every
previous call to one of the per-hash update functions - but just
mechanically doing that would have missed the opportunity to simplify
a lot of the call sites.
2018-05-25 14:36:16 +01:00
Simon Tatham
f1b1b1d260 Simplify hashing operations in sshrsa.c and sshdss.c.
We can now simply call the centralised functions to put uint32s and
mpints into hash states, so there's no need to have duplicate local
copies doing the same things less type-generically.
2018-05-25 14:36:16 +01:00
Simon Tatham
7e8ae41a3f Clean up the crufty old SSH-1 RSA API.
Lots of functions had really generic names (like 'makekey'), or names
that missed out an important concept (like 'rsakey_pubblob', which
loads a public blob from a _file_ and doesn't generate it from an
in-memory representation at all). Also, the opaque 'int order' that
distinguishes the two formats of public key blob is now a mnemonic
enumeration, and while I'm at it, rsa_ssh1_public_blob takes one of
those as an extra argument.
2018-05-25 14:08:24 +01:00
Simon Tatham
8fdeb3a95c Merge tag '0.66'
This brings in the rest of the 0.66 branch, including some changes new
on master.

Conflicts:
        doc/plink.but
        sshrsa.c

(The conflicts were both trivial: in one, the addition of an extra
parameter to rsa2_newkey on master happened on the line next to 0.66's
addition of a check for NULL return value, and in the other, I'd got
the version number in the plink -h transcript messed up on master.)
2015-11-07 09:54:05 +00:00
Ben Harris
e170041a5d rsa2_pubkey_bits: Cope correctly with a NULL return from rsa2_newkey()
Dereferencing it is not correct.
Bug found with the help of afl-fuzz.

Conflicts:
	sshrsa.c
2015-10-24 22:32:59 +01:00
Simon Tatham
1293334ebf Provide an 'extra' pointer in ssh_signkey and ssh_kex.
This gives families of public key and kex functions (by which I mean
those sharing a set of methods) a place to store parameters that allow
the methods to vary depending on which exact algorithm is in use.

The ssh_kex structure already had a set of parameters specific to
Diffie-Hellman key exchange; I've moved those into sshdh.c and made
them part of the 'extra' structure for that family only, so that
unrelated kex methods don't have to faff about saying NULL,NULL,0,0.
(This required me to write an extra accessor function for ssh.c to ask
whether a DH method was group-exchange style or fixed-group style, but
that doesn't seem too silly.)
2015-05-15 10:12:08 +01:00
Simon Tatham
870ad6ab07 Pass the ssh_signkey structure itself to public key methods.
Not all of them, but the ones that don't get a 'void *key' parameter.
This means I can share methods between multiple ssh_signkey
structures, and still give those methods an easy way to find out which
public key method they're dealing with, by loading parameters from a
larger structure in which the ssh_signkey is the first element.

(In OO terms, I'm arranging that all static methods of my public key
classes get a pointer to the class vtable, to make up for not having a
pointer to the class instance.)

I haven't actually done anything with the new facility in this commit,
but it will shortly allow me to clean up the constant lookups by curve
name in the ECDSA code.
2015-05-15 10:12:07 +01:00
Simon Tatham
8682246d33 Centralise SSH-2 key fingerprinting into sshpubk.c.
There were ad-hoc functions for fingerprinting a bare key blob in both
cmdgen.c and pageant.c, not quite doing the same thing. Also, every
SSH-2 public key algorithm in the code base included a dedicated
fingerprint() method, which is completely pointless since SSH-2 key
fingerprints are computed in an algorithm-independent way (just hash
the standard-format public key blob), so each of those methods was
just duplicating the work of the public_blob() method with a less
general output mechanism.

Now sshpubk.c centrally provides an ssh2_fingerprint_blob() function
that does all the real work, plus an ssh2_fingerprint() function that
wraps it and deals with calling public_blob() to get something to
fingerprint. And the fingerprint() method has been completely removed
from ssh_signkey and all its implementations, and good riddance.
2015-05-12 14:56:38 +01:00
Simon Tatham
bcfcb169ef Const-correctness in public-key functions.
Several of the functions in ssh2_signkey, and one or two SSH-1 key
functions too, were still taking assorted non-const buffer parameters
that had never been properly constified. Sort them all out.
2015-05-05 20:16:17 +01:00
Simon Tatham
6b30316922 Use find_pubkey_alg in openssh_read_new().
This is better than listing all the algorithm names in yet another
place that will then need updating when a new key format is added.
However, that also means I need to find a new place to put the
'npieces' value I was previously setting up differently per key type;
since that's a fundamental property of the key format, I've moved it
to a constant field in the ssh_signkey structure, and filled that
field in for all the existing key types with the values from the
replaced code in openssh_read_new().
2015-05-02 15:11:41 +01:00
Simon Tatham
b8e5f74d4a Add a missing bn_restore_invariant in RSA blinding code.
We were inventing a random number by starting with a long zero bignum
and then setting bits at random, which left an opportunity for the
result to be a non-normalised representation (with a leading zero
word) and hence fail an assertion in bignum_cmp.

[originally from svn r10147]
2014-02-24 23:35:55 +00:00
Simon Tatham
20aabc3059 Spot when we didn't successfully create an RSA public key from a
public blob, and return a proper error in that situation rather than a
struct with unhelpful NULLs in.

[originally from svn r9991]
2013-08-04 19:34:10 +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
4b1fcc8ba2 Remove some redundant null-pointer checks from code that must have
been written before I wrote a never-failing snew.

[originally from svn r9985]
2013-08-04 19:33:46 +00:00
Simon Tatham
493a333078 Verify RSA keys created by rsa2_openssh_createkey.
[originally from svn r9980]
2013-08-02 06:28:05 +00:00
Simon Tatham
2e0723e9ef Replace some 'sfree' calls of bignums with the proper 'freebn'.
[originally from svn r9979]
2013-08-02 06:28:00 +00:00
Simon Tatham
6184e9f95d Add some missing bounds checks in signature verification routines.
[originally from svn r9978]
2013-08-02 06:27:56 +00:00
Simon Tatham
ea301bdd9b Fix another giant batch of resource leaks. (Mostly memory, but there's
one missing fclose too.)

[originally from svn r9919]
2013-07-14 10:46:07 +00:00
Simon Tatham
896bb7c74d Tighten up a lot of casts from unsigned to int which are read by one
of the GET_32BIT macros and then used as length fields. Missing bounds
checks against zero have been added, and also I've introduced a helper
function toint() which casts from unsigned to int in such a way as to
avoid C undefined behaviour, since I'm not sure I trust compilers any
more to do the obviously sensible thing.

[originally from svn r9918]
2013-07-14 10:45:54 +00:00
Simon Tatham
8b6a8b617f Add an assortment of extra safety checks.
[originally from svn r9896]
2013-07-08 22:36:04 +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
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
ff294f4ffd Ahem. Make sure I NULL out any unused pointer field that I later
plan to free if it isn't NULL.

[originally from svn r8202]
2008-10-08 18:09:56 +00:00
Simon Tatham
a59c4e9486 sshrsa.c now obeys the RFC793 Robustness Principle when it comes to
the ordering of the primes in a fully specified RSA private key:
when the key format typically has p > q, it will always output p > q
but be willing to tolerate p < q on input. (Inspired by seeing an
OpenSSH-format key file in the wild which had p < q, which I've
never seen before; I suspect a third-party application incautiously
generating the format.)

[originally from svn r8201]
2008-10-07 17:48:59 +00:00
Simon Tatham
90e7bf4228 Fix a couple of signedness compiler warnings, presumably due to me
using a different version of gcc from before.

[originally from svn r7627]
2007-06-30 18:18:20 +00:00
Ben Harris
3814ef0725 Make bounds of automatic array constant.
[originally from svn r7503]
2007-05-01 20:29:11 +00:00
Ben Harris
dad558a1e5 Add support for RFC 4432 RSA key exchange, the patch for which has been
lying around in my home directory for _years_.

[originally from svn r7496]
2007-04-30 22:09:26 +00:00
Jacob Nevins
6eec320f0b Unify GET_32BIT()/PUT_32BIT() et al from numerous source files into misc.h.
I've done a bit of testing (not exhaustive), and I don't _think_ I've broken
anything...

[originally from svn r5632]
2005-04-12 20:04:56 +00:00
Ben Harris
37278b3bfc Add an assertion so that short-rsa2-key-crash at least avoids segfaulting
while we come up with a better solution.

[originally from svn r5146]
2005-01-19 23:30:38 +00:00
Simon Tatham
e7470a08cd `dwalin' spotted a NULL dereference in the new makekey() error
handling. Oops.

[originally from svn r4541]
2004-09-12 22:02:06 +00:00
Simon Tatham
e2cd7e404e More sensible error handling when we receive an SSH1 public key
modulus of zero (!!), and also a robustness fix in ssh1_rdpkt which
I happened to notice while debugging that.

[originally from svn r4516]
2004-08-28 16:51:26 +00:00
Simon Tatham
4217269931 Merged SSH1 robustness changes from 0.55 release branch on to trunk.
[originally from svn r4379]
2004-08-01 12:07:11 +00:00
Simon Tatham
72e538e3b2 Charles Wilcox reported a signature validation bug with 2500-bit RSA
keys. This _appears_ to be due to me computing the byte count of the
key by dividing the bit count by 8 and rounding _down_ rather than
up. Therefore, I can't see how this code could ever have worked on
any SSH2 RSA key whose length was not a multiple of 8 bits; and
therefore I'm staggered that we haven't noticed it before! OpenSSH's
keygen appears to be scrupulous about ensuring the returned key
length is exactly what you asked for rather than one bit less, but
even so I'm astonished that _all_ keygen implementations for servers
we've ever interoperated with have avoided tripping this bug...

[originally from svn r3815]
2004-02-07 10:02:20 +00:00
Simon Tatham
2d1287b9ca Added a command-line key generation tool. Currently builds and runs
on Linux, but the (very few) platform-specific bits are already
abstracted out of the main code, so it should port to other
platforms with a minimum of fuss.

[originally from svn r3762]
2004-01-22 19:15:32 +00:00
Simon Tatham
7a1eae7ff2 Joe Yates's memory leak patches.
[originally from svn r3650]
2003-12-19 12:44:46 +00:00