Hi all, Enabling FIPS with OpenSSL 1.0.2 causes direct calls to the SHAXXX routines to fail: "Low level API call to digest SHA256 forbidden in fips mode"
This got discussed back in 2018, but I never got back to it: https://www.postgresql.org/message-id/20180911030250.ga27...@paquier.xyz One thing I did not like back in the past patch was that we did not handle failures if one of OpenSSL's call failed, but this can easily be handled by using a trick similar to jsonapi.c to fail hard if that happens. It is worth noting that the low-level SHA routines are not recommended for years in OpenSSL, and that these have been officially marked as deprecated in 3.0.0. So, while the changes in sha2.h don't make this stuff back-patchable per the ABI breakage it introduces, switching sha2_openssl.c to use EVP is a better move in the long term, even if that means that SCRAM+FIPS would not work with PG 10~13, so the attached is something for HEAD, even if this would be possible to do in older releases as the routines used in the attached are available in versions of OpenSSL older than 1.0.1. Any thoughts? -- Michael
diff --git a/src/include/common/sha2.h b/src/include/common/sha2.h index 9c4abf777d..2c52838161 100644 --- a/src/include/common/sha2.h +++ b/src/include/common/sha2.h @@ -51,7 +51,7 @@ #define _PG_SHA2_H_ #ifdef USE_OPENSSL -#include <openssl/sha.h> +#include <openssl/evp.h> #endif /*** SHA224/256/384/512 Various Length Definitions ***********************/ @@ -70,10 +70,10 @@ /* Context Structures for SHA224/256/384/512 */ #ifdef USE_OPENSSL -typedef SHA256_CTX pg_sha256_ctx; -typedef SHA512_CTX pg_sha512_ctx; -typedef SHA256_CTX pg_sha224_ctx; -typedef SHA512_CTX pg_sha384_ctx; +typedef EVP_MD_CTX *pg_sha256_ctx; +typedef EVP_MD_CTX *pg_sha512_ctx; +typedef EVP_MD_CTX *pg_sha224_ctx; +typedef EVP_MD_CTX *pg_sha384_ctx; #else typedef struct pg_sha256_ctx { diff --git a/src/common/sha2_openssl.c b/src/common/sha2_openssl.c index 41673b3a88..1d0b254487 100644 --- a/src/common/sha2_openssl.c +++ b/src/common/sha2_openssl.c @@ -20,83 +20,116 @@ #include "postgres_fe.h" #endif -#include <openssl/sha.h> - #include "common/sha2.h" +#ifdef FRONTEND +#include "common/logging.h" +#else +#include "miscadmin.h" +#endif + +#ifdef FRONTEND +#define sha2_log_and_abort(...) \ + do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0) +#else +#define sha2_log_and_abort(...) elog(ERROR, __VA_ARGS__) +#endif + +static void +digest_init(EVP_MD_CTX **ctx, const EVP_MD *type) +{ + *ctx = EVP_MD_CTX_create(); + if (*ctx == NULL) + sha2_log_and_abort("could not create EVP digest context"); + EVP_DigestInit_ex(*ctx, type, NULL); +} + +static void +digest_update(EVP_MD_CTX **ctx, const uint8 *data, size_t len) +{ + EVP_DigestUpdate(*ctx, data, len); +} + +static void +digest_final(EVP_MD_CTX **ctx, uint8 *dest) +{ + if (EVP_DigestFinal_ex(*ctx, dest, 0) <= 0) + sha2_log_and_abort("could not finalize EVP digest context"); + EVP_MD_CTX_destroy(*ctx); +} /* Interface routines for SHA-256 */ void pg_sha256_init(pg_sha256_ctx *ctx) { - SHA256_Init((SHA256_CTX *) ctx); + digest_init(ctx, EVP_sha256()); } void pg_sha256_update(pg_sha256_ctx *ctx, const uint8 *data, size_t len) { - SHA256_Update((SHA256_CTX *) ctx, data, len); + digest_update(ctx, data, len); } void pg_sha256_final(pg_sha256_ctx *ctx, uint8 *dest) { - SHA256_Final(dest, (SHA256_CTX *) ctx); + digest_final(ctx, dest); } /* Interface routines for SHA-512 */ void pg_sha512_init(pg_sha512_ctx *ctx) { - SHA512_Init((SHA512_CTX *) ctx); + digest_init(ctx, EVP_sha512()); } void pg_sha512_update(pg_sha512_ctx *ctx, const uint8 *data, size_t len) { - SHA512_Update((SHA512_CTX *) ctx, data, len); + digest_update(ctx, data, len); } void pg_sha512_final(pg_sha512_ctx *ctx, uint8 *dest) { - SHA512_Final(dest, (SHA512_CTX *) ctx); + digest_final(ctx, dest); } /* Interface routines for SHA-384 */ void pg_sha384_init(pg_sha384_ctx *ctx) { - SHA384_Init((SHA512_CTX *) ctx); + digest_init(ctx, EVP_sha384()); } void pg_sha384_update(pg_sha384_ctx *ctx, const uint8 *data, size_t len) { - SHA384_Update((SHA512_CTX *) ctx, data, len); + digest_update(ctx, data, len); } void pg_sha384_final(pg_sha384_ctx *ctx, uint8 *dest) { - SHA384_Final(dest, (SHA512_CTX *) ctx); + digest_final(ctx, dest); } /* Interface routines for SHA-224 */ void pg_sha224_init(pg_sha224_ctx *ctx) { - SHA224_Init((SHA256_CTX *) ctx); + digest_init(ctx, EVP_sha224()); } void pg_sha224_update(pg_sha224_ctx *ctx, const uint8 *data, size_t len) { - SHA224_Update((SHA256_CTX *) ctx, data, len); + digest_update(ctx, data, len); } void pg_sha224_final(pg_sha224_ctx *ctx, uint8 *dest) { - SHA224_Final(dest, (SHA256_CTX *) ctx); + digest_final(ctx, dest); }
signature.asc
Description: PGP signature