diff options
author | Rajesh Nyamagoud <nyamagoud@google.com> | 2023-10-04 18:36:55 +0000 |
---|---|---|
committer | Rajesh Nyamagoud <nyamagoud@google.com> | 2023-10-06 23:15:21 +0000 |
commit | 19fe29adb35c301d7bcbb6964a70b3e5f926c1b2 (patch) | |
tree | a1d3b968cc21e938e39295589f435f17a4fe06a2 /keystore2/test_utils | |
parent | 1a7cd1d195a635b96c83e78114837d81ce923512 (diff) | |
download | security-19fe29adb35c301d7bcbb6964a70b3e5f926c1b2.tar.gz |
Removed dependency on `libkeymint_vts_test_utils`.
Test: mmm system/security/keystore2/test_utils/; mmm system/security/keystore2/tests;
atest keystore2_client_tests; atest keystore2_test_utils_test; atest keystore2_test; atest keystore2_legacy_blobs_test;
Bug: 194359114
Change-Id: I2e17697c8ea54b1c38e128b32b4d30f1214c51fc
Diffstat (limited to 'keystore2/test_utils')
-rw-r--r-- | keystore2/test_utils/Android.bp | 11 | ||||
-rw-r--r-- | keystore2/test_utils/ffi_test_utils.cpp | 240 | ||||
-rw-r--r-- | keystore2/test_utils/ffi_test_utils.rs | 6 |
3 files changed, 178 insertions, 79 deletions
diff --git a/keystore2/test_utils/Android.bp b/keystore2/test_utils/Android.bp index b2360dbd..9f3a4e90 100644 --- a/keystore2/test_utils/Android.bp +++ b/keystore2/test_utils/Android.bp @@ -43,11 +43,10 @@ rust_defaults { "libkeystore2_ffi_test_utils", ], shared_libs: [ + "libbase", "libcrypto", - "libkeymaster_messages", "libkeymaster_portable", "libkeymint_support", - "libkeymint_vts_test_utils", "libkeystore-engine", ], } @@ -73,8 +72,7 @@ cc_library_static { name: "libkeystore2_ffi_test_utils", srcs: ["ffi_test_utils.cpp"], defaults: [ - "keymint_vts_defaults", - "hidl_defaults", + "keymint_use_latest_hal_aidl_ndk_shared", ], generated_headers: [ "cxx-bridge-header", @@ -82,11 +80,12 @@ cc_library_static { ], generated_sources: ["libkeystore2_ffi_test_utils_bridge_code"], shared_libs: [ + "libbase", + "libcrypto", "libcppbor_external", - "libkeymaster_messages", "libkeymaster_portable", "libkeystore-engine", - "libkeymint_vts_test_utils", + "libkeymint_support", ], } diff --git a/keystore2/test_utils/ffi_test_utils.cpp b/keystore2/test_utils/ffi_test_utils.cpp index 7fbfb8b2..1853c079 100644 --- a/keystore2/test_utils/ffi_test_utils.cpp +++ b/keystore2/test_utils/ffi_test_utils.cpp @@ -1,26 +1,21 @@ #include "ffi_test_utils.hpp" #include <iostream> - -#include <android-base/logging.h> - -#include <KeyMintAidlTestBase.h> -#include <aidl/android/hardware/security/keymint/ErrorCode.h> -#include <keymaster/UniquePtr.h> - #include <vector> -#include <hardware/keymaster_defs.h> -#include <keymaster/android_keymaster_utils.h> -#include <keymaster/keymaster_tags.h> - +#include <android-base/logging.h> #include <keymaster/km_openssl/attestation_record.h> #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> +#include <keymint_support/attestation_record.h> +#include <openssl/mem.h> -#include <android-base/logging.h> - -using aidl::android::hardware::security::keymint::ErrorCode; +using keymaster::ASN1_OBJECT_Ptr; +using keymaster::EVP_PKEY_Ptr; +using keymaster::X509_Ptr; +using std::endl; +using std::string; +using std::vector; #define TAG_SEQUENCE 0x30 #define LENGTH_MASK 0x80 @@ -29,6 +24,8 @@ using aidl::android::hardware::security::keymint::ErrorCode; /* EVP_PKEY_from_keystore is from system/security/keystore-engine. */ extern "C" EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id); +typedef std::vector<uint8_t> certificate_t; + /** * ASN.1 structure for `KeyDescription` Schema. * See `IKeyMintDevice.aidl` for documentation of the `KeyDescription` schema. @@ -91,6 +88,94 @@ struct TEST_SECURE_KEY_WRAPPER_Delete { const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:"); +string bin2hex(const vector<uint8_t>& data) { + string retval; + char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + retval.reserve(data.size() * 2 + 1); + for (uint8_t byte : data) { + retval.push_back(nibble2hex[0x0F & (byte >> 4)]); + retval.push_back(nibble2hex[0x0F & byte]); + } + return retval; +} + +string x509NameToStr(X509_NAME* name) { + char* s = X509_NAME_oneline(name, nullptr, 0); + string retval(s); + OPENSSL_free(s); + return retval; +} + +X509_Ptr parseCertBlob(const vector<uint8_t>& blob) { + const uint8_t* p = blob.data(); + return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size())); +} + +// Extract attestation record from cert. Returned object is still part of cert; don't free it +// separately. +ASN1_OCTET_STRING* getAttestationRecord(X509* certificate) { + ASN1_OBJECT_Ptr oid(OBJ_txt2obj(aidl::android::hardware::security::keymint::kAttestionRecordOid, + 1 /* dotted string format */)); + if (!oid.get()) return nullptr; + + int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */); + if (location == -1) return nullptr; + + X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location); + if (!attest_rec_ext) return nullptr; + + ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext); + return attest_rec; +} + +bool ChainSignaturesAreValid(const vector<certificate_t>& chain, bool strict_issuer_check) { + std::stringstream cert_data; + + for (size_t i = 0; i < chain.size(); ++i) { + cert_data << bin2hex(chain[i]) << std::endl; + + X509_Ptr key_cert(parseCertBlob(chain[i])); + X509_Ptr signing_cert; + if (i < chain.size() - 1) { + signing_cert = parseCertBlob(chain[i + 1]); + } else { + signing_cert = parseCertBlob(chain[i]); + } + if (!key_cert.get() || !signing_cert.get()) { + LOG(ERROR) << cert_data.str(); + return false; + } + + EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get())); + if (!signing_pubkey.get()) { + LOG(ERROR) << cert_data.str(); + return false; + } + + if (!X509_verify(key_cert.get(), signing_pubkey.get())) { + LOG(ERROR) << "Verification of certificate " << i << " failed " + << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL) + << '\n' + << cert_data.str(); + return false; + } + + string cert_issuer = x509NameToStr(X509_get_issuer_name(key_cert.get())); + string signer_subj = x509NameToStr(X509_get_subject_name(signing_cert.get())); + if (cert_issuer != signer_subj && strict_issuer_check) { + LOG(ERROR) << "Cert " << i << " has wrong issuer.\n" + << " Signer subject is " << signer_subj << " Issuer subject is " + << cert_issuer << endl + << cert_data.str(); + } + } + + // Dump cert data. + LOG(ERROR) << cert_data.str(); + return true; +} + /* This function extracts a certificate from the certs_chain_buffer at the given * offset. Each DER encoded certificate starts with TAG_SEQUENCE followed by the * total length of the certificate. The length of the certificate is determined @@ -101,13 +186,12 @@ const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:"); * @data_size: Length of the DER encoded X.509 certificates buffer. * @index: DER encoded X.509 certificates buffer offset. * @cert: Encoded certificate to be extracted from buffer as outcome. - * @return: ErrorCode::OK on success, otherwise ErrorCode::UNKNOWN_ERROR. + * @return: true on success, otherwise false. */ -ErrorCode -extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buffer_size, int& index, - aidl::android::hardware::security::keymint::Certificate& cert) { +bool extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buffer_size, + int& index, certificate_t& cert) { if (index >= certs_chain_buffer_size) { - return ErrorCode::UNKNOWN_ERROR; + return false; } uint32_t length = 0; @@ -140,7 +224,7 @@ extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buff length += 6; } else { // Length is larger than uint32_t max limit. - return ErrorCode::UNKNOWN_ERROR; + return false; } } cert_bytes.insert(cert_bytes.end(), (certs_chain_buffer + index), @@ -148,53 +232,47 @@ extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buff index += length; for (int i = 0; i < cert_bytes.size(); i++) { - cert.encodedCertificate = std::move(cert_bytes); + cert = std::move(cert_bytes); } } else { // SEQUENCE TAG MISSING. - return ErrorCode::UNKNOWN_ERROR; + return false; } - return ErrorCode::OK; + return true; } -ErrorCode getCertificateChain( - rust::Vec<rust::u8>& chainBuffer, - std::vector<aidl::android::hardware::security::keymint::Certificate>& certChain) { +bool getCertificateChain(rust::Vec<rust::u8>& chainBuffer, std::vector<certificate_t>& certChain) { uint8_t* data = chainBuffer.data(); int index = 0; int data_size = chainBuffer.size(); while (index < data_size) { - aidl::android::hardware::security::keymint::Certificate cert = - aidl::android::hardware::security::keymint::Certificate(); - if (extractCertFromCertChainBuffer(data, data_size, index, cert) != ErrorCode::OK) { - return ErrorCode::UNKNOWN_ERROR; + certificate_t cert; + if (!extractCertFromCertChainBuffer(data, data_size, index, cert)) { + return false; } certChain.push_back(std::move(cert)); } - return ErrorCode::OK; + return true; } bool validateCertChain(rust::Vec<rust::u8> cert_buf, uint32_t cert_len, bool strict_issuer_check) { - std::vector<aidl::android::hardware::security::keymint::Certificate> cert_chain = - std::vector<aidl::android::hardware::security::keymint::Certificate>(); + std::vector<certificate_t> cert_chain = std::vector<certificate_t>(); if (cert_len <= 0) { return false; } - if (getCertificateChain(cert_buf, cert_chain) != ErrorCode::OK) { + if (!getCertificateChain(cert_buf, cert_chain)) { return false; } + std::stringstream cert_data; for (int i = 0; i < cert_chain.size(); i++) { - std::cout << cert_chain[i].toString() << "\n"; + cert_data << bin2hex(cert_chain[i]) << std::endl; } - auto result = aidl::android::hardware::security::keymint::test::ChainSignaturesAreValid( - cert_chain, strict_issuer_check); - - if (result == testing::AssertionSuccess()) return true; + LOG(INFO) << cert_data.str() << "\n"; - return false; + return ChainSignaturesAreValid(cert_chain, strict_issuer_check); } /** @@ -278,7 +356,7 @@ CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key, rust::Vec<rust::u8> tag) { CxxResult cxx_result{}; keymaster_error_t error; - cxx_result.error = KM_ERROR_OK; + cxx_result.error = false; uint8_t* enc_secure_key_data = encrypted_secure_key.data(); int enc_secure_key_size = encrypted_secure_key.size(); @@ -295,13 +373,16 @@ CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key, keymaster::UniquePtr<TEST_SECURE_KEY_WRAPPER, TEST_SECURE_KEY_WRAPPER_Delete> sec_key_wrapper( TEST_SECURE_KEY_WRAPPER_new()); if (!sec_key_wrapper.get()) { - cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED; + LOG(ERROR) << "createWrappedKey - Failed to allocate a memory"; + cxx_result.error = true; return cxx_result; } // Fill version = 0 if (!ASN1_INTEGER_set(sec_key_wrapper->version, 0)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling version: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } @@ -309,14 +390,18 @@ CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key, if (enc_transport_key_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_transport_key, enc_transport_key_data, enc_transport_key_size)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling encrypted transport key: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } // Fill encrypted secure key. if (enc_secure_key_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_key, enc_secure_key_data, enc_secure_key_size)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling encrypted secure key: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } @@ -324,46 +409,55 @@ CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key, keymaster::AuthorizationSet auth_list = build_wrapped_key_auth_list(); error = build_auth_list(auth_list, sec_key_wrapper->key_desc->key_params); if (error != KM_ERROR_OK) { - cxx_result.error = error; + cxx_result.error = true; return cxx_result; } // Fill secure key format. if (!ASN1_INTEGER_set(sec_key_wrapper->key_desc->key_format, KM_KEY_FORMAT_RAW)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling secure key format: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } // Fill initialization vector used for encrypting secure key. if (iv_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->initialization_vector, iv_data, iv_size)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling IV: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } // Fill GCM-tag, extracted during secure key encryption. if (tag_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->tag, tag_data, tag_size)) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while filling GCM-tag: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } // ASN.1 DER-encoding of secure key wrapper. int asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), nullptr); if (asn1_data_len < 0) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "createWrappedKey - Error while performing DER encode: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } std::vector<uint8_t> asn1_data(asn1_data_len, 0); if (!asn1_data.data()) { - cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED; + LOG(ERROR) << "createWrappedKey - Failed to allocate a memory for asn1_data"; + cxx_result.error = true; return cxx_result; } uint8_t* p = asn1_data.data(); asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), &p); if (asn1_data_len < 0) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } @@ -508,7 +602,7 @@ bool performCryptoOpUsingKeystoreEngine(int64_t grant_id) { CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { CxxResult cxx_result{}; - cxx_result.error = KM_ERROR_OK; + cxx_result.error = false; uint8_t* cert_data = cert_buf.data(); int cert_data_size = cert_buf.size(); @@ -516,17 +610,18 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { std::vector<uint8_t> cert_bytes; cert_bytes.insert(cert_bytes.end(), cert_data, (cert_data + cert_data_size)); - aidl::android::hardware::security::keymint::X509_Ptr cert( - aidl::android::hardware::security::keymint::test::parse_cert_blob(cert_bytes)); + X509_Ptr cert(parseCertBlob(cert_bytes)); if (!cert.get()) { - cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED; + LOG(ERROR) << "getValueFromAttestRecord - Failed to allocate a memory for certificate"; + cxx_result.error = true; return cxx_result; } - ASN1_OCTET_STRING* attest_rec = - aidl::android::hardware::security::keymint::test::get_attestation_record(cert.get()); + ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get()); if (!attest_rec) { - cxx_result.error = keymaster::TranslateLastOpenSslError(); + LOG(ERROR) << "getValueFromAttestRecord - Error in getAttestationRecord: " + << keymaster::TranslateLastOpenSslError(); + cxx_result.error = true; return cxx_result; } @@ -540,13 +635,14 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { std::vector<uint8_t> att_unique_id; std::vector<uint8_t> att_app_id; - auto error = aidl::android::hardware::security::keymint::parse_attestation_record( - attest_rec->data, attest_rec->length, &att_attestation_version, - &att_attestation_security_level, &att_keymint_version, &att_keymint_security_level, - &att_challenge, &att_sw_enforced, &att_hw_enforced, &att_unique_id); - EXPECT_EQ(ErrorCode::OK, error); - if (error != ErrorCode::OK) { - cxx_result.error = static_cast<int32_t>(error); + int32_t error = + static_cast<int32_t>(aidl::android::hardware::security::keymint::parse_attestation_record( + attest_rec->data, attest_rec->length, &att_attestation_version, + &att_attestation_security_level, &att_keymint_version, &att_keymint_security_level, + &att_challenge, &att_sw_enforced, &att_hw_enforced, &att_unique_id)); + if (error) { + LOG(ERROR) << "getValueFromAttestRecord - Error in parse_attestation_record: " << error; + cxx_result.error = true; return cxx_result; } @@ -557,7 +653,8 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { int pos = att_sw_enforced.find( aidl::android::hardware::security::keymint::Tag::ATTESTATION_APPLICATION_ID); if (pos == -1) { - cxx_result.error = KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING; + LOG(ERROR) << "getValueFromAttestRecord - Attestation-application-id missing."; + cxx_result.error = true; return cxx_result; } aidl::android::hardware::security::keymint::KeyParameter param = att_sw_enforced[pos]; @@ -569,7 +666,8 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { if (auth_tag == aidl::android::hardware::security::keymint::Tag::ATTESTATION_CHALLENGE) { if (att_challenge.size() == 0) { - cxx_result.error = KM_ERROR_ATTESTATION_CHALLENGE_MISSING; + LOG(ERROR) << "getValueFromAttestRecord - Attestation-challenge missing."; + cxx_result.error = true; return cxx_result; } std::move(att_challenge.begin(), att_challenge.end(), std::back_inserter(cxx_result.data)); @@ -578,7 +676,8 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { if (auth_tag == aidl::android::hardware::security::keymint::Tag::UNIQUE_ID) { if (att_unique_id.size() == 0) { - cxx_result.error = KM_ERROR_UNSUPPORTED_TAG; + LOG(ERROR) << "getValueFromAttestRecord - unsupported tag - UNIQUE_ID."; + cxx_result.error = true; return cxx_result; } std::move(att_unique_id.begin(), att_unique_id.end(), std::back_inserter(cxx_result.data)); @@ -587,7 +686,8 @@ CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) { int pos = att_hw_enforced.find(auth_tag); if (pos == -1) { - cxx_result.error = KM_ERROR_UNSUPPORTED_TAG; + LOG(ERROR) << "getValueFromAttestRecord - unsupported tag."; + cxx_result.error = true; return cxx_result; } aidl::android::hardware::security::keymint::KeyParameter param = att_hw_enforced[pos]; diff --git a/keystore2/test_utils/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs index 019c26b1..95e3160b 100644 --- a/keystore2/test_utils/ffi_test_utils.rs +++ b/keystore2/test_utils/ffi_test_utils.rs @@ -21,7 +21,7 @@ use android_hardware_security_keymint::aidl::android::hardware::security::keymin mod ffi { struct CxxResult { data: Vec<u8>, - error: i32, + error: bool, } unsafe extern "C++" { @@ -50,7 +50,7 @@ pub fn validate_certchain(cert_buf: &[u8]) -> Result<bool, Error> { /// Collect the result from CxxResult into a Rust supported structure. fn get_result(result: ffi::CxxResult) -> Result<Vec<u8>, Error> { - if result.error == 0 && !result.data.is_empty() { + if !result.error && !result.data.is_empty() { Ok(result.data) } else { Err(Error::DerEncodeFailed) @@ -97,7 +97,7 @@ pub fn perform_crypto_op_using_keystore_engine(grant_id: i64) -> Result<bool, Er /// Get the value of the given `Tag` from attestation record. pub fn get_value_from_attest_record(cert_buf: &[u8], tag: Tag) -> Result<Vec<u8>, Error> { let result = ffi::getValueFromAttestRecord(cert_buf.to_vec(), tag.0); - if result.error == 0 && !result.data.is_empty() { + if !result.error && !result.data.is_empty() { return Ok(result.data); } Err(Error::AttestRecordGetValueFailed) |