summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2022-03-30 11:44:04 +0800
committerMatt Johnston <matt@ucc.asn.au>2022-03-30 11:44:04 +0800
commitda8ad3ebc94c72f07cf54db540a762095f3deef2 (patch)
tree279311e4ee802b78f30a169592755fc42597795a
parent2bfc2be6e411572c9050fae7c83b132af605dd39 (diff)
downloaddropbear-da8ad3ebc94c72f07cf54db540a762095f3deef2.tar.gz
Make SHA1 optional, implement SHA256 fingerprints
SHA256 is always compiled and only enable SHA1 when needed. Fingerprints are always SHA256: base64 format, md5 and sha1 are removed. dbrandom now uses sha256 its hash function.
-rw-r--r--common-kex.c2
-rw-r--r--crypto_desc.c7
-rw-r--r--dbrandom.c47
-rw-r--r--default_options.h4
-rw-r--r--dropbearkey.c2
-rw-r--r--libtomcrypt/src/headers/tomcrypt_dropbear.h8
-rw-r--r--signkey.c112
-rw-r--r--sysoptions.h8
8 files changed, 66 insertions, 124 deletions
diff --git a/common-kex.c b/common-kex.c
index 6aaec29..ac88442 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -249,7 +249,7 @@ static void kexinitialise() {
/* Helper function for gen_new_keys, creates a hash. It makes a copy of the
* already initialised hash_state hs, which should already have processed
* the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
- * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
+ * out must have at least min(hash_size, outlen) bytes allocated.
*
* See Section 7.2 of rfc4253 (ssh transport) for details */
static void hashkeys(unsigned char *out, unsigned int outlen,
diff --git a/crypto_desc.c b/crypto_desc.c
index b370728..5e0e960 100644
--- a/crypto_desc.c
+++ b/crypto_desc.c
@@ -31,8 +31,9 @@ void crypto_init() {
};
const struct ltc_hash_descriptor *reghashes[] = {
- /* we need sha1 for hostkey stuff regardless */
+#if DROPBEAR_SHA1_HMAC
&sha1_desc,
+#endif
#if DROPBEAR_MD5_HMAC
&md5_desc,
#endif
@@ -46,9 +47,9 @@ void crypto_init() {
&sha512_desc,
#endif
NULL
- };
+ };
int i;
-
+
for (i = 0; regciphers[i] != NULL; i++) {
if (register_cipher(regciphers[i]) == -1) {
dropbear_exit("Error registering crypto");
diff --git a/dbrandom.c b/dbrandom.c
index 3f21593..755645c 100644
--- a/dbrandom.c
+++ b/dbrandom.c
@@ -34,7 +34,7 @@ static uint32_t counter = 0;
/* the max value for the counter, so it won't integer overflow */
#define MAX_COUNTER (1<<30)
-static unsigned char hashpool[SHA1_HASH_SIZE] = {0};
+static unsigned char hashpool[SHA256_HASH_SIZE] = {0};
static int donerandinit = 0;
#define INIT_SEED_SIZE 32 /* 256 bits */
@@ -100,7 +100,7 @@ process_file(hash_state *hs, const char *filename,
}
goto out;
}
- sha1_process(hs, readbuf, readlen);
+ sha256_process(hs, readbuf, readlen);
readcount += readlen;
}
ret = DROPBEAR_SUCCESS;
@@ -120,13 +120,13 @@ void addrandom(const unsigned char * buf, unsigned int len)
#endif
/* hash in the new seed data */
- sha1_init(&hs);
+ sha256_init(&hs);
/* existing state (zeroes on startup) */
- sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
+ sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
/* new */
- sha1_process(&hs, buf, len);
- sha1_done(&hs, hashpool);
+ sha256_process(&hs, buf, len);
+ sha256_done(&hs, hashpool);
}
static void write_urandom()
@@ -152,10 +152,10 @@ static void write_urandom()
#if DROPBEAR_FUZZ
void fuzz_seed(const unsigned char* dat, unsigned int len) {
hash_state hs;
- sha1_init(&hs);
- sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
- sha1_process(&hs, dat, len);
- sha1_done(&hs, hashpool);
+ sha256_init(&hs);
+ sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
+ sha256_process(&hs, dat, len);
+ sha256_done(&hs, hashpool);
counter = 0;
donerandinit = 1;
}
@@ -209,7 +209,7 @@ static int process_getrandom(hash_state *hs) {
if (ret == sizeof(buf)) {
/* Success, stir in the entropy */
- sha1_process(hs, (void*)buf, sizeof(buf));
+ sha256_process(hs, (void*)buf, sizeof(buf));
return DROPBEAR_SUCCESS;
}
@@ -221,7 +221,6 @@ static int process_getrandom(hash_state *hs) {
/* Initialise the prng from /dev/urandom or prngd. This function can
* be called multiple times */
void seedrandom() {
-
hash_state hs;
pid_t pid;
@@ -236,10 +235,10 @@ void seedrandom() {
#endif
/* hash in the new seed data */
- sha1_init(&hs);
+ sha256_init(&hs);
/* existing state */
- sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
+ sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
#ifdef HAVE_GETRANDOM
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
@@ -289,21 +288,21 @@ void seedrandom() {
#endif
pid = getpid();
- sha1_process(&hs, (void*)&pid, sizeof(pid));
+ sha256_process(&hs, (void*)&pid, sizeof(pid));
/* gettimeofday() doesn't completely fill out struct timeval on
OS X (10.8.3), avoid valgrind warnings by clearing it first */
memset(&tv, 0x0, sizeof(tv));
gettimeofday(&tv, NULL);
- sha1_process(&hs, (void*)&tv, sizeof(tv));
+ sha256_process(&hs, (void*)&tv, sizeof(tv));
clockval = clock();
- sha1_process(&hs, (void*)&clockval, sizeof(clockval));
+ sha256_process(&hs, (void*)&clockval, sizeof(clockval));
/* When a private key is read by the client or server it will
* be added to the hashpool - see runopts.c */
- sha1_done(&hs, hashpool);
+ sha256_done(&hs, hashpool);
counter = 0;
donerandinit = 1;
@@ -317,7 +316,7 @@ void seedrandom() {
void genrandom(unsigned char* buf, unsigned int len) {
hash_state hs;
- unsigned char hash[SHA1_HASH_SIZE];
+ unsigned char hash[SHA256_HASH_SIZE];
unsigned int copylen;
if (!donerandinit) {
@@ -325,17 +324,17 @@ void genrandom(unsigned char* buf, unsigned int len) {
}
while (len > 0) {
- sha1_init(&hs);
- sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
- sha1_process(&hs, (void*)&counter, sizeof(counter));
- sha1_done(&hs, hash);
+ sha256_init(&hs);
+ sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
+ sha256_process(&hs, (void*)&counter, sizeof(counter));
+ sha256_done(&hs, hash);
counter++;
if (counter > MAX_COUNTER) {
seedrandom();
}
- copylen = MIN(len, SHA1_HASH_SIZE);
+ copylen = MIN(len, SHA256_HASH_SIZE);
memcpy(buf, hash, copylen);
len -= copylen;
buf += copylen;
diff --git a/default_options.h b/default_options.h
index d9e7ba2..4a5709a 100644
--- a/default_options.h
+++ b/default_options.h
@@ -116,7 +116,7 @@ IMPORTANT: Some options will require "make clean" after changes */
* Compiling in will add ~6kB to binary size on x86-64 */
#define DROPBEAR_ENABLE_GCM_MODE 0
-/* Message integrity. sha2-256 is recommended as a default,
+/* Message integrity. sha2-256 is recommended as a default,
sha1 for compatibility */
#define DROPBEAR_SHA1_HMAC 1
#define DROPBEAR_SHA2_256_HMAC 1
@@ -172,7 +172,7 @@ IMPORTANT: Some options will require "make clean" after changes */
* Small systems should generally include either curve25519 or ecdh for performance.
* curve25519 is less widely supported but is faster
- */
+ */
#define DROPBEAR_DH_GROUP14_SHA1 1
#define DROPBEAR_DH_GROUP14_SHA256 1
#define DROPBEAR_DH_GROUP16 0
diff --git a/dropbearkey.c b/dropbearkey.c
index 183e58b..fa1ee39 100644
--- a/dropbearkey.c
+++ b/dropbearkey.c
@@ -341,7 +341,7 @@ static void printpubkey(sign_key * key, int keytype) {
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
if (err != CRYPT_OK) {
- fprintf(stderr, "base64 failed");
+ dropbear_exit("base64 failed");
}
typestring = signkey_name_from_type(keytype, NULL);
diff --git a/libtomcrypt/src/headers/tomcrypt_dropbear.h b/libtomcrypt/src/headers/tomcrypt_dropbear.h
index 3e24ea2..46e84fb 100644
--- a/libtomcrypt/src/headers/tomcrypt_dropbear.h
+++ b/libtomcrypt/src/headers/tomcrypt_dropbear.h
@@ -16,12 +16,6 @@
#if DROPBEAR_AES
#define LTC_RIJNDAEL
#endif
-/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
- * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
-#if DROPBEAR_TWOFISH
-#define LTC_TWOFISH
-#define LTC_TWOFISH_SMALL
-#endif
#if DROPBEAR_3DES
#define LTC_DES
@@ -56,7 +50,9 @@
#define LTC_SHA256
#endif
+#if DROPBEAR_SHA1
#define LTC_SHA1
+#endif
#if DROPBEAR_MD5
#define LTC_MD5
diff --git a/signkey.c b/signkey.c
index 597ba65..3f145b0 100644
--- a/signkey.c
+++ b/signkey.c
@@ -544,98 +544,42 @@ void sign_key_free(sign_key *key) {
TRACE2(("leave sign_key_free"))
}
-static char hexdig(unsigned char x) {
- if (x > 0xf)
- return 'X';
-
- if (x < 10)
- return '0' + x;
- else
- return 'a' + x - 10;
-}
-
-/* Since we're not sure if we'll have md5 or sha1, we present both.
- * MD5 is used in preference, but sha1 could still be useful */
-#if DROPBEAR_MD5_HMAC
-static char * sign_key_md5_fingerprint(const unsigned char* keyblob,
- unsigned int keybloblen) {
-
- char * ret;
- hash_state hs;
- unsigned char hash[MD5_HASH_SIZE];
- unsigned int i;
- unsigned int buflen;
-
- md5_init(&hs);
-
- /* skip the size int of the string - this is a bit messy */
- md5_process(&hs, keyblob, keybloblen);
-
- md5_done(&hs, hash);
-
- /* "md5 hexfingerprinthere\0", each hex digit is "AB:" etc */
- buflen = 4 + 3*MD5_HASH_SIZE;
- ret = (char*)m_malloc(buflen);
-
- memset(ret, 'Z', buflen);
- strcpy(ret, "md5 ");
-
- for (i = 0; i < MD5_HASH_SIZE; i++) {
- unsigned int pos = 4 + i*3;
- ret[pos] = hexdig(hash[i] >> 4);
- ret[pos+1] = hexdig(hash[i] & 0x0f);
- ret[pos+2] = ':';
- }
- ret[buflen-1] = 0x0;
-
- return ret;
-}
-
-#else /* use SHA1 rather than MD5 for fingerprint */
-static char * sign_key_sha1_fingerprint(const unsigned char* keyblob,
+static char * sign_key_sha256_fingerprint(const unsigned char* keyblob,
unsigned int keybloblen) {
char * ret;
hash_state hs;
- unsigned char hash[SHA1_HASH_SIZE];
- unsigned int i;
- unsigned int buflen;
-
- sha1_init(&hs);
-
- /* skip the size int of the string - this is a bit messy */
- sha1_process(&hs, keyblob, keybloblen);
-
- sha1_done(&hs, hash);
-
- /* "sha1!! hexfingerprinthere\0", each hex digit is "AB:" etc */
- buflen = 7 + 3*SHA1_HASH_SIZE;
- ret = (char*)m_malloc(buflen);
-
- strcpy(ret, "sha1 ");
-
- for (i = 0; i < SHA1_HASH_SIZE; i++) {
- unsigned int pos = 7 + 3*i;
- ret[pos] = hexdig(hash[i] >> 4);
- ret[pos+1] = hexdig(hash[i] & 0x0f);
- ret[pos+2] = ':';
- }
- ret[buflen-1] = 0x0;
-
+ unsigned char hash[SHA256_HASH_SIZE];
+ unsigned int b64chars, start;
+ unsigned long b64size;
+ const char *prefix = "SHA256:";
+ int err;
+
+ sha256_init(&hs);
+ sha256_process(&hs, keyblob, keybloblen);
+ sha256_done(&hs, hash);
+
+ /* eg "SHA256:P9szN0L2ls6KxkVv7Bppv3asnZCn03rY7Msm/c8+ZgA"
+ * 256/6 = 42.66 => 43 base64 chars. OpenSSH discards
+ * base64 padding output. */
+ start = strlen(prefix);
+ b64chars = 43;
+ /* space for discarded b64 padding and null terminator */
+ b64size = b64chars + 4;
+ ret = m_malloc(start + b64size);
+
+ memcpy(ret, prefix, start);
+ err = base64_encode(hash, SHA256_HASH_SIZE, &ret[start], &b64size);
+ if (err != CRYPT_OK) {
+ dropbear_exit("base64 failed");
+ }
+ ret[start + b64chars] = '\0';
return ret;
}
-#endif /* MD5/SHA1 switch */
-
-/* This will return a freshly malloced string, containing a fingerprint
- * in either sha1 or md5 */
+/* This will return a freshly malloced string */
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen) {
-
-#if DROPBEAR_MD5_HMAC
- return sign_key_md5_fingerprint(keyblob, keybloblen);
-#else
- return sign_key_sha1_fingerprint(keyblob, keybloblen);
-#endif
+ return sign_key_sha256_fingerprint(keyblob, keybloblen);
}
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
diff --git a/sysoptions.h b/sysoptions.h
index 3267d95..6c164f7 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -157,9 +157,11 @@
#endif
/* hashes which will be linked and registered */
-#define DROPBEAR_SHA256 ((DROPBEAR_SHA2_256_HMAC) || (DROPBEAR_ECC_256) \
- || (DROPBEAR_CURVE25519) || (DROPBEAR_DH_GROUP14_SHA256) \
- || (DROPBEAR_RSA_SHA256))
+#define DROPBEAR_SHA1 (DROPBEAR_RSA_SHA1 || DROPBEAR_DSS \
+ || DROPBEAR_SHA1_HMAC || DROPBEAR_SHA1_96_HMAC \
+ || DROPBEAR_DH_GROUP1 || DROPBEAR_DH_GROUP14_SHA1 )
+/* sha256 is always used for fingerprints and dbrandom */
+#define DROPBEAR_SHA256 1
#define DROPBEAR_SHA384 (DROPBEAR_ECC_384)
/* LTC SHA384 depends on SHA512 */
#define DROPBEAR_SHA512 ((DROPBEAR_SHA2_512_HMAC) || (DROPBEAR_ECC_521) \