2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* Digital Signature Standard implementation for PuTTY.
|
|
|
|
*/
|
|
|
|
|
2000-09-07 16:33:49 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2001-03-03 11:54:34 +00:00
|
|
|
#include <assert.h>
|
2000-09-07 16:33:49 +00:00
|
|
|
|
2000-09-05 14:28:17 +00:00
|
|
|
#include "ssh.h"
|
2001-09-22 20:52:21 +00:00
|
|
|
#include "misc.h"
|
2000-09-05 14:28:17 +00:00
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_freekey(ssh_key *key); /* forward reference */
|
2013-08-04 19:33:49 +00:00
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
static ssh_key *dss_newkey(const ssh_keyalg *self, ptrlen data)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource src[1];
|
2000-12-02 12:48:15 +00:00
|
|
|
struct dss_key *dss;
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource_BARE_INIT(src, data.ptr, data.len);
|
|
|
|
if (!ptrlen_eq_string(get_string(src), "ssh-dss"))
|
2000-12-02 12:48:15 +00:00
|
|
|
return NULL;
|
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-05-31 17:40:51 +00:00
|
|
|
|
|
|
|
dss = snew(struct dss_key);
|
|
|
|
dss->p = get_mp_ssh2(src);
|
|
|
|
dss->q = get_mp_ssh2(src);
|
|
|
|
dss->g = get_mp_ssh2(src);
|
|
|
|
dss->y = get_mp_ssh2(src);
|
2013-08-04 19:33:43 +00:00
|
|
|
dss->x = NULL;
|
2000-12-02 12:48:15 +00:00
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
if (get_err(src) ||
|
2013-08-04 19:33:49 +00:00
|
|
|
!bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
|
|
|
|
/* Invalid key. */
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2013-08-04 19:33:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
return &dss->sshk;
|
2000-09-07 16:33:49 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_freekey(ssh_key *key)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2013-08-04 19:33:43 +00:00
|
|
|
if (dss->p)
|
|
|
|
freebn(dss->p);
|
|
|
|
if (dss->q)
|
|
|
|
freebn(dss->q);
|
|
|
|
if (dss->g)
|
|
|
|
freebn(dss->g);
|
|
|
|
if (dss->y)
|
|
|
|
freebn(dss->y);
|
|
|
|
if (dss->x)
|
|
|
|
freebn(dss->x);
|
2000-12-12 10:33:13 +00:00
|
|
|
sfree(dss);
|
2000-12-02 12:48:15 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static char *dss_fmtkey(ssh_key *key)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2000-09-07 16:33:49 +00:00
|
|
|
char *p;
|
2000-09-27 15:21:04 +00:00
|
|
|
int len, i, pos, nibbles;
|
|
|
|
static const char hex[] = "0123456789abcdef";
|
2000-12-02 12:48:15 +00:00
|
|
|
if (!dss->p)
|
2001-05-06 14:35:20 +00:00
|
|
|
return NULL;
|
|
|
|
len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
|
|
|
|
len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
|
|
|
|
len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
|
|
|
|
len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
|
|
|
|
len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
|
2003-03-29 16:14:26 +00:00
|
|
|
p = snewn(len, char);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (!p)
|
|
|
|
return NULL;
|
2000-09-27 15:21:04 +00:00
|
|
|
|
|
|
|
pos = 0;
|
2001-05-06 14:35:20 +00:00
|
|
|
pos += sprintf(p + pos, "0x");
|
|
|
|
nibbles = (3 + bignum_bitcount(dss->p)) / 4;
|
|
|
|
if (nibbles < 1)
|
|
|
|
nibbles = 1;
|
|
|
|
for (i = nibbles; i--;)
|
|
|
|
p[pos++] =
|
|
|
|
hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
|
|
|
|
pos += sprintf(p + pos, ",0x");
|
|
|
|
nibbles = (3 + bignum_bitcount(dss->q)) / 4;
|
|
|
|
if (nibbles < 1)
|
|
|
|
nibbles = 1;
|
|
|
|
for (i = nibbles; i--;)
|
|
|
|
p[pos++] =
|
|
|
|
hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
|
|
|
|
pos += sprintf(p + pos, ",0x");
|
|
|
|
nibbles = (3 + bignum_bitcount(dss->g)) / 4;
|
|
|
|
if (nibbles < 1)
|
|
|
|
nibbles = 1;
|
|
|
|
for (i = nibbles; i--;)
|
|
|
|
p[pos++] =
|
|
|
|
hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF];
|
|
|
|
pos += sprintf(p + pos, ",0x");
|
|
|
|
nibbles = (3 + bignum_bitcount(dss->y)) / 4;
|
|
|
|
if (nibbles < 1)
|
|
|
|
nibbles = 1;
|
|
|
|
for (i = nibbles; i--;)
|
|
|
|
p[pos++] =
|
|
|
|
hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF];
|
2000-09-27 15:21:04 +00:00
|
|
|
p[pos] = '\0';
|
2000-09-07 16:33:49 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
static int dss_verifysig(ssh_key *key, ptrlen sig, ptrlen data)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource src[1];
|
|
|
|
unsigned char hash[20];
|
2000-10-23 16:11:31 +00:00
|
|
|
Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
|
2000-09-07 16:33:49 +00:00
|
|
|
int ret;
|
|
|
|
|
2000-12-02 12:48:15 +00:00
|
|
|
if (!dss->p)
|
2001-05-06 14:35:20 +00:00
|
|
|
return 0;
|
2000-09-07 16:33:49 +00:00
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource_BARE_INIT(src, sig.ptr, sig.len);
|
|
|
|
|
2000-10-03 09:05:56 +00:00
|
|
|
/*
|
|
|
|
* Commercial SSH (2.0.13) and OpenSSH disagree over the format
|
2007-10-03 21:21:18 +00:00
|
|
|
* of a DSA signature. OpenSSH is in line with RFC 4253:
|
2000-10-03 09:05:56 +00:00
|
|
|
* it uses a string "ssh-dss", followed by a 40-byte string
|
|
|
|
* containing two 160-bit integers end-to-end. Commercial SSH
|
|
|
|
* can't be bothered with the header bit, and considers a DSA
|
|
|
|
* signature blob to be _just_ the 40-byte string containing
|
|
|
|
* the two 160-bit integers. We tell them apart by measuring
|
|
|
|
* the length: length 40 means the commercial-SSH bug, anything
|
2007-10-03 21:21:18 +00:00
|
|
|
* else is assumed to be RFC-compliant.
|
2000-10-03 09:05:56 +00:00
|
|
|
*/
|
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-05-31 17:40:51 +00:00
|
|
|
if (sig.len != 40) { /* bug not present; read admin fields */
|
|
|
|
ptrlen type = get_string(src);
|
|
|
|
sig = get_string(src);
|
|
|
|
|
|
|
|
if (get_err(src) || !ptrlen_eq_string(type, "ssh-dss") ||
|
|
|
|
sig.len != 40)
|
|
|
|
return 0;
|
2000-09-07 16:33:49 +00:00
|
|
|
}
|
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-05-31 17:40:51 +00:00
|
|
|
|
|
|
|
/* Now we're sitting on a 40-byte string for sure. */
|
|
|
|
r = bignum_from_bytes(sig.ptr, 20);
|
|
|
|
s = bignum_from_bytes((const char *)sig.ptr + 20, 20);
|
2013-08-04 19:33:57 +00:00
|
|
|
if (!r || !s) {
|
|
|
|
if (r)
|
|
|
|
freebn(r);
|
|
|
|
if (s)
|
|
|
|
freebn(s);
|
2001-05-06 14:35:20 +00:00
|
|
|
return 0;
|
2013-08-04 19:33:57 +00:00
|
|
|
}
|
2000-09-07 16:33:49 +00:00
|
|
|
|
2013-08-04 19:34:00 +00:00
|
|
|
if (!bignum_cmp(s, Zero)) {
|
|
|
|
freebn(r);
|
|
|
|
freebn(s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-09-07 16:33:49 +00:00
|
|
|
/*
|
|
|
|
* Step 1. w <- s^-1 mod q.
|
|
|
|
*/
|
2000-12-02 12:48:15 +00:00
|
|
|
w = modinv(s, dss->q);
|
2013-08-04 19:34:07 +00:00
|
|
|
if (!w) {
|
|
|
|
freebn(r);
|
|
|
|
freebn(s);
|
|
|
|
return 0;
|
|
|
|
}
|
2000-09-07 16:33:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 2. u1 <- SHA(message) * w mod q.
|
|
|
|
*/
|
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-05-31 17:40:51 +00:00
|
|
|
SHA_Simple(data.ptr, data.len, hash);
|
|
|
|
sha = bignum_from_bytes(hash, 20);
|
2000-12-02 12:48:15 +00:00
|
|
|
u1 = modmul(sha, w, dss->q);
|
2000-09-07 16:33:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 3. u2 <- r * w mod q.
|
|
|
|
*/
|
2000-12-02 12:48:15 +00:00
|
|
|
u2 = modmul(r, w, dss->q);
|
2000-09-07 16:33:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 4. v <- (g^u1 * y^u2 mod p) mod q.
|
|
|
|
*/
|
2000-12-02 12:48:15 +00:00
|
|
|
gu1p = modpow(dss->g, u1, dss->p);
|
|
|
|
yu2p = modpow(dss->y, u2, dss->p);
|
|
|
|
gu1yu2p = modmul(gu1p, yu2p, dss->p);
|
|
|
|
v = modmul(gu1yu2p, One, dss->q);
|
2000-09-07 16:33:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 5. v should now be equal to r.
|
|
|
|
*/
|
|
|
|
|
2000-10-23 16:03:21 +00:00
|
|
|
ret = !bignum_cmp(v, r);
|
2000-09-07 16:33:49 +00:00
|
|
|
|
|
|
|
freebn(w);
|
|
|
|
freebn(sha);
|
2013-07-14 10:46:07 +00:00
|
|
|
freebn(u1);
|
|
|
|
freebn(u2);
|
2000-10-23 16:11:31 +00:00
|
|
|
freebn(gu1p);
|
|
|
|
freebn(yu2p);
|
|
|
|
freebn(gu1yu2p);
|
2000-09-07 16:33:49 +00:00
|
|
|
freebn(v);
|
|
|
|
freebn(r);
|
|
|
|
freebn(s);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_public_blob(ssh_key *key, BinarySink *bs)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2001-03-03 11:54:34 +00:00
|
|
|
|
2018-05-24 09:59:39 +00:00
|
|
|
put_stringz(bs, "ssh-dss");
|
|
|
|
put_mp_ssh2(bs, dss->p);
|
|
|
|
put_mp_ssh2(bs, dss->q);
|
|
|
|
put_mp_ssh2(bs, dss->g);
|
|
|
|
put_mp_ssh2(bs, dss->y);
|
2001-03-03 11:54:34 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_private_blob(ssh_key *key, BinarySink *bs)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
2018-05-24 09:59:39 +00:00
|
|
|
put_mp_ssh2(bs, dss->x);
|
2001-03-03 11:54:34 +00:00
|
|
|
}
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
static ssh_key *dss_createkey(const ssh_keyalg *self, ptrlen pub, ptrlen priv)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource src[1];
|
2018-05-31 17:32:09 +00:00
|
|
|
ssh_key *sshk;
|
2001-09-22 20:52:21 +00:00
|
|
|
struct dss_key *dss;
|
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-05-31 17:40:51 +00:00
|
|
|
ptrlen hash;
|
2001-09-22 20:52:21 +00:00
|
|
|
SHA_State s;
|
|
|
|
unsigned char digest[20];
|
|
|
|
Bignum ytest;
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
sshk = dss_newkey(self, pub);
|
2018-05-31 17:32:09 +00:00
|
|
|
if (!sshk)
|
2013-08-04 19:33:49 +00:00
|
|
|
return NULL;
|
2018-05-31 17:32:09 +00:00
|
|
|
|
|
|
|
dss = FROMFIELD(sshk, struct dss_key, sshk);
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource_BARE_INIT(src, priv.ptr, priv.len);
|
|
|
|
dss->x = get_mp_ssh2(src);
|
|
|
|
if (get_err(src)) {
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2013-08-04 19:33:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2001-09-22 20:52:21 +00:00
|
|
|
|
|
|
|
/*
|
2001-11-25 14:31:46 +00:00
|
|
|
* Check the obsolete hash in the old DSS key format.
|
2001-09-22 20:52:21 +00:00
|
|
|
*/
|
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-05-31 17:40:51 +00:00
|
|
|
hash = get_string(src);
|
|
|
|
if (hash.len == 20) {
|
2001-11-25 14:31:46 +00:00
|
|
|
SHA_Init(&s);
|
2018-05-24 08:42:02 +00:00
|
|
|
put_mp_ssh2(&s, dss->p);
|
|
|
|
put_mp_ssh2(&s, dss->q);
|
|
|
|
put_mp_ssh2(&s, dss->g);
|
2001-11-25 14:31:46 +00:00
|
|
|
SHA_Final(&s, digest);
|
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-05-31 17:40:51 +00:00
|
|
|
if (0 != memcmp(hash.ptr, digest, 20)) {
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2001-11-25 14:31:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2001-09-22 20:52:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now ensure g^x mod p really is y.
|
|
|
|
*/
|
|
|
|
ytest = modpow(dss->g, dss->x, dss->p);
|
|
|
|
if (0 != bignum_cmp(ytest, dss->y)) {
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2013-07-14 10:46:07 +00:00
|
|
|
freebn(ytest);
|
2001-09-22 20:52:21 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
freebn(ytest);
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
return &dss->sshk;
|
2001-03-03 11:54:34 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static ssh_key *dss_openssh_createkey(const ssh_keyalg *self,
|
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-05-31 17:40:51 +00:00
|
|
|
BinarySource *src)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-09-22 20:52:21 +00:00
|
|
|
struct dss_key *dss;
|
|
|
|
|
2003-03-29 16:14:26 +00:00
|
|
|
dss = snew(struct dss_key);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
dss->p = get_mp_ssh2(src);
|
|
|
|
dss->q = get_mp_ssh2(src);
|
|
|
|
dss->g = get_mp_ssh2(src);
|
|
|
|
dss->y = get_mp_ssh2(src);
|
|
|
|
dss->x = get_mp_ssh2(src);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
if (get_err(src) ||
|
2013-08-04 19:33:49 +00:00
|
|
|
!bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
|
|
|
|
/* Invalid key. */
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2013-08-04 19:33:49 +00:00
|
|
|
return NULL;
|
2001-09-22 20:52:21 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
return &dss->sshk;
|
2001-03-03 15:31:35 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_openssh_fmtkey(ssh_key *key, BinarySink *bs)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2018-05-24 09:59:39 +00:00
|
|
|
|
|
|
|
put_mp_ssh2(bs, dss->p);
|
|
|
|
put_mp_ssh2(bs, dss->q);
|
|
|
|
put_mp_ssh2(bs, dss->g);
|
|
|
|
put_mp_ssh2(bs, dss->y);
|
|
|
|
put_mp_ssh2(bs, dss->x);
|
2001-04-16 11:16:58 +00:00
|
|
|
}
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
static int dss_pubkey_bits(const ssh_keyalg *self, ptrlen pub)
|
2004-01-22 19:15:32 +00:00
|
|
|
{
|
2018-05-31 17:32:09 +00:00
|
|
|
ssh_key *sshk;
|
2004-01-22 19:15:32 +00:00
|
|
|
struct dss_key *dss;
|
|
|
|
int ret;
|
|
|
|
|
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-05-31 17:40:51 +00:00
|
|
|
sshk = dss_newkey(self, pub);
|
2018-05-31 17:32:09 +00:00
|
|
|
if (!sshk)
|
2013-08-04 19:33:49 +00:00
|
|
|
return -1;
|
2018-05-31 17:32:09 +00:00
|
|
|
|
|
|
|
dss = FROMFIELD(sshk, struct dss_key, sshk);
|
2004-01-22 19:15:32 +00:00
|
|
|
ret = bignum_bitcount(dss->p);
|
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 07:32:21 +00:00
|
|
|
dss_freekey(&dss->sshk);
|
2004-01-22 19:15:32 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-11-01 19:48:48 +00:00
|
|
|
Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key,
|
|
|
|
unsigned char *digest, int digest_len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-09-22 20:52:21 +00:00
|
|
|
/*
|
|
|
|
* The basic DSS signing algorithm is:
|
|
|
|
*
|
|
|
|
* - invent a random k between 1 and q-1 (exclusive).
|
|
|
|
* - Compute r = (g^k mod p) mod q.
|
|
|
|
* - Compute s = k^-1 * (hash + x*r) mod q.
|
|
|
|
*
|
|
|
|
* This has the dangerous properties that:
|
|
|
|
*
|
|
|
|
* - if an attacker in possession of the public key _and_ the
|
|
|
|
* signature (for example, the host you just authenticated
|
|
|
|
* to) can guess your k, he can reverse the computation of s
|
|
|
|
* and work out x = r^-1 * (s*k - hash) mod q. That is, he
|
|
|
|
* can deduce the private half of your key, and masquerade
|
|
|
|
* as you for as long as the key is still valid.
|
|
|
|
*
|
|
|
|
* - since r is a function purely of k and the public key, if
|
|
|
|
* the attacker only has a _range of possibilities_ for k
|
|
|
|
* it's easy for him to work through them all and check each
|
|
|
|
* one against r; he'll never be unsure of whether he's got
|
|
|
|
* the right one.
|
|
|
|
*
|
|
|
|
* - if you ever sign two different hashes with the same k, it
|
|
|
|
* will be immediately obvious because the two signatures
|
|
|
|
* will have the same r, and moreover an attacker in
|
|
|
|
* possession of both signatures (and the public key of
|
|
|
|
* course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
|
|
|
|
* and from there deduce x as before.
|
|
|
|
*
|
|
|
|
* - the Bleichenbacher attack on DSA makes use of methods of
|
|
|
|
* generating k which are significantly non-uniformly
|
|
|
|
* distributed; in particular, generating a 160-bit random
|
|
|
|
* number and reducing it mod q is right out.
|
|
|
|
*
|
|
|
|
* For this reason we must be pretty careful about how we
|
|
|
|
* generate our k. Since this code runs on Windows, with no
|
|
|
|
* particularly good system entropy sources, we can't trust our
|
|
|
|
* RNG itself to produce properly unpredictable data. Hence, we
|
|
|
|
* use a totally different scheme instead.
|
|
|
|
*
|
|
|
|
* What we do is to take a SHA-512 (_big_) hash of the private
|
|
|
|
* key x, and then feed this into another SHA-512 hash that
|
|
|
|
* also includes the message hash being signed. That is:
|
|
|
|
*
|
|
|
|
* proto_k = SHA512 ( SHA512(x) || SHA160(message) )
|
|
|
|
*
|
|
|
|
* This number is 512 bits long, so reducing it mod q won't be
|
|
|
|
* noticeably non-uniform. So
|
|
|
|
*
|
|
|
|
* k = proto_k mod q
|
|
|
|
*
|
|
|
|
* This has the interesting property that it's _deterministic_:
|
|
|
|
* signing the same hash twice with the same key yields the
|
|
|
|
* same signature.
|
|
|
|
*
|
2001-09-22 21:00:16 +00:00
|
|
|
* Despite this determinism, it's still not predictable to an
|
|
|
|
* attacker, because in order to repeat the SHA-512
|
|
|
|
* construction that created it, the attacker would have to
|
|
|
|
* know the private key value x - and by assumption he doesn't,
|
|
|
|
* because if he knew that he wouldn't be attacking k!
|
|
|
|
*
|
|
|
|
* (This trick doesn't, _per se_, protect against reuse of k.
|
|
|
|
* Reuse of k is left to chance; all it does is prevent
|
|
|
|
* _excessively high_ chances of reuse of k due to entropy
|
|
|
|
* problems.)
|
2001-09-22 20:52:21 +00:00
|
|
|
*
|
|
|
|
* Thanks to Colin Plumb for the general idea of using x to
|
|
|
|
* ensure k is hard to guess, and to the Cambridge University
|
|
|
|
* Computer Security Group for helping to argue out all the
|
|
|
|
* fine details.
|
|
|
|
*/
|
|
|
|
SHA512_State ss;
|
2014-11-01 19:48:48 +00:00
|
|
|
unsigned char digest512[64];
|
|
|
|
Bignum proto_k, k;
|
2001-09-22 20:52:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Hash some identifying text plus x.
|
|
|
|
*/
|
|
|
|
SHA512_Init(&ss);
|
2018-05-24 09:03:36 +00:00
|
|
|
put_asciz(&ss, id_string);
|
2018-05-24 08:42:02 +00:00
|
|
|
put_mp_ssh2(&ss, private_key);
|
2001-09-22 20:52:21 +00:00
|
|
|
SHA512_Final(&ss, digest512);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now hash that digest plus the message hash.
|
|
|
|
*/
|
|
|
|
SHA512_Init(&ss);
|
2018-05-24 09:03:36 +00:00
|
|
|
put_data(&ss, digest512, sizeof(digest512));
|
|
|
|
put_data(&ss, digest, digest_len);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
2013-08-04 19:34:07 +00:00
|
|
|
while (1) {
|
|
|
|
SHA512_State ss2 = ss; /* structure copy */
|
|
|
|
SHA512_Final(&ss2, digest512);
|
|
|
|
|
|
|
|
smemclr(&ss2, sizeof(ss2));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now convert the result into a bignum, and reduce it mod q.
|
|
|
|
*/
|
|
|
|
proto_k = bignum_from_bytes(digest512, 64);
|
2014-11-01 19:48:48 +00:00
|
|
|
k = bigmod(proto_k, modulus);
|
2013-08-04 19:34:07 +00:00
|
|
|
freebn(proto_k);
|
2014-11-01 19:48:48 +00:00
|
|
|
|
|
|
|
if (bignum_cmp(k, One) != 0 && bignum_cmp(k, Zero) != 0) {
|
|
|
|
smemclr(&ss, sizeof(ss));
|
|
|
|
smemclr(digest512, sizeof(digest512));
|
|
|
|
return k;
|
2013-08-04 19:34:07 +00:00
|
|
|
}
|
|
|
|
|
2014-11-01 19:48:48 +00:00
|
|
|
/* Very unlikely we get here, but if so, k was unsuitable. */
|
|
|
|
freebn(k);
|
|
|
|
/* Perturb the hash to think of a different k. */
|
2018-05-24 09:03:36 +00:00
|
|
|
put_byte(&ss, 'x');
|
2014-11-01 19:48:48 +00:00
|
|
|
/* Go round and try again. */
|
2013-08-04 19:34:07 +00:00
|
|
|
}
|
2014-11-01 19:48:48 +00:00
|
|
|
}
|
2001-09-22 20:52:21 +00:00
|
|
|
|
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 07:32:21 +00:00
|
|
|
static void dss_sign(ssh_key *key, const void *data, int datalen,
|
2018-05-24 09:59:39 +00:00
|
|
|
BinarySink *bs)
|
2014-11-01 19:48:48 +00:00
|
|
|
{
|
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 07:32:21 +00:00
|
|
|
struct dss_key *dss = FROMFIELD(key, struct dss_key, sshk);
|
2014-11-01 19:48:48 +00:00
|
|
|
Bignum k, gkp, hash, kinv, hxr, r, s;
|
|
|
|
unsigned char digest[20];
|
2018-05-24 09:59:39 +00:00
|
|
|
int i;
|
2014-11-01 19:48:48 +00:00
|
|
|
|
|
|
|
SHA_Simple(data, datalen, digest);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
2014-11-01 19:48:48 +00:00
|
|
|
k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x,
|
|
|
|
digest, sizeof(digest));
|
|
|
|
kinv = modinv(k, dss->q); /* k^-1 mod q */
|
|
|
|
assert(kinv);
|
2001-09-22 20:52:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we have k, so just go ahead and compute the signature.
|
|
|
|
*/
|
|
|
|
gkp = modpow(dss->g, k, dss->p); /* g^k mod p */
|
|
|
|
r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */
|
|
|
|
freebn(gkp);
|
|
|
|
|
|
|
|
hash = bignum_from_bytes(digest, 20);
|
|
|
|
hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */
|
|
|
|
s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */
|
|
|
|
freebn(hxr);
|
|
|
|
freebn(kinv);
|
2013-08-04 19:33:57 +00:00
|
|
|
freebn(k);
|
2001-09-22 20:52:21 +00:00
|
|
|
freebn(hash);
|
|
|
|
|
2018-05-24 09:59:39 +00:00
|
|
|
put_stringz(bs, "ssh-dss");
|
|
|
|
put_uint32(bs, 40);
|
|
|
|
for (i = 0; i < 20; i++)
|
|
|
|
put_byte(bs, bignum_byte(r, 19 - i));
|
|
|
|
for (i = 0; i < 20; i++)
|
|
|
|
put_byte(bs, bignum_byte(s, 19 - i));
|
2001-09-22 20:52:21 +00:00
|
|
|
freebn(r);
|
|
|
|
freebn(s);
|
2000-12-02 12:48:15 +00:00
|
|
|
}
|
|
|
|
|
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 07:32:21 +00:00
|
|
|
const ssh_keyalg ssh_dss = {
|
2000-12-02 12:48:15 +00:00
|
|
|
dss_newkey,
|
|
|
|
dss_freekey,
|
2000-09-07 16:33:49 +00:00
|
|
|
dss_fmtkey,
|
2001-03-03 11:54:34 +00:00
|
|
|
dss_public_blob,
|
|
|
|
dss_private_blob,
|
|
|
|
dss_createkey,
|
2001-03-03 15:31:35 +00:00
|
|
|
dss_openssh_createkey,
|
2001-04-16 11:16:58 +00:00
|
|
|
dss_openssh_fmtkey,
|
2015-05-02 14:11:41 +00:00
|
|
|
5 /* p,q,g,y,x */,
|
2004-01-22 19:15:32 +00:00
|
|
|
dss_pubkey_bits,
|
2000-09-07 16:33:49 +00:00
|
|
|
dss_verifysig,
|
2000-12-02 12:48:15 +00:00
|
|
|
dss_sign,
|
2000-09-27 15:21:04 +00:00
|
|
|
"ssh-dss",
|
2015-05-15 09:12:08 +00:00
|
|
|
"dss",
|
|
|
|
NULL,
|
2000-09-05 14:28:17 +00:00
|
|
|
};
|