1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Pageant core: separate public and private key storage.

Previously, we had a single data structure 'keytree' containing
records each involving a public and private key (the latter maybe in
clear, or as an encrypted key file, or both). Now, we have separate
'pubkeytree' and 'privkeytree', the former storing public keys indexed
by their full public blob (including certificate, if any), and the
latter storing private keys, indexed by the _base_ public blob
only (i.e. with no certificate included).

The effect of this is that deferred decryption interacts more sensibly
with certificates. Now, if you load certified and uncertified versions
of the same key into Pageant, or two or more differently certified
versions, then the separate public key records will all share the same
private key record, and hence, a single state of decryption. So the
first time you enter a passphrase that unlocks that private key, it
will unlock it for all public keys that share the same private half.
Conversely, re-encrypting any one of them will cause all of them to
become re-encrypted, eliminating the risk that you deliberately
re-encrypt a key you really care about and forget that another equally
valuble copy of it is still in clear.

The most subtle part of this turned out to be the question of what key
comment you present in a deferred decryption prompt. It's very
tempting to imagine that it should be the comment that goes with
whichever _public_ key was involved in the signing request that
triggered the prompt. But in fact, it _must_ be the comment that goes
with whichever version of the encrypted key file is stored in Pageant
- because what if the user chose different passphrases for their
uncertified and certified PPKs? Then the decryption prompt will have
to indicate which passphrase they should be typing, so it's vital to
present the comment that goes with the _file we're decrypting_.

(Of course, if the user has selected different passphrases for those
two PPKs but the _same_ comment, they're still going to end up
confused. But at least once they realise they've done that, they have
a workaround.)
This commit is contained in:
Simon Tatham 2022-08-06 10:41:41 +01:00
parent cd7f6c4407
commit 423ce20ffb
3 changed files with 505 additions and 263 deletions

View File

@ -76,6 +76,21 @@ RSAKey *BinarySource_get_rsa_ssh1_priv_agent(BinarySource *src)
return rsa;
}
void duprsakey(RSAKey *dst, const RSAKey *src)
{
dst->bits = src->bits;
dst->bytes = src->bytes;
dst->modulus = mp_copy(src->modulus);
dst->exponent = mp_copy(src->exponent);
dst->private_exponent = src->private_exponent ?
mp_copy(src->private_exponent) : NULL;
dst->p = mp_copy(src->p);
dst->q = mp_copy(src->q);
dst->iqmp = mp_copy(src->iqmp);
dst->comment = src->comment ? dupstr(src->comment) : NULL;
dst->sshk.vt = src->sshk.vt;
}
bool rsa_ssh1_encrypt(unsigned char *data, int length, RSAKey *key)
{
mp_int *b1, *b2;

752
pageant.c

File diff suppressed because it is too large Load Diff

1
ssh.h
View File

@ -597,6 +597,7 @@ bool rsa_verify(RSAKey *key);
void rsa_ssh1_public_blob(BinarySink *bs, RSAKey *key, RsaSsh1Order order);
int rsa_ssh1_public_blob_len(ptrlen data);
void rsa_ssh1_private_blob_agent(BinarySink *bs, RSAKey *key);
void duprsakey(RSAKey *dst, const RSAKey *src);
void freersapriv(RSAKey *key);
void freersakey(RSAKey *key);
key_components *rsa_components(RSAKey *key);