blob.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /*
  2. * Copyright (C) 2015 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. #define LOG_TAG "keystore"
  17. #include <arpa/inet.h>
  18. #include <errno.h>
  19. #include <fcntl.h>
  20. #include <string.h>
  21. #include <log/log.h>
  22. #include "blob.h"
  23. #include "keystore_utils.h"
  24. #include <openssl/evp.h>
  25. #include <openssl/rand.h>
  26. #include <istream>
  27. #include <ostream>
  28. #include <streambuf>
  29. #include <string>
  30. #include <android-base/logging.h>
  31. namespace {
  32. constexpr size_t kGcmIvSizeBytes = 96 / 8;
  33. template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter {
  34. void operator()(T* p) { FreeFunc(p); }
  35. };
  36. #define DEFINE_OPENSSL_OBJECT_POINTER(name) \
  37. typedef OpenSslObjectDeleter<name, name##_free> name##_Delete; \
  38. typedef std::unique_ptr<name, name##_Delete> name##_Ptr;
  39. DEFINE_OPENSSL_OBJECT_POINTER(EVP_CIPHER_CTX);
  40. #if defined(__clang__)
  41. #define OPTNONE __attribute__((optnone))
  42. #elif defined(__GNUC__)
  43. #define OPTNONE __attribute__((optimize("O0")))
  44. #else
  45. #error Need a definition for OPTNONE
  46. #endif
  47. class ArrayEraser {
  48. public:
  49. ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
  50. OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
  51. private:
  52. volatile uint8_t* mArr;
  53. size_t mSize;
  54. };
  55. /**
  56. * Returns a EVP_CIPHER appropriate for the given key, based on the key's size.
  57. */
  58. const EVP_CIPHER* getAesCipherForKey(const std::vector<uint8_t>& key) {
  59. const EVP_CIPHER* cipher = EVP_aes_256_gcm();
  60. if (key.size() == kAes128KeySizeBytes) {
  61. cipher = EVP_aes_128_gcm();
  62. }
  63. return cipher;
  64. }
  65. /*
  66. * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
  67. * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
  68. * 'tag'.
  69. */
  70. ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
  71. const std::vector<uint8_t>& key, const uint8_t* iv, uint8_t* tag) {
  72. // There can be 128-bit and 256-bit keys
  73. const EVP_CIPHER* cipher = getAesCipherForKey(key);
  74. EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
  75. EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
  76. EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
  77. std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
  78. uint8_t* out_pos = out_tmp.get();
  79. int out_len;
  80. EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
  81. out_pos += out_len;
  82. EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
  83. out_pos += out_len;
  84. if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
  85. ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
  86. out_pos - out_tmp.get());
  87. return ResponseCode::SYSTEM_ERROR;
  88. }
  89. std::copy(out_tmp.get(), out_pos, out);
  90. EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
  91. return ResponseCode::NO_ERROR;
  92. }
  93. /*
  94. * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
  95. * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
  96. * location as 'in').
  97. */
  98. ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len,
  99. const std::vector<uint8_t> key, const uint8_t* iv,
  100. const uint8_t* tag) {
  101. // There can be 128-bit and 256-bit keys
  102. const EVP_CIPHER* cipher = getAesCipherForKey(key);
  103. EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
  104. EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
  105. EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
  106. EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
  107. std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
  108. ArrayEraser out_eraser(out_tmp.get(), len);
  109. uint8_t* out_pos = out_tmp.get();
  110. int out_len;
  111. EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
  112. out_pos += out_len;
  113. if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
  114. ALOGD("Failed to decrypt blob; ciphertext or tag is likely corrupted");
  115. return ResponseCode::VALUE_CORRUPTED;
  116. }
  117. out_pos += out_len;
  118. if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
  119. ALOGD("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
  120. out_pos - out_tmp.get());
  121. return ResponseCode::VALUE_CORRUPTED;
  122. }
  123. std::copy(out_tmp.get(), out_pos, out);
  124. return ResponseCode::NO_ERROR;
  125. }
  126. class ArrayStreamBuffer : public std::streambuf {
  127. public:
  128. template <typename T, size_t size> explicit ArrayStreamBuffer(const T (&data)[size]) {
  129. static_assert(sizeof(T) == 1, "Array element size too large");
  130. std::streambuf::char_type* d = const_cast<std::streambuf::char_type*>(
  131. reinterpret_cast<const std::streambuf::char_type*>(&data[0]));
  132. setg(d, d, d + size);
  133. setp(d, d + size);
  134. }
  135. protected:
  136. pos_type seekoff(off_type off, std::ios_base::seekdir dir,
  137. std::ios_base::openmode which = std::ios_base::in |
  138. std::ios_base::out) override {
  139. bool in = which & std::ios_base::in;
  140. bool out = which & std::ios_base::out;
  141. if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1;
  142. std::streambuf::char_type* newPosPtr;
  143. switch (dir) {
  144. case std::ios_base::beg:
  145. newPosPtr = pbase();
  146. break;
  147. case std::ios_base::cur:
  148. // if dir == cur then in xor out due to
  149. // if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1; above
  150. if (in)
  151. newPosPtr = gptr();
  152. else
  153. newPosPtr = pptr();
  154. break;
  155. case std::ios_base::end:
  156. // in and out bounds are the same and cannot change, so we can take either range
  157. // regardless of the value of "which"
  158. newPosPtr = epptr();
  159. break;
  160. }
  161. newPosPtr += off;
  162. if (newPosPtr < pbase() || newPosPtr > epptr()) return -1;
  163. if (in) {
  164. gbump(newPosPtr - gptr());
  165. }
  166. if (out) {
  167. pbump(newPosPtr - pptr());
  168. }
  169. return newPosPtr - pbase();
  170. }
  171. };
  172. } // namespace
  173. Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
  174. BlobType type) {
  175. mBlob = std::make_unique<blobv3>();
  176. memset(mBlob.get(), 0, sizeof(blobv3));
  177. if (valueLength > kValueSize) {
  178. valueLength = kValueSize;
  179. ALOGW("Provided blob length too large");
  180. }
  181. if (infoLength + valueLength > kValueSize) {
  182. infoLength = kValueSize - valueLength;
  183. ALOGW("Provided info length too large");
  184. }
  185. mBlob->length = valueLength;
  186. memcpy(mBlob->value, value, valueLength);
  187. mBlob->info = infoLength;
  188. memcpy(mBlob->value + valueLength, info, infoLength);
  189. mBlob->version = CURRENT_BLOB_VERSION;
  190. mBlob->type = uint8_t(type);
  191. if (type == TYPE_MASTER_KEY || type == TYPE_MASTER_KEY_AES256) {
  192. mBlob->flags = KEYSTORE_FLAG_ENCRYPTED;
  193. } else {
  194. mBlob->flags = KEYSTORE_FLAG_NONE;
  195. }
  196. }
  197. Blob::Blob(blobv3 b) {
  198. mBlob = std::make_unique<blobv3>(b);
  199. }
  200. Blob::Blob() {
  201. if (mBlob) *mBlob = {};
  202. }
  203. Blob::Blob(const Blob& rhs) {
  204. if (rhs.mBlob) {
  205. mBlob = std::make_unique<blobv3>(*rhs.mBlob);
  206. }
  207. }
  208. Blob::Blob(Blob&& rhs) : mBlob(std::move(rhs.mBlob)) {}
  209. Blob& Blob::operator=(const Blob& rhs) {
  210. if (&rhs != this) {
  211. if (mBlob) *mBlob = {};
  212. if (rhs) {
  213. mBlob = std::make_unique<blobv3>(*rhs.mBlob);
  214. } else {
  215. mBlob = {};
  216. }
  217. }
  218. return *this;
  219. }
  220. Blob& Blob::operator=(Blob&& rhs) {
  221. if (mBlob) *mBlob = {};
  222. mBlob = std::move(rhs.mBlob);
  223. return *this;
  224. }
  225. template <typename BlobType> static bool rawBlobIsEncrypted(const BlobType& blob) {
  226. if (blob.version < 2) return true;
  227. return blob.flags & (KEYSTORE_FLAG_ENCRYPTED | KEYSTORE_FLAG_SUPER_ENCRYPTED);
  228. }
  229. bool Blob::isEncrypted() const {
  230. if (mBlob->version < 2) {
  231. return true;
  232. }
  233. return mBlob->flags & KEYSTORE_FLAG_ENCRYPTED;
  234. }
  235. bool Blob::isSuperEncrypted() const {
  236. return mBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED;
  237. }
  238. bool Blob::isCriticalToDeviceEncryption() const {
  239. return mBlob->flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
  240. }
  241. inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) {
  242. return set ? (flags | flag) : (flags & ~flag);
  243. }
  244. void Blob::setEncrypted(bool encrypted) {
  245. mBlob->flags = setFlag(mBlob->flags, encrypted, KEYSTORE_FLAG_ENCRYPTED);
  246. }
  247. void Blob::setSuperEncrypted(bool superEncrypted) {
  248. mBlob->flags = setFlag(mBlob->flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
  249. }
  250. void Blob::setCriticalToDeviceEncryption(bool critical) {
  251. mBlob->flags = setFlag(mBlob->flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
  252. }
  253. void Blob::setFallback(bool fallback) {
  254. if (fallback) {
  255. mBlob->flags |= KEYSTORE_FLAG_FALLBACK;
  256. } else {
  257. mBlob->flags &= ~KEYSTORE_FLAG_FALLBACK;
  258. }
  259. }
  260. static ResponseCode writeBlob(const std::string& filename, Blob blob, blobv3* rawBlob,
  261. const std::vector<uint8_t>& aes_key, State state) {
  262. ALOGV("writing blob %s", filename.c_str());
  263. const size_t dataLength = rawBlob->length;
  264. rawBlob->length = htonl(rawBlob->length);
  265. if (blob.isEncrypted() || blob.isSuperEncrypted()) {
  266. if (state != STATE_NO_ERROR) {
  267. ALOGD("couldn't insert encrypted blob while not unlocked");
  268. return ResponseCode::LOCKED;
  269. }
  270. memset(rawBlob->initialization_vector, 0, AES_BLOCK_SIZE);
  271. if (!RAND_bytes(rawBlob->initialization_vector, kGcmIvSizeBytes)) {
  272. ALOGW("Could not read random data for: %s", filename.c_str());
  273. return ResponseCode::SYSTEM_ERROR;
  274. }
  275. auto rc = AES_gcm_encrypt(rawBlob->value /* in */, rawBlob->value /* out */, dataLength,
  276. aes_key, rawBlob->initialization_vector, rawBlob->aead_tag);
  277. if (rc != ResponseCode::NO_ERROR) return rc;
  278. }
  279. size_t fileLength = offsetof(blobv3, value) + dataLength + rawBlob->info;
  280. int out =
  281. TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
  282. if (out < 0) {
  283. ALOGW("could not open file: %s: %s", filename.c_str(), strerror(errno));
  284. return ResponseCode::SYSTEM_ERROR;
  285. }
  286. const size_t writtenBytes = writeFully(out, reinterpret_cast<uint8_t*>(rawBlob), fileLength);
  287. if (close(out) != 0) {
  288. return ResponseCode::SYSTEM_ERROR;
  289. }
  290. if (writtenBytes != fileLength) {
  291. ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
  292. unlink(filename.c_str());
  293. return ResponseCode::SYSTEM_ERROR;
  294. }
  295. return ResponseCode::NO_ERROR;
  296. }
  297. ResponseCode LockedKeyBlobEntry::writeBlobs(Blob keyBlob, Blob characteristicsBlob,
  298. const std::vector<uint8_t>& aes_key,
  299. State state) const {
  300. if (entry_ == nullptr) {
  301. return ResponseCode::SYSTEM_ERROR;
  302. }
  303. ResponseCode rc;
  304. if (keyBlob) {
  305. blobv3* rawBlob = keyBlob.mBlob.get();
  306. rc = writeBlob(entry_->getKeyBlobPath(), std::move(keyBlob), rawBlob, aes_key, state);
  307. if (rc != ResponseCode::NO_ERROR) {
  308. return rc;
  309. }
  310. }
  311. if (characteristicsBlob) {
  312. blobv3* rawBlob = characteristicsBlob.mBlob.get();
  313. rc = writeBlob(entry_->getCharacteristicsBlobPath(), std::move(characteristicsBlob),
  314. rawBlob, aes_key, state);
  315. }
  316. return rc;
  317. }
  318. ResponseCode Blob::readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
  319. State state) {
  320. ResponseCode rc;
  321. ALOGV("reading blob %s", filename.c_str());
  322. std::unique_ptr<blobv3> rawBlob = std::make_unique<blobv3>();
  323. const int in = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY));
  324. if (in < 0) {
  325. return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR;
  326. }
  327. // fileLength may be less than sizeof(mBlob)
  328. const size_t fileLength = readFully(in, (uint8_t*)rawBlob.get(), sizeof(blobv3));
  329. if (close(in) != 0) {
  330. return ResponseCode::SYSTEM_ERROR;
  331. }
  332. if (fileLength == 0) {
  333. return ResponseCode::VALUE_CORRUPTED;
  334. }
  335. if (rawBlobIsEncrypted(*rawBlob)) {
  336. if (state == STATE_LOCKED) {
  337. mBlob = std::move(rawBlob);
  338. return ResponseCode::LOCKED;
  339. }
  340. if (state == STATE_UNINITIALIZED) return ResponseCode::UNINITIALIZED;
  341. }
  342. if (fileLength < offsetof(blobv3, value)) return ResponseCode::VALUE_CORRUPTED;
  343. if (rawBlob->version == 3) {
  344. const ssize_t encryptedLength = ntohl(rawBlob->length);
  345. if (rawBlobIsEncrypted(*rawBlob)) {
  346. rc = AES_gcm_decrypt(rawBlob->value /* in */, rawBlob->value /* out */, encryptedLength,
  347. aes_key, rawBlob->initialization_vector, rawBlob->aead_tag);
  348. if (rc != ResponseCode::NO_ERROR) {
  349. // If the blob was superencrypted and decryption failed, it is
  350. // almost certain that decryption is failing due to a user's
  351. // changed master key.
  352. if ((rawBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED) &&
  353. (rc == ResponseCode::VALUE_CORRUPTED)) {
  354. return ResponseCode::KEY_PERMANENTLY_INVALIDATED;
  355. }
  356. return rc;
  357. }
  358. }
  359. } else if (rawBlob->version < 3) {
  360. blobv2& v2blob = reinterpret_cast<blobv2&>(*rawBlob);
  361. const size_t headerLength = offsetof(blobv2, encrypted);
  362. const ssize_t encryptedLength = fileLength - headerLength - v2blob.info;
  363. if (encryptedLength < 0) return ResponseCode::VALUE_CORRUPTED;
  364. if (rawBlobIsEncrypted(*rawBlob)) {
  365. if (encryptedLength % AES_BLOCK_SIZE != 0) {
  366. return ResponseCode::VALUE_CORRUPTED;
  367. }
  368. AES_KEY key;
  369. AES_set_decrypt_key(aes_key.data(), kAesKeySize * 8, &key);
  370. AES_cbc_encrypt(v2blob.encrypted, v2blob.encrypted, encryptedLength, &key,
  371. v2blob.vector, AES_DECRYPT);
  372. key = {}; // clear key
  373. uint8_t computedDigest[MD5_DIGEST_LENGTH];
  374. ssize_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
  375. MD5(v2blob.digested, digestedLength, computedDigest);
  376. if (memcmp(v2blob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
  377. return ResponseCode::VALUE_CORRUPTED;
  378. }
  379. }
  380. }
  381. const ssize_t maxValueLength = fileLength - offsetof(blobv3, value) - rawBlob->info;
  382. rawBlob->length = ntohl(rawBlob->length);
  383. if (rawBlob->length < 0 || rawBlob->length > maxValueLength ||
  384. rawBlob->length + rawBlob->info + AES_BLOCK_SIZE >
  385. static_cast<ssize_t>(sizeof(rawBlob->value))) {
  386. return ResponseCode::VALUE_CORRUPTED;
  387. }
  388. if (rawBlob->info != 0 && rawBlob->version < 3) {
  389. // move info from after padding to after data
  390. memmove(rawBlob->value + rawBlob->length, rawBlob->value + maxValueLength, rawBlob->info);
  391. }
  392. mBlob = std::move(rawBlob);
  393. return ResponseCode::NO_ERROR;
  394. }
  395. std::tuple<ResponseCode, Blob, Blob>
  396. LockedKeyBlobEntry::readBlobs(const std::vector<uint8_t>& aes_key, State state) const {
  397. std::tuple<ResponseCode, Blob, Blob> result;
  398. auto& [rc, keyBlob, characteristicsBlob] = result;
  399. if (entry_ == nullptr) return rc = ResponseCode::SYSTEM_ERROR, result;
  400. rc = keyBlob.readBlob(entry_->getKeyBlobPath(), aes_key, state);
  401. if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::UNINITIALIZED) {
  402. return result;
  403. }
  404. if (entry_->hasCharacteristicsBlob()) {
  405. characteristicsBlob.readBlob(entry_->getCharacteristicsBlobPath(), aes_key, state);
  406. }
  407. return result;
  408. }
  409. ResponseCode LockedKeyBlobEntry::deleteBlobs() const {
  410. if (entry_ == nullptr) return ResponseCode::NO_ERROR;
  411. // always try to delete both
  412. ResponseCode rc1 = (unlink(entry_->getKeyBlobPath().c_str()) && errno != ENOENT)
  413. ? ResponseCode::SYSTEM_ERROR
  414. : ResponseCode::NO_ERROR;
  415. if (rc1 != ResponseCode::NO_ERROR) {
  416. ALOGW("Failed to delete key blob file \"%s\"", entry_->getKeyBlobPath().c_str());
  417. }
  418. ResponseCode rc2 = (unlink(entry_->getCharacteristicsBlobPath().c_str()) && errno != ENOENT)
  419. ? ResponseCode::SYSTEM_ERROR
  420. : ResponseCode::NO_ERROR;
  421. if (rc2 != ResponseCode::NO_ERROR) {
  422. ALOGW("Failed to delete key characteristics file \"%s\"",
  423. entry_->getCharacteristicsBlobPath().c_str());
  424. }
  425. // then report the first error that occured
  426. if (rc1 != ResponseCode::NO_ERROR) return rc1;
  427. return rc2;
  428. }
  429. keystore::SecurityLevel Blob::getSecurityLevel() const {
  430. return keystore::flagsToSecurityLevel(mBlob->flags);
  431. }
  432. void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) {
  433. mBlob->flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX);
  434. mBlob->flags |= keystore::securityLevelToFlags(secLevel);
  435. }
  436. std::tuple<bool, keystore::AuthorizationSet, keystore::AuthorizationSet>
  437. Blob::getKeyCharacteristics() const {
  438. std::tuple<bool, keystore::AuthorizationSet, keystore::AuthorizationSet> result;
  439. auto& [success, hwEnforced, swEnforced] = result;
  440. success = false;
  441. ArrayStreamBuffer buf(mBlob->value);
  442. std::istream in(&buf);
  443. // only the characteristics cache has both sets
  444. if (getType() == TYPE_KEY_CHARACTERISTICS_CACHE) {
  445. hwEnforced.Deserialize(&in);
  446. } else if (getType() != TYPE_KEY_CHARACTERISTICS) {
  447. // if its not the cache and not the legacy characteristics file we have no business
  448. // here
  449. return result;
  450. }
  451. swEnforced.Deserialize(&in);
  452. success = !in.bad();
  453. return result;
  454. }
  455. bool Blob::putKeyCharacteristics(const keystore::AuthorizationSet& hwEnforced,
  456. const keystore::AuthorizationSet& swEnforced) {
  457. if (!mBlob) mBlob = std::make_unique<blobv3>();
  458. mBlob->version = CURRENT_BLOB_VERSION;
  459. ArrayStreamBuffer buf(mBlob->value);
  460. std::ostream out(&buf);
  461. hwEnforced.Serialize(&out);
  462. swEnforced.Serialize(&out);
  463. if (out.bad()) return false;
  464. setType(TYPE_KEY_CHARACTERISTICS_CACHE);
  465. mBlob->length = out.tellp();
  466. return true;
  467. }
  468. void LockedKeyBlobEntry::put(const KeyBlobEntry& entry) {
  469. std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
  470. locked_blobs_.erase(entry);
  471. lock.unlock();
  472. locked_blobs_mutex_cond_var_.notify_all();
  473. }
  474. LockedKeyBlobEntry::~LockedKeyBlobEntry() {
  475. if (entry_ != nullptr) put(*entry_);
  476. }
  477. LockedKeyBlobEntry LockedKeyBlobEntry::get(KeyBlobEntry entry) {
  478. std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
  479. locked_blobs_mutex_cond_var_.wait(
  480. lock, [&] { return locked_blobs_.find(entry) == locked_blobs_.end(); });
  481. auto [iterator, success] = locked_blobs_.insert(std::move(entry));
  482. if (!success) return {};
  483. return LockedKeyBlobEntry(*iterator);
  484. }
  485. std::set<KeyBlobEntry> LockedKeyBlobEntry::locked_blobs_;
  486. std::mutex LockedKeyBlobEntry::locked_blobs_mutex_;
  487. std::condition_variable LockedKeyBlobEntry::locked_blobs_mutex_cond_var_;
  488. /* Here is the encoding of key names. This is necessary in order to allow arbitrary
  489. * characters in key names. Characters in [0-~] are not encoded. Others are encoded
  490. * into two bytes. The first byte is one of [+-.] which represents the first
  491. * two bits of the character. The second byte encodes the rest of the bits into
  492. * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
  493. * that Base64 cannot be used here due to the need of prefix match on keys. */
  494. std::string encodeKeyName(const std::string& keyName) {
  495. std::string encodedName;
  496. encodedName.reserve(keyName.size() * 2);
  497. auto in = keyName.begin();
  498. while (in != keyName.end()) {
  499. // Input character needs to be encoded.
  500. if (*in < '0' || *in > '~') {
  501. // Encode the two most-significant bits of the input char in the first
  502. // output character, by counting up from 43 ('+').
  503. encodedName.append(1, '+' + (uint8_t(*in) >> 6));
  504. // Encode the six least-significant bits of the input char in the second
  505. // output character, by counting up from 48 ('0').
  506. // This is safe because the maximum value is 112, which is the
  507. // character 'p'.
  508. encodedName.append(1, '0' + (*in & 0x3F));
  509. } else {
  510. // No need to encode input char - append as-is.
  511. encodedName.append(1, *in);
  512. }
  513. ++in;
  514. }
  515. return encodedName;
  516. }
  517. std::string decodeKeyName(const std::string& encodedName) {
  518. std::string decodedName;
  519. decodedName.reserve(encodedName.size());
  520. auto in = encodedName.begin();
  521. bool multichar = false;
  522. char c;
  523. while (in != encodedName.end()) {
  524. if (multichar) {
  525. // Second part of a multi-character encoding. Turn off the multichar
  526. // flag and set the six least-significant bits of c to the value originally
  527. // encoded by counting up from '0'.
  528. multichar = false;
  529. decodedName.append(1, c | (uint8_t(*in) - '0'));
  530. } else if (*in >= '+' && *in <= '.') {
  531. // First part of a multi-character encoding. Set the multichar flag
  532. // and set the two most-significant bits of c to be the two bits originally
  533. // encoded by counting up from '+'.
  534. multichar = true;
  535. c = (*in - '+') << 6;
  536. } else {
  537. // Regular character, append as-is.
  538. decodedName.append(1, *in);
  539. }
  540. ++in;
  541. }
  542. // mulitchars at the end get truncated
  543. return decodedName;
  544. }
  545. std::string KeyBlobEntry::getKeyBlobBaseName() const {
  546. std::stringstream s;
  547. if (masterkey_) {
  548. s << alias_;
  549. } else {
  550. s << uid_ << "_" << encodeKeyName(alias_);
  551. }
  552. return s.str();
  553. }
  554. std::string KeyBlobEntry::getKeyBlobPath() const {
  555. std::stringstream s;
  556. if (masterkey_) {
  557. s << user_dir_ << "/" << alias_;
  558. } else {
  559. s << user_dir_ << "/" << uid_ << "_" << encodeKeyName(alias_);
  560. }
  561. return s.str();
  562. }
  563. std::string KeyBlobEntry::getCharacteristicsBlobBaseName() const {
  564. std::stringstream s;
  565. if (!masterkey_) s << "." << uid_ << "_chr_" << encodeKeyName(alias_);
  566. return s.str();
  567. }
  568. std::string KeyBlobEntry::getCharacteristicsBlobPath() const {
  569. std::stringstream s;
  570. if (!masterkey_)
  571. s << user_dir_ << "/"
  572. << "." << uid_ << "_chr_" << encodeKeyName(alias_);
  573. return s.str();
  574. }
  575. bool KeyBlobEntry::hasKeyBlob() const {
  576. int trys = 3;
  577. while (trys--) {
  578. if (!access(getKeyBlobPath().c_str(), R_OK | W_OK)) return true;
  579. if (errno == ENOENT) return false;
  580. LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")"
  581. << " while checking for key blob";
  582. if (errno != EAGAIN) break;
  583. }
  584. return false;
  585. }
  586. bool KeyBlobEntry::hasCharacteristicsBlob() const {
  587. int trys = 3;
  588. while (trys--) {
  589. if (!access(getCharacteristicsBlobPath().c_str(), R_OK | W_OK)) return true;
  590. if (errno == ENOENT) return false;
  591. LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")"
  592. << " while checking for key characteristics blob";
  593. if (errno != EAGAIN) break;
  594. }
  595. return false;
  596. }
  597. static std::tuple<bool, uid_t, std::string> filename2UidAlias(const std::string& filepath) {
  598. std::tuple<bool, uid_t, std::string> result;
  599. auto& [success, uid, alias] = result;
  600. success = false;
  601. auto filenamebase = filepath.find_last_of('/');
  602. std::string filename =
  603. filenamebase == std::string::npos ? filepath : filepath.substr(filenamebase + 1);
  604. if (filename[0] == '.') return result;
  605. auto sep = filename.find('_');
  606. if (sep == std::string::npos) return result;
  607. std::stringstream s(filename.substr(0, sep));
  608. s >> uid;
  609. if (!s) return result;
  610. alias = decodeKeyName(filename.substr(sep + 1));
  611. success = true;
  612. return result;
  613. }
  614. std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>>
  615. LockedKeyBlobEntry::list(const std::string& user_dir,
  616. std::function<bool(uid_t, const std::string&)> filter) {
  617. std::list<LockedKeyBlobEntry> matches;
  618. // This is a fence against any concurrent database accesses during database iteration.
  619. // Only the keystore thread can lock entries. So it cannot be starved
  620. // by workers grabbing new individual locks. We just wait here until all
  621. // workers have relinquished their locked files.
  622. std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
  623. locked_blobs_mutex_cond_var_.wait(lock, [&] { return locked_blobs_.empty(); });
  624. DIR* dir = opendir(user_dir.c_str());
  625. if (!dir) {
  626. ALOGW("can't open directory for user: %s", strerror(errno));
  627. return std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>&&>{ResponseCode::SYSTEM_ERROR,
  628. std::move(matches)};
  629. }
  630. struct dirent* file;
  631. while ((file = readdir(dir)) != nullptr) {
  632. // We only care about files.
  633. if (file->d_type != DT_REG) {
  634. continue;
  635. }
  636. // Skip anything that starts with a "."
  637. if (file->d_name[0] == '.') {
  638. continue;
  639. }
  640. auto [success, uid, alias] = filename2UidAlias(file->d_name);
  641. if (!success) {
  642. ALOGW("could not parse key filename \"%s\"", file->d_name);
  643. continue;
  644. }
  645. if (!filter(uid, alias)) continue;
  646. auto [iterator, dummy] = locked_blobs_.emplace(alias, user_dir, uid);
  647. matches.push_back(*iterator);
  648. }
  649. closedir(dir);
  650. return std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>&&>{ResponseCode::NO_ERROR,
  651. std::move(matches)};
  652. }