Bug 224083

Summary: WebCrypto in Safari will not AES-GCM encrypt 0 bytes
Product: WebKit Reporter: Jiewen Tan <jiewen_tan>
Component: WebCore Misc.Assignee: Jiewen Tan <jiewen_tan>
Status: RESOLVED FIXED    
Severity: Normal CC: bfulgham, darin, jiewen_tan, webkit-bug-importer, youennf
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch
none
Patch
youennf: review+
Patch for landing none

Description Jiewen Tan 2021-04-01 15:40:04 PDT
WebCrypto in Safari will not AES-GCM encrypt 0 bytes.
Comment 1 Jiewen Tan 2021-04-01 15:40:16 PDT Comment hidden (obsolete)
Comment 2 Jiewen Tan 2021-04-01 15:45:19 PDT
Created attachment 424955 [details]
Patch
Comment 3 youenn fablet 2021-04-02 01:22:36 PDT
Comment on attachment 424955 [details]
Patch

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

> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:42
> +    cipherText.reserveCapacity(cipherText.size() + desiredTagLengthInBytes);

Can we just do Vector<uint8_t> cipherText(plainText.size() + desiredTagLengthInBytes) and update below code to memcpy the tag?
This would allow to do a single allocation.

> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:61
> +    plainText.reserveCapacity(cipherText.size());

Are we guaranteed that cipherText.size() <= desiredTagLengthInBytes?
If not, can we just write:
if (cipherText.size() <= desiredTagLengthInBytes)
    return Vector<uint8_t> { };

If this is guaranteed, can we do:
auto length = cipherText.size() - desiredTagLengthInBytes;
if (!length)
    return Vector<uint8_t> { };
Comment 4 Jiewen Tan 2021-04-02 19:17:01 PDT
Comment on attachment 424955 [details]
Patch

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

Thanks Youenn for reviewing this patch.

>> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:42
>> +    cipherText.reserveCapacity(cipherText.size() + desiredTagLengthInBytes);
> 
> Can we just do Vector<uint8_t> cipherText(plainText.size() + desiredTagLengthInBytes) and update below code to memcpy the tag?
> This would allow to do a single allocation.

Good catch. Fixed.

>> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:61
>> +    plainText.reserveCapacity(cipherText.size());
> 
> Are we guaranteed that cipherText.size() <= desiredTagLengthInBytes?
> If not, can we just write:
> if (cipherText.size() <= desiredTagLengthInBytes)
>     return Vector<uint8_t> { };
> 
> If this is guaranteed, can we do:
> auto length = cipherText.size() - desiredTagLengthInBytes;
> if (!length)
>     return Vector<uint8_t> { };

We cannot return empty vector directly. The cipher will contain the tag which will need to be validated by the AES-GCM algorithm.
Comment 5 Jiewen Tan 2021-04-02 19:20:26 PDT
Created attachment 425078 [details]
Patch
Comment 6 youenn fablet 2021-04-06 10:10:31 PDT
Comment on attachment 425078 [details]
Patch

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

> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:73
> +    plainText.shrink(cipherText.size() - desiredTagLengthInBytes);

You could use offset here.
Comment 7 Jiewen Tan 2021-04-06 10:33:58 PDT
Comment on attachment 425078 [details]
Patch

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

Thanks Youenn for r+ this patch.

>> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:73
>> +    plainText.shrink(cipherText.size() - desiredTagLengthInBytes);
> 
> You could use offset here.

Good catch. Fixed.
Comment 8 Jiewen Tan 2021-04-06 10:39:15 PDT
Created attachment 425300 [details]
Patch for landing
Comment 9 Jiewen Tan 2021-04-06 10:44:39 PDT
rdar://59951871
Comment 10 EWS 2021-04-06 11:10:36 PDT
Committed r275535: <https://commits.webkit.org/r275535>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 425300 [details].
Comment 11 Darin Adler 2021-04-06 14:46:33 PDT
Comment on attachment 425300 [details]
Patch for landing

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

> Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:40
> +    // This is a wordaround for rdar://75093377. Force the buffer to be a non null pointer.

Typo in "workaround" here, and 2 other places below.

Also not sure we should call this a "workaround". Just because we misunderstood and thought the pointer could be null, doesn’t mean we should comment each line saying "workaround" like this.

Honestly, I find the relationship of the comment to he code confusing. I am fairly expect on how Vector works and I can’t find anything here that is "forcing" a buffer to be a non-null pointer.
Comment 12 Jiewen Tan 2021-04-08 14:02:03 PDT
(In reply to Darin Adler from comment #11)
> Comment on attachment 425300 [details]
> Patch for landing
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=425300&action=review
> 
> > Source/WebCore/crypto/mac/CryptoAlgorithmAES_GCMMac.cpp:40
> > +    // This is a wordaround for rdar://75093377. Force the buffer to be a non null pointer.
> 
> Typo in "workaround" here, and 2 other places below.
> 
> Also not sure we should call this a "workaround". Just because we
> misunderstood and thought the pointer could be null, doesn’t mean we should
> comment each line saying "workaround" like this.
> 
> Honestly, I find the relationship of the comment to he code confusing. I am
> fairly expect on how Vector works and I can’t find anything here that is
> "forcing" a buffer to be a non-null pointer.

Got you. Will land a follow up to fix the comments. As long as the Vector's capacity is larger than 0, then .data() will be non-null pointer.
Comment 13 Jiewen Tan 2021-04-08 14:31:08 PDT
A follow up according to Darin's comment.
Committed r275678: <https://commits.webkit.org/r275678>
Committed r275678 (236314@main): <https://commits.webkit.org/236314@main>