blob: e2828bf2bdecccbc0b4e3a76096cb44653d1d4fe [file] [log] [blame]
David Zeuthenc75ac312019-10-28 13:16:45 -04001/*
2 * Copyright 2019, 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#define LOG_TAG "IdentityCredentialSupport"
18
19#include <android/hardware/identity/support/IdentityCredentialSupport.h>
20
21#define _POSIX_C_SOURCE 199309L
22
23#include <ctype.h>
24#include <stdarg.h>
25#include <stdio.h>
26#include <time.h>
27#include <iomanip>
28
29#include <openssl/aes.h>
30#include <openssl/bn.h>
31#include <openssl/crypto.h>
32#include <openssl/ec.h>
33#include <openssl/err.h>
34#include <openssl/evp.h>
35#include <openssl/hkdf.h>
36#include <openssl/hmac.h>
37#include <openssl/objects.h>
38#include <openssl/pem.h>
39#include <openssl/pkcs12.h>
40#include <openssl/rand.h>
41#include <openssl/x509.h>
42#include <openssl/x509_vfy.h>
43
44#include <android-base/logging.h>
45#include <android-base/stringprintf.h>
46
47#include <cppbor.h>
48#include <cppbor_parse.h>
49
50namespace android {
51namespace hardware {
52namespace identity {
53namespace support {
54
55using ::std::pair;
56using ::std::unique_ptr;
57
58// ---------------------------------------------------------------------------
59// Miscellaneous utilities.
60// ---------------------------------------------------------------------------
61
62void hexdump(const string& name, const vector<uint8_t>& data) {
63 fprintf(stderr, "%s: dumping %zd bytes\n", name.c_str(), data.size());
64 size_t n, m, o;
65 for (n = 0; n < data.size(); n += 16) {
66 fprintf(stderr, "%04zx ", n);
67 for (m = 0; m < 16 && n + m < data.size(); m++) {
68 fprintf(stderr, "%02x ", data[n + m]);
69 }
70 for (o = m; o < 16; o++) {
71 fprintf(stderr, " ");
72 }
73 fprintf(stderr, " ");
74 for (m = 0; m < 16 && n + m < data.size(); m++) {
75 int c = data[n + m];
76 fprintf(stderr, "%c", isprint(c) ? c : '.');
77 }
78 fprintf(stderr, "\n");
79 }
80 fprintf(stderr, "\n");
81}
82
83string encodeHex(const uint8_t* data, size_t dataLen) {
84 static const char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
85 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
86
87 string ret;
88 ret.resize(dataLen * 2);
89 for (size_t n = 0; n < dataLen; n++) {
90 uint8_t byte = data[n];
91 ret[n * 2 + 0] = hexDigits[byte >> 4];
92 ret[n * 2 + 1] = hexDigits[byte & 0x0f];
93 }
94
95 return ret;
96}
97
98string encodeHex(const string& str) {
99 return encodeHex(reinterpret_cast<const uint8_t*>(str.data()), str.size());
100}
101
102string encodeHex(const vector<uint8_t>& data) {
103 return encodeHex(data.data(), data.size());
104}
105
106// Returns -1 on error, otherwise an integer in the range 0 through 15, both inclusive.
107int parseHexDigit(char hexDigit) {
108 if (hexDigit >= '0' && hexDigit <= '9') {
109 return int(hexDigit) - '0';
110 } else if (hexDigit >= 'a' && hexDigit <= 'f') {
111 return int(hexDigit) - 'a' + 10;
112 } else if (hexDigit >= 'A' && hexDigit <= 'F') {
113 return int(hexDigit) - 'A' + 10;
114 }
115 return -1;
116}
117
118optional<vector<uint8_t>> decodeHex(const string& hexEncoded) {
119 vector<uint8_t> out;
120 size_t hexSize = hexEncoded.size();
121 if ((hexSize & 1) != 0) {
122 LOG(ERROR) << "Size of data cannot be odd";
123 return {};
124 }
125
126 out.resize(hexSize / 2);
127 for (size_t n = 0; n < hexSize / 2; n++) {
128 int upperNibble = parseHexDigit(hexEncoded[n * 2]);
129 int lowerNibble = parseHexDigit(hexEncoded[n * 2 + 1]);
130 if (upperNibble == -1 || lowerNibble == -1) {
131 LOG(ERROR) << "Invalid hex digit at position " << n;
132 return {};
133 }
134 out[n] = (upperNibble << 4) + lowerNibble;
135 }
136
137 return out;
138}
139
140// ---------------------------------------------------------------------------
141// CBOR utilities.
142// ---------------------------------------------------------------------------
143
144static bool cborAreAllElementsNonCompound(const cppbor::CompoundItem* compoundItem) {
145 if (compoundItem->type() == cppbor::ARRAY) {
146 const cppbor::Array* array = compoundItem->asArray();
147 for (size_t n = 0; n < array->size(); n++) {
148 const cppbor::Item* entry = (*array)[n].get();
149 switch (entry->type()) {
150 case cppbor::ARRAY:
151 case cppbor::MAP:
152 return false;
153 default:
154 break;
155 }
156 }
157 } else {
158 const cppbor::Map* map = compoundItem->asMap();
159 for (size_t n = 0; n < map->size(); n++) {
160 auto [keyEntry, valueEntry] = (*map)[n];
161 switch (keyEntry->type()) {
162 case cppbor::ARRAY:
163 case cppbor::MAP:
164 return false;
165 default:
166 break;
167 }
168 switch (valueEntry->type()) {
169 case cppbor::ARRAY:
170 case cppbor::MAP:
171 return false;
172 default:
173 break;
174 }
175 }
176 }
177 return true;
178}
179
180static bool cborPrettyPrintInternal(const cppbor::Item* item, string& out, size_t indent,
181 size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
182 char buf[80];
183
184 string indentString(indent, ' ');
185
186 switch (item->type()) {
187 case cppbor::UINT:
188 snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
189 out.append(buf);
190 break;
191
192 case cppbor::NINT:
193 snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
194 out.append(buf);
195 break;
196
197 case cppbor::BSTR: {
198 const cppbor::Bstr* bstr = item->asBstr();
199 const vector<uint8_t>& value = bstr->value();
200 if (value.size() > maxBStrSize) {
201 unsigned char digest[SHA_DIGEST_LENGTH];
202 SHA_CTX ctx;
203 SHA1_Init(&ctx);
204 SHA1_Update(&ctx, value.data(), value.size());
205 SHA1_Final(digest, &ctx);
206 char buf2[SHA_DIGEST_LENGTH * 2 + 1];
207 for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
208 snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
209 }
210 snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", value.size(), buf2);
211 out.append(buf);
212 } else {
213 out.append("{");
214 for (size_t n = 0; n < value.size(); n++) {
215 if (n > 0) {
216 out.append(", ");
217 }
218 snprintf(buf, sizeof(buf), "0x%02x", value[n]);
219 out.append(buf);
220 }
221 out.append("}");
222 }
223 } break;
224
225 case cppbor::TSTR:
226 out.append("'");
227 {
228 // TODO: escape "'" characters
229 out.append(item->asTstr()->value().c_str());
230 }
231 out.append("'");
232 break;
233
234 case cppbor::ARRAY: {
235 const cppbor::Array* array = item->asArray();
236 if (array->size() == 0) {
237 out.append("[]");
238 } else if (cborAreAllElementsNonCompound(array)) {
239 out.append("[");
240 for (size_t n = 0; n < array->size(); n++) {
241 if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
242 mapKeysToNotPrint)) {
243 return false;
244 }
245 out.append(", ");
246 }
247 out.append("]");
248 } else {
249 out.append("[\n" + indentString);
250 for (size_t n = 0; n < array->size(); n++) {
251 out.append(" ");
252 if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
253 mapKeysToNotPrint)) {
254 return false;
255 }
256 out.append(",\n" + indentString);
257 }
258 out.append("]");
259 }
260 } break;
261
262 case cppbor::MAP: {
263 const cppbor::Map* map = item->asMap();
264
265 if (map->size() == 0) {
266 out.append("{}");
267 } else {
268 out.append("{\n" + indentString);
269 for (size_t n = 0; n < map->size(); n++) {
270 out.append(" ");
271
272 auto [map_key, map_value] = (*map)[n];
273
274 if (!cborPrettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
275 mapKeysToNotPrint)) {
276 return false;
277 }
278 out.append(" : ");
279 if (map_key->type() == cppbor::TSTR &&
280 std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
281 map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
282 out.append("<not printed>");
283 } else {
284 if (!cborPrettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
285 mapKeysToNotPrint)) {
286 return false;
287 }
288 }
289 out.append(",\n" + indentString);
290 }
291 out.append("}");
292 }
293 } break;
294
295 case cppbor::SEMANTIC: {
296 const cppbor::Semantic* semantic = item->asSemantic();
297 snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", semantic->value());
298 out.append(buf);
299 cborPrettyPrintInternal(semantic->child().get(), out, indent, maxBStrSize,
300 mapKeysToNotPrint);
301 } break;
302
303 case cppbor::SIMPLE:
304 const cppbor::Bool* asBool = item->asSimple()->asBool();
305 const cppbor::Null* asNull = item->asSimple()->asNull();
306 if (asBool != nullptr) {
307 out.append(asBool->value() ? "true" : "false");
308 } else if (asNull != nullptr) {
309 out.append("null");
310 } else {
311 LOG(ERROR) << "Only boolean/null is implemented for SIMPLE";
312 return false;
313 }
314 break;
315 }
316
317 return true;
318}
319
320string cborPrettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
321 const vector<string>& mapKeysToNotPrint) {
322 auto [item, _, message] = cppbor::parse(encodedCbor);
323 if (item == nullptr) {
324 LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
325 return "";
326 }
327
328 string out;
329 cborPrettyPrintInternal(item.get(), out, 0, maxBStrSize, mapKeysToNotPrint);
330 return out;
331}
332
333// ---------------------------------------------------------------------------
334// Crypto functionality / abstraction.
335// ---------------------------------------------------------------------------
336
337struct EVP_CIPHER_CTX_Deleter {
338 void operator()(EVP_CIPHER_CTX* ctx) const {
339 if (ctx != nullptr) {
340 EVP_CIPHER_CTX_free(ctx);
341 }
342 }
343};
344
345using EvpCipherCtxPtr = unique_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Deleter>;
346
347// bool getRandom(size_t numBytes, vector<uint8_t>& output) {
348optional<vector<uint8_t>> getRandom(size_t numBytes) {
349 vector<uint8_t> output;
350 output.resize(numBytes);
351 if (RAND_bytes(output.data(), numBytes) != 1) {
352 LOG(ERROR) << "RAND_bytes: failed getting " << numBytes << " random";
353 return {};
354 }
355 return output;
356}
357
358optional<vector<uint8_t>> decryptAes128Gcm(const vector<uint8_t>& key,
359 const vector<uint8_t>& encryptedData,
360 const vector<uint8_t>& additionalAuthenticatedData) {
361 int cipherTextSize = int(encryptedData.size()) - kAesGcmIvSize - kAesGcmTagSize;
362 if (cipherTextSize < 0) {
363 LOG(ERROR) << "encryptedData too small";
364 return {};
365 }
366 unsigned char* nonce = (unsigned char*)encryptedData.data();
367 unsigned char* cipherText = nonce + kAesGcmIvSize;
368 unsigned char* tag = cipherText + cipherTextSize;
369
370 vector<uint8_t> plainText;
371 plainText.resize(cipherTextSize);
372
373 auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
374 if (ctx.get() == nullptr) {
375 LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
376 return {};
377 }
378
379 if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
380 LOG(ERROR) << "EVP_DecryptInit_ex: failed";
381 return {};
382 }
383
384 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
385 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
386 return {};
387 }
388
389 if (EVP_DecryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(), nonce) != 1) {
390 LOG(ERROR) << "EVP_DecryptInit_ex: failed";
391 return {};
392 }
393
394 int numWritten;
395 if (additionalAuthenticatedData.size() > 0) {
396 if (EVP_DecryptUpdate(ctx.get(), NULL, &numWritten,
397 (unsigned char*)additionalAuthenticatedData.data(),
398 additionalAuthenticatedData.size()) != 1) {
399 LOG(ERROR) << "EVP_DecryptUpdate: failed for additionalAuthenticatedData";
400 return {};
401 }
402 if ((size_t)numWritten != additionalAuthenticatedData.size()) {
403 LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
404 << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
405 return {};
406 }
407 }
408
409 if (EVP_DecryptUpdate(ctx.get(), (unsigned char*)plainText.data(), &numWritten, cipherText,
410 cipherTextSize) != 1) {
411 LOG(ERROR) << "EVP_DecryptUpdate: failed";
412 return {};
413 }
414 if (numWritten != cipherTextSize) {
415 LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
416 << cipherTextSize << ")";
417 return {};
418 }
419
420 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag)) {
421 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting expected tag";
422 return {};
423 }
424
425 int ret = EVP_DecryptFinal_ex(ctx.get(), (unsigned char*)plainText.data() + numWritten,
426 &numWritten);
427 if (ret != 1) {
428 LOG(ERROR) << "EVP_DecryptFinal_ex: failed";
429 return {};
430 }
431 if (numWritten != 0) {
432 LOG(ERROR) << "EVP_DecryptFinal_ex: Unexpected non-zero outl=" << numWritten;
433 return {};
434 }
435
436 return plainText;
437}
438
439optional<vector<uint8_t>> encryptAes128Gcm(const vector<uint8_t>& key, const vector<uint8_t>& nonce,
440 const vector<uint8_t>& data,
441 const vector<uint8_t>& additionalAuthenticatedData) {
442 if (key.size() != kAes128GcmKeySize) {
443 LOG(ERROR) << "key is not kAes128GcmKeySize bytes";
444 return {};
445 }
446 if (nonce.size() != kAesGcmIvSize) {
447 LOG(ERROR) << "nonce is not kAesGcmIvSize bytes";
448 return {};
449 }
450
451 // The result is the nonce (kAesGcmIvSize bytes), the ciphertext, and
452 // finally the tag (kAesGcmTagSize bytes).
453 vector<uint8_t> encryptedData;
454 encryptedData.resize(data.size() + kAesGcmIvSize + kAesGcmTagSize);
455 unsigned char* noncePtr = (unsigned char*)encryptedData.data();
456 unsigned char* cipherText = noncePtr + kAesGcmIvSize;
457 unsigned char* tag = cipherText + data.size();
458 memcpy(noncePtr, nonce.data(), kAesGcmIvSize);
459
460 auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
461 if (ctx.get() == nullptr) {
462 LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
463 return {};
464 }
465
466 if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
467 LOG(ERROR) << "EVP_EncryptInit_ex: failed";
468 return {};
469 }
470
471 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
472 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
473 return {};
474 }
475
476 if (EVP_EncryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(),
477 (unsigned char*)nonce.data()) != 1) {
478 LOG(ERROR) << "EVP_EncryptInit_ex: failed";
479 return {};
480 }
481
482 int numWritten;
483 if (additionalAuthenticatedData.size() > 0) {
484 if (EVP_EncryptUpdate(ctx.get(), NULL, &numWritten,
485 (unsigned char*)additionalAuthenticatedData.data(),
486 additionalAuthenticatedData.size()) != 1) {
487 LOG(ERROR) << "EVP_EncryptUpdate: failed for additionalAuthenticatedData";
488 return {};
489 }
490 if ((size_t)numWritten != additionalAuthenticatedData.size()) {
491 LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
492 << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
493 return {};
494 }
495 }
496
497 if (data.size() > 0) {
498 if (EVP_EncryptUpdate(ctx.get(), cipherText, &numWritten, (unsigned char*)data.data(),
499 data.size()) != 1) {
500 LOG(ERROR) << "EVP_EncryptUpdate: failed";
501 return {};
502 }
503 if ((size_t)numWritten != data.size()) {
504 LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
505 << data.size() << ")";
506 return {};
507 }
508 }
509
510 if (EVP_EncryptFinal_ex(ctx.get(), cipherText + numWritten, &numWritten) != 1) {
511 LOG(ERROR) << "EVP_EncryptFinal_ex: failed";
512 return {};
513 }
514 if (numWritten != 0) {
515 LOG(ERROR) << "EVP_EncryptFinal_ex: Unexpected non-zero outl=" << numWritten;
516 return {};
517 }
518
519 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize, tag) != 1) {
520 LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed getting tag";
521 return {};
522 }
523
524 return encryptedData;
525}
526
527struct EC_KEY_Deleter {
528 void operator()(EC_KEY* key) const {
529 if (key != nullptr) {
530 EC_KEY_free(key);
531 }
532 }
533};
534using EC_KEY_Ptr = unique_ptr<EC_KEY, EC_KEY_Deleter>;
535
536struct EVP_PKEY_Deleter {
537 void operator()(EVP_PKEY* key) const {
538 if (key != nullptr) {
539 EVP_PKEY_free(key);
540 }
541 }
542};
543using EVP_PKEY_Ptr = unique_ptr<EVP_PKEY, EVP_PKEY_Deleter>;
544
545struct EVP_PKEY_CTX_Deleter {
546 void operator()(EVP_PKEY_CTX* ctx) const {
547 if (ctx != nullptr) {
548 EVP_PKEY_CTX_free(ctx);
549 }
550 }
551};
552using EVP_PKEY_CTX_Ptr = unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Deleter>;
553
554struct EC_GROUP_Deleter {
555 void operator()(EC_GROUP* group) const {
556 if (group != nullptr) {
557 EC_GROUP_free(group);
558 }
559 }
560};
561using EC_GROUP_Ptr = unique_ptr<EC_GROUP, EC_GROUP_Deleter>;
562
563struct EC_POINT_Deleter {
564 void operator()(EC_POINT* point) const {
565 if (point != nullptr) {
566 EC_POINT_free(point);
567 }
568 }
569};
570
571using EC_POINT_Ptr = unique_ptr<EC_POINT, EC_POINT_Deleter>;
572
573struct ECDSA_SIG_Deleter {
574 void operator()(ECDSA_SIG* sig) const {
575 if (sig != nullptr) {
576 ECDSA_SIG_free(sig);
577 }
578 }
579};
580using ECDSA_SIG_Ptr = unique_ptr<ECDSA_SIG, ECDSA_SIG_Deleter>;
581
582struct X509_Deleter {
583 void operator()(X509* x509) const {
584 if (x509 != nullptr) {
585 X509_free(x509);
586 }
587 }
588};
589using X509_Ptr = unique_ptr<X509, X509_Deleter>;
590
591struct PKCS12_Deleter {
592 void operator()(PKCS12* pkcs12) const {
593 if (pkcs12 != nullptr) {
594 PKCS12_free(pkcs12);
595 }
596 }
597};
598using PKCS12_Ptr = unique_ptr<PKCS12, PKCS12_Deleter>;
599
600struct BIGNUM_Deleter {
601 void operator()(BIGNUM* bignum) const {
602 if (bignum != nullptr) {
603 BN_free(bignum);
604 }
605 }
606};
607using BIGNUM_Ptr = unique_ptr<BIGNUM, BIGNUM_Deleter>;
608
609struct ASN1_INTEGER_Deleter {
610 void operator()(ASN1_INTEGER* value) const {
611 if (value != nullptr) {
612 ASN1_INTEGER_free(value);
613 }
614 }
615};
616using ASN1_INTEGER_Ptr = unique_ptr<ASN1_INTEGER, ASN1_INTEGER_Deleter>;
617
618struct ASN1_TIME_Deleter {
619 void operator()(ASN1_TIME* value) const {
620 if (value != nullptr) {
621 ASN1_TIME_free(value);
622 }
623 }
624};
625using ASN1_TIME_Ptr = unique_ptr<ASN1_TIME, ASN1_TIME_Deleter>;
626
627struct X509_NAME_Deleter {
628 void operator()(X509_NAME* value) const {
629 if (value != nullptr) {
630 X509_NAME_free(value);
631 }
632 }
633};
634using X509_NAME_Ptr = unique_ptr<X509_NAME, X509_NAME_Deleter>;
635
636vector<uint8_t> certificateChainJoin(const vector<vector<uint8_t>>& certificateChain) {
637 vector<uint8_t> ret;
638 for (const vector<uint8_t>& certificate : certificateChain) {
639 ret.insert(ret.end(), certificate.begin(), certificate.end());
640 }
641 return ret;
642}
643
644optional<vector<vector<uint8_t>>> certificateChainSplit(const vector<uint8_t>& certificateChain) {
645 const unsigned char* pStart = (unsigned char*)certificateChain.data();
646 const unsigned char* p = pStart;
647 const unsigned char* pEnd = p + certificateChain.size();
648 vector<vector<uint8_t>> certificates;
649 while (p < pEnd) {
650 size_t begin = p - pStart;
651 auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
652 size_t next = p - pStart;
653 if (x509 == nullptr) {
654 LOG(ERROR) << "Error parsing X509 certificate";
655 return {};
656 }
657 vector<uint8_t> cert =
658 vector<uint8_t>(certificateChain.begin() + begin, certificateChain.begin() + next);
659 certificates.push_back(std::move(cert));
660 }
661 return certificates;
662}
663
664static bool parseX509Certificates(const vector<uint8_t>& certificateChain,
665 vector<X509_Ptr>& parsedCertificates) {
666 const unsigned char* p = (unsigned char*)certificateChain.data();
667 const unsigned char* pEnd = p + certificateChain.size();
668 parsedCertificates.resize(0);
669 while (p < pEnd) {
670 auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
671 if (x509 == nullptr) {
672 LOG(ERROR) << "Error parsing X509 certificate";
673 return false;
674 }
675 parsedCertificates.push_back(std::move(x509));
676 }
677 return true;
678}
679
680// TODO: Right now the only check we perform is to check that each certificate
681// is signed by its successor. We should - but currently don't - also check
682// things like valid dates etc.
683//
684// It would be nice to use X509_verify_cert() instead of doing our own thing.
685//
686bool certificateChainValidate(const vector<uint8_t>& certificateChain) {
687 vector<X509_Ptr> certs;
688
689 if (!parseX509Certificates(certificateChain, certs)) {
690 LOG(ERROR) << "Error parsing X509 certificates";
691 return false;
692 }
693
694 if (certs.size() == 1) {
695 return true;
696 }
697
698 for (size_t n = 1; n < certs.size(); n++) {
699 const X509_Ptr& keyCert = certs[n - 1];
700 const X509_Ptr& signingCert = certs[n];
701 EVP_PKEY_Ptr signingPubkey(X509_get_pubkey(signingCert.get()));
702 if (X509_verify(keyCert.get(), signingPubkey.get()) != 1) {
703 LOG(ERROR) << "Error validating cert at index " << n - 1
704 << " is signed by its successor";
705 return false;
706 }
707 }
708
709 return true;
710}
711
712bool checkEcDsaSignature(const vector<uint8_t>& digest, const vector<uint8_t>& signature,
713 const vector<uint8_t>& publicKey) {
714 const unsigned char* p = (unsigned char*)signature.data();
715 auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size()));
716 if (sig.get() == nullptr) {
717 LOG(ERROR) << "Error decoding DER encoded signature";
718 return false;
719 }
720
721 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
722 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
723 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
724 1) {
725 LOG(ERROR) << "Error decoding publicKey";
726 return false;
727 }
728 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
729 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
730 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
731 LOG(ERROR) << "Memory allocation failed";
732 return false;
733 }
734 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
735 LOG(ERROR) << "Error setting group";
736 return false;
737 }
738 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
739 LOG(ERROR) << "Error setting point";
740 return false;
741 }
742 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
743 LOG(ERROR) << "Error setting key";
744 return false;
745 }
746
747 int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get());
748 if (rc != 1) {
749 LOG(ERROR) << "Error verifying signature (rc=" << rc << ")";
750 return false;
751 }
752
753 return true;
754}
755
756vector<uint8_t> sha256(const vector<uint8_t>& data) {
757 vector<uint8_t> ret;
758 ret.resize(SHA256_DIGEST_LENGTH);
759 SHA256_CTX ctx;
760 SHA256_Init(&ctx);
761 SHA256_Update(&ctx, data.data(), data.size());
762 SHA256_Final((unsigned char*)ret.data(), &ctx);
763 return ret;
764}
765
766optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
767 auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
768 if (bn.get() == nullptr) {
769 LOG(ERROR) << "Error creating BIGNUM";
770 return {};
771 }
772
773 auto ec_key = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
774 if (EC_KEY_set_private_key(ec_key.get(), bn.get()) != 1) {
775 LOG(ERROR) << "Error setting private key from BIGNUM";
776 return {};
777 }
778
779 auto digest = sha256(data);
780 ECDSA_SIG* sig = ECDSA_do_sign(digest.data(), digest.size(), ec_key.get());
781 if (sig == nullptr) {
782 LOG(ERROR) << "Error signing digest";
783 return {};
784 }
785 size_t len = i2d_ECDSA_SIG(sig, nullptr);
786 vector<uint8_t> signature;
787 signature.resize(len);
788 unsigned char* p = (unsigned char*)signature.data();
789 i2d_ECDSA_SIG(sig, &p);
790 ECDSA_SIG_free(sig);
791 return signature;
792}
793
794optional<vector<uint8_t>> hmacSha256(const vector<uint8_t>& key, const vector<uint8_t>& data) {
795 HMAC_CTX ctx;
796 HMAC_CTX_init(&ctx);
797 if (HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), nullptr /* impl */) != 1) {
798 LOG(ERROR) << "Error initializing HMAC_CTX";
799 return {};
800 }
801 if (HMAC_Update(&ctx, data.data(), data.size()) != 1) {
802 LOG(ERROR) << "Error updating HMAC_CTX";
803 return {};
804 }
805 vector<uint8_t> hmac;
806 hmac.resize(32);
807 unsigned int size = 0;
808 if (HMAC_Final(&ctx, hmac.data(), &size) != 1) {
809 LOG(ERROR) << "Error finalizing HMAC_CTX";
810 return {};
811 }
812 if (size != 32) {
813 LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
814 return {};
815 }
816 return hmac;
817}
818
819optional<vector<uint8_t>> createEcKeyPair() {
820 auto ec_key = EC_KEY_Ptr(EC_KEY_new());
821 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
822 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
823 if (ec_key.get() == nullptr || pkey.get() == nullptr) {
824 LOG(ERROR) << "Memory allocation failed";
825 return {};
826 }
827
828 if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
829 EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
830 LOG(ERROR) << "Error generating key";
831 return {};
832 }
833
834 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
835 LOG(ERROR) << "Error getting private key";
836 return {};
837 }
838
839 int size = i2d_PrivateKey(pkey.get(), nullptr);
840 if (size == 0) {
841 LOG(ERROR) << "Error generating public key encoding";
842 return {};
843 }
844 vector<uint8_t> keyPair;
845 keyPair.resize(size);
846 unsigned char* p = keyPair.data();
847 i2d_PrivateKey(pkey.get(), &p);
848 return keyPair;
849}
850
851optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair) {
852 const unsigned char* p = (const unsigned char*)keyPair.data();
853 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
854 if (pkey.get() == nullptr) {
855 LOG(ERROR) << "Error parsing keyPair";
856 return {};
857 }
858
859 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
860 if (ecKey.get() == nullptr) {
861 LOG(ERROR) << "Failed getting EC key";
862 return {};
863 }
864
865 auto ecGroup = EC_KEY_get0_group(ecKey.get());
866 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
867 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
868 nullptr);
869 if (size == 0) {
870 LOG(ERROR) << "Error generating public key encoding";
871 return {};
872 }
873
874 vector<uint8_t> publicKey;
875 publicKey.resize(size);
876 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
877 publicKey.size(), nullptr);
878 return publicKey;
879}
880
881optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair) {
882 const unsigned char* p = (const unsigned char*)keyPair.data();
883 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
884 if (pkey.get() == nullptr) {
885 LOG(ERROR) << "Error parsing keyPair";
886 return {};
887 }
888
889 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
890 if (ecKey.get() == nullptr) {
891 LOG(ERROR) << "Failed getting EC key";
892 return {};
893 }
894
895 const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey.get());
896 if (bignum == nullptr) {
897 LOG(ERROR) << "Error getting bignum from private key";
898 return {};
899 }
900 vector<uint8_t> privateKey;
901 privateKey.resize(BN_num_bytes(bignum));
902 BN_bn2bin(bignum, privateKey.data());
903 return privateKey;
904}
905
906optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
907 const string& serialDecimal, const string& issuer,
908 const string& subject, time_t validityNotBefore,
909 time_t validityNotAfter) {
910 const unsigned char* p = (const unsigned char*)keyPair.data();
911 auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
912 if (pkey.get() == nullptr) {
913 LOG(ERROR) << "Error parsing keyPair";
914 return {};
915 }
916
917 auto x509 = X509_Ptr(X509_new());
918 if (!x509.get()) {
919 LOG(ERROR) << "Error creating X509 certificate";
920 return {};
921 }
922
923 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
924 LOG(ERROR) << "Error setting version to 3";
925 return {};
926 }
927
928 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
929 LOG(ERROR) << "Error setting public key";
930 return {};
931 }
932
933 BIGNUM* bignumSerial = nullptr;
934 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
935 LOG(ERROR) << "Error parsing serial";
936 return {};
937 }
938 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
939 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
940 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
941 LOG(ERROR) << "Error setting serial";
942 return {};
943 }
944
945 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
946 if (x509Issuer.get() == nullptr ||
947 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
948 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
949 0 /* set */) != 1 ||
950 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
951 LOG(ERROR) << "Error setting issuer";
952 return {};
953 }
954
955 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
956 if (x509Subject.get() == nullptr ||
957 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
958 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
959 0 /* set */) != 1 ||
960 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
961 LOG(ERROR) << "Error setting subject";
962 return {};
963 }
964
965 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
966 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
967 LOG(ERROR) << "Error setting notBefore";
968 return {};
969 }
970
971 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
972 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
973 LOG(ERROR) << "Error setting notAfter";
974 return {};
975 }
976
977 if (X509_sign(x509.get(), pkey.get(), EVP_sha256()) == 0) {
978 LOG(ERROR) << "Error signing X509 certificate";
979 return {};
980 }
981
982 // Ideally we wouldn't encrypt it (we're only using this function for
983 // sending a key-pair over binder to the Android app) but BoringSSL does not
984 // support this: from pkcs8_x509.c in BoringSSL: "In OpenSSL, -1 here means
985 // to use no encryption, which we do not currently support."
986 //
987 // Passing nullptr as |pass|, though, means "no password". So we'll do that.
988 // Compare with the receiving side - CredstoreIdentityCredential.java - where
989 // an empty char[] is passed as the password.
990 //
991 auto pkcs12 = PKCS12_Ptr(PKCS12_create(nullptr, name.c_str(), pkey.get(), x509.get(),
992 nullptr, // ca
993 0, // nid_key
994 0, // nid_cert
995 0, // iter,
996 0, // mac_iter,
997 0)); // keytype
998 if (pkcs12.get() == nullptr) {
999 char buf[128];
1000 long errCode = ERR_get_error();
1001 ERR_error_string_n(errCode, buf, sizeof buf);
1002 LOG(ERROR) << "Error creating PKCS12, code " << errCode << ": " << buf;
1003 return {};
1004 }
1005
1006 unsigned char* buffer = nullptr;
1007 int length = i2d_PKCS12(pkcs12.get(), &buffer);
1008 if (length < 0) {
1009 LOG(ERROR) << "Error encoding PKCS12";
1010 return {};
1011 }
1012 vector<uint8_t> pkcs12Bytes;
1013 pkcs12Bytes.resize(length);
1014 memcpy(pkcs12Bytes.data(), buffer, length);
1015 OPENSSL_free(buffer);
1016
1017 return pkcs12Bytes;
1018}
1019
1020optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
1021 const vector<uint8_t>& publicKey, const vector<uint8_t>& signingKey,
1022 const string& serialDecimal, const string& issuer, const string& subject,
1023 time_t validityNotBefore, time_t validityNotAfter) {
1024 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1025 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1026 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1027 1) {
1028 LOG(ERROR) << "Error decoding publicKey";
1029 return {};
1030 }
1031 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1032 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1033 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1034 LOG(ERROR) << "Memory allocation failed";
1035 return {};
1036 }
1037 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1038 LOG(ERROR) << "Error setting group";
1039 return {};
1040 }
1041 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1042 LOG(ERROR) << "Error setting point";
1043 return {};
1044 }
1045 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1046 LOG(ERROR) << "Error setting key";
1047 return {};
1048 }
1049
1050 auto bn = BIGNUM_Ptr(BN_bin2bn(signingKey.data(), signingKey.size(), nullptr));
1051 if (bn.get() == nullptr) {
1052 LOG(ERROR) << "Error creating BIGNUM for private key";
1053 return {};
1054 }
1055 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1056 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1057 LOG(ERROR) << "Error setting private key from BIGNUM";
1058 return {};
1059 }
1060 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1061 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1062 LOG(ERROR) << "Error setting private key";
1063 return {};
1064 }
1065
1066 auto x509 = X509_Ptr(X509_new());
1067 if (!x509.get()) {
1068 LOG(ERROR) << "Error creating X509 certificate";
1069 return {};
1070 }
1071
1072 if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
1073 LOG(ERROR) << "Error setting version to 3";
1074 return {};
1075 }
1076
1077 if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
1078 LOG(ERROR) << "Error setting public key";
1079 return {};
1080 }
1081
1082 BIGNUM* bignumSerial = nullptr;
1083 if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
1084 LOG(ERROR) << "Error parsing serial";
1085 return {};
1086 }
1087 auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
1088 auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
1089 if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
1090 LOG(ERROR) << "Error setting serial";
1091 return {};
1092 }
1093
1094 auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
1095 if (x509Issuer.get() == nullptr ||
1096 X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
1097 (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
1098 0 /* set */) != 1 ||
1099 X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
1100 LOG(ERROR) << "Error setting issuer";
1101 return {};
1102 }
1103
1104 auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
1105 if (x509Subject.get() == nullptr ||
1106 X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
1107 (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
1108 0 /* set */) != 1 ||
1109 X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
1110 LOG(ERROR) << "Error setting subject";
1111 return {};
1112 }
1113
1114 auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
1115 if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
1116 LOG(ERROR) << "Error setting notBefore";
1117 return {};
1118 }
1119
1120 auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
1121 if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
1122 LOG(ERROR) << "Error setting notAfter";
1123 return {};
1124 }
1125
1126 if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
1127 LOG(ERROR) << "Error signing X509 certificate";
1128 return {};
1129 }
1130
1131 unsigned char* buffer = nullptr;
1132 int length = i2d_X509(x509.get(), &buffer);
1133 if (length < 0) {
1134 LOG(ERROR) << "Error DER encoding X509 certificate";
1135 return {};
1136 }
1137
1138 vector<uint8_t> certificate;
1139 certificate.resize(length);
1140 memcpy(certificate.data(), buffer, length);
1141 OPENSSL_free(buffer);
1142 return certificate;
1143}
1144
1145optional<vector<uint8_t>> ecdh(const vector<uint8_t>& publicKey,
1146 const vector<uint8_t>& privateKey) {
1147 auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
1148 auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
1149 if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1150 1) {
1151 LOG(ERROR) << "Error decoding publicKey";
1152 return {};
1153 }
1154 auto ecKey = EC_KEY_Ptr(EC_KEY_new());
1155 auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1156 if (ecKey.get() == nullptr || pkey.get() == nullptr) {
1157 LOG(ERROR) << "Memory allocation failed";
1158 return {};
1159 }
1160 if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
1161 LOG(ERROR) << "Error setting group";
1162 return {};
1163 }
1164 if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
1165 LOG(ERROR) << "Error setting point";
1166 return {};
1167 }
1168 if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
1169 LOG(ERROR) << "Error setting key";
1170 return {};
1171 }
1172
1173 auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
1174 if (bn.get() == nullptr) {
1175 LOG(ERROR) << "Error creating BIGNUM for private key";
1176 return {};
1177 }
1178 auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
1179 if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
1180 LOG(ERROR) << "Error setting private key from BIGNUM";
1181 return {};
1182 }
1183 auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
1184 if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
1185 LOG(ERROR) << "Error setting private key";
1186 return {};
1187 }
1188
1189 auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL));
1190 if (ctx.get() == nullptr) {
1191 LOG(ERROR) << "Error creating context";
1192 return {};
1193 }
1194
1195 if (EVP_PKEY_derive_init(ctx.get()) != 1) {
1196 LOG(ERROR) << "Error initializing context";
1197 return {};
1198 }
1199
1200 if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
1201 LOG(ERROR) << "Error setting peer";
1202 return {};
1203 }
1204
1205 /* Determine buffer length for shared secret */
1206 size_t secretLen = 0;
1207 if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) {
1208 LOG(ERROR) << "Error determing length of shared secret";
1209 return {};
1210 }
1211 vector<uint8_t> sharedSecret;
1212 sharedSecret.resize(secretLen);
1213
1214 if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) {
1215 LOG(ERROR) << "Error deriving shared secret";
1216 return {};
1217 }
1218 return sharedSecret;
1219}
1220
1221optional<vector<uint8_t>> hkdf(const vector<uint8_t>& sharedSecret, const vector<uint8_t>& salt,
1222 const vector<uint8_t>& info, size_t size) {
1223 vector<uint8_t> derivedKey;
1224 derivedKey.resize(size);
1225 if (HKDF(derivedKey.data(), derivedKey.size(), EVP_sha256(), sharedSecret.data(),
1226 sharedSecret.size(), salt.data(), salt.size(), info.data(), info.size()) != 1) {
1227 LOG(ERROR) << "Error deriving key";
1228 return {};
1229 }
1230 return derivedKey;
1231}
1232
1233void removeLeadingZeroes(vector<uint8_t>& vec) {
1234 while (vec.size() >= 1 && vec[0] == 0x00) {
1235 vec.erase(vec.begin());
1236 }
1237}
1238
1239tuple<bool, vector<uint8_t>, vector<uint8_t>> ecPublicKeyGetXandY(
1240 const vector<uint8_t>& publicKey) {
1241 if (publicKey.size() != 65 || publicKey[0] != 0x04) {
1242 LOG(ERROR) << "publicKey is not in the expected format";
1243 return std::make_tuple(false, vector<uint8_t>(), vector<uint8_t>());
1244 }
1245 vector<uint8_t> x, y;
1246 x.resize(32);
1247 y.resize(32);
1248 memcpy(x.data(), publicKey.data() + 1, 32);
1249 memcpy(y.data(), publicKey.data() + 33, 32);
1250
1251 removeLeadingZeroes(x);
1252 removeLeadingZeroes(y);
1253
1254 return std::make_tuple(true, x, y);
1255}
1256
1257optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain) {
1258 vector<X509_Ptr> certs;
1259 if (!parseX509Certificates(certificateChain, certs)) {
1260 return {};
1261 }
1262 if (certs.size() < 1) {
1263 LOG(ERROR) << "No certificates in chain";
1264 return {};
1265 }
1266
1267 int algoId = OBJ_obj2nid(certs[0]->cert_info->key->algor->algorithm);
1268 if (algoId != NID_X9_62_id_ecPublicKey) {
1269 LOG(ERROR) << "Expected NID_X9_62_id_ecPublicKey, got " << OBJ_nid2ln(algoId);
1270 return {};
1271 }
1272
1273 auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
1274 if (pkey.get() == nullptr) {
1275 LOG(ERROR) << "No public key";
1276 return {};
1277 }
1278
1279 auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
1280 if (ecKey.get() == nullptr) {
1281 LOG(ERROR) << "Failed getting EC key";
1282 return {};
1283 }
1284
1285 auto ecGroup = EC_KEY_get0_group(ecKey.get());
1286 auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
1287 int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
1288 nullptr);
1289 if (size == 0) {
1290 LOG(ERROR) << "Error generating public key encoding";
1291 return {};
1292 }
1293 vector<uint8_t> publicKey;
1294 publicKey.resize(size);
1295 EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
1296 publicKey.size(), nullptr);
1297 return publicKey;
1298}
1299
1300// ---------------------------------------------------------------------------
1301// COSE Utility Functions
1302// ---------------------------------------------------------------------------
1303
1304vector<uint8_t> coseBuildToBeSigned(const vector<uint8_t>& encodedProtectedHeaders,
1305 const vector<uint8_t>& data,
1306 const vector<uint8_t>& detachedContent) {
1307 cppbor::Array sigStructure;
1308 sigStructure.add("Signature1");
1309 sigStructure.add(encodedProtectedHeaders);
1310
1311 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
1312 // so external_aad is the empty bstr
1313 vector<uint8_t> emptyExternalAad;
1314 sigStructure.add(emptyExternalAad);
1315
1316 // Next field is the payload, independently of how it's transported (RFC
1317 // 8152 section 4.4). Since our API specifies only one of |data| and
1318 // |detachedContent| can be non-empty, it's simply just the non-empty one.
1319 if (data.size() > 0) {
1320 sigStructure.add(data);
1321 } else {
1322 sigStructure.add(detachedContent);
1323 }
1324 return sigStructure.encode();
1325}
1326
1327vector<uint8_t> coseEncodeHeaders(const cppbor::Map& protectedHeaders) {
1328 if (protectedHeaders.size() == 0) {
1329 cppbor::Bstr emptyBstr(vector<uint8_t>({}));
1330 return emptyBstr.encode();
1331 }
1332 return protectedHeaders.encode();
1333}
1334
1335// From https://tools.ietf.org/html/rfc8152
1336const int COSE_LABEL_ALG = 1;
1337const int COSE_LABEL_X5CHAIN = 33; // temporary identifier
1338
1339// From "COSE Algorithms" registry
1340const int COSE_ALG_ECDSA_256 = -7;
1341const int COSE_ALG_HMAC_256_256 = 5;
1342
1343bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
1344 vector<uint8_t>& ecdsaDerSignature) {
1345 if (ecdsaCoseSignature.size() != 64) {
1346 LOG(ERROR) << "COSE signature length is " << ecdsaCoseSignature.size() << ", expected 64";
1347 return false;
1348 }
1349
1350 auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr));
1351 if (rBn.get() == nullptr) {
1352 LOG(ERROR) << "Error creating BIGNUM for r";
1353 return false;
1354 }
1355
1356 auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr));
1357 if (sBn.get() == nullptr) {
1358 LOG(ERROR) << "Error creating BIGNUM for s";
1359 return false;
1360 }
1361
1362 ECDSA_SIG sig;
1363 sig.r = rBn.get();
1364 sig.s = sBn.get();
1365
1366 size_t len = i2d_ECDSA_SIG(&sig, nullptr);
1367 ecdsaDerSignature.resize(len);
1368 unsigned char* p = (unsigned char*)ecdsaDerSignature.data();
1369 i2d_ECDSA_SIG(&sig, &p);
1370
1371 return true;
1372}
1373
1374bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
1375 vector<uint8_t>& ecdsaCoseSignature) {
1376 ECDSA_SIG* sig;
1377 const unsigned char* p = ecdsaDerSignature.data();
1378 sig = d2i_ECDSA_SIG(nullptr, &p, ecdsaDerSignature.size());
1379 if (sig == nullptr) {
1380 LOG(ERROR) << "Error decoding DER signature";
1381 return false;
1382 }
1383
1384 ecdsaCoseSignature.clear();
1385 ecdsaCoseSignature.resize(64);
1386 if (BN_bn2binpad(sig->r, ecdsaCoseSignature.data(), 32) != 32) {
1387 LOG(ERROR) << "Error encoding r";
1388 return false;
1389 }
1390 if (BN_bn2binpad(sig->s, ecdsaCoseSignature.data() + 32, 32) != 32) {
1391 LOG(ERROR) << "Error encoding s";
1392 return false;
1393 }
1394 return true;
1395}
1396
1397optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
1398 const vector<uint8_t>& detachedContent,
1399 const vector<uint8_t>& certificateChain) {
1400 cppbor::Map unprotectedHeaders;
1401 cppbor::Map protectedHeaders;
1402
1403 if (data.size() > 0 && detachedContent.size() > 0) {
1404 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1405 return {};
1406 }
1407
1408 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
1409
1410 if (certificateChain.size() != 0) {
1411 optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
1412 if (!certs) {
1413 LOG(ERROR) << "Error splitting certificate chain";
1414 return {};
1415 }
1416 if (certs.value().size() == 1) {
1417 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
1418 } else {
1419 cppbor::Array certArray;
1420 for (const vector<uint8_t>& cert : certs.value()) {
1421 certArray.add(cert);
1422 }
1423 unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
1424 }
1425 }
1426
1427 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1428 vector<uint8_t> toBeSigned =
1429 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
1430
1431 optional<vector<uint8_t>> derSignature = signEcDsa(key, toBeSigned);
1432 if (!derSignature) {
1433 LOG(ERROR) << "Error signing toBeSigned data";
1434 return {};
1435 }
1436 vector<uint8_t> coseSignature;
1437 if (!ecdsaSignatureDerToCose(derSignature.value(), coseSignature)) {
1438 LOG(ERROR) << "Error converting ECDSA signature from DER to COSE format";
1439 return {};
1440 }
1441
1442 cppbor::Array coseSign1;
1443 coseSign1.add(encodedProtectedHeaders);
1444 coseSign1.add(std::move(unprotectedHeaders));
1445 if (data.size() == 0) {
1446 cppbor::Null nullValue;
1447 coseSign1.add(std::move(nullValue));
1448 } else {
1449 coseSign1.add(data);
1450 }
1451 coseSign1.add(coseSignature);
1452 vector<uint8_t> signatureCoseSign1;
1453 signatureCoseSign1 = coseSign1.encode();
1454 return signatureCoseSign1;
1455}
1456
1457bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
1458 const vector<uint8_t>& detachedContent,
1459 const vector<uint8_t>& publicKey) {
1460 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1461 if (item == nullptr) {
1462 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
1463 return false;
1464 }
1465 const cppbor::Array* array = item->asArray();
1466 if (array == nullptr) {
1467 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
1468 return false;
1469 }
1470 if (array->size() != 4) {
1471 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
1472 return false;
1473 }
1474
1475 const cppbor::Bstr* encodedProtectedHeadersBstr = (*array)[0]->asBstr();
1476 ;
1477 if (encodedProtectedHeadersBstr == nullptr) {
1478 LOG(ERROR) << "Value for encodedProtectedHeaders is not a bstr";
1479 return false;
1480 }
1481 const vector<uint8_t> encodedProtectedHeaders = encodedProtectedHeadersBstr->value();
1482
1483 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
1484 if (unprotectedHeaders == nullptr) {
1485 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
1486 return false;
1487 }
1488
1489 vector<uint8_t> data;
1490 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
1491 if (payloadAsSimple != nullptr) {
1492 if (payloadAsSimple->asNull() == nullptr) {
1493 LOG(ERROR) << "Value for payload is not null or a bstr";
1494 return false;
1495 }
1496 } else {
1497 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
1498 if (payloadAsBstr == nullptr) {
1499 LOG(ERROR) << "Value for payload is not null or a bstr";
1500 return false;
1501 }
1502 data = payloadAsBstr->value(); // TODO: avoid copy
1503 }
1504
1505 if (data.size() > 0 && detachedContent.size() > 0) {
1506 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1507 return false;
1508 }
1509
1510 const cppbor::Bstr* signatureBstr = (*array)[3]->asBstr();
1511 if (signatureBstr == nullptr) {
1512 LOG(ERROR) << "Value for signature is a bstr";
1513 return false;
1514 }
1515 const vector<uint8_t>& coseSignature = signatureBstr->value();
1516
1517 vector<uint8_t> derSignature;
1518 if (!ecdsaSignatureCoseToDer(coseSignature, derSignature)) {
1519 LOG(ERROR) << "Error converting ECDSA signature from COSE to DER format";
1520 return false;
1521 }
1522
1523 vector<uint8_t> toBeSigned =
1524 coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
1525 if (!checkEcDsaSignature(support::sha256(toBeSigned), derSignature, publicKey)) {
1526 LOG(ERROR) << "Signature check failed";
1527 return false;
1528 }
1529 return true;
1530}
1531
1532optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
1533 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1534 if (item == nullptr) {
1535 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
1536 return {};
1537 }
1538 const cppbor::Array* array = item->asArray();
1539 if (array == nullptr) {
1540 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
1541 return {};
1542 }
1543 if (array->size() != 4) {
1544 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
1545 return {};
1546 }
1547
1548 vector<uint8_t> data;
1549 const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
1550 if (payloadAsSimple != nullptr) {
1551 if (payloadAsSimple->asNull() == nullptr) {
1552 LOG(ERROR) << "Value for payload is not null or a bstr";
1553 return {};
1554 }
1555 // payload is null, so |data| should be empty (as it is)
1556 } else {
1557 const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
1558 if (payloadAsBstr == nullptr) {
1559 LOG(ERROR) << "Value for payload is not null or a bstr";
1560 return {};
1561 }
1562 // Copy payload into |data|
1563 data = payloadAsBstr->value();
1564 }
1565
1566 return data;
1567}
1568
1569optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
1570 auto [item, _, message] = cppbor::parse(signatureCoseSign1);
1571 if (item == nullptr) {
1572 LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
1573 return {};
1574 }
1575 const cppbor::Array* array = item->asArray();
1576 if (array == nullptr) {
1577 LOG(ERROR) << "Value for COSE_Sign1 is not an array";
1578 return {};
1579 }
1580 if (array->size() != 4) {
1581 LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
1582 return {};
1583 }
1584
1585 const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
1586 if (unprotectedHeaders == nullptr) {
1587 LOG(ERROR) << "Value for unprotectedHeaders is not a map";
1588 return {};
1589 }
1590
1591 for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
1592 auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
1593 const cppbor::Int* number = keyItem->asInt();
1594 if (number == nullptr) {
1595 LOG(ERROR) << "Key item in top-level map is not a number";
1596 return {};
1597 }
1598 int label = number->value();
1599 if (label == COSE_LABEL_X5CHAIN) {
1600 const cppbor::Bstr* bstr = valueItem->asBstr();
1601 if (bstr != nullptr) {
1602 return bstr->value();
1603 }
1604 const cppbor::Array* array = valueItem->asArray();
1605 if (array != nullptr) {
1606 vector<uint8_t> certs;
1607 for (size_t m = 0; m < array->size(); m++) {
1608 const cppbor::Bstr* bstr = ((*array)[m])->asBstr();
1609 if (bstr == nullptr) {
1610 LOG(ERROR) << "Item in x5chain array is not a bstr";
1611 return {};
1612 }
1613 const vector<uint8_t>& certValue = bstr->value();
1614 certs.insert(certs.end(), certValue.begin(), certValue.end());
1615 }
1616 return certs;
1617 }
1618 LOG(ERROR) << "Value for x5chain label is not a bstr or array";
1619 return {};
1620 }
1621 }
1622 LOG(ERROR) << "Did not find x5chain label in unprotected headers";
1623 return {};
1624}
1625
1626vector<uint8_t> coseBuildToBeMACed(const vector<uint8_t>& encodedProtectedHeaders,
1627 const vector<uint8_t>& data,
1628 const vector<uint8_t>& detachedContent) {
1629 cppbor::Array macStructure;
1630 macStructure.add("MAC0");
1631 macStructure.add(encodedProtectedHeaders);
1632
1633 // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
1634 // so external_aad is the empty bstr
1635 vector<uint8_t> emptyExternalAad;
1636 macStructure.add(emptyExternalAad);
1637
1638 // Next field is the payload, independently of how it's transported (RFC
1639 // 8152 section 4.4). Since our API specifies only one of |data| and
1640 // |detachedContent| can be non-empty, it's simply just the non-empty one.
1641 if (data.size() > 0) {
1642 macStructure.add(data);
1643 } else {
1644 macStructure.add(detachedContent);
1645 }
1646
1647 return macStructure.encode();
1648}
1649
1650optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
1651 const vector<uint8_t>& detachedContent) {
1652 cppbor::Map unprotectedHeaders;
1653 cppbor::Map protectedHeaders;
1654
1655 if (data.size() > 0 && detachedContent.size() > 0) {
1656 LOG(ERROR) << "data and detachedContent cannot both be non-empty";
1657 return {};
1658 }
1659
1660 protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
1661
1662 vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
1663 vector<uint8_t> toBeMACed = coseBuildToBeMACed(encodedProtectedHeaders, data, detachedContent);
1664
1665 optional<vector<uint8_t>> mac = hmacSha256(key, toBeMACed);
1666 if (!mac) {
1667 LOG(ERROR) << "Error MACing toBeMACed data";
1668 return {};
1669 }
1670
1671 cppbor::Array array;
1672 array.add(encodedProtectedHeaders);
1673 array.add(std::move(unprotectedHeaders));
1674 if (data.size() == 0) {
1675 cppbor::Null nullValue;
1676 array.add(std::move(nullValue));
1677 } else {
1678 array.add(data);
1679 }
1680 array.add(mac.value());
1681 return array.encode();
1682}
1683
1684// ---------------------------------------------------------------------------
David Zeuthenc75ac312019-10-28 13:16:45 -04001685// Utility functions specific to IdentityCredential.
1686// ---------------------------------------------------------------------------
1687
David Zeuthenc75ac312019-10-28 13:16:45 -04001688vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
1689 vector<vector<uint8_t>> ret;
1690
1691 size_t contentSize = content.size();
1692 if (contentSize <= maxChunkSize) {
1693 ret.push_back(content);
1694 return ret;
1695 }
1696
1697 size_t numChunks = (contentSize + maxChunkSize - 1) / maxChunkSize;
1698
1699 size_t pos = 0;
1700 for (size_t n = 0; n < numChunks; n++) {
1701 size_t size = contentSize - pos;
1702 if (size > maxChunkSize) {
1703 size = maxChunkSize;
1704 }
1705 auto begin = content.begin() + pos;
1706 auto end = content.begin() + pos + size;
1707 ret.emplace_back(vector<uint8_t>(begin, end));
1708 pos += maxChunkSize;
1709 }
1710
1711 return ret;
1712}
1713
David Zeuthenc75ac312019-10-28 13:16:45 -04001714
1715vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1716
1717const vector<uint8_t>& getTestHardwareBoundKey() {
1718 return testHardwareBoundKey;
1719}
1720
David Zeuthenc75ac312019-10-28 13:16:45 -04001721} // namespace support
1722} // namespace identity
1723} // namespace hardware
1724} // namespace android