mirror of
https://github.com/clearml/dropbear
synced 2025-06-04 03:36:26 +00:00
Implement server-side support for sk-ecdsa U2F-backed keys (#142)
* Implement server-side support for sk-ecdsa U2F-backed keys * Fix out-of-bounds read on normal ecdsa-sha2-[identifier] keys * Fix one more potential out-of-bounds read * Check if nistp256 curve is used in sk-ecdsa-sha2- key It's the only allowed curve per PROTOCOL.u2f specification * Implement server-side support for sk-ed25519 FIDO2-backed keys * Keys with type sk-* make no sense as host keys, so they should be disabled * fix typo * Make sk-ecdsa call buf_ecdsa_verify This reduces code duplication, the SK code just handles the different message format. * Reduce sk specific code The application id can be stored in signkey, then we don't need to call sk-specific functions from svr-authpubkey * Remove debugging output, which causes compilation errors with DEBUG_TRACE disabled * Proper cleanup of sk_app Co-authored-by: Matt Johnston <matt@codeconstruct.com.au>
This commit is contained in:
parent
18be2a6509
commit
c06d8254d8
@ -35,8 +35,8 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
|
|||||||
signkey.o rsa.o dbrandom.o \
|
signkey.o rsa.o dbrandom.o \
|
||||||
queue.o \
|
queue.o \
|
||||||
atomicio.o compat.o fake-rfc2553.o \
|
atomicio.o compat.o fake-rfc2553.o \
|
||||||
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
|
ltc_prng.o ecc.o ecdsa.o sk-ecdsa.o crypto_desc.o \
|
||||||
curve25519.o ed25519.o \
|
curve25519.o ed25519.o sk-ed25519.o \
|
||||||
dbmalloc.o \
|
dbmalloc.o \
|
||||||
gensignkey.o gendss.o genrsa.o gened25519.o
|
gensignkey.o gendss.o genrsa.o gened25519.o
|
||||||
|
|
||||||
|
@ -239,6 +239,9 @@ algo_type ssh_nocompress[] = {
|
|||||||
algo_type sigalgs[] = {
|
algo_type sigalgs[] = {
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
|
{"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL},
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
{"sk-ssh-ed25519@openssh.com", DROPBEAR_SIGNATURE_SK_ED25519, NULL, 1, NULL},
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ECDSA
|
#if DROPBEAR_ECDSA
|
||||||
#if DROPBEAR_ECC_256
|
#if DROPBEAR_ECC_256
|
||||||
@ -250,6 +253,9 @@ algo_type sigalgs[] = {
|
|||||||
#if DROPBEAR_ECC_521
|
#if DROPBEAR_ECC_521
|
||||||
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
|
{"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL},
|
||||||
#endif
|
#endif
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
{"sk-ecdsa-sha2-nistp256@openssh.com", DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256, NULL, 1, NULL},
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_RSA
|
#if DROPBEAR_RSA
|
||||||
#if DROPBEAR_RSA_SHA256
|
#if DROPBEAR_RSA_SHA256
|
||||||
|
@ -126,9 +126,11 @@ IMPORTANT: Some options will require "make clean" after changes */
|
|||||||
* code (either ECDSA or ECDH) increases binary size - around 30kB
|
* code (either ECDSA or ECDH) increases binary size - around 30kB
|
||||||
* on x86-64 */
|
* on x86-64 */
|
||||||
#define DROPBEAR_ECDSA 1
|
#define DROPBEAR_ECDSA 1
|
||||||
|
#define DROPBEAR_SK_ECDSA 1
|
||||||
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
|
/* Ed25519 is faster than ECDSA. Compiling in Ed25519 code increases
|
||||||
binary size - around 7,5kB on x86-64 */
|
binary size - around 7,5kB on x86-64 */
|
||||||
#define DROPBEAR_ED25519 1
|
#define DROPBEAR_ED25519 1
|
||||||
|
#define DROPBEAR_SK_ED25519 1
|
||||||
|
|
||||||
/* RSA must be >=1024 */
|
/* RSA must be >=1024 */
|
||||||
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
|
#define DROPBEAR_DEFAULT_RSA_SIZE 2048
|
||||||
|
23
ecdsa.c
23
ecdsa.c
@ -81,18 +81,25 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
|
|||||||
struct dropbear_ecc_curve **curve;
|
struct dropbear_ecc_curve **curve;
|
||||||
ecc_key *new_key = NULL;
|
ecc_key *new_key = NULL;
|
||||||
|
|
||||||
/* string "ecdsa-sha2-[identifier]" */
|
/* string "ecdsa-sha2-[identifier]" or "sk-ecdsa-sha2-nistp256@openssh.com" */
|
||||||
key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
|
key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
|
||||||
/* string "[identifier]" */
|
/* string "[identifier]" */
|
||||||
identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
|
identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
|
||||||
|
|
||||||
if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
|
if (strcmp (key_ident, "sk-ecdsa-sha2-nistp256@openssh.com") == 0) {
|
||||||
TRACE(("Bad identifier lengths"))
|
if (strcmp (identifier, "nistp256") != 0) {
|
||||||
goto out;
|
TRACE(("mismatching identifiers"))
|
||||||
}
|
goto out;
|
||||||
if (memcmp(&key_ident[strlen("ecdsa-sha2-")], identifier, identifier_len) != 0) {
|
}
|
||||||
TRACE(("mismatching identifiers"))
|
} else {
|
||||||
goto out;
|
if (key_ident_len != identifier_len + strlen ("ecdsa-sha2-")) {
|
||||||
|
TRACE(("Bad identifier lengths"))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (memcmp(&key_ident[strlen ("ecdsa-sha2-")], identifier, identifier_len) != 0) {
|
||||||
|
TRACE(("mismatching identifiers"))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (curve = dropbear_ecc_curves; *curve; curve++) {
|
for (curve = dropbear_ecc_curves; *curve; curve++) {
|
||||||
|
17
ed25519.c
17
ed25519.c
@ -38,14 +38,25 @@
|
|||||||
* The key will have the same format as buf_put_ed25519_key.
|
* The key will have the same format as buf_put_ed25519_key.
|
||||||
* These should be freed with ed25519_key_free.
|
* These should be freed with ed25519_key_free.
|
||||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||||
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key) {
|
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||||
|
enum signkey_type expect_keytype) {
|
||||||
|
|
||||||
unsigned int len;
|
|
||||||
|
unsigned int len, typelen;
|
||||||
|
char *keytype = NULL;
|
||||||
|
enum signkey_type buf_keytype;
|
||||||
|
|
||||||
TRACE(("enter buf_get_ed25519_pub_key"))
|
TRACE(("enter buf_get_ed25519_pub_key"))
|
||||||
dropbear_assert(key != NULL);
|
dropbear_assert(key != NULL);
|
||||||
|
|
||||||
buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
|
/* consume and check the key string */
|
||||||
|
keytype = buf_getstring(buf, &typelen);
|
||||||
|
buf_keytype = signkey_type_from_name(keytype, typelen);
|
||||||
|
m_free(keytype);
|
||||||
|
if (buf_keytype != expect_keytype) {
|
||||||
|
TRACE(("leave buf_get_ed25519_pub_key: mismatch key type"))
|
||||||
|
return DROPBEAR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
len = buf_getint(buf);
|
len = buf_getint(buf);
|
||||||
if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
|
if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "signkey.h"
|
||||||
|
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
|
|
||||||
@ -43,7 +44,8 @@ void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const bu
|
|||||||
#if DROPBEAR_SIGNKEY_VERIFY
|
#if DROPBEAR_SIGNKEY_VERIFY
|
||||||
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
|
int buf_ed25519_verify(buffer * buf, const dropbear_ed25519_key *key, const buffer *data_buf);
|
||||||
#endif
|
#endif
|
||||||
int buf_get_ed25519_pub_key(buffer* buf, dropbear_ed25519_key *key);
|
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
|
||||||
|
enum signkey_type expect_keytype);
|
||||||
int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key);
|
int buf_get_ed25519_priv_key(buffer* buf, dropbear_ed25519_key *key);
|
||||||
void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key);
|
void buf_put_ed25519_pub_key(buffer* buf, const dropbear_ed25519_key *key);
|
||||||
void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key);
|
void buf_put_ed25519_priv_key(buffer* buf, const dropbear_ed25519_key *key);
|
||||||
|
69
signkey.c
69
signkey.c
@ -28,6 +28,8 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "ecdsa.h"
|
#include "ecdsa.h"
|
||||||
|
#include "sk-ecdsa.h"
|
||||||
|
#include "sk-ed25519.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "dss.h"
|
#include "dss.h"
|
||||||
#include "ed25519.h"
|
#include "ed25519.h"
|
||||||
@ -43,9 +45,15 @@ static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
|
|||||||
"ecdsa-sha2-nistp256",
|
"ecdsa-sha2-nistp256",
|
||||||
"ecdsa-sha2-nistp384",
|
"ecdsa-sha2-nistp384",
|
||||||
"ecdsa-sha2-nistp521",
|
"ecdsa-sha2-nistp521",
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
"sk-ecdsa-sha2-nistp256@openssh.com",
|
||||||
|
#endif /* DROPBEAR_SK_ECDSA */
|
||||||
#endif /* DROPBEAR_ECDSA */
|
#endif /* DROPBEAR_ECDSA */
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
"ssh-ed25519",
|
"ssh-ed25519",
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
"sk-ssh-ed25519@openssh.com",
|
||||||
|
#endif /* DROPBEAR_SK_ED25519 */
|
||||||
#endif /* DROPBEAR_ED25519 */
|
#endif /* DROPBEAR_ED25519 */
|
||||||
/* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
|
/* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
|
||||||
};
|
};
|
||||||
@ -180,11 +188,17 @@ signkey_key_ptr(sign_key *key, enum signkey_type type) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
case DROPBEAR_SIGNKEY_ED25519:
|
case DROPBEAR_SIGNKEY_ED25519:
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
case DROPBEAR_SIGNKEY_SK_ED25519:
|
||||||
|
#endif
|
||||||
return (void**)&key->ed25519key;
|
return (void**)&key->ed25519key;
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ECDSA
|
#if DROPBEAR_ECDSA
|
||||||
#if DROPBEAR_ECC_256
|
#if DROPBEAR_ECC_256
|
||||||
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256:
|
||||||
|
#endif
|
||||||
return (void**)&key->ecckey256;
|
return (void**)&key->ecckey256;
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ECC_384
|
#if DROPBEAR_ECC_384
|
||||||
@ -260,7 +274,11 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ECDSA
|
#if DROPBEAR_ECDSA
|
||||||
if (signkey_is_ecdsa(keytype)) {
|
if (signkey_is_ecdsa(keytype)
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||||
if (eck) {
|
if (eck) {
|
||||||
if (*eck) {
|
if (*eck) {
|
||||||
@ -276,10 +294,14 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
if (keytype == DROPBEAR_SIGNKEY_ED25519) {
|
if (keytype == DROPBEAR_SIGNKEY_ED25519
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
ed25519_key_free(key->ed25519key);
|
ed25519_key_free(key->ed25519key);
|
||||||
key->ed25519key = m_malloc(sizeof(*key->ed25519key));
|
key->ed25519key = m_malloc(sizeof(*key->ed25519key));
|
||||||
ret = buf_get_ed25519_pub_key(buf, key->ed25519key);
|
ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype);
|
||||||
if (ret == DROPBEAR_FAILURE) {
|
if (ret == DROPBEAR_FAILURE) {
|
||||||
m_free(key->ed25519key);
|
m_free(key->ed25519key);
|
||||||
key->ed25519key = NULL;
|
key->ed25519key = NULL;
|
||||||
@ -287,6 +309,19 @@ int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||||
|
if (0
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
|| keytype == DROPBEAR_SIGNKEY_SK_ED25519
|
||||||
|
#endif
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
|| keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
key->sk_app = buf_getstring(buf, &key->sk_applen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TRACE2(("leave buf_get_pub_key"))
|
TRACE2(("leave buf_get_pub_key"))
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -401,7 +436,11 @@ void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
if (type == DROPBEAR_SIGNKEY_ED25519) {
|
if (type == DROPBEAR_SIGNKEY_ED25519
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
|| type == DROPBEAR_SIGNKEY_SK_ED25519
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
|
buf_put_ed25519_pub_key(pubkeys, key->ed25519key);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -495,6 +534,11 @@ void sign_key_free(sign_key *key) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_free(key->filename);
|
m_free(key->filename);
|
||||||
|
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||||
|
if (key->sk_app) {
|
||||||
|
m_free(key->sk_app);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_free(key);
|
m_free(key);
|
||||||
TRACE2(("leave sign_key_free"))
|
TRACE2(("leave sign_key_free"))
|
||||||
@ -639,6 +683,7 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DROPBEAR_SIGNKEY_VERIFY
|
#if DROPBEAR_SIGNKEY_VERIFY
|
||||||
|
|
||||||
/* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
|
/* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE.
|
||||||
* If FAILURE is returned, the position of
|
* If FAILURE is returned, the position of
|
||||||
* buf is undefined. If SUCCESS is returned, buf will be positioned after the
|
* buf is undefined. If SUCCESS is returned, buf will be positioned after the
|
||||||
@ -695,6 +740,22 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
|
|||||||
return buf_ed25519_verify(buf, key->ed25519key, data_buf);
|
return buf_ed25519_verify(buf, key->ed25519key, data_buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) {
|
||||||
|
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||||
|
if (eck && *eck) {
|
||||||
|
return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
|
||||||
|
dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
|
||||||
|
if (eck && *eck) {
|
||||||
|
return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
dropbear_exit("Non-matching signing type");
|
dropbear_exit("Non-matching signing type");
|
||||||
return DROPBEAR_FAILURE;
|
return DROPBEAR_FAILURE;
|
||||||
|
19
signkey.h
19
signkey.h
@ -44,9 +44,15 @@ enum signkey_type {
|
|||||||
DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
||||||
DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
||||||
DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256,
|
||||||
|
#endif /* DROPBEAR_SK_ECDSA */
|
||||||
#endif /* DROPBEAR_ECDSA */
|
#endif /* DROPBEAR_ECDSA */
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
DROPBEAR_SIGNKEY_ED25519,
|
DROPBEAR_SIGNKEY_ED25519,
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
DROPBEAR_SIGNKEY_SK_ED25519,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
DROPBEAR_SIGNKEY_NUM_NAMED,
|
DROPBEAR_SIGNKEY_NUM_NAMED,
|
||||||
DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */
|
DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */
|
||||||
@ -63,9 +69,15 @@ enum signature_type {
|
|||||||
DROPBEAR_SIGNATURE_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
DROPBEAR_SIGNATURE_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_ECDSA_NISTP256,
|
||||||
DROPBEAR_SIGNATURE_ECDSA_NISTP384 = DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
DROPBEAR_SIGNATURE_ECDSA_NISTP384 = DROPBEAR_SIGNKEY_ECDSA_NISTP384,
|
||||||
DROPBEAR_SIGNATURE_ECDSA_NISTP521 = DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
DROPBEAR_SIGNATURE_ECDSA_NISTP521 = DROPBEAR_SIGNKEY_ECDSA_NISTP521,
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256,
|
||||||
|
#endif /* DROPBEAR_SK_ECDSA */
|
||||||
#endif /* DROPBEAR_ECDSA */
|
#endif /* DROPBEAR_ECDSA */
|
||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
DROPBEAR_SIGNATURE_ED25519 = DROPBEAR_SIGNKEY_ED25519,
|
DROPBEAR_SIGNATURE_ED25519 = DROPBEAR_SIGNKEY_ED25519,
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
DROPBEAR_SIGNATURE_SK_ED25519 = DROPBEAR_SIGNKEY_SK_ED25519,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if DROPBEAR_RSA_SHA1
|
#if DROPBEAR_RSA_SHA1
|
||||||
DROPBEAR_SIGNATURE_RSA_SHA1 = 100, /* ssh-rsa signature (sha1) */
|
DROPBEAR_SIGNATURE_RSA_SHA1 = 100, /* ssh-rsa signature (sha1) */
|
||||||
@ -110,6 +122,12 @@ struct SIGN_key {
|
|||||||
#if DROPBEAR_ED25519
|
#if DROPBEAR_ED25519
|
||||||
struct dropbear_ED25519_Key * ed25519key;
|
struct dropbear_ED25519_Key * ed25519key;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
|
||||||
|
/* application ID for U2F/FIDO key types, a malloced string */
|
||||||
|
char * sk_app;
|
||||||
|
unsigned int sk_applen;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SIGN_key sign_key;
|
typedef struct SIGN_key sign_key;
|
||||||
@ -130,6 +148,7 @@ void sign_key_free(sign_key *key);
|
|||||||
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf);
|
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf);
|
||||||
#if DROPBEAR_SIGNKEY_VERIFY
|
#if DROPBEAR_SIGNKEY_VERIFY
|
||||||
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf);
|
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf);
|
||||||
|
int sk_buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf, char* app, unsigned int applen);
|
||||||
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
||||||
#endif
|
#endif
|
||||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||||
|
47
sk-ecdsa.c
Normal file
47
sk-ecdsa.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
|
||||||
|
#include "dbutil.h"
|
||||||
|
#include "ecc.h"
|
||||||
|
#include "ecdsa.h"
|
||||||
|
#include "sk-ecdsa.h"
|
||||||
|
|
||||||
|
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen) {
|
||||||
|
hash_state hs;
|
||||||
|
unsigned char subhash[SHA256_HASH_SIZE];
|
||||||
|
buffer *sk_buffer = NULL, *sig_buffer = NULL;
|
||||||
|
unsigned char flags;
|
||||||
|
unsigned int counter;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
TRACE(("buf_sk_ecdsa_verify"))
|
||||||
|
|
||||||
|
/* from https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f */
|
||||||
|
/* ecdsa signature to verify (r, s) */
|
||||||
|
sig_buffer = buf_getbuf(buf);
|
||||||
|
|
||||||
|
flags = buf_getbyte (buf);
|
||||||
|
counter = buf_getint (buf);
|
||||||
|
/* create the message to be signed */
|
||||||
|
sk_buffer = buf_new (2*SHA256_HASH_SIZE+5);
|
||||||
|
sha256_init (&hs);
|
||||||
|
sha256_process (&hs, app, applen);
|
||||||
|
sha256_done (&hs, subhash);
|
||||||
|
buf_putbytes (sk_buffer, subhash, sizeof (subhash));
|
||||||
|
buf_putbyte (sk_buffer, flags);
|
||||||
|
buf_putint (sk_buffer, counter);
|
||||||
|
sha256_init (&hs);
|
||||||
|
sha256_process (&hs, data_buf->data, data_buf->len);
|
||||||
|
sha256_done (&hs, subhash);
|
||||||
|
buf_putbytes (sk_buffer, subhash, sizeof (subhash));
|
||||||
|
|
||||||
|
ret = buf_ecdsa_verify(sig_buffer, key, sk_buffer);
|
||||||
|
buf_free(sk_buffer);
|
||||||
|
buf_free(sig_buffer);
|
||||||
|
|
||||||
|
TRACE(("leave buf_sk_ecdsa_verify, ret=%d", ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DROPBEAR_SK_ECDSA */
|
15
sk-ecdsa.h
Normal file
15
sk-ecdsa.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DROPBEAR_SK_ECDSA_H_
|
||||||
|
#define DROPBEAR_SK_ECDSA_H_
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "signkey.h"
|
||||||
|
|
||||||
|
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DROPBEAR_SK_ECDSA_H_ */
|
61
sk-ed25519.c
Normal file
61
sk-ed25519.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
|
||||||
|
#include "dbutil.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "curve25519.h"
|
||||||
|
#include "ed25519.h"
|
||||||
|
|
||||||
|
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen) {
|
||||||
|
|
||||||
|
int ret = DROPBEAR_FAILURE;
|
||||||
|
unsigned char *s;
|
||||||
|
unsigned long slen;
|
||||||
|
hash_state hs;
|
||||||
|
unsigned char hash[SHA256_HASH_SIZE];
|
||||||
|
buffer *sk_buffer = NULL;
|
||||||
|
unsigned char flags;
|
||||||
|
unsigned int counter;
|
||||||
|
|
||||||
|
TRACE(("enter buf_sk_ed25519_verify"))
|
||||||
|
dropbear_assert(key != NULL);
|
||||||
|
|
||||||
|
slen = buf_getint(buf);
|
||||||
|
if (slen != 64 || buf->len - buf->pos < slen) {
|
||||||
|
TRACE(("leave buf_sk_ed25519_verify: bad size"))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
s = buf_getptr(buf, slen);
|
||||||
|
buf_incrpos(buf, slen);
|
||||||
|
|
||||||
|
flags = buf_getbyte (buf);
|
||||||
|
counter = buf_getint (buf);
|
||||||
|
sk_buffer = buf_new (2*SHA256_HASH_SIZE+5);
|
||||||
|
sha256_init (&hs);
|
||||||
|
sha256_process (&hs, app, applen);
|
||||||
|
sha256_done (&hs, hash);
|
||||||
|
buf_putbytes (sk_buffer, hash, sizeof (hash));
|
||||||
|
buf_putbyte (sk_buffer, flags);
|
||||||
|
buf_putint (sk_buffer, counter);
|
||||||
|
sha256_init (&hs);
|
||||||
|
sha256_process (&hs, data_buf->data, data_buf->len);
|
||||||
|
sha256_done (&hs, hash);
|
||||||
|
buf_putbytes (sk_buffer, hash, sizeof (hash));
|
||||||
|
|
||||||
|
if (dropbear_ed25519_verify(sk_buffer->data, sk_buffer->len,
|
||||||
|
s, slen, key->pub) == 0) {
|
||||||
|
/* signature is valid */
|
||||||
|
TRACE(("leave buf_sk_ed25519_verify: success!"))
|
||||||
|
ret = DROPBEAR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (sk_buffer) {
|
||||||
|
buf_free(sk_buffer);
|
||||||
|
}
|
||||||
|
TRACE(("leave buf_sk_ed25519_verify: ret %d", ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DROPBEAR_SK_ED25519 */
|
15
sk-ed25519.h
Normal file
15
sk-ed25519.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DROPBEAR_SK_ED25519_H_
|
||||||
|
#define DROPBEAR_SK_ED25519_H_
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "ed25519.h"
|
||||||
|
|
||||||
|
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DROPBEAR_SK_ED25519_H_ */
|
@ -668,6 +668,12 @@ void load_all_hostkeys() {
|
|||||||
any_keys = 1;
|
any_keys = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if DROPBEAR_SK_ECDSA
|
||||||
|
disablekey(DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256);
|
||||||
|
#endif
|
||||||
|
#if DROPBEAR_SK_ED25519
|
||||||
|
disablekey(DROPBEAR_SIGNKEY_SK_ED25519);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!any_keys) {
|
if (!any_keys) {
|
||||||
dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey.");
|
dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey.");
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
#define DROPBEAR_MAX_PASSWORD_LEN 100
|
#define DROPBEAR_MAX_PASSWORD_LEN 100
|
||||||
|
|
||||||
#define SHA1_HASH_SIZE 20
|
#define SHA1_HASH_SIZE 20
|
||||||
|
#define SHA256_HASH_SIZE 32
|
||||||
#define MD5_HASH_SIZE 16
|
#define MD5_HASH_SIZE 16
|
||||||
#define MAX_HASH_SIZE 64 /* sha512 */
|
#define MAX_HASH_SIZE 64 /* sha512 */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user