• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 "atap_ops.h"
18 #include "atap_util.h"
19 #include "libatap.h"
20 
21 static uint8_t session_shared_secret[ATAP_ECDH_SHARED_SECRET_LEN];
22 static uint8_t session_key[ATAP_AES_128_KEY_LEN];
23 static AtapOperation operation;
24 
auth_key_signature_generate(AtapOps * ops,uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],uint8_t ** signature,uint32_t * signature_len)25 static AtapResult auth_key_signature_generate(
26     AtapOps* ops,
27     uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
28     uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
29     uint8_t** signature,
30     uint32_t* signature_len) {
31   AtapResult ret = 0;
32   uint8_t nonce[ATAP_NONCE_LEN];
33   *signature = (uint8_t*)atap_malloc(ATAP_SIGNATURE_LEN_MAX);
34   if (*signature == NULL) {
35     return ATAP_RESULT_ERROR_OOM;
36   }
37   /* deriving nonce uses same HKDF as deriving session key */
38   ret = derive_session_key(ops,
39                            device_pubkey,
40                            ca_pubkey,
41                            session_shared_secret,
42                            "SIGN",
43                            nonce,
44                            ATAP_NONCE_LEN);
45   if (ret != ATAP_RESULT_OK) {
46     return ret;
47   }
48   return ops->auth_key_sign(
49       ops, nonce, ATAP_NONCE_LEN, *signature, signature_len);
50 }
51 
read_available_public_keys(AtapOps * ops,AtapInnerCaRequest * inner_ca_request)52 static AtapResult read_available_public_keys(
53     AtapOps* ops, AtapInnerCaRequest* inner_ca_request) {
54   AtapResult ret = 0;
55 
56   inner_ca_request->RSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
57   inner_ca_request->RSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
58   inner_ca_request->ECDSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
59   inner_ca_request->ECDSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
60   inner_ca_request->edDSA_pubkey.data = (uint8_t*)atap_malloc(ATAP_KEY_LEN_MAX);
61   inner_ca_request->edDSA_pubkey.data_length = ATAP_KEY_LEN_MAX;
62 
63   if (inner_ca_request->RSA_pubkey.data == NULL ||
64       inner_ca_request->ECDSA_pubkey.data == NULL ||
65       inner_ca_request->edDSA_pubkey.data == NULL) {
66     return ATAP_RESULT_ERROR_OOM;
67   }
68   ret = ops->read_attestation_public_key(
69       ops,
70       ATAP_KEY_TYPE_RSA,
71       inner_ca_request->RSA_pubkey.data,
72       &inner_ca_request->RSA_pubkey.data_length);
73   if (ret != ATAP_RESULT_OK) {
74     return ret;
75   }
76   ret = ops->read_attestation_public_key(
77       ops,
78       ATAP_KEY_TYPE_ECDSA,
79       inner_ca_request->ECDSA_pubkey.data,
80       &inner_ca_request->ECDSA_pubkey.data_length);
81   if (ret != ATAP_RESULT_OK) {
82     return ret;
83   }
84   ret = ops->read_attestation_public_key(
85       ops,
86       ATAP_KEY_TYPE_edDSA,
87       inner_ca_request->edDSA_pubkey.data,
88       &inner_ca_request->edDSA_pubkey.data_length);
89   /* edDSA support is not required in the initial version */
90   if (ret == ATAP_RESULT_ERROR_UNSUPPORTED_OPERATION) {
91     atap_free(inner_ca_request->edDSA_pubkey.data);
92     inner_ca_request->edDSA_pubkey.data = NULL;
93     inner_ca_request->edDSA_pubkey.data_length = 0;
94     ret = ATAP_RESULT_OK;
95   }
96   return ret;
97 }
98 
initialize_session(AtapOps * ops,const uint8_t * operation_start,uint32_t operation_start_size,AtapKeyType * auth_key_type,uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],AtapCaRequest * ca_request,AtapInnerCaRequest * inner_ca_request)99 static AtapResult initialize_session(AtapOps* ops,
100                                      const uint8_t* operation_start,
101                                      uint32_t operation_start_size,
102                                      AtapKeyType* auth_key_type,
103                                      uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
104                                      AtapCaRequest* ca_request,
105                                      AtapInnerCaRequest* inner_ca_request) {
106   uint32_t message_length = 0;
107   AtapCurveType curve_type = 0;
108   AtapResult ret = 0;
109   uint8_t* buf_ptr = (uint8_t*)operation_start + 4;
110 
111   atap_memset(ca_request, 0, sizeof(AtapCaRequest));
112   atap_memset(inner_ca_request, 0, sizeof(AtapInnerCaRequest));
113 
114   if (operation_start_size != ATAP_OPERATION_START_LEN) {
115     return ATAP_RESULT_ERROR_INVALID_INPUT;
116   }
117   if (operation_start[0] != ATAP_PROTOCOL_VERSION) {
118     return ATAP_RESULT_ERROR_INVALID_INPUT;
119   }
120   copy_uint32_from_buf(&buf_ptr, &message_length);
121   if (message_length != ATAP_ECDH_KEY_LEN + 2) {
122     return ATAP_RESULT_ERROR_INVALID_INPUT;
123   }
124   curve_type = operation_start[ATAP_HEADER_LEN];
125   operation = operation_start[ATAP_HEADER_LEN + 1];
126   if (!validate_operation(operation)) {
127     return ATAP_RESULT_ERROR_UNSUPPORTED_OPERATION;
128   }
129   if (!validate_curve(curve_type)) {
130     return ATAP_RESULT_ERROR_UNSUPPORTED_ALGORITHM;
131   }
132 
133   atap_memcpy(ca_pubkey, &operation_start[10], ATAP_ECDH_KEY_LEN);
134 
135   ret = ops->get_auth_key_type(ops, auth_key_type);
136   if (ret != ATAP_RESULT_OK) {
137     return ret;
138   }
139 
140   ret = ops->ecdh_shared_secret_compute(ops,
141                                         curve_type,
142                                         ca_pubkey,
143                                         ca_request->device_pubkey,
144                                         session_shared_secret);
145   if (ret != ATAP_RESULT_OK) {
146     return ret;
147   }
148 
149   return derive_session_key(ops,
150                             ca_request->device_pubkey,
151                             ca_pubkey,
152                             session_shared_secret,
153                             "KEY",
154                             session_key,
155                             ATAP_AES_128_KEY_LEN);
156 }
157 
compute_auth_signature(AtapOps * ops,uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],AtapInnerCaRequest * inner_ca_request)158 static AtapResult compute_auth_signature(
159     AtapOps* ops,
160     uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
161     uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
162     AtapInnerCaRequest* inner_ca_request) {
163   AtapResult ret = 0;
164   /* read auth key cert chain */
165   ret = ops->read_auth_key_cert_chain(ops,
166                                       &inner_ca_request->auth_key_cert_chain);
167   if (ret != ATAP_RESULT_OK) {
168     return ret;
169   }
170   /* generate auth key signature */
171   return auth_key_signature_generate(ops,
172                                      device_pubkey,
173                                      ca_pubkey,
174                                      &inner_ca_request->signature.data,
175                                      &inner_ca_request->signature.data_length);
176 }
177 
read_product_id_hash(AtapOps * ops,AtapInnerCaRequest * inner_ca_request)178 static AtapResult read_product_id_hash(AtapOps* ops,
179                                        AtapInnerCaRequest* inner_ca_request) {
180   AtapResult ret = 0;
181   uint8_t product_id[ATAP_PRODUCT_ID_LEN];
182 
183   ret = ops->read_product_id(ops, product_id);
184   if (ret != ATAP_RESULT_OK) {
185     return ret;
186   }
187   return ops->sha256(
188       ops, product_id, ATAP_PRODUCT_ID_LEN, inner_ca_request->product_id_hash);
189 }
190 
encrypt_inner_ca_request(AtapOps * ops,const AtapInnerCaRequest * inner_ca_request,AtapCaRequest * ca_request)191 static AtapResult encrypt_inner_ca_request(
192     AtapOps* ops,
193     const AtapInnerCaRequest* inner_ca_request,
194     AtapCaRequest* ca_request) {
195   AtapResult ret = 0;
196   uint32_t inner_ca_request_len = 0;
197   uint8_t* inner_ca_request_buf = NULL;
198 
199   inner_ca_request_len = inner_ca_request_serialized_size(inner_ca_request);
200   inner_ca_request_buf = (uint8_t*)atap_malloc(inner_ca_request_len);
201   ca_request->encrypted_inner_ca_request.data =
202       (uint8_t*)atap_malloc(inner_ca_request_len);
203   ca_request->encrypted_inner_ca_request.data_length = inner_ca_request_len;
204   if (inner_ca_request_buf == NULL ||
205       ca_request->encrypted_inner_ca_request.data == NULL) {
206     return ATAP_RESULT_ERROR_OOM;
207   }
208   append_inner_ca_request_to_buf(inner_ca_request_buf, inner_ca_request);
209 
210   /* generate IV */
211   ret = ops->get_random_bytes(ops, ca_request->iv, ATAP_GCM_IV_LEN);
212   if (ret != ATAP_RESULT_OK) {
213     goto out;
214   }
215 
216   /* encrypt inner CA request with shared key */
217   ret = ops->aes_gcm_128_encrypt(ops,
218                                  inner_ca_request_buf,
219                                  inner_ca_request_len,
220                                  ca_request->iv,
221                                  session_key,
222                                  ca_request->encrypted_inner_ca_request.data,
223                                  ca_request->tag);
224 out:
225   atap_free(inner_ca_request_buf);
226   return ret;
227 }
228 
decrypt_encrypted_message(AtapOps * ops,const uint8_t * buf,uint32_t buf_size,uint8_t * key,uint8_t ** plaintext,uint32_t * plaintext_len)229 static AtapResult decrypt_encrypted_message(AtapOps* ops,
230                                             const uint8_t* buf,
231                                             uint32_t buf_size,
232                                             uint8_t* key,
233                                             uint8_t** plaintext,
234                                             uint32_t* plaintext_len) {
235   const uint8_t *iv = NULL, *tag = NULL, *ciphertext = NULL;
236   uint32_t encrypted_len = 0;
237   uint8_t* buf_ptr = (uint8_t*)buf + ATAP_HEADER_LEN;
238 
239   if (!validate_encrypted_message(buf, buf_size)) {
240     return ATAP_RESULT_ERROR_INVALID_INPUT;
241   }
242 
243   iv = buf_ptr;
244   buf_ptr += ATAP_GCM_IV_LEN;
245   copy_uint32_from_buf(&buf_ptr, &encrypted_len);
246   ciphertext = buf_ptr;
247   buf_ptr += encrypted_len;
248   tag = buf_ptr;
249 
250   *plaintext = (uint8_t*)atap_malloc(encrypted_len);
251   if (*plaintext == NULL) {
252     return ATAP_RESULT_ERROR_OOM;
253   }
254   *plaintext_len = encrypted_len;
255 
256   return ops->aes_gcm_128_decrypt(
257       ops, ciphertext, *plaintext_len, iv, session_key, tag, *plaintext);
258 }
259 
write_attestation_data(AtapOps * ops,uint8_t ** buf_ptr,AtapKeyType key_type)260 static AtapResult write_attestation_data(AtapOps* ops,
261                                          uint8_t** buf_ptr,
262                                          AtapKeyType key_type) {
263   AtapBlob key;
264   AtapCertChain cert_chain;
265   AtapResult ret = ATAP_RESULT_OK;
266 
267   atap_memset(&key, 0, sizeof(key));
268   atap_memset(&cert_chain, 0, sizeof(cert_chain));
269 
270   if (!copy_cert_chain_from_buf(buf_ptr, &cert_chain)) {
271     ret = ATAP_RESULT_ERROR_OOM;
272     goto out;
273   }
274   if (!copy_blob_from_buf(buf_ptr, &key)) {
275     ret = ATAP_RESULT_ERROR_OOM;
276     goto out;
277   }
278   if (key.data_length == 0 && cert_chain.entry_count) {
279     ret = ops->write_attestation_key(ops, key_type, NULL, &cert_chain);
280   } else if (key.data_length && cert_chain.entry_count) {
281     ret = ops->write_attestation_key(ops, key_type, &key, &cert_chain);
282   } else if (key.data_length && cert_chain.entry_count == 0) {
283     /* We never issue a key without a certificate chain */
284     ret = ATAP_RESULT_ERROR_INVALID_INPUT;
285   } else if (key_type != ATAP_KEY_TYPE_edDSA &&
286              key_type != ATAP_KEY_TYPE_SPECIAL &&
287              key_type != ATAP_KEY_TYPE_EPID) {
288     /* edDSA, EPID, and special purpose key are optional in version 1*/
289     ret = ATAP_RESULT_ERROR_INVALID_INPUT;
290   }
291 
292 out:
293   free_blob(key);
294   free_cert_chain(cert_chain);
295   return ret;
296 }
297 
write_inner_ca_response(AtapOps * ops,uint8_t * inner_ca_resp_ptr,uint32_t inner_ca_resp_len)298 static AtapResult write_inner_ca_response(AtapOps* ops,
299                                           uint8_t* inner_ca_resp_ptr,
300                                           uint32_t inner_ca_resp_len) {
301   AtapResult ret = 0;
302   uint8_t** buf_ptr = &inner_ca_resp_ptr;
303 
304   if (!validate_inner_ca_response(
305           inner_ca_resp_ptr, inner_ca_resp_len, operation)) {
306     return ATAP_RESULT_ERROR_INVALID_INPUT;
307   }
308   ret = ops->write_hex_uuid(ops, &inner_ca_resp_ptr[ATAP_HEADER_LEN]);
309   if (ret != ATAP_RESULT_OK) {
310     return ret;
311   }
312   *buf_ptr += (ATAP_HEADER_LEN + ATAP_HEX_UUID_LEN);
313   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_RSA);
314   if (ret != ATAP_RESULT_OK) {
315     return ret;
316   }
317   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_ECDSA);
318   if (ret != ATAP_RESULT_OK) {
319     return ret;
320   }
321   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_edDSA);
322   /* Device may not support edDSA */
323   if (ret != ATAP_RESULT_OK && ret != ATAP_RESULT_ERROR_UNSUPPORTED_ALGORITHM) {
324     return ret;
325   }
326   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_EPID);
327   if (ret != ATAP_RESULT_OK) {
328     return ret;
329   }
330   /* Device may not support Special Cast key */
331   ret = write_attestation_data(ops, buf_ptr, ATAP_KEY_TYPE_SPECIAL);
332   if (ret != ATAP_RESULT_OK) {
333     return ret;
334   }
335   return ATAP_RESULT_OK;
336 }
337 
atap_get_ca_request(AtapOps * ops,const uint8_t * operation_start,uint32_t operation_start_size,uint8_t ** ca_request_p,uint32_t * ca_request_size_p)338 AtapResult atap_get_ca_request(AtapOps* ops,
339                                const uint8_t* operation_start,
340                                uint32_t operation_start_size,
341                                uint8_t** ca_request_p,
342                                uint32_t* ca_request_size_p) {
343   AtapResult ret = 0;
344   AtapKeyType auth_key_type = 0;
345   AtapCaRequest ca_request;
346   AtapInnerCaRequest inner_ca_request;
347   uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN];
348 
349   ret = initialize_session(ops,
350                            operation_start,
351                            operation_start_size,
352                            &auth_key_type,
353                            ca_pubkey,
354                            &ca_request,
355                            &inner_ca_request);
356   if (ret != ATAP_RESULT_OK) {
357     goto err;
358   }
359 
360   if (auth_key_type != ATAP_KEY_TYPE_NONE) {
361     ret = compute_auth_signature(
362         ops, ca_pubkey, ca_request.device_pubkey, &inner_ca_request);
363     if (ret != ATAP_RESULT_OK) {
364       goto err;
365     }
366   }
367 
368   if (operation == ATAP_OPERATION_CERTIFY) {
369     ret = read_available_public_keys(ops, &inner_ca_request);
370     if (ret != ATAP_RESULT_OK) {
371       goto err;
372     }
373   }
374 
375   ret = read_product_id_hash(ops, &inner_ca_request);
376   if (ret != ATAP_RESULT_OK) {
377     goto err;
378   }
379 
380   ret = encrypt_inner_ca_request(ops, &inner_ca_request, &ca_request);
381   if (ret != ATAP_RESULT_OK) {
382     goto err;
383   }
384 
385   *ca_request_size_p = ca_request_serialized_size(&ca_request);
386   *ca_request_p = (uint8_t*)atap_malloc(*ca_request_size_p);
387   if (*ca_request_p == NULL) {
388     *ca_request_size_p = 0;
389     ret = ATAP_RESULT_ERROR_OOM;
390     goto err;
391   }
392   append_ca_request_to_buf(*ca_request_p, &ca_request);
393   goto out;
394 
395 err:
396   /* clear global secrets */
397   atap_memset(session_shared_secret, 0, ATAP_ECDH_SHARED_SECRET_LEN);
398   atap_memset(session_key, 0, ATAP_AES_128_KEY_LEN);
399   *ca_request_p = NULL;
400   *ca_request_size_p = 0;
401 out:
402   free_inner_ca_request(inner_ca_request);
403   free_ca_request(ca_request);
404   return ret;
405 }
406 
atap_set_ca_response(AtapOps * ops,const uint8_t * ca_response,uint32_t ca_response_size)407 AtapResult atap_set_ca_response(AtapOps* ops,
408                                 const uint8_t* ca_response,
409                                 uint32_t ca_response_size) {
410   AtapResult ret = 0;
411   uint8_t* inner_ca_resp = NULL;
412   uint8_t* inner_inner_ca_resp = NULL;
413   uint8_t* inner_ca_resp_ptr = NULL;
414   uint32_t inner_ca_resp_len = 0;
415   uint32_t inner_inner_ca_resp_len = 0;
416   uint8_t soc_global_key[ATAP_AES_128_KEY_LEN];
417 
418   ret = decrypt_encrypted_message(ops,
419                                   ca_response,
420                                   ca_response_size,
421                                   session_key,
422                                   &inner_ca_resp,
423                                   &inner_ca_resp_len);
424   if (ret != ATAP_RESULT_OK) {
425     goto out;
426   }
427   inner_ca_resp_ptr = inner_ca_resp;
428   if (operation == ATAP_OPERATION_ISSUE_ENCRYPTED) {
429     /* Decrypt Encrypted Inner CA Response (encrypted) with SoC global key */
430     ret = ops->read_soc_global_key(ops, soc_global_key);
431     if (ret != ATAP_RESULT_OK) {
432       goto out;
433     }
434     ret = decrypt_encrypted_message(ops,
435                                     inner_ca_resp,
436                                     inner_ca_resp_len,
437                                     soc_global_key,
438                                     &inner_inner_ca_resp,
439                                     &inner_inner_ca_resp_len);
440     if (ret != ATAP_RESULT_OK) {
441       goto out;
442     }
443     inner_ca_resp_ptr = inner_inner_ca_resp;
444     inner_ca_resp_len = inner_inner_ca_resp_len;
445   }
446   ret = write_inner_ca_response(ops, inner_ca_resp_ptr, inner_ca_resp_len);
447 
448 out:
449   if (inner_ca_resp) {
450     atap_free(inner_ca_resp);
451   }
452   if (inner_inner_ca_resp) {
453     atap_free(inner_inner_ca_resp);
454   }
455   return ret;
456 }
457