Mercurial > dropbear
diff signkey_ossh.c @ 1908:eadd023fde4d
Support RSA OpenSSH new format in dropbearconvert
Added support for reading and writing. PEM writing support
has been removed.
OpenSSH file format routines have been moved to signkey_ossh.c
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 29 Mar 2022 22:27:55 +0800 |
parents | |
children | ced53051e200 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signkey_ossh.c Tue Mar 29 22:27:55 2022 +0800 @@ -0,0 +1,125 @@ +#include "includes.h" +#include "dbutil.h" +#include "ssh.h" +#include "signkey_ossh.h" +#include "bignum.h" +#include "ecdsa.h" +#include "sk-ecdsa.h" +#include "sk-ed25519.h" +#include "rsa.h" +#include "dss.h" +#include "ed25519.h" + +#if DROPBEAR_RSA +/* OpenSSH raw private RSA format is +string "ssh-rsa" +mpint n +mpint e +mpint d +mpint iqmp (q^-1) mod p +mpint p +mpint q +*/ + +void buf_put_rsa_priv_ossh(buffer *buf, const sign_key *akey) { + const dropbear_rsa_key *key = akey->rsakey; + mp_int iqmp; + + dropbear_assert(key != NULL); + if (!(key->p && key->q)) { + dropbear_exit("Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n"); + } + + m_mp_init(&iqmp); + /* iqmp = (q^-1) mod p */ + if (mp_invmod(key->q, key->p, &iqmp) != MP_OKAY) { + dropbear_exit("Bignum error for iqmp\n"); + } + buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN); + buf_putmpint(buf, key->n); + buf_putmpint(buf, key->e); + buf_putmpint(buf, key->d); + buf_putmpint(buf, &iqmp); + buf_putmpint(buf, key->p); + buf_putmpint(buf, key->q); + mp_clear(&iqmp); +} + +int buf_get_rsa_priv_ossh(buffer *buf, sign_key *akey) { + int ret = DROPBEAR_FAILURE; + dropbear_rsa_key *key = NULL; + mp_int iqmp; + + rsa_key_free(akey->rsakey); + akey->rsakey = m_malloc(sizeof(*akey->rsakey)); + key = akey->rsakey; + m_mp_alloc_init_multi(&key->e, &key->n, &key->d, &key->p, &key->q, NULL); + + buf_eatstring(buf); + m_mp_init(&iqmp); + if (buf_getmpint(buf, key->n) == DROPBEAR_SUCCESS + && buf_getmpint(buf, key->e) == DROPBEAR_SUCCESS + && buf_getmpint(buf, key->d) == DROPBEAR_SUCCESS + && buf_getmpint(buf, &iqmp) == DROPBEAR_SUCCESS + && buf_getmpint(buf, key->p) == DROPBEAR_SUCCESS + && buf_getmpint(buf, key->q) == DROPBEAR_SUCCESS) { + ret = DROPBEAR_SUCCESS; + } + mp_clear(&iqmp); + return ret; +} + +#endif /* DROPBEAR_RSA */ + +#if DROPBEAR_ED25519 +/* OpenSSH raw private ed25519 format is +string "ssh-ed25519" +uint32 32 +byte[32] pubkey +uint32 64 +byte[32] privkey +byte[32] pubkey +*/ + +void buf_put_ed25519_priv_ossh(buffer *buf, const sign_key *akey) { + const dropbear_ed25519_key *key = akey->ed25519key; + dropbear_assert(key != NULL); + buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN); + buf_putint(buf, CURVE25519_LEN); + buf_putbytes(buf, key->pub, CURVE25519_LEN); + buf_putint(buf, CURVE25519_LEN*2); + buf_putbytes(buf, key->priv, CURVE25519_LEN); + buf_putbytes(buf, key->pub, CURVE25519_LEN); +} + +int buf_get_ed25519_priv_ossh(buffer *buf, sign_key *akey) { + dropbear_ed25519_key *key = NULL; + uint32_t len; + + ed25519_key_free(akey->ed25519key); + akey->ed25519key = m_malloc(sizeof(*akey->ed25519key)); + key = akey->ed25519key; + + /* Parse past the first string and pubkey */ + if (buf_get_ed25519_pub_key(buf, key, DROPBEAR_SIGNKEY_ED25519) + == DROPBEAR_FAILURE) { + dropbear_log(LOG_ERR, "Error parsing ed25519 key, pubkey"); + return DROPBEAR_FAILURE; + } + len = buf_getint(buf); + if (len != 2*CURVE25519_LEN) { + dropbear_log(LOG_ERR, "Error parsing ed25519 key, bad length"); + return DROPBEAR_FAILURE; + } + memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN); + buf_incrpos(buf, CURVE25519_LEN); + + /* Sanity check */ + if (memcmp(buf_getptr(buf, CURVE25519_LEN), key->pub, + CURVE25519_LEN) != 0) { + dropbear_log(LOG_ERR, "Error parsing ed25519 key, mismatch pubkey"); + return DROPBEAR_FAILURE; + } + return DROPBEAR_SUCCESS; +} +#endif /* DROPBEAR_ED255219 */