Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
pgcrypto: Detect errors with EVP calls from OpenSSL
authorMichael Paquier <michael@paquier.xyz>
Tue, 8 Dec 2020 06:23:02 +0000 (15:23 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 8 Dec 2020 06:23:02 +0000 (15:23 +0900)
The following routines are called within pgcrypto when handling digests
but there were no checks for failures:
- EVP_MD_CTX_size (can fail with -1 as of 3.0.0)
- EVP_MD_CTX_block_size (can fail with -1 as of 3.0.0)
- EVP_DigestInit_ex
- EVP_DigestUpdate
- EVP_DigestFinal_ex

A set of elog(ERROR) is added by this commit to detect such failures,
that should never happen except in the event of a processing failure
internal to OpenSSL.

Note that it would be possible to use ERR_reason_error_string() to get
more context about such errors, but these refer mainly to the internals
of OpenSSL, so it is not really obvious how useful that would be.  This
is left out for simplicity.

Per report from Coverity.  Thanks to Tom Lane for the discussion.

Backpatch-through: 9.5

contrib/pgcrypto/openssl.c

index 1f9cde641753422b6f38917ee85547b74b204af4..85c84e6769643b5cf6f6c507fb2db799985d91a8 100644 (file)
@@ -267,16 +267,24 @@ static unsigned
 digest_result_size(PX_MD *h)
 {
    OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
+   int         result = EVP_MD_CTX_size(digest->ctx);
 
-   return EVP_MD_CTX_size(digest->ctx);
+   if (result < 0)
+       elog(ERROR, "EVP_MD_CTX_size() failed");
+
+   return result;
 }
 
 static unsigned
 digest_block_size(PX_MD *h)
 {
    OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
+   int         result = EVP_MD_CTX_block_size(digest->ctx);
+
+   if (result < 0)
+       elog(ERROR, "EVP_MD_CTX_block_size() failed");
 
-   return EVP_MD_CTX_block_size(digest->ctx);
+   return result;
 }
 
 static void
@@ -284,7 +292,8 @@ digest_reset(PX_MD *h)
 {
    OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
 
-   EVP_DigestInit_ex(digest->ctx, digest->algo, NULL);
+   if (!EVP_DigestInit_ex(digest->ctx, digest->algo, NULL))
+       elog(ERROR, "EVP_DigestInit_ex() failed");
 }
 
 static void
@@ -292,7 +301,8 @@ digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
 {
    OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
 
-   EVP_DigestUpdate(digest->ctx, data, dlen);
+   if (!EVP_DigestUpdate(digest->ctx, data, dlen))
+       elog(ERROR, "EVP_DigestUpdate() failed");
 }
 
 static void
@@ -300,7 +310,8 @@ digest_finish(PX_MD *h, uint8 *dst)
 {
    OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
 
-   EVP_DigestFinal_ex(digest->ctx, dst, NULL);
+   if (!EVP_DigestFinal_ex(digest->ctx, dst, NULL))
+       elog(ERROR, "EVP_DigestFinal_ex() failed");
 }
 
 static void