Skip to content

Commit

Permalink
merge rsa-sha256
Browse files Browse the repository at this point in the history
  • Loading branch information
mkj committed May 25, 2020
2 parents 61267f8 + c917807 commit d277f14
Show file tree
Hide file tree
Showing 36 changed files with 697 additions and 267 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ install:
- autoheader
- ./configure $CONFIGURE_FLAGS CFLAGS="-O2 -Wall -Wno-pointer-sign $WEXTRAFLAGS $EXTRACFLAGS" --prefix="$HOME/inst" || (cat config.log; exit 1)
- if [ "$NOWRITEV" = "1" ]; then sed -i -e s/HAVE_WRITEV/DONT_HAVE_WRITEV/ config.h ; fi
- make lint
- make -j3
- test -z $DO_FUZZ || make fuzzstandalone
# avoid concurrent install, osx/freebsd is racey (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208093)
Expand Down
5 changes: 4 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ $(STATIC_LTC): $(OPTION_HEADERS)
$(STATIC_LTM): $(OPTION_HEADERS)
$(MAKE) -C libtommath

.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean
.PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean lint

ltc-clean:
$(MAKE) -C libtomcrypt clean
Expand All @@ -262,6 +262,9 @@ distclean: clean tidy
tidy:
-rm -f *~ *.gcov */*~

lint:
cd $(srcdir); ./dropbear_lint.sh

## Fuzzing targets

# list of fuzz targets
Expand Down
5 changes: 4 additions & 1 deletion agentfwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@

#if DROPBEAR_CLI_AGENTFWD

/* From OpenSSH authfd.h */
#define SSH_AGENT_RSA_SHA2_256 0x02

/* An agent reply can be reasonably large, as it can
* contain a list of all public keys held by the agent.
* 10000 is arbitrary */
Expand All @@ -40,7 +43,7 @@
/* client functions */
void cli_load_agent_keys(m_list * ret_list);
void agent_buf_sign(buffer *sigblob, sign_key *key,
const buffer *data_buf);
const buffer *data_buf, enum signature_type type);
void cli_setup_agent(const struct Channel *channel);

#ifdef __hpux
Expand Down
18 changes: 7 additions & 11 deletions algo.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ typedef struct Algo_Type algo_type;

/* lists mapping ssh types of algorithms to internal values */
extern algo_type sshkex[];
extern algo_type sshhostkey[];
extern algo_type sigalgs[];
extern algo_type sshciphers[];
extern algo_type sshhashes[];
extern algo_type ssh_compress[];
Expand Down Expand Up @@ -120,21 +120,17 @@ struct dropbear_kex {
const struct ltc_hash_descriptor *hash_desc;
};

int have_algo(const char* algo, size_t algolen, const algo_type algos[]);
/* Includes all algorithms is useall is set */
void buf_put_algolist_all(buffer * buf, const algo_type localalgos[], int useall);
/* Includes "usable" algorithms */
void buf_put_algolist(buffer * buf, const algo_type localalgos[]);

enum kexguess2_used {
KEXGUESS2_LOOK,
KEXGUESS2_NO,
KEXGUESS2_YES,
};

#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
#define KEXGUESS2_ALGO_ID 99


int buf_has_algo(buffer *buf, const char *algo);
algo_type * first_usable_algo(algo_type algos[]);
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
enum kexguess2_used *kexguess2, int *goodguess);
int kexguess2, int *goodguess);

