mirror of
https://github.com/clearml/dropbear
synced 2025-03-09 21:41:07 +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* 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;
|
||||||
|
152
keyimport.c
152
keyimport.c
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user