summaryrefslogtreecommitdiffstats
path: root/integrity_assured_key_blob.cpp
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-05-20 16:36:24 -0600
committerShawn Willden <swillden@google.com>2015-05-28 07:28:51 -0600
commit2beb628bfefae72fa6bb84a6235da7e3de532823 (patch)
tree53fdd19f54afc714b37505cbea0dc31e1ecadda9 /integrity_assured_key_blob.cpp
parentde7e66c3692073eb967f01cc8281441709701e2d (diff)
downloadandroid_system_keymaster-2beb628bfefae72fa6bb84a6235da7e3de532823.tar.gz
android_system_keymaster-2beb628bfefae72fa6bb84a6235da7e3de532823.tar.bz2
android_system_keymaster-2beb628bfefae72fa6bb84a6235da7e3de532823.zip
Delegate RSA keys to keymaster0 in SoftKeymasterDevice.
Bug: 20912868 Change-Id: I515a125f1247357d2cd9b4633c3b223590848093
Diffstat (limited to 'integrity_assured_key_blob.cpp')
-rw-r--r--integrity_assured_key_blob.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/integrity_assured_key_blob.cpp b/integrity_assured_key_blob.cpp
new file mode 100644
index 0000000..1376cff
--- /dev/null
+++ b/integrity_assured_key_blob.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "integrity_assured_key_blob.h"
+
+#include <assert.h>
+
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+
+#include "openssl_err.h"
+
+namespace keymaster {
+
+static const uint8_t BLOB_VERSION = 0;
+static const size_t HMAC_SIZE = 8;
+static const char HMAC_KEY[] = "IntegrityAssuredBlob0";
+
+inline size_t min(size_t a, size_t b) {
+ if (a < b)
+ return a;
+ return b;
+}
+
+class HmacCleanup {
+ public:
+ HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
+ ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }
+
+ private:
+ HMAC_CTX* ctx_;
+};
+
+keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
+ const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
+ size_t hidden_bytes_size = hidden.SerializedSize();
+ UniquePtr<uint8_t[]> hidden_bytes(new uint8_t[hidden_bytes_size]);
+ hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
+
+ HMAC_CTX ctx;
+ HMAC_CTX_init(&ctx);
+ const EVP_MD* md = EVP_sha256();
+ if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */))
+ return TranslateLastOpenSslError();
+ HmacCleanup cleanup(&ctx);
+
+ uint8_t tmp[EVP_MAX_MD_SIZE];
+ unsigned tmp_len;
+ if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
+ !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) || //
+ !HMAC_Final(&ctx, tmp, &tmp_len))
+ return TranslateLastOpenSslError();
+
+ assert(tmp_len >= HMAC_SIZE);
+ memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));
+
+ return KM_ERROR_OK;
+}
+
+keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
+ const AuthorizationSet& hidden,
+ const AuthorizationSet& hw_enforced,
+ const AuthorizationSet& sw_enforced,
+ KeymasterKeyBlob* key_blob) {
+ size_t size = 1 /* version */ + //
+ key_material.SerializedSize() + //
+ hw_enforced.SerializedSize() + //
+ sw_enforced.SerializedSize() + //
+ HMAC_SIZE;
+
+ if (!key_blob->Reset(size))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ uint8_t* p = key_blob->writable_data();
+ *p++ = BLOB_VERSION;
+ p = key_material.Serialize(p, key_blob->end());
+ p = hw_enforced.Serialize(p, key_blob->end());
+ p = sw_enforced.Serialize(p, key_blob->end());
+
+ return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
+}
+
+keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
+ const AuthorizationSet& hidden,
+ KeymasterKeyBlob* key_material,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) {
+ const uint8_t* p = key_blob.begin();
+ const uint8_t* end = key_blob.end();
+
+ uint8_t computed_hmac[HMAC_SIZE];
+ keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
+ hidden, computed_hmac);
+ if (error != KM_ERROR_OK)
+ return error;
+
+ if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
+ return KM_ERROR_INVALID_KEY_BLOB;
+
+ if (*p != BLOB_VERSION)
+ return KM_ERROR_INVALID_KEY_BLOB;
+ ++p;
+
+ if (!key_material->Deserialize(&p, end) || //
+ !hw_enforced->Deserialize(&p, end) || //
+ !sw_enforced->Deserialize(&p, end))
+ return KM_ERROR_INVALID_KEY_BLOB;
+
+ return KM_ERROR_OK;
+}
+
+} // namespace keymaster;