#if DROPBEAR_USER_ALGO_LIST
int check_user_algos(const char* user_algo_list, algo_type * algos,
Expand Down
22 changes: 20 additions & 2 deletions buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,37 @@ char* buf_getstring(buffer* buf, unsigned int *retlen) {
}

/* Return a string as a newly allocated buffer */
buffer * buf_getstringbuf(buffer *buf) {
static buffer * buf_getstringbuf_int(buffer *buf, int incllen) {
buffer *ret = NULL;
unsigned int len = buf_getint(buf);
int extra = 0;
if (len > MAX_STRING_LEN) {
dropbear_exit("String too long");
}
ret = buf_new(len);
if (incllen) {
extra = 4;
}
ret = buf_new(len+extra);
if (incllen) {
buf_putint(ret, len);
}
memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
buf_incrpos(buf, len);
buf_incrlen(ret, len);
buf_setpos(ret, 0);
return ret;
}

/* Return a string as a newly allocated buffer */
buffer * buf_getstringbuf(buffer *buf) {
return buf_getstringbuf_int(buf, 0);
}

/* Returns a string in a new buffer, including the length */
buffer * buf_getbuf(buffer *buf) {
return buf_getstringbuf_int(buf, 1);
}

/* Just increment the buffer position the same as if we'd used buf_getstring,
* but don't bother copying/malloc()ing for it */
void buf_eatstring(buffer *buf) {
Expand Down
1 change: 1 addition & 0 deletions buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ unsigned char* buf_getptr(const buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len);
char* buf_getstring(buffer* buf, unsigned int *retlen);
buffer * buf_getstringbuf(buffer *buf);
buffer * buf_getbuf(buffer *buf);
void buf_eatstring(buffer *buf);
void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const char* str, unsigned int len);
Expand Down
10 changes: 8 additions & 2 deletions cli-agentfwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,12 @@ void cli_load_agent_keys(m_list *ret_list) {
}

void agent_buf_sign(buffer *sigblob, sign_key *key,
const buffer *data_buf) {
const buffer *data_buf, enum signature_type sigtype) {
buffer *request_data = NULL;
buffer *response = NULL;
unsigned int siglen;
int packet_type;
int flags = 0;

/* Request format
byte SSH2_AGENTC_SIGN_REQUEST
Expand All @@ -271,7 +272,12 @@ void agent_buf_sign(buffer *sigblob, sign_key *key,
buf_put_pub_key(request_data, key, key->type);

buf_putbufstring(request_data, data_buf);
buf_putint(request_data, 0);
#if DROPBEAR_RSA_SHA256
if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
flags |= SSH_AGENT_RSA_SHA2_256;
}
#endif
buf_putint(request_data, flags);

response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);

Expand Down
100 changes: 84 additions & 16 deletions cli-authpubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 signature_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 */
Expand All @@ -59,13 +59,15 @@ void recv_msg_userauth_pk_ok() {
char* algotype = NULL;
unsigned int algolen;
enum signkey_type keytype;
enum signature_type sigtype;
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);
Expand Down Expand Up @@ -112,39 +114,40 @@ void recv_msg_userauth_pk_ok() {
TRACE(("matching key"))
/* XXX TODO: if it's an encrypted key, here we ask for their
* password */
send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1);
} else {
TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"))
}

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 signature_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;
sigblob = buf_new(MAX_PUBKEY_SIZE);
agent_buf_sign(sigblob, key, data_buf);
agent_buf_sign(sigblob, key, data_buf, sigtype);
buf_putbufstring(buf, sigblob);
buf_free(sigblob);
} 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 signature_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"))
TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
CHECKCLEARTOWRITE();

buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
Expand All @@ -160,10 +163,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"))
Expand All @@ -172,7 +174,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 */
}

Expand All @@ -182,21 +184,87 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {

/* Returns 1 if a key was tried */
int cli_auth_pubkey() {

enum signature_type sigtype;
TRACE(("enter cli_auth_pubkey"))

#if DROPBEAR_CLI_AGENTFWD
if (!cli_opts.agent_keys_loaded) {
/* get the list of available keys from the agent */
cli_load_agent_keys(cli_opts.privkeys);
cli_opts.agent_keys_loaded = 1;
TRACE(("cli_auth_pubkey: agent keys loaded"))
}
#endif

/* iterate through privkeys to remove ones not allowed in server-sig-algs */
while (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
if (cli_ses.server_sig_algs) {
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA256
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256)
== DROPBEAR_SUCCESS) {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
TRACE(("server-sig-algs allows rsa sha256"))
break;
}
#endif /* DROPBEAR_RSA_SHA256 */
#if DROPBEAR_RSA_SHA1
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNKEY_RSA)
== DROPBEAR_SUCCESS) {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
TRACE(("server-sig-algs allows rsa sha1"))
break;
}
#endif /* DROPBEAR_RSA_SHA256 */
} else
#endif /* DROPBEAR_RSA */
{
/* Not RSA */
const char *name = NULL;
sigtype = signature_type_from_signkey(key->type);
name = signature_name_from_type(sigtype, NULL);
if (buf_has_algo(cli_ses.server_sig_algs, name)
== DROPBEAR_SUCCESS) {
TRACE(("server-sig-algs allows %s", name))
break;
}
}

/* No match, skip this key */
TRACE(("server-sig-algs no match keytype %d, skipping", key->type))
key = list_remove(cli_opts.privkeys->first);
sign_key_free(key);
continue;
} else {
/* Server didn't provide a server-sig-algs list, we'll
assume all except rsa-sha256 are OK. */
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA1
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
TRACE(("no server-sig-algs, using rsa sha1"))
break;
#else
/* only support rsa-sha256, skip this key */
TRACE(("no server-sig-algs, skipping rsa sha256"))
key = list_remove(cli_opts.privkeys->first);
sign_key_free(key);
continue;
#endif
} /* key->type == DROPBEAR_SIGNKEY_RSA */
#endif /* DROPBEAR_RSA */
sigtype = signature_type_from_signkey(key->type);
TRACE(("no server-sig-algs, using key"))
break;
}
}

if (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
/* Send a trial request */
send_msg_userauth_pubkey(key, key->type, 0);
send_msg_userauth_pubkey(key, sigtype, 0);
cli_ses.lastprivkey = key;
TRACE(("leave cli_auth_pubkey-success"))
return 1;
Expand Down
Loading

0 comments on commit d277f14

Please sign in to comment.