soft_keymaster_enforcement.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. **
  3. ** Copyright 2017, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. #include <keymaster/km_openssl/soft_keymaster_enforcement.h>
  18. #include <assert.h>
  19. #include <time.h>
  20. #include <openssl/cmac.h>
  21. #include <openssl/evp.h>
  22. #include <openssl/hmac.h>
  23. #include <openssl/rand.h>
  24. #include <keymaster/km_openssl/ckdf.h>
  25. #include <keymaster/km_openssl/openssl_err.h>
  26. #include <keymaster/km_openssl/openssl_utils.h>
  27. namespace keymaster {
  28. namespace {
  29. constexpr uint8_t kFakeKeyAgreementKey[32] = {};
  30. constexpr const char* kSharedHmacLabel = "KeymasterSharedMac";
  31. constexpr const char* kMacVerificationString = "Keymaster HMAC Verification";
  32. constexpr const char* kAuthVerificationLabel = "Auth Verification";
  33. class EvpMdCtx {
  34. public:
  35. EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
  36. ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
  37. EVP_MD_CTX* get() { return &ctx_; }
  38. private:
  39. EVP_MD_CTX ctx_;
  40. };
  41. } // anonymous namespace
  42. uint64_t SoftKeymasterEnforcement::get_current_time_ms() const {
  43. struct timespec tp;
  44. int err = clock_gettime(CLOCK_BOOTTIME, &tp);
  45. if (err || tp.tv_sec < 0) return 0;
  46. return static_cast<uint64_t>(tp.tv_sec) * 1000 + static_cast<uint64_t>(tp.tv_nsec) / 1000000;
  47. }
  48. bool SoftKeymasterEnforcement::CreateKeyId(const keymaster_key_blob_t& key_blob,
  49. km_id_t* keyid) const {
  50. EvpMdCtx ctx;
  51. uint8_t hash[EVP_MAX_MD_SIZE];
  52. unsigned int hash_len;
  53. if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
  54. EVP_DigestUpdate(ctx.get(), key_blob.key_material, key_blob.key_material_size) &&
  55. EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
  56. assert(hash_len >= sizeof(*keyid));
  57. memcpy(keyid, hash, sizeof(*keyid));
  58. return true;
  59. }
  60. return false;
  61. }
  62. keymaster_error_t
  63. SoftKeymasterEnforcement::GetHmacSharingParameters(HmacSharingParameters* params) {
  64. if (!have_saved_params_) {
  65. saved_params_.seed = {};
  66. RAND_bytes(saved_params_.nonce, 32);
  67. have_saved_params_ = true;
  68. }
  69. params->seed = saved_params_.seed;
  70. memcpy(params->nonce, saved_params_.nonce, sizeof(params->nonce));
  71. return KM_ERROR_OK;
  72. }
  73. namespace {
  74. DEFINE_OPENSSL_OBJECT_POINTER(HMAC_CTX);
  75. keymaster_error_t hmacSha256(const keymaster_key_blob_t& key, const keymaster_blob_t data_chunks[],
  76. size_t data_chunk_count, KeymasterBlob* output) {
  77. if (!output) return KM_ERROR_UNEXPECTED_NULL_POINTER;
  78. unsigned digest_len = SHA256_DIGEST_LENGTH;
  79. if (!output->Reset(digest_len)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
  80. HMAC_CTX_Ptr ctx(HMAC_CTX_new());
  81. if (!HMAC_Init_ex(ctx.get(), key.key_material, key.key_material_size, EVP_sha256(),
  82. nullptr /* engine*/)) {
  83. return TranslateLastOpenSslError();
  84. }
  85. for (size_t i = 0; i < data_chunk_count; i++) {
  86. auto& chunk = data_chunks[i];
  87. if (!HMAC_Update(ctx.get(), chunk.data, chunk.data_length)) {
  88. return TranslateLastOpenSslError();
  89. }
  90. }
  91. if (!HMAC_Final(ctx.get(), output->writable_data(), &digest_len)) {
  92. return TranslateLastOpenSslError();
  93. }
  94. if (digest_len != output->data_length) return KM_ERROR_UNKNOWN_ERROR;
  95. return KM_ERROR_OK;
  96. }
  97. // Helpers for converting types to keymaster_blob_t, for easy feeding of hmacSha256.
  98. template <typename T> inline keymaster_blob_t toBlob(const T& t) {
  99. return {reinterpret_cast<const uint8_t*>(&t), sizeof(t)};
  100. }
  101. inline keymaster_blob_t toBlob(const char* str) {
  102. return {reinterpret_cast<const uint8_t*>(str), strlen(str)};
  103. }
  104. // Perhaps these shoud be in utils, but the impact of that needs to be considered carefully. For
  105. // now, just define it here.
  106. inline bool operator==(const keymaster_blob_t& a, const keymaster_blob_t& b) {
  107. if (!a.data_length && !b.data_length) return true;
  108. if (!(a.data && b.data)) return a.data == b.data;
  109. return (a.data_length == b.data_length && !memcmp(a.data, b.data, a.data_length));
  110. }
  111. bool operator==(const HmacSharingParameters& a, const HmacSharingParameters& b) {
  112. return a.seed == b.seed && !memcmp(a.nonce, b.nonce, sizeof(a.nonce));
  113. }
  114. } // namespace
  115. keymaster_error_t
  116. SoftKeymasterEnforcement::ComputeSharedHmac(const HmacSharingParametersArray& params_array,
  117. KeymasterBlob* sharingCheck) {
  118. size_t num_chunks = params_array.num_params * 2;
  119. UniquePtr<keymaster_blob_t[]> context_chunks(new (std::nothrow) keymaster_blob_t[num_chunks]);
  120. if (!context_chunks.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
  121. bool found_mine = false;
  122. auto context_chunks_pos = context_chunks.get();
  123. for (auto& params : array_range(params_array.params_array, params_array.num_params)) {
  124. *context_chunks_pos++ = params.seed;
  125. *context_chunks_pos++ = {params.nonce, sizeof(params.nonce)};
  126. found_mine = found_mine || params == saved_params_;
  127. }
  128. assert(context_chunks_pos - num_chunks == context_chunks.get());
  129. if (!found_mine) return KM_ERROR_INVALID_ARGUMENT;
  130. if (!hmac_key_.Reset(SHA256_DIGEST_LENGTH)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
  131. keymaster_error_t error = ckdf(
  132. KeymasterKeyBlob(kFakeKeyAgreementKey, sizeof(kFakeKeyAgreementKey)),
  133. KeymasterBlob(reinterpret_cast<const uint8_t*>(kSharedHmacLabel), strlen(kSharedHmacLabel)),
  134. context_chunks.get(), num_chunks, //
  135. &hmac_key_);
  136. if (error != KM_ERROR_OK) return error;
  137. keymaster_blob_t data = {reinterpret_cast<const uint8_t*>(kMacVerificationString),
  138. strlen(kMacVerificationString)};
  139. keymaster_blob_t data_chunks[] = {data};
  140. return hmacSha256(hmac_key_, data_chunks, 1, sharingCheck);
  141. }
  142. VerifyAuthorizationResponse
  143. SoftKeymasterEnforcement::VerifyAuthorization(const VerifyAuthorizationRequest& request) {
  144. // The only thing this implementation provides is timestamp and security level. Note that this
  145. // is an acceptable implementation strategy for production use as well. Additional verification
  146. // need only be provided by an implementation if it is interoperating with another
  147. // implementation that requires more.
  148. VerifyAuthorizationResponse response;
  149. response.token.challenge = request.challenge;
  150. response.token.timestamp = get_current_time_ms();
  151. response.token.security_level = SecurityLevel();
  152. keymaster_blob_t data_chunks[] = {
  153. toBlob(kAuthVerificationLabel),
  154. toBlob(response.token.challenge),
  155. toBlob(response.token.timestamp),
  156. toBlob(response.token.security_level),
  157. {}, // parametersVerified
  158. };
  159. response.error = hmacSha256(hmac_key_, data_chunks, 5, &response.token.mac);
  160. return response;
  161. }
  162. } // namespace keymaster