xref: /aosp_15_r20/system/keymaster/km_openssl/certificate_utils.cpp (revision 789431f29546679ab5188a97751fb38e3018d44d)
1*789431f2SAndroid Build Coastguard Worker /*
2*789431f2SAndroid Build Coastguard Worker  * Copyright 2020, The Android Open Source Project
3*789431f2SAndroid Build Coastguard Worker  *
4*789431f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*789431f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*789431f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*789431f2SAndroid Build Coastguard Worker  *
8*789431f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*789431f2SAndroid Build Coastguard Worker  *
10*789431f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*789431f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*789431f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*789431f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*789431f2SAndroid Build Coastguard Worker  * limitations under the License.
15*789431f2SAndroid Build Coastguard Worker  */
16*789431f2SAndroid Build Coastguard Worker 
17*789431f2SAndroid Build Coastguard Worker #include <inttypes.h>
18*789431f2SAndroid Build Coastguard Worker #include <iostream>
19*789431f2SAndroid Build Coastguard Worker #include <utility>
20*789431f2SAndroid Build Coastguard Worker 
21*789431f2SAndroid Build Coastguard Worker #include <openssl/asn1.h>
22*789431f2SAndroid Build Coastguard Worker #include <openssl/evp.h>
23*789431f2SAndroid Build Coastguard Worker #include <openssl/x509v3.h>
24*789431f2SAndroid Build Coastguard Worker 
25*789431f2SAndroid Build Coastguard Worker #include <hardware/keymaster_defs.h>
26*789431f2SAndroid Build Coastguard Worker #include <keymaster/android_keymaster_utils.h>
27*789431f2SAndroid Build Coastguard Worker #include <keymaster/authorization_set.h>
28*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/asymmetric_key.h>
29*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/certificate_utils.h>
30*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_err.h>
31*789431f2SAndroid Build Coastguard Worker #include <keymaster/logger.h>
32*789431f2SAndroid Build Coastguard Worker 
33*789431f2SAndroid Build Coastguard Worker namespace keymaster {
34*789431f2SAndroid Build Coastguard Worker 
35*789431f2SAndroid Build Coastguard Worker namespace {
36*789431f2SAndroid Build Coastguard Worker 
37*789431f2SAndroid Build Coastguard Worker constexpr const char kDefaultSubject[] = "Android Keystore Key";
38*789431f2SAndroid Build Coastguard Worker constexpr int kDataEnciphermentKeyUsageBit = 3;
39*789431f2SAndroid Build Coastguard Worker constexpr int kDigitalSignatureKeyUsageBit = 0;
40*789431f2SAndroid Build Coastguard Worker constexpr int kKeyEnciphermentKeyUsageBit = 2;
41*789431f2SAndroid Build Coastguard Worker constexpr int kKeyAgreementKeyUsageBit = 4;
42*789431f2SAndroid Build Coastguard Worker constexpr int kMaxKeyUsageBit = 8;
43*789431f2SAndroid Build Coastguard Worker 
min(T && a,T && b)44*789431f2SAndroid Build Coastguard Worker template <typename T> T&& min(T&& a, T&& b) {
45*789431f2SAndroid Build Coastguard Worker     return (a < b) ? std::forward<T>(a) : std::forward<T>(b);
46*789431f2SAndroid Build Coastguard Worker }
47*789431f2SAndroid Build Coastguard Worker 
fake_sign_cert(X509 * cert)48*789431f2SAndroid Build Coastguard Worker keymaster_error_t fake_sign_cert(X509* cert) {
49*789431f2SAndroid Build Coastguard Worker     X509_ALGOR_Ptr algor(X509_ALGOR_new());
50*789431f2SAndroid Build Coastguard Worker     if (!algor.get()) {
51*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
52*789431f2SAndroid Build Coastguard Worker     }
53*789431f2SAndroid Build Coastguard Worker     X509_ALGOR_set0(algor.get(), OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL, nullptr);
54*789431f2SAndroid Build Coastguard Worker 
55*789431f2SAndroid Build Coastguard Worker     // Set signature to a bit string containing a single byte, value 0.
56*789431f2SAndroid Build Coastguard Worker     uint8_t fake_sig = 0;
57*789431f2SAndroid Build Coastguard Worker     if (!X509_set1_signature_algo(cert, algor.get()) ||
58*789431f2SAndroid Build Coastguard Worker         !X509_set1_signature_value(cert, &fake_sig, sizeof(fake_sig))) {
59*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
60*789431f2SAndroid Build Coastguard Worker     }
61*789431f2SAndroid Build Coastguard Worker 
62*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
63*789431f2SAndroid Build Coastguard Worker }
64*789431f2SAndroid Build Coastguard Worker 
65*789431f2SAndroid Build Coastguard Worker }  // namespace
66*789431f2SAndroid Build Coastguard Worker 
make_name_from_str(const char name[],X509_NAME_Ptr * name_out)67*789431f2SAndroid Build Coastguard Worker keymaster_error_t make_name_from_str(const char name[], X509_NAME_Ptr* name_out) {
68*789431f2SAndroid Build Coastguard Worker     if (name_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
69*789431f2SAndroid Build Coastguard Worker     X509_NAME_Ptr x509_name(X509_NAME_new());
70*789431f2SAndroid Build Coastguard Worker     if (!x509_name.get()) {
71*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
72*789431f2SAndroid Build Coastguard Worker     }
73*789431f2SAndroid Build Coastguard Worker     if (!X509_NAME_add_entry_by_txt(x509_name.get(),  //
74*789431f2SAndroid Build Coastguard Worker                                     "CN",             //
75*789431f2SAndroid Build Coastguard Worker                                     MBSTRING_ASC, reinterpret_cast<const uint8_t*>(&name[0]),
76*789431f2SAndroid Build Coastguard Worker                                     -1,  // len
77*789431f2SAndroid Build Coastguard Worker                                     -1,  // loc
78*789431f2SAndroid Build Coastguard Worker                                     0 /* set */)) {
79*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
80*789431f2SAndroid Build Coastguard Worker     }
81*789431f2SAndroid Build Coastguard Worker     *name_out = std::move(x509_name);
82*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
83*789431f2SAndroid Build Coastguard Worker }
84*789431f2SAndroid Build Coastguard Worker 
make_name_from_der(const keymaster_blob_t & name,X509_NAME_Ptr * name_out)85*789431f2SAndroid Build Coastguard Worker keymaster_error_t make_name_from_der(const keymaster_blob_t& name, X509_NAME_Ptr* name_out) {
86*789431f2SAndroid Build Coastguard Worker     if (!name_out || !name.data) return KM_ERROR_UNEXPECTED_NULL_POINTER;
87*789431f2SAndroid Build Coastguard Worker 
88*789431f2SAndroid Build Coastguard Worker     const uint8_t* p = name.data;
89*789431f2SAndroid Build Coastguard Worker     X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name.data_length));
90*789431f2SAndroid Build Coastguard Worker     if (!x509_name.get()) {
91*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
92*789431f2SAndroid Build Coastguard Worker     }
93*789431f2SAndroid Build Coastguard Worker 
94*789431f2SAndroid Build Coastguard Worker     *name_out = std::move(x509_name);
95*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
96*789431f2SAndroid Build Coastguard Worker }
97*789431f2SAndroid Build Coastguard Worker 
get_common_name(X509_NAME * name,UniquePtr<const char[]> * name_out)98*789431f2SAndroid Build Coastguard Worker keymaster_error_t get_common_name(X509_NAME* name, UniquePtr<const char[]>* name_out) {
99*789431f2SAndroid Build Coastguard Worker     if (name == nullptr || name_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
100*789431f2SAndroid Build Coastguard Worker     int len = X509_NAME_get_text_by_NID(name, NID_commonName, nullptr, 0);
101*789431f2SAndroid Build Coastguard Worker     UniquePtr<char[]> name_ptr(new (std::nothrow) char[len]);
102*789431f2SAndroid Build Coastguard Worker     if (!name_ptr) {
103*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
104*789431f2SAndroid Build Coastguard Worker     }
105*789431f2SAndroid Build Coastguard Worker     X509_NAME_get_text_by_NID(name, NID_commonName, name_ptr.get(), len);
106*789431f2SAndroid Build Coastguard Worker     *name_out = UniquePtr<const char[]>{name_ptr.release()};
107*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
108*789431f2SAndroid Build Coastguard Worker }
109*789431f2SAndroid Build Coastguard Worker 
get_certificate_params(const AuthorizationSet & caller_params,CertificateCallerParams * cert_params,KmVersion kmVersion)110*789431f2SAndroid Build Coastguard Worker keymaster_error_t get_certificate_params(const AuthorizationSet& caller_params,
111*789431f2SAndroid Build Coastguard Worker                                          CertificateCallerParams* cert_params,
112*789431f2SAndroid Build Coastguard Worker                                          KmVersion kmVersion) {
113*789431f2SAndroid Build Coastguard Worker     if (!cert_params) return KM_ERROR_UNEXPECTED_NULL_POINTER;
114*789431f2SAndroid Build Coastguard Worker 
115*789431f2SAndroid Build Coastguard Worker     BIGNUM_Ptr serial(BN_new());
116*789431f2SAndroid Build Coastguard Worker     if (!serial) {
117*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
118*789431f2SAndroid Build Coastguard Worker     }
119*789431f2SAndroid Build Coastguard Worker 
120*789431f2SAndroid Build Coastguard Worker     keymaster_blob_t serial_blob{.data = nullptr, .data_length = 0};
121*789431f2SAndroid Build Coastguard Worker     if (caller_params.GetTagValue(TAG_CERTIFICATE_SERIAL, &serial_blob)) {
122*789431f2SAndroid Build Coastguard Worker         if (BN_bin2bn(serial_blob.data, serial_blob.data_length, serial.get()) == nullptr) {
123*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
124*789431f2SAndroid Build Coastguard Worker         }
125*789431f2SAndroid Build Coastguard Worker     } else {
126*789431f2SAndroid Build Coastguard Worker         // Default serial is one.
127*789431f2SAndroid Build Coastguard Worker         BN_one(serial.get());
128*789431f2SAndroid Build Coastguard Worker     }
129*789431f2SAndroid Build Coastguard Worker     cert_params->serial = std::move(serial);
130*789431f2SAndroid Build Coastguard Worker 
131*789431f2SAndroid Build Coastguard Worker     cert_params->active_date_time = 0;
132*789431f2SAndroid Build Coastguard Worker     cert_params->expire_date_time = kUndefinedExpirationDateTime;
133*789431f2SAndroid Build Coastguard Worker 
134*789431f2SAndroid Build Coastguard Worker     uint64_t tmp;
135*789431f2SAndroid Build Coastguard Worker     if (kmVersion < KmVersion::KEYMINT_1) {
136*789431f2SAndroid Build Coastguard Worker         if (caller_params.GetTagValue(TAG_ACTIVE_DATETIME, &tmp)) {
137*789431f2SAndroid Build Coastguard Worker             LOG_D("Using TAG_ACTIVE_DATETIME: %" PRIu64, tmp);
138*789431f2SAndroid Build Coastguard Worker             cert_params->active_date_time = static_cast<int64_t>(tmp);
139*789431f2SAndroid Build Coastguard Worker         }
140*789431f2SAndroid Build Coastguard Worker         if (caller_params.GetTagValue(TAG_ORIGINATION_EXPIRE_DATETIME, &tmp)) {
141*789431f2SAndroid Build Coastguard Worker             LOG_D("Using TAG_ORIGINATION_EXPIRE_DATETIME: %" PRIu64, tmp);
142*789431f2SAndroid Build Coastguard Worker             cert_params->expire_date_time = static_cast<int64_t>(tmp);
143*789431f2SAndroid Build Coastguard Worker         }
144*789431f2SAndroid Build Coastguard Worker     } else {
145*789431f2SAndroid Build Coastguard Worker         if (!caller_params.GetTagValue(TAG_CERTIFICATE_NOT_BEFORE, &tmp)) {
146*789431f2SAndroid Build Coastguard Worker             return KM_ERROR_MISSING_NOT_BEFORE;
147*789431f2SAndroid Build Coastguard Worker         }
148*789431f2SAndroid Build Coastguard Worker         LOG_D("Using TAG_CERTIFICATE_NOT_BEFORE: %" PRIu64, tmp);
149*789431f2SAndroid Build Coastguard Worker         cert_params->active_date_time = static_cast<int64_t>(tmp);
150*789431f2SAndroid Build Coastguard Worker 
151*789431f2SAndroid Build Coastguard Worker         if (!caller_params.GetTagValue(TAG_CERTIFICATE_NOT_AFTER, &tmp)) {
152*789431f2SAndroid Build Coastguard Worker             return KM_ERROR_MISSING_NOT_AFTER;
153*789431f2SAndroid Build Coastguard Worker         }
154*789431f2SAndroid Build Coastguard Worker         LOG_D("Using TAG_CERTIFICATE_NOT_AFTER: %" PRIu64, tmp);
155*789431f2SAndroid Build Coastguard Worker         cert_params->expire_date_time = static_cast<int64_t>(tmp);
156*789431f2SAndroid Build Coastguard Worker     }
157*789431f2SAndroid Build Coastguard Worker 
158*789431f2SAndroid Build Coastguard Worker     LOG_D("Got certificate date params:  NotBefore = %" PRId64 ", NotAfter = %" PRId64,
159*789431f2SAndroid Build Coastguard Worker           cert_params->active_date_time, cert_params->expire_date_time);
160*789431f2SAndroid Build Coastguard Worker 
161*789431f2SAndroid Build Coastguard Worker     keymaster_blob_t subject{};
162*789431f2SAndroid Build Coastguard Worker     if (caller_params.GetTagValue(TAG_CERTIFICATE_SUBJECT, &subject) && subject.data_length) {
163*789431f2SAndroid Build Coastguard Worker         return make_name_from_der(subject, &cert_params->subject_name);
164*789431f2SAndroid Build Coastguard Worker     }
165*789431f2SAndroid Build Coastguard Worker 
166*789431f2SAndroid Build Coastguard Worker     return make_name_from_str(kDefaultSubject, &cert_params->subject_name);
167*789431f2SAndroid Build Coastguard Worker }
168*789431f2SAndroid Build Coastguard Worker 
make_key_usage_extension(bool is_signing_key,bool is_encryption_key,bool is_key_agreement_key,X509_EXTENSION_Ptr * usage_extension_out)169*789431f2SAndroid Build Coastguard Worker keymaster_error_t make_key_usage_extension(bool is_signing_key, bool is_encryption_key,
170*789431f2SAndroid Build Coastguard Worker                                            bool is_key_agreement_key,
171*789431f2SAndroid Build Coastguard Worker                                            X509_EXTENSION_Ptr* usage_extension_out) {
172*789431f2SAndroid Build Coastguard Worker     if (usage_extension_out == nullptr) return KM_ERROR_UNEXPECTED_NULL_POINTER;
173*789431f2SAndroid Build Coastguard Worker 
174*789431f2SAndroid Build Coastguard Worker     // Build BIT_STRING with correct contents.
175*789431f2SAndroid Build Coastguard Worker     ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
176*789431f2SAndroid Build Coastguard Worker     if (!key_usage) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
177*789431f2SAndroid Build Coastguard Worker 
178*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
179*789431f2SAndroid Build Coastguard Worker         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
180*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
181*789431f2SAndroid Build Coastguard Worker         }
182*789431f2SAndroid Build Coastguard Worker     }
183*789431f2SAndroid Build Coastguard Worker 
184*789431f2SAndroid Build Coastguard Worker     if (is_signing_key) {
185*789431f2SAndroid Build Coastguard Worker         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
186*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
187*789431f2SAndroid Build Coastguard Worker         }
188*789431f2SAndroid Build Coastguard Worker     }
189*789431f2SAndroid Build Coastguard Worker 
190*789431f2SAndroid Build Coastguard Worker     if (is_encryption_key) {
191*789431f2SAndroid Build Coastguard Worker         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
192*789431f2SAndroid Build Coastguard Worker             !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
193*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
194*789431f2SAndroid Build Coastguard Worker         }
195*789431f2SAndroid Build Coastguard Worker     }
196*789431f2SAndroid Build Coastguard Worker 
197*789431f2SAndroid Build Coastguard Worker     if (is_key_agreement_key) {
198*789431f2SAndroid Build Coastguard Worker         if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyAgreementKeyUsageBit, 1)) {
199*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
200*789431f2SAndroid Build Coastguard Worker         }
201*789431f2SAndroid Build Coastguard Worker     }
202*789431f2SAndroid Build Coastguard Worker 
203*789431f2SAndroid Build Coastguard Worker     // Convert to octets
204*789431f2SAndroid Build Coastguard Worker     int len = i2d_ASN1_BIT_STRING(key_usage.get(), nullptr);
205*789431f2SAndroid Build Coastguard Worker     if (len < 0) {
206*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
207*789431f2SAndroid Build Coastguard Worker     }
208*789431f2SAndroid Build Coastguard Worker     UniquePtr<uint8_t[]> asn1_key_usage(new (std::nothrow) uint8_t[len]);
209*789431f2SAndroid Build Coastguard Worker     if (!asn1_key_usage.get()) {
210*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
211*789431f2SAndroid Build Coastguard Worker     }
212*789431f2SAndroid Build Coastguard Worker     uint8_t* p = asn1_key_usage.get();
213*789431f2SAndroid Build Coastguard Worker     len = i2d_ASN1_BIT_STRING(key_usage.get(), &p);
214*789431f2SAndroid Build Coastguard Worker     if (len < 0) {
215*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
216*789431f2SAndroid Build Coastguard Worker     }
217*789431f2SAndroid Build Coastguard Worker 
218*789431f2SAndroid Build Coastguard Worker     // Build OCTET_STRING
219*789431f2SAndroid Build Coastguard Worker     ASN1_OCTET_STRING_Ptr key_usage_str(ASN1_OCTET_STRING_new());
220*789431f2SAndroid Build Coastguard Worker     if (!key_usage_str.get() ||
221*789431f2SAndroid Build Coastguard Worker         !ASN1_OCTET_STRING_set(key_usage_str.get(), asn1_key_usage.get(), len)) {
222*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
223*789431f2SAndroid Build Coastguard Worker     }
224*789431f2SAndroid Build Coastguard Worker 
225*789431f2SAndroid Build Coastguard Worker     X509_EXTENSION_Ptr key_usage_extension(X509_EXTENSION_create_by_NID(nullptr,        //
226*789431f2SAndroid Build Coastguard Worker                                                                         NID_key_usage,  //
227*789431f2SAndroid Build Coastguard Worker                                                                         true /* critical */,
228*789431f2SAndroid Build Coastguard Worker                                                                         key_usage_str.get()));
229*789431f2SAndroid Build Coastguard Worker     if (!key_usage_extension.get()) {
230*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
231*789431f2SAndroid Build Coastguard Worker     }
232*789431f2SAndroid Build Coastguard Worker 
233*789431f2SAndroid Build Coastguard Worker     *usage_extension_out = std::move(key_usage_extension);
234*789431f2SAndroid Build Coastguard Worker 
235*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
236*789431f2SAndroid Build Coastguard Worker }
237*789431f2SAndroid Build Coastguard Worker 
238*789431f2SAndroid Build Coastguard Worker // Creates a rump certificate structure with serial, subject and issuer names, as well as
239*789431f2SAndroid Build Coastguard Worker // activation and expiry date.
240*789431f2SAndroid Build Coastguard Worker // Callers should pass an empty X509_Ptr and check the return value for KM_ERROR_OK (0) before
241*789431f2SAndroid Build Coastguard Worker // accessing the result.
make_cert_rump(const X509_NAME * issuer,const CertificateCallerParams & cert_params,X509_Ptr * cert_out)242*789431f2SAndroid Build Coastguard Worker keymaster_error_t make_cert_rump(const X509_NAME* issuer,
243*789431f2SAndroid Build Coastguard Worker                                  const CertificateCallerParams& cert_params, X509_Ptr* cert_out) {
244*789431f2SAndroid Build Coastguard Worker     if (!cert_out || !issuer) return KM_ERROR_UNEXPECTED_NULL_POINTER;
245*789431f2SAndroid Build Coastguard Worker 
246*789431f2SAndroid Build Coastguard Worker     // Create certificate structure.
247*789431f2SAndroid Build Coastguard Worker     X509_Ptr certificate(X509_new());
248*789431f2SAndroid Build Coastguard Worker     if (!certificate.get()) return TranslateLastOpenSslError();
249*789431f2SAndroid Build Coastguard Worker 
250*789431f2SAndroid Build Coastguard Worker     // Set the X509 version.
251*789431f2SAndroid Build Coastguard Worker     if (!X509_set_version(certificate.get(), 2 /* version 3 */)) return TranslateLastOpenSslError();
252*789431f2SAndroid Build Coastguard Worker 
253*789431f2SAndroid Build Coastguard Worker     // Set the certificate serialNumber
254*789431f2SAndroid Build Coastguard Worker     ASN1_INTEGER_Ptr serial_number(ASN1_INTEGER_new());
255*789431f2SAndroid Build Coastguard Worker     if (!serial_number.get() ||  //
256*789431f2SAndroid Build Coastguard Worker         !BN_to_ASN1_INTEGER(cert_params.serial.get(), serial_number.get()) ||
257*789431f2SAndroid Build Coastguard Worker         !X509_set_serialNumber(certificate.get(),
258*789431f2SAndroid Build Coastguard Worker                                serial_number.get() /* Don't release; copied */)) {
259*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
260*789431f2SAndroid Build Coastguard Worker     }
261*789431f2SAndroid Build Coastguard Worker 
262*789431f2SAndroid Build Coastguard Worker     if (!X509_set_subject_name(certificate.get(),
263*789431f2SAndroid Build Coastguard Worker                                const_cast<X509_NAME*>(cert_params.subject_name.get()))) {
264*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
265*789431f2SAndroid Build Coastguard Worker     }
266*789431f2SAndroid Build Coastguard Worker 
267*789431f2SAndroid Build Coastguard Worker     if (!X509_set_issuer_name(certificate.get(), const_cast<X509_NAME*>(issuer))) {
268*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
269*789431f2SAndroid Build Coastguard Worker     }
270*789431f2SAndroid Build Coastguard Worker 
271*789431f2SAndroid Build Coastguard Worker     // Set activation date.
272*789431f2SAndroid Build Coastguard Worker     ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
273*789431f2SAndroid Build Coastguard Worker     LOG_D("Setting notBefore to %" PRId64, cert_params.active_date_time / 1000);
274*789431f2SAndroid Build Coastguard Worker     int64_t notBeforeTime = cert_params.active_date_time / 1000;
275*789431f2SAndroid Build Coastguard Worker     if (!notBefore.get() || !ASN1_TIME_set_posix(notBefore.get(), notBeforeTime) ||
276*789431f2SAndroid Build Coastguard Worker         !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */)) {
277*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
278*789431f2SAndroid Build Coastguard Worker     }
279*789431f2SAndroid Build Coastguard Worker 
280*789431f2SAndroid Build Coastguard Worker     // Set expiration date.
281*789431f2SAndroid Build Coastguard Worker     ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
282*789431f2SAndroid Build Coastguard Worker     LOG_D("Setting notAfter to %" PRId64, cert_params.expire_date_time / 1000);
283*789431f2SAndroid Build Coastguard Worker     int64_t notAfterTime = cert_params.expire_date_time / 1000;
284*789431f2SAndroid Build Coastguard Worker 
285*789431f2SAndroid Build Coastguard Worker     if (!notAfter.get() || !ASN1_TIME_set_posix(notAfter.get(), notAfterTime) ||
286*789431f2SAndroid Build Coastguard Worker         !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
287*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
288*789431f2SAndroid Build Coastguard Worker     }
289*789431f2SAndroid Build Coastguard Worker 
290*789431f2SAndroid Build Coastguard Worker     *cert_out = std::move(certificate);
291*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
292*789431f2SAndroid Build Coastguard Worker }
293*789431f2SAndroid Build Coastguard Worker 
make_cert(const EVP_PKEY * evp_pkey,const X509_NAME * issuer,const CertificateCallerParams & cert_params,X509_Ptr * cert_out)294*789431f2SAndroid Build Coastguard Worker keymaster_error_t make_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer,
295*789431f2SAndroid Build Coastguard Worker                             const CertificateCallerParams& cert_params, X509_Ptr* cert_out) {
296*789431f2SAndroid Build Coastguard Worker 
297*789431f2SAndroid Build Coastguard Worker     // Make the rump certificate with serial, subject, not before and not after dates.
298*789431f2SAndroid Build Coastguard Worker     X509_Ptr certificate;
299*789431f2SAndroid Build Coastguard Worker     if (keymaster_error_t error = make_cert_rump(issuer, cert_params, &certificate)) {
300*789431f2SAndroid Build Coastguard Worker         return error;
301*789431f2SAndroid Build Coastguard Worker     }
302*789431f2SAndroid Build Coastguard Worker 
303*789431f2SAndroid Build Coastguard Worker     // Set the public key.
304*789431f2SAndroid Build Coastguard Worker     if (!X509_set_pubkey(certificate.get(), (EVP_PKEY*)evp_pkey)) {
305*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
306*789431f2SAndroid Build Coastguard Worker     }
307*789431f2SAndroid Build Coastguard Worker 
308*789431f2SAndroid Build Coastguard Worker     // Make and add the key usage extension.
309*789431f2SAndroid Build Coastguard Worker     X509_EXTENSION_Ptr key_usage_extension;
310*789431f2SAndroid Build Coastguard Worker     if (auto error =
311*789431f2SAndroid Build Coastguard Worker             make_key_usage_extension(cert_params.is_signing_key, cert_params.is_encryption_key,
312*789431f2SAndroid Build Coastguard Worker                                      cert_params.is_agreement_key, &key_usage_extension)) {
313*789431f2SAndroid Build Coastguard Worker         return error;
314*789431f2SAndroid Build Coastguard Worker     }
315*789431f2SAndroid Build Coastguard Worker     if (!X509_add_ext(certificate.get(), key_usage_extension.get() /* Don't release; copied */,
316*789431f2SAndroid Build Coastguard Worker                       -1 /* insert at end */)) {
317*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
318*789431f2SAndroid Build Coastguard Worker     }
319*789431f2SAndroid Build Coastguard Worker 
320*789431f2SAndroid Build Coastguard Worker     *cert_out = std::move(certificate);
321*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
322*789431f2SAndroid Build Coastguard Worker }
323*789431f2SAndroid Build Coastguard Worker 
sign_cert(X509 * certificate,const EVP_PKEY * signing_key)324*789431f2SAndroid Build Coastguard Worker keymaster_error_t sign_cert(X509* certificate, const EVP_PKEY* signing_key) {
325*789431f2SAndroid Build Coastguard Worker     if (!certificate || !signing_key) return KM_ERROR_UNEXPECTED_NULL_POINTER;
326*789431f2SAndroid Build Coastguard Worker 
327*789431f2SAndroid Build Coastguard Worker     // X509_sign takes the key as non-const, but per the BoringSSL dev team, that's a legacy
328*789431f2SAndroid Build Coastguard Worker     // mistake that hasn't yet been corrected.
329*789431f2SAndroid Build Coastguard Worker     auto sk = const_cast<EVP_PKEY*>(signing_key);
330*789431f2SAndroid Build Coastguard Worker 
331*789431f2SAndroid Build Coastguard Worker     // Ed25519 has an internal digest so needs to have no digest fed into X509_sign.
332*789431f2SAndroid Build Coastguard Worker     const EVP_MD* digest = (EVP_PKEY_id(signing_key) == EVP_PKEY_ED25519) ? nullptr : EVP_sha256();
333*789431f2SAndroid Build Coastguard Worker 
334*789431f2SAndroid Build Coastguard Worker     if (!X509_sign(certificate, sk, digest)) {
335*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
336*789431f2SAndroid Build Coastguard Worker     }
337*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
338*789431f2SAndroid Build Coastguard Worker }
339*789431f2SAndroid Build Coastguard Worker 
generate_self_signed_cert(const AsymmetricKey & key,const AuthorizationSet & params,bool fake_signature,keymaster_error_t * error)340*789431f2SAndroid Build Coastguard Worker CertificateChain generate_self_signed_cert(const AsymmetricKey& key, const AuthorizationSet& params,
341*789431f2SAndroid Build Coastguard Worker                                            bool fake_signature, keymaster_error_t* error) {
342*789431f2SAndroid Build Coastguard Worker     keymaster_error_t err;
343*789431f2SAndroid Build Coastguard Worker     if (!error) error = &err;
344*789431f2SAndroid Build Coastguard Worker 
345*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_Ptr pkey(key.InternalToEvp());
346*789431f2SAndroid Build Coastguard Worker     if (pkey.get() == nullptr) {
347*789431f2SAndroid Build Coastguard Worker         *error = TranslateLastOpenSslError();
348*789431f2SAndroid Build Coastguard Worker         return {};
349*789431f2SAndroid Build Coastguard Worker     }
350*789431f2SAndroid Build Coastguard Worker 
351*789431f2SAndroid Build Coastguard Worker     CertificateCallerParams cert_params{};
352*789431f2SAndroid Build Coastguard Worker     // Self signed certificates are only generated since Keymint 1.0. To keep the API stable for
353*789431f2SAndroid Build Coastguard Worker     // now, we pass KEYMINT_1 to get_certificate_params, which has the intended effect. If
354*789431f2SAndroid Build Coastguard Worker     // get_certificate_params ever has to distinguish between versions of KeyMint this needs to be
355*789431f2SAndroid Build Coastguard Worker     // changed.
356*789431f2SAndroid Build Coastguard Worker     *error = get_certificate_params(params, &cert_params, KmVersion::KEYMINT_1);
357*789431f2SAndroid Build Coastguard Worker     if (*error != KM_ERROR_OK) return {};
358*789431f2SAndroid Build Coastguard Worker 
359*789431f2SAndroid Build Coastguard Worker     cert_params.is_signing_key =
360*789431f2SAndroid Build Coastguard Worker         (key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) ||
361*789431f2SAndroid Build Coastguard Worker          key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY));
362*789431f2SAndroid Build Coastguard Worker     cert_params.is_encryption_key = key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
363*789431f2SAndroid Build Coastguard Worker     cert_params.is_agreement_key = key.authorizations().Contains(TAG_PURPOSE, KM_PURPOSE_AGREE_KEY);
364*789431f2SAndroid Build Coastguard Worker 
365*789431f2SAndroid Build Coastguard Worker     X509_Ptr cert;
366*789431f2SAndroid Build Coastguard Worker     *error = make_cert(pkey.get(), cert_params.subject_name.get() /* issuer */, cert_params, &cert);
367*789431f2SAndroid Build Coastguard Worker     if (*error != KM_ERROR_OK) return {};
368*789431f2SAndroid Build Coastguard Worker 
369*789431f2SAndroid Build Coastguard Worker     if (fake_signature) {
370*789431f2SAndroid Build Coastguard Worker         *error = fake_sign_cert(cert.get());
371*789431f2SAndroid Build Coastguard Worker     } else {
372*789431f2SAndroid Build Coastguard Worker         *error = sign_cert(cert.get(), pkey.get());
373*789431f2SAndroid Build Coastguard Worker     }
374*789431f2SAndroid Build Coastguard Worker     if (*error != KM_ERROR_OK) return {};
375*789431f2SAndroid Build Coastguard Worker 
376*789431f2SAndroid Build Coastguard Worker     CertificateChain result(1);
377*789431f2SAndroid Build Coastguard Worker     if (!result) {
378*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
379*789431f2SAndroid Build Coastguard Worker         return {};
380*789431f2SAndroid Build Coastguard Worker     }
381*789431f2SAndroid Build Coastguard Worker 
382*789431f2SAndroid Build Coastguard Worker     *error = encode_certificate(cert.get(), &result.entries[0]);
383*789431f2SAndroid Build Coastguard Worker     if (*error != KM_ERROR_OK) return {};
384*789431f2SAndroid Build Coastguard Worker 
385*789431f2SAndroid Build Coastguard Worker     return result;
386*789431f2SAndroid Build Coastguard Worker }
387*789431f2SAndroid Build Coastguard Worker 
encode_certificate(X509 * certificate,keymaster_blob_t * blob)388*789431f2SAndroid Build Coastguard Worker keymaster_error_t encode_certificate(X509* certificate, keymaster_blob_t* blob) {
389*789431f2SAndroid Build Coastguard Worker     int len = i2d_X509(certificate, nullptr /* ppout */);
390*789431f2SAndroid Build Coastguard Worker     if (len < 0) return TranslateLastOpenSslError();
391*789431f2SAndroid Build Coastguard Worker 
392*789431f2SAndroid Build Coastguard Worker     blob->data = new (std::nothrow) uint8_t[len];
393*789431f2SAndroid Build Coastguard Worker     if (!blob->data) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
394*789431f2SAndroid Build Coastguard Worker 
395*789431f2SAndroid Build Coastguard Worker     uint8_t* p = const_cast<uint8_t*>(blob->data);
396*789431f2SAndroid Build Coastguard Worker     blob->data_length = i2d_X509(certificate, &p);
397*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
398*789431f2SAndroid Build Coastguard Worker }
399*789431f2SAndroid Build Coastguard Worker 
400*789431f2SAndroid Build Coastguard Worker }  // namespace keymaster
401