| /* |
| * Copyright (C) 2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "Test.h" |
| |
| #if ENABLE(SERVICE_WORKER) |
| |
| #include <WebCore/PushMessageCrypto.h> |
| #include <wtf/text/Base64.h> |
| |
| namespace TestWebKitAPI { |
| using namespace WebCore::PushCrypto; |
| |
| static Vector<uint8_t> mustBase64URLDecode(const String& encoded) |
| { |
| return base64URLDecode(encoded).value(); |
| } |
| |
| static ClientKeys makeAES128GCMClientKeys(void) |
| { |
| // Example values from RFC8291 Section 5. |
| auto publicKey = mustBase64URLDecode("BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4"_s); |
| auto privateKey = mustBase64URLDecode("q1dXpw3UpT5VOmu_cf_v6ih07Aems3njxI-JWgLcM94"_s); |
| auto secret = mustBase64URLDecode("BTBZMqHH6r4Tts7J_aSIgg"_s); |
| |
| return ClientKeys { |
| P256DHKeyPair { WTFMove(publicKey), WTFMove(privateKey) }, |
| WTFMove(secret) |
| }; |
| } |
| |
| TEST(PushMessageCrypto, AES128GCMPayloadWithMinimalPadding) |
| { |
| // Example payload from RFC8291 Section 5. |
| auto clientKeys = makeAES128GCMClientKeys(); |
| auto payload = mustBase64URLDecode("DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_Qulcy4a-fN"_s); |
| |
| auto result = decryptAES128GCMPayload(clientKeys, payload); |
| ASSERT_TRUE(result.has_value()); |
| |
| auto actual = String::adopt(WTFMove(*result)); |
| ASSERT_EQ("When I grow up, I want to be a watermelon"_s, actual); |
| } |
| |
| TEST(PushMessageCrypto, AES128GCMPayloadWithPadding) |
| { |
| auto clientKeys = makeAES128GCMClientKeys(); |
| auto payload = mustBase64URLDecode("DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_DkNRXA6CYFiG805FVNqPbr9v9EW9lfwpny0c"_s); |
| |
| auto result = decryptAES128GCMPayload(clientKeys, payload); |
| ASSERT_TRUE(result.has_value()); |
| |
| auto actual = String::adopt(WTFMove(*result)); |
| ASSERT_EQ("foobar"_s, actual); |
| } |
| |
| TEST(PushMessageCrypto, AES128GCMPayloadWithIncorrectPadding) |
| { |
| auto clientKeys = makeAES128GCMClientKeys(); |
| auto payload = mustBase64URLDecode("DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_DkNRXA6CbFiG80zK6Bf1IRIL9ovjHp7iLjCw"_s); |
| |
| auto result = decryptAES128GCMPayload(clientKeys, payload); |
| ASSERT_FALSE(result.has_value()); |
| } |
| |
| TEST(PushMessageCrypto, AES128GCMPayloadWithEmptyPlaintext) |
| { |
| auto clientKeys = makeAES128GCMClientKeys(); |
| auto payload = mustBase64URLDecode("DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A-nWA9JFLVeQ32ERULH8YEUcA"_s); |
| |
| auto result = decryptAES128GCMPayload(clientKeys, payload); |
| ASSERT_TRUE(result.has_value()); |
| ASSERT_TRUE(result->isEmpty()); |
| } |
| |
| static ClientKeys makeAESGCMClientKeys(void) |
| { |
| // Example values from draft-ietf-webpush-encryption-04 Section 5. |
| auto publicKey = mustBase64URLDecode("BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3il2nNZct4HgAUQU"_s); |
| auto privateKey = mustBase64URLDecode("9FWl15_QUQAWDaD3k3l50ZBZQJ4au27F1V4F0uLSD_M"_s); |
| auto secret = mustBase64URLDecode("R29vIGdvbyBnJyBqb29iIQ"_s); |
| |
| return ClientKeys { |
| P256DHKeyPair { WTFMove(publicKey), WTFMove(privateKey) }, |
| WTFMove(secret) |
| }; |
| } |
| |
| TEST(PushMessageCrypto, AESGCMPayloadWithMinimalPadding) |
| { |
| // Example values from draft-ietf-webpush-encryption-04 Section 5. |
| auto clientKeys = makeAESGCMClientKeys(); |
| auto salt = mustBase64URLDecode("lngarbyKfMoi9Z75xYXmkg"_s); |
| auto serverPublicKey = mustBase64URLDecode("BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"_s); |
| auto payload = mustBase64URLDecode("6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA"_s); |
| |
| auto result = decryptAESGCMPayload(clientKeys, serverPublicKey, salt, payload); |
| ASSERT_TRUE(result.has_value()); |
| |
| auto actual = String::adopt(WTFMove(*result)); |
| ASSERT_EQ("I am the walrus"_s, actual); |
| } |
| |
| TEST(PushMessageCrypto, AESGCMPayloadWithPadding) |
| { |
| auto clientKeys = makeAESGCMClientKeys(); |
| auto salt = mustBase64URLDecode("lngarbyKfMoi9Z75xYXmkg"_s); |
| auto serverPublicKey = mustBase64URLDecode("BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"_s); |
| auto payload = mustBase64URLDecode("6nnJYSIPvQhgx8ApDFDkWY6v5N9KAuur3Nv6"_s); |
| |
| auto result = decryptAESGCMPayload(clientKeys, serverPublicKey, salt, payload); |
| ASSERT_TRUE(result.has_value()); |
| |
| auto actual = String::adopt(WTFMove(*result)); |
| ASSERT_EQ("foobar"_s, actual); |
| } |
| |
| TEST(PushMessageCrypto, AESGCMPayloadWithIncorrectPadding) |
| { |
| auto clientKeys = makeAESGCMClientKeys(); |
| auto salt = mustBase64URLDecode("lngarbyKfMoi9Z75xYXmkg"_s); |
| auto serverPublicKey = mustBase64URLDecode("BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"_s); |
| auto payload = mustBase64URLDecode("6n7JYSNptAhtxNNyA5YtGywKZGxwcbEsBPqauw"_s); |
| |
| auto result = decryptAESGCMPayload(clientKeys, serverPublicKey, salt, payload); |
| ASSERT_FALSE(result.has_value()); |
| } |
| |
| TEST(PushMessageCrypto, AESGCMPayloadWithEmptyPlaintext) |
| { |
| auto clientKeys = makeAESGCMClientKeys(); |
| auto salt = mustBase64URLDecode("lngarbyKfMoi9Z75xYXmkg"_s); |
| auto serverPublicKey = mustBase64URLDecode("BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU"_s); |
| auto payload = mustBase64URLDecode("6nogQ_ptbmKpIB8yi4_4H0LS"_s); |
| |
| auto result = decryptAESGCMPayload(clientKeys, serverPublicKey, salt, payload); |
| ASSERT_TRUE(result.has_value()); |
| ASSERT_TRUE(result->isEmpty()); |
| } |
| |
| } |
| |
| #endif |