diff options
author | Mattias Nissler | 2016-03-31 09:31:42 -0500 |
---|---|---|
committer | Elliott Hughes | 2016-04-12 17:08:01 -0500 |
commit | b62146dcabedcacf99349793c1947797a173f0e6 (patch) | |
tree | be19fb1ff38584708cf4ed4058a1718b18fb5f7b /libcrypto_utils | |
parent | 979ce0e33827a9c5bb2b76b2e2557544f8eb0cce (diff) | |
download | platform-system-core-b62146dcabedcacf99349793c1947797a173f0e6.tar.gz platform-system-core-b62146dcabedcacf99349793c1947797a173f0e6.tar.xz platform-system-core-b62146dcabedcacf99349793c1947797a173f0e6.zip |
Add libcrypto_utils.
This provides a tiny library implementing encode/decode functionality
for Android's custom RSA public key binary format. Keys are encoded
from and decoded to BoringSSL RSA key objects.
Change-Id: I55e5522d557e0e9f35927a87b6581f020ee34e7a
Diffstat (limited to 'libcrypto_utils')
-rw-r--r-- | libcrypto_utils/Android.mk | 56 | ||||
-rw-r--r-- | libcrypto_utils/android_pubkey.c | 167 | ||||
-rw-r--r-- | libcrypto_utils/include/crypto_utils/android_pubkey.h | 61 | ||||
-rw-r--r-- | libcrypto_utils/tests/Android.mk | 24 | ||||
-rw-r--r-- | libcrypto_utils/tests/android_pubkey_test.cpp | 129 |
5 files changed, 437 insertions, 0 deletions
diff --git a/libcrypto_utils/Android.mk b/libcrypto_utils/Android.mk new file mode 100644 index 000000000..5e9763fe5 --- /dev/null +++ b/libcrypto_utils/Android.mk | |||
@@ -0,0 +1,56 @@ | |||
1 | # | ||
2 | # Copyright (C) 2016 The Android Open Source Project | ||
3 | # | ||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | # you may not use this file except in compliance with the License. | ||
6 | # You may obtain a copy of the License at | ||
7 | # | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | # | ||
10 | # Unless required by applicable law or agreed to in writing, software | ||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | # See the License for the specific language governing permissions and | ||
14 | # limitations under the License. | ||
15 | # | ||
16 | |||
17 | LOCAL_PATH := $(call my-dir) | ||
18 | |||
19 | include $(CLEAR_VARS) | ||
20 | LOCAL_MODULE := libcrypto_utils | ||
21 | LOCAL_SRC_FILES := android_pubkey.c | ||
22 | LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99 | ||
23 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include | ||
24 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | ||
25 | LOCAL_SHARED_LIBRARIES := libcrypto | ||
26 | include $(BUILD_SHARED_LIBRARY) | ||
27 | |||
28 | include $(CLEAR_VARS) | ||
29 | LOCAL_MODULE := libcrypto_utils | ||
30 | LOCAL_SRC_FILES := android_pubkey.c | ||
31 | LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99 | ||
32 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include | ||
33 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | ||
34 | LOCAL_SHARED_LIBRARIES := libcrypto-host | ||
35 | include $(BUILD_HOST_SHARED_LIBRARY) | ||
36 | |||
37 | include $(CLEAR_VARS) | ||
38 | LOCAL_MODULE := libcrypto_utils_static | ||
39 | LOCAL_SRC_FILES := android_pubkey.c | ||
40 | LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99 | ||
41 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include | ||
42 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | ||
43 | LOCAL_STATIC_LIBRARIES := libcrypto_static | ||
44 | include $(BUILD_STATIC_LIBRARY) | ||
45 | |||
46 | include $(CLEAR_VARS) | ||
47 | LOCAL_MODULE := libcrypto_utils_static | ||
48 | LOCAL_MODULE_HOST_OS := darwin linux windows | ||
49 | LOCAL_SRC_FILES := android_pubkey.c | ||
50 | LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99 | ||
51 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include | ||
52 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | ||
53 | LOCAL_STATIC_LIBRARIES := libcrypto_static | ||
54 | include $(BUILD_HOST_STATIC_LIBRARY) | ||
55 | |||
56 | include $(call all-makefiles-under,$(LOCAL_PATH)) | ||
diff --git a/libcrypto_utils/android_pubkey.c b/libcrypto_utils/android_pubkey.c new file mode 100644 index 000000000..9cd9aabe1 --- /dev/null +++ b/libcrypto_utils/android_pubkey.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <crypto_utils/android_pubkey.h> | ||
18 | |||
19 | #include <assert.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | |||
23 | // Better safe than sorry. | ||
24 | #if (ANDROID_PUBKEY_MODULUS_SIZE % 4) != 0 | ||
25 | #error RSA modulus size must be multiple of the word size! | ||
26 | #endif | ||
27 | |||
28 | // Size of the RSA modulus in words. | ||
29 | #define ANDROID_PUBKEY_MODULUS_SIZE_WORDS (ANDROID_PUBKEY_MODULUS_SIZE / 4) | ||
30 | |||
31 | // This file implements encoding and decoding logic for Android's custom RSA | ||
32 | // public key binary format. Public keys are stored as a sequence of | ||
33 | // little-endian 32 bit words. Note that Android only supports little-endian | ||
34 | // processors, so we don't do any byte order conversions when parsing the binary | ||
35 | // struct. | ||
36 | typedef struct RSAPublicKey { | ||
37 | // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE. | ||
38 | uint32_t modulus_size_words; | ||
39 | |||
40 | // Precomputed montgomery parameter: -1 / n[0] mod 2^32 | ||
41 | uint32_t n0inv; | ||
42 | |||
43 | // RSA modulus as a little-endian array. | ||
44 | uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE]; | ||
45 | |||
46 | // Montgomery parameter R^2 as a little-endian array of little-endian words. | ||
47 | uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE]; | ||
48 | |||
49 | // RSA modulus: 3 or 65537 | ||
50 | uint32_t exponent; | ||
51 | } RSAPublicKey; | ||
52 | |||
53 | // Reverses byte order in |buffer|. | ||
54 | static void reverse_bytes(uint8_t* buffer, size_t size) { | ||
55 | for (size_t i = 0; i < (size + 1) / 2; ++i) { | ||
56 | uint8_t tmp = buffer[i]; | ||
57 | buffer[i] = buffer[size - i - 1]; | ||
58 | buffer[size - i - 1] = tmp; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | bool android_pubkey_decode(const uint8_t* key_buffer, size_t size, RSA** key) { | ||
63 | const RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer; | ||
64 | bool ret = false; | ||
65 | uint8_t modulus_buffer[ANDROID_PUBKEY_MODULUS_SIZE]; | ||
66 | RSA* new_key = RSA_new(); | ||
67 | if (!new_key) { | ||
68 | goto cleanup; | ||
69 | } | ||
70 | |||
71 | // Check |size| is large enough and the modulus size is correct. | ||
72 | if (size < sizeof(RSAPublicKey)) { | ||
73 | goto cleanup; | ||
74 | } | ||
75 | if (key_struct->modulus_size_words != ANDROID_PUBKEY_MODULUS_SIZE_WORDS) { | ||
76 | goto cleanup; | ||
77 | } | ||
78 | |||
79 | // Convert the modulus to big-endian byte order as expected by BN_bin2bn. | ||
80 | memcpy(modulus_buffer, key_struct->modulus, sizeof(modulus_buffer)); | ||
81 | reverse_bytes(modulus_buffer, sizeof(modulus_buffer)); | ||
82 | new_key->n = BN_bin2bn(modulus_buffer, sizeof(modulus_buffer), NULL); | ||
83 | if (!new_key->n) { | ||
84 | goto cleanup; | ||
85 | } | ||
86 | |||
87 | // Read the exponent. | ||
88 | new_key->e = BN_new(); | ||
89 | if (!new_key->e || !BN_set_word(new_key->e, key_struct->exponent)) { | ||
90 | goto cleanup; | ||
91 | } | ||
92 | |||
93 | // Note that we don't extract the montgomery parameters n0inv and rr from | ||
94 | // the RSAPublicKey structure. They assume a word size of 32 bits, but | ||
95 | // BoringSSL may use a word size of 64 bits internally, so we're lacking the | ||
96 | // top 32 bits of n0inv in general. For now, we just ignore the parameters | ||
97 | // and have BoringSSL recompute them internally. More sophisticated logic can | ||
98 | // be added here if/when we want the additional speedup from using the | ||
99 | // pre-computed montgomery parameters. | ||
100 | |||
101 | *key = new_key; | ||
102 | ret = true; | ||
103 | |||
104 | cleanup: | ||
105 | if (!ret && new_key) { | ||
106 | RSA_free(new_key); | ||
107 | } | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static bool android_pubkey_encode_bignum(const BIGNUM* num, uint8_t* buffer) { | ||
112 | if (!BN_bn2bin_padded(buffer, ANDROID_PUBKEY_MODULUS_SIZE, num)) { | ||
113 | return false; | ||
114 | } | ||
115 | |||
116 | reverse_bytes(buffer, ANDROID_PUBKEY_MODULUS_SIZE); | ||
117 | return true; | ||
118 | } | ||
119 | |||
120 | bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size) { | ||
121 | RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer; | ||
122 | bool ret = false; | ||
123 | BN_CTX* ctx = BN_CTX_new(); | ||
124 | BIGNUM* r32 = BN_new(); | ||
125 | BIGNUM* n0inv = BN_new(); | ||
126 | BIGNUM* rr = BN_new(); | ||
127 | |||
128 | if (sizeof(RSAPublicKey) > size || | ||
129 | RSA_size(key) != ANDROID_PUBKEY_MODULUS_SIZE) { | ||
130 | goto cleanup; | ||
131 | } | ||
132 | |||
133 | // Store the modulus size. | ||
134 | key_struct->modulus_size_words = ANDROID_PUBKEY_MODULUS_SIZE_WORDS; | ||
135 | |||
136 | // Compute and store n0inv = -1 / N[0] mod 2^32. | ||
137 | if (!ctx || !r32 || !n0inv || !BN_set_bit(r32, 32) || | ||
138 | !BN_mod(n0inv, key->n, r32, ctx) || | ||
139 | !BN_mod_inverse(n0inv, n0inv, r32, ctx) || !BN_sub(n0inv, r32, n0inv)) { | ||
140 | goto cleanup; | ||
141 | } | ||
142 | key_struct->n0inv = (uint32_t)BN_get_word(n0inv); | ||
143 | |||
144 | // Store the modulus. | ||
145 | if (!android_pubkey_encode_bignum(key->n, key_struct->modulus)) { | ||
146 | goto cleanup; | ||
147 | } | ||
148 | |||
149 | // Compute and store rr = (2^(rsa_size)) ^ 2 mod N. | ||
150 | if (!ctx || !rr || !BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8) || | ||
151 | !BN_mod_sqr(rr, rr, key->n, ctx) || | ||
152 | !android_pubkey_encode_bignum(rr, key_struct->rr)) { | ||
153 | goto cleanup; | ||
154 | } | ||
155 | |||
156 | // Store the exponent. | ||
157 | key_struct->exponent = (uint32_t)BN_get_word(key->e); | ||
158 | |||
159 | ret = true; | ||
160 | |||
161 | cleanup: | ||
162 | BN_free(rr); | ||
163 | BN_free(n0inv); | ||
164 | BN_free(r32); | ||
165 | BN_CTX_free(ctx); | ||
166 | return ret; | ||
167 | } | ||
diff --git a/libcrypto_utils/include/crypto_utils/android_pubkey.h b/libcrypto_utils/include/crypto_utils/android_pubkey.h new file mode 100644 index 000000000..1045eba0f --- /dev/null +++ b/libcrypto_utils/include/crypto_utils/android_pubkey.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef CRYPTO_UTILS_ANDROID_PUBKEY_H | ||
18 | #define CRYPTO_UTILS_ANDROID_PUBKEY_H | ||
19 | |||
20 | #include <stdbool.h> | ||
21 | #include <stddef.h> | ||
22 | #include <stdint.h> | ||
23 | |||
24 | #include <openssl/rsa.h> | ||
25 | |||
26 | #ifdef __cplusplus | ||
27 | extern "C" { | ||
28 | #endif | ||
29 | |||
30 | // Size of an RSA modulus such as an encrypted block or a signature. | ||
31 | #define ANDROID_PUBKEY_MODULUS_SIZE (2048 / 8) | ||
32 | |||
33 | // Size of an encoded RSA key. | ||
34 | #define ANDROID_PUBKEY_ENCODED_SIZE \ | ||
35 | (3 * sizeof(uint32_t) + 2 * ANDROID_PUBKEY_MODULUS_SIZE) | ||
36 | |||
37 | /* Allocates a new RSA |key| object, decodes a public RSA key stored in | ||
38 | * Android's custom binary format from |key_buffer| and sets the key parameters | ||
39 | * in |key|. |size| specifies the size of the key buffer and must be at least | ||
40 | * |ANDROID_PUBKEY_ENCODED_SIZE|. The resulting |*key| can be used with the | ||
41 | * standard BoringSSL API to perform public operations. | ||
42 | * | ||
43 | * Returns true if successful, in which case the caller receives ownership of | ||
44 | * the |*key| object, i.e. needs to call RSA_free() when done with it. If there | ||
45 | * is an error, |key| is left untouched and the return value will be false. | ||
46 | */ | ||
47 | bool android_pubkey_decode(const uint8_t* key_buffer, size_t size, RSA** key); | ||
48 | |||
49 | /* Encodes |key| in the Android RSA public key binary format and stores the | ||
50 | * bytes in |key_buffer|. |key_buffer| should be of size at least | ||
51 | * |ANDROID_PUBKEY_ENCODED_SIZE|. | ||
52 | * | ||
53 | * Returns true if successful, false on error. | ||
54 | */ | ||
55 | bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size); | ||
56 | |||
57 | #ifdef __cplusplus | ||
58 | } // extern "C" | ||
59 | #endif | ||
60 | |||
61 | #endif // CRYPTO_UTILS_ANDROID_PUBKEY_H | ||
diff --git a/libcrypto_utils/tests/Android.mk b/libcrypto_utils/tests/Android.mk new file mode 100644 index 000000000..dad82f70f --- /dev/null +++ b/libcrypto_utils/tests/Android.mk | |||
@@ -0,0 +1,24 @@ | |||
1 | # | ||
2 | # Copyright (C) 2016 The Android Open Source Project | ||
3 | # | ||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | # you may not use this file except in compliance with the License. | ||
6 | # You may obtain a copy of the License at | ||
7 | # | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | # | ||
10 | # Unless required by applicable law or agreed to in writing, software | ||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | # See the License for the specific language governing permissions and | ||
14 | # limitations under the License. | ||
15 | # | ||
16 | |||
17 | LOCAL_PATH := $(call my-dir) | ||
18 | |||
19 | include $(CLEAR_VARS) | ||
20 | LOCAL_MODULE := libcrypto_utils_test | ||
21 | LOCAL_SRC_FILES := android_pubkey_test.cpp | ||
22 | LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c++11 | ||
23 | LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto-host | ||
24 | include $(BUILD_HOST_NATIVE_TEST) | ||
diff --git a/libcrypto_utils/tests/android_pubkey_test.cpp b/libcrypto_utils/tests/android_pubkey_test.cpp new file mode 100644 index 000000000..f8c2e0cae --- /dev/null +++ b/libcrypto_utils/tests/android_pubkey_test.cpp | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <crypto_utils/android_pubkey.h> | ||
18 | |||
19 | #include <string.h> | ||
20 | |||
21 | #include <memory> | ||
22 | |||
23 | #include <openssl/obj_mac.h> | ||
24 | #include <openssl/rsa.h> | ||
25 | |||
26 | #include <gtest/gtest.h> | ||
27 | |||
28 | // Test digest to verify. | ||
29 | const uint8_t kDigest[] = { | ||
30 | 0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0, | ||
31 | 0x06, 0x4e, 0x4a, 0x01, 0x64, 0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8, | ||
32 | 0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3, | ||
33 | }; | ||
34 | |||
35 | // 2048 RSA test key. | ||
36 | const uint8_t kKey2048[ANDROID_PUBKEY_ENCODED_SIZE] = { | ||
37 | 0x40, 0x00, 0x00, 0x00, 0x05, 0x75, 0x61, 0xd1, 0x33, 0xf0, 0x2d, 0x12, | ||
38 | 0x45, 0xfb, 0xae, 0x07, 0x02, 0x15, 0x4f, 0x3a, 0x2b, 0xa3, 0xbc, 0x49, | ||
39 | 0xbd, 0x14, 0x07, 0xa0, 0xc0, 0x9f, 0x0c, 0x52, 0x60, 0x77, 0x9f, 0xa2, | ||
40 | 0x31, 0xd0, 0xa7, 0xfb, 0x7e, 0xde, 0xfb, 0xc9, 0x05, 0xc0, 0x97, 0xf7, | ||
41 | 0x74, 0x99, 0xe6, 0xd1, 0x08, 0xa6, 0xc2, 0x59, 0x5a, 0xd8, 0x37, 0x1d, | ||
42 | 0xe0, 0x48, 0x5e, 0x63, 0x44, 0x04, 0x8b, 0x05, 0x20, 0xf6, 0x25, 0x67, | ||
43 | 0x38, 0xb2, 0xb6, 0xf9, 0xbe, 0xb6, 0x1d, 0x7f, 0x1b, 0x71, 0x8a, 0xeb, | ||
44 | 0xb7, 0xf8, 0x01, 0xc1, 0x5e, 0xf7, 0xfe, 0x48, 0x08, 0x27, 0x0f, 0x27, | ||
45 | 0x2a, 0x64, 0x1a, 0x43, 0x8d, 0xcf, 0x5a, 0x33, 0x5c, 0x18, 0xc5, 0xf4, | ||
46 | 0xe7, 0xfe, 0xee, 0xd3, 0x12, 0x62, 0xad, 0x61, 0x78, 0x9a, 0x03, 0xb0, | ||
47 | 0xaf, 0xab, 0x91, 0x57, 0x46, 0xbf, 0x18, 0xc6, 0xbc, 0x0c, 0x6b, 0x55, | ||
48 | 0xcd, 0xda, 0xc4, 0xcc, 0x98, 0x46, 0x91, 0x99, 0xbc, 0xa3, 0xca, 0x6c, | ||
49 | 0x86, 0xa6, 0x1c, 0x8f, 0xca, 0xf8, 0xf6, 0x8a, 0x00, 0x8e, 0x05, 0xd7, | ||
50 | 0x13, 0x43, 0xe2, 0xf2, 0x1a, 0x13, 0xf3, 0x50, 0x13, 0xa4, 0xf2, 0x4e, | ||
51 | 0x41, 0xb1, 0x36, 0x78, 0x55, 0x4c, 0x5e, 0x27, 0xc5, 0xc0, 0x4b, 0xd8, | ||
52 | 0x93, 0xaa, 0x7e, 0xf0, 0x90, 0x08, 0x10, 0x26, 0x72, 0x6d, 0xb9, 0x21, | ||
53 | 0xae, 0x4d, 0x01, 0x4b, 0x55, 0x1d, 0xe7, 0x1e, 0x5e, 0x31, 0x6e, 0x62, | ||
54 | 0xd1, 0x33, 0x26, 0xcb, 0xdb, 0xfe, 0x72, 0x98, 0xc8, 0x06, 0x1c, 0x12, | ||
55 | 0xdf, 0xfc, 0x74, 0xe5, 0x7a, 0x6f, 0xf5, 0xa3, 0x63, 0x08, 0xe3, 0x02, | ||
56 | 0x68, 0x4d, 0x7c, 0x70, 0x05, 0xec, 0x95, 0x7e, 0x24, 0xa4, 0xbc, 0x4c, | ||
57 | 0xcd, 0x39, 0x14, 0xb5, 0x2a, 0x8f, 0xc1, 0xe3, 0x4e, 0xfa, 0xf8, 0x70, | ||
58 | 0x50, 0x8f, 0xd5, 0x8e, 0xc7, 0xb5, 0x32, 0x89, 0x4d, 0xbb, 0x6a, 0xc1, | ||
59 | 0xc1, 0xa2, 0x42, 0x57, 0x57, 0xbd, 0x2a, 0xdc, 0xa6, 0xfd, 0xc8, 0x86, | ||
60 | 0x44, 0x6a, 0x03, 0x5d, 0x4d, 0x28, 0xe1, 0xde, 0xb4, 0xa9, 0xa5, 0x03, | ||
61 | 0x61, 0x7a, 0x5f, 0xb1, 0x09, 0x17, 0x2b, 0x9c, 0xa2, 0x54, 0x28, 0xad, | ||
62 | 0x34, 0xc9, 0x5f, 0x6c, 0x9f, 0xb8, 0xd2, 0xa9, 0x78, 0xa7, 0xaa, 0xb3, | ||
63 | 0x11, 0x2f, 0x65, 0x9b, 0x4e, 0x67, 0x0c, 0xcc, 0x20, 0x36, 0xbf, 0x26, | ||
64 | 0x2b, 0x4e, 0xc0, 0xd4, 0xbd, 0x22, 0x64, 0xc4, 0x1c, 0x56, 0x69, 0xdb, | ||
65 | 0x5f, 0x89, 0xe1, 0x75, 0x68, 0x8d, 0x0e, 0xab, 0x1c, 0x10, 0x1a, 0xc0, | ||
66 | 0x12, 0x5d, 0x6f, 0xbd, 0x09, 0xbb, 0x47, 0xcb, 0xe7, 0x34, 0xef, 0x56, | ||
67 | 0xab, 0xea, 0xc3, 0xe9, 0x7f, 0x9a, 0x3d, 0xe9, 0x2d, 0x14, 0x61, 0x25, | ||
68 | 0x37, 0x5c, 0x3b, 0x4b, 0xaf, 0x5a, 0x4b, 0xc8, 0x99, 0x1a, 0x32, 0x8f, | ||
69 | 0x54, 0x07, 0xd3, 0x57, 0x8a, 0x3d, 0x2a, 0xf7, 0x9e, 0x7e, 0x92, 0x2a, | ||
70 | 0x50, 0xe9, 0xd8, 0xdb, 0xd6, 0x03, 0xd3, 0x8e, 0x54, 0x32, 0xce, 0x87, | ||
71 | 0x93, 0x92, 0xe7, 0x75, 0xe1, 0x6b, 0x78, 0x1a, 0x85, 0xc2, 0x46, 0xa1, | ||
72 | 0x31, 0xbb, 0xc7, 0xb9, 0x1d, 0xd1, 0x71, 0xe0, 0xe2, 0x9b, 0x9c, 0x0d, | ||
73 | 0xa3, 0xcf, 0x93, 0x4d, 0x87, 0x7b, 0x65, 0xd9, 0xda, 0x4c, 0xd9, 0x6a, | ||
74 | 0xa6, 0x36, 0xc2, 0xc7, 0xe3, 0x33, 0xe2, 0xc3, 0x83, 0xd1, 0x72, 0x54, | ||
75 | 0x30, 0x81, 0x5e, 0x34, 0x2c, 0x61, 0xee, 0xf4, 0x48, 0x97, 0xb6, 0xaa, | ||
76 | 0x47, 0x6a, 0x05, 0x09, 0xd8, 0x4d, 0x90, 0xaf, 0xa8, 0x4e, 0x82, 0xe4, | ||
77 | 0x8e, 0xb5, 0xe2, 0x65, 0x86, 0x67, 0xe9, 0x5b, 0x4b, 0x9a, 0x68, 0x08, | ||
78 | 0x30, 0xf6, 0x25, 0x8b, 0x20, 0xda, 0x26, 0x6f, 0xbd, 0x0d, 0xa5, 0xd8, | ||
79 | 0x6a, 0x7b, 0x01, 0x2f, 0xab, 0x7b, 0xb5, 0xfe, 0x62, 0x37, 0x2d, 0x94, | ||
80 | 0x43, 0x2f, 0x4d, 0x16, 0x01, 0x00, 0x01, 0x00, | ||
81 | }; | ||
82 | |||
83 | // 2048 bit RSA signature. | ||
84 | const uint8_t kSignature2048[ANDROID_PUBKEY_MODULUS_SIZE] = { | ||
85 | 0x3a, 0x11, 0x84, 0x40, 0xc1, 0x2f, 0x13, 0x8c, 0xde, 0xb0, 0xc3, 0x89, | ||
86 | 0x8a, 0x63, 0xb2, 0x50, 0x93, 0x58, 0xc0, 0x0c, 0xb7, 0x08, 0xe7, 0x6c, | ||
87 | 0x52, 0x87, 0x4e, 0x78, 0x89, 0xa3, 0x9a, 0x47, 0xeb, 0x11, 0x57, 0xbc, | ||
88 | 0xb3, 0x97, 0xf8, 0x34, 0xf1, 0xf7, 0xbf, 0x3a, 0xfa, 0x1c, 0x6b, 0xdc, | ||
89 | 0xd1, 0x02, 0xde, 0x9a, 0x0d, 0x72, 0xe7, 0x19, 0x63, 0x81, 0x46, 0x68, | ||
90 | 0x1e, 0x63, 0x64, 0xc6, 0x59, 0xe7, 0x7c, 0x39, 0xed, 0x32, 0xd2, 0xd1, | ||
91 | 0xd5, 0x1f, 0x13, 0x9b, 0x52, 0xdf, 0x34, 0xa3, 0xc0, 0xc4, 0x9a, 0x63, | ||
92 | 0x9b, 0x9c, 0xbe, 0x22, 0xc8, 0xd8, 0x14, 0x2f, 0x4c, 0x78, 0x36, 0xdb, | ||
93 | 0x16, 0x41, 0x67, 0xc1, 0x21, 0x8a, 0x73, 0xb2, 0xe5, 0xb0, 0xd3, 0x80, | ||
94 | 0x91, 0x7a, 0xbf, 0xf9, 0x59, 0x4a, 0x4d, 0x78, 0x45, 0x44, 0xa1, 0x52, | ||
95 | 0x86, 0x29, 0x48, 0x4d, 0xf0, 0x5d, 0xf2, 0x55, 0xa7, 0xcd, 0xc5, 0x2b, | ||
96 | 0x7b, 0xe0, 0xb1, 0xf6, 0x2a, 0xd5, 0x61, 0xba, 0x1e, 0x1e, 0x3a, 0xf0, | ||
97 | 0x55, 0xbc, 0x8c, 0x44, 0x41, 0xfc, 0xb8, 0x8c, 0x76, 0xbf, 0x80, 0x58, | ||
98 | 0x82, 0x35, 0x4b, 0x0c, 0xfd, 0xef, 0xd5, 0x70, 0xd1, 0x64, 0xcb, 0x46, | ||
99 | 0x58, 0x37, 0xbc, 0xa9, 0x7d, 0xd4, 0x70, 0xac, 0xce, 0xec, 0xca, 0x48, | ||
100 | 0xcb, 0x0a, 0x40, 0x77, 0x04, 0x59, 0xca, 0x9c, 0x7d, 0x1a, 0x0b, 0xf0, | ||
101 | 0xb5, 0xdd, 0xde, 0x71, 0x18, 0xb8, 0xef, 0x90, 0x2a, 0x09, 0x42, 0x39, | ||
102 | 0x74, 0xff, 0x45, 0xa1, 0x39, 0x17, 0x50, 0x89, 0xa6, 0x5f, 0xbc, 0x9c, | ||
103 | 0x0c, 0x9b, 0x47, 0x25, 0x79, 0x3e, 0xe3, 0xaa, 0xaf, 0xbe, 0x73, 0x6b, | ||
104 | 0xcb, 0xe7, 0x35, 0xc1, 0x27, 0x09, 0xcd, 0xeb, 0xd7, 0xcf, 0x63, 0x83, | ||
105 | 0x64, 0x8c, 0x45, 0x1c, 0x1d, 0x58, 0xcc, 0xd2, 0xf8, 0x2b, 0x4c, 0x4e, | ||
106 | 0x14, 0x89, 0x2d, 0x70, | ||
107 | }; | ||
108 | |||
109 | struct AndroidPubkeyTest : public ::testing::Test { | ||
110 | void SetUp() override { | ||
111 | RSA* new_key = nullptr; | ||
112 | ASSERT_TRUE(android_pubkey_decode(kKey2048, sizeof(kKey2048), &new_key)); | ||
113 | key_.reset(new_key); | ||
114 | } | ||
115 | |||
116 | std::unique_ptr<RSA, void(*)(RSA*)> key_ = {nullptr, RSA_free}; | ||
117 | }; | ||
118 | |||
119 | TEST_F(AndroidPubkeyTest, Decode) { | ||
120 | // Make sure the decoded key successfully verifies a valid signature. | ||
121 | EXPECT_TRUE(RSA_verify(NID_sha256, kDigest, sizeof(kDigest), kSignature2048, | ||
122 | sizeof(kSignature2048), key_.get())); | ||
123 | } | ||
124 | |||
125 | TEST_F(AndroidPubkeyTest, Encode) { | ||
126 | uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE]; | ||
127 | ASSERT_TRUE(android_pubkey_encode(key_.get(), key_data, sizeof(key_data))); | ||
128 | ASSERT_EQ(0, memcmp(kKey2048, key_data, sizeof(kKey2048))); | ||
129 | } | ||