hackish ECC import code from OpenSSH

--HG--
branch : ecc
This commit is contained in:
Matt Johnston 2013-05-23 22:18:33 +08:00
parent d9e790e7dc
commit 6b0d47b364
2 changed files with 140 additions and 15 deletions

View File

@ -62,6 +62,9 @@ int main(int argc, char ** argv) {
const char* infile; const char* infile;
const char* outfile; const char* outfile;
crypto_init();
seedrandom();
#ifdef DEBUG_TRACE #ifdef DEBUG_TRACE
/* It's hard for it to get in the way _too_ much */ /* It's hard for it to get in the way _too_ much */
debug_trace = 1; debug_trace = 1;

View File

@ -36,6 +36,11 @@
#include "bignum.h" #include "bignum.h"
#include "buffer.h" #include "buffer.h"
#include "dbutil.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 { \ #define PUT_32BIT(cp, value) do { \
(cp)[3] = (unsigned char)(value); \ (cp)[3] = (unsigned char)(value); \
@ -158,7 +163,7 @@ static int dropbear_write(const char*filename, sign_key * key) {
#endif #endif
buf = buf_new(MAX_PRIVKEY_SIZE); 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"); fp = fopen(filename, "w");
if (!fp) { if (!fp) {
@ -523,6 +528,8 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
sign_key *retkey; sign_key *retkey;
buffer * blobbuf = NULL; buffer * blobbuf = NULL;
retkey = new_sign_key();
key = load_openssh_key(filename); key = load_openssh_key(filename);
if (!key) if (!key)
@ -599,6 +606,8 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
num_integers = 9; num_integers = 9;
else if (key->type == OSSH_DSA) else if (key->type == OSSH_DSA)
num_integers = 6; num_integers = 6;
else if (key->type == OSSH_EC)
num_integers = 1;
/* /*
* Space to create key blob in. * Space to create key blob in.
@ -622,11 +631,18 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
} }
if (i == 0) { if (i == 0) {
/* /* First integer is a version indicator */
* The first integer should be zero always (I think int expected;
* this is some sort of version indication). switch (key->type) {
*/ case OSSH_RSA:
if (len != 1 || p[0] != 0) { case OSSH_DSA:
expected = 0;
break;
case OSSH_EC:
expected = 1;
break;
}
if (len != 1 || p[0] != expected) {
errmsg = "Version number mismatch"; errmsg = "Version number mismatch";
goto error; goto error;
} }
@ -657,21 +673,127 @@ static sign_key *openssh_read(const char *filename, char *passphrase)
p += len; 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 * Now put together the actual key. Simplest way to do this is
* to assemble our own key blobs and feed them to the createkey * 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 * functions; this is a bit faffy but it does mean we get all
* the sanity checks for free. * the sanity checks for free.
*/ */
retkey = new_sign_key(); if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
buf_setpos(blobbuf, 0); buf_setpos(blobbuf, 0);
type = DROPBEAR_SIGNKEY_ANY; type = DROPBEAR_SIGNKEY_ANY;
if (buf_get_priv_key(blobbuf, retkey, &type) if (buf_get_priv_key(blobbuf, retkey, &type)
!= DROPBEAR_SUCCESS) { != DROPBEAR_SUCCESS) {
errmsg = "unable to create key structure"; errmsg = "unable to create key structure";
sign_key_free(retkey); sign_key_free(retkey);
retkey = NULL; retkey = NULL;
goto error; goto error;
}
} }
errmsg = NULL; /* no error */ errmsg = NULL; /* no error */