mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 15:27:32 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
178
mobile/ios/ThirdParty/ecec/test/base64url.c
vendored
Normal file
178
mobile/ios/ThirdParty/ecec/test/base64url.c
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct base64url_encode_test_s {
|
||||
const char* binary;
|
||||
size_t binaryLen;
|
||||
ece_base64url_encode_policy_t paddingPolicy;
|
||||
const char* base64;
|
||||
size_t base64Len;
|
||||
} base64url_encode_test_t;
|
||||
|
||||
static base64url_encode_test_t base64url_encode_tests[] = {
|
||||
{"f", 1, ECE_BASE64URL_OMIT_PADDING, "Zg", 2},
|
||||
{"f", 1, ECE_BASE64URL_INCLUDE_PADDING, "Zg==", 4},
|
||||
|
||||
{"fo", 2, ECE_BASE64URL_OMIT_PADDING, "Zm8", 3},
|
||||
{"fo", 2, ECE_BASE64URL_INCLUDE_PADDING, "Zm8=", 4},
|
||||
|
||||
{"foo", 3, ECE_BASE64URL_OMIT_PADDING, "Zm9v", 4},
|
||||
{"foo", 3, ECE_BASE64URL_INCLUDE_PADDING, "Zm9v", 4},
|
||||
|
||||
{"foob", 4, ECE_BASE64URL_OMIT_PADDING, "Zm9vYg", 6},
|
||||
{"foob", 4, ECE_BASE64URL_INCLUDE_PADDING, "Zm9vYg==", 8},
|
||||
|
||||
{"fooba", 5, ECE_BASE64URL_OMIT_PADDING, "Zm9vYmE", 7},
|
||||
{"fooba", 5, ECE_BASE64URL_INCLUDE_PADDING, "Zm9vYmE=", 8},
|
||||
|
||||
{"foobar", 6, ECE_BASE64URL_OMIT_PADDING, "Zm9vYmFy", 8},
|
||||
{"foobar", 6, ECE_BASE64URL_INCLUDE_PADDING, "Zm9vYmFy", 8},
|
||||
|
||||
{"\x14\xfb\x9c\x03\xd9\x7e", 6, ECE_BASE64URL_OMIT_PADDING, "FPucA9l-", 8},
|
||||
{"\x14\xfb\x9c\x03\xd9\x7e", 6, ECE_BASE64URL_INCLUDE_PADDING, "FPucA9l-", 8},
|
||||
|
||||
{"\x14\xfb\x9c\x03\xd9", 5, ECE_BASE64URL_OMIT_PADDING, "FPucA9k", 7},
|
||||
{"\x14\xfb\x9c\x03\xd9", 5, ECE_BASE64URL_INCLUDE_PADDING, "FPucA9k=", 8},
|
||||
|
||||
{"\x14\xfb\x9c\x03", 4, ECE_BASE64URL_OMIT_PADDING, "FPucAw", 6},
|
||||
{"\x14\xfb\x9c\x03", 4, ECE_BASE64URL_INCLUDE_PADDING, "FPucAw==", 8},
|
||||
};
|
||||
|
||||
typedef struct base64url_decode_test_s {
|
||||
const char* base64;
|
||||
size_t base64Len;
|
||||
ece_base64url_decode_policy_t paddingPolicy;
|
||||
size_t requiredBinaryLen;
|
||||
const char* binary;
|
||||
size_t binaryLen;
|
||||
} base64url_decode_test_t;
|
||||
|
||||
static base64url_decode_test_t base64url_decode_tests[] = {
|
||||
// Test vectors from RFC 4648, section 10.
|
||||
{"", 0, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
|
||||
{"Zg", 2, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"Zg", 2, ECE_BASE64URL_IGNORE_PADDING, 1, "f", 1},
|
||||
{"Zg", 2, ECE_BASE64URL_REJECT_PADDING, 1, "f", 1},
|
||||
|
||||
{"Zg==", 4, ECE_BASE64URL_REQUIRE_PADDING, 1, "f", 1},
|
||||
{"Zg==", 4, ECE_BASE64URL_IGNORE_PADDING, 1, "f", 1},
|
||||
{"Zg==", 4, ECE_BASE64URL_REJECT_PADDING, 3, NULL, 0},
|
||||
|
||||
{"Zm8", 3, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"Zm8", 3, ECE_BASE64URL_IGNORE_PADDING, 2, "fo", 2},
|
||||
{"Zm8", 3, ECE_BASE64URL_REJECT_PADDING, 2, "fo", 2},
|
||||
|
||||
{"Zm8=", 4, ECE_BASE64URL_REQUIRE_PADDING, 2, "fo", 2},
|
||||
{"Zm8=", 4, ECE_BASE64URL_IGNORE_PADDING, 2, "fo", 2},
|
||||
{"Zm8=", 4, ECE_BASE64URL_REJECT_PADDING, 3, NULL, 0},
|
||||
|
||||
{"Zm9v", 4, ECE_BASE64URL_REQUIRE_PADDING, 3, "foo", 3},
|
||||
{"Zm9v", 4, ECE_BASE64URL_IGNORE_PADDING, 3, "foo", 3},
|
||||
{"Zm9v", 4, ECE_BASE64URL_REJECT_PADDING, 3, "foo", 3},
|
||||
|
||||
{"Zm9vYg", 6, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"Zm9vYg", 6, ECE_BASE64URL_IGNORE_PADDING, 4, "foob", 4},
|
||||
{"Zm9vYg", 6, ECE_BASE64URL_REJECT_PADDING, 4, "foob", 4},
|
||||
|
||||
{"Zm9vYg==", 8, ECE_BASE64URL_REQUIRE_PADDING, 4, "foob", 4},
|
||||
{"Zm9vYg==", 8, ECE_BASE64URL_IGNORE_PADDING, 4, "foob", 4},
|
||||
{"Zm9vYg==", 8, ECE_BASE64URL_REJECT_PADDING, 6, NULL, 0},
|
||||
|
||||
{"Zm9vYmE", 7, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"Zm9vYmE", 7, ECE_BASE64URL_IGNORE_PADDING, 5, "fooba", 5},
|
||||
{"Zm9vYmE", 7, ECE_BASE64URL_REJECT_PADDING, 5, "fooba", 5},
|
||||
|
||||
{"Zm9vYmE=", 8, ECE_BASE64URL_REQUIRE_PADDING, 5, "fooba", 5},
|
||||
{"Zm9vYmE=", 8, ECE_BASE64URL_IGNORE_PADDING, 5, "fooba", 5},
|
||||
{"Zm9vYmE=", 8, ECE_BASE64URL_REJECT_PADDING, 6, NULL, 0},
|
||||
|
||||
{"Zm9vYmFy", 8, ECE_BASE64URL_REQUIRE_PADDING, 6, "foobar", 6},
|
||||
{"Zm9vYmFy", 8, ECE_BASE64URL_IGNORE_PADDING, 6, "foobar", 6},
|
||||
{"Zm9vYmFy", 8, ECE_BASE64URL_REJECT_PADDING, 6, "foobar", 6},
|
||||
|
||||
// Examples from RFC 4648, section 9.
|
||||
{"FPucA9l-", 8, ECE_BASE64URL_REQUIRE_PADDING, 6, "\x14\xfb\x9c\x03\xd9\x7e",
|
||||
6},
|
||||
{"FPucA9l-", 8, ECE_BASE64URL_IGNORE_PADDING, 6, "\x14\xfb\x9c\x03\xd9\x7e",
|
||||
6},
|
||||
{"FPucA9l-", 8, ECE_BASE64URL_REJECT_PADDING, 6, "\x14\xfb\x9c\x03\xd9\x7e",
|
||||
6},
|
||||
|
||||
{"FPucA9k", 7, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"FPucA9k", 7, ECE_BASE64URL_IGNORE_PADDING, 5, "\x14\xfb\x9c\x03\xd9", 5},
|
||||
{"FPucA9k", 7, ECE_BASE64URL_REJECT_PADDING, 5, "\x14\xfb\x9c\x03\xd9", 5},
|
||||
|
||||
{"FPucA9k=", 8, ECE_BASE64URL_REQUIRE_PADDING, 5, "\x14\xfb\x9c\x03\xd9", 5},
|
||||
{"FPucA9k=", 8, ECE_BASE64URL_IGNORE_PADDING, 5, "\x14\xfb\x9c\x03\xd9", 5},
|
||||
{"FPucA9k=", 8, ECE_BASE64URL_REJECT_PADDING, 6, NULL, 0},
|
||||
|
||||
{"FPucAw", 6, ECE_BASE64URL_REQUIRE_PADDING, 0, NULL, 0},
|
||||
{"FPucAw", 6, ECE_BASE64URL_IGNORE_PADDING, 4, "\x14\xfb\x9c\x03", 4},
|
||||
{"FPucAw", 6, ECE_BASE64URL_REJECT_PADDING, 4, "\x14\xfb\x9c\x03", 4},
|
||||
|
||||
{"FPucAw==", 8, ECE_BASE64URL_REQUIRE_PADDING, 4, "\x14\xfb\x9c\x03", 4},
|
||||
{"FPucAw==", 8, ECE_BASE64URL_IGNORE_PADDING, 4, "\x14\xfb\x9c\x03", 4},
|
||||
{"FPucAw==", 8, ECE_BASE64URL_REJECT_PADDING, 6, NULL, 0},
|
||||
};
|
||||
|
||||
void
|
||||
test_base64url_encode(void) {
|
||||
size_t tests =
|
||||
sizeof(base64url_encode_tests) / sizeof(base64url_encode_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
base64url_encode_test_t t = base64url_encode_tests[i];
|
||||
|
||||
size_t requiredBase64Len =
|
||||
ece_base64url_encode(t.binary, t.binaryLen, t.paddingPolicy, NULL, 0);
|
||||
ece_assert(
|
||||
requiredBase64Len == t.base64Len,
|
||||
"Got required length %zu for `%s` with padding policy %d; want %zu",
|
||||
requiredBase64Len, t.base64, t.paddingPolicy, t.base64Len);
|
||||
|
||||
char* base64 = malloc(requiredBase64Len + 1);
|
||||
ece_assert(base64,
|
||||
"Failed to allocate string for `%s` with padding policy %d",
|
||||
t.base64, t.paddingPolicy);
|
||||
|
||||
size_t actualBase64Len = ece_base64url_encode(
|
||||
t.binary, t.binaryLen, t.paddingPolicy, base64, requiredBase64Len + 1);
|
||||
ece_assert(actualBase64Len == t.base64Len,
|
||||
"Got length %zu for `%s` with padding policy %d; want %zu",
|
||||
actualBase64Len, t.base64, t.paddingPolicy, t.base64Len);
|
||||
|
||||
free(base64);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_base64url_decode(void) {
|
||||
size_t tests =
|
||||
sizeof(base64url_decode_tests) / sizeof(base64url_decode_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
base64url_decode_test_t t = base64url_decode_tests[i];
|
||||
|
||||
size_t requiredBinaryLen =
|
||||
ece_base64url_decode(t.base64, t.base64Len, t.paddingPolicy, NULL, 0);
|
||||
ece_assert(requiredBinaryLen == t.requiredBinaryLen,
|
||||
"Got required length %zu for `%s` with padding %d; want %zu",
|
||||
requiredBinaryLen, t.base64, t.paddingPolicy,
|
||||
t.requiredBinaryLen);
|
||||
|
||||
uint8_t* binary = calloc(requiredBinaryLen, sizeof(uint8_t));
|
||||
ece_assert(binary, "Failed to allocate buffer for `%s` with padding %d",
|
||||
t.base64, t.paddingPolicy);
|
||||
|
||||
size_t binaryLen = ece_base64url_decode(
|
||||
t.base64, t.base64Len, t.paddingPolicy, binary, requiredBinaryLen);
|
||||
ece_assert(binaryLen == t.binaryLen,
|
||||
"Got length %zu for `%s` with padding %d; want %zu", binaryLen,
|
||||
t.base64, t.paddingPolicy, t.binaryLen);
|
||||
ece_assert(!memcmp(binary, t.binary, binaryLen),
|
||||
"Wrong output for `%s` with padding %d", t.base64,
|
||||
t.paddingPolicy);
|
||||
|
||||
free(binary);
|
||||
}
|
||||
}
|
||||
497
mobile/ios/ThirdParty/ecec/test/decrypt/aes128gcm.c
vendored
Normal file
497
mobile/ios/ThirdParty/ecec/test/decrypt/aes128gcm.c
vendored
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct webpush_aes128gcm_decrypt_ok_test_s {
|
||||
const char* desc;
|
||||
const char* plaintext;
|
||||
const char* recvPrivKey;
|
||||
const char* authSecret;
|
||||
const char* payload;
|
||||
size_t payloadLen;
|
||||
size_t maxPlaintextLen;
|
||||
size_t plaintextLen;
|
||||
} webpush_aes128gcm_decrypt_ok_test_t;
|
||||
|
||||
static webpush_aes128gcm_decrypt_ok_test_t
|
||||
webpush_aes128gcm_decrypt_ok_tests[] = {
|
||||
{
|
||||
.desc = "rs = 24, pad = 0",
|
||||
.plaintext = "I am the walrus",
|
||||
.recvPrivKey = "\xc8\x99\xd1\x1d\x32\xe2\xb7\xe6\xfe\x74\x98\x78\x6f\x50"
|
||||
"\xf2\x3b\x98\xac\xe5\x39\x7a\xd2\x61\xde\x39\xba\x64\x49"
|
||||
"\xec\xc1\x2c\xad",
|
||||
.authSecret =
|
||||
"\x99\x6f\xad\x8b\x50\xaa\x2d\x02\xb8\x3f\x26\x41\x2b\x2e\x2a\xee",
|
||||
.payload = "\x49\x5c\xe6\xc8\xde\x93\xa4\x53\x9e\x86\x2e\x86\x34\x99\x3c"
|
||||
"\xbb\x00\x00"
|
||||
"\x00\x18\x41\x04\x3c\x33\x78\xa2\xc0\xab\x95\x4e\x14\x98\x71"
|
||||
"\x8e\x85\xf0"
|
||||
"\x8b\xb7\x23\xfb\x7d\x25\xe1\x35\xa6\x63\xfe\x38\x58\x84\xeb"
|
||||
"\x81\x92\x33"
|
||||
"\x6b\xf9\x0a\x54\xed\x72\x0f\x1c\x04\x5c\x0b\x40\x5e\x9b\xbc"
|
||||
"\x3a\x21\x42"
|
||||
"\xb1\x6c\x89\x08\x67\x34\xc3\x74\xeb\xaf\x70\x99\xe6\x42\x7e"
|
||||
"\x2d\x32\xc8"
|
||||
"\xad\xa5\x01\x87\x03\xc5\x4b\x10\xb4\x81\xe1\x02\x7d\x72\x09"
|
||||
"\xd8\xc6\xb4"
|
||||
"\x35\x53\xfa\x13\x3a\xfa\x59\x7f\x2d\xdc\x45\xa5\xba\x81\x40"
|
||||
"\x94\x4e\x64"
|
||||
"\x90\xbb\x8d\x6d\x99\xba\x1d\x02\xe6\x0d\x95\xf4\x8c\xe6\x44"
|
||||
"\x47\x7c\x17"
|
||||
"\x23\x1d\x95\xb9\x7a\x4f\x95\xdd",
|
||||
.payloadLen = 152,
|
||||
.maxPlaintextLen = 18,
|
||||
.plaintextLen = 15,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 49, pad = 84; ciphertext length falls on record boundary",
|
||||
.plaintext = "Hello, world",
|
||||
.recvPrivKey = "\x67\x00\x4a\x4e\xa8\x20\xde\xed\x8e\x49\xdb\x5e\x94\x80"
|
||||
"\xe6\x3d\x3e\xa3\xcc\xe1\xae\x8e\x1a\x60\x60\x97\x13\xd5"
|
||||
"\x27\xd0\x01\xef",
|
||||
.authSecret =
|
||||
"\x95\xf1\x75\x70\xe5\x08\xef\x6a\x2b\x2a\xd1\xb4\xf5\xca\xde\x33",
|
||||
.payload =
|
||||
"\xfb\x28\x83\xce\xc1\xc4\xfc\xad\xd6\xd1\x37\x1f\x6e\xa4\x91\xe0\x00"
|
||||
"\x00\x00\x31\x41\x04\x2d\x44\x1e\xe7\xf9\xff\x6a\x03\x29\xa6\x49\x27"
|
||||
"\xd0\x52\x4f\xdb\xe7\xb2\x2c\x6f\xb6\x5e\x10\xab\x4f\xdc\x03\x8f\x94"
|
||||
"\x42\x0a\x0c\xa3\xfa\x28\xda\xd3\x6c\x84\xec\x91\xa1\x62\xea\xe0\x78"
|
||||
"\xfa\xad\x2c\x1c\xed\x78\xde\x81\x13\xe1\x96\x02\xb2\x0e\x89\x4f\x49"
|
||||
"\x76\xb9\x73\xe2\xfc\xf6\x82\xfa\x0c\x8c\xcd\x9a\xf3\xd5\xbf\xf1\xed"
|
||||
"\xe1\x6f\xad\x5a\x31\xce\x19\xd3\x8b\x5e\x1f\xe1\xf7\x8a\x4f\xad\x84"
|
||||
"\x2b\xbc\x10\x25\x4c\x2c\x6c\xdd\x96\xa2\xb5\x52\x84\xd9\x72\xc5\x3c"
|
||||
"\xad\x8c\x3b\xac\xb1\x0f\x5f\x57\xeb\x0d\x4a\x43\x33\xb6\x04\x10\x2b"
|
||||
"\xa1\x17\xca\xe2\x91\x08\xfb\xd9\xf6\x29\xa8\xba\x69\x60\xdd\x01\x94"
|
||||
"\x5b\x39\xed\x37\xba\x70\x6c\x43\x4a\x10\xfd\x2b\xd2\x09\x4f\xf9\x24"
|
||||
"\x9b\xcd\xad\x45\x13\x5f\x5f\xe4\x5f\xcd\x38\x07\x1f\x8b\x2d\x39\x41"
|
||||
"\xaf\xda\x43\x98\x10\xd7\x7a\xac\xaf\x7c\xe5\x0b\x54\x32\x5b\xf5\x8c"
|
||||
"\x95\x03\x33\x7d\x07\x37\x85\xa3\x23\xdf\xa3\x43",
|
||||
.payloadLen = 233,
|
||||
.maxPlaintextLen = 99,
|
||||
.plaintextLen = 12,
|
||||
},
|
||||
{
|
||||
.desc = "Example from draft-ietf-webpush-encryption-latest",
|
||||
.plaintext = "When I grow up, I want to be a watermelon",
|
||||
.recvPrivKey = "\xab\x57\x57\xa7\x0d\xd4\xa5\x3e\x55\x3a\x6b\xbf\x71\xff"
|
||||
"\xef\xea\x28\x74\xec\x07\xa6\xb3\x79\xe3\xc4\x8f\x89\x5a"
|
||||
"\x02\xdc\x33\xde",
|
||||
.authSecret =
|
||||
"\x05\x30\x59\x32\xa1\xc7\xea\xbe\x13\xb6\xce\xc9\xfd\xa4\x88\x82",
|
||||
.payload = "\x0c\x6b\xfa\xad\xad\x67\x95\x88\x03\x09\x2d\x45\x46\x76\xf3"
|
||||
"\x97\x00\x00\x10\x00\x41\x04\xfe\x33\xf4\xab\x0d\xea\x71\x91"
|
||||
"\x4d\xb5\x58\x23\xf7\x3b\x54\x94\x8f\x41\x30\x6d\x92\x07\x32"
|
||||
"\xdb\xb9\xa5\x9a\x53\x28\x64\x82\x20\x0e\x59\x7a\x7b\x7b\xc2"
|
||||
"\x60\xba\x1c\x22\x79\x98\x58\x09\x92\xe9\x39\x73\x00\x2f\x30"
|
||||
"\x12\xa2\x8a\xe8\xf0\x6b\xbb\x78\xe5\xec\x0f\xf2\x97\xde\x5b"
|
||||
"\x42\x9b\xba\x71\x53\xd3\xa4\xae\x0c\xaa\x09\x1f\xd4\x25\xf3"
|
||||
"\xb4\xb5\x41\x4a\xdd\x8a\xb3\x7a\x19\xc1\xbb\xb0\x5c\xf5\xcb"
|
||||
"\x5b\x2a\x2e\x05\x62\xd5\x58\x63\x56\x41\xec\x52\x81\x2c\x6c"
|
||||
"\x8f\xf4\x2e\x95\xcc\xb8\x6b\xe7\xcd",
|
||||
.payloadLen = 144,
|
||||
.maxPlaintextLen = 42,
|
||||
.plaintextLen = 41,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 18, pad = 0",
|
||||
.plaintext = "1",
|
||||
.recvPrivKey = "\x27\x43\x3f\xab\x89\x70\xb3\xcb\x52\x84\xb6\x11\x83\xef"
|
||||
"\xb4\x62\x86\x56\x2c\xd2\xa7\x33\x0d\x8c\xae\x96\x09\x11"
|
||||
"\xa5\x57\x1d\x0c",
|
||||
.authSecret =
|
||||
"\xd6\x5a\x04\xdf\x95\xf2\xdb\x5e\x60\x48\x39\xf7\x17\xdc\xde\x79",
|
||||
.payload = "\x7c\xae\xbd\xbc\x20\x93\x8e\xe3\x40\xa9\x46\xf1\xbd\x4f\x68"
|
||||
"\xf1\x00\x00\x00\x12\x41\x04\x37\xcf\xdb\x52\x23\xd9\xf9\x5e"
|
||||
"\xaa\x02\xf6\xed\x94\x0f\xf2\x2e\xaf\x05\xb3\x62\x2e\x94\x9d"
|
||||
"\xc3\xce\x9f\x33\x5e\x6e\xf9\xb2\x6a\xea\xac\xca\x0f\x74\x08"
|
||||
"\x0a\x8b\x36\x45\x92\xf2\xcc\xc6\xd5\xed\xdd\x43\x00\x4b\x70"
|
||||
"\xb9\x18\x87\xd1\x44\xd9\xfa\x93\xf1\x6c\x3b\xc7\xea\x68\xf4"
|
||||
"\xfd\x54\x7a\x94\xec\xa8\x4b\x16\xe1\x38\xa6\x08\x01\x77",
|
||||
.payloadLen = 104,
|
||||
.maxPlaintextLen = 2,
|
||||
.plaintextLen = 1,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct webpush_aes128gcm_err_decrypt_test_s {
|
||||
const char* desc;
|
||||
const char* recvPrivKey;
|
||||
const char* authSecret;
|
||||
const char* payload;
|
||||
size_t payloadLen;
|
||||
size_t maxPlaintextLen;
|
||||
int err;
|
||||
} webpush_aes128gcm_err_decrypt_test_t;
|
||||
|
||||
static webpush_aes128gcm_err_decrypt_test_t
|
||||
webpush_aes128gcm_err_decrypt_tests[] = {
|
||||
{
|
||||
// Header block shorter than 21 bytes.
|
||||
.desc = "Missing header block",
|
||||
.recvPrivKey = "\x1b\xe8\x3f\x38\x33\x2e\xf0\x96\x81\xfa\xf3\xf3\x07\xb1"
|
||||
"\xff\x2e\x10\xca\xb7\x8c\xc7\xcd\xab\x68\x3a\xc0\xee\x92"
|
||||
"\xac\x3f\x6e\xe1",
|
||||
.authSecret =
|
||||
"\x34\x71\xbb\x98\x48\x1e\x02\x53\x3b\xf3\x95\x42\xbc\xf3\xdb\xa4",
|
||||
.payload = "\x45\xb7\x4d\x2b\x69\xbe\x9b\x07\x4d\xe3\xb3\x5a\xa8\x7e\x7c"
|
||||
"\x15\x61\x1d",
|
||||
.payloadLen = 18,
|
||||
.maxPlaintextLen = 0,
|
||||
.err = ECE_ERROR_SHORT_HEADER,
|
||||
},
|
||||
{
|
||||
// Sender key shorter than 65 bytes.
|
||||
.desc = "Truncated sender key",
|
||||
.recvPrivKey = "\xce\x88\xe8\xe0\xb3\x05\x7a\x47\x52\xeb\x4c\x8f\xa9\x31"
|
||||
"\xeb\x62\x1c\x30\x2d\xa5\xad\x03\xb8\x1a\xf4\x59\xcf\x67"
|
||||
"\x35\x56\x0c\xae",
|
||||
.authSecret =
|
||||
"\x5c\x31\xe0\xd9\x6d\x9a\x13\x98\x99\xac\x09\x69\xd3\x59\xf7\x40",
|
||||
.payload = "\xde\x5b\x69\x6b\x87\xf1\xa1\x5c\xb6\xad\xeb\xdd\x79\xd6\xf9"
|
||||
"\x9e\x00\x00\x00\x12\x01\x00\xb6\xbc\x18\x26\xc3\x7c\x9f\x73"
|
||||
"\xdd\x6b\x48\x59\xc2\xb5\x05\x18\x19\x52",
|
||||
.payloadLen = 40,
|
||||
.maxPlaintextLen = 2,
|
||||
.err = ECE_ERROR_COMPUTE_SECRET,
|
||||
},
|
||||
{
|
||||
// The payload is encrypted with only the first 12 bytes of the auth
|
||||
// secret.
|
||||
.desc = "Truncated auth secret",
|
||||
.recvPrivKey = "\x60\xc7\x63\x6a\x51\x7d\xe7\x03\x9a\x0a\xc2\xd0\xe3\x06"
|
||||
"\x44\x00\x79\x4c\x78\xe7\xe0\x49\x39\x81\x29\xa2\x27\xce"
|
||||
"\xe0\xf9\xa8\x01",
|
||||
.authSecret =
|
||||
"\x35\x5a\x38\xcd\x6d\x9b\xef\x15\x99\x0e\x2d\x33\x08\xdb\xd6\x00",
|
||||
.payload = "\x81\x15\xf4\x98\x8b\x8c\x39\x2a\x7b\xac\xb4\x3c\x8f\x1a\xc5"
|
||||
"\x65\x00\x00\x00\x12\x41\x04\x19\x94\x48\x3c\x54\x1e\x9b\xc3"
|
||||
"\x9a\x6a\xf0\x3f\xf7\x13\xaa\x77\x45\xc2\x84\xe1\x38\xa4\x2a"
|
||||
"\x24\x35\xb7\x97\xb2\x0c\x4b\x69\x8c\xf5\x11\x8b\x4f\x85\x55"
|
||||
"\x31\x7c\x19\x0e\xab\xeb\xfa\xb7\x49\xc1\x64\xd3\xf6\xbd\xeb"
|
||||
"\xe0\xd4\x41\x71\x91\x31\xa3\x57\xd8\x89\x0a\x13\xc4\xdb\xd4"
|
||||
"\xb1\x6f\xf3\xdd\x5a\x83\xf7\xc9\x1a\xd6\xe0\x40\xac\x42\x73"
|
||||
"\x0a\x7f\x0b\x3c\xd3\x24\x5e\x9f\x8d\x6f\xf3\x1c\x75\x1d\x41"
|
||||
"\x0c\xfd",
|
||||
.payloadLen = 122,
|
||||
.maxPlaintextLen = 4,
|
||||
.err = ECE_ERROR_DECRYPT,
|
||||
},
|
||||
{
|
||||
.desc = "Early final record",
|
||||
.recvPrivKey = "\x5d\xda\x1d\x91\x8b\xc4\x07\xba\x3c\xda\x12\xcb\x80\x14"
|
||||
"\xd4\x9a\xa7\xe0\x26\x90\x02\x82\x03\x04\x46\x6b\xc8\x00"
|
||||
"\x34\xca\x92\x40",
|
||||
.authSecret =
|
||||
"\x40\xc2\x41\xfd\xe4\x26\x9e\xe1\xe6\xd7\x25\x59\x2d\x98\x27\x18",
|
||||
.payload = "\xdb\xe2\x15\x50\x7d\x1a\xd3\xd2\xea\xea\xbe\xae\x6e\x87\x4d"
|
||||
"\x8f\x00\x00\x00\x12\x41\x04\x7b\xc4\x34\x3f\x34\xa8\x34\x8c"
|
||||
"\xdc\x4e\x46\x2f\xfc\x7c\x40\xaa\x6a\x8c\x61\xa7\x39\xc4\xc4"
|
||||
"\x1d\x45\x12\x55\x05\xf7\x0e\x9f\xc5\xf9\xef\xa8\x68\x52\xdd"
|
||||
"\x48\x8d\xcf\x8e\x8e\xa2\xca\xfb\x75\xe0\x7a\xbd\x5e\xe7\xc9"
|
||||
"\xd5\xc0\x38\xba\xfe\xf0\x79\x57\x1b\x0b\xda\x29\x44\x11\xce"
|
||||
"\x98\xc7\x6d\xd0\x31\xc0\xe5\x80\x57\x7a\x49\x80\xa3\x75\xe4"
|
||||
"\x5e\xd3\x04\x29\xbe\x0e\x2e\xe9\xda\x7e\x6d\xf8\x69\x6d\x01"
|
||||
"\xb8\xec",
|
||||
.payloadLen = 122,
|
||||
.maxPlaintextLen = 4,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct aes128gcm_ok_decrypt_test_s {
|
||||
const char* desc;
|
||||
const char* plaintext;
|
||||
const char* ikm;
|
||||
const char* payload;
|
||||
size_t payloadLen;
|
||||
size_t maxPlaintextLen;
|
||||
size_t plaintextLen;
|
||||
} aes128gcm_ok_decrypt_test_t;
|
||||
|
||||
static aes128gcm_ok_decrypt_test_t aes128gcm_ok_decrypt_tests[] = {
|
||||
{
|
||||
.desc = "rs = 18, pad = 8",
|
||||
.plaintext = "When I grow up, I want to be a watermelon",
|
||||
.ikm = "\x28\xc0\x66\x11\x4a\x2d\xa5\x21\xca\x89\xf4\x21\x9d\xa8\xac\xc0",
|
||||
.payload =
|
||||
"\x1f\xc2\xec\x59\x4d\xbd\xa8\xc8\xab\x26\x25\x47\x04\x65\xb8\xcd\x00\x00"
|
||||
"\x00\x12\x00\x92\x56\xfe\x1c\x43\x4f\x71\x8e\x85\x16\x3a\x0f\x52\x69\xc1"
|
||||
"\xb8\x24\x55\x73\x60\x7d\x06\x06\xc3\x97\xfc\xfd\xc3\x27\xd5\xf9\x0c\x44"
|
||||
"\x8d\x6a\x11\xa0\xc4\xb8\xd0\x51\xc8\x54\x94\xb0\x0f\xb5\xeb\xb9\xe6\x85"
|
||||
"\x38\x2f\x88\xee\x5a\xce\x19\x1b\xfa\x73\x1d\xa2\xc9\xb2\x3f\x0a\xe4\xfe"
|
||||
"\x4b\x9a\xd5\xf5\x4d\xf0\xec\xc8\x17\x9f\xc6\xdb\xed\x3a\x94\x33\xbe\x4f"
|
||||
"\x92\xa8\xdd\xf1\x0d\x5f\x29\x9f\x76\x73\xfb\x79\x33\x69\xc9\x6b\xf5\x20"
|
||||
"\x5b\x4e\xa5\x47\xef\xa3\xd4\x4b\x6c\xaa\x47\xac\x97\x9a\xa1\x69\x45\x2a"
|
||||
"\xf6\xf6\x84\x65\xda\xba\x9b\x8a\xb3\x9c\xed\x91\x15\xd4\x4f\xbb\x7c\xf6"
|
||||
"\xc6\xfa\x0f\x86\x71\xa2\xa1\x2c\xf6\x18\x18\x86\x94\xf1\x7c\x2f\x63\xb7"
|
||||
"\x46\xe0\x6e\x9a\x51\x20\x6a\x8c\x54\xc9\x91\x54\xb1\x84\xa9\xec\x8a\x29"
|
||||
"\x71\x4e\xfd\xb6\x8f\xde\xe4\xc4\x2f\x57\xb3\x2e\x48\x8d\x5c\x47\x51\x05"
|
||||
"\xd0\x57\xb6\x55\x15\xc4\xa0\xeb\x59\x5b\xd6\xe8\xa7\x11\x65\x18\xad\xfb"
|
||||
"\xc5\xdf\xbc\x51\x71\x01\xae\x72\x2b\x19\x14\xa1\x47\x3e\x35\xbb\x52\xa7"
|
||||
"\xc9\xad\x22\x09\xc6\xea\x8f\x2b\x60\x5f\x8d\xf9\x78\x65\x4e\xd5\x2c\x71"
|
||||
"\x17\x5c\x12\x4e\xb3\xa5\x6e\xfa\xfe\x64\x77\xd8\x05\x07\x4d\xd0\x29\x15"
|
||||
"\x65\x37\x4b\xb1\x02\x8c\x9b\xbd\x59\xd6\x4d\x56\x27\xe7\x28\x02\x5a\x30"
|
||||
"\x59\x10\x0f\x48\xe8\x88\x5f\x7f\xe4\x4e\x0d\xec\xbb\x7b\x98\x08\x3d\x85"
|
||||
"\xe1\xc8\x2b\x11\x8a\x8a\xf5\xb3\x8f\x33\xb3\xb6\x7b\xa6\xd5\x8e\x58\xc1"
|
||||
"\x3a\xff\xaf\x8c\x2b\x99\x9d\x4f\xc2\x09\xed\x73\x7a\x04\x74\x93\x48\x1b"
|
||||
"\xfa\xfd\x71\x9d\x49\x8d\xf0\xa9\x8c\x6f\x43\x48\xc7\x24\x3a\xa6\x78\x9a"
|
||||
"\xf3\x36\x85\x4b\x7e\x87\xf9\x5a\x05\x47\xcf\x73\x5e\xc3\x83\xa8\x27\x4d"
|
||||
"\xdc\xf5\xd9\x76\x43\x85\x37\x36\xb4\xc6\x06\x3f\x48\x95\xab\x38\x38\xc9"
|
||||
"\x99\x9c\xec\x7b\x73\x1c\xda\xcb\xd5\x0f\x8c\x06\xde\x9f\xe8\x0a\xad\xaf"
|
||||
"\x91\xd1\x1b\x9a\x35\xaa\xdf\x41\xa0\x5c\x6b\xae\xda\x0c\x6d\x00\xb4\xa8"
|
||||
"\xc0\xc3\x69\xf9\x8f\x4c\x6e\x6a\x97\x76\xab\x41\x7e\x28\x39\x1b\x47\x5c"
|
||||
"\xe7\xfc\x01\x65\xdb\xe4\x9e\xf9\x89\x1f\x9c\xef\x82\xe2\x86\x7e\xd6\xd6"
|
||||
"\x7c\x4a\x5a\x71\xda\xa1\xf7\x5d\x26\x5f\x85\x92\xa8\x1d\xb4\x8c\xbc\x92"
|
||||
"\xc3\x82\xd6\x3a\x96\xf5\x80\x0f\xa8\xec\xa9\xe2\x02\x7b\xaf\xb7\x4b\xc9"
|
||||
"\xe3\x3b\xdc\xd3\xb8\xf4\xd8\xe0\x5f\x36\xdd\xa5\x44\xf8\x97\x5e\xcb\xea"
|
||||
"\x47\x8d\xb8\x36\x61\xa1\xdb\xc5\xfc\xcb\x7f\xeb\x05\x57\xde\xd7\x3a\x37"
|
||||
"\x90\xc3\x52\x69\xfa\x59\xe4\x75\x0e\x55\xc7\x29\xa0\x08\xc9\x8c\xe9\xee"
|
||||
"\x88\x82\xe0\xc2\xae\xaf\x1e\xbe\x40\x3b\xe9\x6d\xaa\x25\xb4\x2a\xc0\x1b"
|
||||
"\x6a\xd4\x35\x5b\xc3\x60\xcd\xd1\x31\x10\xe3\xff\xc7\x6a\xb4\x51\xf5\x9e"
|
||||
"\x04\xa8\xab\x3f\x1a\x4a\x69\xdf\x21\x91\xab\x4b\x60\xfd\x31\x76\x13\x2b"
|
||||
"\x8f\x99\x1d\x3a\xb2\x96\xa0\x36\x93\x36\xb5\x35\xaa\xcc\x15\x97\x7d\x50"
|
||||
"\x5b\xe2\xc5\xd4\xb6\xb7\xbc\x55\xd8\x3c\xd1\x7c\x1e\x80\x35\x7f\x4a\x21"
|
||||
"\x8d\x72\x93\x3f\xa6\x09\x74\x73\x29\x6d\x7d\xdc\x30\xd7\xa1\x7b\x73\x23"
|
||||
"\xac\x17\x3e\xc3\x47\x72\x45\x1a\xa6\x70\x95\xca\xcf\xbc\x87\x6c\x05\x56"
|
||||
"\xa7\xae\x2f\x2c\x64\x55\x50\xd8\xab\x05\xe6\xa7\x87\xa5\x5a\x1c\x0c\xe1"
|
||||
"\x59\x7b\x95\x8e\xe7\xea\xff\x10\x29\x93\x02\xd9\x9c\x35\xca\xc9\x83\xb9"
|
||||
"\x6c\x0f\xec\xaf\x61\x59\x3a\x17\x66\xd3\xbc\xc7\xc2\xd5\x00\x4a\x4c\x43"
|
||||
"\x91\xcb\x41\xb1\x36\x79\x35\xe3\x9d\x73\xf3\xa2\xe0\x84\x59\xd2\x83\x2c"
|
||||
"\x18\x34\xf2\x60\x6a\x87\x40\x10\xd7\xcf\x17\x7e\x7b\xcf\x61\xad\x41\x3d"
|
||||
"\x0f\xfc\xe3\x3d\x6b\xef\x39\xb9\x61\x39\xda\x24\xaf\xc9\xac\xe7\x94\x28"
|
||||
"\x8d\x79\x75\xac\x74\xc9\x86\x66\x1d\x40\x34\x42\x25\xf7\x99\xf5\x96\x35"
|
||||
"\xa9\x1f\x98\x7b\x54\x42\x3a\x5e\x10\x60\x9b\x6d\x8e\xb4\xda\xe5\xc2\xc8"
|
||||
"\x2e\x53\xae\xc3\xa3\xdd\xe5\xaf\xbf\x06\x2c\x42\xe2\x95\x91\xd9\x3e\x49"
|
||||
"\xe4\x54\x80\x90\xb5\x22\x7e\x13\xda\x62\x70\x14\x7e\x5d\x9d\xee\x3f\x2e"
|
||||
"\x8d\x2f\x7d\xe0\xaf\x1d\xd7\x61\x27\x9d\xd3\xf2\x8a\xce\x13\x74\x73\x15"
|
||||
"\x11\xf2\x1a",
|
||||
.payloadLen = 903,
|
||||
.maxPlaintextLen = 98,
|
||||
.plaintextLen = 41,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct aes128gcm_err_decrypt_test_s {
|
||||
const char* desc;
|
||||
const char* ikm;
|
||||
const char* payload;
|
||||
size_t payloadLen;
|
||||
size_t maxPlaintextLen;
|
||||
int err;
|
||||
} aes128gcm_err_decrypt_test_t;
|
||||
|
||||
static aes128gcm_err_decrypt_test_t aes128gcm_err_decrypt_tests[] = {
|
||||
{
|
||||
.desc = "Truncated ciphertext, rs = 18",
|
||||
.ikm = "\x28\xc0\x66\x11\x4a\x2d\xa5\x21\xca\x89\xf4\x21\x9d\xa8\xac\xc0",
|
||||
.payload = "\x1f\xc2\xec\x59\x4d\xbd\xa8\xc8\xab\x26\x25\x47\x04\x65\xb8"
|
||||
"\xcd\x00\x00\x00\x12\x00\x92\x56\xfe\x1c\x43\x4f\x71\x8e\x85"
|
||||
"\x16\x3a\x0f\x52\x69\xc1\xb8\x24\x55",
|
||||
.payloadLen = 40,
|
||||
.maxPlaintextLen = 0,
|
||||
.err = ECE_ERROR_DECRYPT,
|
||||
},
|
||||
{
|
||||
.desc = "rs <= block overhead",
|
||||
.ikm = "\x2f\xb1\x75\xc2\x71\xb9\x2f\x6b\x55\xe4\xf2\xa2\x52\xd1\x45\x43",
|
||||
.payload = "\x76\xf9\x1d\x48\x4e\x84\x91\xda\x55\xc5\xf7\xbf\xe6\xd3\x3e"
|
||||
"\x89\x00\x00\x00\x02\x00",
|
||||
.payloadLen = 21,
|
||||
.maxPlaintextLen = 0,
|
||||
.err = ECE_ERROR_INVALID_RS,
|
||||
},
|
||||
{
|
||||
.desc = "Zero plaintext",
|
||||
.ikm = "\x64\xc7\x0e\x64\xa7\x25\x55\x14\x51\xf2\x08\xdf\xba\xa0\xb9\x72",
|
||||
.payload = "\xaa\xd2\x05\x7d\x33\x53\xb7\xff\x37\xbd\xe4\x2a\xe1\xd5\x0f"
|
||||
"\xda\x00\x00\x00\x20\x00\xbb\xc7\xb9\x65\x76\x0b\xf0\x66\x2b"
|
||||
"\x93\xf4\xe5\xd6\x94\xb7\x65\xf0\xcd\x15\x9b\x28\x01\xa5",
|
||||
.payloadLen = 44,
|
||||
.maxPlaintextLen = 7,
|
||||
.err = ECE_ERROR_ZERO_PLAINTEXT,
|
||||
},
|
||||
{
|
||||
.desc = "Bad early padding delimiter",
|
||||
.ikm = "\x64\xc7\x0e\x64\xa7\x25\x55\x14\x51\xf2\x08\xdf\xba\xa0\xb9\x72",
|
||||
.payload = "\xaa\xd2\x05\x7d\x33\x53\xb7\xff\x37\xbd\xe4\x2a\xe1\xd5\x0f"
|
||||
"\xda\x00\x00\x00\x20\x00\xb9\xc7\xb9\x65\x76\x0b\xf0\x9e\x42"
|
||||
"\xb1\x08\x43\x38\x75\xa3\x06\xc9\x78\x06\x0a\xfc\x7c\x7d\xe9"
|
||||
"\x52\x85\x91\x8b\x58\x02\x60\xf3\x45\x38\x7a\x28\xe5\x25\x66"
|
||||
"\x2f\x48\xc1\xc3\x32\x04\xb1\x95\xb5\x4e\x9e\x70\xd4\x0e\x3c"
|
||||
"\xf3\xef\x0c\x67\x1b\xe0\x14\x49\x7e\xdc",
|
||||
.payloadLen = 85,
|
||||
.maxPlaintextLen = 32,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
{
|
||||
.desc = "Bad final padding delimiter",
|
||||
.ikm = "\x64\xc7\x0e\x64\xa7\x25\x55\x14\x51\xf2\x08\xdf\xba\xa0\xb9\x72",
|
||||
.payload = "\xaa\xd2\x05\x7d\x33\x53\xb7\xff\x37\xbd\xe4\x2a\xe1\xd5\x0f"
|
||||
"\xda\x00\x00\x00\x20\x00\xba\xc7\xb9\x65\x76\x0b\xf0\x9e\x42"
|
||||
"\xb1\x08\x4a\x69\xe4\x50\x1b\x8d\x49\xdb\xc6\x79\x23\x4d\x47"
|
||||
"\xc2\x57\x16",
|
||||
.payloadLen = 48,
|
||||
.maxPlaintextLen = 11,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid auth tag",
|
||||
.ikm = "\x64\xc7\x0e\x64\xa7\x25\x55\x14\x51\xf2\x08\xdf\xba\xa0\xb9\x72",
|
||||
.payload = "\xaa\xd2\x05\x7d\x33\x53\xb7\xff\x37\xbd\xe4\x2a\xe1\xd5\x0f"
|
||||
"\xda\x00\x00\x00\x20\x00\xbb\xc6\xb1\x1d\x46\x3a\x7e\x0f\x07"
|
||||
"\x2b\xbe\xaa\x44\xe0\xd6\x2e\x4b\xe5\xf9\x5d\x25\xe3\x86\x71"
|
||||
"\xe0\x7d",
|
||||
.payloadLen = 47,
|
||||
.maxPlaintextLen = 10,
|
||||
.err = ECE_ERROR_DECRYPT,
|
||||
},
|
||||
{
|
||||
// 2 records; last record is "\x00" without a delimiter.
|
||||
.desc = "rs = 21, truncated padding for last record",
|
||||
.ikm = "\x1a\x5c\x05\x64\x16\xdf\x83\x73\x87\x51\x01\xd1\x11\x98\x47\x83",
|
||||
.payload = "\x53\x06\xdc\x45\xdd\x8e\x51\x00\x16\x53\x3c\x1e\xba\xe5\x50"
|
||||
"\x53\x00\x00\x00\x15\x00\xa7\x0d\x92\x4e\xe6\x08\xd0\xc1\xc1"
|
||||
"\x00\x88\x5a\xe8\x78\x1d\xd1\x47\x67\x02\x12\x63\xf7\x9d\x22"
|
||||
"\xa9\x44\x8d\xb2\x33\x6e\xe0\xe5\x72\xe2\x3c\x38\x49\x70",
|
||||
.payloadLen = 59,
|
||||
.maxPlaintextLen = 6,
|
||||
.err = ECE_ERROR_ZERO_PLAINTEXT,
|
||||
},
|
||||
{
|
||||
// 2 records; last record is just the auth tag.
|
||||
.desc = "rs = 21, auth tag for last record",
|
||||
.ikm = "\xc1\xc9\xc0\x91\x9d\x81\x0a\xe7\xd9\xe8\x0c\x45\xbc\x21\xa9\xfa",
|
||||
.payload = "\xc1\xaf\x29\x07\x6f\x69\x25\x60\xde\x6d\x1f\xde\x02\x11\x69"
|
||||
"\x79\x00\x00\x00\x15\x00\x46\x9f\xde\x73\xa7\x8a\x2a\x66\x1d"
|
||||
"\xb0\xf1\xae\x55\xec\xec\x86\x6a\xaa\xe5\xf3\x04\xa3\x3e\xc3"
|
||||
"\xb0\xbb\x16\xe9\x0a\xab\xc4\xba\xe0\xed\xbb\x73\x46",
|
||||
.payloadLen = 58,
|
||||
.maxPlaintextLen = 5,
|
||||
.err = ECE_ERROR_SHORT_BLOCK,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_decrypt_ok(void) {
|
||||
size_t tests = sizeof(webpush_aes128gcm_decrypt_ok_tests) /
|
||||
sizeof(webpush_aes128gcm_decrypt_ok_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
webpush_aes128gcm_decrypt_ok_test_t t =
|
||||
webpush_aes128gcm_decrypt_ok_tests[i];
|
||||
|
||||
const void* recvPrivKey = t.recvPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* payload = t.payload;
|
||||
|
||||
size_t plaintextLen =
|
||||
ece_aes128gcm_plaintext_max_length(payload, t.payloadLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aes128gcm_decrypt(
|
||||
recvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, payload, t.payloadLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(!err, "Got %d decrypting payload for `%s`", err, t.desc);
|
||||
|
||||
ece_assert(plaintextLen == t.plaintextLen,
|
||||
"Got plaintext length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.plaintextLen);
|
||||
ece_assert(!memcmp(plaintext, t.plaintext, plaintextLen),
|
||||
"Wrong plaintext for `%s`", t.desc);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_decrypt_err(void) {
|
||||
size_t tests = sizeof(webpush_aes128gcm_err_decrypt_tests) /
|
||||
sizeof(webpush_aes128gcm_err_decrypt_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
webpush_aes128gcm_err_decrypt_test_t t =
|
||||
webpush_aes128gcm_err_decrypt_tests[i];
|
||||
|
||||
const void* recvPrivKey = t.recvPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* payload = t.payload;
|
||||
|
||||
size_t plaintextLen =
|
||||
ece_aes128gcm_plaintext_max_length(payload, t.payloadLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aes128gcm_decrypt(
|
||||
recvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, payload, t.payloadLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(err == t.err, "Got %d decrypting payload for `%s`; want %d", err,
|
||||
t.desc, t.err);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_aes128gcm_decrypt_ok(void) {
|
||||
size_t tests =
|
||||
sizeof(aes128gcm_ok_decrypt_tests) / sizeof(aes128gcm_ok_decrypt_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
aes128gcm_ok_decrypt_test_t t = aes128gcm_ok_decrypt_tests[i];
|
||||
|
||||
size_t plaintextLen = ece_aes128gcm_plaintext_max_length(
|
||||
(const uint8_t*) t.payload, t.payloadLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_aes128gcm_decrypt((const uint8_t*) t.ikm, 16,
|
||||
(const uint8_t*) t.payload, t.payloadLen,
|
||||
plaintext, &plaintextLen);
|
||||
ece_assert(!err, "Got %d decrypting payload for `%s`", err, t.desc);
|
||||
|
||||
ece_assert(plaintextLen == t.plaintextLen,
|
||||
"Got plaintext length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.plaintextLen);
|
||||
ece_assert(!memcmp(plaintext, t.plaintext, plaintextLen),
|
||||
"Wrong plaintext for `%s`", t.desc);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_aes128gcm_decrypt_err(void) {
|
||||
size_t tests =
|
||||
sizeof(aes128gcm_err_decrypt_tests) / sizeof(aes128gcm_err_decrypt_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
aes128gcm_err_decrypt_test_t t = aes128gcm_err_decrypt_tests[i];
|
||||
|
||||
const void* ikm = t.ikm;
|
||||
const void* payload = t.payload;
|
||||
|
||||
size_t plaintextLen =
|
||||
ece_aes128gcm_plaintext_max_length(payload, t.payloadLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_aes128gcm_decrypt(ikm, 16, payload, t.payloadLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(err == t.err, "Got %d decrypting payload for `%s`; want %d", err,
|
||||
t.desc, t.err);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
306
mobile/ios/ThirdParty/ecec/test/decrypt/aesgcm.c
vendored
Normal file
306
mobile/ios/ThirdParty/ecec/test/decrypt/aesgcm.c
vendored
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct webpush_aesgcm_decrypt_ok_test_s {
|
||||
const char* desc;
|
||||
const char* plaintext;
|
||||
const char* recvPrivKey;
|
||||
const char* authSecret;
|
||||
const char* ciphertext;
|
||||
const char* cryptoKey;
|
||||
const char* encryption;
|
||||
size_t ciphertextLen;
|
||||
size_t maxPlaintextLen;
|
||||
size_t plaintextLen;
|
||||
} webpush_aesgcm_decrypt_ok_test_t;
|
||||
|
||||
typedef struct webpush_aesgcm_decrypt_err_test_s {
|
||||
const char* desc;
|
||||
const char* recvPrivKey;
|
||||
const char* authSecret;
|
||||
const char* ciphertext;
|
||||
const char* cryptoKey;
|
||||
const char* encryption;
|
||||
size_t maxPlaintextLen;
|
||||
size_t ciphertextLen;
|
||||
int err;
|
||||
} webpush_aesgcm_decrypt_err_test_t;
|
||||
|
||||
static webpush_aesgcm_decrypt_ok_test_t webpush_aesgcm_decrypt_ok_tests[] = {
|
||||
{
|
||||
.desc = "rs = 24, pad = 0",
|
||||
.plaintext = "Some message",
|
||||
.recvPrivKey = "\xe2\x1d\xb7\x1b\xf2\xa4\x5c\x2f\x53\xbc\x14\x8a\xda\xfd"
|
||||
"\x10\xec\x89\xa9\x4b\x66\x00\xb9\x17\x7c\x85\x0c\x8d\xd2"
|
||||
"\xb1\x40\xc0\x18",
|
||||
.authSecret =
|
||||
"\x69\x30\xdc\xe8\x97\x9b\xcd\x1e\x9e\x49\xcc\xb6\xa0\xba\x38\x45",
|
||||
.ciphertext = "\x3a\x8d\xf8\xc3\x61\x7d\x55\x59\xd3\x30\x57\xca\xb5\xdc"
|
||||
"\x78\xf0\x06\x56\x43\xd2\xe2\xf4\xce\x83\x6a\xe5\x89\x56"
|
||||
"\x05\xd4",
|
||||
.cryptoKey = "dh="
|
||||
"BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxa"
|
||||
"DKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo",
|
||||
.encryption = "salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24",
|
||||
.ciphertextLen = 30,
|
||||
.maxPlaintextLen = 14,
|
||||
.plaintextLen = 12,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 8, pad = 16",
|
||||
.plaintext = "Yet another message",
|
||||
.recvPrivKey = "\xe2\x1d\xb7\x1b\xf2\xa4\x5c\x2f\x53\xbc\x14\x8a\xda\xfd"
|
||||
"\x10\xec\x89\xa9\x4b\x66\x00\xb9\x17\x7c\x85\x0c\x8d\xd2"
|
||||
"\xb1\x40\xc0\x18",
|
||||
.authSecret =
|
||||
"\xea\x99\x70\x66\x74\xa9\x55\x46\xc5\xec\x03\xc3\x5e\xeb\x37\x51",
|
||||
.ciphertext =
|
||||
"\xb8\x40\xb9\x07\xfb\x51\xf9\xfb\x90\xdd\xd7\xa5\x41\xca\xf3\xac\x30"
|
||||
"\xa9\xe3\x45\xba\x8a\x93\x19\x8c\x66\x7b\xf1\x44\x83\x27\x9b\x0c\x8f"
|
||||
"\xee\x9b\x00\xe5\x46\xdc\x02\xba\x26\xa1\x65\xf4\x4e\x80\xa1\x68\x81"
|
||||
"\x61\x8b\xcc\x65\xfc\x13\x85\x5c\x66\x0e\x7c\x3a\x44\x7b\x55\x78\xb2"
|
||||
"\x85\x33\x90\xd6\x82\x5d\x44\xc2\x43\xa8\x87\x01\xf6\x12\x18\x83\x0f"
|
||||
"\x48\x0c\xde\x2a\x3e\x77\xbf\x56\x2b\x33\x8f\x64\x4f\x6b\x0d\x65\x12"
|
||||
"\xbf\xae\x09\xb2\xd2\x26\x49\xf5\xff\x00\x34\x1f\x00\x1a\xef\x6d\x99"
|
||||
"\x1e\x69\x6c\x61\xe7\x71\x06\xe7\xd4\x0c\x38\x49\x45\x26\xa1\xee\x7b"
|
||||
"\x87\x4c\x51\x1a\x6c\x31\x78",
|
||||
.cryptoKey = "dh=BEaA4gzA3i0JDuirGhiLgymS4hfFX7TNTdEhSk_"
|
||||
"HBlLpkjgCpjPL5c-GL9uBGIfa_fhGNKKFhXz1k9Kyens2ZpQ",
|
||||
.encryption = "salt=ZFhzj0S-n29g9P2p4-I7tA; rs=8",
|
||||
.ciphertextLen = 143,
|
||||
.maxPlaintextLen = 47,
|
||||
.plaintextLen = 19,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 3, pad = 0",
|
||||
.plaintext = "Small record size",
|
||||
.recvPrivKey = "\xe2\x1d\xb7\x1b\xf2\xa4\x5c\x2f\x53\xbc\x14\x8a\xda\xfd"
|
||||
"\x10\xec\x89\xa9\x4b\x66\x00\xb9\x17\x7c\x85\x0c\x8d\xd2"
|
||||
"\xb1\x40\xc0\x18",
|
||||
.authSecret =
|
||||
"\x83\x6a\xd6\x54\x75\x02\xa5\x4c\x60\x70\xbf\x53\xcf\xbb\xf2\x79",
|
||||
.ciphertext =
|
||||
"\xa1\x8e\x1e\xe5\xe0\xda\xb4\x35\x6d\xd9\xfa\x50\xca\x5c\x5b\x3c\x93"
|
||||
"\x3e\xde\xfa\xdf\x84\x36\xac\x7c\xf7\x3c\x43\x53\xd6\xb7\x8b\x4f\x7c"
|
||||
"\xc5\x5b\xcf\xfb\x03\x34\xbf\xdc\xbe\xbd\x03\x5d\x79\x1d\x17\x34\xb5"
|
||||
"\x97\x1b\x09\xb2\x3e\x79\xd1\x44\xb1\xe0\xc3\x25\xd3\x58\xa1\x8c\x89"
|
||||
"\x97\x0a\x3a\xf0\xf5\x1e\x71\x16\x01\x6b\x08\x0a\x89\x0f\x71\xb0\x5c"
|
||||
"\x0d\x6f\xcd\x2e\x13\xe7\x2b\xc6\x55\xb5\x29\xdd\x29\xdd\x30\x37\x53"
|
||||
"\xd4\xe0\x9c\x12\x87\xd3\x9f\xb5\x42\xeb\x16\x7e\xcc\xff\x2b\xcd\x24"
|
||||
"\x1f\x0c\x20\x41\xc6\x63\xd4\xec\xe2\x12\xce\xbf\x19\xe0\x7c\xb3\x14"
|
||||
"\x21\x89\x78\x17\xea\x89\x9e\xf2\x51\xf3\x65\x28\x5d\x71\xe5\x46\x99"
|
||||
"\xe1\x7e\xa2\x53\xf4\xd7\xc7\x92\xa5\x43\x2f\xed\xa1\x5d\x5d\x5d\x9d"
|
||||
"\x9e\x10\x03\x07\x25\x47\x12\x74\x0a\xef\x07\xac\xd1\xa4\x57\x44\x23"
|
||||
"\x17\x5c\x1d\xc2\x72\xa3\x50\x48\x62\x00\x18\x4c\x37\x40\x23\x2f\xff"
|
||||
"\x20\x95\x42\x3d\x8f\xdb\xd8\x21\x39\x5b\xfe\xa8\x86\x56\x0a\x07\xbc"
|
||||
"\x43\xc8\x7f\x20\x88\xdb\x96\x59\x70\x20\x06\x8c\xd4\x7d\x27\x0b\x51"
|
||||
"\x58\xcf\x0b\x7f\x32\x25\x3a\x40\x52\x2e\xb0\xea\x95\xe0\x5d\x45\x9f"
|
||||
"\x7d\xe9\xdd\x7b\x91\x6b\x79\x0a\x67\x30\x52\xf5\x2f\x81\xbe\xdf\xcc"
|
||||
"\x2c\x23\xff\x88\x48\x83\xb3\x74\xef\x10\x22\xb5\xc7\xc6\x6b\x5c\xd5"
|
||||
"\x2e\x71\xcd\x8b\xbc\x6c\xca\x92\x80\x28\xa7\xbc\x21\x30\x75\xe1\x85"
|
||||
"\x0a\x68\xa0\x85\x18\xe3\xf2\xdd\x73\x45\x6a\x34\x0f\x5e\x2b\x1d\xb4"
|
||||
"\x0b\x3d\x1f\xdb\xd4\xfe\x52\xbc\x47\x89\x4e\xd4\xbd\x36\x6d\xe2\x89"
|
||||
"\xb3",
|
||||
.cryptoKey = "dh=BCg6ZIGuE2ZNm2ti6Arf4CDVD_8--"
|
||||
"aLXAGLYhpghwjl1xxVjTLLpb7zihuEOGGbyt8Qj0_"
|
||||
"fYHBP4ObxwJNl56bk",
|
||||
.encryption = "salt=5LIDBXbvkBvvb7ZdD-T4PQ; rs=3",
|
||||
.ciphertextLen = 341,
|
||||
.maxPlaintextLen = 53,
|
||||
.plaintextLen = 17,
|
||||
},
|
||||
{
|
||||
.desc = "Example from draft-ietf-httpbis-encryption-encoding-02",
|
||||
.plaintext = "I am the walrus",
|
||||
.recvPrivKey = "\xf4\x55\xa5\xd7\x9f\xd0\x51\x00\x16\x0d\xa0\xf7\x93\x79"
|
||||
"\x79\xd1\x90\x59\x40\x9e\x1a\xbb\x6e\xc5\xd5\x5e\x05\xd2"
|
||||
"\xe2\xd2\x0f\xf3",
|
||||
.authSecret =
|
||||
"\x47\x6f\x6f\x20\x67\x6f\x6f\x20\x67\x27\x20\x6a\x6f\x6f\x62\x21",
|
||||
.ciphertext = "\xea\x7a\x80\x41\x43\x04\xf2\x13\x6a\xc3\x92\x77\x92\x5f"
|
||||
"\x1c\xa5\x55\x49\xca\x55\xca\x62\xa6\x4e\x7a\xc7\x99\x1b"
|
||||
"\xc5\x2e\x78\xaa\x40",
|
||||
.cryptoKey = "keyid=\"dhkey\"; "
|
||||
"dh="
|
||||
"\"BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4"
|
||||
"aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU\"",
|
||||
.encryption = "keyid=\"dhkey\"; salt=\"lngarbyKfMoi9Z75xYXmkg\"",
|
||||
.ciphertextLen = 33,
|
||||
.maxPlaintextLen = 17,
|
||||
.plaintextLen = 15,
|
||||
},
|
||||
};
|
||||
|
||||
static webpush_aesgcm_decrypt_err_test_t webpush_aesgcm_decrypt_err_tests[] = {
|
||||
{
|
||||
.desc = "rs = 7, no trailer",
|
||||
.recvPrivKey = "\xd9\xbb\xb8\xa5\xa3\x80\x65\xb2\xf6\x79\xfd\x6e\xfb\x04"
|
||||
"\xf3\x38\xdb\x93\x21\xc0\xcf\x73\x4d\x28\xd3\x35\x09\x82"
|
||||
"\x0e\x3a\x5d\x37",
|
||||
.authSecret =
|
||||
"\x42\x80\xe2\xd2\xee\xaf\x72\xc9\x48\x54\x92\xa2\xa2\xe5\xcc\x5f",
|
||||
// "O hai". The ciphertext is exactly `rs + 16`, without a trailer.
|
||||
.ciphertext = "\x60\x6e\x05\xf9\xbd\x3a\xcb\x9f\x74\x85\x19\x67\x4a\xcc\x3f"
|
||||
"\xbe\xe3\xb0\xeb\x65\x7d\x23\x3f",
|
||||
.cryptoKey = "dh=BD_"
|
||||
"bsTUpxBMvSv8eksith3vijMLj44D4jhJjO51y7wK1ytbUlsyYBBYYyB5AAe5b"
|
||||
"nREA_WipTgemDVz00LiWcfM",
|
||||
.encryption = "salt=xKWvs_jWWeg4KOsot_uBhA; rs=7",
|
||||
.ciphertextLen = 23,
|
||||
.maxPlaintextLen = 7,
|
||||
.err = ECE_ERROR_DECRYPT_TRUNCATED,
|
||||
},
|
||||
{
|
||||
// Last block is only 1 byte; pad length prefix is 2 bytes.
|
||||
.desc = "Pad size > last block length",
|
||||
.recvPrivKey = "\x0a\x8b\x04\x44\x05\x57\x82\xf4\xef\xa2\x1e\xd4\x92\xb4"
|
||||
"\x42\xd9\x5f\xa2\x5e\x83\x6c\xd1\xb5\xe5\x7b\xd2\x3a\xf2"
|
||||
"\xac\xe4\x95\xeb",
|
||||
.authSecret =
|
||||
"\x42\xd1\x99\x79\x8f\x0c\x41\xf0\x9a\xab\xe5\xf0\x28\xe5\x46\x05",
|
||||
.ciphertext = "\x26\xf5\xfd\x1e\xc2\x78\x94\xbe\x60\xcc\xff\x3f\xb8\x22\x9c"
|
||||
"\xea\xcd\x79\x89\x12\x1a\x36\x10\xf8\xa4\x50\xa0\xab\x9f\x9d"
|
||||
"\x7f\x06\xd4\xa8\x47\x0d\x52\x4a\xaf",
|
||||
.cryptoKey = "dh=BBNZNEi5Ew_ID5S4Y9jWBi1NeVDje6Mjs7SDLViUn6A8VAZj-"
|
||||
"6X3QAuYQ3j20BblqjwTgYst7PRnY6UGrKyLbmU",
|
||||
.encryption = "salt=ot8hzbwOo6CYe6ZhdlwKtg; rs=6",
|
||||
.ciphertextLen = 39,
|
||||
.maxPlaintextLen = 7,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
{
|
||||
// Last block is 1 byte, but claims its pad length is 2.
|
||||
.desc = "Padding length > last block length",
|
||||
.recvPrivKey = "\xf6\x5f\x9a\x85\xc0\x4c\xf8\x8d\x32\x93\x06\xd6\x88\x34"
|
||||
"\xbd\x29\x1a\xcf\x76\x1c\xaf\x4d\x9d\x12\xc4\xa8\x8f\xa6"
|
||||
"\x3d\x9a\x79\xa2",
|
||||
.authSecret =
|
||||
"\x80\xa1\xbf\x3f\xaf\x9d\x7b\x9a\x72\xcd\x2f\x21\xc8\x7f\xcd\xc9",
|
||||
.ciphertext = "\xa1\x64\x8e\x14\x0f\x94\x3b\x9a\x16\xab\xe9\x08\xef\xd4\x47"
|
||||
"\x68\x57\xf0\x01\xe8\xcb\x89\x02\x78\x0b\xb7\x93\x9a\xb4\x93"
|
||||
"\x06\x5e\x20\x02\xb2\xd7\x7f\x1e\xe5\x67\xe6",
|
||||
.cryptoKey = "dh=BKe2IBO_cwmEzQyTVscSbQcj0Y3uBSzGZ_mHlANMciS8uGpb7U8_"
|
||||
"Bw7TNdlYfpwWDLd0cxM8YYWNDbNJ_p2Rp4o",
|
||||
.encryption = "salt=z7QJ6UR89SiFRkd4RsC4Vg; rs=6",
|
||||
.ciphertextLen = 41,
|
||||
.maxPlaintextLen = 9,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
{
|
||||
// First block has no padding, but claims its pad length is 1.
|
||||
.desc = "Non-zero padding",
|
||||
.recvPrivKey = "\x23\x3b\x9a\xc4\xba\x85\x26\x68\xd2\xbb\xc1\xa3\x2c\x2a"
|
||||
"\x36\xa0\x46\x83\x66\x30\xc1\xba\xd5\xb8\x9b\x84\xf4\xab"
|
||||
"\x1d\x36\x5e\xc3",
|
||||
.authSecret =
|
||||
"\x70\xca\x56\x41\x6e\x7c\x06\xba\x43\x6c\x9f\x0a\xa9\xb4\xbd\x8a",
|
||||
.ciphertext = "\x41\xdb\xe3\x87\x42\xe4\x65\x72\xae\xff\x51\xef\xbf\x9e\x83"
|
||||
"\xd2\xb3\x92\x17\xa3\x30\xc3\x7c\xb4\x17\xcc\x64\xc5\x43\x65"
|
||||
"\xc1\x5b\xb6\x53\x58\x9a\x90\xe5\x14\x19\x1b",
|
||||
.cryptoKey = "dh=BBicj01QI0ryiFzAaty9VpW_crgq9XbU1bOCtEZI9UNE6tuOgp4lyN_"
|
||||
"UN0N905ECnLWK5v_sCPUIxnQgOuCseSo",
|
||||
.encryption = "salt=SbkGHONbQBBsBcj9dLyIUw; rs=6",
|
||||
.ciphertextLen = 41,
|
||||
.maxPlaintextLen = 9,
|
||||
.err = ECE_ERROR_DECRYPT_PADDING,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 6, auth tag for last record",
|
||||
.recvPrivKey = "\x9e\x13\x93\xf7\x5e\xf5\xc6\xea\x10\x04\x91\xa4\x89\x9d"
|
||||
"\xda\xa9\x3e\x6a\xc3\xf2\x0b\x27\xde\x3f\x3c\xf8\x95\x36"
|
||||
"\xed\x4b\x15\x26",
|
||||
.authSecret =
|
||||
"\xde\xb5\xa1\xb1\x10\x94\xfc\xa7\x5a\xa9\xf2\x8f\x6d\xdd\xf3\x05",
|
||||
.ciphertext = "\x0b\xbb\xb7\x8f\x90\x0b\xe1\x8c\xe1\xdb\x26\x01\xfe\xe9\x8d"
|
||||
"\xea\xdc\xeb\x54\x7c\x6b\xb7\xb0\xf9\x6d\xa4\xc4\x5b\xd0\xc4"
|
||||
"\xd4\x19\x37\xba\x9f\x5f\x63\x8c",
|
||||
.cryptoKey = "dh=BI38Qs_OhDmQIxbszc6Nako-MrX3FzAE_8HzxM1wgoEIG4ocxyF-"
|
||||
"YAAVhfkpJUvDpRyKW2LDHIaoylaZuxQfRhE",
|
||||
.encryption = "salt=QClh48OlvGpSjZ0Mg0e8rg; rs=6",
|
||||
.ciphertextLen = 38,
|
||||
.maxPlaintextLen = 6,
|
||||
.err = ECE_ERROR_SHORT_BLOCK,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_decrypt_ok(void) {
|
||||
size_t length = sizeof(webpush_aesgcm_decrypt_ok_tests) /
|
||||
sizeof(webpush_aesgcm_decrypt_ok_test_t);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
webpush_aesgcm_decrypt_ok_test_t t = webpush_aesgcm_decrypt_ok_tests[i];
|
||||
|
||||
const void* recvPrivKey = t.recvPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* ciphertext = t.ciphertext;
|
||||
|
||||
uint8_t salt[ECE_SALT_LENGTH];
|
||||
uint8_t rawSenderPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
uint32_t rs;
|
||||
int err = ece_webpush_aesgcm_headers_extract_params(
|
||||
t.cryptoKey, t.encryption, salt, ECE_SALT_LENGTH, rawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, &rs);
|
||||
ece_assert(!err, "Got %d parsing crypto headers", err);
|
||||
|
||||
size_t plaintextLen = ece_aesgcm_plaintext_max_length(rs, t.ciphertextLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
err = ece_webpush_aesgcm_decrypt(
|
||||
recvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, rawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, ciphertext, t.ciphertextLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(!err, "Got %d decrypting ciphertext for `%s`", err, t.desc);
|
||||
|
||||
ece_assert(plaintextLen == t.plaintextLen,
|
||||
"Got plaintext length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.plaintextLen);
|
||||
ece_assert(!memcmp(plaintext, t.plaintext, plaintextLen),
|
||||
"Wrong plaintext for `%s`", t.desc);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_decrypt_err(void) {
|
||||
size_t tests = sizeof(webpush_aesgcm_decrypt_err_tests) /
|
||||
sizeof(webpush_aesgcm_decrypt_err_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
webpush_aesgcm_decrypt_err_test_t t = webpush_aesgcm_decrypt_err_tests[i];
|
||||
|
||||
const void* recvPrivKey = t.recvPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* ciphertext = t.ciphertext;
|
||||
|
||||
uint8_t salt[ECE_SALT_LENGTH];
|
||||
uint8_t rawSenderPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
uint32_t rs;
|
||||
int err = ece_webpush_aesgcm_headers_extract_params(
|
||||
t.cryptoKey, t.encryption, salt, ECE_SALT_LENGTH, rawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, &rs);
|
||||
ece_assert(!err, "Got %d parsing crypto headers", err);
|
||||
|
||||
size_t plaintextLen = ece_aesgcm_plaintext_max_length(rs, t.ciphertextLen);
|
||||
ece_assert(plaintextLen == t.maxPlaintextLen,
|
||||
"Got plaintext max length %zu for `%s`; want %zu", plaintextLen,
|
||||
t.desc, t.maxPlaintextLen);
|
||||
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
err = ece_webpush_aesgcm_decrypt(
|
||||
recvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, rawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, ciphertext, t.ciphertextLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(err == t.err, "Got %d decrypting ciphertext for `%s`; want %d",
|
||||
err, t.desc, t.err);
|
||||
|
||||
free(plaintext);
|
||||
}
|
||||
}
|
||||
134
mobile/ios/ThirdParty/ecec/test/e2e.c
vendored
Normal file
134
mobile/ios/ThirdParty/ecec/test/e2e.c
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_e2e(void) {
|
||||
uint8_t rawRecvPrivKey[ECE_WEBPUSH_PRIVATE_KEY_LENGTH];
|
||||
uint8_t rawRecvPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
uint8_t authSecret[ECE_WEBPUSH_AUTH_SECRET_LENGTH];
|
||||
int err = ece_webpush_generate_keys(
|
||||
rawRecvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, rawRecvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, authSecret, ECE_WEBPUSH_AUTH_SECRET_LENGTH);
|
||||
ece_assert(!err, "Got %d generating keys", err);
|
||||
|
||||
const void* input = "When I grow up, I want to be a watermelon";
|
||||
size_t inputLen = strlen(input);
|
||||
|
||||
size_t payloadLen = ece_aes128gcm_payload_max_length(4096, 0, inputLen);
|
||||
ece_assert(payloadLen == 334, "Got %zu for payload max length; want 334",
|
||||
payloadLen);
|
||||
uint8_t* payload = calloc(payloadLen, sizeof(uint8_t));
|
||||
|
||||
err = ece_webpush_aes128gcm_encrypt(rawRecvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, 4096, 0,
|
||||
input, inputLen, payload, &payloadLen);
|
||||
ece_assert(!err, "Got %d encrypting plaintext", err);
|
||||
ece_assert(payloadLen == 144, "Got %zu for payload length; want 144",
|
||||
payloadLen);
|
||||
|
||||
size_t plaintextLen = ece_aes128gcm_plaintext_max_length(payload, payloadLen);
|
||||
ece_assert(plaintextLen == 42, "Got %zu for plaintext max length; want 42",
|
||||
plaintextLen);
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
err = ece_webpush_aes128gcm_decrypt(
|
||||
rawRecvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, payload, payloadLen, plaintext,
|
||||
&plaintextLen);
|
||||
ece_assert(!err, "Got %d decrypting payload", err);
|
||||
ece_assert(plaintextLen == inputLen, "Got %zu for plaintext length; want %zu",
|
||||
plaintextLen, inputLen);
|
||||
ece_assert(!memcmp(plaintext, input, inputLen),
|
||||
"Got `%s` for plaintext; want `%s`", plaintext, input);
|
||||
|
||||
free(payload);
|
||||
free(plaintext);
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_e2e(void) {
|
||||
uint8_t rawRecvPrivKey[ECE_WEBPUSH_PRIVATE_KEY_LENGTH];
|
||||
uint8_t rawRecvPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
uint8_t authSecret[ECE_WEBPUSH_AUTH_SECRET_LENGTH];
|
||||
int err = ece_webpush_generate_keys(
|
||||
rawRecvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, rawRecvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, authSecret, ECE_WEBPUSH_AUTH_SECRET_LENGTH);
|
||||
ece_assert(!err, "Got %d generating keys", err);
|
||||
|
||||
const void* input = "If the wind in my sail on the sea stays behind me, one "
|
||||
"day I'll know how far I'll go";
|
||||
size_t inputLen = strlen(input);
|
||||
|
||||
size_t ciphertextLen = ece_aesgcm_ciphertext_max_length(26, 6, inputLen);
|
||||
ece_assert(ciphertextLen == 162,
|
||||
"Got %zu for ciphertext max length; want 162", ciphertextLen);
|
||||
|
||||
uint8_t* ciphertext = calloc(ciphertextLen, sizeof(uint8_t));
|
||||
|
||||
uint8_t encryptSalt[ECE_SALT_LENGTH];
|
||||
uint8_t encryptRawSenderPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
err = ece_webpush_aesgcm_encrypt(
|
||||
rawRecvPubKey, ECE_WEBPUSH_PUBLIC_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, 26, 6, input, inputLen, encryptSalt,
|
||||
ECE_SALT_LENGTH, encryptRawSenderPubKey, ECE_WEBPUSH_PUBLIC_KEY_LENGTH,
|
||||
ciphertext, &ciphertextLen);
|
||||
ece_assert(!err, "Got %d encrypting plaintext", err);
|
||||
ece_assert(ciphertextLen == 162, "Got %zu for ciphertext length; want 162",
|
||||
ciphertextLen);
|
||||
|
||||
size_t cryptoKeyHeaderLen = 0;
|
||||
size_t encryptionHeaderLen = 0;
|
||||
err = ece_webpush_aesgcm_headers_from_params(
|
||||
encryptSalt, ECE_SALT_LENGTH, encryptRawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, 14, NULL, &cryptoKeyHeaderLen, NULL,
|
||||
&encryptionHeaderLen);
|
||||
ece_assert(!err, "Got %d determining crypto header lengths", err);
|
||||
|
||||
char* cryptoKeyHeader = malloc(cryptoKeyHeaderLen + 1);
|
||||
char* encryptionHeader = malloc(encryptionHeaderLen + 1);
|
||||
err = ece_webpush_aesgcm_headers_from_params(
|
||||
encryptSalt, ECE_SALT_LENGTH, encryptRawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, 26, cryptoKeyHeader, &cryptoKeyHeaderLen,
|
||||
encryptionHeader, &encryptionHeaderLen);
|
||||
ece_assert(!err, "Got %d formatting crypto headers", err);
|
||||
cryptoKeyHeader[cryptoKeyHeaderLen] = '\0';
|
||||
encryptionHeader[encryptionHeaderLen] = '\0';
|
||||
|
||||
uint8_t decryptSalt[ECE_SALT_LENGTH];
|
||||
uint8_t decryptRawSenderPubKey[ECE_WEBPUSH_PUBLIC_KEY_LENGTH];
|
||||
uint32_t rs;
|
||||
err = ece_webpush_aesgcm_headers_extract_params(
|
||||
cryptoKeyHeader, encryptionHeader, decryptSalt, ECE_SALT_LENGTH,
|
||||
decryptRawSenderPubKey, ECE_WEBPUSH_PUBLIC_KEY_LENGTH, &rs);
|
||||
ece_assert(!err, "Got %d extracting crypto params", err);
|
||||
ece_assert(!memcmp(encryptSalt, decryptSalt, ECE_SALT_LENGTH),
|
||||
"Wrong salt for `%s`", input);
|
||||
ece_assert(!memcmp(encryptRawSenderPubKey, decryptRawSenderPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH),
|
||||
"Wrong sender public key for `%s`", input);
|
||||
ece_assert(rs == 26, "Got rs = %" PRIu32 "; want 26", rs);
|
||||
|
||||
size_t plaintextLen = ece_aesgcm_plaintext_max_length(rs, ciphertextLen);
|
||||
ece_assert(plaintextLen == 98, "Got %zu for plaintext max length; want 98",
|
||||
plaintextLen);
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
|
||||
err = ece_webpush_aesgcm_decrypt(
|
||||
rawRecvPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, decryptSalt, ECE_SALT_LENGTH,
|
||||
decryptRawSenderPubKey, ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, ciphertext,
|
||||
ciphertextLen, plaintext, &plaintextLen);
|
||||
ece_assert(!err, "Got %d decrypting ciphertext", err);
|
||||
ece_assert(plaintextLen == inputLen, "Got %zu for plaintext length; want %zu",
|
||||
plaintextLen, inputLen);
|
||||
ece_assert(!memcmp(plaintext, input, inputLen),
|
||||
"Got `%s` for plaintext; want `%s`", plaintext, input);
|
||||
|
||||
free(ciphertext);
|
||||
free(cryptoKeyHeader);
|
||||
free(encryptionHeader);
|
||||
free(plaintext);
|
||||
}
|
||||
372
mobile/ios/ThirdParty/ecec/test/encrypt/aes128gcm.c
vendored
Normal file
372
mobile/ios/ThirdParty/ecec/test/encrypt/aes128gcm.c
vendored
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
typedef struct webpush_aes128gcm_encrypt_ok_test_s {
|
||||
const char* desc;
|
||||
const char* payload;
|
||||
const char* senderPrivKey;
|
||||
const char* recvPubKey;
|
||||
const char* authSecret;
|
||||
const char* salt;
|
||||
const char* plaintext;
|
||||
size_t plaintextLen;
|
||||
size_t padLen;
|
||||
size_t maxPayloadLen;
|
||||
size_t payloadLen;
|
||||
uint32_t rs;
|
||||
} webpush_aes128gcm_encrypt_ok_test_t;
|
||||
|
||||
static webpush_aes128gcm_encrypt_ok_test_t
|
||||
webpush_aes128gcm_encrypt_ok_tests[] = {
|
||||
{
|
||||
.desc = "Example from draft-ietf-webpush-encryption-latest",
|
||||
.payload = "\x0c\x6b\xfa\xad\xad\x67\x95\x88\x03\x09\x2d\x45\x46\x76\xf3"
|
||||
"\x97\x00\x00\x10\x00\x41\x04\xfe\x33\xf4\xab\x0d\xea\x71\x91"
|
||||
"\x4d\xb5\x58\x23\xf7\x3b\x54\x94\x8f\x41\x30\x6d\x92\x07\x32"
|
||||
"\xdb\xb9\xa5\x9a\x53\x28\x64\x82\x20\x0e\x59\x7a\x7b\x7b\xc2"
|
||||
"\x60\xba\x1c\x22\x79\x98\x58\x09\x92\xe9\x39\x73\x00\x2f\x30"
|
||||
"\x12\xa2\x8a\xe8\xf0\x6b\xbb\x78\xe5\xec\x0f\xf2\x97\xde\x5b"
|
||||
"\x42\x9b\xba\x71\x53\xd3\xa4\xae\x0c\xaa\x09\x1f\xd4\x25\xf3"
|
||||
"\xb4\xb5\x41\x4a\xdd\x8a\xb3\x7a\x19\xc1\xbb\xb0\x5c\xf5\xcb"
|
||||
"\x5b\x2a\x2e\x05\x62\xd5\x58\x63\x56\x41\xec\x52\x81\x2c\x6c"
|
||||
"\x8f\xf4\x2e\x95\xcc\xb8\x6b\xe7\xcd",
|
||||
.senderPrivKey =
|
||||
"\xc9\xf5\x8f\x89\x81\x3e\x9f\x8e\x87\x2e\x71\xf4\x2a\xa6"
|
||||
"\x4e\x17\x57\xc9\x25\x4d\xcc\x62\xb7\x2d\xdc\x01\x0b\xb4"
|
||||
"\x04\x3e\xa1\x1c",
|
||||
.recvPubKey =
|
||||
"\x04\x25\x71\xb2\xbe\xcd\xfd\xe3\x60\x55\x1a\xaf\x1e\xd0\xf4"
|
||||
"\xcd\x36\x6c\x11\xce\xbe\x55\x5f\x89\xbc\xb7\xb1\x86\xa5\x33"
|
||||
"\x39\x17\x31\x68\xec\xe2\xeb\xe0\x18\x59\x7b\xd3\x04\x79\xb8"
|
||||
"\x6e\x3c\x8f\x8e\xce\xd5\x77\xca\x59\x18\x7e\x92\x46\x99\x0d"
|
||||
"\xb6\x82\x00\x8b\x0e",
|
||||
.authSecret =
|
||||
"\x05\x30\x59\x32\xa1\xc7\xea\xbe\x13\xb6\xce\xc9\xfd\xa4\x88\x82",
|
||||
.salt =
|
||||
"\x0c\x6b\xfa\xad\xad\x67\x95\x88\x03\x09\x2d\x45\x46\x76\xf3\x97",
|
||||
.plaintext = "When I grow up, I want to be a watermelon",
|
||||
.plaintextLen = 41,
|
||||
.padLen = 0,
|
||||
.maxPayloadLen = 334,
|
||||
.payloadLen = 144,
|
||||
.rs = 4096,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 24, pad = 6",
|
||||
.payload = "\xff\x80\x50\x30\xa1\x08\xe1\x14\xe6\xc1\x7f\xad\x61\x86\xa1"
|
||||
"\xa6\x00\x00"
|
||||
"\x00\x18\x41\x04\x30\xef\xcb\x1e\xb0\x43\xb8\x05\xe4\xe4\x4b"
|
||||
"\xab\x35\xf8"
|
||||
"\x25\x13\xc3\x3f\xed\xb2\x87\x00\xf7\xe5\x68\xac\x8b\x61\xe8"
|
||||
"\xd8\x35\x66"
|
||||
"\x5a\x51\xeb\x66\x79\xb2\xdb\x22\x8a\x10\xc0\xc3\xfe\x50\x77"
|
||||
"\x06\x28\x48"
|
||||
"\xd9\xbb\x3d\x60\x27\x9f\x93\xce\x35\x48\x47\x28\xaa\x1f\xd2"
|
||||
"\xc1\x71\x39"
|
||||
"\x49\xae\xc9\x8f\x05\x09\x6c\x72\x98\xfd\x3f\x51\xc4\xf8\x18"
|
||||
"\xfa\xfa\x1f"
|
||||
"\xe6\x15\xd8\x44\x7b\x3a\x05\x40\x60\x31\xf6\x40\x1a\xc2\x4f"
|
||||
"\x2a\x77\x5c"
|
||||
"\xa5\x24\x56\xa9\x21\xb8\x3b\x9e\x00\x42\xc3\xa6\x3e\x1a\xfa"
|
||||
"\x1a\xe0\x12"
|
||||
"\x77\x4d\x9d\x77\x5b\xe8\xd1\x94\x19\x45\x1d\x37\xff\x59\xff"
|
||||
"\x59\x2e\x84"
|
||||
"\xf0\x74\x40\xa6\x3f\xc1\x7f\x5c\xab\xcb\x9a\x50\xed\xda\xf7"
|
||||
"\x53\x70\xdb"
|
||||
"\x64\x7f\x94\x44\x7d\x3f\x16\x62\x69\xd8\x71\x1d\xf0\xf5\x7e"
|
||||
"\x56\x04\x95"
|
||||
"\x76\xe1\x13\x0a\x5a\x5e\x1f\x94\xba\x8a\x5d\x0b\x00\x07\xc6"
|
||||
"\xc0\xfd\x29"
|
||||
"\x98\x42\x9e\x7d\x63\xd4\xef\x91\x97\x98\xf4\x6e\xcf\x5f\x0b"
|
||||
"\x28\xfb\x80"
|
||||
"\xf5\xb2\x43\x9d\xe2\x6b\x8a\x52\x20\x0b\xc7\xd6\xaf\x7a\x48"
|
||||
"\x40\x72\x1f"
|
||||
"\xe8\xbe\x85\x24\xa6\x91\xb6\xef\x0e\xda\xe9\x0b\xb6\xf5\x92"
|
||||
"\x78\x94\x81"
|
||||
"\x9b\x83\x1b\x45\xb5\x3f\x84\x01\xfe\x02\x2d\xbb\x64\xed\x75"
|
||||
"\x65\x35\x09"
|
||||
"\x04\xac\x0b\x51\x71\x35\xd7\xf8\xab\xbc\x98\x12\x7f\xb1\x63"
|
||||
"\x86\x4d\x4d"
|
||||
"\x4a\x30\x74\x25\xb2\xcd\x43\xdb\x22\xaf\x26\x7d\x71\xc3\x71"
|
||||
"\x46\x99\x4a"
|
||||
"\x8c\x48\x05\xad\xc3\x41\xbf\xba\x27\xaf\x09\xfd\x80\xbd\x5e"
|
||||
"\xff\x51\xd8"
|
||||
"\x77\x28\x2a\x2f\xbf\xbf\xeb\x10\x19\x9e\x78\x79\xe4\xb9\xd1"
|
||||
"\x3a\x46\xd5"
|
||||
"\x7f\xb7\xd7\x86\x82\x48\x53\xe1\xcc\x89\xca\xfb\xaf\x14\xde"
|
||||
"\x1e\x92\x4c"
|
||||
"\x94\x4f\xeb\x8b\x62\x6c\xe0\x20\x7d\x6f\x9f\xa9\xd8\x49\xee"
|
||||
"\xca\xc6\x9b"
|
||||
"\x42\xd6\xe7\xa2\x3b\xd5\x12\x4d\x49\x62\x2b\x44\xb3\x5c\x5b"
|
||||
"\x15\xfb\x0e"
|
||||
"\x6a\x77\x81\xa5\x03\xf1\xa4\xe0\x62\xe0\x15\xd5\x57\xd9\x5d"
|
||||
"\x44\xd9\xd8"
|
||||
"\xb0\x79\x9b\x3a\xaf\xce\x83\xd5\xd4",
|
||||
.senderPrivKey =
|
||||
"\x0f\x28\xbe\xaf\x7e\x27\x79\x3c\x03\x63\x8d\xc2\x97\x3a"
|
||||
"\x15\xb0\x01\x6e\x1b\x36\x7c\xbf\xfd\xa8\x86\x1a\xb1\x75"
|
||||
"\xf3\x1b\xce\x02",
|
||||
.recvPubKey =
|
||||
"\x04\xc0\xd1\xa8\x12\xb2\x91\x29\x1d\xd7\xbe\xee\x35\x87\x13"
|
||||
"\xc1\x26\xc5\x89\xf3\x63\x3c\x26\xd1\xa2\x01\x31\x1d\xe0\x36"
|
||||
"\xdc\x10\x93\x1e\x4e\xe1\x42\xf6\x19\x21\xa3\xea\x58\x64\xe8"
|
||||
"\x72\xa9\x38\x41\xa5\x29\x44\xe5\xb3\xf6\xac\xce\xcc\xe8\xc8"
|
||||
"\x28\xfb\x04\xa4\xcd",
|
||||
.authSecret =
|
||||
"\x9d\x77\x35\xd8\xde\x19\x62\xb9\x83\x94\xb0\x7f\xfe\x28\x7e\x20",
|
||||
.salt =
|
||||
"\xff\x80\x50\x30\xa1\x08\xe1\x14\xe6\xc1\x7f\xad\x61\x86\xa1\xa6",
|
||||
.plaintext = "I am the very model of a modern Major-General, I've "
|
||||
"information vegetable, animal, and mineral",
|
||||
.plaintextLen = 94,
|
||||
.padLen = 6,
|
||||
.maxPayloadLen = 631,
|
||||
.payloadLen = 441,
|
||||
.rs = 24,
|
||||
},
|
||||
{
|
||||
// This test is also interesting because the data length (54) is a
|
||||
// multiple of rs (18). We'll allocate memory to hold 4 records, but only
|
||||
// write 3.
|
||||
.desc = "rs = 18, pad = 31",
|
||||
.payload = "\xe4\x98\x88\xd2\xb2\x8f\x27\x7f\x84\x7b\xc5\xde\x96\xf0\xf8"
|
||||
"\x1b\x00\x00"
|
||||
"\x00\x12\x41\x04\x00\xb8\x33\xe4\x81\xa9\x9a\xa3\x30\xdc\xb2"
|
||||
"\x77\x92\x2d"
|
||||
"\x5f\x84\xaf\x2e\x9c\xe6\x11\xad\x2a\xd3\xed\x0f\x5b\x43\x19"
|
||||
"\x12\xd3\x5e"
|
||||
"\xa7\x2f\xc5\xbf\x76\xb7\x69\xd9\x52\x67\x78\xf5\xab\xfa\x05"
|
||||
"\x86\x50\x98"
|
||||
"\x8d\xa5\xe5\x31\xff\x82\xd1\xa7\x04\x37\x94\xc7\x17\x06\x3a"
|
||||
"\xeb\x95\x8b"
|
||||
"\xf1\x16\xbc\xcf\x50\x74\x2f\xd4\xd6\x9b\xd0\xea\x7e\x3f\x61"
|
||||
"\x1c\x70\x9b"
|
||||
"\xf2\xcd\xf5\xcd\x47\xc6\x42\x6c\xb8\x32\x3b\x53\x98\xc4\x3c"
|
||||
"\x0d\x0b\x92"
|
||||
"\xcc\x98\x2d\xa1\xc2\x4c\xe5\xfe\xe2\xb2\x03\xf7\xad\x78\xca"
|
||||
"\x44\xf0\x49"
|
||||
"\x0f\x34\x07\xf5\xfe\xe8\x83\x26\x6e\xe4\x70\x35\x19\x5d\xe0"
|
||||
"\xfe\x6d\x8a"
|
||||
"\x75\xe4\x87\xdf\x25\x6d\xb5\x97\xa7\x5e\x45\xae\x4f\xb5\x5b"
|
||||
"\x82\x59\xcb"
|
||||
"\x0b\x2d\x19\xe7\xb0\x57\x14\x26\x7e\xb5\x60\xae\x07\x2b\x7a"
|
||||
"\x66\x59\x51"
|
||||
"\x91\x7a\x06\x87\x32\xdf\x30\x9b\xe2\x56\xf9\x0f\x2a\xdd\xa3"
|
||||
"\x2f\x05\xfe"
|
||||
"\xaa\x5e\x9b\x06\x95\xbc\xa2\xcc\xf2\x2a\xae\xfc\x7d\xa9\xce"
|
||||
"\xeb\xc5\xd4"
|
||||
"\x0c\x12\xd3\x2a\xdb\x5c\x84\xcb\x32\x0a\xf9\x44\x01\x60\x95"
|
||||
"\x36\x2f\xeb"
|
||||
"\xba\x4f\xfa\x4a\x99\x83\x0e\x49\x58\xea\x2b\xba\x50\x8c\xb6"
|
||||
"\x83\xa5\x8d"
|
||||
"\x20\x27\xd4\xb7\x47\x26\xa8\x53\xb2\x4b\x47\xcc\xba\x75\x1a"
|
||||
"\xbe\x9d\x9a"
|
||||
"\xb2\xda\x9e\xc2\xba\x9c\x7c\xcf\x0c\xf1\x73\x05\xba\xe3\x14"
|
||||
"\xd3\x8a\x68"
|
||||
"\x76\x18\xb0\x77\x2f\xcb\x71\xd4\x41\x90\x27\xa4\xbf\x43\x5c"
|
||||
"\xb7\x21\xaa"
|
||||
"\xd7\x4e\xfc\x17\x99\x81\xb7\x16\x96\x04\xbf\x97\xec\xac\x41"
|
||||
"\xe7\x38\x84"
|
||||
"\x45\x69\x33\x73\x48\x18\x13\x29\x23\xb5\x6c\x15\x2d\x6c\x9e"
|
||||
"\x59\xae\xf9"
|
||||
"\x95\xac\xa5\x9d\xe0\xbf\x2c\x80\x3a\x07\x18\x08\x89\x67\x0a"
|
||||
"\x08\xe6\x4a"
|
||||
"\x20\xd2\xbf\xa8\x53\xe0\x11\x28\x72\x94\x7b\xaa\xaf\xfb\x51"
|
||||
"\x0c\xc9\xe7"
|
||||
"\x5d\x63\x10\xed\x6a\xac\xbd\x2e\x0b\xa3\xa2\x9b\xe4\x2c\x65"
|
||||
"\x32\xea\x4e"
|
||||
"\x33\x46\xe1\xf0\x57\x16\x46\x37\x1c\x71\x66\x5e\x3f\xac\x9d"
|
||||
"\x76\xfa\xee"
|
||||
"\x1f\x12\x2e\x64\xd4\x90\xdd\x2a\x3e\x31\x81\x6e\xab\x58\x3f"
|
||||
"\x17\x28\x41"
|
||||
"\xa0\x75\xd2\x05\xf3\x18\x71\x4a\x8c\x70\xce\x0f\x32\x7f\x4d"
|
||||
"\x92\xb8\xc9"
|
||||
"\xdc\xb8\x13\xe6\xd2\x4f\xe8\x56\x33\xf1\xa9\xc7\xc1\xe4\xa1"
|
||||
"\xfb\x31\x4d"
|
||||
"\xd5\xfe\x3e\x28\x0e\x39\x08\xf3\x6c\x8c\xbf\xb8\x0b\x7d\x92"
|
||||
"\x43\xab\xaf"
|
||||
"\xfa\x65\xc2\x16\xcf\x1a\xa8\xb8\xd6\x26\xa6\x30\xdf\xe8\x18"
|
||||
"\x6c\xe9\x77"
|
||||
"\xa5\xb8\xf3\x64\x9d\x37\x53\xb9\x17\x6c\x36\x7e\x4e\x07\xf2"
|
||||
"\x20\xa1\x75"
|
||||
"\x80\x61\x38\xe8\x88\x25\xa2\xf3\x49\x84\x20\x58\x2b\x96\x20"
|
||||
"\x96\x58\xbb"
|
||||
"\xfa\x8f\x2b\xa6\x93\x3a\x83\xc2\x5e\xdb\x26\x91\x87\x79\x65"
|
||||
"\x42\xe2\xac"
|
||||
"\x49\xb8\x07\x86\x36\xbd\xdc\x26\x8e\x11\x62\x5e\x8b\xff\x9f"
|
||||
"\x0a\x34\x3d"
|
||||
"\x3a\x4c\x06\x08\x0e\xf0\x80\x3b\x8d\xcd\x8e\x84\x1d\x0e\x27"
|
||||
"\x59\xe4\x83"
|
||||
"\xea\x19\xb9\x03\x32\x4d\x9e\xc4\xd5\x2f\x49\x1a\xce\xf3\xee"
|
||||
"\xff\x44\x1c"
|
||||
"\x37\x88\x1c\x75\x93\xea\xc3\x16\x21\x33\x7a\x5e\x86\x59\xf9"
|
||||
"\x3e\x20\x07"
|
||||
"\x9b\x0e\x26\xeb\xfe\x56\xc1\x04\x55\xd1\x09\x71\x13\x0b\xd2"
|
||||
"\xa2\xc1\x59"
|
||||
"\xc7\x4f\x48\xb2\xe5\x26\x53\x0a\x76\xf6\x4c\xca\x2e\xfb\x24"
|
||||
"\x6e\x79\x3d"
|
||||
"\x11\xfb\x75\xa6\x68\x01\x8e\x70\xc3\x10\x71\x00\xf8\x1b\xa3"
|
||||
"\xb1\x6a\xe4"
|
||||
"\x0a\x83\x8f\x18\xd4\xc4\x7f\x1d\x71\x32\xf1\x74\x68\x8e\xc5"
|
||||
"\x38\x23\x94"
|
||||
"\xe0\x11\x99\x21\x73\x1a\x16\x87\x9b\x85\x8f\xf3\x8f\x72\x85"
|
||||
"\x1e\xa3\xd9"
|
||||
"\xf5\x26\x3f\xec\x5a\x60\x6d\x12\x71\xa8\x9b\x84\xcc\xa5\x3e"
|
||||
"\xd7\x3c\x52"
|
||||
"\x54\xe2\x45\xbf\x8f\x2f\x27\xc2\xc1\xc8\x7f\x39\xee\xa7\x8c"
|
||||
"\x70\x17\xc8"
|
||||
"\xc6\xb5\xab\x01\x66\x30\x32\xb5\x8d\xa3\x10\x57\x28\x5e\x56"
|
||||
"\xc2\x03\xf4"
|
||||
"\xe4\x8d\x67\x89\xc6\x6b\x26\x95\xa9\x00\xe0\x04\x82\xbd\x84"
|
||||
"\x65\x59\xec"
|
||||
"\xdd\xd4\x02\x64\xb3\x8e\x27\x96\x47\xd1\xec\x0f\xcc\xdc\x18"
|
||||
"\x81\x83\x8b"
|
||||
"\xbe\x0c\x83\x5e\x26\x90\xef\x05\x8b\x8f\x6a\x03\xe2\x9c\xd9"
|
||||
"\xeb\x95\x84"
|
||||
"\xe9\x7f\xbc\x30\x97\x73\xc3\x68\x8e\x5e\x03\xf9\xd3\x8e\x3e"
|
||||
"\x45\x48\x73"
|
||||
"\x8a\x5f\x56\x9c\x59\x14\x7d\x3e\x82\x3c\xcc\xac\x71\xd5\xe8"
|
||||
"\x82\x5d\x51"
|
||||
"\x34\xce\x98\x13\xcd\x0b\x8f\x96\x27\xa3\xdb\xfa\x45\xb8\x3a"
|
||||
"\x59\xc8\x3d"
|
||||
"\x2b\x4d\x3a\xd4\x37\x77\x8a\x3c\xb1\xbc\x77\xba\x16\xc9\x23"
|
||||
"\x06\xf4\x26"
|
||||
"\x1a\x2a\x1f\x0d\x5c\x7e\xda\xec\xf9\x26\xf9\x2d\x7c\x9d\xfc"
|
||||
"\xae\x87\x51"
|
||||
"\x3a\x68\xb8\xc7\xef\x7c\x63\x26\x4b\x85\x87\x67\xc1\x1a\xaa"
|
||||
"\x41\xd2\x7c"
|
||||
"\x63\x6f\x52\xe2\x85\x51\xe9\x3a\x96\x9c\xdc\x96\xd4\x38\x67"
|
||||
"\xb7\xcb\xd6"
|
||||
"\x8f\xe0\x35\x7b\xd3\x34\x15\xfa\xf2\x2a\xae\xeb\xc9\x57\xf4"
|
||||
"\xb5\x73\x7a"
|
||||
"\x04\xab\x72\x77\xb4\xed\x40\x08\xf0\x9e\xda\xff\x5a\x6d\xb6"
|
||||
"\x9f\x6c\xb0"
|
||||
"\x6f\x3d\x0b\x76\x68\x89\x06\xb2\xf5\x3b\x27\xe6\x3f\x37\x28"
|
||||
"\xba\x2e\xda"
|
||||
"\x50\x5f\xb1\xb3\x2f\x81\xdd\xdc\x6d\x30\x5f\xd5\x94\x9e\xdd"
|
||||
"\x05\x49\x0c"
|
||||
"\xb1\x61\x8f\x0c\xe1\x43\x0e\x9f\x5e\xdf\x50\x01\x2d\xc3",
|
||||
.senderPrivKey =
|
||||
"\x78\x30\x57\x7b\xaf\xcf\xc4\x58\x28\xda\x0c\x40\xaa\xb0"
|
||||
"\x9f\xb2\x27\xbf\xea\xe0\x68\xaa\xb8\xc0\x64\x22\x2a\xcb"
|
||||
"\xe6\xef\xfd\x34",
|
||||
.recvPubKey =
|
||||
"\x04\xc3\xd7\x14\xcb\x42\xe2\xb0\xa1\xd6\xf9\x85\x99\xe2\xf1"
|
||||
"\x86\xb8\xc2\xba\x6f\x6f\xab\x5e\x09\xa2\xab\xca\x86\x5c\x08"
|
||||
"\x05\x89\x2b\x2c\x37\x29\x33\x0e\xf8\x3d\xc9\xdf\x4b\x44\x36"
|
||||
"\x2b\x03\x9a\x06\x09\xd3\x6b\xeb\x93\x21\xa4\x31\xec\x12\x35"
|
||||
"\x06\xdd\xd9\x0f\x24",
|
||||
.authSecret =
|
||||
"\xe4\xd7\xb7\x9d\xec\xde\xde\x12\xc3\xe9\xd9\x0d\x3e\x05\x73\x0f",
|
||||
.salt =
|
||||
"\xe4\x98\x88\xd2\xb2\x8f\x27\x7f\x84\x7b\xc5\xde\x96\xf0\xf8\x1b",
|
||||
.plaintext = "Push the button, Frank!",
|
||||
.plaintextLen = 23,
|
||||
.padLen = 31,
|
||||
.maxPayloadLen = 1265,
|
||||
.payloadLen = 1058,
|
||||
.rs = 18,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_encrypt_ok(void) {
|
||||
size_t tests = sizeof(webpush_aes128gcm_encrypt_ok_tests) /
|
||||
sizeof(webpush_aes128gcm_encrypt_ok_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
webpush_aes128gcm_encrypt_ok_test_t t =
|
||||
webpush_aes128gcm_encrypt_ok_tests[i];
|
||||
|
||||
const void* senderPrivKey = t.senderPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* salt = t.salt;
|
||||
const void* recvPubKey = t.recvPubKey;
|
||||
const void* plaintext = t.plaintext;
|
||||
|
||||
size_t payloadLen =
|
||||
ece_aes128gcm_payload_max_length(t.rs, t.padLen, t.plaintextLen);
|
||||
ece_assert(payloadLen == t.maxPayloadLen,
|
||||
"Got payload max length %zu for `%s`; want %zu", payloadLen,
|
||||
t.desc, t.maxPayloadLen);
|
||||
|
||||
uint8_t* payload = calloc(payloadLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aes128gcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, t.rs, t.padLen, plaintext, t.plaintextLen,
|
||||
payload, &payloadLen);
|
||||
ece_assert(!err, "Got %d encrypting payload for `%s`", err, t.desc);
|
||||
|
||||
ece_assert(payloadLen == t.payloadLen,
|
||||
"Got actual payload length %zu for `%s`; want %zu", payloadLen,
|
||||
t.desc, t.payloadLen);
|
||||
ece_assert(!memcmp(payload, t.payload, payloadLen),
|
||||
"Wrong payload for `%s`", t.desc);
|
||||
|
||||
free(payload);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_encrypt_pad(void) {
|
||||
static const uint32_t maxRs = 128;
|
||||
|
||||
const void* senderPrivKey = "\xac\xae\xc1\xc3\x7c\x30\x7c\xb9\x02\x8f\xbb\xd9"
|
||||
"\xc7\xf3\xc6\x89\x26\x60\x08\x95\x9a\x5e\xd4\x03"
|
||||
"\x42\x21\xb2\xda\x72\x01\x82\x8f";
|
||||
const void* authSecret =
|
||||
"\x44\x29\x81\x2d\x53\x5f\xbf\xdb\xea\xc8\x6d\xb7\x14\x5c\x6a\xf2";
|
||||
const void* salt =
|
||||
"\x45\x2b\xfb\xea\x8c\xc7\xa7\x57\x14\xd2\x03\xcf\xf1\x02\xe8\x76";
|
||||
const void* recvPubKey =
|
||||
"\x04\x2d\x78\x8d\x3e\x8e\x82\xf2\xd7\xea\xef\xbd\xe3\xa1\xbe\xde\xa2\x1f"
|
||||
"\x3b\xc9\x60\x33\x15\x73\x22\xa0\x9e\x14\x46\x55\xa3\xdf\x78\xfd\xca\xc8"
|
||||
"\x10\xe3\x02\x2a\xb5\x6a\x0e\xa9\xb8\xec\x06\x73\x8a\xce\x41\x1f\x49\x54"
|
||||
"\x7b\xc0\x0d\x1a\x1c\xde\x97\xce\x7b\xdd\x26";
|
||||
|
||||
// For rs = `ECE_AES128GCM_MIN_RS`, we allow any amount of padding, because we
|
||||
// can only include one byte of data per record.
|
||||
for (uint32_t rs = ECE_AES128GCM_MIN_RS + 1; rs <= maxRs; rs++) {
|
||||
// Generate a random plaintext.
|
||||
size_t plaintextLen = (size_t)(rand() % (int) (maxRs - 1) + 1);
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
int ok = RAND_bytes(plaintext, (int) plaintextLen);
|
||||
ece_assert(ok == 1, "Got %d generating plaintext for rs = %d", ok, rs);
|
||||
|
||||
size_t maxPadLen = (rs - ECE_AES128GCM_MIN_RS) * (plaintextLen + 1);
|
||||
|
||||
// Encrypting with the maximum padding length should succeed.
|
||||
size_t payloadLen =
|
||||
ece_aes128gcm_payload_max_length(rs, maxPadLen, plaintextLen);
|
||||
uint8_t* payload = calloc(payloadLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aes128gcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, maxPadLen, plaintext, plaintextLen,
|
||||
payload, &payloadLen);
|
||||
ece_assert(!err, "Got %d encrypting with rs = %d, padLen = %zu", err, rs,
|
||||
maxPadLen);
|
||||
|
||||
// Adding more padding should fail.
|
||||
size_t badPadLen = maxPadLen + 1;
|
||||
payloadLen = ece_aes128gcm_payload_max_length(rs, badPadLen, plaintextLen);
|
||||
payload = realloc(payload, payloadLen);
|
||||
|
||||
err = ece_webpush_aes128gcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, badPadLen, plaintext, plaintextLen,
|
||||
payload, &payloadLen);
|
||||
ece_assert(err == ECE_ERROR_ENCRYPT_PADDING,
|
||||
"Want error encrypting with rs = %d, padLen = %zu", rs,
|
||||
badPadLen);
|
||||
|
||||
free(plaintext);
|
||||
free(payload);
|
||||
}
|
||||
}
|
||||
219
mobile/ios/ThirdParty/ecec/test/encrypt/aesgcm.c
vendored
Normal file
219
mobile/ios/ThirdParty/ecec/test/encrypt/aesgcm.c
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
typedef struct webpush_aesgcm_encrypt_ok_test_s {
|
||||
const char* desc;
|
||||
const char* ciphertext;
|
||||
const char* senderPrivKey;
|
||||
const char* recvPubKey;
|
||||
const char* authSecret;
|
||||
const char* salt;
|
||||
const char* plaintext;
|
||||
size_t plaintextLen;
|
||||
size_t padLen;
|
||||
size_t maxCiphertextLen;
|
||||
size_t ciphertextLen;
|
||||
uint32_t rs;
|
||||
} webpush_aesgcm_encrypt_ok_test_t;
|
||||
|
||||
static webpush_aesgcm_encrypt_ok_test_t webpush_aesgcm_encrypt_ok_tests[] = {
|
||||
{
|
||||
.desc = "Example from draft-ietf-webpush-encryption-04",
|
||||
.ciphertext = "\xea\x7a\x80\x41\x43\x04\xf2\x13\x6a\xc3\x92\x77\x92\x5f"
|
||||
"\x1c\xa5\x55\x49\xca\x55\xca\x62\xa6\x4e\x7a\xc7\x99\x1b"
|
||||
"\xc5\x2e\x78\xaa\x40",
|
||||
.senderPrivKey = "\x9c\x24\x9c\x7a\x4f\x90\xa4\x48\xe6\x38\xe9\x53\xfa"
|
||||
"\xb4\x37\xf2\x76\x73\xbd\xd3\xe5\xa9\xad\x34\x67\x2d"
|
||||
"\x22\xea\x6d\x8e\x26\xf6",
|
||||
.recvPubKey = "\x04\x21\x24\x06\x3c\xcb\xf1\x9d\xc2\xfa\x88\xb6\x43\xba"
|
||||
"\x04\xe6\xdd\x8d\xa7\xea\x7b\xa2\xc8\xc6\x2e\x0f\x77\xa9"
|
||||
"\x43\xf4\xc2\xfa\x91\x4f\x6d\x44\x11\x6c\x9f\xd1\xc4\x03"
|
||||
"\x41\xc6\xa4\x40\xca\xb3\xe2\x14\x0a\x60\xe4\x37\x8a\x5d"
|
||||
"\xa7\x35\x97\x2d\xe0\x78\x00\x51\x05",
|
||||
.authSecret =
|
||||
"\x47\x6f\x6f\x20\x67\x6f\x6f\x20\x67\x27\x20\x6a\x6f\x6f\x62\x21",
|
||||
.salt = "\x96\x78\x1a\xad\xbc\x8a\x7c\xca\x22\xf5\x9e\xf9\xc5\x85\xe6\x92",
|
||||
.plaintext = "I am the walrus",
|
||||
.plaintextLen = 15,
|
||||
.padLen = 0,
|
||||
.maxCiphertextLen = 33,
|
||||
.ciphertextLen = 33,
|
||||
.rs = 4096,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 4, trailer",
|
||||
.ciphertext =
|
||||
"\xe8\x7d\x81\x05\x8d\x25\xd1\xdb\xfc\xf3\x1c\x5d\x52\xd4\x39\x51\xb4"
|
||||
"\x7c\x63\x07\x4d\x6d\xb3\xf0\xaf\x89\xe4\xb3\xae\x64\x3d\x00\xb5\xce"
|
||||
"\xda\x84\x4c\xf7\x9b\xce\xb7\xf9\x4e\xdc\x95\xa9\xf8\x78\x4d\xcf\xf0"
|
||||
"\xb7\xeb\xdc\x27\x7e\x9a\x17\xdb\xd4\x62\x78\xaa\x8d\x7e\xe9\x65\x24"
|
||||
"\x81\x22\xe8\x40\x81\x37\x4c\xab\xd0\x3d\xb8\x3b\x98\x39\xdb\x34\x28"
|
||||
"\x88\xf9\x68\x58\x35\x26\x58\x34\xbb\x11\xe6\xdb\x1e\xb0\x95\xcd\x17"
|
||||
"\x5e\x12\xc5\xf8\x3f\x1f\xb6\xed\x3a\x4a\x00\x2b\x05\x7c\x10\xeb\x97"
|
||||
"\x94\x16\x6a\xc6\x1d\xc0\x00\x74\xf8\xd0\x95\xbb\xb6\x7f\xa8\x18\x35"
|
||||
"\xac\x1b\xa7\x16\xc8\xde\x94\xda\x49\xfb\xdb\x0a\x74\xf6\xac\x68\x89"
|
||||
"\x7b\xb3\x8d\x3f\xba\x88\x7a\x8b\xc9\x44\xa4\xc9\xdd\x83\x61\x20\x8b"
|
||||
"\xc3\x82\x57\x65\xe6\xb8\xc7\x69\xd5\x4d\xa7\xa4\x6f\x26\xf0\x50\xd0"
|
||||
"\xad\xc9\x5a\x16\xde\xa1\xa7\x50\xb0\xf7\xcf\x4d\x3b\xf4\xf5\x1f\xad"
|
||||
"\x32\xaf\x7a\x0a\x4a\x6a\x4c\x33\x2b\xa8\x49\xe5\xcf\x78\xa3\xf7\x8b"
|
||||
"\x38\x98\xdc\x3a\x8c\x95\x3c\xde\xb1\xc9\x79\x9b\x0e\xb4\x6e\xad\x37"
|
||||
"\xe0\xfa\xf4\xba\xc2\xbe\xd6\x56\x58\xb4\x86\x1c\xf9\x42\xfd\x77\xf2"
|
||||
"\x36\x33\xc5\xe5\xa1\x2e\xe1\x3c\xba\xd7\x64\xa2\x1a\x92\x5c\x79\x47"
|
||||
"\xf1\xd3\x18\x34\x9a\x9d\x96\x10\x71\xb8\x74\xc6\xb0\xc1\x06\x66\x62"
|
||||
"\x34\x97\x27\x84\x36\xa9\x3c\xd1\xa9\xa4\xe0\x32\xa9\x64\x9f\x29\x7a"
|
||||
"\x4d\x8b\xa4\x59\x44\xf6\x3b\xdb\x0b\xce\x45\xce\x0d\x75\xd3\x7c\x24"
|
||||
"\xa0\x69\x0f\xa0\x96\x0d\x86\x6e\x99\x2d\x61\x63\x15\xba\x01\x3b\x80"
|
||||
"\xc6\xe3\xac\xfd\x97\x26\x07\x42\x4b\xec\x10\x88\x8d\xd5\x0a\x15\x13"
|
||||
"\x42\xf1\x5d\x48\x18\x36\xfd\xf3\x65\x8c\x86\xe8\x58\xac\xc0\xf2\x5f"
|
||||
"\x3f\xe0\xce\xe5\xc2\x29\x5f\x04\x4e\x1e\x82\x89\xbc\x52\x50\x9d\x4f"
|
||||
"\x5c\x4e\xb5\x56\x5d\x4e\x62\x0a\xe5\x9c\xdb\x26\xa5\x02\x09\x63\xfc"
|
||||
"\x6e\x43\xca\x0e\x7c\x45\x29\xb3\x22\x38\xfd\x3a\xf6\x0e\xda\xf6\xc5"
|
||||
"\x6c\x9f\xb4\x08\x95\xb1\xe6\x01\x4a\xd7\x3b\x69\xb3\xcb\x55\x2c\xe8"
|
||||
"\xc0\xa8\xbb\x14\xff\xe9\x66\xc7\x4d\x40\xfc\x28\xd2\x05\xab\xee\x5f"
|
||||
"\x73\xed\x9a\x0d\xb9\x64\xe0\x69\xe4\x86\xb3\x02\xef\x58\xcc\xf6\xa3"
|
||||
"\x4b\x4e",
|
||||
.senderPrivKey = "\xf1\xfe\xd7\x17\xb0\xd8\x35\xd2\x9b\x9e\x4e\x4f\x4c"
|
||||
"\xf8\x7d\x0c\xb9\x85\xe2\xbc\x44\xff\xd6\xd4\x37\xa4"
|
||||
"\xe7\x4a\x18\x04\x55\x87",
|
||||
.recvPubKey = "\x04\x09\x22\xf1\x7c\xed\x7d\x09\xd4\x55\x10\x2d\xd9\x0c"
|
||||
"\x31\x46\xce\x33\x2f\x45\xd2\x34\x96\x46\xfe\x64\xca\xbb"
|
||||
"\x7f\x41\x23\x03\xbe\x5c\x23\x53\x9a\xff\x5c\x30\x72\xdd"
|
||||
"\x85\xa9\x0b\x76\x92\xe1\x96\x22\x09\x39\xee\xb7\x3e\x0e"
|
||||
"\xf2\x47\x59\x32\xb1\xcd\xa9\x16\xc7",
|
||||
.authSecret =
|
||||
"\xd3\xf8\x22\xf4\x8c\x74\x74\x19\x5d\xa6\x4d\x78\x5f\x40\x8f\x26",
|
||||
.salt = "\x77\x10\x67\x4b\x1e\xcd\x0b\xf7\xa7\xd3\x25\x88\xea\xe9\x53\x9c",
|
||||
.plaintext = "I am the very model of a modern Major-General.",
|
||||
.plaintextLen = 46,
|
||||
.padLen = 0,
|
||||
.maxCiphertextLen = 478,
|
||||
.ciphertextLen = 478,
|
||||
.rs = 4,
|
||||
},
|
||||
{
|
||||
.desc = "rs = 6, pad = 4",
|
||||
.ciphertext = "\x54\x6d\x13\x0b\x1e\xf0\xc2\x3e\xff\x49\x87\xe5\xc6\x57\xf1"
|
||||
"\x94\xb1\xb8\xad\x5a\xda\xb7\x02\x32\x3c\xf9\xc0\x7b\xd8\x28"
|
||||
"\x20\x9e\x5d\xe7\x5e\x8b\xf6\x6a\xa5\xf8\xf6\x3b\x0a\x66\xd3"
|
||||
"\x99\xeb\x8b\x98\x70\x6c\xfc\xa5\xa5\x3f\x8f\x50\x8c\x26\x56"
|
||||
"\x5a\x34\xe4",
|
||||
.senderPrivKey = "\xe3\x31\x8e\xc3\x99\xa9\xc4\x71\x7a\xa9\x4b\xa4\xed\xb3"
|
||||
"\xaa\x1d\x90\x96\x5c\xe7\x6a\x57\x6b\x52\xa0\x7c\x27\x44"
|
||||
"\x0c\x6d\x9b\xd1",
|
||||
.recvPubKey = "\x04\xaa\xec\x79\x05\x22\xad\x2b\x70\x56\x05\x58\x99\xda\xa6"
|
||||
"\x47\x7d\x55\xab\x3f\x16\x5d\x76\x00\x56\x19\xf3\xdf\xa9\x72"
|
||||
"\x19\xf5\x59\x02\x5d\x09\xc0\x80\x83\x70\xc6\x06\x8a\x66\x51"
|
||||
"\x81\xd4\x3d\x74\xac\x3d\x0a\xca\x28\x67\x5e\x81\x55\x9a\x20"
|
||||
"\x4a\x6d\x44\xb5\x91",
|
||||
.authSecret =
|
||||
"\x54\x9d\xe2\xfd\x40\x52\xef\x4e\x05\x28\x45\x13\x3e\x37\x61\x3d",
|
||||
.salt = "\x3a\x4b\xd3\x72\x75\x09\x5d\x71\xc9\x81\xe0\x9c\xde\x0d\xa6\x2a",
|
||||
.plaintext = "Hello",
|
||||
.plaintextLen = 5,
|
||||
.padLen = 4,
|
||||
.maxCiphertextLen = 63,
|
||||
.ciphertextLen = 63,
|
||||
.rs = 6,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_encrypt_ok(void) {
|
||||
size_t tests = sizeof(webpush_aesgcm_encrypt_ok_tests) /
|
||||
sizeof(webpush_aesgcm_encrypt_ok_test_t);
|
||||
for (size_t i = 0; i < tests; i++) {
|
||||
webpush_aesgcm_encrypt_ok_test_t t = webpush_aesgcm_encrypt_ok_tests[i];
|
||||
|
||||
const void* senderPrivKey = t.senderPrivKey;
|
||||
const void* authSecret = t.authSecret;
|
||||
const void* salt = t.salt;
|
||||
const void* recvPubKey = t.recvPubKey;
|
||||
const void* plaintext = t.plaintext;
|
||||
|
||||
size_t ciphertextLen =
|
||||
ece_aesgcm_ciphertext_max_length(t.rs, t.padLen, t.plaintextLen);
|
||||
ece_assert(ciphertextLen == t.maxCiphertextLen,
|
||||
"Got ciphertext max length %zu for `%s`; want %zu",
|
||||
ciphertextLen, t.desc, t.maxCiphertextLen);
|
||||
|
||||
uint8_t* ciphertext = calloc(ciphertextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aesgcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, t.rs, t.padLen, plaintext, t.plaintextLen,
|
||||
ciphertext, &ciphertextLen);
|
||||
ece_assert(!err, "Got %d encrypting ciphertext for `%s`", err, t.desc);
|
||||
|
||||
ece_assert(ciphertextLen == t.ciphertextLen,
|
||||
"Got actual ciphertext length %zu for `%s`; want %zu",
|
||||
ciphertextLen, t.desc, t.ciphertextLen);
|
||||
ece_assert(!memcmp(ciphertext, t.ciphertext, ciphertextLen),
|
||||
"Wrong ciphertext for `%s`", t.desc);
|
||||
|
||||
free(ciphertext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_encrypt_pad(void) {
|
||||
static const uint32_t maxRs = 128;
|
||||
|
||||
const void* senderPrivKey = "\xac\xae\xc1\xc3\x7c\x30\x7c\xb9\x02\x8f\xbb\xd9"
|
||||
"\xc7\xf3\xc6\x89\x26\x60\x08\x95\x9a\x5e\xd4\x03"
|
||||
"\x42\x21\xb2\xda\x72\x01\x82\x8f";
|
||||
const void* authSecret =
|
||||
"\x44\x29\x81\x2d\x53\x5f\xbf\xdb\xea\xc8\x6d\xb7\x14\x5c\x6a\xf2";
|
||||
const void* salt =
|
||||
"\x45\x2b\xfb\xea\x8c\xc7\xa7\x57\x14\xd2\x03\xcf\xf1\x02\xe8\x76";
|
||||
const void* recvPubKey =
|
||||
"\x04\x2d\x78\x8d\x3e\x8e\x82\xf2\xd7\xea\xef\xbd\xe3\xa1\xbe\xde\xa2\x1f"
|
||||
"\x3b\xc9\x60\x33\x15\x73\x22\xa0\x9e\x14\x46\x55\xa3\xdf\x78\xfd\xca\xc8"
|
||||
"\x10\xe3\x02\x2a\xb5\x6a\x0e\xa9\xb8\xec\x06\x73\x8a\xce\x41\x1f\x49\x54"
|
||||
"\x7b\xc0\x0d\x1a\x1c\xde\x97\xce\x7b\xdd\x26";
|
||||
|
||||
for (uint32_t rs = ECE_AESGCM_MIN_RS + 1; rs <= maxRs; rs++) {
|
||||
// Generate a random plaintext.
|
||||
size_t plaintextLen = (size_t)(rand() % (int) (maxRs - 1) + 1);
|
||||
uint8_t* plaintext = calloc(plaintextLen, sizeof(uint8_t));
|
||||
int ok = RAND_bytes(plaintext, (int) plaintextLen);
|
||||
ece_assert(ok == 1, "Got %d generating plaintext for rs = %d", ok, rs);
|
||||
|
||||
size_t maxPadLen = (rs - ECE_AESGCM_MIN_RS) * (plaintextLen + 1);
|
||||
|
||||
// Encrypting with the maximum padding length should succeed.
|
||||
size_t ciphertextLen =
|
||||
ece_aesgcm_ciphertext_max_length(rs, maxPadLen, plaintextLen);
|
||||
uint8_t* ciphertext = calloc(ciphertextLen, sizeof(uint8_t));
|
||||
|
||||
int err = ece_webpush_aesgcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, maxPadLen, plaintext, plaintextLen,
|
||||
ciphertext, &ciphertextLen);
|
||||
ece_assert(!err, "Got %d encrypting with rs = %d, padLen = %zu", err, rs,
|
||||
maxPadLen);
|
||||
|
||||
// Adding more padding should fail.
|
||||
size_t badPadLen = maxPadLen + 1;
|
||||
ciphertextLen =
|
||||
ece_aesgcm_ciphertext_max_length(rs, badPadLen, plaintextLen);
|
||||
ciphertext = realloc(ciphertext, ciphertextLen);
|
||||
|
||||
err = ece_webpush_aesgcm_encrypt_with_keys(
|
||||
senderPrivKey, ECE_WEBPUSH_PRIVATE_KEY_LENGTH, authSecret,
|
||||
ECE_WEBPUSH_AUTH_SECRET_LENGTH, salt, ECE_SALT_LENGTH, recvPubKey,
|
||||
ECE_WEBPUSH_PUBLIC_KEY_LENGTH, rs, badPadLen, plaintext, plaintextLen,
|
||||
ciphertext, &ciphertextLen);
|
||||
ece_assert(err == ECE_ERROR_ENCRYPT_PADDING,
|
||||
"Want error encrypting with rs = %d, padLen = %zu", rs,
|
||||
badPadLen);
|
||||
|
||||
free(plaintext);
|
||||
free(ciphertext);
|
||||
}
|
||||
}
|
||||
391
mobile/ios/ThirdParty/ecec/test/params.c
vendored
Normal file
391
mobile/ios/ThirdParty/ecec/test/params.c
vendored
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct webpush_aesgcm_from_params_test_s {
|
||||
const char* cryptoKey;
|
||||
const char* encryption;
|
||||
const char* salt;
|
||||
const char* rawSenderPubKey;
|
||||
size_t cryptoKeyLen;
|
||||
size_t encryptionLen;
|
||||
size_t saltLen;
|
||||
size_t rawSenderPubKeyLen;
|
||||
uint32_t rs;
|
||||
} webpush_aesgcm_from_params_test_t;
|
||||
|
||||
static webpush_aesgcm_from_params_test_t webpush_aesgcm_from_params_tests[] = {
|
||||
{
|
||||
.cryptoKey = "dh=Iy1Je2Kv11A",
|
||||
.cryptoKeyLen = 14,
|
||||
.encryption = "rs=7;salt=upk1yFkp1xI",
|
||||
.encryptionLen = 21,
|
||||
.salt = "\xba\x99\x35\xc8\x59\x29\xd7\x12",
|
||||
.saltLen = 8,
|
||||
.rawSenderPubKey = "\x23\x2d\x49\x7b\x62\xaf\xd7\x50",
|
||||
.rawSenderPubKeyLen = 8,
|
||||
.rs = 7,
|
||||
},
|
||||
{
|
||||
.cryptoKey = "dh=mwyOULZ4upjVbCpQLRLOeg",
|
||||
.cryptoKeyLen = 25,
|
||||
.encryption = "rs=4096;salt=qzqku7FRdW9Vs97w8O8DoA",
|
||||
.encryptionLen = 35,
|
||||
.salt = "\xab\x3a\xa4\xbb\xb1\x51\x75\x6f\x55\xb3\xde\xf0\xf0\xef\x03\xa0",
|
||||
.saltLen = 16,
|
||||
.rawSenderPubKey =
|
||||
"\x9b\x0c\x8e\x50\xb6\x78\xba\x98\xd5\x6c\x2a\x50\x2d\x12\xce\x7a",
|
||||
.rawSenderPubKeyLen = 16,
|
||||
.rs = 4096,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct webpush_aesgcm_extract_params_ok_test_s {
|
||||
const char* desc;
|
||||
const char* cryptoKey;
|
||||
const char* encryption;
|
||||
const char* salt;
|
||||
const char* rawSenderPubKey;
|
||||
uint32_t rs;
|
||||
} webpush_aesgcm_extract_params_ok_test_t;
|
||||
|
||||
static webpush_aesgcm_extract_params_ok_test_t
|
||||
webpush_aesgcm_extract_params_ok_tests[] = {
|
||||
{
|
||||
.desc = "Multiple keys in Crypto-Key header",
|
||||
.cryptoKey = "keyid=p256dh;dh=Iy1Je2Kv11A,p256ecdsa=o2M8QfiEKuI",
|
||||
.encryption = "keyid=p256dh;salt=upk1yFkp1xI",
|
||||
.salt = "\xba\x99\x35\xc8\x59\x29\xd7\x12",
|
||||
.rawSenderPubKey = "\x23\x2d\x49\x7b\x62\xaf\xd7\x50",
|
||||
.rs = 4096,
|
||||
},
|
||||
{
|
||||
.desc = "Multiple keys in both headers",
|
||||
.cryptoKey = "keyid=a;dh=bX0VbuZy8HQ,dh=Iy1Je2Kv11A;keyid=p256dh",
|
||||
.encryption =
|
||||
"salt=upk1yFkp1xI;rs=48;keyid=p256dh,salt=U0DM1JsdIbU;keyid=a",
|
||||
.salt = "\xba\x99\x35\xc8\x59\x29\xd7\x12",
|
||||
.rawSenderPubKey = "\x23\x2d\x49\x7b\x62\xaf\xd7\x50",
|
||||
.rs = 48,
|
||||
},
|
||||
{
|
||||
.desc = "Quoted key ID pair value",
|
||||
.cryptoKey = "dh=\"byfHbUffc-k\"",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.salt = "\x0b\x5d\x40\xbc\x0b\x29\xe8\x67",
|
||||
.rawSenderPubKey = "\x6f\x27\xc7\x6d\x47\xdf\x73\xe9",
|
||||
.rs = 4096,
|
||||
},
|
||||
{
|
||||
.desc = "Quoted salt pair value and rs = 24",
|
||||
.cryptoKey = "dh=ybuT4VDz-Bg",
|
||||
.encryption = "rs=24; salt=\"H7U7wcIoIKs\"",
|
||||
.salt = "\x1f\xb5\x3b\xc1\xc2\x28\x20\xab",
|
||||
.rawSenderPubKey = "\xc9\xbb\x93\xe1\x50\xf3\xf8\x18",
|
||||
.rs = 24,
|
||||
},
|
||||
{
|
||||
.desc = "Multiple keys, extra whitespace, strange key ID",
|
||||
.cryptoKey = " dh= \"ujIToeKunCY\" ,keyid = hello ; dh = I7p5M0yyP8A ",
|
||||
.encryption = "salt=ie_oYLhw7SI; keyid=\"hello\"; rs =6 , salt = "
|
||||
"6NAh50bfJZc ;keyid=ujIToeKunCY ",
|
||||
.salt = "\x89\xef\xe8\x60\xb8\x70\xed\x22",
|
||||
.rawSenderPubKey = "\x23\xba\x79\x33\x4c\xb2\x3f\xc0",
|
||||
.rs = 6,
|
||||
},
|
||||
{
|
||||
// Invalid, but we don't check the entire `Crypto-Key` param once we see a
|
||||
// match.
|
||||
.desc = "Duplicate key ID in Crypto-Key",
|
||||
.cryptoKey = "keyid=a;keyid=b;dh=pbmv1QkcEDY",
|
||||
.encryption = "salt=Esao8aTBfIk;keyid=b",
|
||||
.salt = "\x12\xc6\xa8\xf1\xa4\xc1\x7c\x89",
|
||||
.rawSenderPubKey = "\xa5\xb9\xaf\xd5\x09\x1c\x10\x36",
|
||||
.rs = 4096,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct webpush_aesgcm_extract_params_err_test_s {
|
||||
const char* desc;
|
||||
const char* cryptoKey;
|
||||
const char* encryption;
|
||||
int err;
|
||||
} webpush_aesgcm_extract_params_err_test_t;
|
||||
|
||||
static webpush_aesgcm_extract_params_err_test_t
|
||||
webpush_aesgcm_extract_params_err_tests[] = {
|
||||
{
|
||||
.desc = "Invalid record size",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt=Esao8aTBfIk;rs=bad",
|
||||
.err = ECE_ERROR_INVALID_RS,
|
||||
},
|
||||
{
|
||||
.desc = "Blank Crypto-Key header",
|
||||
.cryptoKey = " \t ",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Empty Encryption header",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Crypto-Key missing pair value",
|
||||
.cryptoKey = "dh=",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Encryption missing pair value with trailing whitespace",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt= ",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Crypto-Key pair without value",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY; keyid, dh=rqowftPcCVo",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Encryption pair without value",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "rs; salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Crypto-Key missing pair name",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY; =rqowftPcCVo",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Encryption missing pair name",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Whitespace in quoted Crypto-Key pair value",
|
||||
.cryptoKey = "dh=byfHbUffc-k; param=\" \"",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Empty quoted value in Encryption header",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "salt=\"\"; rs=6",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid character in Crypto-Key pair value",
|
||||
.cryptoKey = "dh==byfHbUffc-k",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid character in Encryption pair name",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "sa!t=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Leading , in Crypto-Key header",
|
||||
.cryptoKey = ",dh=byfHbUffc-k",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Trailing ; in Crypto-Key header",
|
||||
.cryptoKey = "dh=byfHbUffc-k;",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Leading ; in Encryption header",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "; salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Trailing , in Encryption header",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "salt=C11AvAsp6Gc,",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Unterminated quoted value in Encryption header",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "rs=6; salt=\"C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid quoted name in Crypto-Key header",
|
||||
.cryptoKey = "\"dh\"=\"byfHbUffc-k\"",
|
||||
.encryption = "salt=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid quoted name in Encryption header",
|
||||
.cryptoKey = "dh=byfHbUffc-k",
|
||||
.encryption = "\"salt\"=C11AvAsp6Gc",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Mismatched key IDs",
|
||||
.cryptoKey = "keyid=p256dh;dh=pbmv1QkcEDY",
|
||||
.encryption = "keyid=different;salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_DH,
|
||||
},
|
||||
{
|
||||
.desc = "Multiple mismatched key IDs",
|
||||
.cryptoKey = "keyid=a;dh=bX0VbuZy8HQ,dh=Iy1Je2Kv11A;keyid=b",
|
||||
.encryption = "salt=upk1yFkp1xI;rs=48;keyid=c,salt=U0DM1JsdIbU;keyid=d",
|
||||
.err = ECE_ERROR_INVALID_DH,
|
||||
},
|
||||
{
|
||||
.desc = "Key ID with matching pair value, wrong pair name",
|
||||
.cryptoKey = "p256dh=p256dh;dh=pbmv1QkcEDY",
|
||||
.encryption = "keyid=p256dh;salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_DH,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid Base64url-encoded salt",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt=99999",
|
||||
.err = ECE_ERROR_INVALID_SALT,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid Base64url-encoded dh pair value",
|
||||
.cryptoKey = "dh=zzzzz",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_DH,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid character at end of salt pair name",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt !=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid character at end of salt",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt=Esao8aTBfIk!",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Invalid character after quoted dh pair value",
|
||||
.cryptoKey = "dh=\"pbmv1QkcEDY\"!",
|
||||
.encryption = "salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_CRYPTO_KEY_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Duplicate key ID in Encryption header",
|
||||
.cryptoKey = "keyid=b;dh=pbmv1QkcEDY",
|
||||
.encryption = "keyid=a;salt=Esao8aTBfIk;keyid=b",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Duplicate record size in Encryption header",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "rs=5;salt=Esao8aTBfIk;rs=10",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Duplicate salt in Encryption header",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "salt=Esao8aTBfIk; salt=Esao8aTBfIk",
|
||||
.err = ECE_ERROR_INVALID_ENCRYPTION_HEADER,
|
||||
},
|
||||
{
|
||||
.desc = "Missing salt in Encryption header",
|
||||
.cryptoKey = "dh=pbmv1QkcEDY",
|
||||
.encryption = "rs=5",
|
||||
.err = ECE_ERROR_INVALID_SALT,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_from_params(void) {
|
||||
size_t length = sizeof(webpush_aesgcm_from_params_tests) /
|
||||
sizeof(webpush_aesgcm_from_params_test_t);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
webpush_aesgcm_from_params_test_t t = webpush_aesgcm_from_params_tests[i];
|
||||
|
||||
size_t cryptoKeyLen = 0;
|
||||
size_t encryptionLen = 0;
|
||||
int err = ece_webpush_aesgcm_headers_from_params(
|
||||
t.salt, t.saltLen, t.rawSenderPubKey, t.rawSenderPubKeyLen, t.rs, NULL,
|
||||
&cryptoKeyLen, NULL, &encryptionLen);
|
||||
ece_assert(!err, "Got %d determining lengths for (%s, %s)", err,
|
||||
t.cryptoKey, t.encryption);
|
||||
ece_assert(cryptoKeyLen == t.cryptoKeyLen,
|
||||
"Got Crypto-Key length %zu for (%s, %s); want %zu", cryptoKeyLen,
|
||||
t.cryptoKey, t.encryption, t.cryptoKeyLen);
|
||||
ece_assert(encryptionLen == t.encryptionLen,
|
||||
"Got Encryption length %zu for (%s, %s); want %zu",
|
||||
encryptionLen, t.cryptoKey, t.encryption, t.encryptionLen);
|
||||
|
||||
char* cryptoKey = malloc(cryptoKeyLen + 1);
|
||||
char* encryption = malloc(encryptionLen + 1);
|
||||
|
||||
err = ece_webpush_aesgcm_headers_from_params(
|
||||
t.salt, t.saltLen, t.rawSenderPubKey, t.rawSenderPubKeyLen, t.rs,
|
||||
cryptoKey, &cryptoKeyLen, encryption, &encryptionLen);
|
||||
ece_assert(!err, "Got %d formatting headers for (%s, %s)", err, t.cryptoKey,
|
||||
t.encryption);
|
||||
ece_assert(!memcmp(cryptoKey, t.cryptoKey, t.cryptoKeyLen),
|
||||
"Wrong Crypto-Key for (%s, %s)", t.cryptoKey, t.encryption);
|
||||
ece_assert(!memcmp(encryption, t.encryption, t.encryptionLen),
|
||||
"Wrong Encryption for (%s, %s)", t.cryptoKey, t.encryption);
|
||||
|
||||
free(cryptoKey);
|
||||
free(encryption);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_extract_params_ok(void) {
|
||||
size_t length = sizeof(webpush_aesgcm_extract_params_ok_tests) /
|
||||
sizeof(webpush_aesgcm_extract_params_ok_test_t);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
webpush_aesgcm_extract_params_ok_test_t t =
|
||||
webpush_aesgcm_extract_params_ok_tests[i];
|
||||
|
||||
uint8_t salt[8];
|
||||
uint32_t rs;
|
||||
uint8_t rawSenderPubKey[8];
|
||||
int err = ece_webpush_aesgcm_headers_extract_params(
|
||||
t.cryptoKey, t.encryption, salt, 8, rawSenderPubKey, 8, &rs);
|
||||
|
||||
ece_assert(!err, "Got %d extracting params for `%s`", err, t.desc);
|
||||
ece_assert(!memcmp(salt, t.salt, 8), "Wrong salt for `%s`", t.desc);
|
||||
ece_assert(rs == t.rs, "Got rs = %" PRIu32 " for `%s`; want %" PRIu32, rs,
|
||||
t.desc, t.rs);
|
||||
ece_assert(!memcmp(rawSenderPubKey, t.rawSenderPubKey, 8),
|
||||
"Wrong public key for `%s`", t.desc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_extract_params_err(void) {
|
||||
size_t length = sizeof(webpush_aesgcm_extract_params_err_tests) /
|
||||
sizeof(webpush_aesgcm_extract_params_err_test_t);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
webpush_aesgcm_extract_params_err_test_t t =
|
||||
webpush_aesgcm_extract_params_err_tests[i];
|
||||
|
||||
uint8_t salt[8];
|
||||
uint32_t rs;
|
||||
uint8_t rawSenderPubKey[8];
|
||||
int err = ece_webpush_aesgcm_headers_extract_params(
|
||||
t.cryptoKey, t.encryption, salt, 8, rawSenderPubKey, 8, &rs);
|
||||
|
||||
ece_assert(err == t.err, "Got %d extracting params for `%s`; want %d", err,
|
||||
t.desc, t.err);
|
||||
}
|
||||
}
|
||||
66
mobile/ios/ThirdParty/ecec/test/test.c
vendored
Normal file
66
mobile/ios/ThirdParty/ecec/test/test.c
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include "test.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main() {
|
||||
test_webpush_aesgcm_headers_from_params();
|
||||
test_webpush_aesgcm_headers_extract_params_ok();
|
||||
test_webpush_aesgcm_headers_extract_params_err();
|
||||
|
||||
test_webpush_aesgcm_encrypt_ok();
|
||||
test_webpush_aesgcm_encrypt_pad();
|
||||
test_webpush_aesgcm_decrypt_ok();
|
||||
test_webpush_aesgcm_decrypt_err();
|
||||
|
||||
test_webpush_aes128gcm_encrypt_ok();
|
||||
test_webpush_aes128gcm_encrypt_pad();
|
||||
test_webpush_aes128gcm_decrypt_ok();
|
||||
test_webpush_aes128gcm_decrypt_err();
|
||||
test_aes128gcm_decrypt_ok();
|
||||
test_aes128gcm_decrypt_err();
|
||||
|
||||
test_webpush_aes128gcm_e2e();
|
||||
test_webpush_aesgcm_e2e();
|
||||
|
||||
test_base64url_encode();
|
||||
test_base64url_decode();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ece_log(const char* funcName, int line, const char* expr, const char* format,
|
||||
...) {
|
||||
char* message = NULL;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
// Determine the size of the formatted message, then allocate and write to a
|
||||
// buffer large enough to hold the message. `vsnprintf` mutates its argument
|
||||
// list, so we make a copy for calculating the size.
|
||||
va_list sizeArgs;
|
||||
va_copy(sizeArgs, args);
|
||||
int size = vsnprintf(NULL, 0, format, sizeArgs);
|
||||
va_end(sizeArgs);
|
||||
if (size < 0) {
|
||||
goto error;
|
||||
}
|
||||
message = malloc((size_t) size + 1);
|
||||
if (!message || vsprintf(message, format, args) != size) {
|
||||
goto error;
|
||||
}
|
||||
message[size] = '\0';
|
||||
fprintf(stderr, "[%s:%d] (%s): %s\n", funcName, line, expr, message);
|
||||
goto end;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "[%s:%d]: %s\n", funcName, line, expr);
|
||||
|
||||
end:
|
||||
va_end(args);
|
||||
free(message);
|
||||
}
|
||||
70
mobile/ios/ThirdParty/ecec/test/test.h
vendored
Normal file
70
mobile/ios/ThirdParty/ecec/test/test.h
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ece.h>
|
||||
|
||||
// This macro is similar to the standard `assert`, but accepts a format string
|
||||
// with an informative failure message.
|
||||
#define ece_assert(cond, format, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
ece_log(__func__, __LINE__, #cond, format, __VA_ARGS__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Logs an assertion failure to standard error.
|
||||
void
|
||||
ece_log(const char* funcName, int line, const char* expr, const char* format,
|
||||
...);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_from_params(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_extract_params_ok(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_headers_extract_params_err(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_encrypt_ok(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_encrypt_pad(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_decrypt_ok(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_decrypt_err(void);
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_encrypt_ok(void);
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_encrypt_pad(void);
|
||||
|
||||
void
|
||||
test_aes128gcm_decrypt_ok(void);
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_decrypt_ok(void);
|
||||
|
||||
void
|
||||
test_aes128gcm_decrypt_err(void);
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_decrypt_err(void);
|
||||
|
||||
void
|
||||
test_webpush_aes128gcm_e2e(void);
|
||||
|
||||
void
|
||||
test_webpush_aesgcm_e2e(void);
|
||||
|
||||
void
|
||||
test_base64url_encode(void);
|
||||
|
||||
void
|
||||
test_base64url_decode(void);
|
||||
Loading…
Add table
Add a link
Reference in a new issue