mirror of
https://github.com/clearml/dropbear
synced 2025-04-07 22:24:21 +00:00
use sigtype where appropriate
This commit is contained in:
parent
90cfbe1f7a
commit
7dc2f36c3e
1
algo.h
1
algo.h
@ -112,7 +112,6 @@ struct dropbear_kex {
|
||||
const struct ltc_hash_descriptor *hash_desc;
|
||||
};
|
||||
|
||||
int have_algo(const char* algo, size_t algolen, const algo_type algos[]);
|
||||
void buf_put_algolist(buffer * buf, const algo_type localalgos[]);
|
||||
|
||||
enum kexguess2_used {
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "agentfwd.h"
|
||||
|
||||
#if DROPBEAR_CLI_PUBKEY_AUTH
|
||||
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
|
||||
static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign);
|
||||
|
||||
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
|
||||
* We use it to remove the key we tried from the list */
|
||||
@ -58,14 +58,15 @@ void recv_msg_userauth_pk_ok() {
|
||||
buffer* keybuf = NULL;
|
||||
char* algotype = NULL;
|
||||
unsigned int algolen;
|
||||
enum signkey_type keytype;
|
||||
enum signkey_type sigtype, keytype;
|
||||
unsigned int remotelen;
|
||||
|
||||
TRACE(("enter recv_msg_userauth_pk_ok"))
|
||||
|
||||
algotype = buf_getstring(ses.payload, &algolen);
|
||||
keytype = signkey_type_from_name(algotype, algolen);
|
||||
TRACE(("recv_msg_userauth_pk_ok: type %d", keytype))
|
||||
sigtype = signature_type_from_name(algotype, algolen);
|
||||
keytype = signkey_type_from_signature(sigtype);
|
||||
TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
|
||||
m_free(algotype);
|
||||
|
||||
keybuf = buf_new(MAX_PUBKEY_SIZE);
|
||||
@ -120,9 +121,10 @@ void recv_msg_userauth_pk_ok() {
|
||||
TRACE(("leave recv_msg_userauth_pk_ok"))
|
||||
}
|
||||
|
||||
void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
|
||||
static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype,
|
||||
const buffer *data_buf) {
|
||||
#if DROPBEAR_CLI_AGENTFWD
|
||||
// TODO: rsa-sha256 agent
|
||||
if (key->source == SIGNKEY_SOURCE_AGENT) {
|
||||
/* Format the agent signature ourselves, as buf_put_sign would. */
|
||||
buffer *sigblob;
|
||||
@ -133,16 +135,16 @@ void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
|
||||
} else
|
||||
#endif /* DROPBEAR_CLI_AGENTFWD */
|
||||
{
|
||||
buf_put_sign(buf, key, type, data_buf);
|
||||
buf_put_sign(buf, key, sigtype, data_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: make it take an agent reference to use as well */
|
||||
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
||||
static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign) {
|
||||
|
||||
const char *algoname = NULL;
|
||||
unsigned int algolen;
|
||||
buffer* sigbuf = NULL;
|
||||
enum signkey_type keytype = signkey_type_from_signature(sigtype);
|
||||
|
||||
TRACE(("enter send_msg_userauth_pubkey"))
|
||||
CHECKCLEARTOWRITE();
|
||||
@ -160,10 +162,9 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
||||
|
||||
buf_putbyte(ses.writepayload, realsign);
|
||||
|
||||
algoname = signkey_name_from_type(type, &algolen);
|
||||
|
||||
algoname = signature_name_from_type(sigtype, &algolen);
|
||||
buf_putstring(ses.writepayload, algoname, algolen);
|
||||
buf_put_pub_key(ses.writepayload, key, type);
|
||||
buf_put_pub_key(ses.writepayload, key, keytype);
|
||||
|
||||
if (realsign) {
|
||||
TRACE(("realsign"))
|
||||
@ -172,7 +173,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
||||
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
|
||||
buf_putbufstring(sigbuf, ses.session_id);
|
||||
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
||||
cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
|
||||
cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
|
||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||
}
|
||||
|
||||
@ -195,8 +196,15 @@ int cli_auth_pubkey() {
|
||||
|
||||
if (cli_opts.privkeys->first) {
|
||||
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
|
||||
enum signkey_type sigtype = key->type;
|
||||
/* Send a trial request */
|
||||
send_msg_userauth_pubkey(key, key->type, 0);
|
||||
#if DROPBEAR_RSA && DROPBEAR_RSA_SHA256
|
||||
// TODO: use ext-info to choose rsa kind
|
||||
if (sigtype == DROPBEAR_SIGNKEY_RSA) {
|
||||
sigtype = DROPBEAR_SIGNKEY_RSA_SHA256;
|
||||
}
|
||||
#endif
|
||||
send_msg_userauth_pubkey(key, sigtype, 0);
|
||||
cli_ses.lastprivkey = key;
|
||||
TRACE(("leave cli_auth_pubkey-success"))
|
||||
return 1;
|
||||
|
11
cli-kex.c
11
cli-kex.c
@ -94,7 +94,7 @@ void send_msg_kexdh_init() {
|
||||
void recv_msg_kexdh_reply() {
|
||||
|
||||
sign_key *hostkey = NULL;
|
||||
unsigned int type, keybloblen;
|
||||
unsigned int keytype, keybloblen;
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"))
|
||||
@ -102,8 +102,8 @@ void recv_msg_kexdh_reply() {
|
||||
if (cli_ses.kex_state != KEXDH_INIT_SENT) {
|
||||
dropbear_exit("Received out-of-order kexdhreply");
|
||||
}
|
||||
type = ses.newkeys->algo_hostkey;
|
||||
TRACE(("type is %d", type))
|
||||
keytype = ses.newkeys->algo_hostkey;
|
||||
TRACE(("keytype is %d", keytype))
|
||||
|
||||
hostkey = new_sign_key();
|
||||
keybloblen = buf_getint(ses.payload);
|
||||
@ -114,7 +114,7 @@ void recv_msg_kexdh_reply() {
|
||||
checkhostkey(keyblob, keybloblen);
|
||||
}
|
||||
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) {
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &keytype) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting pubkey"))
|
||||
dropbear_exit("Bad KEX packet");
|
||||
}
|
||||
@ -173,7 +173,8 @@ void recv_msg_kexdh_reply() {
|
||||
#endif
|
||||
|
||||
cli_ses.param_kex_algo = NULL;
|
||||
if (buf_verify(ses.payload, hostkey, ses.hash) != DROPBEAR_SUCCESS) {
|
||||
if (buf_verify(ses.payload, hostkey, ses.newkeys->algo_signature,
|
||||
ses.hash) != DROPBEAR_SUCCESS) {
|
||||
dropbear_exit("Bad hostkey signature");
|
||||
}
|
||||
|
||||
|
@ -237,8 +237,13 @@ algo_type sshhostkey[] = {
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
{"rsa-sha2-256", DROPBEAR_SIGNKEY_RSA_SHA256, NULL, 1, NULL},
|
||||
#endif
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_DSS
|
||||
{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
|
||||
#endif
|
||||
@ -311,24 +316,6 @@ algo_type sshkex[] = {
|
||||
{NULL, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/* algolen specifies the length of algo, algos is our local list to match
|
||||
* against.
|
||||
* Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
|
||||
* otherwise */
|
||||
int have_algo(const char* algo, size_t algolen, const algo_type algos[]) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; algos[i].name != NULL; i++) {
|
||||
if (strlen(algos[i].name) == algolen
|
||||
&& (strncmp(algos[i].name, algo, algolen) == 0)) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
/* Output a comma separated list of algorithms to a buffer */
|
||||
void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
|
||||
|
||||
|
@ -111,7 +111,8 @@ void send_msg_kexinit() {
|
||||
|
||||
if (ses.send_kex_first_guess) {
|
||||
ses.newkeys->algo_kex = sshkex[0].data;
|
||||
ses.newkeys->algo_hostkey = sshhostkey[0].val;
|
||||
ses.newkeys->algo_signature = sshhostkey[0].val;
|
||||
ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
|
||||
ses.send_kex_first_guess();
|
||||
}
|
||||
|
||||
@ -152,6 +153,7 @@ static void switch_keys() {
|
||||
TRACE(("switch_keys done"))
|
||||
ses.keys->algo_kex = ses.newkeys->algo_kex;
|
||||
ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
|
||||
ses.keys->algo_signature = ses.newkeys->algo_signature;
|
||||
ses.keys->allow_compress = 0;
|
||||
m_free(ses.newkeys);
|
||||
ses.newkeys = NULL;
|
||||
@ -847,8 +849,9 @@ static void read_kex_algos() {
|
||||
erralgo = "hostkey";
|
||||
goto error;
|
||||
}
|
||||
TRACE(("hostkey algo %s", algo->name))
|
||||
ses.newkeys->algo_hostkey = algo->val;
|
||||
TRACE(("signature algo %s", algo->name))
|
||||
ses.newkeys->algo_signature = algo->val;
|
||||
ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
|
||||
|
||||
/* encryption_algorithms_client_to_server */
|
||||
c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, NULL, NULL);
|
||||
|
2
dss.h
2
dss.h
@ -30,7 +30,7 @@
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
|
||||
typedef struct {
|
||||
typedef struct dropbear_DSS_Key {
|
||||
|
||||
mp_int* p;
|
||||
mp_int* q;
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#define CURVE25519_LEN 32
|
||||
|
||||
typedef struct {
|
||||
typedef struct dropbear_ED25519_Key {
|
||||
|
||||
unsigned char priv[CURVE25519_LEN];
|
||||
unsigned char pub[CURVE25519_LEN];
|
||||
|
@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
unsigned int algolen;
|
||||
char* algoname = buf_getstring(keyblob, &algolen);
|
||||
|
||||
if (have_algo(algoname, algolen, sshhostkey) == DROPBEAR_FAILURE) {
|
||||
if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) {
|
||||
dropbear_exit("fuzzer imagined a bogus algorithm");
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "dbutil.h"
|
||||
#include "ecc.h"
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
#include "dss.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
static const unsigned char OSSH_PKEY_BLOB[] =
|
||||
"openssh-key-v1\0" /* AUTH_MAGIC */
|
||||
|
101
rsa.c
101
rsa.c
@ -35,11 +35,16 @@
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "dbrandom.h"
|
||||
#include "signkey.h"
|
||||
|
||||
#if DROPBEAR_RSA
|
||||
|
||||
#if !(DROPBEAR_RSA_SHA1 || DROPBEAR_RSA_SHA256)
|
||||
#error Somehow RSA was enabled with neither DROPBEAR_RSA_SHA1 nor DROPBEAR_RSA_SHA256
|
||||
#endif
|
||||
|
||||
static void rsa_pad_em(const dropbear_rsa_key * key,
|
||||
const buffer *data_buf, mp_int * rsa_em);
|
||||
const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype);
|
||||
|
||||
/* Load a public rsa key from a buffer, initialising the values.
|
||||
* The key will have the same format as buf_put_rsa_key.
|
||||
@ -191,7 +196,8 @@ void buf_put_rsa_priv_key(buffer* buf, const dropbear_rsa_key *key) {
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
/* Verify a signature in buf, made on data by the key given.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, const buffer *data_buf) {
|
||||
int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key,
|
||||
enum signkey_type sigtype, const buffer *data_buf) {
|
||||
unsigned int slen;
|
||||
DEF_MP_INT(rsa_s);
|
||||
DEF_MP_INT(rsa_mdash);
|
||||
@ -223,7 +229,7 @@ int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, const buffer *data
|
||||
}
|
||||
|
||||
/* create the magic PKCS padded value */
|
||||
rsa_pad_em(key, data_buf, &rsa_em);
|
||||
rsa_pad_em(key, data_buf, &rsa_em, sigtype);
|
||||
|
||||
if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) {
|
||||
TRACE(("failed exptmod rsa_s"))
|
||||
@ -246,8 +252,10 @@ out:
|
||||
|
||||
/* Sign the data presented with key, writing the signature contents
|
||||
* to the buffer */
|
||||
void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, const buffer *data_buf) {
|
||||
unsigned int nsize, ssize;
|
||||
void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key,
|
||||
enum signkey_type sigtype, const buffer *data_buf) {
|
||||
const char *name = NULL;
|
||||
unsigned int nsize, ssize, namelen = 0;
|
||||
unsigned int i;
|
||||
DEF_MP_INT(rsa_s);
|
||||
DEF_MP_INT(rsa_tmp1);
|
||||
@ -259,7 +267,7 @@ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, const buffer *da
|
||||
|
||||
m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
|
||||
|
||||
rsa_pad_em(key, data_buf, &rsa_tmp1);
|
||||
rsa_pad_em(key, data_buf, &rsa_tmp1, sigtype);
|
||||
|
||||
/* the actual signing of the padded data */
|
||||
|
||||
@ -311,7 +319,8 @@ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, const buffer *da
|
||||
mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
|
||||
|
||||
/* create the signature to return */
|
||||
buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
|
||||
name = signature_name_from_type(sigtype, &namelen);
|
||||
buf_putstring(buf, name, namelen);
|
||||
|
||||
nsize = mp_unsigned_bin_size(key->n);
|
||||
|
||||
@ -340,51 +349,73 @@ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, const buffer *da
|
||||
TRACE(("leave buf_put_rsa_sign"))
|
||||
}
|
||||
|
||||
/* Creates the message value as expected by PKCS, see rfc2437 etc */
|
||||
/* format to be padded to is:
|
||||
* EM = 01 | FF* | 00 | prefix | hash
|
||||
*
|
||||
* where FF is repeated enough times to make EM one byte
|
||||
* shorter than the size of key->n
|
||||
*
|
||||
* prefix is the ASN1 designator prefix,
|
||||
* hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
|
||||
*
|
||||
* rsa_em must be a pointer to an initialised mp_int.
|
||||
*/
|
||||
/* Creates the message value as expected by PKCS,
|
||||
see rfc8017 section 9.2 */
|
||||
static void rsa_pad_em(const dropbear_rsa_key * key,
|
||||
const buffer *data_buf, mp_int * rsa_em) {
|
||||
const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype) {
|
||||
/* EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
PS is padding of 0xff to make EM the size of key->n
|
||||
|
||||
/* ASN1 designator (including the 0x00 preceding) */
|
||||
const unsigned char rsa_asn1_magic[] =
|
||||
{0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
|
||||
T is the DER encoding of the hash alg (sha1 or sha256)
|
||||
*/
|
||||
|
||||
/* From rfc8017 page 46 */
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
const unsigned char T_sha1[] =
|
||||
{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
|
||||
0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
|
||||
const unsigned int RSA_ASN1_MAGIC_LEN = 16;
|
||||
#endif
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
const unsigned char T_sha256[] =
|
||||
{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
|
||||
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
|
||||
#endif
|
||||
|
||||
int Tlen = 0;
|
||||
const unsigned char *T = NULL;
|
||||
const struct ltc_hash_descriptor *hash_desc = NULL;
|
||||
buffer * rsa_EM = NULL;
|
||||
hash_state hs;
|
||||
unsigned int nsize;
|
||||
|
||||
switch (sigtype) {
|
||||
#if DROPBEAR_RSA_SHA1
|
||||
case DROPBEAR_SIGNKEY_RSA:
|
||||
Tlen = sizeof(T_sha1);
|
||||
T = T_sha1;
|
||||
hash_desc = &sha1_desc;
|
||||
break;
|
||||
#endif
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
case DROPBEAR_SIGNKEY_RSA_SHA256:
|
||||
Tlen = sizeof(T_sha256);
|
||||
T = T_sha256;
|
||||
hash_desc = &sha256_desc;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
dropbear_assert(key != NULL);
|
||||
nsize = mp_unsigned_bin_size(key->n);
|
||||
|
||||
rsa_EM = buf_new(nsize-1);
|
||||
rsa_EM = buf_new(nsize);
|
||||
/* type byte */
|
||||
buf_putbyte(rsa_EM, 0x00);
|
||||
buf_putbyte(rsa_EM, 0x01);
|
||||
/* Padding with 0xFF bytes */
|
||||
while(rsa_EM->pos != rsa_EM->size - RSA_ASN1_MAGIC_LEN - SHA1_HASH_SIZE) {
|
||||
/* Padding with PS 0xFF bytes */
|
||||
while(rsa_EM->pos != rsa_EM->size - (1 + Tlen + hash_desc->hashsize)) {
|
||||
buf_putbyte(rsa_EM, 0xff);
|
||||
}
|
||||
buf_putbyte(rsa_EM, 0x00);
|
||||
/* Magic ASN1 stuff */
|
||||
memcpy(buf_getwriteptr(rsa_EM, RSA_ASN1_MAGIC_LEN),
|
||||
rsa_asn1_magic, RSA_ASN1_MAGIC_LEN);
|
||||
buf_incrwritepos(rsa_EM, RSA_ASN1_MAGIC_LEN);
|
||||
buf_putbytes(rsa_EM, T, Tlen);
|
||||
|
||||
/* The hash of the data */
|
||||
sha1_init(&hs);
|
||||
sha1_process(&hs, data_buf->data, data_buf->len);
|
||||
sha1_done(&hs, buf_getwriteptr(rsa_EM, SHA1_HASH_SIZE));
|
||||
buf_incrwritepos(rsa_EM, SHA1_HASH_SIZE);
|
||||
hash_desc->init(&hs);
|
||||
hash_desc->process(&hs, data_buf->data, data_buf->len);
|
||||
hash_desc->done(&hs, buf_getwriteptr(rsa_EM, hash_desc->hashsize));
|
||||
buf_incrwritepos(rsa_EM, hash_desc->hashsize);
|
||||
|
||||
dropbear_assert(rsa_EM->pos == rsa_EM->size);
|
||||
|
||||
|
11
rsa.h
11
rsa.h
@ -26,13 +26,12 @@
|
||||
#define DROPBEAR_RSA_H_
|
||||
|
||||
#include "includes.h"
|
||||
#include "signkey.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#if DROPBEAR_RSA
|
||||
|
||||
#define RSA_SIGNATURE_SIZE (4+7+4+40)
|
||||
|
||||
typedef struct {
|
||||
typedef struct dropbear_RSA_Key {
|
||||
|
||||
mp_int* n;
|
||||
mp_int* e;
|
||||
@ -43,9 +42,11 @@ typedef struct {
|
||||
|
||||
} dropbear_rsa_key;
|
||||
|
||||
void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, const buffer *data_buf);
|
||||
void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key,
|
||||
enum signkey_type sigtype, const buffer *data_buf);
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, const buffer *data_buf);
|
||||
int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key,
|
||||
enum signkey_type sigtype, const buffer *data_buf);
|
||||
#endif
|
||||
int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key);
|
||||
int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key);
|
||||
|
@ -92,7 +92,8 @@ struct key_context {
|
||||
struct key_context_directional trans;
|
||||
|
||||
const struct dropbear_kex *algo_kex;
|
||||
int algo_hostkey;
|
||||
int algo_hostkey; /* server key type */
|
||||
int algo_signature; /* server signature type */
|
||||
|
||||
int allow_compress; /* whether compression has started (useful in
|
||||
zlib@openssh.com delayed compression case) */
|
||||
|
78
signkey.c
78
signkey.c
@ -28,6 +28,9 @@
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "ecdsa.h"
|
||||
#include "rsa.h"
|
||||
#include "dss.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
|
||||
#if DROPBEAR_RSA
|
||||
@ -44,6 +47,7 @@ static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = {
|
||||
#if DROPBEAR_ED25519
|
||||
"ssh-ed25519",
|
||||
#endif /* DROPBEAR_ED25519 */
|
||||
/* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */
|
||||
};
|
||||
|
||||
/* malloc a new sign_key and set the dss and rsa keys to NULL */
|
||||
@ -105,6 +109,38 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen)
|
||||
return DROPBEAR_SIGNKEY_NONE;
|
||||
}
|
||||
|
||||
/* Special case for rsa-sha2-256. This could be generalised if more
|
||||
signature names are added that aren't 1-1 with public key names */
|
||||
const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen) {
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
if (type == DROPBEAR_SIGNKEY_RSA_SHA256) {
|
||||
*namelen = strlen(SSH_SIGNKEY_RSA_SHA256);
|
||||
return SSH_SIGNKEY_RSA_SHA256;
|
||||
}
|
||||
#endif
|
||||
return signkey_name_from_type(type, namelen);
|
||||
}
|
||||
|
||||
enum signkey_type signature_type_from_name(const char* name, unsigned int namelen) {
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
if (namelen == strlen(SSH_SIGNKEY_RSA_SHA256)
|
||||
&& memcmp(name, SSH_SIGNKEY_RSA_SHA256, namelen) == 0) {
|
||||
return DROPBEAR_SIGNKEY_RSA_SHA256;
|
||||
}
|
||||
#endif
|
||||
return signkey_type_from_name(name, namelen);
|
||||
}
|
||||
|
||||
enum signkey_type signkey_type_from_signature(enum signkey_type sigtype) {
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
if (sigtype == DROPBEAR_SIGNKEY_RSA_SHA256) {
|
||||
return DROPBEAR_SIGNKEY_RSA;
|
||||
}
|
||||
#endif
|
||||
assert(sigtype < DROPBEAR_SIGNKEY_NUM_NAMED);
|
||||
return sigtype;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the key part specific to "type".
|
||||
Be sure to check both (ret != NULL) and (*ret != NULL) */
|
||||
void **
|
||||
@ -526,31 +562,31 @@ char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloble
|
||||
#endif
|
||||
}
|
||||
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type,
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype,
|
||||
const buffer *data_buf) {
|
||||
buffer *sigblob;
|
||||
sigblob = buf_new(MAX_PUBKEY_SIZE);
|
||||
buffer *sigblob = buf_new(MAX_PUBKEY_SIZE);
|
||||
enum signkey_type keytype = signkey_type_from_signature(sigtype);
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
if (type == DROPBEAR_SIGNKEY_DSS) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
buf_put_dss_sign(sigblob, key->dsskey, data_buf);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
if (type == DROPBEAR_SIGNKEY_RSA) {
|
||||
buf_put_rsa_sign(sigblob, key->rsakey, data_buf);
|
||||
if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
||||
buf_put_rsa_sign(sigblob, key->rsakey, sigtype, data_buf);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
buf_put_ecdsa_sign(sigblob, *eck, data_buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519) {
|
||||
buf_put_ed25519_sign(sigblob, key->ed25519key, data_buf);
|
||||
}
|
||||
#endif
|
||||
@ -567,21 +603,27 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type,
|
||||
* If FAILURE is returned, the position of
|
||||
* buf is undefined. If SUCCESS is returned, buf will be positioned after the
|
||||
* signature blob */
|
||||
int buf_verify(buffer * buf, sign_key *key, const buffer *data_buf) {
|
||||
int buf_verify(buffer * buf, sign_key *key, enum signkey_type expect_sigtype, const buffer *data_buf) {
|
||||
|
||||
char *type_name = NULL;
|
||||
unsigned int type_name_len = 0;
|
||||
enum signkey_type type;
|
||||
enum signkey_type sigtype, keytype;
|
||||
|
||||
TRACE(("enter buf_verify"))
|
||||
|
||||
buf_getint(buf); /* blob length */
|
||||
type_name = buf_getstring(buf, &type_name_len);
|
||||
type = signkey_type_from_name(type_name, type_name_len);
|
||||
sigtype = signature_type_from_name(type_name, type_name_len);
|
||||
m_free(type_name);
|
||||
|
||||
if (expect_sigtype != DROPBEAR_SIGNKEY_ANY
|
||||
&& expect_sigtype != sigtype) {
|
||||
dropbear_exit("Non-matching signing type");
|
||||
}
|
||||
|
||||
keytype = signkey_type_from_signature(sigtype);
|
||||
#if DROPBEAR_DSS
|
||||
if (type == DROPBEAR_SIGNKEY_DSS) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_DSS) {
|
||||
if (key->dsskey == NULL) {
|
||||
dropbear_exit("No DSS key to verify signature");
|
||||
}
|
||||
@ -590,23 +632,23 @@ int buf_verify(buffer * buf, sign_key *key, const buffer *data_buf) {
|
||||
#endif
|
||||
|
||||
#if DROPBEAR_RSA
|
||||
if (type == DROPBEAR_SIGNKEY_RSA) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_RSA) {
|
||||
if (key->rsakey == NULL) {
|
||||
dropbear_exit("No RSA key to verify signature");
|
||||
}
|
||||
return buf_rsa_verify(buf, key->rsakey, data_buf);
|
||||
return buf_rsa_verify(buf, key->rsakey, sigtype, data_buf);
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
if (signkey_is_ecdsa(type)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, type);
|
||||
if (signkey_is_ecdsa(keytype)) {
|
||||
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
|
||||
if (eck && *eck) {
|
||||
return buf_ecdsa_verify(buf, *eck, data_buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
if (type == DROPBEAR_SIGNKEY_ED25519) {
|
||||
if (keytype == DROPBEAR_SIGNKEY_ED25519) {
|
||||
if (key->ed25519key == NULL) {
|
||||
dropbear_exit("No Ed25519 key to verify signature");
|
||||
}
|
||||
|
24
signkey.h
24
signkey.h
@ -26,9 +26,11 @@
|
||||
#define DROPBEAR_SIGNKEY_H_
|
||||
|
||||
#include "buffer.h"
|
||||
#include "dss.h"
|
||||
#include "rsa.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct dropbear_DSS_Key;
|
||||
struct dropbear_RSA_Key;
|
||||
struct dropbear_ED25519_Key;
|
||||
|
||||
enum signkey_type {
|
||||
#if DROPBEAR_RSA
|
||||
@ -47,6 +49,9 @@ enum signkey_type {
|
||||
#endif
|
||||
DROPBEAR_SIGNKEY_NUM_NAMED,
|
||||
DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */
|
||||
#if DROPBEAR_RSA_SHA256
|
||||
DROPBEAR_SIGNKEY_RSA_SHA256, /* rsa-sha2-256 signature. has a ssh-rsa key */
|
||||
#endif
|
||||
DROPBEAR_SIGNKEY_ANY = 80,
|
||||
DROPBEAR_SIGNKEY_NONE = 90,
|
||||
};
|
||||
@ -66,10 +71,10 @@ struct SIGN_key {
|
||||
char *filename;
|
||||
|
||||
#if DROPBEAR_DSS
|
||||
dropbear_dss_key * dsskey;
|
||||
struct dropbear_DSS_Key * dsskey;
|
||||
#endif
|
||||
#if DROPBEAR_RSA
|
||||
dropbear_rsa_key * rsakey;
|
||||
struct dropbear_RSA_Key * rsakey;
|
||||
#endif
|
||||
#if DROPBEAR_ECDSA
|
||||
#if DROPBEAR_ECC_256
|
||||
@ -83,7 +88,7 @@ struct SIGN_key {
|
||||
#endif
|
||||
#endif
|
||||
#if DROPBEAR_ED25519
|
||||
dropbear_ed25519_key * ed25519key;
|
||||
struct dropbear_ED25519_Key * ed25519key;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -92,14 +97,17 @@ typedef struct SIGN_key sign_key;
|
||||
sign_key * new_sign_key(void);
|
||||
const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen);
|
||||
enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen);
|
||||
const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen);
|
||||
enum signkey_type signature_type_from_name(const char* name, unsigned int namelen);
|
||||
enum signkey_type signkey_type_from_signature(enum signkey_type sigtype);
|
||||
int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type);
|
||||
int buf_get_priv_key(buffer* buf, sign_key *key, enum signkey_type *type);
|
||||
void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type);
|
||||
void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type);
|
||||
void sign_key_free(sign_key *key);
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type type, const buffer *data_buf);
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, const buffer *data_buf);
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_verify(buffer * buf, sign_key *key, const buffer *data_buf);
|
||||
int buf_verify(buffer * buf, sign_key *key, enum signkey_type type, const buffer *data_buf);
|
||||
char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
||||
#endif
|
||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
|
4
ssh.h
4
ssh.h
@ -100,13 +100,15 @@
|
||||
#define SSH_SERVICE_CONNECTION "ssh-connection"
|
||||
#define SSH_SERVICE_CONNECTION_LEN 14
|
||||
|
||||
/* public key types */
|
||||
/* public/signature key types */
|
||||
#define SSH_SIGNKEY_DSS "ssh-dss"
|
||||
#define SSH_SIGNKEY_DSS_LEN 7
|
||||
#define SSH_SIGNKEY_RSA "ssh-rsa"
|
||||
#define SSH_SIGNKEY_RSA_LEN 7
|
||||
#define SSH_SIGNKEY_ED25519 "ssh-ed25519"
|
||||
#define SSH_SIGNKEY_ED25519_LEN 11
|
||||
/* signature type */
|
||||
#define SSH_SIGNKEY_RSA_SHA256 "rsa-sha2-256"
|
||||
|
||||
/* Agent commands. These aren't part of the spec, and are defined
|
||||
* only on the openssh implementation. */
|
||||
|
@ -70,10 +70,10 @@
|
||||
#define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */
|
||||
#define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */
|
||||
|
||||
static int checkpubkey(const char* algo, unsigned int algolen,
|
||||
static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen);
|
||||
static int checkpubkeyperms(void);
|
||||
static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen,
|
||||
static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen);
|
||||
static int checkfileperm(char * filename);
|
||||
|
||||
@ -82,16 +82,18 @@ static int checkfileperm(char * filename);
|
||||
void svr_auth_pubkey(int valid_user) {
|
||||
|
||||
unsigned char testkey; /* whether we're just checking if a key is usable */
|
||||
char* algo = NULL; /* pubkey algo */
|
||||
unsigned int algolen;
|
||||
char* sigalgo = NULL;
|
||||
unsigned int sigalgolen;
|
||||
const char* keyalgo;
|
||||
unsigned int keyalgolen;
|
||||
unsigned char* keyblob = NULL;
|
||||
unsigned int keybloblen;
|
||||
unsigned int sign_payload_length;
|
||||
buffer * signbuf = NULL;
|
||||
sign_key * key = NULL;
|
||||
char* fp = NULL;
|
||||
enum signkey_type type = -1;
|
||||
int auth_failure = 1;
|
||||
enum signkey_type sigtype, keytype;
|
||||
int auth_failure = 1;
|
||||
|
||||
TRACE(("enter pubkeyauth"))
|
||||
|
||||
@ -99,7 +101,11 @@ void svr_auth_pubkey(int valid_user) {
|
||||
* actual attempt*/
|
||||
testkey = (buf_getbool(ses.payload) == 0);
|
||||
|
||||
algo = buf_getstring(ses.payload, &algolen);
|
||||
sigalgo = buf_getstring(ses.payload, &sigalgolen);
|
||||
sigtype = signature_type_from_name(sigalgo, sigalgolen);
|
||||
keytype = signkey_type_from_signature(sigtype);
|
||||
keyalgo = signkey_name_from_type(keytype, &keyalgolen);
|
||||
|
||||
keybloblen = buf_getint(ses.payload);
|
||||
keyblob = buf_getptr(ses.payload, keybloblen);
|
||||
|
||||
@ -117,8 +123,8 @@ void svr_auth_pubkey(int valid_user) {
|
||||
if (svr_ses.plugin_instance->checkpubkey(
|
||||
svr_ses.plugin_instance,
|
||||
&ses.plugin_session,
|
||||
algo,
|
||||
algolen,
|
||||
keyalgo,
|
||||
keyalgolen,
|
||||
keyblob,
|
||||
keybloblen,
|
||||
ses.authstate.username) == DROPBEAR_SUCCESS) {
|
||||
@ -146,7 +152,7 @@ void svr_auth_pubkey(int valid_user) {
|
||||
#endif
|
||||
/* check if the key is valid */
|
||||
if (auth_failure) {
|
||||
auth_failure = checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE;
|
||||
auth_failure = checkpubkey(keyalgo, keyalgolen, keyblob, keybloblen) == DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
if (auth_failure) {
|
||||
@ -156,7 +162,7 @@ void svr_auth_pubkey(int valid_user) {
|
||||
|
||||
/* let them know that the key is ok to use */
|
||||
if (testkey) {
|
||||
send_msg_userauth_pk_ok(algo, algolen, keyblob, keybloblen);
|
||||
send_msg_userauth_pk_ok(sigalgo, sigalgolen, keyblob, keybloblen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -164,8 +170,7 @@ void svr_auth_pubkey(int valid_user) {
|
||||
|
||||
/* get the key */
|
||||
key = new_sign_key();
|
||||
type = DROPBEAR_SIGNKEY_ANY;
|
||||
if (buf_get_pub_key(ses.payload, key, &type) == DROPBEAR_FAILURE) {
|
||||
if (buf_get_pub_key(ses.payload, key, &keytype) == DROPBEAR_FAILURE) {
|
||||
send_msg_userauth_failure(0, 1);
|
||||
goto out;
|
||||
}
|
||||
@ -188,7 +193,7 @@ void svr_auth_pubkey(int valid_user) {
|
||||
|
||||
/* ... and finally verify the signature */
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
if (buf_verify(ses.payload, key, signbuf) == DROPBEAR_SUCCESS) {
|
||||
if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) {
|
||||
dropbear_log(LOG_NOTICE,
|
||||
"Pubkey auth succeeded for '%s' with key %s from %s",
|
||||
ses.authstate.pw_name, fp, svr_ses.addrstring);
|
||||
@ -213,8 +218,8 @@ out:
|
||||
if (signbuf) {
|
||||
buf_free(signbuf);
|
||||
}
|
||||
if (algo) {
|
||||
m_free(algo);
|
||||
if (sigalgo) {
|
||||
m_free(sigalgo);
|
||||
}
|
||||
if (key) {
|
||||
sign_key_free(key);
|
||||
@ -230,14 +235,14 @@ out:
|
||||
/* Reply that the key is valid for auth, this is sent when the user sends
|
||||
* a straight copy of their pubkey to test, to avoid having to perform
|
||||
* expensive signing operations with a worthless key */
|
||||
static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen,
|
||||
static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
TRACE(("enter send_msg_userauth_pk_ok"))
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK);
|
||||
buf_putstring(ses.writepayload, algo, algolen);
|
||||
buf_putstring(ses.writepayload, sigalgo, sigalgolen);
|
||||
buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen);
|
||||
|
||||
encrypt_packet();
|
||||
@ -354,7 +359,7 @@ out:
|
||||
/* Checks whether a specified publickey (and associated algorithm) is an
|
||||
* acceptable key for authentication */
|
||||
/* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */
|
||||
static int checkpubkey(const char* algo, unsigned int algolen,
|
||||
static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
|
||||
const unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
FILE * authfile = NULL;
|
||||
@ -368,14 +373,6 @@ static int checkpubkey(const char* algo, unsigned int algolen,
|
||||
|
||||
TRACE(("enter checkpubkey"))
|
||||
|
||||
/* check that we can use the algo */
|
||||
if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) {
|
||||
dropbear_log(LOG_WARNING,
|
||||
"Pubkey auth attempt with unknown algo for '%s' from %s",
|
||||
ses.authstate.pw_name, svr_ses.addrstring);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check file permissions, also whether file exists */
|
||||
if (checkpubkeyperms() == DROPBEAR_FAILURE) {
|
||||
TRACE(("bad authorized_keys permissions, or file doesn't exist"))
|
||||
@ -427,7 +424,7 @@ static int checkpubkey(const char* algo, unsigned int algolen,
|
||||
}
|
||||
line_num++;
|
||||
|
||||
ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen);
|
||||
ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, keyblob, keybloblen);
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
|
||||
|
||||
/* calc the signature */
|
||||
buf_put_sign(ses.writepayload, svr_opts.hostkey,
|
||||
ses.newkeys->algo_hostkey, ses.hash);
|
||||
ses.newkeys->algo_signature, ses.hash);
|
||||
|
||||
/* the SSH_MSG_KEXDH_REPLY is done */
|
||||
encrypt_packet();
|
||||
|
12
sysoptions.h
12
sysoptions.h
@ -139,9 +139,17 @@ If you test it please contact the Dropbear author */
|
||||
* signing operations slightly slower. */
|
||||
#define DROPBEAR_RSA_BLINDING 1
|
||||
|
||||
#ifndef DROPBEAR_RSA_SHA1
|
||||
#define DROPBEAR_RSA_SHA1 DROPBEAR_RSA
|
||||
#endif
|
||||
#ifndef DROPBEAR_RSA_SHA256
|
||||
#define DROPBEAR_RSA_SHA256 DROPBEAR_RSA
|
||||
#endif
|
||||
|
||||
/* hashes which will be linked and registered */
|
||||
#define DROPBEAR_SHA256 ((DROPBEAR_SHA2_256_HMAC) || (DROPBEAR_ECC_256) \
|
||||
|| (DROPBEAR_CURVE25519) || (DROPBEAR_DH_GROUP14_SHA256))
|
||||
#define DROPBEAR_SHA256 ((DROPBEAR_SHA2_256_HMAC) || (DROPBEAR_ECC_256) \
|
||||
|| (DROPBEAR_CURVE25519) || (DROPBEAR_DH_GROUP14_SHA256) \
|
||||
|| (DROPBEAR_RSA_SHA256))
|
||||
#define DROPBEAR_SHA384 (DROPBEAR_ECC_384)
|
||||
/* LTC SHA384 depends on SHA512 */
|
||||
#define DROPBEAR_SHA512 ((DROPBEAR_SHA2_512_HMAC) || (DROPBEAR_ECC_521) \
|
||||
|
Loading…
Reference in New Issue
Block a user