• 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_util.h"
18 
19 #include "atap_ops.h"
20 
atap_basename(const char * str)21 const char* atap_basename(const char* str) {
22   int64_t n = 0;
23   size_t len = atap_strlen(str);
24 
25   if (len >= 2) {
26     for (n = len - 2; n >= 0; n--) {
27       if (str[n] == '/') {
28         return str + n + 1;
29       }
30     }
31   }
32   return str;
33 }
34 
append_to_buf(uint8_t * buf,const void * data,uint32_t data_size)35 uint8_t* append_to_buf(uint8_t* buf, const void* data, uint32_t data_size) {
36   atap_memcpy(buf, data, data_size);
37   return buf + data_size;
38 }
39 
append_uint32_to_buf(uint8_t * buf,uint32_t x)40 uint8_t* append_uint32_to_buf(uint8_t* buf, uint32_t x) {
41   return append_to_buf(buf, &x, sizeof(uint32_t));
42 }
43 
append_header_to_buf(uint8_t * buf,uint32_t message_length)44 uint8_t* append_header_to_buf(uint8_t* buf, uint32_t message_length) {
45   buf[0] = ATAP_PROTOCOL_VERSION;
46   atap_memset(&buf[1], 0, 3);  // reserved
47   buf += 4;
48   return append_uint32_to_buf(buf, message_length);
49 }
50 
append_blob_to_buf(uint8_t * buf,const AtapBlob * blob)51 uint8_t* append_blob_to_buf(uint8_t* buf, const AtapBlob* blob) {
52   atap_assert(blob->data_length == 0 || blob->data);
53   buf = append_uint32_to_buf(buf, blob->data_length);
54   if (blob->data_length > 0) {
55     buf = append_to_buf(buf, blob->data, blob->data_length);
56   }
57   return buf;
58 }
59 
append_cert_chain_to_buf(uint8_t * buf,const AtapCertChain * cert_chain)60 uint8_t* append_cert_chain_to_buf(uint8_t* buf,
61                                   const AtapCertChain* cert_chain) {
62   uint32_t cert_chain_size =
63       cert_chain_serialized_size(cert_chain) - sizeof(uint32_t);
64   uint32_t i = 0;
65   uint8_t* local_buf = buf;
66 
67   /* Append size of cert chain, as it is a Variable field. */
68   local_buf = append_uint32_to_buf(local_buf, cert_chain_size);
69 
70   for (i = 0; i < cert_chain->entry_count; ++i) {
71     local_buf = append_blob_to_buf(local_buf, &cert_chain->entries[i]);
72   }
73   atap_assert(local_buf == (buf + cert_chain_size + sizeof(uint32_t)));
74   return local_buf;
75 }
76 
append_ca_request_to_buf(uint8_t * buf,const AtapCaRequest * ca_request)77 uint8_t* append_ca_request_to_buf(uint8_t* buf,
78                                   const AtapCaRequest* ca_request) {
79   uint32_t ca_request_len = ca_request_serialized_size(ca_request);
80 
81   buf = append_header_to_buf(buf, ca_request_len - ATAP_HEADER_LEN);
82   buf = append_to_buf(buf, ca_request->device_pubkey, ATAP_ECDH_KEY_LEN);
83   buf = append_to_buf(buf, ca_request->iv, ATAP_GCM_IV_LEN);
84   buf = append_blob_to_buf(buf, &ca_request->encrypted_inner_ca_request);
85   return append_to_buf(buf, ca_request->tag, ATAP_GCM_TAG_LEN);
86 }
87 
append_inner_ca_request_to_buf(uint8_t * buf,const AtapInnerCaRequest * inner_ca_request)88 uint8_t* append_inner_ca_request_to_buf(
89     uint8_t* buf, const AtapInnerCaRequest* inner_ca_request) {
90   uint32_t inner_ca_request_len =
91       inner_ca_request_serialized_size(inner_ca_request);
92 
93   buf = append_header_to_buf(buf, inner_ca_request_len - ATAP_HEADER_LEN);
94   buf = append_cert_chain_to_buf(buf, &inner_ca_request->auth_key_cert_chain);
95   buf = append_blob_to_buf(buf, &inner_ca_request->signature);
96   buf = append_to_buf(
97       buf, inner_ca_request->product_id_hash, ATAP_SHA256_DIGEST_LEN);
98   buf = append_blob_to_buf(buf, &inner_ca_request->RSA_pubkey);
99   buf = append_blob_to_buf(buf, &inner_ca_request->ECDSA_pubkey);
100   return append_blob_to_buf(buf, &inner_ca_request->edDSA_pubkey);
101 }
102 
copy_from_buf(uint8_t ** buf_ptr,void * data,uint32_t data_size)103 void copy_from_buf(uint8_t** buf_ptr, void* data, uint32_t data_size) {
104   atap_memcpy(data, *buf_ptr, data_size);
105   *buf_ptr += data_size;
106 }
107 
copy_uint32_from_buf(uint8_t ** buf_ptr,uint32_t * x)108 void copy_uint32_from_buf(uint8_t** buf_ptr, uint32_t* x) {
109   copy_from_buf(buf_ptr, x, sizeof(uint32_t));
110 }
111 
copy_blob_from_buf(uint8_t ** buf_ptr,AtapBlob * blob)112 bool copy_blob_from_buf(uint8_t** buf_ptr, AtapBlob* blob) {
113   atap_memset(blob, 0, sizeof(AtapBlob));
114   copy_uint32_from_buf(buf_ptr, &blob->data_length);
115   if (blob->data_length > ATAP_BLOB_LEN_MAX) {
116     return false;
117   }
118   if (blob->data_length) {
119     blob->data = (uint8_t*)atap_malloc(blob->data_length);
120     if (blob->data == NULL) {
121       return false;
122     }
123     copy_from_buf(buf_ptr, blob->data, blob->data_length);
124   }
125   return true;
126 }
127 
copy_cert_chain_from_buf(uint8_t ** buf_ptr,AtapCertChain * cert_chain)128 bool copy_cert_chain_from_buf(uint8_t** buf_ptr, AtapCertChain* cert_chain) {
129   uint32_t cert_chain_size = 0;
130   int32_t bytes_remaining = 0;
131   size_t i = 0;
132   bool retval = true;
133 
134   atap_memset(cert_chain, 0, sizeof(AtapCertChain));
135 
136   /* Copy size of cert chain, as it is a Variable field. */
137   copy_from_buf(buf_ptr, &cert_chain_size, sizeof(cert_chain_size));
138 
139   if (cert_chain_size > ATAP_CERT_CHAIN_LEN_MAX) {
140     return false;
141   }
142   if (cert_chain_size == 0) {
143     return true;
144   }
145   bytes_remaining = cert_chain_size;
146   for (i = 0; i < ATAP_CERT_CHAIN_ENTRIES_MAX; ++i) {
147     if (!copy_blob_from_buf(buf_ptr, &cert_chain->entries[i])) {
148       retval = false;
149       break;
150     }
151     ++cert_chain->entry_count;
152     bytes_remaining -= (sizeof(uint32_t) + cert_chain->entries[i].data_length);
153     if (bytes_remaining <= 0) {
154       retval = (bytes_remaining == 0);
155       break;
156     }
157   }
158   if (retval == false) {
159     free_cert_chain(*cert_chain);
160   }
161   return retval;
162 }
163 
blob_serialized_size(const AtapBlob * blob)164 uint32_t blob_serialized_size(const AtapBlob* blob) {
165   return sizeof(uint32_t) + blob->data_length;
166 }
167 
cert_chain_serialized_size(const AtapCertChain * cert_chain)168 uint32_t cert_chain_serialized_size(const AtapCertChain* cert_chain) {
169   uint32_t size = sizeof(uint32_t);
170   uint32_t i = 0;
171 
172   for (i = 0; i < cert_chain->entry_count; ++i) {
173     size += sizeof(uint32_t) + cert_chain->entries[i].data_length;
174   }
175   return size;
176 }
177 
ca_request_serialized_size(const AtapCaRequest * ca_request)178 uint32_t ca_request_serialized_size(const AtapCaRequest* ca_request) {
179   uint32_t size =
180       ATAP_HEADER_LEN + ATAP_ECDH_KEY_LEN + ATAP_GCM_IV_LEN + ATAP_GCM_TAG_LEN;
181 
182   size += blob_serialized_size(&ca_request->encrypted_inner_ca_request);
183   return size;
184 }
185 
inner_ca_request_serialized_size(const AtapInnerCaRequest * inner_ca_request)186 uint32_t inner_ca_request_serialized_size(
187     const AtapInnerCaRequest* inner_ca_request) {
188   uint32_t size = ATAP_HEADER_LEN + ATAP_SHA256_DIGEST_LEN;
189 
190   size += cert_chain_serialized_size(&inner_ca_request->auth_key_cert_chain);
191   size += blob_serialized_size(&inner_ca_request->signature);
192   size += blob_serialized_size(&inner_ca_request->RSA_pubkey);
193   size += blob_serialized_size(&inner_ca_request->ECDSA_pubkey);
194   size += blob_serialized_size(&inner_ca_request->edDSA_pubkey);
195   return size;
196 }
197 
free_blob(AtapBlob blob)198 void free_blob(AtapBlob blob) {
199   if (blob.data) {
200     atap_free(blob.data);
201   }
202   blob.data_length = 0;
203 }
204 
free_cert_chain(AtapCertChain cert_chain)205 void free_cert_chain(AtapCertChain cert_chain) {
206   unsigned int i = 0;
207 
208   for (i = 0; i < cert_chain.entry_count; ++i) {
209     if (cert_chain.entries[i].data) {
210       atap_free(cert_chain.entries[i].data);
211     }
212     cert_chain.entries[i].data_length = 0;
213   }
214   atap_memset(&cert_chain, 0, sizeof(AtapCertChain));
215 }
216 
free_ca_request(AtapCaRequest ca_request)217 void free_ca_request(AtapCaRequest ca_request) {
218   free_blob(ca_request.encrypted_inner_ca_request);
219 }
220 
free_inner_ca_request(AtapInnerCaRequest inner_ca_request)221 void free_inner_ca_request(AtapInnerCaRequest inner_ca_request) {
222   free_cert_chain(inner_ca_request.auth_key_cert_chain);
223   free_blob(inner_ca_request.signature);
224   free_blob(inner_ca_request.RSA_pubkey);
225   free_blob(inner_ca_request.ECDSA_pubkey);
226   free_blob(inner_ca_request.edDSA_pubkey);
227 }
228 
validate_operation(AtapOperation operation)229 bool validate_operation(AtapOperation operation) {
230   if (operation != ATAP_OPERATION_CERTIFY &&
231       operation != ATAP_OPERATION_ISSUE &&
232       operation != ATAP_OPERATION_ISSUE_ENCRYPTED) {
233     return false;
234   }
235   return true;
236 }
237 
validate_curve(AtapCurveType curve)238 bool validate_curve(AtapCurveType curve) {
239   if (curve != ATAP_CURVE_TYPE_P256 && curve != ATAP_CURVE_TYPE_X25519) {
240     return false;
241   }
242   return true;
243 }
244 
validate_encrypted_message(const uint8_t * buf,uint32_t buf_size)245 bool validate_encrypted_message(const uint8_t* buf, uint32_t buf_size) {
246   uint32_t encrypted_len, message_len;
247   uint8_t* buf_ptr = (uint8_t*)buf;
248 
249   if (buf_size <
250       ATAP_HEADER_LEN + ATAP_GCM_IV_LEN + sizeof(uint32_t) + ATAP_GCM_TAG_LEN) {
251     return false;
252   }
253   if (buf[0] != ATAP_PROTOCOL_VERSION) {
254     return false;
255   }
256   buf_ptr += 4;
257   copy_uint32_from_buf(&buf_ptr, &message_len);
258   if (message_len != buf_size - ATAP_HEADER_LEN) {
259     return false;
260   }
261   buf_ptr += ATAP_GCM_IV_LEN;
262   copy_uint32_from_buf(&buf_ptr, &encrypted_len);
263   if (encrypted_len !=
264       message_len - ATAP_GCM_IV_LEN - sizeof(uint32_t) - ATAP_GCM_TAG_LEN) {
265     return false;
266   }
267   return true;
268 }
269 
validate_inner_ca_response(const uint8_t * buf,uint32_t buf_size,AtapOperation operation)270 bool validate_inner_ca_response(const uint8_t* buf,
271                                 uint32_t buf_size,
272                                 AtapOperation operation) {
273   uint32_t cert_chain_len = 0, len = 0;
274   size_t i = 0;
275   int tmp = 0;
276   uint8_t* buf_ptr = (uint8_t*)buf;
277 
278   if (buf_size < ATAP_HEADER_LEN + ATAP_HEX_UUID_LEN +
279                      ATAP_INNER_CA_RESPONSE_FIELDS * sizeof(uint32_t)) {
280     return false;
281   }
282   if (buf[0] != ATAP_PROTOCOL_VERSION) {
283     return false;
284   }
285   buf_ptr += 4;
286   copy_uint32_from_buf(&buf_ptr, &len);
287   if (len != buf_size - ATAP_HEADER_LEN) {
288     return false;
289   }
290   buf_ptr += ATAP_HEX_UUID_LEN;
291   for (i = 0; i < ATAP_INNER_CA_RESPONSE_FIELDS; ++i) {
292     /* Odd indices are private keys */
293     if (i % 2) {
294       copy_uint32_from_buf(&buf_ptr, &len);
295       /* Product keys (non special purpose) are omitted on certify operation. */
296       if (operation == ATAP_OPERATION_CERTIFY &&
297           i != ATAP_INNER_CA_RESPONSE_FIELDS - 1 && len != 0) {
298         return false;
299       }
300       if (len > ATAP_KEY_LEN_MAX) {
301         return false;
302       }
303       buf_ptr += len;
304     } else {
305       copy_uint32_from_buf(&buf_ptr, &cert_chain_len);
306       if (cert_chain_len > ATAP_CERT_CHAIN_LEN_MAX) {
307         return false;
308       }
309       tmp = cert_chain_len;
310       while (tmp) {
311         copy_uint32_from_buf(&buf_ptr, &len);
312         if (len > ATAP_CERT_LEN_MAX) {
313           return false;
314         }
315         buf_ptr += len;
316         tmp -= (sizeof(uint32_t) + len);
317         /* Length value list was not constructed correctly. */
318         if (tmp < 0) {
319           return false;
320         }
321       }
322     }
323   }
324   if (buf_ptr != buf + buf_size) {
325     return false;
326   }
327   return true;
328 }
329 
derive_session_key(AtapOps * ops,const uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],const uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],const uint8_t shared_secret[ATAP_ECDH_SHARED_SECRET_LEN],const char * info,uint8_t * okm,uint32_t okm_len)330 AtapResult derive_session_key(
331     AtapOps* ops,
332     const uint8_t device_pubkey[ATAP_ECDH_KEY_LEN],
333     const uint8_t ca_pubkey[ATAP_ECDH_KEY_LEN],
334     const uint8_t shared_secret[ATAP_ECDH_SHARED_SECRET_LEN],
335     const char* info,
336     uint8_t* okm,
337     uint32_t okm_len) {
338   uint8_t salt[2 * ATAP_ECDH_KEY_LEN];
339 
340   atap_memcpy(salt, ca_pubkey, ATAP_ECDH_KEY_LEN);
341   atap_memcpy(salt + ATAP_ECDH_KEY_LEN, device_pubkey, ATAP_ECDH_KEY_LEN);
342 
343   return ops->hkdf_sha256(ops,
344                           salt,
345                           sizeof(salt),
346                           shared_secret,
347                           ATAP_ECDH_SHARED_SECRET_LEN,
348                           (const uint8_t*)info,
349                           atap_strlen(info),
350                           okm,
351                           okm_len);
352 }
353