• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 2017, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include <openssl/evp.h>
19 #include <openssl/x509v3.h>
20 
21 #include <hardware/keymaster_defs.h>
22 
23 #include <keymaster/authorization_set.h>
24 #include <keymaster/km_openssl/asymmetric_key.h>
25 #include <keymaster/km_openssl/attestation_record.h>
26 #include <keymaster/km_openssl/attestation_utils.h>
27 #include <keymaster/km_openssl/certificate_utils.h>
28 #include <keymaster/km_openssl/openssl_err.h>
29 #include <keymaster/km_openssl/openssl_utils.h>
30 
31 namespace keymaster {
32 
33 namespace {
34 
make_cert_chain(X509 * certificate,CertificateChain chain,keymaster_error_t * error)35 CertificateChain make_cert_chain(X509* certificate, CertificateChain chain,
36                                  keymaster_error_t* error) {
37     keymaster_blob_t blob{};
38     *error = encode_certificate(certificate, &blob);
39     if (*error != KM_ERROR_OK) return {};
40 
41     if (!chain.push_front(blob)) {
42         *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
43         return {};
44     }
45     return chain;
46 }
47 
build_attestation_extension(const AuthorizationSet & attest_params,const AuthorizationSet & tee_enforced,const AuthorizationSet & sw_enforced,const AttestationContext & context,X509_EXTENSION_Ptr * extension)48 keymaster_error_t build_attestation_extension(const AuthorizationSet& attest_params,
49                                               const AuthorizationSet& tee_enforced,
50                                               const AuthorizationSet& sw_enforced,
51                                               const AttestationContext& context,
52                                               X509_EXTENSION_Ptr* extension) {
53     ASN1_OBJECT_Ptr oid(
54         OBJ_txt2obj(kAsn1TokenOid, 1 /* accept numerical dotted string form only */));
55     if (!oid.get()) return TranslateLastOpenSslError();
56 
57     UniquePtr<uint8_t[]> attest_bytes;
58     size_t attest_bytes_len;
59     keymaster_error_t error = build_attestation_record(attest_params, sw_enforced, tee_enforced,
60                                                        context, &attest_bytes, &attest_bytes_len);
61     if (error != KM_ERROR_OK) return error;
62 
63     ASN1_OCTET_STRING_Ptr attest_str(ASN1_OCTET_STRING_new());
64     if (!attest_str.get() ||
65         !ASN1_OCTET_STRING_set(attest_str.get(), attest_bytes.get(), attest_bytes_len)) {
66         return TranslateLastOpenSslError();
67     }
68 
69     extension->reset(
70         X509_EXTENSION_create_by_OBJ(nullptr, oid.get(), 0 /* not critical */, attest_str.get()));
71     if (!extension->get()) {
72         return TranslateLastOpenSslError();
73     }
74 
75     return KM_ERROR_OK;
76 }
77 
78 #ifdef KEYMINT_EAT_EXTENSION_SUPPORT
build_eat_extension(const AuthorizationSet & attest_params,const AuthorizationSet & tee_enforced,const AuthorizationSet & sw_enforced,const AttestationContext & context,X509_EXTENSION_Ptr * extension)79 keymaster_error_t build_eat_extension(const AuthorizationSet& attest_params,
80                                       const AuthorizationSet& tee_enforced,
81                                       const AuthorizationSet& sw_enforced,
82                                       const AttestationContext& context,  //
83                                       X509_EXTENSION_Ptr* extension) {
84     ASN1_OBJECT_Ptr oid(
85         OBJ_txt2obj(kEatTokenOid, 1 /* accept numerical dotted string form only */));
86     if (!oid.get()) {
87         return TranslateLastOpenSslError();
88     }
89 
90     std::vector<uint8_t> eat_bytes;
91     keymaster_error_t error =
92         build_eat_record(attest_params, sw_enforced, tee_enforced, context, &eat_bytes);
93     if (error != KM_ERROR_OK) return error;
94 
95     ASN1_OCTET_STRING_Ptr eat_str(ASN1_OCTET_STRING_new());
96     if (!eat_str.get() ||
97         !ASN1_OCTET_STRING_set(eat_str.get(), eat_bytes.data(), eat_bytes.size())) {
98         return TranslateLastOpenSslError();
99     }
100 
101     extension->reset(
102         X509_EXTENSION_create_by_OBJ(nullptr, oid.get(), 0 /* not critical */, eat_str.get()));
103     if (!extension->get()) {
104         return TranslateLastOpenSslError();
105     }
106 
107     return KM_ERROR_OK;
108 }
109 #endif
110 
add_attestation_extension(const AuthorizationSet & attest_params,const AuthorizationSet & tee_enforced,const AuthorizationSet & sw_enforced,const AttestationContext & context,X509 * certificate)111 keymaster_error_t add_attestation_extension(const AuthorizationSet& attest_params,
112                                             const AuthorizationSet& tee_enforced,
113                                             const AuthorizationSet& sw_enforced,
114                                             const AttestationContext& context,  //
115                                             X509* certificate) {
116     X509_EXTENSION_Ptr attest_extension;
117     if (auto error = build_attestation_extension(attest_params, tee_enforced, sw_enforced, context,
118                                                  &attest_extension)) {
119         return error;
120     }
121 
122     if (!X509_add_ext(certificate, attest_extension.get() /* Don't release; copied */,
123                       -1 /* insert at end */)) {
124         return TranslateLastOpenSslError();
125     }
126 
127     return KM_ERROR_OK;
128 }
129 
make_attestation_cert(const EVP_PKEY * evp_pkey,const X509_NAME * issuer,const CertificateCallerParams & cert_params,const AuthorizationSet & attest_params,const AuthorizationSet & tee_enforced,const AuthorizationSet & sw_enforced,const AttestationContext & context,X509_Ptr * cert_out)130 keymaster_error_t make_attestation_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer,
131                                         const CertificateCallerParams& cert_params,
132                                         const AuthorizationSet& attest_params,
133                                         const AuthorizationSet& tee_enforced,
134                                         const AuthorizationSet& sw_enforced,
135                                         const AttestationContext& context, X509_Ptr* cert_out) {
136 
137     // First make the basic certificate with usage extension.
138     X509_Ptr certificate;
139     if (auto error = make_cert(evp_pkey, issuer, cert_params, &certificate)) {
140         return error;
141     }
142 
143     // Add attestation extension.
144     if (auto error = add_attestation_extension(attest_params, tee_enforced, sw_enforced, context,
145                                                certificate.get())) {
146         return error;
147     }
148 
149     *cert_out = move(certificate);
150     return KM_ERROR_OK;
151 }
152 
get_issuer_subject(const AttestKeyInfo & attest_key,keymaster_error_t * error)153 X509_NAME_Ptr get_issuer_subject(const AttestKeyInfo& attest_key, keymaster_error_t* error) {
154     // Use subject from attest_key.
155     const uint8_t* p = attest_key.issuer_subject->data;
156     if (!p || !attest_key.issuer_subject->data_length) {
157         *error = KM_ERROR_MISSING_ISSUER_SUBJECT;
158         return {};
159     }
160     X509_NAME_Ptr retval(d2i_X509_NAME(nullptr /* Allocate X509_NAME */, &p,
161                                        attest_key.issuer_subject->data_length));
162     if (!retval) *error = KM_ERROR_INVALID_ISSUER_SUBJECT;
163     return retval;
164 }
165 
get_issuer_subject(const keymaster_blob_t & signing_cert_der,keymaster_error_t * error)166 X509_NAME_Ptr get_issuer_subject(const keymaster_blob_t& signing_cert_der,
167                                  keymaster_error_t* error) {
168     const uint8_t* p = signing_cert_der.data;
169     if (!p) {
170         *error = KM_ERROR_UNEXPECTED_NULL_POINTER;
171         return {};
172     }
173     X509_Ptr signing_cert(d2i_X509(nullptr /* Allocate X509 */, &p, signing_cert_der.data_length));
174     if (!signing_cert) {
175         *error = TranslateLastOpenSslError();
176         return {};
177     }
178 
179     X509_NAME* issuer_subject = X509_get_subject_name(signing_cert.get());
180     if (!issuer_subject) {
181         *error = TranslateLastOpenSslError();
182         return {};
183     }
184 
185     X509_NAME_Ptr retval(X509_NAME_dup(issuer_subject));
186     if (!retval) *error = TranslateLastOpenSslError();
187 
188     return retval;
189 }
190 
191 // Return subject from attest_key, if non-null, otherwise extract from cert_chain.
get_issuer_subject(const AttestKeyInfo & attest_key,const CertificateChain & cert_chain,keymaster_error_t * error)192 X509_NAME_Ptr get_issuer_subject(const AttestKeyInfo& attest_key,
193                                  const CertificateChain& cert_chain, keymaster_error_t* error) {
194     if (attest_key) {
195         return get_issuer_subject(attest_key, error);
196     }
197 
198     // Need to extract issuer from cert chain.  First cert in the chain is the signing key cert.
199     if (cert_chain.entry_count >= 1) return get_issuer_subject(cert_chain.entries[0], error);
200 
201     *error = KM_ERROR_UNKNOWN_ERROR;
202     return {};
203 }
204 
check_attest_key_auths(const Key & key)205 keymaster_error_t check_attest_key_auths(const Key& key) {
206     auto auths = key.authorizations();
207 
208     if (!auths.Contains(TAG_ALGORITHM, KM_ALGORITHM_RSA) &&
209         !auths.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC)) {
210         return KM_ERROR_INCOMPATIBLE_ALGORITHM;
211     }
212     if (!auths.Contains(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY)) {
213         return KM_ERROR_INCOMPATIBLE_PURPOSE;
214     }
215     return KM_ERROR_OK;
216 }
217 
get_attestation_key(keymaster_algorithm_t algorithm,const AttestationContext & context,keymaster_error_t * error)218 EVP_PKEY_Ptr get_attestation_key(keymaster_algorithm_t algorithm, const AttestationContext& context,
219                                  keymaster_error_t* error) {
220     KeymasterKeyBlob signing_key_blob = context.GetAttestationKey(algorithm, error);
221     if (*error != KM_ERROR_OK) return {};
222 
223     const uint8_t* p = signing_key_blob.key_material;
224     EVP_PKEY_Ptr retval(
225         d2i_AutoPrivateKey(nullptr /* Allocate key */, &p, signing_key_blob.key_material_size));
226     if (!retval) *error = TranslateLastOpenSslError();
227     return retval;
228 }
229 
230 }  // namespace
231 
AttestKeyInfo(const UniquePtr<Key> & key,const KeymasterBlob * issuer_subject_,keymaster_error_t * error)232 AttestKeyInfo::AttestKeyInfo(const UniquePtr<Key>& key, const KeymasterBlob* issuer_subject_,
233                              keymaster_error_t* error)
234     : issuer_subject(issuer_subject_) {
235     if (!error) return;
236 
237     if (!key) {
238         // No key... so this is just an empty AttestKeyInfo.
239         issuer_subject = nullptr;
240         return;
241     }
242 
243     if (!issuer_subject) {
244         *error = KM_ERROR_UNEXPECTED_NULL_POINTER;
245         return;
246     }
247 
248     *error = check_attest_key_auths(*key);
249     if (*error != KM_ERROR_OK) return;
250 
251     signing_key = static_cast<const AsymmetricKey&>(*key).InternalToEvp();
252     if (signing_key.get() == nullptr) {
253         *error = KM_ERROR_UNKNOWN_ERROR;
254     }
255 }
256 
generate_attestation(const AsymmetricKey & key,const AuthorizationSet & attest_params,AttestKeyInfo attest_key,const AttestationContext & context,keymaster_error_t * error)257 CertificateChain generate_attestation(const AsymmetricKey& key,
258                                       const AuthorizationSet& attest_params,
259                                       AttestKeyInfo attest_key,
260                                       const AttestationContext& context,  //
261                                       keymaster_error_t* error) {
262     EVP_PKEY_Ptr pkey(key.InternalToEvp());
263     if (pkey.get() == nullptr) {
264         *error = TranslateLastOpenSslError();
265         return {};
266     }
267 
268     return generate_attestation(pkey.get(), key.sw_enforced(), key.hw_enforced(), attest_params,
269                                 move(attest_key), context, error);
270 }
271 
generate_attestation(const EVP_PKEY * evp_key,const AuthorizationSet & sw_enforced,const AuthorizationSet & tee_enforced,const AuthorizationSet & attest_params,AttestKeyInfo attest_key,const AttestationContext & context,keymaster_error_t * error)272 CertificateChain generate_attestation(const EVP_PKEY* evp_key,              //
273                                       const AuthorizationSet& sw_enforced,  //
274                                       const AuthorizationSet& tee_enforced,
275                                       const AuthorizationSet& attest_params,
276                                       AttestKeyInfo attest_key,
277                                       const AttestationContext& context,  //
278                                       keymaster_error_t* error) {
279     if (!error) return {};
280 
281     CertificateCallerParams cert_params{};
282     *error = get_certificate_params(attest_params, &cert_params, context.GetKmVersion());
283     if (*error != KM_ERROR_OK) return {};
284 
285     AuthProxy proxy(tee_enforced, sw_enforced);
286     cert_params.is_signing_key = (proxy.Contains(TAG_PURPOSE, KM_PURPOSE_SIGN) ||
287                                   proxy.Contains(TAG_PURPOSE, KM_PURPOSE_ATTEST_KEY));
288     cert_params.is_encryption_key = proxy.Contains(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
289     cert_params.is_agreement_key = proxy.Contains(TAG_PURPOSE, KM_PURPOSE_AGREE_KEY);
290 
291     keymaster_algorithm_t algorithm;
292     if (!proxy.GetTagValue(TAG_ALGORITHM, &algorithm)) {
293         *error = KM_ERROR_UNSUPPORTED_PURPOSE;
294         return {};
295     }
296 
297     CertificateChain cert_chain =
298         attest_key ? CertificateChain() : context.GetAttestationChain(algorithm, error);
299     if (*error != KM_ERROR_OK) return {};
300 
301     X509_NAME_Ptr issuer_subject = get_issuer_subject(attest_key, cert_chain, error);
302     if (*error != KM_ERROR_OK) return {};
303 
304     X509_Ptr certificate;
305     *error = make_attestation_cert(evp_key, issuer_subject.get(), cert_params, attest_params,
306                                    tee_enforced, sw_enforced, context, &certificate);
307     if (*error != KM_ERROR_OK) return {};
308 
309     EVP_PKEY_Ptr signing_key;
310     const EVP_PKEY* signing_key_ptr = attest_key.signing_key.get();
311     if (!signing_key_ptr) {
312         signing_key = get_attestation_key(algorithm, context, error);
313         if (*error != KM_ERROR_OK) return {};
314         signing_key_ptr = signing_key.get();
315     }
316 
317     *error = sign_cert(certificate.get(), signing_key_ptr);
318     if (*error != KM_ERROR_OK) return {};
319 
320     return make_cert_chain(certificate.get(), move(cert_chain), error);
321 }
322 
323 }  // namespace keymaster
324