mirror of
https://github.com/clearml/dropbear
synced 2025-04-19 05:35:05 +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);
|
||||||
|
|
||||||
|
135
keyimport.c
135
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,28 +816,18 @@ 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.
|
* Fetch the key blobs.
|
||||||
*/
|
*/
|
||||||
keyblob = buf_new(3000);
|
keyblob = buf_new(3000);
|
||||||
buf_put_priv_key(keyblob, key, keytype);
|
buf_put_priv_key(keyblob, key, key->type);
|
||||||
|
|
||||||
buf_setpos(keyblob, 0);
|
buf_setpos(keyblob, 0);
|
||||||
/* skip the "ssh-rsa" or "ssh-dss" header */
|
/* skip the "ssh-rsa" or "ssh-dss" header */
|
||||||
@ -861,7 +840,7 @@ static int openssh_write(const char *filename, sign_key *key,
|
|||||||
numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
|
numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
|
||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
if (key->type == DROPBEAR_SIGNKEY_RSA) {
|
||||||
|
|
||||||
if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
|
if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
|
||||||
fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
|
fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
|
||||||
@ -957,7 +936,7 @@ static int openssh_write(const char *filename, sign_key *key,
|
|||||||
#endif /* DROPBEAR_RSA */
|
#endif /* DROPBEAR_RSA */
|
||||||
|
|
||||||
#ifdef DROPBEAR_DSS
|
#ifdef DROPBEAR_DSS
|
||||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
if (key->type == DROPBEAR_SIGNKEY_DSS) {
|
||||||
|
|
||||||
/* p */
|
/* p */
|
||||||
numbers[1].bytes = buf_getint(keyblob);
|
numbers[1].bytes = buf_getint(keyblob);
|
||||||
@ -1023,6 +1002,96 @@ static int openssh_write(const char *filename, sign_key *key,
|
|||||||
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
|
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
|
||||||
pos += 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 0, 2+curve_oid_len, 0xa0));
|
||||||
|
// object == 6
|
||||||
|
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);
|
||||||
|
|
||||||
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 1, 2+1+pubkey_size, 0xa0));
|
||||||
|
buf_incrwritepos(seq_buf,
|
||||||
|
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 3, 1+pubkey_size, 0));
|
||||||
|
buf_putbyte(seq_buf, 0);
|
||||||
|
int err = ecc_ansi_x963_export(*eck, buf_getwriteptr(seq_buf, pubkey_size), &pubkey_size);
|
||||||
|
if (err != CRYPT_OK) {
|
||||||
|
dropbear_exit("ECC error");
|
||||||
|
}
|
||||||
|
buf_incrwritepos(seq_buf, pubkey_size);
|
||||||
|
|
||||||
|
buf_setpos(seq_buf, 0);
|
||||||
|
|
||||||
|
outblob = (unsigned char*)m_malloc(200);
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
pos += ber_write_id_len(outblob+pos, 16, seq_buf->len, ASN1_CONSTRUCTED);
|
||||||
|
memcpy(&outblob[pos], seq_buf->data, seq_buf->len);
|
||||||
|
pos += seq_buf->len;
|
||||||
|
len = pos;
|
||||||
|
outlen = len;
|
||||||
|
|
||||||
|
buf_burn(seq_buf);
|
||||||
|
buf_free(seq_buf);
|
||||||
|
seq_buf = NULL;
|
||||||
|
|
||||||
|
header = "-----BEGIN EC PRIVATE KEY-----\n";
|
||||||
|
footer = "-----END EC PRIVATE KEY-----\n";
|
||||||
|
}
|
||||||
|
#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