system/corennnnn
Revision | 64ef267bafb992b2fe60834728f2e1c66f257ffe (tree) |
---|---|
Zeit | 2016-09-04 08:47:15 |
Autor | Mattias Nissler <mnissler@goog...> |
Commiter | Steve Kondik |
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
@@ -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)) |
@@ -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 | +} |
@@ -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 |
@@ -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) |
@@ -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 | +} |