1 /*
2 * Copyright (C) 2020 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 "CertUtils.h"
18
19 #include <android-base/logging.h>
20 #include <android-base/result.h>
21
22 #include <openssl/bn.h>
23 #include <openssl/crypto.h>
24 #include <openssl/rsa.h>
25 #include <openssl/x509.h>
26 #include <openssl/x509v3.h>
27
28 #include <vector>
29
30 #include "KeyConstants.h"
31
32 // Common properties for all of our certificates.
33 constexpr int kCertLifetimeSeconds = 10 * 365 * 24 * 60 * 60;
34 const char* const kIssuerCountry = "US";
35 const char* const kIssuerOrg = "Android";
36
37 using android::base::ErrnoError;
38 using android::base::Error;
39 using android::base::Result;
40
loadX509(const std::string & path)41 static Result<bssl::UniquePtr<X509>> loadX509(const std::string& path) {
42 X509* rawCert;
43 auto f = fopen(path.c_str(), "re");
44 if (f == nullptr) {
45 return Error() << "Failed to open " << path;
46 }
47 if (!d2i_X509_fp(f, &rawCert)) {
48 fclose(f);
49 return Error() << "Unable to decode x509 cert at " << path;
50 }
51 bssl::UniquePtr<X509> cert(rawCert);
52
53 fclose(f);
54 return cert;
55 }
56
add_ext(X509V3_CTX * context,X509 * cert,int nid,const char * value)57 static bool add_ext(X509V3_CTX* context, X509* cert, int nid, const char* value) {
58 bssl::UniquePtr<X509_EXTENSION> ex(X509V3_EXT_nconf_nid(nullptr, context, nid, value));
59 if (!ex) {
60 return false;
61 }
62
63 X509_add_ext(cert, ex.get(), -1);
64 return true;
65 }
66
addNameEntry(X509_NAME * name,const char * field,const char * value)67 static void addNameEntry(X509_NAME* name, const char* field, const char* value) {
68 X509_NAME_add_entry_by_txt(name, field, MBSTRING_ASC,
69 reinterpret_cast<const unsigned char*>(value), -1, -1, 0);
70 }
71
getRsaFromModulus(const std::vector<uint8_t> & publicKey)72 static Result<bssl::UniquePtr<RSA>> getRsaFromModulus(const std::vector<uint8_t>& publicKey) {
73 bssl::UniquePtr<BIGNUM> n(BN_new());
74 bssl::UniquePtr<BIGNUM> e(BN_new());
75 bssl::UniquePtr<RSA> rsaPubkey(RSA_new());
76 if (!n || !e || !rsaPubkey || !BN_bin2bn(publicKey.data(), publicKey.size(), n.get()) ||
77 !BN_set_word(e.get(), kRsaKeyExponent) ||
78 !RSA_set0_key(rsaPubkey.get(), n.get(), e.get(), /*d=*/nullptr)) {
79 return Error() << "Failed to create RSA key";
80 }
81 // RSA_set0_key takes ownership of |n| and |e| on success.
82 (void)n.release();
83 (void)e.release();
84
85 return rsaPubkey;
86 }
87
modulusToRsaPkey(const std::vector<uint8_t> & publicKey)88 static Result<bssl::UniquePtr<EVP_PKEY>> modulusToRsaPkey(const std::vector<uint8_t>& publicKey) {
89 // "publicKey" corresponds to the raw public key bytes - need to create
90 // a new RSA key with the correct exponent.
91 auto rsaPubkey = getRsaFromModulus(publicKey);
92 if (!rsaPubkey.ok()) {
93 return rsaPubkey.error();
94 }
95
96 bssl::UniquePtr<EVP_PKEY> public_key(EVP_PKEY_new());
97 if (!EVP_PKEY_assign_RSA(public_key.get(), rsaPubkey->release())) {
98 return Error() << "Failed to assign key";
99 }
100 return public_key;
101 }
102
verifySignature(const std::string & message,const std::string & signature,const std::vector<uint8_t> & publicKey)103 Result<void> verifySignature(const std::string& message, const std::string& signature,
104 const std::vector<uint8_t>& publicKey) {
105 auto rsaKey = getRsaFromModulus(publicKey);
106 if (!rsaKey.ok()) {
107 return rsaKey.error();
108 }
109 uint8_t hashBuf[SHA256_DIGEST_LENGTH];
110 SHA256(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(message.c_str())),
111 message.length(), hashBuf);
112
113 bool success = RSA_verify(NID_sha256, hashBuf, sizeof(hashBuf),
114 (const uint8_t*)signature.c_str(), signature.length(), rsaKey->get());
115
116 if (!success) {
117 return Error() << "Failed to verify signature";
118 }
119 return {};
120 }
121
createSelfSignedCertificate(const std::vector<uint8_t> & publicKey,const std::function<Result<std::string> (const std::string &)> & signFunction,const std::string & path)122 Result<void> createSelfSignedCertificate(
123 const std::vector<uint8_t>& publicKey,
124 const std::function<Result<std::string>(const std::string&)>& signFunction,
125 const std::string& path) {
126 auto rsa_pkey = modulusToRsaPkey(publicKey);
127 if (!rsa_pkey.ok()) {
128 return rsa_pkey.error();
129 }
130 bssl::UniquePtr<X509> x509(X509_new());
131 if (!x509) {
132 return Error() << "Unable to allocate x509 container";
133 }
134 X509_set_version(x509.get(), 2);
135 X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
136 X509_gmtime_adj(X509_get_notAfter(x509.get()), kCertLifetimeSeconds);
137 ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), kRootSubject.serialNumber);
138
139 bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
140 if (!algor ||
141 !X509_ALGOR_set0(algor.get(), OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL,
142 NULL) ||
143 !X509_set1_signature_algo(x509.get(), algor.get())) {
144 return Error() << "Unable to set x509 signature algorithm";
145 }
146
147 if (!X509_set_pubkey(x509.get(), rsa_pkey.value().get())) {
148 return Error() << "Unable to set x509 public key";
149 }
150
151 X509_NAME* subjectName = X509_get_subject_name(x509.get());
152 if (!subjectName) {
153 return Error() << "Unable to get x509 subject name";
154 }
155 addNameEntry(subjectName, "C", kIssuerCountry);
156 addNameEntry(subjectName, "O", kIssuerOrg);
157 addNameEntry(subjectName, "CN", kRootSubject.commonName);
158 if (!X509_set_issuer_name(x509.get(), subjectName)) {
159 return Error() << "Unable to set x509 issuer name";
160 }
161
162 X509V3_CTX context = {};
163 X509V3_set_ctx(&context, x509.get(), x509.get(), nullptr, nullptr, 0);
164 add_ext(&context, x509.get(), NID_basic_constraints, "CA:TRUE");
165 add_ext(&context, x509.get(), NID_key_usage, "critical,keyCertSign,cRLSign,digitalSignature");
166 add_ext(&context, x509.get(), NID_subject_key_identifier, "hash");
167 add_ext(&context, x509.get(), NID_authority_key_identifier, "keyid:always");
168
169 // Get the data to be signed
170 unsigned char* to_be_signed_buf(nullptr);
171 size_t to_be_signed_length = i2d_re_X509_tbs(x509.get(), &to_be_signed_buf);
172
173 auto signed_data = signFunction(
174 std::string(reinterpret_cast<const char*>(to_be_signed_buf), to_be_signed_length));
175 if (!signed_data.ok()) {
176 return signed_data.error();
177 }
178
179 if (!X509_set1_signature_value(x509.get(),
180 reinterpret_cast<const uint8_t*>(signed_data->data()),
181 signed_data->size())) {
182 return Error() << "Unable to set x509 signature";
183 }
184
185 auto f = fopen(path.c_str(), "wbe");
186 if (f == nullptr) {
187 return ErrnoError() << "Failed to open " << path;
188 }
189 i2d_X509_fp(f, x509.get());
190 if (fclose(f) != 0) {
191 return ErrnoError() << "Failed to close " << path;
192 }
193
194 return {};
195 }
196
extractPublicKey(EVP_PKEY * pkey)197 static Result<std::vector<uint8_t>> extractPublicKey(EVP_PKEY* pkey) {
198 if (pkey == nullptr) {
199 return Error() << "Failed to extract public key from x509 cert";
200 }
201
202 if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
203 return Error() << "The public key is not an RSA key";
204 }
205
206 RSA* rsa = EVP_PKEY_get0_RSA(pkey);
207 auto num_bytes = BN_num_bytes(RSA_get0_n(rsa));
208 std::vector<uint8_t> pubKey(num_bytes);
209 int res = BN_bn2bin(RSA_get0_n(rsa), pubKey.data());
210
211 if (!res) {
212 return Error() << "Failed to convert public key to bytes";
213 }
214
215 return pubKey;
216 }
217
extractPublicKeyFromX509(const std::vector<uint8_t> & derCert)218 Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::vector<uint8_t>& derCert) {
219 auto derCertBytes = derCert.data();
220 bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &derCertBytes, derCert.size()));
221 if (decoded_cert.get() == nullptr) {
222 return Error() << "Failed to decode X509 certificate.";
223 }
224 bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
225
226 return extractPublicKey(decoded_pkey.get());
227 }
228
extractPublicKeyFromX509(const std::string & path)229 Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path) {
230 auto cert = loadX509(path);
231 if (!cert.ok()) {
232 return cert.error();
233 }
234 return extractPublicKey(X509_get_pubkey(cert.value().get()));
235 }
236