mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Support SHA-256 and SHA-512 based RSA signatures.
Now the RSA signing function supports the two flags defined in draft-miller-ssh-agent-02, and uses them to generate RSA signatures based on SHA-256 and SHA-512, which look exactly like the ordinary kind of RSA SHA-1 signature except that the decoded signature integer has a different hash at the bottom and an ASN.1 identifying prefix to match, and also the signature-type string prefixing the integer changes from "ssh-rsa" to "rsa-sha2-256" or "rsa-sha2-512" as appropriate. We don't _accept_ signatures of these new types - that would need an entirely different protocol extension - and we don't generate them under any circumstances other than Pageant receiving a sign request with one of those flags set.
This commit is contained in:
parent
7d4a276fc1
commit
13b29008b4
6
ssh.h
6
ssh.h
@ -807,6 +807,12 @@ struct ssh_keyalg {
|
||||
#define ssh_key_ssh_id(key) ((*(key))->ssh_id)
|
||||
#define ssh_key_cache_id(key) ((*(key))->cache_id)
|
||||
|
||||
/*
|
||||
* Enumeration of signature flags from draft-miller-ssh-agent-02
|
||||
*/
|
||||
#define SSH_AGENT_RSA_SHA2_256 2
|
||||
#define SSH_AGENT_RSA_SHA2_512 4
|
||||
|
||||
typedef struct ssh_compressor {
|
||||
const struct ssh_compression_alg *vt;
|
||||
} ssh_compressor;
|
||||
|
71
sshrsa.c
71
sshrsa.c
@ -676,12 +676,28 @@ static int rsa2_pubkey_bits(const ssh_keyalg *self, ptrlen pub)
|
||||
* iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
* algorithms(2) 26 }
|
||||
*/
|
||||
static const unsigned char asn1_weird_stuff[] = {
|
||||
static const unsigned char sha1_asn1_prefix[] = {
|
||||
0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
|
||||
0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
|
||||
};
|
||||
|
||||
#define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) )
|
||||
/*
|
||||
* Two more similar pieces of ASN.1 used for signatures using SHA-256
|
||||
* and SHA-512, in the same format but differing only in various
|
||||
* length fields and OID.
|
||||
*/
|
||||
static const unsigned char sha256_asn1_prefix[] = {
|
||||
0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
|
||||
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
|
||||
0x05, 0x00, 0x04, 0x20,
|
||||
};
|
||||
static const unsigned char sha512_asn1_prefix[] = {
|
||||
0x00, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
|
||||
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
|
||||
0x05, 0x00, 0x04, 0x40,
|
||||
};
|
||||
|
||||
#define SHA1_ASN1_PREFIX_LEN sizeof(sha1_asn1_prefix)
|
||||
|
||||
static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data)
|
||||
{
|
||||
@ -723,13 +739,13 @@ static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data)
|
||||
if (bignum_byte(out, bytes - 2) != 1)
|
||||
toret = false;
|
||||
/* Most of the rest should be FF. */
|
||||
for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) {
|
||||
for (i = bytes - 3; i >= 20 + SHA1_ASN1_PREFIX_LEN; i--) {
|
||||
if (bignum_byte(out, i) != 0xFF)
|
||||
toret = false;
|
||||
}
|
||||
/* Then we expect to see the asn1_weird_stuff. */
|
||||
for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) {
|
||||
if (bignum_byte(out, i) != asn1_weird_stuff[j])
|
||||
/* Then we expect to see the sha1_asn1_prefix. */
|
||||
for (i = 20 + SHA1_ASN1_PREFIX_LEN - 1, j = 0; i >= 20; i--, j++) {
|
||||
if (bignum_byte(out, i) != sha1_asn1_prefix[j])
|
||||
toret = false;
|
||||
}
|
||||
/* Finally, we expect to see the SHA-1 hash of the signed data. */
|
||||
@ -749,22 +765,47 @@ static void rsa2_sign(ssh_key *key, const void *data, int datalen,
|
||||
struct RSAKey *rsa = container_of(key, struct RSAKey, sshk);
|
||||
unsigned char *bytes;
|
||||
int nbytes;
|
||||
unsigned char hash[20];
|
||||
unsigned char hash[64];
|
||||
Bignum in, out;
|
||||
int i, j;
|
||||
const struct ssh_hashalg *halg;
|
||||
ssh_hash *h;
|
||||
const unsigned char *asn1_prefix;
|
||||
unsigned asn1_prefix_size;
|
||||
const char *sign_alg_name;
|
||||
|
||||
SHA_Simple(data, datalen, hash);
|
||||
if (flags & SSH_AGENT_RSA_SHA2_256) {
|
||||
halg = &ssh_sha256;
|
||||
asn1_prefix = sha256_asn1_prefix;
|
||||
asn1_prefix_size = sizeof(sha256_asn1_prefix);
|
||||
sign_alg_name = "rsa-sha2-256";
|
||||
} else if (flags & SSH_AGENT_RSA_SHA2_512) {
|
||||
halg = &ssh_sha512;
|
||||
asn1_prefix = sha512_asn1_prefix;
|
||||
asn1_prefix_size = sizeof(sha512_asn1_prefix);
|
||||
sign_alg_name = "rsa-sha2-512";
|
||||
} else {
|
||||
halg = &ssh_sha1;
|
||||
asn1_prefix = sha1_asn1_prefix;
|
||||
asn1_prefix_size = sizeof(sha1_asn1_prefix);
|
||||
sign_alg_name = "ssh-rsa";
|
||||
}
|
||||
|
||||
h = ssh_hash_new(halg);
|
||||
put_data(h, data, datalen);
|
||||
ssh_hash_final(h, hash);
|
||||
|
||||
nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
|
||||
assert(1 <= nbytes - 20 - ASN1_LEN);
|
||||
assert(1 <= nbytes - halg->hlen - asn1_prefix_size);
|
||||
bytes = snewn(nbytes, unsigned char);
|
||||
|
||||
bytes[0] = 1;
|
||||
for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
|
||||
for (i = 1; i < nbytes - halg->hlen - asn1_prefix_size; i++)
|
||||
bytes[i] = 0xFF;
|
||||
for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
|
||||
bytes[i] = asn1_weird_stuff[j];
|
||||
for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
|
||||
for (i = nbytes - halg->hlen - asn1_prefix_size, j = 0;
|
||||
i < nbytes - halg->hlen; i++, j++)
|
||||
bytes[i] = asn1_prefix[j];
|
||||
for (i = nbytes - halg->hlen, j = 0; i < nbytes; i++, j++)
|
||||
bytes[i] = hash[j];
|
||||
|
||||
in = bignum_from_bytes(bytes, nbytes);
|
||||
@ -773,7 +814,7 @@ static void rsa2_sign(ssh_key *key, const void *data, int datalen,
|
||||
out = rsa_privkey_op(in, rsa);
|
||||
freebn(in);
|
||||
|
||||
put_stringz(bs, "ssh-rsa");
|
||||
put_stringz(bs, sign_alg_name);
|
||||
nbytes = (bignum_bitcount(out) + 7) / 8;
|
||||
put_uint32(bs, nbytes);
|
||||
for (i = 0; i < nbytes; i++)
|
||||
@ -800,7 +841,7 @@ const ssh_keyalg ssh_rsa = {
|
||||
"ssh-rsa",
|
||||
"rsa2",
|
||||
NULL,
|
||||
0, /* no supported flags */
|
||||
SSH_AGENT_RSA_SHA2_256 | SSH_AGENT_RSA_SHA2_512,
|
||||
};
|
||||
|
||||
struct RSAKey *ssh_rsakex_newkey(const void *data, int len)
|
||||
|
Loading…
Reference in New Issue
Block a user