From 86fb1d768fc3e9742799da1f5d76fa81620e65ea Mon Sep 17 00:00:00 2001 From: Tobias Heider Date: Wed, 16 Mar 2022 11:41:32 +0100 Subject: [PATCH] Use SHA256 instead of MD5 for key fingerprints Adopt upstream OpenSSH switch to default to SHA256 fingerprints. Switch fingerprint encoding to base64 and append hash name to conform with upstream format since OpenSSH 6.8. --- key.c | 44 ++++++++++++++++++++++++++++++++++++----- key.h | 1 + pam_user_key_allowed2.c | 2 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/key.c b/key.c index dcc5fc8..b3135ba 100644 --- a/key.c +++ b/key.c @@ -281,11 +281,8 @@ pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type, *dgst_raw_length = 0; switch (dgst_type) { - case SSH_FP_MD5: - md = EVP_md5(); - break; - case SSH_FP_SHA1: - md = EVP_sha1(); + case SSH_FP_SHA256: + md = EVP_sha256(); break; default: pamsshagentauth_fatal("key_fingerprint_raw: bad digest type %d", @@ -337,6 +334,31 @@ pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type, return retval; } +static char * +key_fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) +{ + char *ret; + size_t plen = strlen(alg) + 1; + size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; + int r; + + if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) + return NULL; + pamsshagentauth_strlcpy(ret, alg, rlen); + pamsshagentauth_strlcat(ret, ":", rlen); + if (dgst_raw_len == 0) + return ret; + if ((r = pamsshagentauth___b64_ntop(dgst_raw, dgst_raw_len, + ret + plen, rlen - plen)) == -1) { + explicit_bzero(ret, rlen); + free(ret); + return NULL; + } + /* Trim padding characters from end */ + ret[strcspn(ret, "=")] = '\0'; + return ret; +} + static char * key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) { @@ -405,6 +427,7 @@ key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) char * pamsshagentauth_key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) { + const char *dgst_name; char *retval = NULL; u_char *dgst_raw; u_int dgst_raw_len; @@ -416,6 +439,16 @@ pamsshagentauth_key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_re case SSH_FP_HEX: retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); break; + case SSH_FP_BASE64: + switch (dgst_type) { + case SSH_FP_SHA256: + dgst_name = "SHA256"; + break; + default: + goto done; + } + retval = key_fingerprint_b64(dgst_name, dgst_raw, dgst_raw_len); + break; case SSH_FP_BUBBLEBABBLE: retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); break; @@ -424,6 +457,7 @@ pamsshagentauth_key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_re dgst_rep); break; } + done: memset(dgst_raw, 0, dgst_raw_len); pamsshagentauth_xfree(dgst_raw); return retval; diff --git a/key.h b/key.h index e9d01af..7223b95 100644 --- a/key.h +++ b/key.h @@ -50,6 +50,7 @@ enum fp_type { }; enum fp_rep { SSH_FP_HEX, + SSH_FP_BASE64, SSH_FP_BUBBLEBABBLE }; diff --git a/pam_user_key_allowed2.c b/pam_user_key_allowed2.c index 0e1b71b..49ab8b0 100644 --- a/pam_user_key_allowed2.c +++ b/pam_user_key_allowed2.c @@ -102,7 +102,7 @@ pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key) found_key = 1; pamsshagentauth_logit("matching key found: file/command %s, line %lu", file, linenum); - fp = pamsshagentauth_key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + fp = pamsshagentauth_key_fingerprint(found, SSH_FP_SHA256, SSH_FP_BASE64); pamsshagentauth_logit("Found matching %s key: %s", pamsshagentauth_key_type(found), fp); pamsshagentauth_xfree(fp);