diff options
Diffstat (limited to 'signkey.c')
-rw-r--r-- | signkey.c | 78 |
1 files changed, 60 insertions, 18 deletions
@@ -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"); } |