diff gensignkey.c @ 849:754d7bee1068 ecc

Merge
author Matt Johnston <matt@ucc.asn.au>
date Fri, 08 Nov 2013 23:32:13 +0800
parents f4bb964c8678
children 7540c0822374
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gensignkey.c	Fri Nov 08 23:32:13 2013 +0800
@@ -0,0 +1,127 @@
+#include "includes.h"
+#include "dbutil.h"
+#include "buffer.h"
+#include "ecdsa.h"
+#include "genrsa.h"
+#include "gendss.h"
+#include "signkey.h"
+
+#define RSA_DEFAULT_SIZE 2048
+#define DSS_DEFAULT_SIZE 1024
+
+// Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
+static int buf_writefile(buffer * buf, const char * filename) {
+	int ret = DROPBEAR_FAILURE;
+	int fd = -1;
+
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+	if (fd < 0) {
+		dropbear_log(LOG_ERR, "Couldn't create new file %s: %s",
+			filename, strerror(errno));
+		goto out;
+	}
+
+	/* write the file now */
+	while (buf->pos != buf->len) {
+		int len = write(fd, buf_getptr(buf, buf->len - buf->pos),
+				buf->len - buf->pos);
+		if (errno == EINTR) {
+			continue;
+		}
+		if (len <= 0) {
+			dropbear_log(LOG_ERR, "Failed writing file %s: %s",
+				filename, strerror(errno));
+			goto out;
+		}
+		buf_incrpos(buf, len);
+	}
+
+	ret = DROPBEAR_SUCCESS;
+
+out:
+	if (fd >= 0) {
+		m_close(fd);
+	}
+	return ret;
+}
+
+/* returns 0 on failure */
+static int get_default_bits(enum signkey_type keytype)
+{
+        switch (keytype) {
+#ifdef DROPBEAR_RSA
+            case DROPBEAR_SIGNKEY_RSA:
+				return RSA_DEFAULT_SIZE;
+#endif
+#ifdef DROPBEAR_DSS
+            case DROPBEAR_SIGNKEY_DSS:
+                return DSS_DEFAULT_SIZE;
+#endif
+#ifdef DROPBEAR_ECDSA
+            case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
+                return ECDSA_DEFAULT_SIZE;
+            case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
+            	return 521;
+            case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
+            	return 384;
+            case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
+            	return 256;
+#endif
+            default:
+                return 0;
+		}
+}
+
+int signkey_generate(enum signkey_type keytype, int bits, const char* filename)
+{
+	sign_key * key = NULL;
+	buffer *buf = NULL;
+	int ret = DROPBEAR_FAILURE;
+	if (bits == 0)
+	{
+		bits = get_default_bits(keytype);
+	}
+
+	/* now we can generate the key */
+	key = new_sign_key();
+
+	switch(keytype) {
+#ifdef DROPBEAR_RSA
+		case DROPBEAR_SIGNKEY_RSA:
+			key->rsakey = gen_rsa_priv_key(bits);
+			break;
+#endif
+#ifdef DROPBEAR_DSS
+		case DROPBEAR_SIGNKEY_DSS:
+			key->dsskey = gen_dss_priv_key(bits);
+			break;
+#endif
+#ifdef DROPBEAR_ECDSA
+		case DROPBEAR_SIGNKEY_ECDSA_KEYGEN:
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
+		case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
+			{
+				ecc_key *ecckey = gen_ecdsa_priv_key(bits);
+				keytype = ecdsa_signkey_type(ecckey);
+				*signkey_key_ptr(key, keytype) = ecckey;
+			}
+			break;
+#endif
+		default:
+			dropbear_exit("Internal error");
+	}
+
+	buf = buf_new(MAX_PRIVKEY_SIZE); 
+
+	buf_put_priv_key(buf, key, keytype);
+	sign_key_free(key);
+	key = NULL;
+	buf_setpos(buf, 0);
+	ret = buf_writefile(buf, filename);
+
+	buf_burn(buf);
+	buf_free(buf);
+	buf = NULL;
+	return ret;
+}