From 513cfbe2bf7216c1696887980dead2a800fe9a65 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 8 Mar 2022 14:57:44 +0100 Subject: [PATCH 1/3] migrate RSA initialization to openssl 3 --- configure.ac | 12 ++--- src/match_openssh.c | 116 ++++++++++++++++++++++++++++++-------------- src/pam_p11.c | 11 ----- 3 files changed, 86 insertions(+), 53 deletions(-) diff --git a/configure.ac b/configure.ac index c813df7..2d3e1e9 100644 --- a/configure.ac +++ b/configure.ac @@ -70,11 +70,11 @@ ifdef( PKG_CHECK_MODULES([LIBP11], [libp11 >= 0.2.4],, [AC_MSG_ERROR([libp11 is required])]) PKG_CHECK_MODULES( [OPENSSL], - [libcrypto >= 0.9.7], + [libcrypto >= 1.1.1], , [PKG_CHECK_MODULES( [OPENSSL], - [openssl >= 0.9.7], + [openssl >= 1.1.1], , [AC_CHECK_LIB( [crypto], @@ -85,10 +85,10 @@ PKG_CHECK_MODULES( )] ) -saved_LIBS="$LIBS" -LIBS="$OPENSSL_LIBS $LIBS" -AC_CHECK_FUNCS(EVP_MD_CTX_new EVP_MD_CTX_free EVP_MD_CTX_reset) -LIBS="$saved_LIBS" +#saved_LIBS="$LIBS" +#LIBS="$OPENSSL_LIBS $LIBS" +#AC_CHECK_FUNCS(EVP_MD_CTX_new EVP_MD_CTX_free EVP_MD_CTX_reset) +#LIBS="$saved_LIBS" if test -z "${PAM_LIBS}"; then AC_ARG_VAR([PAM_CFLAGS], [C compiler flags for pam]) diff --git a/src/match_openssh.c b/src/match_openssh.c index de11c04..15b8f00 100644 --- a/src/match_openssh.c +++ b/src/match_openssh.c @@ -6,6 +6,11 @@ #include #include #include +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif #include #include #include @@ -57,21 +62,59 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) #endif -static EVP_PKEY *ssh1_line_to_key(char *line) +static EVP_PKEY *init_evp_pkey_rsa(BIGNUM *rsa_e, BIGNUM *rsa_n) { - EVP_PKEY *key; - RSA *rsa; - char *b, *e, *m, *c; - BIGNUM *rsa_e, *rsa_n; + EVP_PKEY *key = NULL; + if (!rsa_e || !rsa_n) + return NULL; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L key = EVP_PKEY_new(); if (!key) return NULL; - rsa = RSA_new(); + RSA *rsa = RSA_new(); + if (!rsa) { + EVP_PKEY_free(key); + return NULL; + } - if (!rsa) - goto err; + /* set e and n */ + if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) { + RSA_free(rsa); + EVP_PKEY_free(key); + return NULL; + } + + EVP_PKEY_assign_RSA(key, rsa); +#else + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + + if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL + || (bld = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, rsa_n) + || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, rsa_e) + || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL + || EVP_PKEY_fromdata_init(pctx) <= 0 + || EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_CTX_free(pctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + return NULL; + } +#endif + + return key; +} + +static EVP_PKEY *ssh1_line_to_key(char *line) +{ + EVP_PKEY *key = NULL; + char *b, *e, *m, *c; + BIGNUM *rsa_e = NULL, *rsa_n = NULL; /* first digitstring: the bits */ b = line; @@ -82,7 +125,7 @@ static EVP_PKEY *ssh1_line_to_key(char *line) /* must be a whitespace */ if (*e != ' ' && *e != '\t') - return NULL; + goto err; /* cut the string in two part */ *e = 0; @@ -98,7 +141,7 @@ static EVP_PKEY *ssh1_line_to_key(char *line) /* must be a whitespace */ if (*m != ' ' && *m != '\t') - return NULL; + goto err; /* cut the string in two part */ *m = 0; @@ -113,7 +156,7 @@ static EVP_PKEY *ssh1_line_to_key(char *line) /* could be a whitespace or end of line */ if (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\r' && *c != 0) - return NULL; + goto err; if (*c == ' ' || *c == '\t') { *c = 0; @@ -139,24 +182,26 @@ static EVP_PKEY *ssh1_line_to_key(char *line) BN_dec2bn(&rsa_e, e); BN_dec2bn(&rsa_n, m); - if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) - goto err; - EVP_PKEY_assign_RSA(key, rsa); - return key; + key = init_evp_pkey_rsa(rsa_n, rsa_e); + +err: + if (!key) { + if (rsa_n) + BN_free(rsa_n); + if (rsa_e) + BN_free(rsa_e); + } - err: - EVP_PKEY_free(key); - return NULL; + return key; } extern int sc_base64_decode(const char *in, unsigned char *out, size_t outlen); static EVP_PKEY *ssh2_line_to_key(char *line) { - EVP_PKEY *key; - RSA *rsa; - BIGNUM *rsa_e, *rsa_n; + EVP_PKEY *key = NULL; + BIGNUM *rsa_e = NULL, *rsa_n = NULL; unsigned char decoded[OPENSSH_LINE_MAX]; int len; @@ -167,7 +212,7 @@ static EVP_PKEY *ssh2_line_to_key(char *line) b = line; if (!b) - return NULL; + goto err; /* find the first whitespace */ while (*b && *b != ' ') @@ -184,7 +229,7 @@ static EVP_PKEY *ssh2_line_to_key(char *line) /* decode binary data */ if (sc_base64_decode(b, decoded, OPENSSH_LINE_MAX) < 0) - return NULL; + goto err; i = 0; @@ -196,13 +241,13 @@ static EVP_PKEY *ssh2_line_to_key(char *line) /* now: key_from_blob */ if (strncmp((char *)&decoded[i], "ssh-rsa", 7) != 0) - return NULL; + goto err; i += len; /* to prevent access beyond 'decoded' array, index 'i' must be always checked */ if ( i + 4 > OPENSSH_LINE_MAX ) - return NULL; + goto err; /* get integer from blob */ len = (decoded[i] << 24) + (decoded[i + 1] << 16) + @@ -210,13 +255,13 @@ static EVP_PKEY *ssh2_line_to_key(char *line) i += 4; if ( i + len > OPENSSH_LINE_MAX ) - return NULL; + goto err; /* get bignum */ rsa_e = BN_bin2bn(decoded + i, len, NULL); i += len; if ( i + 4 > OPENSSH_LINE_MAX ) - return NULL; + goto err; /* get integer from blob */ len = (decoded[i] << 24) + (decoded[i + 1] << 16) + @@ -224,21 +269,20 @@ static EVP_PKEY *ssh2_line_to_key(char *line) i += 4; if ( i + len > OPENSSH_LINE_MAX ) - return NULL; + goto err; /* get bignum */ rsa_n = BN_bin2bn(decoded + i, len, NULL); - key = EVP_PKEY_new(); - rsa = RSA_new(); + key = init_evp_pkey_rsa(rsa_n, rsa_e); - /* set e and n */ - if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) { - EVP_PKEY_free(key); - RSA_free(rsa); - return NULL; +err: + if (!key) { + if (rsa_n) + BN_free(rsa_n); + if (rsa_e) + BN_free(rsa_e); } - EVP_PKEY_assign_RSA(key, rsa); return key; } diff --git a/src/pam_p11.c b/src/pam_p11.c index ff1a829..6d362fa 100644 --- a/src/pam_p11.c +++ b/src/pam_p11.c @@ -33,17 +33,6 @@ #include #include -/* openssl deprecated API emulation */ -#ifndef HAVE_EVP_MD_CTX_NEW -#define EVP_MD_CTX_new() EVP_MD_CTX_create() -#endif -#ifndef HAVE_EVP_MD_CTX_FREE -#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy((ctx)) -#endif -#ifndef HAVE_EVP_MD_CTX_RESET -#define EVP_MD_CTX_reset(ctx) EVP_MD_CTX_cleanup((ctx)) -#endif - #ifdef ENABLE_NLS #include #include -- 2.35.1 From b973b0e413e9d421cedd0e8231aeccf230c8a74c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 8 Mar 2022 15:45:04 +0100 Subject: [PATCH 2/3] added openssl 3 compatibility for ec pubkeys --- src/match_openssh.c | 80 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/src/match_openssh.c b/src/match_openssh.c index 15b8f00..bcf8897 100644 --- a/src/match_openssh.c +++ b/src/match_openssh.c @@ -110,6 +110,68 @@ static EVP_PKEY *init_evp_pkey_rsa(BIGNUM *rsa_e, BIGNUM *rsa_n) return key; } +static EVP_PKEY *init_evp_pkey_ec(int nid_curve, BIGNUM *pub_x, BIGNUM *pub_y) +{ + EVP_PKEY *key = NULL; + + if (!pub_x || !pub_y) + return NULL; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + key = EVP_PKEY_new(); + if (!key) + return NULL; + + EC_KEY *ec_key = EC_KEY_new_by_curve_name(nid_curve); + if (!ec_key) { + EVP_PKEY_free(key); + return NULL; + } + + /* do error checking here: valid x, y, ec_key, point on curve.. */ + if (!EC_KEY_set_public_key_affine_coordinates(ec_key, pub_x, pub_y)) { + EC_KEY_free(ec_key); + EVP_PKEY_free(key); + return NULL; + } + EVP_PKEY_assign_EC_KEY(key, ec_key); +#else + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + char *group_name; + switch (nid_curve) { + case NID_X9_62_prime256v1: + group_name = SN_X9_62_prime256v1; + break; + case NID_secp384r1: + group_name = SN_secp384r1; + break; + case NID_secp521r1: + group_name = SN_secp521r1; + break; + default: + return NULL; + } + + if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL + || (bld = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) + || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_PUB_X, pub_x) + || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_PUB_Y, pub_y) + || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL + || EVP_PKEY_fromdata_init(pctx) <= 0 + || EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_CTX_free(pctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + return NULL; + } +#endif + + return key; +} + static EVP_PKEY *ssh1_line_to_key(char *line) { EVP_PKEY *key = NULL; @@ -289,7 +351,6 @@ err: static EVP_PKEY *ssh_nistp_line_to_key(char *line) { EVP_PKEY *key; - EC_KEY *ec_key; BIGNUM *x; BIGNUM *y; @@ -378,24 +439,19 @@ static EVP_PKEY *ssh_nistp_line_to_key(char *line) return NULL; i++; - /* create key */ - ec_key = EC_KEY_new_by_curve_name(nid); - /* read point coordinates */ x = BN_bin2bn(decoded + i, flen, NULL); i += flen; y = BN_bin2bn(decoded + i, flen, NULL); - /* do error checking here: valid x, y, ec_key, point on curve.. */ - if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) { - EC_KEY_free(ec_key); - BN_free(x); - BN_free(y); - return NULL; + key = init_evp_pkey_ec(nid, x, y); + if (!key) { + if (x) + BN_free(x); + if (y) + BN_free(y); } - key = EVP_PKEY_new(); - EVP_PKEY_assign_EC_KEY(key, ec_key); return key; } -- 2.35.1 From 1e110f77f4fb52878722de3e1c0991d6199cf701 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 8 Mar 2022 16:16:03 +0100 Subject: [PATCH 3/3] added compatibility for openssl 3 evp_pkey comparison --- src/match_opensc.c | 6 ++++++ src/match_openssh.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/match_opensc.c b/src/match_opensc.c index eeba115..a453d18 100644 --- a/src/match_opensc.c +++ b/src/match_opensc.c @@ -48,9 +48,15 @@ extern int match_user_opensc(EVP_PKEY *authkey, const char *login) if (key == NULL) continue; +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (1 == EVP_PKEY_cmp(authkey, key)) { found = 1; } +#else + if (1 == EVP_PKEY_eq(authkey, key)) { + found = 1; + } +#endif EVP_PKEY_free(key); } while (found == 0); diff --git a/src/match_openssh.c b/src/match_openssh.c index bcf8897..89cbd73 100644 --- a/src/match_openssh.c +++ b/src/match_openssh.c @@ -500,9 +500,15 @@ extern int match_user_openssh(EVP_PKEY *authkey, const char *login) if (key == NULL) continue; +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (1 == EVP_PKEY_cmp(authkey, key)) { found = 1; } +#else + if (1 == EVP_PKEY_eq(authkey, key)) { + found = 1; + } +#endif EVP_PKEY_free(key); } while (found == 0); -- 2.35.1