From e278c950a37d2eb2b3ebce279670135cb8c33fed Mon Sep 17 00:00:00 2001 From: Gary Buhrmaster Date: Wed, 15 Sep 2021 15:29:05 +0000 Subject: [PATCH] Apply upstream patches for OpenSSL 3.0 --- ...eplace-SHA256_-with-EVP_-equivalents.patch | 204 ++++++++++ ...e-fido_verify_sig_-eddsa-es256-rs256.patch | 363 ++++++++++++++++++ 0003-cred-rework-verify_sig.patch | 85 ++++ ...st-to-silence-warning-with-OpenSSL-3.patch | 28 ++ ...56_verify_sig-OpenSSL-3.0-compatible.patch | 59 +++ ...-drop-OpenSSL-1.0-compatibility-shim.patch | 49 +++ ...56_verify_sig-OpenSSL-3.0-compatible.patch | 135 +++++++ ...PI_COMPAT-if-OpenSSL-3.0-is-detected.patch | 34 ++ libfido2.spec | 15 +- 9 files changed, 971 insertions(+), 1 deletion(-) create mode 100644 0001-Replace-SHA256_-with-EVP_-equivalents.patch create mode 100644 0002-Rename-and-move-fido_verify_sig_-eddsa-es256-rs256.patch create mode 100644 0003-cred-rework-verify_sig.patch create mode 100644 0004-ecdh-explicit-cast-to-silence-warning-with-OpenSSL-3.patch create mode 100644 0005-es256-make-es256_verify_sig-OpenSSL-3.0-compatible.patch create mode 100644 0006-rs256-drop-OpenSSL-1.0-compatibility-shim.patch create mode 100644 0007-rs256-make-rs256_verify_sig-OpenSSL-3.0-compatible.patch create mode 100644 0008-Define-OPENSSL_API_COMPAT-if-OpenSSL-3.0-is-detected.patch diff --git a/0001-Replace-SHA256_-with-EVP_-equivalents.patch b/0001-Replace-SHA256_-with-EVP_-equivalents.patch new file mode 100644 index 0000000..864668d --- /dev/null +++ b/0001-Replace-SHA256_-with-EVP_-equivalents.patch @@ -0,0 +1,204 @@ +From c7c07de1dbfb0a33fb096f7fa2fd901e7485d6eb Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Wed, 28 Jul 2021 10:23:28 +0200 +Subject: [PATCH 06/70] Replace SHA256_* with EVP_* equivalents + +SHA256_{Init,Update,Final} are marked as deprecated in OpenSSL 3.0. +Given that alternatives exist in OpenSSL 1.1 and LibreSSL, switch to +them as a first step towards OpenSSL 3.0 integration. + +Joint work with Dmitry Belyavskiy. +--- + fuzz/wrap.c | 48 ++++++++++++++++++++++++------------------------ + fuzz/wrapped.sym | 6 +++--- + src/assert.c | 16 +++++++++++----- + src/cred.c | 39 ++++++++++++++++++++++++--------------- + 4 files changed, 62 insertions(+), 47 deletions(-) + +diff --git a/fuzz/wrap.c b/fuzz/wrap.c +index 5b91a64..188dbd4 100644 +--- a/fuzz/wrap.c ++++ b/fuzz/wrap.c +@@ -136,30 +136,6 @@ WRAP(int, + 1 + ) + +-WRAP(int, +- SHA256_Init, +- (SHA256_CTX *c), +- 0, +- (c), +- 1 +-) +- +-WRAP(int, +- SHA256_Update, +- (SHA256_CTX *c, const void *data, size_t len), +- 0, +- (c, data, len), +- 1 +-) +- +-WRAP(int, +- SHA256_Final, +- (unsigned char *md, SHA256_CTX *c), +- 0, +- (md, c), +- 1 +-) +- + WRAP(RSA *, + EVP_PKEY_get0_RSA, + (EVP_PKEY *pkey), +@@ -201,6 +177,30 @@ WRAP(int, + 1 + ) + ++WRAP(int, ++ EVP_DigestInit_ex, ++ (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl), ++ 0, ++ (ctx, type, impl), ++ 1 ++) ++ ++WRAP(int, ++ EVP_DigestUpdate, ++ (EVP_MD_CTX *ctx, const void *data, size_t count), ++ 0, ++ (ctx, data, count), ++ 1 ++) ++ ++WRAP(int, ++ EVP_DigestFinal_ex, ++ (EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize), ++ 0, ++ (ctx, md, isize), ++ 1 ++) ++ + WRAP(BIGNUM *, + BN_bin2bn, + (const unsigned char *s, int len, BIGNUM *ret), +diff --git a/fuzz/wrapped.sym b/fuzz/wrapped.sym +index de4f24a..87d4f28 100644 +--- a/fuzz/wrapped.sym ++++ b/fuzz/wrapped.sym +@@ -31,6 +31,9 @@ EVP_CIPHER_CTX_set_padding + EVP_CipherInit + EVP_DecryptInit_ex + EVP_DecryptUpdate ++EVP_DigestFinal_ex ++EVP_DigestInit_ex ++EVP_DigestUpdate + EVP_DigestVerifyInit + EVP_EncryptInit_ex + EVP_EncryptUpdate +@@ -61,9 +64,6 @@ ioctl + malloc + RSA_set0_key + SHA256 +-SHA256_Final +-SHA256_Init +-SHA256_Update + strdup + udev_device_get_devnode + udev_device_get_parent_with_subsystem_devtype +diff --git a/src/assert.c b/src/assert.c +index b36f8e3..d28484c 100644 +--- a/src/assert.c ++++ b/src/assert.c +@@ -372,7 +372,8 @@ fido_get_signed_hash(int cose_alg, fido_blob_t *dgst, + unsigned char *authdata_ptr = NULL; + size_t authdata_len; + struct cbor_load_result cbor; +- SHA256_CTX ctx; ++ const EVP_MD *md = NULL; ++ EVP_MD_CTX *ctx = NULL; + int ok = -1; + + if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len, +@@ -386,10 +387,13 @@ fido_get_signed_hash(int cose_alg, fido_blob_t *dgst, + authdata_len = cbor_bytestring_length(item); + + if (cose_alg != COSE_EDDSA) { +- if (dgst->len < SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 || +- SHA256_Update(&ctx, authdata_ptr, authdata_len) == 0 || +- SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 || +- SHA256_Final(dgst->ptr, &ctx) == 0) { ++ if (dgst->len < SHA256_DIGEST_LENGTH || ++ (md = EVP_sha256()) == NULL || ++ (ctx = EVP_MD_CTX_new()) == NULL || ++ EVP_DigestInit_ex(ctx, md, NULL) != 1 || ++ EVP_DigestUpdate(ctx, authdata_ptr, authdata_len) != 1 || ++ EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 || ++ EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) { + fido_log_debug("%s: sha256", __func__); + goto fail; + } +@@ -411,6 +415,8 @@ fail: + if (item != NULL) + cbor_decref(&item); + ++ EVP_MD_CTX_free(ctx); ++ + return (ok); + } + +diff --git a/src/cred.c b/src/cred.c +index 5e65b08..e38972b 100644 +--- a/src/cred.c ++++ b/src/cred.c +@@ -225,24 +225,33 @@ get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id, + size_t rp_id_len, const fido_blob_t *clientdata, const fido_blob_t *id, + const es256_pk_t *pk) + { +- const uint8_t zero = 0; +- const uint8_t four = 4; /* uncompressed point */ +- SHA256_CTX ctx; +- +- if (dgst->len != SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 || +- SHA256_Update(&ctx, &zero, sizeof(zero)) == 0 || +- SHA256_Update(&ctx, rp_id, rp_id_len) == 0 || +- SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 || +- SHA256_Update(&ctx, id->ptr, id->len) == 0 || +- SHA256_Update(&ctx, &four, sizeof(four)) == 0 || +- SHA256_Update(&ctx, pk->x, sizeof(pk->x)) == 0 || +- SHA256_Update(&ctx, pk->y, sizeof(pk->y)) == 0 || +- SHA256_Final(dgst->ptr, &ctx) == 0) { ++ const uint8_t zero = 0; ++ const uint8_t four = 4; /* uncompressed point */ ++ const EVP_MD *md = NULL; ++ EVP_MD_CTX *ctx = NULL; ++ int ok = -1; ++ ++ if (dgst->len != SHA256_DIGEST_LENGTH || ++ (md = EVP_sha256()) == NULL || ++ (ctx = EVP_MD_CTX_new()) == NULL || ++ EVP_DigestInit_ex(ctx, md, NULL) != 1 || ++ EVP_DigestUpdate(ctx, &zero, sizeof(zero)) != 1 || ++ EVP_DigestUpdate(ctx, rp_id, rp_id_len) != 1 || ++ EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 || ++ EVP_DigestUpdate(ctx, id->ptr, id->len) != 1 || ++ EVP_DigestUpdate(ctx, &four, sizeof(four)) != 1 || ++ EVP_DigestUpdate(ctx, pk->x, sizeof(pk->x)) != 1 || ++ EVP_DigestUpdate(ctx, pk->y, sizeof(pk->y)) != 1 || ++ EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) { + fido_log_debug("%s: sha256", __func__); +- return (-1); ++ goto fail; + } + +- return (0); ++ ok = 0; ++fail: ++ EVP_MD_CTX_free(ctx); ++ ++ return (ok); + } + + static int +-- +2.31.1 + diff --git a/0002-Rename-and-move-fido_verify_sig_-eddsa-es256-rs256.patch b/0002-Rename-and-move-fido_verify_sig_-eddsa-es256-rs256.patch new file mode 100644 index 0000000..13de351 --- /dev/null +++ b/0002-Rename-and-move-fido_verify_sig_-eddsa-es256-rs256.patch @@ -0,0 +1,363 @@ +From e4f0b9aee150be7291ac57bc7c27f335f5c75694 Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Mon, 2 Aug 2021 19:04:43 +0200 +Subject: [PATCH 14/70] Rename and move fido_verify_sig_{eddsa,es256,rs256} + +Rename fido_verify_sig_{eddsa,es256,rs256} and move them to +{eddsa,es256,rs256}.c respectively. No functional change. +--- + src/assert.c | 124 ++------------------------------------------------- + src/cred.c | 6 +-- + src/eddsa.c | 47 +++++++++++++++++++ + src/es256.c | 36 +++++++++++++++ + src/extern.h | 6 +-- + src/rs256.c | 35 +++++++++++++++ + 6 files changed, 127 insertions(+), 127 deletions(-) + +diff --git a/src/assert.c b/src/assert.c +index d28484c..a3efbf5 100644 +--- a/src/assert.c ++++ b/src/assert.c +@@ -4,7 +4,6 @@ + * license that can be found in the LICENSE file. + */ + +-#include + #include + + #include "fido.h" +@@ -420,123 +419,6 @@ fail: + return (ok); + } + +-int +-fido_verify_sig_es256(const fido_blob_t *dgst, const es256_pk_t *pk, +- const fido_blob_t *sig) +-{ +- EVP_PKEY *pkey = NULL; +- EC_KEY *ec = NULL; +- int ok = -1; +- +- /* ECDSA_verify needs ints */ +- if (dgst->len > INT_MAX || sig->len > INT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, +- dgst->len, sig->len); +- return (-1); +- } +- +- if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL || +- (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { +- fido_log_debug("%s: pk -> ec", __func__); +- goto fail; +- } +- +- if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr, +- (int)sig->len, ec) != 1) { +- fido_log_debug("%s: ECDSA_verify", __func__); +- goto fail; +- } +- +- ok = 0; +-fail: +- if (pkey != NULL) +- EVP_PKEY_free(pkey); +- +- return (ok); +-} +- +-int +-fido_verify_sig_rs256(const fido_blob_t *dgst, const rs256_pk_t *pk, +- const fido_blob_t *sig) +-{ +- EVP_PKEY *pkey = NULL; +- RSA *rsa = NULL; +- int ok = -1; +- +- /* RSA_verify needs unsigned ints */ +- if (dgst->len > UINT_MAX || sig->len > UINT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, +- dgst->len, sig->len); +- return (-1); +- } +- +- if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL || +- (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { +- fido_log_debug("%s: pk -> ec", __func__); +- goto fail; +- } +- +- if (RSA_verify(NID_sha256, dgst->ptr, (unsigned int)dgst->len, sig->ptr, +- (unsigned int)sig->len, rsa) != 1) { +- fido_log_debug("%s: RSA_verify", __func__); +- goto fail; +- } +- +- ok = 0; +-fail: +- if (pkey != NULL) +- EVP_PKEY_free(pkey); +- +- return (ok); +-} +- +-int +-fido_verify_sig_eddsa(const fido_blob_t *dgst, const eddsa_pk_t *pk, +- const fido_blob_t *sig) +-{ +- EVP_PKEY *pkey = NULL; +- EVP_MD_CTX *mdctx = NULL; +- int ok = -1; +- +- /* EVP_DigestVerify needs ints */ +- if (dgst->len > INT_MAX || sig->len > INT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, +- dgst->len, sig->len); +- return (-1); +- } +- +- if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) { +- fido_log_debug("%s: pk -> pkey", __func__); +- goto fail; +- } +- +- if ((mdctx = EVP_MD_CTX_new()) == NULL) { +- fido_log_debug("%s: EVP_MD_CTX_new", __func__); +- goto fail; +- } +- +- if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) { +- fido_log_debug("%s: EVP_DigestVerifyInit", __func__); +- goto fail; +- } +- +- if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr, +- dgst->len) != 1) { +- fido_log_debug("%s: EVP_DigestVerify", __func__); +- goto fail; +- } +- +- ok = 0; +-fail: +- if (mdctx != NULL) +- EVP_MD_CTX_free(mdctx); +- +- if (pkey != NULL) +- EVP_PKEY_free(pkey); +- +- return (ok); +-} +- + int + fido_assert_verify(const fido_assert_t *assert, size_t idx, int cose_alg, + const void *pk) +@@ -595,13 +477,13 @@ fido_assert_verify(const fido_assert_t *assert, size_t idx, int cose_alg, + + switch (cose_alg) { + case COSE_ES256: +- ok = fido_verify_sig_es256(&dgst, pk, &stmt->sig); ++ ok = es256_verify_sig(&dgst, pk, &stmt->sig); + break; + case COSE_RS256: +- ok = fido_verify_sig_rs256(&dgst, pk, &stmt->sig); ++ ok = rs256_verify_sig(&dgst, pk, &stmt->sig); + break; + case COSE_EDDSA: +- ok = fido_verify_sig_eddsa(&dgst, pk, &stmt->sig); ++ ok = eddsa_verify_sig(&dgst, pk, &stmt->sig); + break; + default: + fido_log_debug("%s: unsupported cose_alg %d", __func__, +diff --git a/src/cred.c b/src/cred.c +index ce5be34..bce5c13 100644 +--- a/src/cred.c ++++ b/src/cred.c +@@ -444,15 +444,15 @@ fido_cred_verify_self(const fido_cred_t *cred) + + switch (cred->attcred.type) { + case COSE_ES256: +- ok = fido_verify_sig_es256(&dgst, &cred->attcred.pubkey.es256, ++ ok = es256_verify_sig(&dgst, &cred->attcred.pubkey.es256, + &cred->attstmt.sig); + break; + case COSE_RS256: +- ok = fido_verify_sig_rs256(&dgst, &cred->attcred.pubkey.rs256, ++ ok = rs256_verify_sig(&dgst, &cred->attcred.pubkey.rs256, + &cred->attstmt.sig); + break; + case COSE_EDDSA: +- ok = fido_verify_sig_eddsa(&dgst, &cred->attcred.pubkey.eddsa, ++ ok = eddsa_verify_sig(&dgst, &cred->attcred.pubkey.eddsa, + &cred->attstmt.sig); + break; + default: +diff --git a/src/eddsa.c b/src/eddsa.c +index 89b84c5..dffbdf7 100644 +--- a/src/eddsa.c ++++ b/src/eddsa.c +@@ -170,3 +170,50 @@ eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey) + + return (FIDO_OK); + } ++ ++int ++eddsa_verify_sig(const fido_blob_t *dgst, const eddsa_pk_t *pk, ++ const fido_blob_t *sig) ++{ ++ EVP_PKEY *pkey = NULL; ++ EVP_MD_CTX *mdctx = NULL; ++ int ok = -1; ++ ++ /* EVP_DigestVerify needs ints */ ++ if (dgst->len > INT_MAX || sig->len > INT_MAX) { ++ fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, ++ dgst->len, sig->len); ++ return (-1); ++ } ++ ++ if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) { ++ fido_log_debug("%s: pk -> pkey", __func__); ++ goto fail; ++ } ++ ++ if ((mdctx = EVP_MD_CTX_new()) == NULL) { ++ fido_log_debug("%s: EVP_MD_CTX_new", __func__); ++ goto fail; ++ } ++ ++ if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) { ++ fido_log_debug("%s: EVP_DigestVerifyInit", __func__); ++ goto fail; ++ } ++ ++ if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr, ++ dgst->len) != 1) { ++ fido_log_debug("%s: EVP_DigestVerify", __func__); ++ goto fail; ++ } ++ ++ ok = 0; ++fail: ++ if (mdctx != NULL) ++ EVP_MD_CTX_free(mdctx); ++ ++ if (pkey != NULL) ++ EVP_PKEY_free(pkey); ++ ++ return (ok); ++} +diff --git a/src/es256.c b/src/es256.c +index 9cdb48e..dcdcb80 100644 +--- a/src/es256.c ++++ b/src/es256.c +@@ -5,6 +5,7 @@ + */ + + #include ++#include + #include + + #include "fido.h" +@@ -451,3 +452,38 @@ fail: + + return (ok); + } ++ ++int ++es256_verify_sig(const fido_blob_t *dgst, const es256_pk_t *pk, ++ const fido_blob_t *sig) ++{ ++ EVP_PKEY *pkey = NULL; ++ EC_KEY *ec = NULL; ++ int ok = -1; ++ ++ /* ECDSA_verify needs ints */ ++ if (dgst->len > INT_MAX || sig->len > INT_MAX) { ++ fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, ++ dgst->len, sig->len); ++ return (-1); ++ } ++ ++ if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL || ++ (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { ++ fido_log_debug("%s: pk -> ec", __func__); ++ goto fail; ++ } ++ ++ if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr, ++ (int)sig->len, ec) != 1) { ++ fido_log_debug("%s: ECDSA_verify", __func__); ++ goto fail; ++ } ++ ++ ok = 0; ++fail: ++ if (pkey != NULL) ++ EVP_PKEY_free(pkey); ++ ++ return (ok); ++} +diff --git a/src/extern.h b/src/extern.h +index 91e129b..a2d1ba4 100644 +--- a/src/extern.h ++++ b/src/extern.h +@@ -200,11 +200,11 @@ int fido_get_random(void *, size_t); + int fido_sha256(fido_blob_t *, const u_char *, size_t); + + /* crypto */ +-int fido_verify_sig_es256(const fido_blob_t *, const es256_pk_t *, ++int es256_verify_sig(const fido_blob_t *, const es256_pk_t *, + const fido_blob_t *); +-int fido_verify_sig_rs256(const fido_blob_t *, const rs256_pk_t *, ++int rs256_verify_sig(const fido_blob_t *, const rs256_pk_t *, + const fido_blob_t *); +-int fido_verify_sig_eddsa(const fido_blob_t *, const eddsa_pk_t *, ++int eddsa_verify_sig(const fido_blob_t *, const eddsa_pk_t *, + const fido_blob_t *); + int fido_get_signed_hash(int, fido_blob_t *, const fido_blob_t *, + const fido_blob_t *); +diff --git a/src/rs256.c b/src/rs256.c +index c6d87a3..001417b 100644 +--- a/src/rs256.c ++++ b/src/rs256.c +@@ -198,3 +198,38 @@ rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa) + + return (FIDO_OK); + } ++ ++int ++rs256_verify_sig(const fido_blob_t *dgst, const rs256_pk_t *pk, ++ const fido_blob_t *sig) ++{ ++ EVP_PKEY *pkey = NULL; ++ RSA *rsa = NULL; ++ int ok = -1; ++ ++ /* RSA_verify needs unsigned ints */ ++ if (dgst->len > UINT_MAX || sig->len > UINT_MAX) { ++ fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, ++ dgst->len, sig->len); ++ return (-1); ++ } ++ ++ if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL || ++ (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { ++ fido_log_debug("%s: pk -> ec", __func__); ++ goto fail; ++ } ++ ++ if (RSA_verify(NID_sha256, dgst->ptr, (unsigned int)dgst->len, sig->ptr, ++ (unsigned int)sig->len, rsa) != 1) { ++ fido_log_debug("%s: RSA_verify", __func__); ++ goto fail; ++ } ++ ++ ok = 0; ++fail: ++ if (pkey != NULL) ++ EVP_PKEY_free(pkey); ++ ++ return (ok); ++} +-- +2.31.1 + diff --git a/0003-cred-rework-verify_sig.patch b/0003-cred-rework-verify_sig.patch new file mode 100644 index 0000000..a60fe74 --- /dev/null +++ b/0003-cred-rework-verify_sig.patch @@ -0,0 +1,85 @@ +From 2d258bc64a67bb66990538e00e11e094b49cd942 Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 08:48:43 +0200 +Subject: [PATCH 15/70] cred: rework verify_sig + +Rework verify_sig (used by fido_cred_verify) to accept key types +other than ES256, while making the code OpenSSL 3.0 compatible. + +Diff from Dmitry Belyavskiy (@beldmit). +--- + man/fido_cred_verify.3 | 1 - + src/cred.c | 26 ++++++++++++-------------- + 2 files changed, 12 insertions(+), 15 deletions(-) + +diff --git a/man/fido_cred_verify.3 b/man/fido_cred_verify.3 +index d90a4c7..e5179d9 100644 +--- a/man/fido_cred_verify.3 ++++ b/man/fido_cred_verify.3 +@@ -47,7 +47,6 @@ The attestation type implemented by + .Fn fido_cred_verify + is + .Em Basic Attestation . +-The attestation key pair is assumed to be of the type ES256. + Other attestation formats and types are not supported. + .Sh RETURN VALUES + The error codes returned by +diff --git a/src/cred.c b/src/cred.c +index bce5c13..6b99476 100644 +--- a/src/cred.c ++++ b/src/cred.c +@@ -261,13 +261,12 @@ verify_sig(const fido_blob_t *dgst, const fido_blob_t *x5c, + BIO *rawcert = NULL; + X509 *cert = NULL; + EVP_PKEY *pkey = NULL; +- EC_KEY *ec; ++ EVP_PKEY_CTX *pctx = NULL; + int ok = -1; + + /* openssl needs ints */ +- if (dgst->len > INT_MAX || x5c->len > INT_MAX || sig->len > INT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, x5c->len=%zu, sig->len=%zu", +- __func__, dgst->len, x5c->len, sig->len); ++ if (x5c->len > INT_MAX) { ++ fido_log_debug("%s: x5c->len=%zu", __func__, x5c->len); + return (-1); + } + +@@ -275,25 +274,24 @@ verify_sig(const fido_blob_t *dgst, const fido_blob_t *x5c, + if ((rawcert = BIO_new_mem_buf(x5c->ptr, (int)x5c->len)) == NULL || + (cert = d2i_X509_bio(rawcert, NULL)) == NULL || + (pkey = X509_get_pubkey(cert)) == NULL || +- (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { ++ (pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + fido_log_debug("%s: x509 key", __func__); + goto fail; + } + +- if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr, +- (int)sig->len, ec) != 1) { +- fido_log_debug("%s: ECDSA_verify", __func__); ++ if (EVP_PKEY_verify_init(pctx) != 1 || ++ EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr, ++ dgst->len) != 1) { ++ fido_log_debug("%s: EVP_PKEY_verify", __func__); + goto fail; + } + + ok = 0; + fail: +- if (rawcert != NULL) +- BIO_free(rawcert); +- if (cert != NULL) +- X509_free(cert); +- if (pkey != NULL) +- EVP_PKEY_free(pkey); ++ BIO_free(rawcert); ++ X509_free(cert); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(pctx); + + return (ok); + } +-- +2.31.1 + diff --git a/0004-ecdh-explicit-cast-to-silence-warning-with-OpenSSL-3.patch b/0004-ecdh-explicit-cast-to-silence-warning-with-OpenSSL-3.patch new file mode 100644 index 0000000..5cfdde5 --- /dev/null +++ b/0004-ecdh-explicit-cast-to-silence-warning-with-OpenSSL-3.patch @@ -0,0 +1,28 @@ +From cbf522fc65e16bc206810a6a0de9d757558ff55b Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 13:28:09 +0200 +Subject: [PATCH 16/70] ecdh: explicit cast to silence warning with OpenSSL 3.0 + +EVP_PKEY_CTX_add1_hkdf_info takes a const unsigned char * in OpenSSL +3, and a void * in OpenSSL 1.1. We pass a char *, so add an explicit +cast to void * to satisfy both variations. +--- + src/ecdh.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ecdh.c b/src/ecdh.c +index 3ea47ae..1e85e7e 100644 +--- a/src/ecdh.c ++++ b/src/ecdh.c +@@ -56,7 +56,7 @@ hkdf_sha256(uint8_t *key, char *info, fido_blob_t *secret) + EVP_PKEY_CTX_set_hkdf_md(ctx, md) < 1 || + EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt, sizeof(salt)) < 1 || + EVP_PKEY_CTX_set1_hkdf_key(ctx, secret->ptr, (int)secret->len) < 1 || +- EVP_PKEY_CTX_add1_hkdf_info(ctx, info, (int)strlen(info)) < 1) { ++ EVP_PKEY_CTX_add1_hkdf_info(ctx, (void *)info, (int)strlen(info)) < 1) { + fido_log_debug("%s: EVP_PKEY_CTX", __func__); + goto fail; + } +-- +2.31.1 + diff --git a/0005-es256-make-es256_verify_sig-OpenSSL-3.0-compatible.patch b/0005-es256-make-es256_verify_sig-OpenSSL-3.0-compatible.patch new file mode 100644 index 0000000..78646a1 --- /dev/null +++ b/0005-es256-make-es256_verify_sig-OpenSSL-3.0-compatible.patch @@ -0,0 +1,59 @@ +From a2955599e77237d6daf99301ccdf9f1d9c2ae181 Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 13:51:52 +0200 +Subject: [PATCH 17/70] es256: make es256_verify_sig OpenSSL 3.0 compatible + +Use the EVP_PKEY_verify family of functions to make es256_verify_sig +compatible with OpenSSL 3.0. Diff from Dmitry Belyavskiy (@beldmit). +--- + src/es256.c | 22 ++++++++-------------- + 1 file changed, 8 insertions(+), 14 deletions(-) + +diff --git a/src/es256.c b/src/es256.c +index dcdcb80..f2f4024 100644 +--- a/src/es256.c ++++ b/src/es256.c +@@ -458,32 +458,26 @@ es256_verify_sig(const fido_blob_t *dgst, const es256_pk_t *pk, + const fido_blob_t *sig) + { + EVP_PKEY *pkey = NULL; +- EC_KEY *ec = NULL; ++ EVP_PKEY_CTX *pctx = NULL; + int ok = -1; + +- /* ECDSA_verify needs ints */ +- if (dgst->len > INT_MAX || sig->len > INT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, +- dgst->len, sig->len); +- return (-1); +- } +- + if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL || +- (ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { ++ (pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + fido_log_debug("%s: pk -> ec", __func__); + goto fail; + } + +- if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr, +- (int)sig->len, ec) != 1) { +- fido_log_debug("%s: ECDSA_verify", __func__); ++ if (EVP_PKEY_verify_init(pctx) != 1 || ++ EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr, ++ dgst->len) != 1) { ++ fido_log_debug("%s: EVP_PKEY_verify", __func__); + goto fail; + } + + ok = 0; + fail: +- if (pkey != NULL) +- EVP_PKEY_free(pkey); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(pctx); + + return (ok); + } +-- +2.31.1 + diff --git a/0006-rs256-drop-OpenSSL-1.0-compatibility-shim.patch b/0006-rs256-drop-OpenSSL-1.0-compatibility-shim.patch new file mode 100644 index 0000000..df0f004 --- /dev/null +++ b/0006-rs256-drop-OpenSSL-1.0-compatibility-shim.patch @@ -0,0 +1,49 @@ +From f769df638f942bc10f1062ac1c5e1ca51b047bf7 Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 14:47:21 +0200 +Subject: [PATCH 18/70] rs256: drop OpenSSL 1.0 compatibility shim + +--- + src/rs256.c | 26 -------------------------- + 1 file changed, 26 deletions(-) + +diff --git a/src/rs256.c b/src/rs256.c +index 001417b..ac0b1f2 100644 +--- a/src/rs256.c ++++ b/src/rs256.c +@@ -11,32 +11,6 @@ + #include "fido.h" + #include "fido/rs256.h" + +-#if OPENSSL_VERSION_NUMBER < 0x10100000L +-static int +-RSA_bits(const RSA *r) +-{ +- return (BN_num_bits(r->n)); +-} +- +-static int +-RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +-{ +- r->n = n; +- r->e = e; +- r->d = d; +- +- return (1); +-} +- +-static void +-RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +-{ +- *n = r->n; +- *e = r->e; +- *d = r->d; +-} +-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ +- + static int + decode_bignum(const cbor_item_t *item, void *ptr, size_t len) + { +-- +2.31.1 + diff --git a/0007-rs256-make-rs256_verify_sig-OpenSSL-3.0-compatible.patch b/0007-rs256-make-rs256_verify_sig-OpenSSL-3.0-compatible.patch new file mode 100644 index 0000000..58d1518 --- /dev/null +++ b/0007-rs256-make-rs256_verify_sig-OpenSSL-3.0-compatible.patch @@ -0,0 +1,135 @@ +From 4632562e363249f0b5d92a8863c19e2662e55b19 Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 14:50:12 +0200 +Subject: [PATCH 19/70] rs256: make rs256_verify_sig OpenSSL 3.0 compatible + +Use the EVP_PKEY_verify family of functions to make rs256_verify_sig +compatible with OpenSSL 3.0. Diff from Dmitry Belyavskiy (@beldmit). +--- + src/rs256.c | 86 +++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 71 insertions(+), 15 deletions(-) + +diff --git a/src/rs256.c b/src/rs256.c +index ac0b1f2..881b575 100644 +--- a/src/rs256.c ++++ b/src/rs256.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018 Yubico AB. All rights reserved. ++ * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ +@@ -11,6 +11,55 @@ + #include "fido.h" + #include "fido/rs256.h" + ++#if defined(LIBRESSL_VERSION_NUMBER) ++static EVP_MD * ++rs256_get_EVP_MD(void) ++{ ++ const EVP_MD *from; ++ EVP_MD *to = NULL; ++ ++ if ((from = EVP_sha256()) != NULL && (to = malloc(sizeof(*to))) != NULL) ++ memcpy(to, from, sizeof(*to)); ++ ++ return (to); ++} ++ ++static void ++rs256_free_EVP_MD(EVP_MD *md) ++{ ++ freezero(md, sizeof(*md)); ++} ++#elif OPENSSL_VERSION_NUMBER >= 0x30000000 ++static EVP_MD * ++rs256_get_EVP_MD(void) ++{ ++ return (EVP_MD_fetch(NULL, "SHA2-256", NULL)); ++} ++ ++static void ++rs256_free_EVP_MD(EVP_MD *md) ++{ ++ EVP_MD_free(md); ++} ++#else ++static EVP_MD * ++rs256_get_EVP_MD(void) ++{ ++ const EVP_MD *md; ++ ++ if ((md = EVP_sha256()) == NULL) ++ return (NULL); ++ ++ return (EVP_MD_meth_dup(md)); ++} ++ ++static void ++rs256_free_EVP_MD(EVP_MD *md) ++{ ++ EVP_MD_meth_free(md); ++} ++#endif /* LIBRESSL_VERSION_NUMBER */ ++ + static int + decode_bignum(const cbor_item_t *item, void *ptr, size_t len) + { +@@ -178,32 +227,39 @@ rs256_verify_sig(const fido_blob_t *dgst, const rs256_pk_t *pk, + const fido_blob_t *sig) + { + EVP_PKEY *pkey = NULL; +- RSA *rsa = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_MD *md = NULL; + int ok = -1; + +- /* RSA_verify needs unsigned ints */ +- if (dgst->len > UINT_MAX || sig->len > UINT_MAX) { +- fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__, +- dgst->len, sig->len); +- return (-1); ++ if ((md = rs256_get_EVP_MD()) == NULL) { ++ fido_log_debug("%s: rs256_get_EVP_MD", __func__); ++ goto fail; ++ } ++ ++ if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) { ++ fido_log_debug("%s: rs256_pk_to_EVP_PKEY", __func__); ++ goto fail; + } + +- if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL || +- (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { +- fido_log_debug("%s: pk -> ec", __func__); ++ if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL || ++ EVP_PKEY_verify_init(pctx) != 1 || ++ EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 || ++ EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) { ++ fido_log_debug("%s: EVP_PKEY_CTX", __func__); + goto fail; + } + +- if (RSA_verify(NID_sha256, dgst->ptr, (unsigned int)dgst->len, sig->ptr, +- (unsigned int)sig->len, rsa) != 1) { +- fido_log_debug("%s: RSA_verify", __func__); ++ if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr, ++ dgst->len) != 1) { ++ fido_log_debug("%s: EVP_PKEY_verify", __func__); + goto fail; + } + + ok = 0; + fail: +- if (pkey != NULL) +- EVP_PKEY_free(pkey); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(pctx); ++ rs256_free_EVP_MD(md); + + return (ok); + } +-- +2.31.1 + diff --git a/0008-Define-OPENSSL_API_COMPAT-if-OpenSSL-3.0-is-detected.patch b/0008-Define-OPENSSL_API_COMPAT-if-OpenSSL-3.0-is-detected.patch new file mode 100644 index 0000000..4f422d9 --- /dev/null +++ b/0008-Define-OPENSSL_API_COMPAT-if-OpenSSL-3.0-is-detected.patch @@ -0,0 +1,34 @@ +From 29c0eca2a2cc19201d9f231005920c02abfffbca Mon Sep 17 00:00:00 2001 +From: pedro martelletto +Date: Tue, 3 Aug 2021 16:26:22 +0200 +Subject: [PATCH 20/70] Define OPENSSL_API_COMPAT if OpenSSL 3.0 is detected + +If OpenSSL 3.0 is detected, build with OPENSSL_API_COMPAT set to +0x10100000L to suppress deprecation warnings on otherwise working +code. Discussed with Dmitry Belyavskiy (@beldmit). +--- + CMakeLists.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ecf3448..10bb8a6 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -277,9 +277,14 @@ else() + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") + ++ if(CRYPTO_VERSION VERSION_GREATER_EQUAL 3.0) ++ add_definitions(-DOPENSSL_API_COMPAT=0x10100000L) ++ endif() ++ + if(FUZZ) + add_definitions(-DFIDO_FUZZ) + endif() ++ + if(LIBFUZZER) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link") + endif() +-- +2.31.1 + diff --git a/libfido2.spec b/libfido2.spec index 2bfa435..ac331b1 100644 --- a/libfido2.spec +++ b/libfido2.spec @@ -1,7 +1,7 @@ Name: libfido2 Version: 1.8.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: FIDO2 library License: BSD @@ -10,6 +10,16 @@ Source0: https://developers.yubico.com/%{name}/Releases/%{name}-%{version Source1: https://developers.yubico.com/%{name}/Releases/%{name}-%{version}.tar.gz.sig Source2: yubico-release-gpgkeys.asc +# Upstream patches for OpenSSL 3.0 compatibility +Patch0001: 0001-Replace-SHA256_-with-EVP_-equivalents.patch +Patch0002: 0002-Rename-and-move-fido_verify_sig_-eddsa-es256-rs256.patch +Patch0003: 0003-cred-rework-verify_sig.patch +Patch0004: 0004-ecdh-explicit-cast-to-silence-warning-with-OpenSSL-3.patch +Patch0005: 0005-es256-make-es256_verify_sig-OpenSSL-3.0-compatible.patch +Patch0006: 0006-rs256-drop-OpenSSL-1.0-compatibility-shim.patch +Patch0007: 0007-rs256-make-rs256_verify_sig-OpenSSL-3.0-compatible.patch +Patch0008: 0008-Define-OPENSSL_API_COMPAT-if-OpenSSL-3.0-is-detected.patch + BuildRequires: cmake BuildRequires: hidapi-devel BuildRequires: libcbor-devel @@ -86,6 +96,9 @@ find %{buildroot} -type f -name "*.a" -delete -print %changelog +* Wed Sep 15 2021 Gary Buhrmaster - 1.8.0-3 +- Apply upstream patches for OpenSSL 3.0 + * Tue Sep 14 2021 Sahana Prasad - 1.8.0-2 - Rebuilt with OpenSSL 3.0.0