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