Bug 239858 - [OpenSSL] Treat types as opaque
Summary: [OpenSSL] Treat types as opaque
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Platform (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Don Olmstead
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2022-04-28 10:30 PDT by Don Olmstead
Modified: 2022-06-02 22:03 PDT (History)
5 users (show)

See Also:


Attachments
Patch (15.85 KB, patch)
2022-04-28 10:38 PDT, Don Olmstead
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (15.88 KB, patch)
2022-04-28 11:13 PDT, Don Olmstead
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (16.07 KB, patch)
2022-04-29 15:39 PDT, Don Olmstead
no flags Details | Formatted Diff | Diff
Patch (16.09 KB, patch)
2022-05-09 14:26 PDT, Don Olmstead
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (16.22 KB, patch)
2022-05-10 16:17 PDT, Don Olmstead
no flags Details | Formatted Diff | Diff
Patch (16.78 KB, patch)
2022-05-11 10:32 PDT, Don Olmstead
no flags Details | Formatted Diff | Diff
Patch (16.78 KB, patch)
2022-05-11 11:34 PDT, Don Olmstead
Basuke.Suzuki: review+
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (16.80 KB, patch)
2022-05-12 16:35 PDT, Don Olmstead
no flags Details | Formatted Diff | Diff
Patch (16.76 KB, patch)
2022-05-12 16:47 PDT, Don Olmstead
ews-feeder: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Don Olmstead 2022-04-28 10:30:09 PDT
OpenSSL types should not be accessed directly. Instead use functions to access and modify instances.

LibreSSL made the types completely opaque in 3.5.x release so WebKit won't build with an updated library.
Comment 1 Don Olmstead 2022-04-28 10:38:00 PDT Comment hidden (obsolete)
Comment 2 Don Olmstead 2022-04-28 11:13:59 PDT
Created attachment 458535 [details]
Patch
Comment 3 Yoshiaki Jitsukawa 2022-04-28 17:25:52 PDT
(In reply to Don Olmstead from comment #2)
> Created attachment 458535 [details]
> Patch

LGTM besides style warings.
Comment 4 Don Olmstead 2022-04-29 15:39:44 PDT
Created attachment 458613 [details]
Patch
Comment 5 Radar WebKit Bug Importer 2022-05-05 10:31:14 PDT
<rdar://problem/92805748>
Comment 6 Don Olmstead 2022-05-09 14:26:45 PDT
Created attachment 459081 [details]
Patch
Comment 7 Basuke Suzuki 2022-05-09 15:09:14 PDT
Comment on attachment 459081 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459081&action=review

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:84
> +    auto n = convertToBigNumber(keyData.modulus());

I think it should be wrapped by `BIGNUMPtr` if it's allocated. More to say, if convertToBigNumber always allocate a new memory, then it can return BIGNUMPtr wrapped result.

> Source/WebCore/crypto/openssl/OpenSSLUtilities.h:47
> +BIGNUM* convertToBigNumber(const Vector<uint8_t>& bytes, BIGNUM* ret = nullptr);

If all usage doesn't pass second argument, why can't we remove the second argument?
Comment 8 Don Olmstead 2022-05-09 15:12:58 PDT
Comment on attachment 459081 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459081&action=review

>> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:84
>> +    auto n = convertToBigNumber(keyData.modulus());
> 
> I think it should be wrapped by `BIGNUMPtr` if it's allocated. More to say, if convertToBigNumber always allocate a new memory, then it can return BIGNUMPtr wrapped result.

When the associated `set` is called OpenSSL then takes over the BIGNUM so we wouldn't want it accidentally deleted.

>> Source/WebCore/crypto/openssl/OpenSSLUtilities.h:47
>> +BIGNUM* convertToBigNumber(const Vector<uint8_t>& bytes, BIGNUM* ret = nullptr);
> 
> If all usage doesn't pass second argument, why can't we remove the second argument?

I'm fine with removing it. Can add back later if its needed.
Comment 9 Basuke Suzuki 2022-05-10 14:07:10 PDT
Comment on attachment 459081 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459081&action=review

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:86
> +    if (!n || !e)

Then if n is assigned and e was failed, here comes a memory leak.
Comment 10 Don Olmstead 2022-05-10 16:17:22 PDT
Created attachment 459139 [details]
Patch
Comment 11 Basuke Suzuki 2022-05-10 16:32:44 PDT
Comment on attachment 459139 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459139&action=review

Always I feel it's difficult to use OpenSSL in C++ code.

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:98
> +        if (!RSA_set0_factors(rsa.get(), p.release(), q.release()))

Do they release the parameter on failure?

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:110
> +        if (!RSA_set0_crt_params(rsa.get(), dmp1.release(), dmq1.release(), iqmp.release()))

Ditto.

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:114
> +    if (!RSA_set0_key(rsa.get(), n.release(), e.release(), d.release()))

Ditto.
Comment 12 Don Olmstead 2022-05-11 10:32:25 PDT
Created attachment 459172 [details]
Patch
Comment 13 Don Olmstead 2022-05-11 10:33:20 PDT
Good catch Basuke! I made it so the release happens after success and I called out the ownership transfer.
Comment 14 Basuke Suzuki 2022-05-11 11:14:00 PDT
Comment on attachment 459172 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459172&action=review

For memory perspective, LGTM. Some extra note was added.

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:45
> +    return RSA_bits(rsa) * 8;

Does this returns same value? The previous one seems bits. It sounds RSA_bits() already returns bits, not byte. I'm not confident about this, but function names sounds confusing so that I'm confirming it.

> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:95
> +    e.release();

How about wrapping with scope instead of releasing explicitly? It's a bit noisy to see explicit release for smart pointers. Also scoping is a standard technique to be used to narrow the effectiveness of variables, not only for smart pointers.
Comment 15 Don Olmstead 2022-05-11 11:32:50 PDT
Comment on attachment 459172 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459172&action=review

>> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:45
>> +    return RSA_bits(rsa) * 8;
> 
> Does this returns same value? The previous one seems bits. It sounds RSA_bits() already returns bits, not byte. I'm not confident about this, but function names sounds confusing so that I'm confirming it.

You're right it should `RSA_size`

From LibreSSL's implementation

int
RSA_bits(const RSA *r)
{
	return BN_num_bits(r->n);
}

vs

int
RSA_size(const RSA *r)
{
	return BN_num_bytes(r->n);
}

>> Source/WebCore/crypto/openssl/CryptoKeyRSAOpenSSL.cpp:95
>> +    e.release();
> 
> How about wrapping with scope instead of releasing explicitly? It's a bit noisy to see explicit release for smart pointers. Also scoping is a standard technique to be used to narrow the effectiveness of variables, not only for smart pointers.

From https://en.cppreference.com/w/cpp/memory/unique_ptr/release

Releases the ownership of the managed object, if any.

get() returns nullptr after the call.

The caller is responsible for deleting the object.

In these cases ownership is transferred to OpenSSL so we don't want the std::unique_ptr to try and delete it and we can accomplish this by using release.
Comment 16 Don Olmstead 2022-05-11 11:34:33 PDT
Created attachment 459175 [details]
Patch
Comment 17 Basuke Suzuki 2022-05-11 11:39:40 PDT
Got it. I didn't get the point of transferring. Then it makes sense.

r=me
Comment 18 Yoshiaki Jitsukawa 2022-05-12 05:16:59 PDT
I've yet to look into the issue but with the patch (id=459175) relevant crypt/subtle tests come to fail.
Comment 19 Don Olmstead 2022-05-12 16:35:34 PDT
Created attachment 459257 [details]
Patch

Fixed the crash, was retrieving the wrong values in algorithm.
Comment 20 Don Olmstead 2022-05-12 16:47:33 PDT
Created attachment 459259 [details]
Patch
Comment 21 Yoshiaki Jitsukawa 2022-05-12 17:06:57 PDT
Comment on attachment 459259 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=459259&action=review

> Source/WebCore/crypto/openssl/OpenSSLUtilities.h:46
> +BIGNUMPtr convertToBigNumber(const Vector<uint8_t>& bytes);

I'm against to force programmers to use BIGNUMPtr returned by convertToBigNumber() because this force programmers to write ownership transfer code in normal codepaths (otherwise use-after-free would happen). This seems more error-prone to me than memory leak in error cases of set0, which never happens with the current libressl implementation.
Comment 22 Yoshiaki Jitsukawa 2022-05-12 17:35:54 PDT
We may want to have a wrapper template function for set0 family that releases BIGNUMs if set0 fails.
Comment 23 Don Olmstead 2022-05-25 13:32:52 PDT
Pull request: https://github.com/webkit/webkit/pull/1023
Comment 24 EWS 2022-06-02 22:03:57 PDT
Committed r295168 (251252@main): <https://commits.webkit.org/251252@main>

Reviewed commits have been landed. Closing PR #1023 and removing active labels.