Merge "Fix Android Compiler Warning in system/keymaster"
am: d34d9f7a52
Change-Id: If92d8f6fc1d129fcf55b33b3d9879252f61c77c4
diff --git a/Makefile b/Makefile
index 656c4e5..51f8db3 100644
--- a/Makefile
+++ b/Makefile
@@ -28,11 +28,11 @@
external/gtest \
system/security/softkeymaster \
system/security/keystore
-GTEST=$(BASE)/external/gtest
+GTEST=$(BASE)/external/googletest/googletest
INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
-I $(BASE)/libnativehelper/include/nativehelper \
- -I $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
+ -I $(GTEST)/include -isystem $(GTEST) -Iinclude -I$(BASE)/../boringssl/include
ifdef FORCE_32_BIT
ARCH_FLAGS = -m32
diff --git a/android_keymaster.cpp b/android_keymaster.cpp
index 47ebb16..0a62ff4 100644
--- a/android_keymaster.cpp
+++ b/android_keymaster.cpp
@@ -402,6 +402,12 @@
if (response->error != KM_ERROR_OK)
return;
+ keymaster_blob_t attestation_application_id;
+ if (request.attest_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID,
+ &attestation_application_id)) {
+ sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_application_id);
+ }
+
response->error = key->GenerateAttestation(*context_, request.attest_params, tee_enforced,
sw_enforced, &response->certificate_chain);
}
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index ce85316..33bb58f 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -29,6 +29,7 @@
#include "android_keymaster_test_utils.h"
#include "attestation_record.h"
+#include "hmac_key.h"
#include "keymaster0_engine.h"
#include "openssl_utils.h"
@@ -84,7 +85,8 @@
class TestKeymasterContext : public SoftKeymasterContext {
public:
TestKeymasterContext() {}
- explicit TestKeymasterContext(const string& root_of_trust) : SoftKeymasterContext(root_of_trust) {}
+ explicit TestKeymasterContext(const string& root_of_trust)
+ : SoftKeymasterContext(root_of_trust) {}
KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
@@ -112,13 +114,14 @@
int keymaster0_calls() const override { return 0; }
bool is_keymaster1_hw() const override { return false; }
KeymasterContext* keymaster_context() const override { return context_; }
+ string name() const override { return "Soft Keymaster2"; }
private:
mutable TestKeymasterContext* context_;
};
/**
- * Test instance creator that builds keymaster1 instances which wrap a faked hardware keymaster0
+ * Test instance creator that builds keymaster2 instances which wrap a faked hardware keymaster0
* instance, with or without EC support.
*/
class Keymaster0AdapterTestInstanceCreator : public Keymaster2TestInstanceCreator {
@@ -166,6 +169,10 @@
int keymaster0_calls() const override { return counting_keymaster0_device_->count(); }
bool is_keymaster1_hw() const override { return false; }
KeymasterContext* keymaster_context() const override { return context_; }
+ string name() const override {
+ return string("Wrapped fake keymaster0 ") + (support_ec_ ? "with" : "without") +
+ " EC support";
+ }
private:
mutable TestKeymasterContext* context_;
@@ -177,7 +184,7 @@
* Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
* instance, with minimal digest support.
*/
-class Sha256OnlyKeymaster2TestInstanceCreator : public Keymaster2TestInstanceCreator {
+class Sha256OnlyKeymaster1TestInstanceCreator : public Keymaster2TestInstanceCreator {
keymaster2_device_t* CreateDevice() const {
std::cerr << "Creating keymaster1-backed device that supports only SHA256";
@@ -202,6 +209,42 @@
int minimal_digest_set() const override { return true; }
bool is_keymaster1_hw() const override { return true; }
KeymasterContext* keymaster_context() const override { return context_; }
+ string name() const override { return "Wrapped fake keymaster1 w/minimal digests"; }
+
+ private:
+ mutable TestKeymasterContext* context_;
+};
+
+/**
+ * Test instance creator that builds a SoftKeymasterDevice which wraps a fake hardware keymaster1
+ * instance, with full digest support
+ */
+class Keymaster1TestInstanceCreator : public Keymaster2TestInstanceCreator {
+ keymaster2_device_t* CreateDevice() const {
+ std::cerr << "Creating keymaster1-backed device";
+
+ // fake_device doesn't leak because device (below) takes ownership of it.
+ keymaster1_device_t* fake_device =
+ (new SoftKeymasterDevice(new TestKeymasterContext("PseudoHW")))->keymaster_device();
+
+ // device doesn't leak; it's cleaned up by device->keymaster_device()->common.close().
+ context_ = new TestKeymasterContext;
+ SoftKeymasterDevice* device = new SoftKeymasterDevice(context_);
+ device->SetHardwareDevice(fake_device);
+
+ AuthorizationSet version_info(AuthorizationSetBuilder()
+ .Authorization(TAG_OS_VERSION, kOsVersion)
+ .Authorization(TAG_OS_PATCHLEVEL, kOsPatchLevel));
+ device->keymaster2_device()->configure(device->keymaster2_device(), &version_info);
+ return device->keymaster2_device();
+ }
+
+ bool algorithm_in_km0_hardware(keymaster_algorithm_t) const override { return false; }
+ int keymaster0_calls() const override { return 0; }
+ int minimal_digest_set() const override { return false; }
+ bool is_keymaster1_hw() const override { return true; }
+ KeymasterContext* keymaster_context() const override { return context_; }
+ string name() const override { return "Wrapped fake keymaster1 w/full digests"; }
private:
mutable TestKeymasterContext* context_;
@@ -211,7 +254,8 @@
InstanceCreatorPtr(new SoftKeymasterTestInstanceCreator),
InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(true /* support_ec */)),
InstanceCreatorPtr(new Keymaster0AdapterTestInstanceCreator(false /* support_ec */)),
- InstanceCreatorPtr(new Sha256OnlyKeymaster2TestInstanceCreator));
+ InstanceCreatorPtr(new Keymaster1TestInstanceCreator),
+ InstanceCreatorPtr(new Sha256OnlyKeymaster1TestInstanceCreator));
class NewKeyGeneration : public Keymaster2Test {
protected:
@@ -368,6 +412,26 @@
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
+TEST_P(NewKeyGeneration, CheckKeySizes) {
+ for (size_t key_size = 0; key_size <= kMaxHmacKeyLengthBits + 10; ++key_size) {
+ if (key_size < kMinHmacKeyLengthBits || key_size > kMaxHmacKeyLengthBits ||
+ key_size % 8 != 0) {
+ EXPECT_EQ(KM_ERROR_UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+ << "HMAC key size " << key_size << " invalid.";
+ } else {
+ EXPECT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 256)));
+ }
+ }
+ EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
TEST_P(NewKeyGeneration, HmacMultipleDigests) {
ASSERT_EQ(KM_ERROR_UNSUPPORTED_DIGEST,
GenerateKey(AuthorizationSetBuilder()
@@ -521,10 +585,8 @@
begin_params.push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN);
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_SIGN, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
string signature;
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&signature));
+ EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &signature));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(2, GetParam()->keymaster0_calls());
@@ -757,10 +819,6 @@
}
TEST_P(SigningOperationsTest, HmacSha1Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA1)
@@ -774,10 +832,6 @@
}
TEST_P(SigningOperationsTest, HmacSha224Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_224)
@@ -791,10 +845,6 @@
}
TEST_P(SigningOperationsTest, HmacSha256Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_256)
@@ -808,10 +858,6 @@
}
TEST_P(SigningOperationsTest, HmacSha384Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_384)
@@ -826,10 +872,6 @@
}
TEST_P(SigningOperationsTest, HmacSha512Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate other digests for HMAC.
- return;
-
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_512)
@@ -856,84 +898,6 @@
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase1) {
- uint8_t key_data[] = {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- };
- string message = "Hi There";
- uint8_t sha_224_expected[] = {
- 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d,
- 0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22,
- };
- uint8_t sha_256_expected[] = {
- 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf,
- 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83,
- 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
- };
- uint8_t sha_384_expected[] = {
- 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4,
- 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
- 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9,
- 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6,
- };
- uint8_t sha_512_expected[] = {
- 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a,
- 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0,
- 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7,
- 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e,
- 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54,
- };
-
- string key = make_string(key_data);
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
-TEST_P(SigningOperationsTest, HmacRfc4231TestCase2) {
- string key = "Jefe";
- string message = "what do ya want for nothing?";
- uint8_t sha_224_expected[] = {
- 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e,
- 0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44,
- };
- uint8_t sha_256_expected[] = {
- 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24,
- 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27,
- 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
- };
- uint8_t sha_384_expected[] = {
- 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2,
- 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
- 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca,
- 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49,
- };
- uint8_t sha_512_expected[] = {
- 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b,
- 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27,
- 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99,
- 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3,
- 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37,
- };
-
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
-
- EXPECT_EQ(0, GetParam()->keymaster0_calls());
-}
-
TEST_P(SigningOperationsTest, HmacRfc4231TestCase3) {
string key(20, 0xaa);
string message(50, 0xdd);
@@ -960,13 +924,10 @@
0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
};
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1001,13 +962,10 @@
0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd,
};
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1033,12 +991,10 @@
0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
};
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1070,12 +1026,10 @@
0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98,
};
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1109,12 +1063,10 @@
0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58,
};
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_256, make_string(sha_256_expected));
- if (!GetParam()->minimal_digest_set()) {
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_224, make_string(sha_224_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
- CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
- }
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_384, make_string(sha_384_expected));
+ CheckHmacTestVector(key, message, KM_DIGEST_SHA_2_512, make_string(sha_512_expected));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -1233,10 +1185,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1259,10 +1208,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1333,10 +1279,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1359,10 +1302,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -1520,10 +1460,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
}
TEST_P(VerificationOperationsTest, EcdsaSha224Success) {
@@ -1544,10 +1481,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(message, signature, &result));
}
TEST_P(VerificationOperationsTest, EcdsaAllDigestsAndKeySizes) {
@@ -1579,10 +1513,6 @@
}
TEST_P(VerificationOperationsTest, HmacSha1Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA1)
@@ -1596,10 +1526,6 @@
}
TEST_P(VerificationOperationsTest, HmacSha224Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_224)
@@ -1644,18 +1570,12 @@
AuthorizationSet begin_params(client_params());
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_INVALID_MAC_LENGTH, FinishOperation(message, signature, &result));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
TEST_P(VerificationOperationsTest, HmacSha384Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_384)
@@ -1669,10 +1589,6 @@
}
TEST_P(VerificationOperationsTest, HmacSha512Success) {
- if (GetParam()->minimal_digest_set())
- // Can't emulate missing digests for HMAC.
- return;
-
GenerateKey(AuthorizationSetBuilder()
.HmacKey(128)
.Digest(KM_DIGEST_SHA_2_512)
@@ -2033,8 +1949,7 @@
BN_bn2bin(rsa->n, modulus_buf.get());
message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
+ EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, "", &result));
if (GetParam()->algorithm_in_km0_hardware(KM_ALGORITHM_RSA))
EXPECT_EQ(4, GetParam()->keymaster0_calls());
@@ -2425,10 +2340,7 @@
begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
string ciphertext;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &ciphertext, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(&ciphertext));
+ EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH, FinishOperation(message, "", &ciphertext));
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
@@ -3603,6 +3515,9 @@
expected_tee_enforced.Sort();
EXPECT_EQ(expected_tee_enforced, att_tee_enforced);
+ delete[] att_challenge.data;
+ delete[] att_unique_id.data;
+
return true;
}
diff --git a/android_keymaster_test_utils.cpp b/android_keymaster_test_utils.cpp
index ecaee62..41135f3 100644
--- a/android_keymaster_test_utils.cpp
+++ b/android_keymaster_test_utils.cpp
@@ -169,6 +169,10 @@
namespace test {
+std::ostream& operator<<(std::ostream& os, const InstanceCreatorPtr& instance_creator) {
+ return os << instance_creator->name();
+}
+
Keymaster2Test::Keymaster2Test() : op_handle_(OP_HANDLE_SENTINEL) {
memset(&characteristics_, 0, sizeof(characteristics_));
blob_.key_material = nullptr;
@@ -291,24 +295,26 @@
}
keymaster_error_t Keymaster2Test::FinishOperation(string* output) {
- return FinishOperation("", output);
+ return FinishOperation("", "", output);
}
-keymaster_error_t Keymaster2Test::FinishOperation(const string& signature, string* output) {
+keymaster_error_t Keymaster2Test::FinishOperation(const string& input, const string& signature,
+ string* output) {
AuthorizationSet additional_params;
AuthorizationSet output_params;
- return FinishOperation(additional_params, signature, &output_params, output);
+ return FinishOperation(additional_params, input, signature, &output_params, output);
}
keymaster_error_t Keymaster2Test::FinishOperation(const AuthorizationSet& additional_params,
- const string& signature,
+ const string& input, const string& signature,
AuthorizationSet* output_params, string* output) {
+ keymaster_blob_t inp = {reinterpret_cast<const uint8_t*>(input.c_str()), input.length()};
keymaster_blob_t sig = {reinterpret_cast<const uint8_t*>(signature.c_str()),
signature.length()};
keymaster_blob_t out_tmp;
keymaster_key_param_set_t out_params;
- keymaster_error_t error = device()->finish(device(), op_handle_, &additional_params,
- nullptr /* input */, &sig, &out_params, &out_tmp);
+ keymaster_error_t error = device()->finish(device(), op_handle_, &additional_params, &inp, &sig,
+ &out_params, &out_tmp);
if (error != KM_ERROR_OK) {
EXPECT_TRUE(out_tmp.data == nullptr);
EXPECT_TRUE(out_params.params == nullptr);
@@ -353,10 +359,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_params */));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(&result));
+ EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, "" /* signature */, &result));
return result;
}
@@ -367,11 +370,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, begin_out_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
- &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, "", &result));
+ EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, message, "" /* signature */, &result));
return result;
}
@@ -382,11 +381,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, begin_params, output_params));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(update_params, message, nullptr /* output_params */,
- &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, signature, &result));
+ EXPECT_EQ(KM_ERROR_OK, FinishOperation(update_params, message, signature, &result));
return result;
}
@@ -395,10 +390,7 @@
EXPECT_EQ(KM_ERROR_OK, BeginOperation(purpose, client_params(), NULL /* output_params */));
string result;
- size_t input_consumed;
- EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &result, &input_consumed));
- EXPECT_EQ(message.size(), input_consumed);
- EXPECT_EQ(KM_ERROR_OK, FinishOperation(signature, &result));
+ EXPECT_EQ(KM_ERROR_OK, FinishOperation(message, signature, &result));
return result;
}
@@ -622,8 +614,8 @@
return error;
}
-void Keymaster2Test::CheckHmacTestVector(const string& key, const string& message, keymaster_digest_t digest,
- string expected_mac) {
+void Keymaster2Test::CheckHmacTestVector(const string& key, const string& message,
+ keymaster_digest_t digest, string expected_mac) {
ASSERT_EQ(KM_ERROR_OK, ImportKey(AuthorizationSetBuilder()
.HmacKey(key.size() * 8)
.Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
@@ -678,7 +670,8 @@
class Sha256OnlyWrapper {
public:
- explicit Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device) : wrapped_device_(wrapped_device) {
+ explicit Sha256OnlyWrapper(const keymaster1_device_t* wrapped_device)
+ : wrapped_device_(wrapped_device) {
new_module = *wrapped_device_->common.module;
new_module_name = std::string("SHA 256-only ") + wrapped_device_->common.module->name;
diff --git a/android_keymaster_test_utils.h b/android_keymaster_test_utils.h
index 5dd0f76..13832bb 100644
--- a/android_keymaster_test_utils.h
+++ b/android_keymaster_test_utils.h
@@ -166,11 +166,15 @@
virtual int minimal_digest_set() const { return false; }
virtual bool is_keymaster1_hw() const = 0;
virtual KeymasterContext* keymaster_context() const = 0;
+
+ virtual std::string name() const = 0;
};
// Use a shared_ptr because it's copyable.
typedef std::shared_ptr<Keymaster2TestInstanceCreator> InstanceCreatorPtr;
+std::ostream& operator<<(std::ostream& os, const InstanceCreatorPtr& instance_creator);
+
const uint64_t OP_HANDLE_SENTINEL = 0xFFFFFFFFFFFFFFFF;
class Keymaster2Test : public testing::TestWithParam<InstanceCreatorPtr> {
protected:
@@ -201,14 +205,17 @@
std::string* output, size_t* input_consumed);
keymaster_error_t FinishOperation(std::string* output);
- keymaster_error_t FinishOperation(const std::string& signature, std::string* output);
+ keymaster_error_t FinishOperation(const std::string& input, const std::string& signature,
+ std::string* output);
keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
- const std::string& signature, std::string* output) {
- return FinishOperation(additional_params, signature, nullptr /* output_params */, output);
+ const std::string& input, const std::string& signature,
+ std::string* output) {
+ return FinishOperation(additional_params, input, signature, nullptr /* output_params */,
+ output);
}
keymaster_error_t FinishOperation(const AuthorizationSet& additional_params,
- const std::string& signature, AuthorizationSet* output_params,
- std::string* output);
+ const std::string& input, const std::string& signature,
+ AuthorizationSet* output_params, std::string* output);
keymaster_error_t AbortOperation();
@@ -217,7 +224,6 @@
keymaster_error_t UpgradeKey(const AuthorizationSet& upgrade_params);
keymaster_error_t GetVersion(uint8_t* major, uint8_t* minor, uint8_t* subminor);
-
std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message);
std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message,
const AuthorizationSet& begin_params,
@@ -274,8 +280,8 @@
keymaster_block_mode_t block_mode, keymaster_padding_t padding,
const std::string& nonce);
- void CheckHmacTestVector(const std::string& key, const std::string& message, keymaster_digest_t digest,
- std::string expected_mac);
+ void CheckHmacTestVector(const std::string& key, const std::string& message,
+ keymaster_digest_t digest, std::string expected_mac);
void CheckAesOcbTestVector(const std::string& key, const std::string& nonce,
const std::string& associated_data, const std::string& message,
const std::string& expected_ciphertext);
diff --git a/asymmetric_key.cpp b/asymmetric_key.cpp
index 782e87b..35406e6 100644
--- a/asymmetric_key.cpp
+++ b/asymmetric_key.cpp
@@ -290,19 +290,10 @@
!X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
return TranslateLastOpenSslError();
- // TODO(swillden): Find useful values (if possible) for issuerName and subjectName.
- X509_NAME_Ptr issuerName(X509_NAME_new());
- if (!issuerName.get() ||
- !X509_NAME_add_entry_by_txt(issuerName.get(), "CN", MBSTRING_ASC,
- reinterpret_cast<const uint8_t*>("Android Keymaster"),
- -1 /* len */, -1 /* loc */, 0 /* set */) ||
- !X509_set_issuer_name(certificate.get(), issuerName.get() /* Don't release; copied */))
- return TranslateLastOpenSslError();
-
X509_NAME_Ptr subjectName(X509_NAME_new());
if (!subjectName.get() ||
!X509_NAME_add_entry_by_txt(subjectName.get(), "CN", MBSTRING_ASC,
- reinterpret_cast<const uint8_t*>("A Keymaster Key"),
+ reinterpret_cast<const uint8_t*>("Android Keystore Key"),
-1 /* len */, -1 /* loc */, 0 /* set */) ||
!X509_set_subject_name(certificate.get(), subjectName.get() /* Don't release; copied */))
return TranslateLastOpenSslError();
@@ -354,6 +345,15 @@
return TranslateLastOpenSslError();
}
+ // Set issuer to subject of batch certificate.
+ X509_NAME* issuerSubject = X509_get_subject_name(signing_cert.get());
+ if (!issuerSubject) {
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ if (!X509_set_issuer_name(certificate.get(), issuerSubject)) {
+ return TranslateLastOpenSslError();
+ }
+
UniquePtr<X509V3_CTX> x509v3_ctx(new X509V3_CTX);
*x509v3_ctx = {};
X509V3_set_ctx(x509v3_ctx.get(), signing_cert.get(), certificate.get(), nullptr /* req */,
diff --git a/attestation_record.cpp b/attestation_record.cpp
index 8417c55..0f7f05f 100644
--- a/attestation_record.cpp
+++ b/attestation_record.cpp
@@ -28,6 +28,9 @@
namespace keymaster {
+constexpr uint kCurrentKeymasterVersion = 3;
+constexpr uint kCurrentAttestationVersion = 2;
+
struct stack_st_ASN1_TYPE_Delete {
void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
};
@@ -79,6 +82,15 @@
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
+ ASN1_OCTET_STRING* attestation_application_id;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -110,6 +122,24 @@
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.masked_tag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.masked_tag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.masked_tag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.masked_tag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -136,6 +166,17 @@
} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
+static const keymaster_tag_t kDeviceAttestationTags[] = {
+ KM_TAG_ATTESTATION_ID_BRAND,
+ KM_TAG_ATTESTATION_ID_DEVICE,
+ KM_TAG_ATTESTATION_ID_PRODUCT,
+ KM_TAG_ATTESTATION_ID_SERIAL,
+ KM_TAG_ATTESTATION_ID_IMEI,
+ KM_TAG_ATTESTATION_ID_MEID,
+ KM_TAG_ATTESTATION_ID_MANUFACTURER,
+ KM_TAG_ATTESTATION_ID_MODEL,
+};
+
struct KM_AUTH_LIST_Delete {
void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); }
};
@@ -306,6 +347,33 @@
case KM_TAG_APPLICATION_ID:
string_ptr = &record->application_id;
break;
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ string_ptr = &record->attestation_application_id;
+ break;
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ string_ptr = &record->attestation_id_brand;
+ break;
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ string_ptr = &record->attestation_id_device;
+ break;
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ string_ptr = &record->attestation_id_product;
+ break;
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ string_ptr = &record->attestation_id_serial;
+ break;
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ string_ptr = &record->attestation_id_imei;
+ break;
+ case KM_TAG_ATTESTATION_ID_MEID:
+ string_ptr = &record->attestation_id_meid;
+ break;
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ string_ptr = &record->attestation_id_manufacturer;
+ break;
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ string_ptr = &record->attestation_id_model;
+ break;
}
keymaster_tag_type_t type = keymaster_tag_get_type(entry.tag);
@@ -407,8 +475,8 @@
// Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and
// tee_enforced.
keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- const AuthorizationSet& sw_enforced,
- const AuthorizationSet& tee_enforced,
+ AuthorizationSet sw_enforced,
+ AuthorizationSet tee_enforced,
const KeymasterContext& context,
UniquePtr<uint8_t[]>* asn1_key_desc,
size_t* asn1_key_desc_len) {
@@ -423,34 +491,14 @@
if (tee_enforced.empty()) {
// Software key.
keymaster_security_level = KM_SECURITY_LEVEL_SOFTWARE;
- keymaster_version = 2;
+ keymaster_version = kCurrentKeymasterVersion;
} else {
keymaster_security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
switch (context.GetSecurityLevel()) {
- case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT: {
- // We're running in a TEE, so the key is KM2.
- keymaster_version = 2;
-
- // Root of trust is only available in TEE
- KM_AUTH_LIST* tee_record = key_desc->tee_enforced;
- tee_record->root_of_trust = KM_ROOT_OF_TRUST_new();
- keymaster_blob_t verified_boot_key;
- keymaster_verified_boot_t verified_boot_state;
- bool device_locked;
- keymaster_error_t error = context.GetVerifiedBootParams(
- &verified_boot_key, &verified_boot_state, &device_locked);
- if (error != KM_ERROR_OK)
- return error;
- if (verified_boot_key.data_length &&
- !ASN1_OCTET_STRING_set(tee_record->root_of_trust->verified_boot_key,
- verified_boot_key.data, verified_boot_key.data_length))
- return TranslateLastOpenSslError();
- tee_record->root_of_trust->device_locked = (int*)device_locked;
- if (!ASN1_ENUMERATED_set(tee_record->root_of_trust->verified_boot_state,
- verified_boot_state))
- return TranslateLastOpenSslError();
+ case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
+ keymaster_version = kCurrentKeymasterVersion;
break;
- }
+
case KM_SECURITY_LEVEL_SOFTWARE:
// We're running in software, wrapping some KM hardware. Is it KM0 or KM1? KM1 keys
// have the purpose in the tee_enforced list. It's possible that a key could be created
@@ -465,7 +513,7 @@
return KM_ERROR_UNKNOWN_ERROR;
}
- if (!ASN1_INTEGER_set(key_desc->attestation_version, 1) ||
+ if (!ASN1_INTEGER_set(key_desc->attestation_version, kCurrentAttestationVersion) ||
!ASN1_ENUMERATED_set(key_desc->attestation_security_level, context.GetSecurityLevel()) ||
!ASN1_INTEGER_set(key_desc->keymaster_version, keymaster_version) ||
!ASN1_ENUMERATED_set(key_desc->keymaster_security_level, keymaster_security_level))
@@ -478,7 +526,26 @@
attestation_challenge.data_length))
return TranslateLastOpenSslError();
- keymaster_error_t error = build_auth_list(sw_enforced, key_desc->software_enforced);
+ keymaster_blob_t attestation_app_id;
+ if (!attestation_params.GetTagValue(TAG_ATTESTATION_APPLICATION_ID, &attestation_app_id))
+ return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, attestation_app_id);
+
+ keymaster_error_t error = context.VerifyAndCopyDeviceIds(attestation_params,
+ keymaster_security_level == KM_SECURITY_LEVEL_SOFTWARE ? &sw_enforced : &tee_enforced);
+ if (error == KM_ERROR_UNIMPLEMENTED) {
+ // The KeymasterContext implementation does not support device ID attestation. Bail out if
+ // device ID attestation is being attempted.
+ for (const auto& tag : kDeviceAttestationTags) {
+ if (attestation_params.find(tag) != -1) {
+ return KM_ERROR_CANNOT_ATTEST_IDS;
+ }
+ }
+ } else if (error != KM_ERROR_OK) {
+ return error;
+ }
+
+ error = build_auth_list(sw_enforced, key_desc->software_enforced);
if (error != KM_ERROR_OK)
return error;
@@ -663,6 +730,55 @@
!auth_list->push_back(TAG_OS_PATCHLEVEL, ASN1_INTEGER_get(record->os_patchlevel)))
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ // Brand name
+ if (record->attestation_id_brand &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_BRAND, record->attestation_id_brand->data,
+ record->attestation_id_brand->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // Device name
+ if (record->attestation_id_device &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_DEVICE, record->attestation_id_device->data,
+ record->attestation_id_device->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // Product name
+ if (record->attestation_id_product &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_PRODUCT, record->attestation_id_product->data,
+ record->attestation_id_product->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // Serial number
+ if (record->attestation_id_serial &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_SERIAL, record->attestation_id_serial->data,
+ record->attestation_id_serial->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // IMEI
+ if (record->attestation_id_imei &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_IMEI, record->attestation_id_imei->data,
+ record->attestation_id_imei->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // MEID
+ if (record->attestation_id_meid &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_MEID, record->attestation_id_meid->data,
+ record->attestation_id_meid->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // Manufacturer name
+ if (record->attestation_id_manufacturer &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_MANUFACTURER,
+ record->attestation_id_manufacturer->data,
+ record->attestation_id_manufacturer->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ // Model name
+ if (record->attestation_id_model &&
+ !auth_list->push_back(TAG_ATTESTATION_ID_MODEL, record->attestation_id_model->data,
+ record->attestation_id_model->length))
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
return KM_ERROR_OK;
}
@@ -704,4 +820,4 @@
return extract_auth_list(record->tee_enforced, tee_enforced);
}
-} // namepace keymaster
+} // namespace keymaster
diff --git a/attestation_record.h b/attestation_record.h
index 64acabc..116f82b 100644
--- a/attestation_record.h
+++ b/attestation_record.h
@@ -42,8 +42,8 @@
static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params,
- const AuthorizationSet& software_enforced,
- const AuthorizationSet& tee_enforced,
+ AuthorizationSet software_enforced,
+ AuthorizationSet tee_enforced,
const KeymasterContext& context,
UniquePtr<uint8_t[]>* asn1_key_desc,
size_t* asn1_key_desc_len);
@@ -57,6 +57,6 @@
AuthorizationSet* software_enforced,
AuthorizationSet* tee_enforced,
keymaster_blob_t* unique_id);
-}
+} // namespace keymaster
#endif // SYSTEM_KEYMASTER_ATTESTATION_RECORD_H_
diff --git a/attestation_record_test.cpp b/attestation_record_test.cpp
index 1cf8630..e7c1906 100644
--- a/attestation_record_test.cpp
+++ b/attestation_record_test.cpp
@@ -133,6 +133,9 @@
&keymaster_security_level, &attestation_challenge,
&parsed_sw_set, &parsed_hw_set, &unique_id));
+ delete[] attestation_challenge.data;
+ delete[] unique_id.data;
+
hw_set.Sort();
sw_set.Sort();
parsed_hw_set.Sort();
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 4cf070c..3f02109 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -65,7 +65,7 @@
if (is_valid() != OK)
return false;
- if (count >= elems_capacity_) {
+ if (count > elems_capacity_) {
keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
if (new_elems == NULL) {
set_invalid(ALLOCATION_FAILURE);
diff --git a/ec_key_factory.cpp b/ec_key_factory.cpp
index 36ec433..3f7b3d2 100644
--- a/ec_key_factory.cpp
+++ b/ec_key_factory.cpp
@@ -170,16 +170,29 @@
return error;
*key_size_bits = extracted_key_size_bits;
- if (!updated_description->GetTagValue(TAG_KEY_SIZE, key_size_bits))
+ if (!updated_description->GetTagValue(TAG_KEY_SIZE, key_size_bits)) {
updated_description->push_back(TAG_KEY_SIZE, extracted_key_size_bits);
- if (*key_size_bits != extracted_key_size_bits)
+ } else if (*key_size_bits != extracted_key_size_bits) {
return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ }
+
+ keymaster_ec_curve_t curve_from_size;
+ error = EcKeySizeToCurve(*key_size_bits, &curve_from_size);
+ if (error != KM_ERROR_OK)
+ return error;
+ keymaster_ec_curve_t curve;
+ if (!updated_description->GetTagValue(TAG_EC_CURVE, &curve)) {
+ updated_description->push_back(TAG_EC_CURVE, curve_from_size);
+ } else if (curve_from_size != curve) {
+ return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ }
keymaster_algorithm_t algorithm = KM_ALGORITHM_EC;
- if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm))
+ if (!updated_description->GetTagValue(TAG_ALGORITHM, &algorithm)) {
updated_description->push_back(TAG_ALGORITHM, KM_ALGORITHM_EC);
- if (algorithm != KM_ALGORITHM_EC)
+ } else if (algorithm != KM_ALGORITHM_EC) {
return KM_ERROR_IMPORT_PARAMETER_MISMATCH;
+ }
return KM_ERROR_OK;
}
diff --git a/ec_keymaster1_key.cpp b/ec_keymaster1_key.cpp
index 5cc2539..4386250 100644
--- a/ec_keymaster1_key.cpp
+++ b/ec_keymaster1_key.cpp
@@ -67,6 +67,15 @@
AuthorizationSet* sw_enforced) const {
AuthorizationSet key_params_copy;
UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
+
+ keymaster_ec_curve_t ec_curve;
+ uint32_t key_size;
+ keymaster_error_t error = GetCurveAndSize(key_description, &ec_curve, &key_size);
+ if (error != KM_ERROR_OK) {
+ return error;
+ } else if (!key_description.Contains(TAG_KEY_SIZE, key_size)) {
+ key_params_copy.push_back(TAG_KEY_SIZE, key_size);
+ }
return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
}
diff --git a/hmac_key.h b/hmac_key.h
index c05e6a3..61d86e0 100644
--- a/hmac_key.h
+++ b/hmac_key.h
@@ -22,6 +22,8 @@
namespace keymaster {
const size_t kMinHmacLengthBits = 64;
+const size_t kMinHmacKeyLengthBits = 64;
+const size_t kMaxHmacKeyLengthBits = 2048; // Some RFC test cases require >1024-bit keys
class HmacKeyFactory : public SymmetricKeyFactory {
public:
@@ -38,7 +40,7 @@
private:
bool key_size_supported(size_t key_size_bits) const override {
return key_size_bits > 0 && key_size_bits % 8 == 00 &&
- key_size_bits <= 2048 /* Some RFC test cases require >1024-bit keys */;
+ key_size_bits >= kMinHmacKeyLengthBits && key_size_bits <= kMaxHmacKeyLengthBits;
}
keymaster_error_t validate_algorithm_specific_new_key_params(
const AuthorizationSet& key_description) const override;
diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h
index a1cbf51..699f731 100644
--- a/include/keymaster/android_keymaster_utils.h
+++ b/include/keymaster/android_keymaster_utils.h
@@ -175,10 +175,15 @@
T* begin_;
T* end_;
};
+
template <typename T> ArrayWrapper<T> array_range(T* begin, size_t length) {
return ArrayWrapper<T>(begin, length);
}
+template <typename T, size_t n> ArrayWrapper<T> array_range(T (&a)[n]) {
+ return ArrayWrapper<T>(a, n);
+}
+
/**
* Convert any unsigned integer from network to host order. We implement this here rather than
* using the functions from arpa/inet.h because the TEE doesn't have inet.h. This isn't the most
diff --git a/include/keymaster/keymaster_configuration.h b/include/keymaster/keymaster_configuration.h
index 97b7fa5..69738fd 100644
--- a/include/keymaster/keymaster_configuration.h
+++ b/include/keymaster/keymaster_configuration.h
@@ -40,12 +40,24 @@
uint32_t GetOsVersion(const char* version_string);
/**
+ * Retrieves and parses OS version information from build properties. Returns 0 if the string
+ * doesn't contain a numeric version number.
+ */
+uint32_t GetOsVersion();
+
+/**
* Parses OS patch level string, returning year and month in integer form. For example, "2016-03-25"
* will be returned as 201603. Returns 0 if the string doesn't contain a date in the form
* YYYY-MM-DD.
*/
uint32_t GetOsPatchlevel(const char* patchlevel_string);
+/**
+ * Retrieves and parses OS patch level from build properties. Returns 0 if the string doesn't
+ * contain a date in the form YYYY-MM-DD.
+ */
+uint32_t GetOsPatchlevel();
+
} // namespace keymaster
#endif // SYSTEM_KEYMASTER_KEYMASTER_CONFIGURATION_H_
diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h
index fab170e..cf18869 100644
--- a/include/keymaster/keymaster_context.h
+++ b/include/keymaster/keymaster_context.h
@@ -182,14 +182,17 @@
Buffer* unique_id) const = 0;
/**
- * Returns verified boot parameters for the Attestation Extension. For hardware-based
- * implementations, these will be the values reported by the bootloader. By default, verified
- * boot state is unknown, and KM_ERROR_UNIMPLEMENTED is returned.
+ * Verify that the device IDs provided in the attestation_params match the device's actual IDs
+ * and copy them to attestation. If *any* of the IDs do not match or verification is not
+ * possible, return KM_ERROR_CANNOT_ATTEST_IDS. If *all* IDs provided are successfully verified
+ * or no IDs were provided, return KM_ERROR_OK.
+ *
+ * If you do not support device ID attestation, ignore all arguments and return
+ * KM_ERROR_UNIMPLEMENTED.
*/
- virtual keymaster_error_t
- GetVerifiedBootParams(keymaster_blob_t* /* verified_boot_key */,
- keymaster_verified_boot_t* /* verified_boot_state */,
- bool* /* device_locked */) const {
+ virtual keymaster_error_t VerifyAndCopyDeviceIds(
+ const AuthorizationSet& /* attestation_params */,
+ AuthorizationSet* /* attestation */) const {
return KM_ERROR_UNIMPLEMENTED;
}
diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h
index 2c7ac03..ad072ec 100644
--- a/include/keymaster/keymaster_tags.h
+++ b/include/keymaster/keymaster_tags.h
@@ -165,7 +165,16 @@
DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_CHALLENGE);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_RESET_SINCE_ID_ROTATION);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
+DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
// DECLARE_KEYMASTER_ENUM_TAG is used to declare TypedEnumTag instances for each enum keymaster tag.
#define DECLARE_KEYMASTER_ENUM_TAG(type, name, enumtype) \
diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h
index a20454d..6663ac4 100644
--- a/include/keymaster/soft_keymaster_device.h
+++ b/include/keymaster/soft_keymaster_device.h
@@ -49,7 +49,6 @@
public:
SoftKeymasterDevice();
- // Public only for testing.
explicit SoftKeymasterDevice(SoftKeymasterContext* context);
/**
@@ -81,6 +80,8 @@
bool configured() const { return configured_; }
+ bool supports_all_digests() { return supports_all_digests_; }
+
typedef std::pair<keymaster_algorithm_t, keymaster_purpose_t> AlgPurposePair;
typedef std::map<AlgPurposePair, std::vector<keymaster_digest_t>> DigestMap;
@@ -105,7 +106,7 @@
* keymaster_device.
*/
- // Keymaster1 methods
+ // Keymaster1 methods -- needed for testing.
static keymaster_error_t get_supported_algorithms(const keymaster1_device_t* dev,
keymaster_algorithm_t** algorithms,
size_t* algorithms_length);
@@ -247,6 +248,7 @@
std::string module_name_;
hw_module_t updated_module_;
bool configured_;
+ bool supports_all_digests_;
};
} // namespace keymaster
diff --git a/keymaster1_engine.cpp b/keymaster1_engine.cpp
index 8e11e91..2051363 100644
--- a/keymaster1_engine.cpp
+++ b/keymaster1_engine.cpp
@@ -153,10 +153,8 @@
// Copy public key into new RSA key
unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
GetKeymaster1PublicKey(key_data->key_material, key_data->begin_params, error));
- if (!pkey) {
- *error = TranslateLastOpenSslError();
+ if (*error != KM_ERROR_OK)
return nullptr;
- }
unique_ptr<RSA, RSA_Delete> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
if (!public_rsa) {
@@ -195,10 +193,8 @@
// Copy public key into new EC key
unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
GetKeymaster1PublicKey(blob, additional_params, error));
- if (!pkey) {
- *error = TranslateLastOpenSslError();
+ if (*error != KM_ERROR_OK)
return nullptr;
- }
unique_ptr<EC_KEY, EC_KEY_Delete> public_ec_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
if (!public_ec_key) {
@@ -380,7 +376,11 @@
unique_ptr<uint8_t, Malloc_Delete> pub_key(const_cast<uint8_t*>(export_data.data));
const uint8_t* p = export_data.data;
- return d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
+ auto result = d2i_PUBKEY(nullptr /* allocate new struct */, &p, export_data.data_length);
+ if (!result) {
+ *error = TranslateLastOpenSslError();
+ }
+ return result;
}
RSA_METHOD Keymaster1Engine::BuildRsaMethod() {
diff --git a/keymaster_configuration.cpp b/keymaster_configuration.cpp
index 428197c..ac6d3c1 100644
--- a/keymaster_configuration.cpp
+++ b/keymaster_configuration.cpp
@@ -70,15 +70,7 @@
}
keymaster_error_t ConfigureDevice(keymaster2_device_t* dev) {
- char version_str[PROPERTY_VALUE_MAX];
- property_get(kPlatformVersionProp, version_str, "" /* default */);
- uint32_t version = GetOsVersion(version_str);
-
- char patchlevel_str[PROPERTY_VALUE_MAX];
- property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */);
- uint32_t patchlevel = GetOsPatchlevel(patchlevel_str);
-
- return ConfigureDevice(dev, version, patchlevel);
+ return ConfigureDevice(dev, GetOsVersion(), GetOsPatchlevel());
}
uint32_t GetOsVersion(const char* version_str) {
@@ -89,7 +81,10 @@
}
regmatch_t matches[kPlatformVersionMatchCount];
- if (regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */)) {
+ int not_match =
+ regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
ALOGI("Platform version string does not match expected format. Using version 0.");
return 0;
}
@@ -101,6 +96,12 @@
return (major * 100 + minor) * 100 + subminor;
}
+uint32_t GetOsVersion() {
+ char version_str[PROPERTY_VALUE_MAX];
+ property_get(kPlatformVersionProp, version_str, "" /* default */);
+ return GetOsVersion(version_str);
+}
+
uint32_t GetOsPatchlevel(const char* patchlevel_str) {
regex_t regex;
if (regcomp(®ex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
@@ -109,7 +110,10 @@
}
regmatch_t matches[kPlatformPatchlevelMatchCount];
- if (regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */)) {
+ int not_match =
+ regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
ALOGI("Platform patchlevel string does not match expected format. Using patchlevel 0");
return 0;
}
@@ -124,4 +128,10 @@
return year * 100 + month;
}
+uint32_t GetOsPatchlevel() {
+ char patchlevel_str[PROPERTY_VALUE_MAX];
+ property_get(kPlatformPatchlevelProp, patchlevel_str, "" /* default */);
+ return GetOsPatchlevel(patchlevel_str);
+}
+
} // namespace keymaster
diff --git a/keymaster_enforcement.cpp b/keymaster_enforcement.cpp
index 3f2e4f4..e49ab46 100644
--- a/keymaster_enforcement.cpp
+++ b/keymaster_enforcement.cpp
@@ -286,6 +286,15 @@
case KM_TAG_ROOT_OF_TRUST:
case KM_TAG_APPLICATION_DATA:
case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ case KM_TAG_ATTESTATION_ID_MEID:
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ case KM_TAG_ATTESTATION_ID_MODEL:
return KM_ERROR_INVALID_KEY_BLOB;
/* Tags used for cryptographic parameters in keygen. Nothing to enforce. */
diff --git a/keymaster_tags.cpp b/keymaster_tags.cpp
index 238bc33..2375389 100644
--- a/keymaster_tags.cpp
+++ b/keymaster_tags.cpp
@@ -111,6 +111,24 @@
return "KM_TAG_ALLOW_WHILE_ON_BODY";
case KM_TAG_ATTESTATION_CHALLENGE:
return "KM_TAG_ATTESTATION_CHALLENGE";
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ return "KM_TAG_ATTESTATION_APPLICATION_ID";
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ return "KM_TAG_ATTESTATION_ID_BRAND";
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ return "KM_TAG_ATTESTATION_ID_DEVICE";
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ return "KM_TAG_ATTESTATION_ID_PRODUCT";
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ return "KM_TAG_ATTESTATION_ID_SERIAL";
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ return "KM_TAG_ATTESTATION_ID_IMEI";
+ case KM_TAG_ATTESTATION_ID_MEID:
+ return "KM_TAG_ATTESTATION_ID_MEID";
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ return "KM_TAG_ATTESTATION_ID_MANUFACTURER";
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ return "KM_TAG_ATTESTATION_ID_MODEL";
}
return "<Unknown>";
}
@@ -151,6 +169,15 @@
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
DEFINE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
+DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
// DEFINE_KEYMASTER_ENUM_TAG is used to create TypedEnumTag instances for each enum keymaster tag.
diff --git a/rsa_key_factory.cpp b/rsa_key_factory.cpp
index e6c3f8c..4cae693 100644
--- a/rsa_key_factory.cpp
+++ b/rsa_key_factory.cpp
@@ -27,7 +27,9 @@
namespace keymaster {
-const int kMaximumRsaKeySize = 16 * 1024; // 16kbits should be enough for anyone.
+const int kMaximumRsaKeySize = 4096; // OpenSSL fails above 4096.
+const int kMinimumRsaKeySize = 16; // OpenSSL goes into an infinite loop if key size < 10
+const int kMinimumRsaExponent = 3;
static RsaSigningOperationFactory sign_factory;
static RsaVerificationOperationFactory verify_factory;
@@ -60,7 +62,11 @@
uint64_t public_exponent;
if (!authorizations.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent)) {
- LOG_E("%s", "No public exponent specified for RSA key generation");
+ LOG_E("No public exponent specified for RSA key generation", 0);
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+ if (public_exponent < kMinimumRsaExponent || public_exponent % 2 != 1) {
+ LOG_E("Invalid public exponent specified for RSA key generation", 0);
return KM_ERROR_INVALID_ARGUMENT;
}
@@ -69,7 +75,7 @@
LOG_E("No key size specified for RSA key generation", 0);
return KM_ERROR_UNSUPPORTED_KEY_SIZE;
}
- if (key_size % 8 != 0 || key_size > kMaximumRsaKeySize) {
+ if (key_size % 8 != 0 || key_size > kMaximumRsaKeySize || key_size < kMinimumRsaKeySize) {
LOG_E("Invalid key size of %u bits specified for RSA key generation", key_size);
return KM_ERROR_UNSUPPORTED_KEY_SIZE;
}
diff --git a/soft_keymaster_context.cpp b/soft_keymaster_context.cpp
index 5766117..c30dffb 100644
--- a/soft_keymaster_context.cpp
+++ b/soft_keymaster_context.cpp
@@ -17,6 +17,7 @@
#include <keymaster/soft_keymaster_context.h>
#include <memory>
+
#include <time.h>
#include <openssl/aes.h>
@@ -340,11 +341,8 @@
rsa_factory_.reset(new RsaKeymaster1KeyFactory(this, km1_engine_.get()));
ec_factory_.reset(new EcdsaKeymaster1KeyFactory(this, km1_engine_.get()));
- // All AES and HMAC operations should be passed directly to the keymaster1 device. Explicitly
- // do not handle them, to provoke errors in case the higher layers fail to send them to the
- // device.
- aes_factory_.reset(nullptr);
- hmac_factory_.reset(nullptr);
+ // Use default HMAC and AES key factories. Higher layers will pass HMAC/AES keys/ops that are
+ // supported by the hardware to it and other ones to the software-only factory.
return KM_ERROR_OK;
}
@@ -684,19 +682,23 @@
else if (km0_engine_)
return ParseKeymaster0HwBlob(blob, key_material, hw_enforced, sw_enforced);
- LOG_E("Failed to parse key; not a valid software blob, no hardware module configured", 0);
return KM_ERROR_INVALID_KEY_BLOB;
}
keymaster_error_t SoftKeymasterContext::DeleteKey(const KeymasterKeyBlob& blob) const {
if (km1_engine_) {
- keymaster_error_t error = km1_engine_->DeleteKey(blob);
- if (error == KM_ERROR_INVALID_KEY_BLOB) {
- // Note that we succeed on invalid blob, because it probably just indicates that the
- // blob is a software blob, not a hardware blob.
- error = KM_ERROR_OK;
+ // HACK. Due to a bug with Qualcomm's Keymaster implementation, which causes the device to
+ // reboot if we pass it a key blob it doesn't understand, we need to check for software
+ // keys. If it looks like a software key there's nothing to do so we just return.
+ KeymasterKeyBlob key_material;
+ AuthorizationSet hw_enforced, sw_enforced;
+ keymaster_error_t error = DeserializeIntegrityAssuredBlob_NoHmacCheck(
+ blob, &key_material, &hw_enforced, &sw_enforced);
+ if (error == KM_ERROR_OK) {
+ return KM_ERROR_OK;
}
- return error;
+
+ return km1_engine_->DeleteKey(blob);
}
if (km0_engine_) {
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index 35523f7..f0d87ca 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -24,6 +24,7 @@
#include <time.h>
#include <algorithm>
+#include <vector>
#include <type_traits>
@@ -35,6 +36,7 @@
#include <keymaster/android_keymaster.h>
#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>
#include <keymaster/soft_keymaster_context.h>
#include <keymaster/soft_keymaster_logger.h>
@@ -80,9 +82,32 @@
return std::vector<T>(array, array + len);
}
+// This helper class implements just enough of the C++ standard collection interface to be able to
+// accept push_back calls, and it does nothing but count them. It's useful when you want to count
+// insertions but not actually store anything. It's used in digest_set_is_full below to count the
+// size of a set intersection.
+struct PushbackCounter {
+ struct value_type {
+ template <typename T> value_type(const T&) {}
+ };
+ void push_back(const value_type&) { ++count; }
+ size_t count = 0;
+};
+
+static std::vector<keymaster_digest_t> full_digest_list = {
+ KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224,
+ KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
+
+template <typename Iter> static bool digest_set_is_full(Iter begin, Iter end) {
+ PushbackCounter counter;
+ std::set_intersection(begin, end, full_digest_list.begin(), full_digest_list.end(),
+ std::back_inserter(counter));
+ return counter.count == full_digest_list.size();
+}
+
static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
keymaster_purpose_t purpose,
- SoftKeymasterDevice::DigestMap* map) {
+ SoftKeymasterDevice::DigestMap* map, bool* supports_all) {
auto key = std::make_pair(algorithm, purpose);
keymaster_digest_t* digests;
@@ -95,30 +120,39 @@
}
std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);
- (*map)[key] = make_vector(digests, digests_length);
- return KM_ERROR_OK;
+ auto digest_vec = make_vector(digests, digests_length);
+ *supports_all = digest_set_is_full(digest_vec.begin(), digest_vec.end());
+ (*map)[key] = std::move(digest_vec);
+ return error;
}
-static keymaster_error_t map_digests(keymaster1_device_t* dev,
- SoftKeymasterDevice::DigestMap* map) {
+static keymaster_error_t map_digests(keymaster1_device_t* dev, SoftKeymasterDevice::DigestMap* map,
+ bool* supports_all) {
map->clear();
+ *supports_all = true;
- keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC};
+ keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_HMAC};
keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
for (auto algorithm : sig_algorithms)
for (auto purpose : sig_purposes) {
- keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+ bool alg_purpose_supports_all;
+ keymaster_error_t error =
+ add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
if (error != KM_ERROR_OK)
return error;
+ *supports_all &= alg_purpose_supports_all;
}
keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
for (auto algorithm : crypt_algorithms)
for (auto purpose : crypt_purposes) {
- keymaster_error_t error = add_digests(dev, algorithm, purpose, map);
+ bool alg_purpose_supports_all;
+ keymaster_error_t error =
+ add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
if (error != KM_ERROR_OK)
return error;
+ *supports_all &= alg_purpose_supports_all;
}
return KM_ERROR_OK;
@@ -152,6 +186,7 @@
if (!context_)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ supports_all_digests_ = false;
keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device);
if (error != KM_ERROR_OK)
return error;
@@ -180,7 +215,8 @@
if (!context_)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
- keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_);
+ keymaster_error_t error =
+ map_digests(keymaster1_device, &km1_device_digests_, &supports_all_digests_);
if (error != KM_ERROR_OK)
return error;
@@ -337,44 +373,17 @@
return reinterpret_cast<SoftKeymasterDevice*>(dev->context);
}
-bool FindAlgorithm(const keymaster_key_param_set_t& params, keymaster_algorithm_t* algorithm) {
+template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum>
+bool FindTagValue(const keymaster_key_param_set_t& params,
+ TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum* value) {
for (size_t i = 0; i < params.length; ++i)
- if (params.params[i].tag == KM_TAG_ALGORITHM) {
- *algorithm = static_cast<keymaster_algorithm_t>(params.params[i].enumerated);
+ if (params.params[i].tag == tag) {
+ *value = static_cast<KeymasterEnum>(params.params[i].enumerated);
return true;
}
return false;
}
-keymaster_error_t GetAlgorithm(const keymaster1_device_t* dev, const keymaster_key_blob_t& key,
- const AuthorizationSet& in_params,
- keymaster_algorithm_t* algorithm) {
- keymaster_blob_t client_id = {nullptr, 0};
- keymaster_blob_t app_data = {nullptr, 0};
- keymaster_blob_t* client_id_ptr = nullptr;
- keymaster_blob_t* app_data_ptr = nullptr;
- if (in_params.GetTagValue(TAG_APPLICATION_ID, &client_id))
- client_id_ptr = &client_id;
- if (in_params.GetTagValue(TAG_APPLICATION_DATA, &app_data))
- app_data_ptr = &app_data;
-
- keymaster_key_characteristics_t* characteristics;
- keymaster_error_t error =
- dev->get_key_characteristics(dev, &key, client_id_ptr, app_data_ptr, &characteristics);
- if (error != KM_ERROR_OK)
- return error;
- std::unique_ptr<keymaster_key_characteristics_t, Characteristics_Delete>
- characteristics_deleter(characteristics);
-
- if (FindAlgorithm(characteristics->hw_enforced, algorithm))
- return KM_ERROR_OK;
-
- if (FindAlgorithm(characteristics->sw_enforced, algorithm))
- return KM_ERROR_OK;
-
- return KM_ERROR_INVALID_KEY_BLOB;
-}
-
} // unnamed namespaced
/* static */
@@ -686,9 +695,9 @@
switch (algorithm) {
case KM_ALGORITHM_AES:
- case KM_ALGORITHM_HMAC:
- LOG_D("Not performing software digesting for algorithm %d", algorithm);
+ LOG_D("Not performing software digesting for AES keys", algorithm);
return false;
+ case KM_ALGORITHM_HMAC:
case KM_ALGORITHM_RSA:
case KM_ALGORITHM_EC:
break;
@@ -792,8 +801,28 @@
keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description)) {
+ keymaster_ec_curve_t curve;
+ if (request.key_description.Contains(TAG_ALGORITHM, KM_ALGORITHM_EC) &&
+ request.key_description.GetTagValue(TAG_EC_CURVE, &curve)) {
+ // Keymaster1 doesn't know about EC curves. We need to translate to key size.
+ uint32_t key_size_from_curve;
+ keymaster_error_t error = EcCurveToKeySize(curve, &key_size_from_curve);
+ if (error != KM_ERROR_OK) {
+ return error;
+ }
+
+ uint32_t key_size_from_desc;
+ if (request.key_description.GetTagValue(TAG_KEY_SIZE, &key_size_from_desc)) {
+ if (key_size_from_desc != key_size_from_curve) {
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+ } else {
+ request.key_description.push_back(TAG_KEY_SIZE, key_size_from_curve);
+ }
+ }
+
keymaster_key_characteristics_t* chars_ptr;
- keymaster_error_t error = km1_dev->generate_key(km1_dev, params, key_blob,
+ keymaster_error_t error = km1_dev->generate_key(km1_dev, &request.key_description, key_blob,
characteristics ? &chars_ptr : nullptr);
if (error != KM_ERROR_OK)
return error;
@@ -839,8 +868,13 @@
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev) {
- return km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data,
- characteristics);
+ keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id,
+ app_data, characteristics);
+ if (error != KM_ERROR_INVALID_KEY_BLOB) {
+ return error;
+ }
+ // If we got "invalid blob", continue to try with the software device. This might be a
+ // software key blob.
}
GetKeyCharacteristicsRequest request;
@@ -881,18 +915,6 @@
SoftKeymasterDevice* sk_dev = convert_device(dev);
- const keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_;
- if (km1_dev) {
- keymaster_key_characteristics_t* tmp_characteristics;
- keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id,
- app_data, &tmp_characteristics);
- if (error == KM_ERROR_OK) {
- *characteristics = *tmp_characteristics;
- free(tmp_characteristics);
- }
- return error;
- }
-
GetKeyCharacteristicsRequest request;
request.SetKeyMaterial(*key_blob);
AddClientAndAppData(client_id, app_data, &request);
@@ -1181,22 +1203,42 @@
const keymaster_key_param_set_t* in_params,
keymaster_key_param_set_t* out_params,
keymaster_operation_handle_t* operation_handle) {
- if (!key || !key->key_material)
+ if (!dev || !key || !key->key_material)
return KM_ERROR_UNEXPECTED_NULL_POINTER;
if (!operation_handle)
return KM_ERROR_OUTPUT_PARAMETER_NULL;
- const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ SoftKeymasterDevice* skdev = convert_device(dev);
+ const keymaster1_device_t* km1_dev = skdev->wrapped_km1_device_;
+
if (km1_dev) {
AuthorizationSet in_params_set(*in_params);
- keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
- keymaster_error_t error = GetAlgorithm(km1_dev, *key, in_params_set, &algorithm);
- if (error != KM_ERROR_OK)
- return error;
+ KeymasterKeyBlob key_material;
+ AuthorizationSet hw_enforced;
+ AuthorizationSet sw_enforced;
+ skdev->context_->ParseKeyBlob(KeymasterKeyBlob(*key), in_params_set, &key_material,
+ &hw_enforced, &sw_enforced);
- if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
+ keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+ if (!hw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm) &&
+ !sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+
+ if (algorithm == KM_ALGORITHM_HMAC) {
+ // Because HMAC keys can have only one digest, in_params_set doesn't contain it. We
+ // need to get the digest from the key and add it to in_params_set.
+ keymaster_digest_t digest;
+ if (!hw_enforced.GetTagValue(TAG_DIGEST, &digest) &&
+ !sw_enforced.GetTagValue(TAG_DIGEST, &digest)) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+ in_params_set.push_back(TAG_DIGEST, digest);
+ }
+
+ if (!skdev->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) {
LOG_D("Operation supported by %s, passing through to keymaster1 module",
km1_dev->common.module->name);
return km1_dev->begin(km1_dev, purpose, key, in_params, out_params, operation_handle);
@@ -1215,7 +1257,7 @@
request.additional_params.Reinitialize(*in_params);
BeginOperationResponse response;
- convert_device(dev)->impl_->BeginOperation(request, &response);
+ skdev->impl_->BeginOperation(request, &response);
if (response.error != KM_ERROR_OK)
return response.error;
@@ -1336,6 +1378,9 @@
const keymaster_blob_t* signature,
keymaster_key_param_set_t* out_params,
keymaster_blob_t* output) {
+ if (!dev)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
// This operation is being handled by km1_dev (or doesn't exist). Pass it through to
@@ -1385,6 +1430,10 @@
return KM_ERROR_OK;
}
+struct KeyParamSetContents_Delete {
+ void operator()(keymaster_key_param_set_t* p) { keymaster_free_param_set(p); }
+};
+
/* static */
keymaster_error_t SoftKeymasterDevice::finish(const keymaster2_device_t* dev,
keymaster_operation_handle_t operation_handle,
@@ -1399,11 +1448,144 @@
if (!convert_device(dev)->configured())
return KM_ERROR_KEYMASTER_NOT_CONFIGURED;
- if (input && input->data)
- return KM_ERROR_UNIMPLEMENTED; // TODO(swillden): Implement this
+ if (out_params)
+ *out_params = {};
- SoftKeymasterDevice* sk_dev = convert_device(dev);
- return finish(&sk_dev->km1_device_, operation_handle, params, signature, out_params, output);
+ if (output)
+ *output = {};
+
+ const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_;
+ if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) {
+ // This operation is being handled by km1_dev (or doesn't exist). Pass it through to
+ // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to
+ // km1_dev after doing necessary digesting.
+
+ std::vector<uint8_t> accumulated_output;
+ AuthorizationSet accumulated_out_params;
+ AuthorizationSet mutable_params(*params);
+ if (input && input->data && input->data_length) {
+ // Keymaster1 doesn't support input to finish(). Call update() to process input.
+
+ accumulated_output.reserve(input->data_length); // Guess at output size
+ keymaster_blob_t mutable_input = *input;
+
+ while (mutable_input.data_length > 0) {
+ keymaster_key_param_set_t update_out_params = {};
+ keymaster_blob_t update_output = {};
+ size_t input_consumed = 0;
+ keymaster_error_t error =
+ km1_dev->update(km1_dev, operation_handle, &mutable_params, &mutable_input,
+ &input_consumed, &update_out_params, &update_output);
+ if (error != KM_ERROR_OK) {
+ return error;
+ }
+
+ accumulated_output.reserve(accumulated_output.size() + update_output.data_length);
+ std::copy(update_output.data, update_output.data + update_output.data_length,
+ std::back_inserter(accumulated_output));
+ free(const_cast<uint8_t*>(update_output.data));
+
+ accumulated_out_params.push_back(update_out_params);
+ keymaster_free_param_set(&update_out_params);
+
+ mutable_input.data += input_consumed;
+ mutable_input.data_length -= input_consumed;
+
+ // AAD should only be sent once, so remove it if present.
+ int aad_pos = mutable_params.find(TAG_ASSOCIATED_DATA);
+ if (aad_pos != -1) {
+ mutable_params.erase(aad_pos);
+ }
+
+ if (input_consumed == 0) {
+ // Apparently we need more input than we have to complete an operation.
+ km1_dev->abort(km1_dev, operation_handle);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+ }
+ }
+
+ keymaster_key_param_set_t finish_out_params = {};
+ keymaster_blob_t finish_output = {};
+ keymaster_error_t error = km1_dev->finish(km1_dev, operation_handle, &mutable_params,
+ signature, &finish_out_params, &finish_output);
+ if (error != KM_ERROR_OK) {
+ return error;
+ }
+
+ if (!accumulated_out_params.empty()) {
+ accumulated_out_params.push_back(finish_out_params);
+ keymaster_free_param_set(&finish_out_params);
+ accumulated_out_params.Deduplicate();
+ accumulated_out_params.CopyToParamSet(&finish_out_params);
+ }
+ std::unique_ptr<keymaster_key_param_set_t, KeyParamSetContents_Delete>
+ finish_out_params_deleter(&finish_out_params);
+
+ if (!accumulated_output.empty()) {
+ size_t finish_out_length = accumulated_output.size() + finish_output.data_length;
+ uint8_t* finish_out_buf = reinterpret_cast<uint8_t*>(malloc(finish_out_length));
+
+ std::copy(accumulated_output.begin(), accumulated_output.end(), finish_out_buf);
+ std::copy(finish_output.data, finish_output.data + finish_output.data_length,
+ finish_out_buf + accumulated_output.size());
+
+ free(const_cast<uint8_t*>(finish_output.data));
+ finish_output.data_length = finish_out_length;
+ finish_output.data = finish_out_buf;
+ }
+ std::unique_ptr<uint8_t, Malloc_Delete> finish_output_deleter(
+ const_cast<uint8_t*>(finish_output.data));
+
+ if ((!out_params && finish_out_params.length) || (!output && finish_output.data_length)) {
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+
+ if (out_params) {
+ *out_params = finish_out_params;
+ }
+
+ if (output) {
+ *output = finish_output;
+ }
+
+ finish_out_params_deleter.release();
+ finish_output_deleter.release();
+
+ return KM_ERROR_OK;
+ }
+
+ FinishOperationRequest request;
+ request.op_handle = operation_handle;
+ if (signature && signature->data_length > 0)
+ request.signature.Reinitialize(signature->data, signature->data_length);
+ if (input && input->data_length > 0)
+ request.input.Reinitialize(input->data, input->data_length);
+ request.additional_params.Reinitialize(*params);
+
+ FinishOperationResponse response;
+ convert_device(dev)->impl_->FinishOperation(request, &response);
+ if (response.error != KM_ERROR_OK)
+ return response.error;
+
+ if (response.output_params.size() > 0) {
+ if (out_params)
+ response.output_params.CopyToParamSet(out_params);
+ else
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+ if (output) {
+ output->data_length = response.output.available_read();
+ uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(output->data_length));
+ if (!tmp)
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ memcpy(tmp, response.output.peek_read(), output->data_length);
+ output->data = tmp;
+ } else if (response.output.available_read() > 0) {
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+
+ return KM_ERROR_OK;
}
/* static */