summaryrefslogtreecommitdiff
path: root/signkey_ossh.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2022-03-29 22:27:55 +0800
committerMatt Johnston <matt@ucc.asn.au>2022-03-29 22:27:55 +0800
commitfc8b735fa6d36b1fb2b97b9e83a483fc2b675185 (patch)
tree6c4bea24de6a548c1bc4281ae8168ba1d0ab5aec /signkey_ossh.c
parentadcd96c4a5b7faa7c294101b00562e6d5bd97b4b (diff)
downloaddropbear-fc8b735fa6d36b1fb2b97b9e83a483fc2b675185.tar.gz
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
Diffstat (limited to 'signkey_ossh.c')
-rw-r--r--signkey_ossh.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/signkey_ossh.c b/signkey_ossh.c
new file mode 100644
index 0000000..5e787a4
--- /dev/null
+++ b/signkey_ossh.c
@@ -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 */