#include "ssh.h"
#include "misc.h"
-int makekey(unsigned char *data, int len, struct RSAKey *result,
- unsigned char **keystr, int order)
+int makekey(const unsigned char *data, int len, struct RSAKey *result,
+ const unsigned char **keystr, int order)
{
- unsigned char *p = data;
+ const unsigned char *p = data;
int i, n;
if (len < 4)
return p - data;
}
-int makeprivate(unsigned char *data, int len, struct RSAKey *result)
+int makeprivate(const unsigned char *data, int len, struct RSAKey *result)
{
return ssh1_read_bignum(data, len, &result->private_exponent);
}
bitsleft--;
bignum_set_bit(random, bits, v);
}
+ bn_restore_invariant(random);
/*
* Now check that this number is strictly greater than
bignum_cmp(random, key->modulus) >= 0) {
freebn(random);
continue;
- } else {
- break;
}
+
+ /*
+ * Also, make sure it has an inverse mod modulus.
+ */
+ random_inverse = modinv(random, key->modulus);
+ if (!random_inverse) {
+ freebn(random);
+ continue;
+ }
+
+ break;
}
/*
*/
random_encrypted = crt_modpow(random, key->exponent,
key->modulus, key->p, key->q, key->iqmp);
- random_inverse = modinv(random, key->modulus);
input_blinded = modmul(input, random_encrypted, key->modulus);
ret_blinded = crt_modpow(input_blinded, key->private_exponent,
key->modulus, key->p, key->q, key->iqmp);
pm1 = copybn(key->p);
decbn(pm1);
ed = modmul(key->exponent, key->private_exponent, pm1);
+ freebn(pm1);
cmp = bignum_cmp(ed, One);
- sfree(ed);
+ freebn(ed);
if (cmp != 0)
return 0;
qm1 = copybn(key->q);
decbn(qm1);
ed = modmul(key->exponent, key->private_exponent, qm1);
+ freebn(qm1);
cmp = bignum_cmp(ed, One);
- sfree(ed);
+ freebn(ed);
if (cmp != 0)
return 0;
freebn(key->iqmp);
key->iqmp = modinv(key->q, key->p);
+ if (!key->iqmp)
+ return 0;
}
/*
*/
n = modmul(key->iqmp, key->q, key->p);
cmp = bignum_cmp(n, One);
- sfree(n);
+ freebn(n);
if (cmp != 0)
return 0;
* Implementation of the ssh-rsa signing key type.
*/
-static void getstring(char **data, int *datalen, char **p, int *length)
+static void getstring(const char **data, int *datalen,
+ const char **p, int *length)
{
*p = NULL;
if (*datalen < 4)
return;
- *length = GET_32BIT(*data);
+ *length = toint(GET_32BIT(*data));
+ if (*length < 0)
+ return;
*datalen -= 4;
*data += 4;
if (*datalen < *length)
*data += *length;
*datalen -= *length;
}
-static Bignum getmp(char **data, int *datalen)
+static Bignum getmp(const char **data, int *datalen)
{
- char *p;
+ const char *p;
int length;
Bignum b;
return b;
}
-static void *rsa2_newkey(char *data, int len)
+static void rsa2_freekey(void *key); /* forward reference */
+
+static void *rsa2_newkey(const struct ssh_signkey *self,
+ const char *data, int len)
{
- char *p;
+ const char *p;
int slen;
struct RSAKey *rsa;
rsa = snew(struct RSAKey);
- if (!rsa)
- return NULL;
getstring(&data, &len, &p, &slen);
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
rsa->p = rsa->q = rsa->iqmp = NULL;
rsa->comment = NULL;
+ if (!rsa->exponent || !rsa->modulus) {
+ rsa2_freekey(rsa);
+ return NULL;
+ }
+
return rsa;
}
return blob;
}
-static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
- unsigned char *priv_blob, int priv_len)
+static void *rsa2_createkey(const struct ssh_signkey *self,
+ const unsigned char *pub_blob, int pub_len,
+ const unsigned char *priv_blob, int priv_len)
{
struct RSAKey *rsa;
- char *pb = (char *) priv_blob;
+ const char *pb = (const char *) priv_blob;
- rsa = rsa2_newkey((char *) pub_blob, pub_len);
+ rsa = rsa2_newkey(self, (char *) pub_blob, pub_len);
rsa->private_exponent = getmp(&pb, &priv_len);
rsa->p = getmp(&pb, &priv_len);
rsa->q = getmp(&pb, &priv_len);
return rsa;
}
-static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
+static void *rsa2_openssh_createkey(const struct ssh_signkey *self,
+ const unsigned char **blob, int *len)
{
- char **b = (char **) blob;
+ const char **b = (const char **) blob;
struct RSAKey *rsa;
rsa = snew(struct RSAKey);
- if (!rsa)
- return NULL;
rsa->comment = NULL;
rsa->modulus = getmp(b, len);
if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||
!rsa->iqmp || !rsa->p || !rsa->q) {
- sfree(rsa->modulus);
- sfree(rsa->exponent);
- sfree(rsa->private_exponent);
- sfree(rsa->iqmp);
- sfree(rsa->p);
- sfree(rsa->q);
- sfree(rsa);
+ rsa2_freekey(rsa);
+ return NULL;
+ }
+
+ if (!rsa_verify(rsa)) {
+ rsa2_freekey(rsa);
return NULL;
}
return bloblen;
}
-static int rsa2_pubkey_bits(void *blob, int len)
+static int rsa2_pubkey_bits(const struct ssh_signkey *self,
+ const void *blob, int len)
{
struct RSAKey *rsa;
int ret;
- rsa = rsa2_newkey((char *) blob, len);
+ rsa = rsa2_newkey(self, (const char *) blob, len);
+ if (!rsa)
+ return -1;
ret = bignum_bitcount(rsa->modulus);
rsa2_freekey(rsa);
return ret;
}
-static char *rsa2_fingerprint(void *key)
-{
- struct RSAKey *rsa = (struct RSAKey *) key;
- struct MD5Context md5c;
- unsigned char digest[16], lenbuf[4];
- char buffer[16 * 3 + 40];
- char *ret;
- int numlen, i;
-
- MD5Init(&md5c);
- MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-rsa", 11);
-
-#define ADD_BIGNUM(bignum) \
- numlen = (bignum_bitcount(bignum)+8)/8; \
- PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
- for (i = numlen; i-- ;) { \
- unsigned char c = bignum_byte(bignum, i); \
- MD5Update(&md5c, &c, 1); \
- }
- ADD_BIGNUM(rsa->exponent);
- ADD_BIGNUM(rsa->modulus);
-#undef ADD_BIGNUM
-
- MD5Final(digest, &md5c);
-
- sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
- for (i = 0; i < 16; i++)
- sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
- digest[i]);
- ret = snewn(strlen(buffer) + 1, char);
- if (ret)
- strcpy(ret, buffer);
- return ret;
-}
-
/*
* This is the magic ASN.1/DER prefix that goes in the decoded
* signature, between the string of FFs and the actual SHA hash
#define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) )
-static int rsa2_verifysig(void *key, char *sig, int siglen,
- char *data, int datalen)
+static int rsa2_verifysig(void *key, const char *sig, int siglen,
+ const char *data, int datalen)
{
struct RSAKey *rsa = (struct RSAKey *) key;
Bignum in, out;
- char *p;
+ const char *p;
int slen;
int bytes, i, j, ret;
unsigned char hash[20];
return 0;
}
in = getmp(&sig, &siglen);
+ if (!in)
+ return 0;
out = modpow(in, rsa->exponent, rsa->modulus);
freebn(in);
return ret;
}
-static unsigned char *rsa2_sign(void *key, char *data, int datalen,
+static unsigned char *rsa2_sign(void *key, const char *data, int datalen,
int *siglen)
{
struct RSAKey *rsa = (struct RSAKey *) key;
rsa2_createkey,
rsa2_openssh_createkey,
rsa2_openssh_fmtkey,
+ 6 /* n,e,d,iqmp,q,p */,
rsa2_pubkey_bits,
- rsa2_fingerprint,
rsa2_verifysig,
rsa2_sign,
"ssh-rsa",
- "rsa2"
+ "rsa2",
+ NULL,
};
void *ssh_rsakex_newkey(char *data, int len)
{
- return rsa2_newkey(data, len);
+ return rsa2_newkey(&ssh_rsa, data, len);
}
void ssh_rsakex_freekey(void *key)
}
static const struct ssh_kex ssh_rsa_kex_sha1 = {
- "rsa1024-sha1", NULL, KEXTYPE_RSA, NULL, NULL, 0, 0, &ssh_sha1
+ "rsa1024-sha1", NULL, KEXTYPE_RSA, &ssh_sha1, NULL,
};
static const struct ssh_kex ssh_rsa_kex_sha256 = {
- "rsa2048-sha256", NULL, KEXTYPE_RSA, NULL, NULL, 0, 0, &ssh_sha256
+ "rsa2048-sha256", NULL, KEXTYPE_RSA, &ssh_sha256, NULL,
};
static const struct ssh_kex *const rsa_kex_list[] = {