mirror of
https://github.com/clearml/dropbear
synced 2025-06-23 02:06:55 +00:00
Add ecdsa OpenSSH format for dropbearconvert
This commit is contained in:
parent
bcbae1f4ba
commit
81e3977360
126
keyimport.c
126
keyimport.c
@ -39,6 +39,7 @@
|
||||
#include "rsa.h"
|
||||
#include "dss.h"
|
||||
#include "ed25519.h"
|
||||
#include "ecdsa.h"
|
||||
#include "signkey_ossh.h"
|
||||
|
||||
static const unsigned char OSSH_PKEY_BLOB[] =
|
||||
@ -629,6 +630,19 @@ static sign_key *openssh_read(const char *filename, const char * UNUSED(passphra
|
||||
goto ossh_error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
if (buf_get_ecdsa_priv_ossh(blobbuf, retkey)
|
||||
== DROPBEAR_SUCCESS) {
|
||||
errmsg = NULL;
|
||||
retval = retkey;
|
||||
goto error;
|
||||
} else {
|
||||
errmsg = "Error parsing OpenSSH ed25519 key";
|
||||
goto ossh_error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -911,12 +925,8 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
int ret = 0;
|
||||
FILE *fp;
|
||||
|
||||
if (
|
||||
#if DROPBEAR_DSS
|
||||
key->type == DROPBEAR_SIGNKEY_DSS ||
|
||||
#endif
|
||||
0)
|
||||
{
|
||||
if (key->type == DROPBEAR_SIGNKEY_DSS) {
|
||||
/*
|
||||
* Fetch the key blobs.
|
||||
*/
|
||||
@ -1001,103 +1011,7 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
pos += numbers[i].bytes;
|
||||
}
|
||||
} /* end DSS handling */
|
||||
|
||||
#if 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 = (ecc_key**)signkey_key_ptr(key, key->type);
|
||||
const long curve_size = (*eck)->dp->size;
|
||||
int curve_oid_len = 0;
|
||||
const void* curve_oid = NULL;
|
||||
unsigned long pubkey_size = 2*curve_size+1;
|
||||
int k_size;
|
||||
int err = 0;
|
||||
size_t written;
|
||||
|
||||
/* 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 */
|
||||
k_size = mp_ubin_size((*eck)->k);
|
||||
dropbear_assert(k_size <= curve_size);
|
||||
buf_incrwritepos(seq_buf,
|
||||
ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, k_size, 0));
|
||||
if (mp_to_ubin((*eck)->k, buf_getwriteptr(seq_buf, k_size), k_size, &written) != MP_OKAY) {
|
||||
dropbear_exit("ECC error");
|
||||
}
|
||||
buf_incrwritepos(seq_buf, written);
|
||||
|
||||
/* 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,
|
||||
(pubkey_size +1 < 128 ? 2 : 3 ) +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);
|
||||
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(1000);
|
||||
|
||||
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
|
||||
#endif /* DROPBEAR_DSS */
|
||||
|
||||
if (0
|
||||
#if DROPBEAR_RSA
|
||||
@ -1105,6 +1019,9 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
|| key->type == DROPBEAR_SIGNKEY_ED25519
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
|| signkey_is_ecdsa(key->type)
|
||||
#endif
|
||||
) {
|
||||
buffer *buf = buf_new(3200);
|
||||
@ -1122,6 +1039,11 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
buf_put_ed25519_priv_ossh(keyblob, key);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(key->type)) {
|
||||
buf_put_ecdsa_priv_ossh(keyblob, key);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* header */
|
||||
buf_putbytes(buf, OSSH_PKEY_BLOB, OSSH_PKEY_BLOBLEN);
|
||||
|
@ -123,3 +123,39 @@ int buf_get_ed25519_priv_ossh(buffer *buf, sign_key *akey) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
#endif /* DROPBEAR_ED255219 */
|
||||
|
||||
#if DROPBEAR_ECDSA
|
||||
/* OpenSSH raw private ecdsa format is the same as Dropbear's.
|
||||
# First part is the same as the SSH wire pubkey format
|
||||
string "ecdsa-sha2-[identifier]"
|
||||
string [identifier]
|
||||
string Q
|
||||
# With private part appended
|
||||
mpint d
|
||||
*/
|
||||
|
||||
void buf_put_ecdsa_priv_ossh(buffer *buf, const sign_key *key) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr((sign_key*)key, key->type);
|
||||
if (eck && *eck) {
|
||||
buf_put_ecdsa_priv_key(buf, *eck);
|
||||
return;
|
||||
}
|
||||
dropbear_exit("ecdsa key is not set");
|
||||
}
|
||||
|
||||
int buf_get_ecdsa_priv_ossh(buffer *buf, sign_key *key) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, key->type);
|
||||
if (eck) {
|
||||
if (*eck) {
|
||||
ecc_free(*eck);
|
||||
m_free(*eck);
|
||||
*eck = NULL;
|
||||
}
|
||||
*eck = buf_get_ecdsa_priv_key(buf);
|
||||
if (*eck) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
}
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
|
@ -9,5 +9,7 @@ void buf_put_rsa_priv_ossh(buffer *buf, const sign_key *akey);
|
||||
int buf_get_rsa_priv_ossh(buffer *buf, sign_key *akey);
|
||||
void buf_put_ed25519_priv_ossh(buffer *buf, const sign_key *akey);
|
||||
int buf_get_ed25519_priv_ossh(buffer *buf, sign_key *akey);
|
||||
void buf_put_ecdsa_priv_ossh(buffer *buf, const sign_key *akey);
|
||||
int buf_get_ecdsa_priv_ossh(buffer *buf, sign_key *akey);
|
||||
|
||||
#endif /* DROPBEAR_SIGNKEY_OSSH_H_ */
|
||||
|
@ -27,10 +27,7 @@ def test_from_openssh(request, tmp_path, keytype, keyformat):
|
||||
kt, keybits = parse_keytype(keytype)
|
||||
|
||||
if kt == 'dss' and keyformat is None:
|
||||
pytest.xfail("dss doesn't support openssh format")
|
||||
|
||||
if kt == 'ecdsa' and keyformat is None:
|
||||
pytest.skip("ecdsa doesn't support openssh format yet")
|
||||
pytest.skip("dss doesn't support openssh format")
|
||||
|
||||
os_kt = kt
|
||||
if os_kt == 'dss':
|
||||
|
Loading…
Reference in New Issue
Block a user