mirror of
https://github.com/clearml/dropbear
synced 2025-03-10 05:50:15 +00:00
hackish ECC import code from OpenSSH
--HG-- branch : ecc
This commit is contained in:
parent
d9e790e7dc
commit
6b0d47b364
@ -62,6 +62,9 @@ int main(int argc, char ** argv) {
|
||||
const char* infile;
|
||||
const char* outfile;
|
||||
|
||||
crypto_init();
|
||||
seedrandom();
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
/* It's hard for it to get in the way _too_ much */
|
||||
debug_trace = 1;
|
||||
|
136
keyimport.c
136
keyimport.c
@ -36,6 +36,11 @@
|
||||
#include "bignum.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "ecc.h"
|
||||
|
||||
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};
|
||||
const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
|
||||
|
||||
#define PUT_32BIT(cp, value) do { \
|
||||
(cp)[3] = (unsigned char)(value); \
|
||||
@ -158,7 +163,7 @@ static int dropbear_write(const char*filename, sign_key * key) {
|
||||
#endif
|
||||
|
||||
buf = buf_new(MAX_PRIVKEY_SIZE);
|
||||
buf_put_priv_key(buf, key, keytype);
|
||||
buf_put_priv_key(buf, key, key->type);
|
||||
|
||||
fp = fopen(filename, "w");
|
||||
if (!fp) {
|
||||
@ -523,6 +528,8 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
sign_key *retkey;
|
||||
buffer * blobbuf = NULL;
|
||||
|
||||
retkey = new_sign_key();
|
||||
|
||||
key = load_openssh_key(filename);
|
||||
|
||||
if (!key)
|
||||
@ -599,6 +606,8 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
num_integers = 9;
|
||||
else if (key->type == OSSH_DSA)
|
||||
num_integers = 6;
|
||||
else if (key->type == OSSH_EC)
|
||||
num_integers = 1;
|
||||
|
||||
/*
|
||||
* Space to create key blob in.
|
||||
@ -622,11 +631,18 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
/*
|
||||
* The first integer should be zero always (I think
|
||||
* this is some sort of version indication).
|
||||
*/
|
||||
if (len != 1 || p[0] != 0) {
|
||||
/* First integer is a version indicator */
|
||||
int expected;
|
||||
switch (key->type) {
|
||||
case OSSH_RSA:
|
||||
case OSSH_DSA:
|
||||
expected = 0;
|
||||
break;
|
||||
case OSSH_EC:
|
||||
expected = 1;
|
||||
break;
|
||||
}
|
||||
if (len != 1 || p[0] != expected) {
|
||||
errmsg = "Version number mismatch";
|
||||
goto error;
|
||||
}
|
||||
@ -657,13 +673,118 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
p += len;
|
||||
}
|
||||
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
if (key->type == OSSH_EC) {
|
||||
const char* ecdsa_name;
|
||||
unsigned char* private_key_bytes = NULL;
|
||||
int private_key_len = 0;
|
||||
unsigned char* public_key_bytes = NULL;
|
||||
int public_key_len = 0;
|
||||
ecc_key *ecc;
|
||||
const struct dropbear_ecc_curve *curve = NULL;
|
||||
|
||||
// See SEC1 v2, Appendix C.4
|
||||
// OpenSSL (so OpenSSH) seems to include the optional parts.
|
||||
|
||||
// privateKey OCTET STRING,
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
&id, &len, &flags);
|
||||
p += ret;
|
||||
// id==4 for octet string
|
||||
if (ret < 0 || id != 4 ||
|
||||
key->keyblob+key->keyblob_len-p < len) {
|
||||
errmsg = "ASN.1 decoding failure";
|
||||
goto error;
|
||||
}
|
||||
private_key_bytes = p;
|
||||
private_key_len = len;
|
||||
p += len;
|
||||
|
||||
// parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL,
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
&id, &len, &flags);
|
||||
p += ret;
|
||||
// id==0
|
||||
if (ret < 0 || id != 0) {
|
||||
errmsg = "ASN.1 decoding failure";
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
&id, &len, &flags);
|
||||
p += ret;
|
||||
// id==6 for object
|
||||
if (ret < 0 || id != 6 ||
|
||||
key->keyblob+key->keyblob_len-p < len) {
|
||||
errmsg = "ASN.1 decoding failure";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (len == sizeof(OID_SEC256R1_BLOB)
|
||||
&& memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
|
||||
curve = &ecc_curve_nistp256;
|
||||
} else if (len == sizeof(OID_SEC384R1_BLOB)
|
||||
&& memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
|
||||
curve = &ecc_curve_nistp384;
|
||||
} else if (len == sizeof(OID_SEC521R1_BLOB)
|
||||
&& memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
|
||||
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
|
||||
curve = &ecc_curve_nistp521;
|
||||
} else {
|
||||
errmsg = "Unknown ECC key type";
|
||||
goto error;
|
||||
}
|
||||
p += len;
|
||||
|
||||
// publicKey [1] BIT STRING OPTIONAL
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
&id, &len, &flags);
|
||||
p += ret;
|
||||
// id==1
|
||||
if (ret < 0 || id != 1) {
|
||||
errmsg = "ASN.1 decoding failure";
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
&id, &len, &flags);
|
||||
p += ret;
|
||||
// id==3 for bit string
|
||||
if (ret < 0 || id != 3 ||
|
||||
key->keyblob+key->keyblob_len-p < len) {
|
||||
errmsg = "ASN.1 decoding failure";
|
||||
goto error;
|
||||
}
|
||||
public_key_bytes = p+1;
|
||||
public_key_len = len-1;
|
||||
p += len;
|
||||
|
||||
buf_putbytes(blobbuf, public_key_bytes, public_key_len);
|
||||
ecc = buf_get_ecc_raw_pubkey(blobbuf, curve);
|
||||
if (!ecc) {
|
||||
errmsg = "Error parsing ECC key";
|
||||
goto error;
|
||||
}
|
||||
m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL);
|
||||
if (mp_read_unsigned_bin(ecc->k, private_key_bytes, private_key_len)
|
||||
!= MP_OKAY) {
|
||||
errmsg = "Error parsing ECC key";
|
||||
goto error;
|
||||
}
|
||||
|
||||
retkey->ecckey = ecc;
|
||||
}
|
||||
#endif // DROPBEAR_ECDSA
|
||||
|
||||
/*
|
||||
* Now put together the actual key. Simplest way to do this is
|
||||
* to assemble our own key blobs and feed them to the createkey
|
||||
* functions; this is a bit faffy but it does mean we get all
|
||||
* the sanity checks for free.
|
||||
*/
|
||||
retkey = new_sign_key();
|
||||
if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
|
||||
buf_setpos(blobbuf, 0);
|
||||
type = DROPBEAR_SIGNKEY_ANY;
|
||||
if (buf_get_priv_key(blobbuf, retkey, &type)
|
||||
@ -673,6 +794,7 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
|
||||
retkey = NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
errmsg = NULL; /* no error */
|
||||
retval = retkey;
|
||||
|
Loading…
Reference in New Issue
Block a user