mirror of
https://github.com/clearml/dropbear
synced 2025-04-15 21:11:19 +00:00
writing out openssh ecc keys works
--HG-- branch : ecc
This commit is contained in:
parent
aafeebd0c8
commit
7fda6418e1
@ -28,6 +28,8 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "dbutil.h"
|
#include "dbutil.h"
|
||||||
#include "keyimport.h"
|
#include "keyimport.h"
|
||||||
|
#include "crypto_desc.h"
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
|
||||||
static int do_convert(int intype, const char* infile, int outtype,
|
static int do_convert(int intype, const char* infile, int outtype,
|
||||||
@ -114,7 +116,7 @@ static int do_convert(int intype, const char* infile, int outtype,
|
|||||||
const char* outfile) {
|
const char* outfile) {
|
||||||
|
|
||||||
sign_key * key = NULL;
|
sign_key * key = NULL;
|
||||||
char * keytype = NULL;
|
const char * keytype = NULL;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
key = import_read(infile, NULL, intype);
|
key = import_read(infile, NULL, intype);
|
||||||
@ -124,16 +126,7 @@ static int do_convert(int intype, const char* infile, int outtype,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
keytype = signkey_name_from_type(key->type, NULL);
|
||||||
if (key->rsakey != NULL) {
|
|
||||||
keytype = "RSA";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
if (key->dsskey != NULL) {
|
|
||||||
keytype = "DSS";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fprintf(stderr, "Key is a %s key\n", keytype);
|
fprintf(stderr, "Key is a %s key\n", keytype);
|
||||||
|
|
||||||
|
457
keyimport.c
457
keyimport.c
@ -2,8 +2,6 @@
|
|||||||
* Based on PuTTY's import.c for importing/exporting OpenSSH and SSH.com
|
* Based on PuTTY's import.c for importing/exporting OpenSSH and SSH.com
|
||||||
* keyfiles.
|
* keyfiles.
|
||||||
*
|
*
|
||||||
* The horribleness of the code is probably mine (matt).
|
|
||||||
*
|
|
||||||
* Modifications copyright 2003 Matt Johnston
|
* Modifications copyright 2003 Matt Johnston
|
||||||
*
|
*
|
||||||
* PuTTY is copyright 1997-2003 Simon Tatham.
|
* PuTTY is copyright 1997-2003 Simon Tatham.
|
||||||
@ -38,9 +36,9 @@
|
|||||||
#include "dbutil.h"
|
#include "dbutil.h"
|
||||||
#include "ecc.h"
|
#include "ecc.h"
|
||||||
|
|
||||||
const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
|
static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
|
||||||
const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
|
static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
|
||||||
const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
|
static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
|
||||||
|
|
||||||
#define PUT_32BIT(cp, value) do { \
|
#define PUT_32BIT(cp, value) do { \
|
||||||
(cp)[3] = (unsigned char)(value); \
|
(cp)[3] = (unsigned char)(value); \
|
||||||
@ -130,6 +128,8 @@ static sign_key *dropbear_read(const char* filename) {
|
|||||||
}
|
}
|
||||||
buf_free(buf);
|
buf_free(buf);
|
||||||
|
|
||||||
|
ret->type = type;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -145,23 +145,11 @@ error:
|
|||||||
/* returns 0 on fail, 1 on success */
|
/* returns 0 on fail, 1 on success */
|
||||||
static int dropbear_write(const char*filename, sign_key * key) {
|
static int dropbear_write(const char*filename, sign_key * key) {
|
||||||
|
|
||||||
int keytype = -1;
|
|
||||||
buffer * buf;
|
buffer * buf;
|
||||||
FILE*fp;
|
FILE*fp;
|
||||||
int len;
|
int len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
|
||||||
if (key->rsakey != NULL) {
|
|
||||||
keytype = DROPBEAR_SIGNKEY_RSA;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
if (key->dsskey != NULL) {
|
|
||||||
keytype = DROPBEAR_SIGNKEY_DSS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||||
buf_put_priv_key(buf, key, key->type);
|
buf_put_priv_key(buf, key, key->type);
|
||||||
|
|
||||||
@ -616,8 +604,10 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
|||||||
|
|
||||||
if (key->type == OSSH_DSA) {
|
if (key->type == OSSH_DSA) {
|
||||||
buf_putstring(blobbuf, "ssh-dss", 7);
|
buf_putstring(blobbuf, "ssh-dss", 7);
|
||||||
|
retkey->type = DROPBEAR_SIGNKEY_DSS;
|
||||||
} else if (key->type == OSSH_RSA) {
|
} else if (key->type == OSSH_RSA) {
|
||||||
buf_putstring(blobbuf, "ssh-rsa", 7);
|
buf_putstring(blobbuf, "ssh-rsa", 7);
|
||||||
|
retkey->type = DROPBEAR_SIGNKEY_RSA;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_integers; i++) {
|
for (i = 0; i < num_integers; i++) {
|
||||||
@ -675,7 +665,6 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
|||||||
|
|
||||||
#ifdef DROPBEAR_ECDSA
|
#ifdef DROPBEAR_ECDSA
|
||||||
if (key->type == OSSH_EC) {
|
if (key->type == OSSH_EC) {
|
||||||
const char* ecdsa_name;
|
|
||||||
unsigned char* private_key_bytes = NULL;
|
unsigned char* private_key_bytes = NULL;
|
||||||
int private_key_len = 0;
|
int private_key_len = 0;
|
||||||
unsigned char* public_key_bytes = NULL;
|
unsigned char* public_key_bytes = NULL;
|
||||||
@ -827,202 +816,282 @@ static int openssh_write(const char *filename, sign_key *key,
|
|||||||
char zero[1];
|
char zero[1];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int keytype = -1;
|
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
|
mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
|
||||||
|
|
||||||
if (key->rsakey != NULL) {
|
|
||||||
keytype = DROPBEAR_SIGNKEY_RSA;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
if (key->dsskey != NULL) {
|
|
||||||
keytype = DROPBEAR_SIGNKEY_DSS;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dropbear_assert(keytype != -1);
|
if (key->type == DROPBEAR_SIGNKEY_RSA || key->type == DROPBEAR_SIGNKEY_DSS)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Fetch the key blobs.
|
||||||
|
*/
|
||||||
|
keyblob = buf_new(3000);
|
||||||
|
buf_put_priv_key(keyblob, key, key->type);
|
||||||
|
|
||||||
/*
|
buf_setpos(keyblob, 0);
|
||||||
* Fetch the key blobs.
|
/* skip the "ssh-rsa" or "ssh-dss" header */
|
||||||
*/
|
buf_incrpos(keyblob, buf_getint(keyblob));
|
||||||
keyblob = buf_new(3000);
|
|
||||||
buf_put_priv_key(keyblob, key, keytype);
|
|
||||||
|
|
||||||
buf_setpos(keyblob, 0);
|
/*
|
||||||
/* skip the "ssh-rsa" or "ssh-dss" header */
|
* Find the sequence of integers to be encoded into the OpenSSH
|
||||||
buf_incrpos(keyblob, buf_getint(keyblob));
|
* key blob, and also decide on the header line.
|
||||||
|
*/
|
||||||
|
numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
|
||||||
|
|
||||||
/*
|
#ifdef DROPBEAR_RSA
|
||||||
* Find the sequence of integers to be encoded into the OpenSSH
|
if (key->type == DROPBEAR_SIGNKEY_RSA) {
|
||||||
* key blob, and also decide on the header line.
|
|
||||||
*/
|
|
||||||
numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
|
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
|
||||||
if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
|
/* e */
|
||||||
fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
|
numbers[2].bytes = buf_getint(keyblob);
|
||||||
goto error;
|
numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[2].bytes);
|
||||||
|
|
||||||
|
/* n */
|
||||||
|
numbers[1].bytes = buf_getint(keyblob);
|
||||||
|
numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[1].bytes);
|
||||||
|
|
||||||
|
/* d */
|
||||||
|
numbers[3].bytes = buf_getint(keyblob);
|
||||||
|
numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[3].bytes);
|
||||||
|
|
||||||
|
/* p */
|
||||||
|
numbers[4].bytes = buf_getint(keyblob);
|
||||||
|
numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[4].bytes);
|
||||||
|
|
||||||
|
/* q */
|
||||||
|
numbers[5].bytes = buf_getint(keyblob);
|
||||||
|
numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[5].bytes);
|
||||||
|
|
||||||
|
/* now calculate some extra parameters: */
|
||||||
|
m_mp_init(&tmpval);
|
||||||
|
m_mp_init(&dmp1);
|
||||||
|
m_mp_init(&dmq1);
|
||||||
|
m_mp_init(&iqmp);
|
||||||
|
|
||||||
|
/* dmp1 = d mod (p-1) */
|
||||||
|
if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) {
|
||||||
|
fprintf(stderr, "Bignum error for p-1\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) {
|
||||||
|
fprintf(stderr, "Bignum error for dmp1\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dmq1 = d mod (q-1) */
|
||||||
|
if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) {
|
||||||
|
fprintf(stderr, "Bignum error for q-1\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) {
|
||||||
|
fprintf(stderr, "Bignum error for dmq1\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iqmp = (q^-1) mod p */
|
||||||
|
if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) {
|
||||||
|
fprintf(stderr, "Bignum error for iqmp\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
extrablob = buf_new(2000);
|
||||||
|
buf_putmpint(extrablob, &dmp1);
|
||||||
|
buf_putmpint(extrablob, &dmq1);
|
||||||
|
buf_putmpint(extrablob, &iqmp);
|
||||||
|
buf_setpos(extrablob, 0);
|
||||||
|
mp_clear(&dmp1);
|
||||||
|
mp_clear(&dmq1);
|
||||||
|
mp_clear(&iqmp);
|
||||||
|
mp_clear(&tmpval);
|
||||||
|
|
||||||
|
/* dmp1 */
|
||||||
|
numbers[6].bytes = buf_getint(extrablob);
|
||||||
|
numbers[6].start = buf_getptr(extrablob, numbers[6].bytes);
|
||||||
|
buf_incrpos(extrablob, numbers[6].bytes);
|
||||||
|
|
||||||
|
/* dmq1 */
|
||||||
|
numbers[7].bytes = buf_getint(extrablob);
|
||||||
|
numbers[7].start = buf_getptr(extrablob, numbers[7].bytes);
|
||||||
|
buf_incrpos(extrablob, numbers[7].bytes);
|
||||||
|
|
||||||
|
/* iqmp */
|
||||||
|
numbers[8].bytes = buf_getint(extrablob);
|
||||||
|
numbers[8].start = buf_getptr(extrablob, numbers[8].bytes);
|
||||||
|
buf_incrpos(extrablob, numbers[8].bytes);
|
||||||
|
|
||||||
|
nnumbers = 9;
|
||||||
|
header = "-----BEGIN RSA PRIVATE KEY-----\n";
|
||||||
|
footer = "-----END RSA PRIVATE KEY-----\n";
|
||||||
|
}
|
||||||
|
#endif /* DROPBEAR_RSA */
|
||||||
|
|
||||||
|
#ifdef DROPBEAR_DSS
|
||||||
|
if (key->type == DROPBEAR_SIGNKEY_DSS) {
|
||||||
|
|
||||||
|
/* p */
|
||||||
|
numbers[1].bytes = buf_getint(keyblob);
|
||||||
|
numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[1].bytes);
|
||||||
|
|
||||||
|
/* q */
|
||||||
|
numbers[2].bytes = buf_getint(keyblob);
|
||||||
|
numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[2].bytes);
|
||||||
|
|
||||||
|
/* g */
|
||||||
|
numbers[3].bytes = buf_getint(keyblob);
|
||||||
|
numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[3].bytes);
|
||||||
|
|
||||||
|
/* y */
|
||||||
|
numbers[4].bytes = buf_getint(keyblob);
|
||||||
|
numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[4].bytes);
|
||||||
|
|
||||||
|
/* x */
|
||||||
|
numbers[5].bytes = buf_getint(keyblob);
|
||||||
|
numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
|
||||||
|
buf_incrpos(keyblob, numbers[5].bytes);
|
||||||
|
|
||||||
|
nnumbers = 6;
|
||||||
|
header = "-----BEGIN DSA PRIVATE KEY-----\n";
|
||||||
|
footer = "-----END DSA PRIVATE KEY-----\n";
|
||||||
|
}
|
||||||
|
#endif /* DROPBEAR_DSS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now count up the total size of the ASN.1 encoded integers,
|
||||||
|
* so as to determine the length of the containing SEQUENCE.
|
||||||
|
*/
|
||||||
|
len = 0;
|
||||||
|
for (i = 0; i < nnumbers; i++) {
|
||||||
|
len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
|
||||||
|
len += numbers[i].bytes;
|
||||||
|
}
|
||||||
|
seqlen = len;
|
||||||
|
/* Now add on the SEQUENCE header. */
|
||||||
|
len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
|
||||||
|
/* Round up to the cipher block size, ensuring we have at least one
|
||||||
|
* byte of padding (see below). */
|
||||||
|
outlen = len;
|
||||||
|
if (passphrase)
|
||||||
|
outlen = (outlen+8) &~ 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we know how big outblob needs to be. Allocate it.
|
||||||
|
*/
|
||||||
|
outblob = (unsigned char*)m_malloc(outlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And write the data into it.
|
||||||
|
*/
|
||||||
|
pos = 0;
|
||||||
|
pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
|
||||||
|
for (i = 0; i < nnumbers; i++) {
|
||||||
|
pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
|
||||||
|
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
|
||||||
|
pos += numbers[i].bytes;
|
||||||
|
}
|
||||||
|
} // end RSA and DSS handling
|
||||||
|
|
||||||
|
#ifdef DROPBEAR_ECDSA
|
||||||
|
if (key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
|
||||||
|
|| key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
|
||||||
|
|| key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) {
|
||||||
|
|
||||||
|
/* SEC1 V2 appendix c.4
|
||||||
|
ECPrivateKey ::= SEQUENCE {
|
||||||
|
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
|
||||||
|
privateKey OCTET STRING,
|
||||||
|
parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL,
|
||||||
|
publicKey [1] BIT STRING OPTIONAL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
buffer *seq_buf = buf_new(400);
|
||||||
|
ecc_key **eck = signkey_ecc_key_ptr(key, key->type);
|
||||||
|
const unsigned long curve_size = (*eck)->dp->size;
|
||||||
|
int curve_oid_len = 0;
|
||||||
|
const void* curve_oid = NULL;
|
||||||
|
unsigned long pubkey_size = 2*curve_size+1;
|
||||||
|
|
||||||
|
/* version. less than 10 bytes */
|
||||||
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 2, 1, 0));
|
||||||
|
buf_putbyte(seq_buf, 1);
|
||||||
|
|
||||||
|
/* privateKey */
|
||||||
|
dropbear_assert(mp_unsigned_bin_size((*eck)->k) == curve_size);
|
||||||
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, curve_size, 0));
|
||||||
|
mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, curve_size));
|
||||||
|
buf_incrwritepos(seq_buf, curve_size);
|
||||||
|
|
||||||
|
/* SECGCurveNames */
|
||||||
|
switch (key->type)
|
||||||
|
{
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||||
|
curve_oid_len = sizeof(OID_SEC256R1_BLOB);
|
||||||
|
curve_oid = OID_SEC256R1_BLOB;
|
||||||
|
break;
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
|
||||||
|
curve_oid_len = sizeof(OID_SEC384R1_BLOB);
|
||||||
|
curve_oid = OID_SEC384R1_BLOB;
|
||||||
|
break;
|
||||||
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
|
||||||
|
curve_oid_len = sizeof(OID_SEC521R1_BLOB);
|
||||||
|
curve_oid = OID_SEC521R1_BLOB;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dropbear_exit("Internal error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* e */
|
buf_incrwritepos(seq_buf,
|
||||||
numbers[2].bytes = buf_getint(keyblob);
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 0, 2+curve_oid_len, 0xa0));
|
||||||
numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
|
// object == 6
|
||||||
buf_incrpos(keyblob, numbers[2].bytes);
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 6, curve_oid_len, 0));
|
||||||
|
buf_putbytes(seq_buf, curve_oid, curve_oid_len);
|
||||||
|
|
||||||
/* n */
|
buf_incrwritepos(seq_buf,
|
||||||
numbers[1].bytes = buf_getint(keyblob);
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 1, 2+1+pubkey_size, 0xa0));
|
||||||
numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
|
buf_incrwritepos(seq_buf,
|
||||||
buf_incrpos(keyblob, numbers[1].bytes);
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 3, 1+pubkey_size, 0));
|
||||||
|
buf_putbyte(seq_buf, 0);
|
||||||
/* d */
|
int err = ecc_ansi_x963_export(*eck, buf_getwriteptr(seq_buf, pubkey_size), &pubkey_size);
|
||||||
numbers[3].bytes = buf_getint(keyblob);
|
if (err != CRYPT_OK) {
|
||||||
numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
|
dropbear_exit("ECC error");
|
||||||
buf_incrpos(keyblob, numbers[3].bytes);
|
|
||||||
|
|
||||||
/* p */
|
|
||||||
numbers[4].bytes = buf_getint(keyblob);
|
|
||||||
numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[4].bytes);
|
|
||||||
|
|
||||||
/* q */
|
|
||||||
numbers[5].bytes = buf_getint(keyblob);
|
|
||||||
numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[5].bytes);
|
|
||||||
|
|
||||||
/* now calculate some extra parameters: */
|
|
||||||
m_mp_init(&tmpval);
|
|
||||||
m_mp_init(&dmp1);
|
|
||||||
m_mp_init(&dmq1);
|
|
||||||
m_mp_init(&iqmp);
|
|
||||||
|
|
||||||
/* dmp1 = d mod (p-1) */
|
|
||||||
if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "Bignum error for p-1\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "Bignum error for dmp1\n");
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
buf_incrwritepos(seq_buf, pubkey_size);
|
||||||
|
|
||||||
/* dmq1 = d mod (q-1) */
|
buf_setpos(seq_buf, 0);
|
||||||
if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "Bignum error for q-1\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "Bignum error for dmq1\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iqmp = (q^-1) mod p */
|
outblob = (unsigned char*)m_malloc(200);
|
||||||
if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "Bignum error for iqmp\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
extrablob = buf_new(2000);
|
pos = 0;
|
||||||
buf_putmpint(extrablob, &dmp1);
|
pos += ber_write_id_len(outblob+pos, 16, seq_buf->len, ASN1_CONSTRUCTED);
|
||||||
buf_putmpint(extrablob, &dmq1);
|
memcpy(&outblob[pos], seq_buf->data, seq_buf->len);
|
||||||
buf_putmpint(extrablob, &iqmp);
|
pos += seq_buf->len;
|
||||||
buf_setpos(extrablob, 0);
|
len = pos;
|
||||||
mp_clear(&dmp1);
|
outlen = len;
|
||||||
mp_clear(&dmq1);
|
|
||||||
mp_clear(&iqmp);
|
|
||||||
mp_clear(&tmpval);
|
|
||||||
|
|
||||||
/* dmp1 */
|
buf_burn(seq_buf);
|
||||||
numbers[6].bytes = buf_getint(extrablob);
|
buf_free(seq_buf);
|
||||||
numbers[6].start = buf_getptr(extrablob, numbers[6].bytes);
|
seq_buf = NULL;
|
||||||
buf_incrpos(extrablob, numbers[6].bytes);
|
|
||||||
|
|
||||||
/* dmq1 */
|
header = "-----BEGIN EC PRIVATE KEY-----\n";
|
||||||
numbers[7].bytes = buf_getint(extrablob);
|
footer = "-----END EC PRIVATE KEY-----\n";
|
||||||
numbers[7].start = buf_getptr(extrablob, numbers[7].bytes);
|
|
||||||
buf_incrpos(extrablob, numbers[7].bytes);
|
|
||||||
|
|
||||||
/* iqmp */
|
|
||||||
numbers[8].bytes = buf_getint(extrablob);
|
|
||||||
numbers[8].start = buf_getptr(extrablob, numbers[8].bytes);
|
|
||||||
buf_incrpos(extrablob, numbers[8].bytes);
|
|
||||||
|
|
||||||
nnumbers = 9;
|
|
||||||
header = "-----BEGIN RSA PRIVATE KEY-----\n";
|
|
||||||
footer = "-----END RSA PRIVATE KEY-----\n";
|
|
||||||
}
|
|
||||||
#endif /* DROPBEAR_RSA */
|
|
||||||
|
|
||||||
#ifdef DROPBEAR_DSS
|
|
||||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
|
||||||
|
|
||||||
/* p */
|
|
||||||
numbers[1].bytes = buf_getint(keyblob);
|
|
||||||
numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[1].bytes);
|
|
||||||
|
|
||||||
/* q */
|
|
||||||
numbers[2].bytes = buf_getint(keyblob);
|
|
||||||
numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[2].bytes);
|
|
||||||
|
|
||||||
/* g */
|
|
||||||
numbers[3].bytes = buf_getint(keyblob);
|
|
||||||
numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[3].bytes);
|
|
||||||
|
|
||||||
/* y */
|
|
||||||
numbers[4].bytes = buf_getint(keyblob);
|
|
||||||
numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[4].bytes);
|
|
||||||
|
|
||||||
/* x */
|
|
||||||
numbers[5].bytes = buf_getint(keyblob);
|
|
||||||
numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
|
|
||||||
buf_incrpos(keyblob, numbers[5].bytes);
|
|
||||||
|
|
||||||
nnumbers = 6;
|
|
||||||
header = "-----BEGIN DSA PRIVATE KEY-----\n";
|
|
||||||
footer = "-----END DSA PRIVATE KEY-----\n";
|
|
||||||
}
|
|
||||||
#endif /* DROPBEAR_DSS */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now count up the total size of the ASN.1 encoded integers,
|
|
||||||
* so as to determine the length of the containing SEQUENCE.
|
|
||||||
*/
|
|
||||||
len = 0;
|
|
||||||
for (i = 0; i < nnumbers; i++) {
|
|
||||||
len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
|
|
||||||
len += numbers[i].bytes;
|
|
||||||
}
|
|
||||||
seqlen = len;
|
|
||||||
/* Now add on the SEQUENCE header. */
|
|
||||||
len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
|
|
||||||
/* Round up to the cipher block size, ensuring we have at least one
|
|
||||||
* byte of padding (see below). */
|
|
||||||
outlen = len;
|
|
||||||
if (passphrase)
|
|
||||||
outlen = (outlen+8) &~ 7;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now we know how big outblob needs to be. Allocate it.
|
|
||||||
*/
|
|
||||||
outblob = (unsigned char*)m_malloc(outlen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* And write the data into it.
|
|
||||||
*/
|
|
||||||
pos = 0;
|
|
||||||
pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
|
|
||||||
for (i = 0; i < nnumbers; i++) {
|
|
||||||
pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
|
|
||||||
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
|
|
||||||
pos += numbers[i].bytes;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Padding on OpenSSH keys is deterministic. The number of
|
* Padding on OpenSSH keys is deterministic. The number of
|
||||||
|
Loading…
Reference in New Issue
Block a user