summaryrefslogtreecommitdiffhomepage
path: root/keyimport.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyimport.c')
-rw-r--r--keyimport.c1200
1 files changed, 601 insertions, 599 deletions
diff --git a/keyimport.c b/keyimport.c
index 1f9952d..d64a6f7 100644
--- a/keyimport.c
+++ b/keyimport.c
@@ -36,9 +36,11 @@
#include "dbutil.h"
#include "ecc.h"
+#if DROPBEAR_ECDSA
static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
+#endif
#define PUT_32BIT(cp, value) do { \
(cp)[3] = (unsigned char)(value); \
@@ -71,11 +73,11 @@ static int sshcom_write(const char *filename, struct ssh2_userkey *key,
int import_encrypted(const char* filename, int filetype) {
- if (filetype == KEYFILE_OPENSSH) {
- return openssh_encrypted(filename);
+ if (filetype == KEYFILE_OPENSSH) {
+ return openssh_encrypted(filename);
#if 0
- } else if (filetype == KEYFILE_SSHCOM) {
- return sshcom_encrypted(filename, NULL);
+ } else if (filetype == KEYFILE_SSHCOM) {
+ return sshcom_encrypted(filename, NULL);
#endif
}
return 0;
@@ -83,101 +85,101 @@ int import_encrypted(const char* filename, int filetype) {
sign_key *import_read(const char *filename, char *passphrase, int filetype) {
- if (filetype == KEYFILE_OPENSSH) {
- return openssh_read(filename, passphrase);
- } else if (filetype == KEYFILE_DROPBEAR) {
- return dropbear_read(filename);
+ if (filetype == KEYFILE_OPENSSH) {
+ return openssh_read(filename, passphrase);
+ } else if (filetype == KEYFILE_DROPBEAR) {
+ return dropbear_read(filename);
#if 0
- } else if (filetype == KEYFILE_SSHCOM) {
- return sshcom_read(filename, passphrase);
+ } else if (filetype == KEYFILE_SSHCOM) {
+ return sshcom_read(filename, passphrase);
#endif
- }
+ }
return NULL;
}
int import_write(const char *filename, sign_key *key, char *passphrase,
- int filetype) {
+ int filetype) {
- if (filetype == KEYFILE_OPENSSH) {
- return openssh_write(filename, key, passphrase);
- } else if (filetype == KEYFILE_DROPBEAR) {
- return dropbear_write(filename, key);
+ if (filetype == KEYFILE_OPENSSH) {
+ return openssh_write(filename, key, passphrase);
+ } else if (filetype == KEYFILE_DROPBEAR) {
+ return dropbear_write(filename, key);
#if 0
- } else if (filetype == KEYFILE_SSHCOM) {
- return sshcom_write(filename, key, passphrase);
+ } else if (filetype == KEYFILE_SSHCOM) {
+ return sshcom_write(filename, key, passphrase);
#endif
- }
+ }
return 0;
}
static sign_key *dropbear_read(const char* filename) {
- buffer * buf = NULL;
- sign_key *ret = NULL;
- enum signkey_type type;
+ buffer * buf = NULL;
+ sign_key *ret = NULL;
+ enum signkey_type type;
- buf = buf_new(MAX_PRIVKEY_SIZE);
- if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
- goto error;
- }
+ buf = buf_new(MAX_PRIVKEY_SIZE);
+ if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) {
+ goto error;
+ }
- buf_setpos(buf, 0);
- ret = new_sign_key();
+ buf_setpos(buf, 0);
+ ret = new_sign_key();
- type = DROPBEAR_SIGNKEY_ANY;
- if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){
- goto error;
- }
- buf_free(buf);
+ type = DROPBEAR_SIGNKEY_ANY;
+ if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){
+ goto error;
+ }
+ buf_free(buf);
- ret->type = type;
+ ret->type = type;
- return ret;
+ return ret;
error:
- if (buf) {
- buf_free(buf);
- }
- if (ret) {
- sign_key_free(ret);
- }
- return NULL;
+ if (buf) {
+ buf_free(buf);
+ }
+ if (ret) {
+ sign_key_free(ret);
+ }
+ return NULL;
}
/* returns 0 on fail, 1 on success */
static int dropbear_write(const char*filename, sign_key * key) {
- buffer * buf;
- FILE*fp;
- int len;
- int ret;
+ buffer * buf;
+ FILE*fp;
+ int len;
+ int ret;
- buf = buf_new(MAX_PRIVKEY_SIZE);
- buf_put_priv_key(buf, key, key->type);
+ buf = buf_new(MAX_PRIVKEY_SIZE);
+ buf_put_priv_key(buf, key, key->type);
- fp = fopen(filename, "w");
- if (!fp) {
- ret = 0;
- goto out;
- }
+ fp = fopen(filename, "w");
+ if (!fp) {
+ ret = 0;
+ goto out;
+ }
- buf_setpos(buf, 0);
- do {
- len = fwrite(buf_getptr(buf, buf->len - buf->pos),
- 1, buf->len - buf->pos, fp);
- buf_incrpos(buf, len);
- } while (len > 0 && buf->len != buf->pos);
+ buf_setpos(buf, 0);
+ do {
+ len = fwrite(buf_getptr(buf, buf->len - buf->pos),
+ 1, buf->len - buf->pos, fp);
+ buf_incrpos(buf, len);
+ } while (len > 0 && buf->len != buf->pos);
- fclose(fp);
+ fclose(fp);
- if (buf->pos != buf->len) {
- ret = 0;
- } else {
- ret = 1;
- }
+ if (buf->pos != buf->len) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
out:
- buf_free(buf);
- return ret;
+ buf_free(buf);
+ return ret;
}
@@ -185,7 +187,7 @@ out:
* Helper routines. (The base64 ones are defined in sshpubk.c.)
*/
-#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
+#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \
((c) >= 'a' && (c) <= 'z') || \
((c) >= '0' && (c) <= '9') || \
(c) == '+' || (c) == '/' || (c) == '=' \
@@ -193,24 +195,24 @@ out:
/* cpl has to be less than 100 */
static void base64_encode_fp(FILE * fp, unsigned char *data,
- int datalen, int cpl)
+ int datalen, int cpl)
{
- unsigned char out[100];
- int n;
- unsigned long outlen;
- int rawcpl;
- rawcpl = cpl * 3 / 4;
- dropbear_assert((unsigned int)cpl < sizeof(out));
-
- while (datalen > 0) {
- n = (datalen < rawcpl ? datalen : rawcpl);
- outlen = sizeof(out);
- base64_encode(data, n, out, &outlen);
- data += n;
- datalen -= n;
- fwrite(out, 1, outlen, fp);
- fputc('\n', fp);
- }
+ unsigned char out[100];
+ int n;
+ unsigned long outlen;
+ int rawcpl;
+ rawcpl = cpl * 3 / 4;
+ dropbear_assert((unsigned int)cpl < sizeof(out));
+
+ while (datalen > 0) {
+ n = (datalen < rawcpl ? datalen : rawcpl);
+ outlen = sizeof(out);
+ base64_encode(data, n, out, &outlen);
+ data += n;
+ datalen -= n;
+ fwrite(out, 1, outlen, fp);
+ fputc('\n', fp);
+ }
}
/*
* Read an ASN.1/BER identifier and length pair.
@@ -222,14 +224,14 @@ static void base64_encode_fp(FILE * fp, unsigned char *data,
*/
/* ASN.1 tag classes. */
-#define ASN1_CLASS_UNIVERSAL (0 << 6)
-#define ASN1_CLASS_APPLICATION (1 << 6)
+#define ASN1_CLASS_UNIVERSAL (0 << 6)
+#define ASN1_CLASS_APPLICATION (1 << 6)
#define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6)
-#define ASN1_CLASS_PRIVATE (3 << 6)
-#define ASN1_CLASS_MASK (3 << 6)
+#define ASN1_CLASS_PRIVATE (3 << 6)
+#define ASN1_CLASS_MASK (3 << 6)
/* Primitive versus constructed bit. */
-#define ASN1_CONSTRUCTED (1 << 5)
+#define ASN1_CONSTRUCTED (1 << 5)
static int ber_read_id_len(void *source, int sourcelen,
int *id, int *length, int *flags)
@@ -309,7 +311,7 @@ static int ber_write_id_len(void *dest, int id, int length, int flags)
len++;
if (d) *d++ = 0x1F | flags;
for (n = 1; (id >> (7*n)) > 0; n++)
- continue; /* count the bytes */
+ continue; /* count the bytes */
while (n--) {
len++;
if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F);
@@ -330,7 +332,7 @@ static int ber_write_id_len(void *dest, int id, int length, int flags)
* encode the actual length.
*/
for (n = 1; (length >> (8*n)) > 0; n++)
- continue; /* count the bytes */
+ continue; /* count the bytes */
len++;
if (d) *d++ = 0x80 | n;
while (n--) {
@@ -356,29 +358,29 @@ struct openssh_key {
int encrypted;
char iv[32];
unsigned char *keyblob;
- unsigned int keyblob_len, keyblob_size;
+ unsigned int keyblob_len, keyblob_size;
};
static struct openssh_key *load_openssh_key(const char *filename)
{
struct openssh_key *ret;
- FILE *fp = NULL;
+ FILE *fp = NULL;
char buffer[256];
- char *errmsg = NULL, *p = NULL;
+ char *errmsg = NULL, *p = NULL;
int headers_done;
- unsigned long len, outlen;
+ unsigned long len, outlen;
- ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key));
+ ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key));
ret->keyblob = NULL;
ret->keyblob_len = ret->keyblob_size = 0;
ret->encrypted = 0;
memset(ret->iv, 0, sizeof(ret->iv));
- if (strlen(filename) == 1 && filename[0] == '-') {
- fp = stdin;
- } else {
- fp = fopen(filename, "r");
- }
+ if (strlen(filename) == 1 && filename[0] == '-') {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ }
if (!fp) {
errmsg = "Unable to open key file";
goto error;
@@ -393,8 +395,8 @@ static struct openssh_key *load_openssh_key(const char *filename)
ret->type = OSSH_RSA;
else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n"))
ret->type = OSSH_DSA;
- else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n"))
- ret->type = OSSH_EC;
+ else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n"))
+ ret->type = OSSH_EC;
else {
errmsg = "Unrecognised key type";
goto error;
@@ -408,7 +410,7 @@ static struct openssh_key *load_openssh_key(const char *filename)
}
if (0 == strncmp(buffer, "-----END ", 9) &&
0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n"))
- break; /* done */
+ break; /* done */
if ((p = strchr(buffer, ':')) != NULL) {
if (headers_done) {
errmsg = "Header found in body of key data";
@@ -445,22 +447,22 @@ static struct openssh_key *load_openssh_key(const char *filename)
}
} else {
headers_done = 1;
- len = strlen(buffer);
- outlen = len*4/3;
- if (ret->keyblob_len + outlen > ret->keyblob_size) {
- ret->keyblob_size = ret->keyblob_len + outlen + 256;
- ret->keyblob = (unsigned char*)m_realloc(ret->keyblob,
- ret->keyblob_size);
- }
- outlen = ret->keyblob_size - ret->keyblob_len;
- if (base64_decode((const unsigned char *)buffer, len,
- ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){
- errmsg = "Error decoding base64";
- goto error;
- }
- ret->keyblob_len += outlen;
- }
+ len = strlen(buffer);
+ outlen = len*4/3;
+ if (ret->keyblob_len + outlen > ret->keyblob_size) {
+ ret->keyblob_size = ret->keyblob_len + outlen + 256;
+ ret->keyblob = (unsigned char*)m_realloc(ret->keyblob,
+ ret->keyblob_size);
+ }
+ outlen = ret->keyblob_size - ret->keyblob_len;
+ if (base64_decode((const unsigned char *)buffer, len,
+ ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){
+ errmsg = "Error decoding base64";
+ goto error;
+ }
+ ret->keyblob_len += outlen;
}
+ }
if (ret->keyblob_len == 0 || !ret->keyblob) {
errmsg = "Key body not present";
@@ -509,31 +511,31 @@ static int openssh_encrypted(const char *filename)
static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
{
- struct openssh_key *key;
+ struct openssh_key *key;
unsigned char *p;
int ret, id, len, flags;
- int i, num_integers = 0;
- sign_key *retval = NULL;
+ int i, num_integers = 0;
+ sign_key *retval = NULL;
char *errmsg;
- unsigned char *modptr = NULL;
- int modlen = -9999;
- enum signkey_type type;
+ unsigned char *modptr = NULL;
+ int modlen = -9999;
+ enum signkey_type type;
- sign_key *retkey;
- buffer * blobbuf = NULL;
+ sign_key *retkey;
+ buffer * blobbuf = NULL;
- retkey = new_sign_key();
+ retkey = new_sign_key();
- key = load_openssh_key(filename);
+ key = load_openssh_key(filename);
if (!key)
return NULL;
if (key->encrypted) {
- errmsg = "encrypted keys not supported currently";
- goto error;
+ errmsg = "encrypted keys not supported currently";
+ goto error;
#if 0
- /* matt TODO */
+ /* matt TODO */
/*
* Derive encryption key from passphrase and iv/salt:
*
@@ -578,11 +580,11 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
* depends on the key type:
*
* - For RSA, we expect the integers to be 0, n, e, d, p, q,
- * dmp1, dmq1, iqmp in that order. (The last three are d mod
- * (p-1), d mod (q-1), inverse of q mod p respectively.)
+ * dmp1, dmq1, iqmp in that order. (The last three are d mod
+ * (p-1), d mod (q-1), inverse of q mod p respectively.)
*
* - For DSA, we expect them to be 0, p, q, g, y, x in that
- * order.
+ * order.
*/
p = key->keyblob;
@@ -601,25 +603,25 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
num_integers = 9;
else if (key->type == OSSH_DSA)
num_integers = 6;
- else if (key->type == OSSH_EC)
- num_integers = 1;
+ else if (key->type == OSSH_EC)
+ num_integers = 1;
/*
* Space to create key blob in.
*/
- blobbuf = buf_new(3000);
+ blobbuf = buf_new(3000);
-#ifdef DROPBEAR_DSS
- if (key->type == OSSH_DSA) {
- buf_putstring(blobbuf, "ssh-dss", 7);
- retkey->type = DROPBEAR_SIGNKEY_DSS;
- }
+#if DROPBEAR_DSS
+ if (key->type == OSSH_DSA) {
+ buf_putstring(blobbuf, "ssh-dss", 7);
+ retkey->type = DROPBEAR_SIGNKEY_DSS;
+ }
#endif
-#ifdef DROPBEAR_RSA
- if (key->type == OSSH_RSA) {
- buf_putstring(blobbuf, "ssh-rsa", 7);
- retkey->type = DROPBEAR_SIGNKEY_RSA;
- }
+#if DROPBEAR_RSA
+ if (key->type == OSSH_RSA) {
+ buf_putstring(blobbuf, "ssh-rsa", 7);
+ retkey->type = DROPBEAR_SIGNKEY_RSA;
+ }
#endif
for (i = 0; i < num_integers; i++) {
@@ -633,160 +635,160 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
}
if (i == 0) {
- /* First integer is a version indicator */
- int expected = -1;
- switch (key->type) {
- case OSSH_RSA:
- case OSSH_DSA:
- expected = 0;
- break;
- case OSSH_EC:
- expected = 1;
- break;
- }
- if (len != 1 || p[0] != expected) {
+ /* First integer is a version indicator */
+ int expected = -1;
+ switch (key->type) {
+ case OSSH_RSA:
+ case OSSH_DSA:
+ expected = 0;
+ break;
+ case OSSH_EC:
+ expected = 1;
+ break;
+ }
+ if (len != 1 || p[0] != expected) {
errmsg = "Version number mismatch";
goto error;
}
} else if (key->type == OSSH_RSA) {
/*
- * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp
- * but we want e, n, d, p, q
+ * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp
+ * but we want e, n, d, p, q
*/
if (i == 1) {
/* Save the details for after we deal with number 2. */
- modptr = p;
+ modptr = p;
modlen = len;
- } else if (i >= 2 && i <= 5) {
- buf_putstring(blobbuf, (const char*)p, len);
+ } else if (i >= 2 && i <= 5) {
+ buf_putstring(blobbuf, (const char*)p, len);
if (i == 2) {
- buf_putstring(blobbuf, (const char*)modptr, modlen);
+ buf_putstring(blobbuf, (const char*)modptr, modlen);
}
}
} else if (key->type == OSSH_DSA) {
/*
- * OpenSSH key order is p, q, g, y, x,
- * we want the same.
+ * OpenSSH key order is p, q, g, y, x,
+ * we want the same.
*/
- buf_putstring(blobbuf, (const char*)p, len);
+ buf_putstring(blobbuf, (const char*)p, len);
}
/* Skip past the number. */
p += len;
}
-#ifdef DROPBEAR_ECDSA
- if (key->type == OSSH_EC) {
- 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 = NULL;
- const struct dropbear_ecc_curve *curve = NULL;
+#if DROPBEAR_ECDSA
+ if (key->type == OSSH_EC) {
+ 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 = NULL;
+ const struct dropbear_ecc_curve *curve = NULL;
- /* See SEC1 v2, Appendix C.4 */
- /* OpenSSL (so OpenSSH) seems to include the optional parts. */
+ /* 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 */
+ /* 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 || len < 0 ||
- 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 */
+ 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 || len < 0) {
- errmsg = "ASN.1 decoding failure";
- goto error;
- }
+ 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 */
+ 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 || len < 0 ||
- key->keyblob+key->keyblob_len-p < len) {
- errmsg = "ASN.1 decoding failure";
- goto error;
- }
+ key->keyblob+key->keyblob_len-p < len) {
+ errmsg = "ASN.1 decoding failure";
+ goto error;
+ }
- if (0) {}
-#ifdef DROPBEAR_ECC_256
- else if (len == sizeof(OID_SEC256R1_BLOB)
- && memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
- retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
- curve = &ecc_curve_nistp256;
- }
+ if (0) {}
+#if DROPBEAR_ECC_256
+ else if (len == sizeof(OID_SEC256R1_BLOB)
+ && memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
+ retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
+ curve = &ecc_curve_nistp256;
+ }
#endif
-#ifdef DROPBEAR_ECC_384
- else if (len == sizeof(OID_SEC384R1_BLOB)
- && memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
- retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
- curve = &ecc_curve_nistp384;
- }
+#if DROPBEAR_ECC_384
+ else if (len == sizeof(OID_SEC384R1_BLOB)
+ && memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
+ retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
+ curve = &ecc_curve_nistp384;
+ }
#endif
-#ifdef DROPBEAR_ECC_521
- else if (len == sizeof(OID_SEC521R1_BLOB)
- && memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
- retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
- curve = &ecc_curve_nistp521;
- }
+#if DROPBEAR_ECC_521
+ else if (len == sizeof(OID_SEC521R1_BLOB)
+ && memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
+ retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
+ curve = &ecc_curve_nistp521;
+ }
#endif
- else {
- errmsg = "Unknown ECC key type";
- goto error;
- }
- p += len;
+ 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 */
+ /* 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 || len < 0) {
- errmsg = "ASN.1 decoding failure";
- goto error;
- }
+ 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 */
+ 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 || len < 0 ||
- 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;
- }
+ 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;
- *signkey_key_ptr(retkey, retkey->type) = ecc;
+ 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;
}
+
+ *signkey_key_ptr(retkey, retkey->type) = ecc;
+ }
#endif /* DROPBEAR_ECDSA */
/*
@@ -795,19 +797,19 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
* functions; this is a bit faffy but it does mean we get all
* the sanity checks for free.
*/
- if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
- buf_setpos(blobbuf, 0);
- type = DROPBEAR_SIGNKEY_ANY;
- if (buf_get_priv_key(blobbuf, retkey, &type)
- != DROPBEAR_SUCCESS) {
- errmsg = "unable to create key structure";
- sign_key_free(retkey);
- retkey = NULL;
- goto error;
- }
+ if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
+ buf_setpos(blobbuf, 0);
+ type = DROPBEAR_SIGNKEY_ANY;
+ if (buf_get_priv_key(blobbuf, retkey, &type)
+ != DROPBEAR_SUCCESS) {
+ errmsg = "unable to create key structure";
+ sign_key_free(retkey);
+ retkey = NULL;
+ goto error;
}
+ }
- errmsg = NULL; /* no error */
+ errmsg = NULL; /* no error */
retval = retkey;
error:
@@ -828,301 +830,301 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
static int openssh_write(const char *filename, sign_key *key,
char *passphrase)
{
- buffer * keyblob = NULL;
- buffer * extrablob = NULL; /* used for calculated values to write */
- unsigned char *outblob = NULL;
- int outlen = -9999;
+ buffer * keyblob = NULL;
+ buffer * extrablob = NULL; /* used for calculated values to write */
+ unsigned char *outblob = NULL;
+ int outlen = -9999;
struct mpint_pos numbers[9];
- int nnumbers = -1, pos = 0, len = 0, seqlen, i;
- char *header = NULL, *footer = NULL;
+ int nnumbers = -1, pos = 0, len = 0, seqlen, i;
+ char *header = NULL, *footer = NULL;
char zero[1];
int ret = 0;
FILE *fp;
-#ifdef DROPBEAR_RSA
- mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
+#if DROPBEAR_RSA
+ mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
#endif
- if (
-#ifdef DROPBEAR_RSA
- key->type == DROPBEAR_SIGNKEY_RSA ||
+ if (
+#if DROPBEAR_RSA
+ key->type == DROPBEAR_SIGNKEY_RSA ||
#endif
-#ifdef DROPBEAR_DSS
- key->type == DROPBEAR_SIGNKEY_DSS ||
+#if DROPBEAR_DSS
+ key->type == DROPBEAR_SIGNKEY_DSS ||
#endif
- 0)
- {
- /*
- * Fetch the key blobs.
- */
- keyblob = buf_new(3000);
- buf_put_priv_key(keyblob, key, key->type);
-
- buf_setpos(keyblob, 0);
- /* skip the "ssh-rsa" or "ssh-dss" header */
- buf_incrpos(keyblob, buf_getint(keyblob));
-
- /*
- * Find the sequence of integers to be encoded into the OpenSSH
- * key blob, and also decide on the header line.
- */
- numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
-
- #ifdef DROPBEAR_RSA
- if (key->type == DROPBEAR_SIGNKEY_RSA) {
-
- if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
- fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
- goto error;
- }
-
- /* e */
- numbers[2].bytes = buf_getint(keyblob);
- numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
- buf_incrpos(keyblob, numbers[2].bytes);
-
- /* n */
- numbers[1].bytes = buf_getint(keyblob);
- numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
- buf_incrpos(keyblob, numbers[1].bytes);
-
- /* d */
- numbers[3].bytes = buf_getint(keyblob);
- numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
- buf_incrpos(keyblob, numbers[3].bytes);
-
- /* p */
- numbers[4].bytes = buf_getint(keyblob);
- numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
- buf_incrpos(keyblob, numbers[4].bytes);
-
- /* q */
- numbers[5].bytes = buf_getint(keyblob);
- numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
- buf_incrpos(keyblob, numbers[5].bytes);
-
- /* now calculate some extra parameters: */
- m_mp_init(&tmpval);
- m_mp_init(&dmp1);
- m_mp_init(&dmq1);
- m_mp_init(&iqmp);
-
- /* dmp1 = d mod (p-1) */
- if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) {
- fprintf(stderr, "Bignum error for p-1\n");
- goto error;
- }
- if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) {
- fprintf(stderr, "Bignum error for dmp1\n");
- goto error;
- }
-
- /* dmq1 = d mod (q-1) */
- if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) {
- fprintf(stderr, "Bignum error for q-1\n");
- goto error;
- }
- if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) {
- fprintf(stderr, "Bignum error for dmq1\n");
- goto error;
- }
-
- /* iqmp = (q^-1) mod p */
- if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) {
- fprintf(stderr, "Bignum error for iqmp\n");
- goto error;
- }
-
- extrablob = buf_new(2000);
- buf_putmpint(extrablob, &dmp1);
- buf_putmpint(extrablob, &dmq1);
- buf_putmpint(extrablob, &iqmp);
- buf_setpos(extrablob, 0);
- mp_clear(&dmp1);
- mp_clear(&dmq1);
- mp_clear(&iqmp);
- mp_clear(&tmpval);
-
- /* dmp1 */
- numbers[6].bytes = buf_getint(extrablob);
- numbers[6].start = buf_getptr(extrablob, numbers[6].bytes);
- buf_incrpos(extrablob, numbers[6].bytes);
-
- /* dmq1 */
- numbers[7].bytes = buf_getint(extrablob);
- numbers[7].start = buf_getptr(extrablob, numbers[7].bytes);
- buf_incrpos(extrablob, numbers[7].bytes);
-
- /* iqmp */
- numbers[8].bytes = buf_getint(extrablob);
- numbers[8].start = buf_getptr(extrablob, numbers[8].bytes);
- buf_incrpos(extrablob, numbers[8].bytes);
-
- nnumbers = 9;
- header = "-----BEGIN RSA PRIVATE KEY-----\n";
- footer = "-----END RSA PRIVATE KEY-----\n";
- }
- #endif /* DROPBEAR_RSA */
-
- #ifdef DROPBEAR_DSS
- if (key->type == DROPBEAR_SIGNKEY_DSS) {
+ 0)
+ {
+ /*
+ * Fetch the key blobs.
+ */
+ keyblob = buf_new(3000);
+ buf_put_priv_key(keyblob, key, key->type);
- /* p */
- numbers[1].bytes = buf_getint(keyblob);
- numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
- buf_incrpos(keyblob, numbers[1].bytes);
+ buf_setpos(keyblob, 0);
+ /* skip the "ssh-rsa" or "ssh-dss" header */
+ buf_incrpos(keyblob, buf_getint(keyblob));
- /* q */
- numbers[2].bytes = buf_getint(keyblob);
- numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
- buf_incrpos(keyblob, numbers[2].bytes);
+ /*
+ * Find the sequence of integers to be encoded into the OpenSSH
+ * key blob, and also decide on the header line.
+ */
+ numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
- /* g */
- numbers[3].bytes = buf_getint(keyblob);
- numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
- buf_incrpos(keyblob, numbers[3].bytes);
+ #ifdef DROPBEAR_RSA
+ if (key->type == DROPBEAR_SIGNKEY_RSA) {
- /* y */
- numbers[4].bytes = buf_getint(keyblob);
- numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
- buf_incrpos(keyblob, numbers[4].bytes);
+ if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
+ fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n");
+ goto error;
+ }
- /* x */
- numbers[5].bytes = buf_getint(keyblob);
- numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
- buf_incrpos(keyblob, numbers[5].bytes);
+ /* e */
+ numbers[2].bytes = buf_getint(keyblob);
+ numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
+ buf_incrpos(keyblob, numbers[2].bytes);
+
+ /* n */
+ numbers[1].bytes = buf_getint(keyblob);
+ numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
+ buf_incrpos(keyblob, numbers[1].bytes);
+
+ /* d */
+ numbers[3].bytes = buf_getint(keyblob);
+ numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
+ buf_incrpos(keyblob, numbers[3].bytes);
+
+ /* p */
+ numbers[4].bytes = buf_getint(keyblob);
+ numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
+ buf_incrpos(keyblob, numbers[4].bytes);
+
+ /* q */
+ numbers[5].bytes = buf_getint(keyblob);
+ numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
+ buf_incrpos(keyblob, numbers[5].bytes);
+
+ /* now calculate some extra parameters: */
+ m_mp_init(&tmpval);
+ m_mp_init(&dmp1);
+ m_mp_init(&dmq1);
+ m_mp_init(&iqmp);
+
+ /* dmp1 = d mod (p-1) */
+ if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) {
+ fprintf(stderr, "Bignum error for p-1\n");
+ goto error;
+ }
+ if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) {
+ fprintf(stderr, "Bignum error for dmp1\n");
+ goto error;
+ }
- nnumbers = 6;
- header = "-----BEGIN DSA PRIVATE KEY-----\n";
- footer = "-----END DSA PRIVATE KEY-----\n";
- }
- #endif /* DROPBEAR_DSS */
+ /* dmq1 = d mod (q-1) */
+ if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) {
+ fprintf(stderr, "Bignum error for q-1\n");
+ goto error;
+ }
+ if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) {
+ fprintf(stderr, "Bignum error for dmq1\n");
+ goto error;
+ }
- /*
- * Now count up the total size of the ASN.1 encoded integers,
- * so as to determine the length of the containing SEQUENCE.
- */
- len = 0;
- for (i = 0; i < nnumbers; i++) {
- len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
- len += numbers[i].bytes;
- }
- seqlen = len;
- /* Now add on the SEQUENCE header. */
- len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
- /* Round up to the cipher block size, ensuring we have at least one
- * byte of padding (see below). */
- outlen = len;
- if (passphrase)
- outlen = (outlen+8) &~ 7;
+ /* iqmp = (q^-1) mod p */
+ if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) {
+ fprintf(stderr, "Bignum error for iqmp\n");
+ goto error;
+ }
- /*
- * Now we know how big outblob needs to be. Allocate it.
- */
- outblob = (unsigned char*)m_malloc(outlen);
+ extrablob = buf_new(2000);
+ buf_putmpint(extrablob, &dmp1);
+ buf_putmpint(extrablob, &dmq1);
+ buf_putmpint(extrablob, &iqmp);
+ buf_setpos(extrablob, 0);
+ mp_clear(&dmp1);
+ mp_clear(&dmq1);
+ mp_clear(&iqmp);
+ mp_clear(&tmpval);
+
+ /* dmp1 */
+ numbers[6].bytes = buf_getint(extrablob);
+ numbers[6].start = buf_getptr(extrablob, numbers[6].bytes);
+ buf_incrpos(extrablob, numbers[6].bytes);
+
+ /* dmq1 */
+ numbers[7].bytes = buf_getint(extrablob);
+ numbers[7].start = buf_getptr(extrablob, numbers[7].bytes);
+ buf_incrpos(extrablob, numbers[7].bytes);
+
+ /* iqmp */
+ numbers[8].bytes = buf_getint(extrablob);
+ numbers[8].start = buf_getptr(extrablob, numbers[8].bytes);
+ buf_incrpos(extrablob, numbers[8].bytes);
+
+ nnumbers = 9;
+ header = "-----BEGIN RSA PRIVATE KEY-----\n";
+ footer = "-----END RSA PRIVATE KEY-----\n";
+ }
+ #endif /* DROPBEAR_RSA */
+
+ #ifdef DROPBEAR_DSS
+ if (key->type == DROPBEAR_SIGNKEY_DSS) {
+
+ /* p */
+ numbers[1].bytes = buf_getint(keyblob);
+ numbers[1].start = buf_getptr(keyblob, numbers[1].bytes);
+ buf_incrpos(keyblob, numbers[1].bytes);
+
+ /* q */
+ numbers[2].bytes = buf_getint(keyblob);
+ numbers[2].start = buf_getptr(keyblob, numbers[2].bytes);
+ buf_incrpos(keyblob, numbers[2].bytes);
+
+ /* g */
+ numbers[3].bytes = buf_getint(keyblob);
+ numbers[3].start = buf_getptr(keyblob, numbers[3].bytes);
+ buf_incrpos(keyblob, numbers[3].bytes);
+
+ /* y */
+ numbers[4].bytes = buf_getint(keyblob);
+ numbers[4].start = buf_getptr(keyblob, numbers[4].bytes);
+ buf_incrpos(keyblob, numbers[4].bytes);
+
+ /* x */
+ numbers[5].bytes = buf_getint(keyblob);
+ numbers[5].start = buf_getptr(keyblob, numbers[5].bytes);
+ buf_incrpos(keyblob, numbers[5].bytes);
+
+ nnumbers = 6;
+ header = "-----BEGIN DSA PRIVATE KEY-----\n";
+ footer = "-----END DSA PRIVATE KEY-----\n";
+ }
+ #endif /* DROPBEAR_DSS */
- /*
- * And write the data into it.
- */
- pos = 0;
- pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
- for (i = 0; i < nnumbers; i++) {
- pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
- memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
- pos += numbers[i].bytes;
- }
- } /* end RSA and DSS handling */
-
-#ifdef 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;
-
- /* 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_unsigned_bin_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));
- mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, k_size));
- buf_incrwritepos(seq_buf, k_size);
-
- /* 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");
- }
+ /*
+ * Now count up the total size of the ASN.1 encoded integers,
+ * so as to determine the length of the containing SEQUENCE.
+ */
+ len = 0;
+ for (i = 0; i < nnumbers; i++) {
+ len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);
+ len += numbers[i].bytes;
+ }
+ seqlen = len;
+ /* Now add on the SEQUENCE header. */
+ len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
+ /* Round up to the cipher block size, ensuring we have at least one
+ * byte of padding (see below). */
+ outlen = len;
+ if (passphrase)
+ outlen = (outlen+8) &~ 7;
- 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, 2+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);
+ /*
+ * Now we know how big outblob needs to be. Allocate it.
+ */
+ outblob = (unsigned char*)m_malloc(outlen);
- buf_setpos(seq_buf, 0);
-
- outblob = (unsigned char*)m_malloc(1000);
+ /*
+ * And write the data into it.
+ */
+ pos = 0;
+ pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);
+ for (i = 0; i < nnumbers; i++) {
+ pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);
+ memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
+ pos += numbers[i].bytes;
+ }
+ } /* end RSA and 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;
+
+ /* 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_unsigned_bin_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));
+ mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, k_size));
+ buf_incrwritepos(seq_buf, k_size);
+
+ /* 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");
+ }
- 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_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, 2+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_burn(seq_buf);
- buf_free(seq_buf);
- seq_buf = NULL;
+ buf_setpos(seq_buf, 0);
+
+ outblob = (unsigned char*)m_malloc(1000);
- header = "-----BEGIN EC PRIVATE KEY-----\n";
- footer = "-----END EC PRIVATE KEY-----\n";
- }
+ 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
/*
@@ -1142,7 +1144,7 @@ static int openssh_write(const char *filename, sign_key *key,
* with the same value. Those are all removed and the rest is
* returned.
*/
- dropbear_assert(pos == len);
+ dropbear_assert(pos == len);
while (pos < outlen) {
outblob[pos++] = outlen - len;
}
@@ -1151,25 +1153,25 @@ static int openssh_write(const char *filename, sign_key *key,
* Encrypt the key.
*/
if (passphrase) {
- fprintf(stderr, "Encrypted keys aren't supported currently\n");
- goto error;
+ fprintf(stderr, "Encrypted keys aren't supported currently\n");
+ goto error;
}
/*
* And save it. We'll use Unix line endings just in case it's
* subsequently transferred in binary mode.
*/
- if (strlen(filename) == 1 && filename[0] == '-') {
- fp = stdout;
- } else {
- fp = fopen(filename, "wb"); /* ensure Unix line endings */
- }
- if (!fp) {
- fprintf(stderr, "Failed opening output file\n");
+ if (strlen(filename) == 1 && filename[0] == '-') {
+ fp = stdout;
+ } else {
+ fp = fopen(filename, "wb"); /* ensure Unix line endings */
+ }
+ if (!fp) {
+ fprintf(stderr, "Failed opening output file\n");
goto error;
- }
+ }
fputs(header, fp);
- base64_encode_fp(fp, outblob, outlen, 64);
+ base64_encode_fp(fp, outblob, outlen, 64);
fputs(footer, fp);
fclose(fp);
ret = 1;
@@ -1205,10 +1207,10 @@ static int openssh_write(const char *filename, sign_key *key,
*
* So. The blob contains:
*
- * - uint32 0x3f6ff9eb (magic number)
- * - uint32 size (total blob size)
- * - string key-type (see below)
- * - string cipher-type (tells you if key is encrypted)
+ * - uint32 0x3f6ff9eb (magic number)
+ * - uint32 size (total blob size)
+ * - string key-type (see below)
+ * - string cipher-type (tells you if key is encrypted)
* - string encrypted-blob
*
* (The first size field includes the size field itself and the
@@ -1264,13 +1266,13 @@ static int openssh_write(const char *filename, sign_key *key,
* - first 16 bytes are MD5(passphrase)
* - next 16 bytes are MD5(passphrase || first 16 bytes)
* - if there were more, they'd be MD5(passphrase || first 32),
- * and so on.
+ * and so on.
*/
#define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb
struct sshcom_key {
- char comment[256]; /* allowing any length is overkill */
+ char comment[256]; /* allowing any length is overkill */
unsigned char *keyblob;
int keyblob_len, keyblob_size;
};
@@ -1291,7 +1293,7 @@ static struct sshcom_key *load_sshcom_key(const char *filename)
ret->keyblob = NULL;
ret->keyblob_len = ret->keyblob_size = 0;
- fp = fopen(filename, "r");
+ fp = fopen(filename, "r");
if (!fp) {
errmsg = "Unable to open key file";
goto error;
@@ -1309,7 +1311,7 @@ static struct sshcom_key *load_sshcom_key(const char *filename)
goto error;
}
if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n"))
- break; /* done */
+ break; /* done */
if ((p = strchr(buffer, ':')) != NULL) {
if (headers_done) {
errmsg = "Header found in body of key data";
@@ -1386,10 +1388,10 @@ static struct sshcom_key *load_sshcom_key(const char *filename)
if (ret) {
if (ret->keyblob) {
memset(ret->keyblob, 0, ret->keyblob_size);
- m_free(ret->keyblob);
+ m_free(ret->keyblob);
}
memset(ret, 0, sizeof(*ret));
- m_free(ret);
+ m_free(ret);
}
return NULL;
}
@@ -1407,7 +1409,7 @@ int sshcom_encrypted(const char *filename, char **comment)
* Check magic number.
*/
if (GET_32BIT(key->keyblob) != 0x3f6ff9eb)
- return 0; /* key is invalid */
+ return 0; /* key is invalid */
/*
* Find the cipher-type string.
@@ -1415,23 +1417,23 @@ int sshcom_encrypted(const char *filename, char **comment)
answer = 0;
pos = 8;
if (key->keyblob_len < pos+4)
- goto done; /* key is far too short */
+ goto done; /* key is far too short */
len = toint(GET_32BIT(key->keyblob + pos));
if (len < 0 || len > key->keyblob_len - pos - 4)
- goto done; /* key is far too short */
+ goto done; /* key is far too short */
pos += 4 + len; /* skip key type */
len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */
if (len < 0 || len > key->keyblob_len - pos - 4)
- goto done; /* cipher type string is incomplete */
+ goto done; /* cipher type string is incomplete */
if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
answer = 1;
done:
*comment = dupstr(key->comment);
memset(key->keyblob, 0, key->keyblob_size);
- m_free(key->keyblob);
+ m_free(key->keyblob);
memset(key, 0, sizeof(*key));
- m_free(key);
+ m_free(key);
return answer;
}
@@ -1455,7 +1457,7 @@ static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
error:
ret->start = NULL;
ret->bytes = -1;
- return len; /* ensure further calls fail as well */
+ return len; /* ensure further calls fail as well */
}
static int sshcom_put_mpint(void *target, void *data, int len)
@@ -1681,13 +1683,13 @@ sign_key *sshcom_read(const char *filename, char *passphrase)
} else
return NULL;
- dropbear_assert(privlen > 0); /* should have bombed by now if not */
+ dropbear_assert(privlen > 0); /* should have bombed by now if not */
retkey = snew(struct ssh2_userkey);
retkey->alg = alg;
retkey->data = alg->createkey(blob, publen, blob+publen, privlen);
if (!retkey->data) {
- m_free(retkey);
+ m_free(retkey);
errmsg = "unable to create key data structure";
goto error;
}
@@ -1699,12 +1701,12 @@ sign_key *sshcom_read(const char *filename, char *passphrase)
error:
if (blob) {
memset(blob, 0, blobsize);
- m_free(blob);
+ m_free(blob);
}
memset(key->keyblob, 0, key->keyblob_size);
- m_free(key->keyblob);
+ m_free(key->keyblob);
memset(key, 0, sizeof(*key));
- m_free(key);
+ m_free(key);
return ret;
}
@@ -1747,7 +1749,7 @@ int sshcom_write(const char *filename, sign_key *key,
pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);
pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);
- dropbear_assert(e.start && iqmp.start); /* can't go wrong */
+ dropbear_assert(e.start && iqmp.start); /* can't go wrong */
numbers[0] = e;
numbers[1] = d;
@@ -1771,7 +1773,7 @@ int sshcom_write(const char *filename, sign_key *key,
pos = 0;
pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);
- dropbear_assert(y.start && x.start); /* can't go wrong */
+ dropbear_assert(y.start && x.start); /* can't go wrong */
numbers[0] = p;
numbers[1] = g;
@@ -1783,7 +1785,7 @@ int sshcom_write(const char *filename, sign_key *key,
initial_zero = 1;
type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}";
} else {
- dropbear_assert(0); /* zoinks! */
+ dropbear_assert(0); /* zoinks! */
}
/*
@@ -1801,15 +1803,15 @@ int sshcom_write(const char *filename, sign_key *key,
*/
pos = 0;
PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4;
- pos += 4; /* length field, fill in later */
+ pos += 4; /* length field, fill in later */
pos += put_string(outblob+pos, type, strlen(type));
{
char *ciphertype = passphrase ? "3des-cbc" : "none";
pos += put_string(outblob+pos, ciphertype, strlen(ciphertype));
}
- lenpos = pos; /* remember this position */
- pos += 4; /* encrypted-blob size */
- pos += 4; /* encrypted-payload size */
+ lenpos = pos; /* remember this position */
+ pos += 4; /* encrypted-blob size */
+ pos += 4; /* encrypted-payload size */
if (initial_zero) {
PUT_32BIT(outblob+pos, 0);
pos += 4;
@@ -1827,13 +1829,13 @@ int sshcom_write(const char *filename, sign_key *key,
}
ciphertext = (char *)outblob+lenpos+4;
cipherlen = pos - (lenpos+4);
- dropbear_assert(!passphrase || cipherlen % 8 == 0);
+ dropbear_assert(!passphrase || cipherlen % 8 == 0);
/* Wrap up the encrypted blob string. */
PUT_32BIT(outblob+lenpos, cipherlen);
/* And finally fill in the total length field. */
PUT_32BIT(outblob+4, pos);
- dropbear_assert(pos < outlen);
+ dropbear_assert(pos < outlen);
/*
* Encrypt the key.
@@ -1874,7 +1876,7 @@ int sshcom_write(const char *filename, sign_key *key,
* And save it. We'll use Unix line endings just in case it's
* subsequently transferred in binary mode.
*/
- fp = fopen(filename, "wb"); /* ensure Unix line endings */
+ fp = fopen(filename, "wb"); /* ensure Unix line endings */
if (!fp)
goto error;
fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
@@ -1886,16 +1888,16 @@ int sshcom_write(const char *filename, sign_key *key,
* Don't ask me, I didn't design it.
*/
{
- int slen = 60; /* starts at 60 due to "Comment: " */
+ int slen = 60; /* starts at 60 due to "Comment: " */
char *c = key->comment;
while ((int)strlen(c) > slen) {
fprintf(fp, "%.*s\\\n", slen, c);
c += slen;
- slen = 70; /* allow 70 chars on subsequent lines */
+ slen = 70; /* allow 70 chars on subsequent lines */
}
fprintf(fp, "%s\"\n", c);
}
- base64_encode_fp(fp, outblob, pos, 70);
+ base64_encode_fp(fp, outblob, pos, 70);
fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
fclose(fp);
ret = 1;
@@ -1903,15 +1905,15 @@ int sshcom_write(const char *filename, sign_key *key,
error:
if (outblob) {
memset(outblob, 0, outlen);
- m_free(outblob);
+ m_free(outblob);
}
if (privblob) {
memset(privblob, 0, privlen);
- m_free(privblob);
+ m_free(privblob);
}
if (pubblob) {
memset(pubblob, 0, publen);
- m_free(pubblob);
+ m_free(pubblob);
}
return ret;
}