mirror of
https://github.com/clearml/dropbear
synced 2025-05-17 01:53:38 +00:00
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.
This commit is contained in:
parent
6dc029f2cb
commit
8b68eb55d9
@ -249,7 +249,7 @@ static void kexinitialise() {
|
|||||||
/* Helper function for gen_new_keys, creates a hash. It makes a copy of the
|
/* 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
|
* 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.
|
* 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 */
|
* See Section 7.2 of rfc4253 (ssh transport) for details */
|
||||||
static void hashkeys(unsigned char *out, unsigned int outlen,
|
static void hashkeys(unsigned char *out, unsigned int outlen,
|
||||||
|
@ -31,8 +31,9 @@ void crypto_init() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const struct ltc_hash_descriptor *reghashes[] = {
|
const struct ltc_hash_descriptor *reghashes[] = {
|
||||||
/* we need sha1 for hostkey stuff regardless */
|
#if DROPBEAR_SHA1_HMAC
|
||||||
&sha1_desc,
|
&sha1_desc,
|
||||||
|
#endif
|
||||||
#if DROPBEAR_MD5_HMAC
|
#if DROPBEAR_MD5_HMAC
|
||||||
&md5_desc,
|
&md5_desc,
|
||||||
#endif
|
#endif
|
||||||
@ -46,9 +47,9 @@ void crypto_init() {
|
|||||||
&sha512_desc,
|
&sha512_desc,
|
||||||
#endif
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; regciphers[i] != NULL; i++) {
|
for (i = 0; regciphers[i] != NULL; i++) {
|
||||||
if (register_cipher(regciphers[i]) == -1) {
|
if (register_cipher(regciphers[i]) == -1) {
|
||||||
dropbear_exit("Error registering crypto");
|
dropbear_exit("Error registering crypto");
|
||||||
|
47
dbrandom.c
47
dbrandom.c
@ -34,7 +34,7 @@ static uint32_t counter = 0;
|
|||||||
/* the max value for the counter, so it won't integer overflow */
|
/* the max value for the counter, so it won't integer overflow */
|
||||||
#define MAX_COUNTER (1<<30)
|
#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;
|
static int donerandinit = 0;
|
||||||
|
|
||||||
#define INIT_SEED_SIZE 32 /* 256 bits */
|
#define INIT_SEED_SIZE 32 /* 256 bits */
|
||||||
@ -100,7 +100,7 @@ process_file(hash_state *hs, const char *filename,
|
|||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sha1_process(hs, readbuf, readlen);
|
sha256_process(hs, readbuf, readlen);
|
||||||
readcount += readlen;
|
readcount += readlen;
|
||||||
}
|
}
|
||||||
ret = DROPBEAR_SUCCESS;
|
ret = DROPBEAR_SUCCESS;
|
||||||
@ -120,13 +120,13 @@ void addrandom(const unsigned char * buf, unsigned int len)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* hash in the new seed data */
|
/* hash in the new seed data */
|
||||||
sha1_init(&hs);
|
sha256_init(&hs);
|
||||||
/* existing state (zeroes on startup) */
|
/* existing state (zeroes on startup) */
|
||||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||||
|
|
||||||
/* new */
|
/* new */
|
||||||
sha1_process(&hs, buf, len);
|
sha256_process(&hs, buf, len);
|
||||||
sha1_done(&hs, hashpool);
|
sha256_done(&hs, hashpool);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_urandom()
|
static void write_urandom()
|
||||||
@ -152,10 +152,10 @@ static void write_urandom()
|
|||||||
#if DROPBEAR_FUZZ
|
#if DROPBEAR_FUZZ
|
||||||
void fuzz_seed(const unsigned char* dat, unsigned int len) {
|
void fuzz_seed(const unsigned char* dat, unsigned int len) {
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
sha1_init(&hs);
|
sha256_init(&hs);
|
||||||
sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
sha256_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz"));
|
||||||
sha1_process(&hs, dat, len);
|
sha256_process(&hs, dat, len);
|
||||||
sha1_done(&hs, hashpool);
|
sha256_done(&hs, hashpool);
|
||||||
counter = 0;
|
counter = 0;
|
||||||
donerandinit = 1;
|
donerandinit = 1;
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ static int process_getrandom(hash_state *hs) {
|
|||||||
|
|
||||||
if (ret == sizeof(buf)) {
|
if (ret == sizeof(buf)) {
|
||||||
/* Success, stir in the entropy */
|
/* Success, stir in the entropy */
|
||||||
sha1_process(hs, (void*)buf, sizeof(buf));
|
sha256_process(hs, (void*)buf, sizeof(buf));
|
||||||
return DROPBEAR_SUCCESS;
|
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
|
/* Initialise the prng from /dev/urandom or prngd. This function can
|
||||||
* be called multiple times */
|
* be called multiple times */
|
||||||
void seedrandom() {
|
void seedrandom() {
|
||||||
|
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -236,10 +235,10 @@ void seedrandom() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* hash in the new seed data */
|
/* hash in the new seed data */
|
||||||
sha1_init(&hs);
|
sha256_init(&hs);
|
||||||
|
|
||||||
/* existing state */
|
/* existing state */
|
||||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM
|
#ifdef HAVE_GETRANDOM
|
||||||
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
|
if (process_getrandom(&hs) == DROPBEAR_SUCCESS) {
|
||||||
@ -289,21 +288,21 @@ void seedrandom() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pid = getpid();
|
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
|
/* gettimeofday() doesn't completely fill out struct timeval on
|
||||||
OS X (10.8.3), avoid valgrind warnings by clearing it first */
|
OS X (10.8.3), avoid valgrind warnings by clearing it first */
|
||||||
memset(&tv, 0x0, sizeof(tv));
|
memset(&tv, 0x0, sizeof(tv));
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
sha1_process(&hs, (void*)&tv, sizeof(tv));
|
sha256_process(&hs, (void*)&tv, sizeof(tv));
|
||||||
|
|
||||||
clockval = clock();
|
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
|
/* When a private key is read by the client or server it will
|
||||||
* be added to the hashpool - see runopts.c */
|
* be added to the hashpool - see runopts.c */
|
||||||
|
|
||||||
sha1_done(&hs, hashpool);
|
sha256_done(&hs, hashpool);
|
||||||
|
|
||||||
counter = 0;
|
counter = 0;
|
||||||
donerandinit = 1;
|
donerandinit = 1;
|
||||||
@ -317,7 +316,7 @@ void seedrandom() {
|
|||||||
void genrandom(unsigned char* buf, unsigned int len) {
|
void genrandom(unsigned char* buf, unsigned int len) {
|
||||||
|
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
unsigned char hash[SHA1_HASH_SIZE];
|
unsigned char hash[SHA256_HASH_SIZE];
|
||||||
unsigned int copylen;
|
unsigned int copylen;
|
||||||
|
|
||||||
if (!donerandinit) {
|
if (!donerandinit) {
|
||||||
@ -325,17 +324,17 @@ void genrandom(unsigned char* buf, unsigned int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
sha1_init(&hs);
|
sha256_init(&hs);
|
||||||
sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
|
sha256_process(&hs, (void*)hashpool, sizeof(hashpool));
|
||||||
sha1_process(&hs, (void*)&counter, sizeof(counter));
|
sha256_process(&hs, (void*)&counter, sizeof(counter));
|
||||||
sha1_done(&hs, hash);
|
sha256_done(&hs, hash);
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
if (counter > MAX_COUNTER) {
|
if (counter > MAX_COUNTER) {
|
||||||
seedrandom();
|
seedrandom();
|
||||||
}
|
}
|
||||||
|
|
||||||
copylen = MIN(len, SHA1_HASH_SIZE);
|
copylen = MIN(len, SHA256_HASH_SIZE);
|
||||||
memcpy(buf, hash, copylen);
|
memcpy(buf, hash, copylen);
|
||||||
len -= copylen;
|
len -= copylen;
|
||||||
buf += copylen;
|
buf += copylen;
|
||||||
|
@ -116,7 +116,7 @@ IMPORTANT: Some options will require "make clean" after changes */
|
|||||||
* Compiling in will add ~6kB to binary size on x86-64 */
|
* Compiling in will add ~6kB to binary size on x86-64 */
|
||||||
#define DROPBEAR_ENABLE_GCM_MODE 0
|
#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 */
|
sha1 for compatibility */
|
||||||
#define DROPBEAR_SHA1_HMAC 1
|
#define DROPBEAR_SHA1_HMAC 1
|
||||||
#define DROPBEAR_SHA2_256_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.
|
* Small systems should generally include either curve25519 or ecdh for performance.
|
||||||
* curve25519 is less widely supported but is faster
|
* curve25519 is less widely supported but is faster
|
||||||
*/
|
*/
|
||||||
#define DROPBEAR_DH_GROUP14_SHA1 1
|
#define DROPBEAR_DH_GROUP14_SHA1 1
|
||||||
#define DROPBEAR_DH_GROUP14_SHA256 1
|
#define DROPBEAR_DH_GROUP14_SHA256 1
|
||||||
#define DROPBEAR_DH_GROUP16 0
|
#define DROPBEAR_DH_GROUP16 0
|
||||||
|
@ -341,7 +341,7 @@ static void printpubkey(sign_key * key, int keytype) {
|
|||||||
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
|
err = base64_encode(buf_getptr(buf, len), len, base64key, &base64len);
|
||||||
|
|
||||||
if (err != CRYPT_OK) {
|
if (err != CRYPT_OK) {
|
||||||
fprintf(stderr, "base64 failed");
|
dropbear_exit("base64 failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
typestring = signkey_name_from_type(keytype, NULL);
|
typestring = signkey_name_from_type(keytype, NULL);
|
||||||
|
@ -16,12 +16,6 @@
|
|||||||
#if DROPBEAR_AES
|
#if DROPBEAR_AES
|
||||||
#define LTC_RIJNDAEL
|
#define LTC_RIJNDAEL
|
||||||
#endif
|
#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
|
#if DROPBEAR_3DES
|
||||||
#define LTC_DES
|
#define LTC_DES
|
||||||
@ -56,7 +50,9 @@
|
|||||||
#define LTC_SHA256
|
#define LTC_SHA256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DROPBEAR_SHA1
|
||||||
#define LTC_SHA1
|
#define LTC_SHA1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if DROPBEAR_MD5
|
#if DROPBEAR_MD5
|
||||||
#define LTC_MD5
|
#define LTC_MD5
|
||||||
|
104
signkey.c
104
signkey.c
@ -544,98 +544,42 @@ void sign_key_free(sign_key *key) {
|
|||||||
TRACE2(("leave sign_key_free"))
|
TRACE2(("leave sign_key_free"))
|
||||||
}
|
}
|
||||||
|
|
||||||
static char hexdig(unsigned char x) {
|
static char * sign_key_sha256_fingerprint(const unsigned char* keyblob,
|
||||||
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) {
|
unsigned int keybloblen) {
|
||||||
|
|
||||||
char * ret;
|
char * ret;
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
unsigned char hash[MD5_HASH_SIZE];
|
unsigned char hash[SHA256_HASH_SIZE];
|
||||||
unsigned int i;
|
unsigned int b64chars, start;
|
||||||
unsigned int buflen;
|
unsigned long b64size;
|
||||||
|
const char *prefix = "SHA256:";
|
||||||
|
int err;
|
||||||
|
|
||||||
md5_init(&hs);
|
sha256_init(&hs);
|
||||||
|
sha256_process(&hs, keyblob, keybloblen);
|
||||||
|
sha256_done(&hs, hash);
|
||||||
|
|
||||||
/* skip the size int of the string - this is a bit messy */
|
/* eg "SHA256:P9szN0L2ls6KxkVv7Bppv3asnZCn03rY7Msm/c8+ZgA"
|
||||||
md5_process(&hs, keyblob, keybloblen);
|
* 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);
|
||||||
|
|
||||||
md5_done(&hs, hash);
|
memcpy(ret, prefix, start);
|
||||||
|
err = base64_encode(hash, SHA256_HASH_SIZE, &ret[start], &b64size);
|
||||||
/* "md5 hexfingerprinthere\0", each hex digit is "AB:" etc */
|
if (err != CRYPT_OK) {
|
||||||
buflen = 4 + 3*MD5_HASH_SIZE;
|
dropbear_exit("base64 failed");
|
||||||
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;
|
ret[start + b64chars] = '\0';
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* use SHA1 rather than MD5 for fingerprint */
|
/* This will return a freshly malloced string */
|
||||||
static char * sign_key_sha1_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;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MD5/SHA1 switch */
|
|
||||||
|
|
||||||
/* This will return a freshly malloced string, containing a fingerprint
|
|
||||||
* in either sha1 or md5 */
|
|
||||||
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen) {
|
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen) {
|
||||||
|
return sign_key_sha256_fingerprint(keyblob, keybloblen);
|
||||||
#if DROPBEAR_MD5_HMAC
|
|
||||||
return sign_key_md5_fingerprint(keyblob, keybloblen);
|
|
||||||
#else
|
|
||||||
return sign_key_sha1_fingerprint(keyblob, keybloblen);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
||||||
|
@ -157,9 +157,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* hashes which will be linked and registered */
|
/* hashes which will be linked and registered */
|
||||||
#define DROPBEAR_SHA256 ((DROPBEAR_SHA2_256_HMAC) || (DROPBEAR_ECC_256) \
|
#define DROPBEAR_SHA1 (DROPBEAR_RSA_SHA1 || DROPBEAR_DSS \
|
||||||
|| (DROPBEAR_CURVE25519) || (DROPBEAR_DH_GROUP14_SHA256) \
|
|| DROPBEAR_SHA1_HMAC || DROPBEAR_SHA1_96_HMAC \
|
||||||
|| (DROPBEAR_RSA_SHA256))
|
|| 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)
|
#define DROPBEAR_SHA384 (DROPBEAR_ECC_384)
|
||||||
/* LTC SHA384 depends on SHA512 */
|
/* LTC SHA384 depends on SHA512 */
|
||||||
#define DROPBEAR_SHA512 ((DROPBEAR_SHA2_512_HMAC) || (DROPBEAR_ECC_521) \
|
#define DROPBEAR_SHA512 ((DROPBEAR_SHA2_512_HMAC) || (DROPBEAR_ECC_521) \
|
||||||
|
Loading…
Reference in New Issue
Block a user