xref: /aosp_15_r20/system/security/keystore2/src/crypto/crypto.cpp (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1*e1997b9aSAndroid Build Coastguard Worker /*
2*e1997b9aSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*e1997b9aSAndroid Build Coastguard Worker  *
4*e1997b9aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1997b9aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1997b9aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1997b9aSAndroid Build Coastguard Worker  *
8*e1997b9aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1997b9aSAndroid Build Coastguard Worker  *
10*e1997b9aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1997b9aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1997b9aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1997b9aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1997b9aSAndroid Build Coastguard Worker  * limitations under the License.
15*e1997b9aSAndroid Build Coastguard Worker  */
16*e1997b9aSAndroid Build Coastguard Worker 
17*e1997b9aSAndroid Build Coastguard Worker #define LOG_TAG "keystore2"
18*e1997b9aSAndroid Build Coastguard Worker 
19*e1997b9aSAndroid Build Coastguard Worker #include "crypto.hpp"
20*e1997b9aSAndroid Build Coastguard Worker 
21*e1997b9aSAndroid Build Coastguard Worker #include <assert.h>
22*e1997b9aSAndroid Build Coastguard Worker #include <log/log.h>
23*e1997b9aSAndroid Build Coastguard Worker #include <openssl/aes.h>
24*e1997b9aSAndroid Build Coastguard Worker #include <openssl/ec.h>
25*e1997b9aSAndroid Build Coastguard Worker #include <openssl/ec_key.h>
26*e1997b9aSAndroid Build Coastguard Worker #include <openssl/ecdh.h>
27*e1997b9aSAndroid Build Coastguard Worker #include <openssl/evp.h>
28*e1997b9aSAndroid Build Coastguard Worker #include <openssl/hkdf.h>
29*e1997b9aSAndroid Build Coastguard Worker #include <openssl/hmac.h>
30*e1997b9aSAndroid Build Coastguard Worker #include <openssl/rand.h>
31*e1997b9aSAndroid Build Coastguard Worker #include <openssl/x509.h>
32*e1997b9aSAndroid Build Coastguard Worker 
33*e1997b9aSAndroid Build Coastguard Worker #include <vector>
34*e1997b9aSAndroid Build Coastguard Worker 
35*e1997b9aSAndroid Build Coastguard Worker // Copied from system/security/keystore/blob.h.
36*e1997b9aSAndroid Build Coastguard Worker 
37*e1997b9aSAndroid Build Coastguard Worker constexpr size_t kGcmTagLength = 128 / 8;
38*e1997b9aSAndroid Build Coastguard Worker constexpr size_t kAes128KeySizeBytes = 128 / 8;
39*e1997b9aSAndroid Build Coastguard Worker 
40*e1997b9aSAndroid Build Coastguard Worker // Copied from system/security/keystore/blob.cpp.
41*e1997b9aSAndroid Build Coastguard Worker 
42*e1997b9aSAndroid Build Coastguard Worker #if defined(__clang__)
43*e1997b9aSAndroid Build Coastguard Worker #define OPTNONE __attribute__((optnone))
44*e1997b9aSAndroid Build Coastguard Worker #elif defined(__GNUC__)
45*e1997b9aSAndroid Build Coastguard Worker #define OPTNONE __attribute__((optimize("O0")))
46*e1997b9aSAndroid Build Coastguard Worker #else
47*e1997b9aSAndroid Build Coastguard Worker #error Need a definition for OPTNONE
48*e1997b9aSAndroid Build Coastguard Worker #endif
49*e1997b9aSAndroid Build Coastguard Worker 
50*e1997b9aSAndroid Build Coastguard Worker class ArrayEraser {
51*e1997b9aSAndroid Build Coastguard Worker   public:
ArrayEraser(uint8_t * arr,size_t size)52*e1997b9aSAndroid Build Coastguard Worker     ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
~ArrayEraser()53*e1997b9aSAndroid Build Coastguard Worker     OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
54*e1997b9aSAndroid Build Coastguard Worker 
55*e1997b9aSAndroid Build Coastguard Worker   private:
56*e1997b9aSAndroid Build Coastguard Worker     volatile uint8_t* mArr;
57*e1997b9aSAndroid Build Coastguard Worker     size_t mSize;
58*e1997b9aSAndroid Build Coastguard Worker };
59*e1997b9aSAndroid Build Coastguard Worker 
60*e1997b9aSAndroid Build Coastguard Worker /**
61*e1997b9aSAndroid Build Coastguard Worker  * Returns a EVP_CIPHER appropriate for the given key size.
62*e1997b9aSAndroid Build Coastguard Worker  */
getAesCipherForKey(size_t key_size)63*e1997b9aSAndroid Build Coastguard Worker const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
64*e1997b9aSAndroid Build Coastguard Worker     const EVP_CIPHER* cipher = EVP_aes_256_gcm();
65*e1997b9aSAndroid Build Coastguard Worker     if (key_size == kAes128KeySizeBytes) {
66*e1997b9aSAndroid Build Coastguard Worker         cipher = EVP_aes_128_gcm();
67*e1997b9aSAndroid Build Coastguard Worker     }
68*e1997b9aSAndroid Build Coastguard Worker     return cipher;
69*e1997b9aSAndroid Build Coastguard Worker }
70*e1997b9aSAndroid Build Coastguard Worker 
hmacSha256(const uint8_t * key,size_t key_size,const uint8_t * msg,size_t msg_size,uint8_t * out,size_t out_size)71*e1997b9aSAndroid Build Coastguard Worker bool hmacSha256(const uint8_t* key, size_t key_size, const uint8_t* msg, size_t msg_size,
72*e1997b9aSAndroid Build Coastguard Worker                 uint8_t* out, size_t out_size) {
73*e1997b9aSAndroid Build Coastguard Worker     const EVP_MD* digest = EVP_sha256();
74*e1997b9aSAndroid Build Coastguard Worker     unsigned int actual_out_size = out_size;
75*e1997b9aSAndroid Build Coastguard Worker     uint8_t* p = HMAC(digest, key, key_size, msg, msg_size, out, &actual_out_size);
76*e1997b9aSAndroid Build Coastguard Worker     return (p != nullptr);
77*e1997b9aSAndroid Build Coastguard Worker }
78*e1997b9aSAndroid Build Coastguard Worker 
randomBytes(uint8_t * out,size_t len)79*e1997b9aSAndroid Build Coastguard Worker bool randomBytes(uint8_t* out, size_t len) {
80*e1997b9aSAndroid Build Coastguard Worker     return RAND_bytes(out, len);
81*e1997b9aSAndroid Build Coastguard Worker }
82*e1997b9aSAndroid Build Coastguard Worker 
83*e1997b9aSAndroid Build Coastguard Worker /*
84*e1997b9aSAndroid Build Coastguard Worker  * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
85*e1997b9aSAndroid Build Coastguard Worker  * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
86*e1997b9aSAndroid Build Coastguard Worker  * 'tag'.
87*e1997b9aSAndroid Build Coastguard Worker  */
AES_gcm_encrypt(const uint8_t * in,uint8_t * out,size_t len,const uint8_t * key,size_t key_size,const uint8_t * iv,uint8_t * tag)88*e1997b9aSAndroid Build Coastguard Worker bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
89*e1997b9aSAndroid Build Coastguard Worker                      size_t key_size, const uint8_t* iv, uint8_t* tag) {
90*e1997b9aSAndroid Build Coastguard Worker 
91*e1997b9aSAndroid Build Coastguard Worker     // There can be 128-bit and 256-bit keys
92*e1997b9aSAndroid Build Coastguard Worker     const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
93*e1997b9aSAndroid Build Coastguard Worker 
94*e1997b9aSAndroid Build Coastguard Worker     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
95*e1997b9aSAndroid Build Coastguard Worker 
96*e1997b9aSAndroid Build Coastguard Worker     EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
97*e1997b9aSAndroid Build Coastguard Worker     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
98*e1997b9aSAndroid Build Coastguard Worker 
99*e1997b9aSAndroid Build Coastguard Worker     std::vector<uint8_t> out_tmp(len);
100*e1997b9aSAndroid Build Coastguard Worker     uint8_t* out_pos = out_tmp.data();
101*e1997b9aSAndroid Build Coastguard Worker     int out_len;
102*e1997b9aSAndroid Build Coastguard Worker 
103*e1997b9aSAndroid Build Coastguard Worker     EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
104*e1997b9aSAndroid Build Coastguard Worker     out_pos += out_len;
105*e1997b9aSAndroid Build Coastguard Worker     EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
106*e1997b9aSAndroid Build Coastguard Worker     out_pos += out_len;
107*e1997b9aSAndroid Build Coastguard Worker     if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
108*e1997b9aSAndroid Build Coastguard Worker         ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
109*e1997b9aSAndroid Build Coastguard Worker               out_pos - out_tmp.data());
110*e1997b9aSAndroid Build Coastguard Worker         return false;
111*e1997b9aSAndroid Build Coastguard Worker     }
112*e1997b9aSAndroid Build Coastguard Worker 
113*e1997b9aSAndroid Build Coastguard Worker     std::copy(out_tmp.data(), out_pos, out);
114*e1997b9aSAndroid Build Coastguard Worker     EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
115*e1997b9aSAndroid Build Coastguard Worker 
116*e1997b9aSAndroid Build Coastguard Worker     return true;
117*e1997b9aSAndroid Build Coastguard Worker }
118*e1997b9aSAndroid Build Coastguard Worker 
119*e1997b9aSAndroid Build Coastguard Worker /*
120*e1997b9aSAndroid Build Coastguard Worker  * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
121*e1997b9aSAndroid Build Coastguard Worker  * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
122*e1997b9aSAndroid Build Coastguard Worker  * location as 'in').
123*e1997b9aSAndroid Build Coastguard Worker  */
AES_gcm_decrypt(const uint8_t * in,uint8_t * out,size_t len,const uint8_t * key,size_t key_size,const uint8_t * iv,const uint8_t * tag)124*e1997b9aSAndroid Build Coastguard Worker bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
125*e1997b9aSAndroid Build Coastguard Worker                      size_t key_size, const uint8_t* iv, const uint8_t* tag) {
126*e1997b9aSAndroid Build Coastguard Worker 
127*e1997b9aSAndroid Build Coastguard Worker     // There can be 128-bit and 256-bit keys
128*e1997b9aSAndroid Build Coastguard Worker     const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
129*e1997b9aSAndroid Build Coastguard Worker 
130*e1997b9aSAndroid Build Coastguard Worker     bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
131*e1997b9aSAndroid Build Coastguard Worker 
132*e1997b9aSAndroid Build Coastguard Worker     EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
133*e1997b9aSAndroid Build Coastguard Worker     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
134*e1997b9aSAndroid Build Coastguard Worker     EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
135*e1997b9aSAndroid Build Coastguard Worker 
136*e1997b9aSAndroid Build Coastguard Worker     std::vector<uint8_t> out_tmp(len);
137*e1997b9aSAndroid Build Coastguard Worker     ArrayEraser out_eraser(out_tmp.data(), len);
138*e1997b9aSAndroid Build Coastguard Worker     uint8_t* out_pos = out_tmp.data();
139*e1997b9aSAndroid Build Coastguard Worker     int out_len;
140*e1997b9aSAndroid Build Coastguard Worker 
141*e1997b9aSAndroid Build Coastguard Worker     EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
142*e1997b9aSAndroid Build Coastguard Worker     out_pos += out_len;
143*e1997b9aSAndroid Build Coastguard Worker     if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
144*e1997b9aSAndroid Build Coastguard Worker         // No error log here; this is expected when trying two different keys to see which one
145*e1997b9aSAndroid Build Coastguard Worker         // works.  The callers handle the error appropriately.
146*e1997b9aSAndroid Build Coastguard Worker         return false;
147*e1997b9aSAndroid Build Coastguard Worker     }
148*e1997b9aSAndroid Build Coastguard Worker     out_pos += out_len;
149*e1997b9aSAndroid Build Coastguard Worker     if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
150*e1997b9aSAndroid Build Coastguard Worker         ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
151*e1997b9aSAndroid Build Coastguard Worker               out_pos - out_tmp.data());
152*e1997b9aSAndroid Build Coastguard Worker         return false;
153*e1997b9aSAndroid Build Coastguard Worker     }
154*e1997b9aSAndroid Build Coastguard Worker 
155*e1997b9aSAndroid Build Coastguard Worker     std::copy(out_tmp.data(), out_pos, out);
156*e1997b9aSAndroid Build Coastguard Worker 
157*e1997b9aSAndroid Build Coastguard Worker     return true;
158*e1997b9aSAndroid Build Coastguard Worker }
159*e1997b9aSAndroid Build Coastguard Worker 
160*e1997b9aSAndroid Build Coastguard Worker // Copied from system/security/keystore/keymaster_enforcement.cpp.
161*e1997b9aSAndroid Build Coastguard Worker 
162*e1997b9aSAndroid Build Coastguard Worker class EvpMdCtx {
163*e1997b9aSAndroid Build Coastguard Worker   public:
EvpMdCtx()164*e1997b9aSAndroid Build Coastguard Worker     EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
~EvpMdCtx()165*e1997b9aSAndroid Build Coastguard Worker     ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
166*e1997b9aSAndroid Build Coastguard Worker 
get()167*e1997b9aSAndroid Build Coastguard Worker     EVP_MD_CTX* get() { return &ctx_; }
168*e1997b9aSAndroid Build Coastguard Worker 
169*e1997b9aSAndroid Build Coastguard Worker   private:
170*e1997b9aSAndroid Build Coastguard Worker     EVP_MD_CTX ctx_;
171*e1997b9aSAndroid Build Coastguard Worker };
172*e1997b9aSAndroid Build Coastguard Worker 
CreateKeyId(const uint8_t * key_blob,size_t len,km_id_t * out_id)173*e1997b9aSAndroid Build Coastguard Worker bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
174*e1997b9aSAndroid Build Coastguard Worker     EvpMdCtx ctx;
175*e1997b9aSAndroid Build Coastguard Worker 
176*e1997b9aSAndroid Build Coastguard Worker     uint8_t hash[EVP_MAX_MD_SIZE];
177*e1997b9aSAndroid Build Coastguard Worker     unsigned int hash_len;
178*e1997b9aSAndroid Build Coastguard Worker     if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
179*e1997b9aSAndroid Build Coastguard Worker         EVP_DigestUpdate(ctx.get(), key_blob, len) &&
180*e1997b9aSAndroid Build Coastguard Worker         EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
181*e1997b9aSAndroid Build Coastguard Worker         assert(hash_len >= sizeof(*out_id));
182*e1997b9aSAndroid Build Coastguard Worker         memcpy(out_id, hash, sizeof(*out_id));
183*e1997b9aSAndroid Build Coastguard Worker         return true;
184*e1997b9aSAndroid Build Coastguard Worker     }
185*e1997b9aSAndroid Build Coastguard Worker 
186*e1997b9aSAndroid Build Coastguard Worker     return false;
187*e1997b9aSAndroid Build Coastguard Worker }
188*e1997b9aSAndroid Build Coastguard Worker 
189*e1997b9aSAndroid Build Coastguard Worker // Copied from system/security/keystore/user_state.h
190*e1997b9aSAndroid Build Coastguard Worker 
191*e1997b9aSAndroid Build Coastguard Worker static constexpr size_t SALT_SIZE = 16;
192*e1997b9aSAndroid Build Coastguard Worker 
193*e1997b9aSAndroid Build Coastguard Worker // Copied from system/security/keystore/user_state.cpp.
194*e1997b9aSAndroid Build Coastguard Worker 
PBKDF2(uint8_t * key,size_t key_len,const char * pw,size_t pw_len,const uint8_t * salt)195*e1997b9aSAndroid Build Coastguard Worker void PBKDF2(uint8_t* key, size_t key_len, const char* pw, size_t pw_len, const uint8_t* salt) {
196*e1997b9aSAndroid Build Coastguard Worker     const EVP_MD* digest = EVP_sha256();
197*e1997b9aSAndroid Build Coastguard Worker 
198*e1997b9aSAndroid Build Coastguard Worker     // SHA1 was used prior to increasing the key size
199*e1997b9aSAndroid Build Coastguard Worker     if (key_len == kAes128KeySizeBytes) {
200*e1997b9aSAndroid Build Coastguard Worker         digest = EVP_sha1();
201*e1997b9aSAndroid Build Coastguard Worker     }
202*e1997b9aSAndroid Build Coastguard Worker 
203*e1997b9aSAndroid Build Coastguard Worker     PKCS5_PBKDF2_HMAC(pw, pw_len, salt, SALT_SIZE, 8192, digest, key_len, key);
204*e1997b9aSAndroid Build Coastguard Worker }
205*e1997b9aSAndroid Build Coastguard Worker 
206*e1997b9aSAndroid Build Coastguard Worker // New code.
207*e1997b9aSAndroid Build Coastguard Worker 
HKDFExtract(uint8_t * out_key,size_t * out_len,const uint8_t * secret,size_t secret_len,const uint8_t * salt,size_t salt_len)208*e1997b9aSAndroid Build Coastguard Worker bool HKDFExtract(uint8_t* out_key, size_t* out_len, const uint8_t* secret, size_t secret_len,
209*e1997b9aSAndroid Build Coastguard Worker                  const uint8_t* salt, size_t salt_len) {
210*e1997b9aSAndroid Build Coastguard Worker     const EVP_MD* digest = EVP_sha256();
211*e1997b9aSAndroid Build Coastguard Worker     auto result = HKDF_extract(out_key, out_len, digest, secret, secret_len, salt, salt_len);
212*e1997b9aSAndroid Build Coastguard Worker     return result == 1;
213*e1997b9aSAndroid Build Coastguard Worker }
214*e1997b9aSAndroid Build Coastguard Worker 
HKDFExpand(uint8_t * out_key,size_t out_len,const uint8_t * prk,size_t prk_len,const uint8_t * info,size_t info_len)215*e1997b9aSAndroid Build Coastguard Worker bool HKDFExpand(uint8_t* out_key, size_t out_len, const uint8_t* prk, size_t prk_len,
216*e1997b9aSAndroid Build Coastguard Worker                 const uint8_t* info, size_t info_len) {
217*e1997b9aSAndroid Build Coastguard Worker     const EVP_MD* digest = EVP_sha256();
218*e1997b9aSAndroid Build Coastguard Worker     auto result = HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len);
219*e1997b9aSAndroid Build Coastguard Worker     return result == 1;
220*e1997b9aSAndroid Build Coastguard Worker }
221*e1997b9aSAndroid Build Coastguard Worker 
ECDHComputeKey(void * out,const EC_POINT * pub_key,const EC_KEY * priv_key)222*e1997b9aSAndroid Build Coastguard Worker int ECDHComputeKey(void* out, const EC_POINT* pub_key, const EC_KEY* priv_key) {
223*e1997b9aSAndroid Build Coastguard Worker     return ECDH_compute_key(out, EC_MAX_BYTES, pub_key, priv_key, nullptr);
224*e1997b9aSAndroid Build Coastguard Worker }
225*e1997b9aSAndroid Build Coastguard Worker 
ECKEYGenerateKey()226*e1997b9aSAndroid Build Coastguard Worker EC_KEY* ECKEYGenerateKey() {
227*e1997b9aSAndroid Build Coastguard Worker     EC_KEY* key = EC_KEY_new();
228*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
229*e1997b9aSAndroid Build Coastguard Worker     EC_KEY_set_group(key, group);
230*e1997b9aSAndroid Build Coastguard Worker     auto result = EC_KEY_generate_key(key);
231*e1997b9aSAndroid Build Coastguard Worker     if (result == 0) {
232*e1997b9aSAndroid Build Coastguard Worker         EC_GROUP_free(group);
233*e1997b9aSAndroid Build Coastguard Worker         EC_KEY_free(key);
234*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
235*e1997b9aSAndroid Build Coastguard Worker     }
236*e1997b9aSAndroid Build Coastguard Worker     return key;
237*e1997b9aSAndroid Build Coastguard Worker }
238*e1997b9aSAndroid Build Coastguard Worker 
ECKEYMarshalPrivateKey(const EC_KEY * priv_key,uint8_t * buf,size_t len)239*e1997b9aSAndroid Build Coastguard Worker size_t ECKEYMarshalPrivateKey(const EC_KEY* priv_key, uint8_t* buf, size_t len) {
240*e1997b9aSAndroid Build Coastguard Worker     CBB cbb;
241*e1997b9aSAndroid Build Coastguard Worker     size_t out_len;
242*e1997b9aSAndroid Build Coastguard Worker     if (!CBB_init_fixed(&cbb, buf, len) ||
243*e1997b9aSAndroid Build Coastguard Worker         !EC_KEY_marshal_private_key(&cbb, priv_key, EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY) ||
244*e1997b9aSAndroid Build Coastguard Worker         !CBB_finish(&cbb, nullptr, &out_len)) {
245*e1997b9aSAndroid Build Coastguard Worker         return 0;
246*e1997b9aSAndroid Build Coastguard Worker     } else {
247*e1997b9aSAndroid Build Coastguard Worker         return out_len;
248*e1997b9aSAndroid Build Coastguard Worker     }
249*e1997b9aSAndroid Build Coastguard Worker }
250*e1997b9aSAndroid Build Coastguard Worker 
ECKEYParsePrivateKey(const uint8_t * buf,size_t len)251*e1997b9aSAndroid Build Coastguard Worker EC_KEY* ECKEYParsePrivateKey(const uint8_t* buf, size_t len) {
252*e1997b9aSAndroid Build Coastguard Worker     CBS cbs;
253*e1997b9aSAndroid Build Coastguard Worker     CBS_init(&cbs, buf, len);
254*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
255*e1997b9aSAndroid Build Coastguard Worker     auto result = EC_KEY_parse_private_key(&cbs, group);
256*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP_free(group);
257*e1997b9aSAndroid Build Coastguard Worker     if (result != nullptr && CBS_len(&cbs) != 0) {
258*e1997b9aSAndroid Build Coastguard Worker         EC_KEY_free(result);
259*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
260*e1997b9aSAndroid Build Coastguard Worker     }
261*e1997b9aSAndroid Build Coastguard Worker     return result;
262*e1997b9aSAndroid Build Coastguard Worker }
263*e1997b9aSAndroid Build Coastguard Worker 
ECPOINTPoint2Oct(const EC_POINT * point,uint8_t * buf,size_t len)264*e1997b9aSAndroid Build Coastguard Worker size_t ECPOINTPoint2Oct(const EC_POINT* point, uint8_t* buf, size_t len) {
265*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
266*e1997b9aSAndroid Build Coastguard Worker     point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
267*e1997b9aSAndroid Build Coastguard Worker     auto result = EC_POINT_point2oct(group, point, form, buf, len, nullptr);
268*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP_free(group);
269*e1997b9aSAndroid Build Coastguard Worker     return result;
270*e1997b9aSAndroid Build Coastguard Worker }
271*e1997b9aSAndroid Build Coastguard Worker 
ECPOINTOct2Point(const uint8_t * buf,size_t len)272*e1997b9aSAndroid Build Coastguard Worker EC_POINT* ECPOINTOct2Point(const uint8_t* buf, size_t len) {
273*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
274*e1997b9aSAndroid Build Coastguard Worker     EC_POINT* point = EC_POINT_new(group);
275*e1997b9aSAndroid Build Coastguard Worker     auto result = EC_POINT_oct2point(group, point, buf, len, nullptr);
276*e1997b9aSAndroid Build Coastguard Worker     EC_GROUP_free(group);
277*e1997b9aSAndroid Build Coastguard Worker     if (result == 0) {
278*e1997b9aSAndroid Build Coastguard Worker         EC_POINT_free(point);
279*e1997b9aSAndroid Build Coastguard Worker         return nullptr;
280*e1997b9aSAndroid Build Coastguard Worker     }
281*e1997b9aSAndroid Build Coastguard Worker     return point;
282*e1997b9aSAndroid Build Coastguard Worker }
283*e1997b9aSAndroid Build Coastguard Worker 
extractSubjectFromCertificate(const uint8_t * cert_buf,size_t cert_len,uint8_t * subject_buf,size_t subject_buf_len)284*e1997b9aSAndroid Build Coastguard Worker int extractSubjectFromCertificate(const uint8_t* cert_buf, size_t cert_len, uint8_t* subject_buf,
285*e1997b9aSAndroid Build Coastguard Worker                                   size_t subject_buf_len) {
286*e1997b9aSAndroid Build Coastguard Worker     if (!cert_buf || !subject_buf) {
287*e1997b9aSAndroid Build Coastguard Worker         ALOGE("extractSubjectFromCertificate: received null pointer");
288*e1997b9aSAndroid Build Coastguard Worker         return 0;
289*e1997b9aSAndroid Build Coastguard Worker     }
290*e1997b9aSAndroid Build Coastguard Worker 
291*e1997b9aSAndroid Build Coastguard Worker     const uint8_t* p = cert_buf;
292*e1997b9aSAndroid Build Coastguard Worker     bssl::UniquePtr<X509> cert(d2i_X509(nullptr /* Allocate X509 struct */, &p, cert_len));
293*e1997b9aSAndroid Build Coastguard Worker     if (!cert) {
294*e1997b9aSAndroid Build Coastguard Worker         ALOGE("extractSubjectFromCertificate: failed to parse certificate");
295*e1997b9aSAndroid Build Coastguard Worker         return 0;
296*e1997b9aSAndroid Build Coastguard Worker     }
297*e1997b9aSAndroid Build Coastguard Worker 
298*e1997b9aSAndroid Build Coastguard Worker     X509_NAME* subject = X509_get_subject_name(cert.get());
299*e1997b9aSAndroid Build Coastguard Worker     if (!subject) {
300*e1997b9aSAndroid Build Coastguard Worker         ALOGE("extractSubjectFromCertificate: failed to retrieve subject name");
301*e1997b9aSAndroid Build Coastguard Worker         return 0;
302*e1997b9aSAndroid Build Coastguard Worker     }
303*e1997b9aSAndroid Build Coastguard Worker 
304*e1997b9aSAndroid Build Coastguard Worker     int subject_len = i2d_X509_NAME(subject, nullptr /* Don't copy the data */);
305*e1997b9aSAndroid Build Coastguard Worker     if (subject_len < 0) {
306*e1997b9aSAndroid Build Coastguard Worker         ALOGE("extractSubjectFromCertificate: error obtaining encoded subject name length");
307*e1997b9aSAndroid Build Coastguard Worker         return 0;
308*e1997b9aSAndroid Build Coastguard Worker     }
309*e1997b9aSAndroid Build Coastguard Worker 
310*e1997b9aSAndroid Build Coastguard Worker     if (subject_len > subject_buf_len) {
311*e1997b9aSAndroid Build Coastguard Worker         // Return the subject length, negated, so the caller knows how much
312*e1997b9aSAndroid Build Coastguard Worker         // buffer space is required.
313*e1997b9aSAndroid Build Coastguard Worker         ALOGI("extractSubjectFromCertificate: needed %d bytes for subject, caller provided %zu",
314*e1997b9aSAndroid Build Coastguard Worker               subject_len, subject_buf_len);
315*e1997b9aSAndroid Build Coastguard Worker         return -subject_len;
316*e1997b9aSAndroid Build Coastguard Worker     }
317*e1997b9aSAndroid Build Coastguard Worker 
318*e1997b9aSAndroid Build Coastguard Worker     // subject_buf has enough space.
319*e1997b9aSAndroid Build Coastguard Worker     uint8_t* tmp = subject_buf;
320*e1997b9aSAndroid Build Coastguard Worker     return i2d_X509_NAME(subject, &tmp);
321*e1997b9aSAndroid Build Coastguard Worker }
322