Loading security/keymint/aidl/vts/functional/AttestKeyTest.cpp +1 −88 Original line number Diff line number Diff line Loading @@ -88,96 +88,9 @@ string get_imei(int slot) { class AttestKeyTest : public KeyMintAidlTestBase { public: void SetUp() override { check_skip_test(); skipAttestKeyTest(); KeyMintAidlTestBase::SetUp(); } protected: const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key"; const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore"; ErrorCode GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { // The original specification for KeyMint v1 required ATTEST_KEY not be combined // with any other key purpose, but the original VTS tests incorrectly did exactly that. // This means that a device that launched prior to Android T (API level 33) may // accept or even require KeyPurpose::SIGN too. if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) { AuthorizationSet key_desc_plus_sign = key_desc; key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN); auto result = GenerateKey(key_desc_plus_sign, attest_key, key_blob, key_characteristics, cert_chain); if (result == ErrorCode::OK) { return result; } // If the key generation failed, it may be because the device is (correctly) // rejecting the combination of ATTEST_KEY+SIGN. Fall through to try again with // just ATTEST_KEY. } return GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain); } // Check if ATTEST_KEY feature is disabled bool is_attest_key_feature_disabled(void) const { if (!check_feature(FEATURE_KEYSTORE_APP_ATTEST_KEY)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_KEYSTORE_APP_ATTEST_KEY + " is disabled"; return true; } return false; } // Check if StrongBox KeyStore is enabled bool is_strongbox_enabled(void) const { if (check_feature(FEATURE_STRONGBOX_KEYSTORE)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_STRONGBOX_KEYSTORE + " is enabled"; return true; } return false; } // Check if chipset has received a waiver allowing it to be launched with Android S or T with // Keymaster 4.0 in StrongBox. bool is_chipset_allowed_km4_strongbox(void) const { std::array<char, PROPERTY_VALUE_MAX> buffer; const int32_t first_api_level = property_get_int32("ro.board.first_api_level", 0); if (first_api_level <= 0 || first_api_level > __ANDROID_API_T__) return false; auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr); if (res <= 0) return false; const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"}; for (const string model : allowed_soc_models) { if (model.compare(buffer.data()) == 0) { GTEST_LOG_(INFO) << "QTI SOC Model " + model + " is allowed SB KM 4.0"; return true; } } return false; } // Skip the test if all the following conditions hold: // 1. ATTEST_KEY feature is disabled // 2. STRONGBOX is enabled // 3. The device is running one of the chipsets that have received a waiver // allowing it to be launched with Android S (or later) with Keymaster 4.0 // in StrongBox void check_skip_test(void) const { // Check the chipset first as that doesn't require a round-trip to Package Manager. if (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() && is_attest_key_feature_disabled()) { GTEST_SKIP() << "Test is not applicable"; } } }; /* Loading security/keymint/aidl/vts/functional/BootloaderStateTest.cpp +18 −17 Original line number Diff line number Diff line Loading @@ -34,20 +34,13 @@ using ::std::vector; // Since this test needs to talk to KeyMint HAL, it can only run as root. Thus, // bootloader can not be locked. class BootloaderStateTest : public testing::TestWithParam<std::string> { public: virtual void SetUp() override { ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str())); keyMint_ = IKeyMintDevice::fromBinder(binder); ASSERT_TRUE(keyMint_) << "Failed to get KM device"; } std::shared_ptr<IKeyMintDevice> keyMint_; }; class BootloaderStateTest : public KeyMintAidlTestBase {}; // Check that attested bootloader state is set to unlocked. TEST_P(BootloaderStateTest, IsUnlocked) { // Generate a key with attestation. vector<uint8_t> key_blob; vector<KeyCharacteristics> key_characteristics; AuthorizationSet keyDesc = AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .EcdsaSigningKey(EcCurve::P_256) Loading @@ -55,15 +48,23 @@ TEST_P(BootloaderStateTest, IsUnlocked) { .AttestationApplicationId("bar") .Digest(Digest::NONE) .SetDefaultValidity(); KeyCreationResult creationResult; auto kmStatus = keyMint_->generateKey(keyDesc.vector_data(), std::nullopt, &creationResult); ASSERT_TRUE(kmStatus.isOk()); vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain); auto result = GenerateKey(keyDesc, &key_blob, &key_characteristics); // If factory provisioned attestation key is not supported by Strongbox, // then create a key with self-signed attestation and use it as the // attestation key instead. if (SecLevel() == SecurityLevel::STRONGBOX && result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) { result = GenerateKeyWithSelfSignedAttestKey( AuthorizationSetBuilder() .EcdsaKey(EcCurve::P_256) .AttestKey() .SetDefaultValidity(), /* attest key params */ keyDesc, &key_blob, &key_characteristics); } ASSERT_EQ(ErrorCode::OK, result); // Parse attested AVB values. const auto& attestation_cert = key_cert_chain[0].encodedCertificate; X509_Ptr cert(parse_cert_blob(attestation_cert)); X509_Ptr cert(parse_cert_blob(cert_chain_[0].encodedCertificate)); ASSERT_TRUE(cert.get()); ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); Loading security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +85 −2 Original line number Diff line number Diff line Loading @@ -322,11 +322,12 @@ ErrorCode KeyMintAidlTestBase::GenerateKeyWithSelfSignedAttestKey( const AuthorizationSet& attest_key_desc, const AuthorizationSet& key_desc, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { skipAttestKeyTest(); AttestationKey attest_key; vector<Certificate> attest_cert_chain; vector<KeyCharacteristics> attest_key_characteristics; // Generate a key with self signed attestation. auto error = GenerateKey(attest_key_desc, std::nullopt, &attest_key.keyBlob, auto error = GenerateAttestKey(attest_key_desc, std::nullopt, &attest_key.keyBlob, &attest_key_characteristics, &attest_cert_chain); if (error != ErrorCode::OK) { return error; Loading Loading @@ -1548,6 +1549,88 @@ ErrorCode KeyMintAidlTestBase::UseEcdsaKey(const vector<uint8_t>& ecdsaKeyBlob) return result; } ErrorCode KeyMintAidlTestBase::GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { // The original specification for KeyMint v1 required ATTEST_KEY not be combined // with any other key purpose, but the original VTS tests incorrectly did exactly that. // This means that a device that launched prior to Android T (API level 33) may // accept or even require KeyPurpose::SIGN too. if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) { AuthorizationSet key_desc_plus_sign = key_desc; key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN); auto result = GenerateKey(key_desc_plus_sign, attest_key, key_blob, key_characteristics, cert_chain); if (result == ErrorCode::OK) { return result; } // If the key generation failed, it may be because the device is (correctly) // rejecting the combination of ATTEST_KEY+SIGN. Fall through to try again with // just ATTEST_KEY. } return GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain); } // Check if ATTEST_KEY feature is disabled bool KeyMintAidlTestBase::is_attest_key_feature_disabled(void) const { if (!check_feature(FEATURE_KEYSTORE_APP_ATTEST_KEY)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_KEYSTORE_APP_ATTEST_KEY + " is disabled"; return true; } return false; } // Check if StrongBox KeyStore is enabled bool KeyMintAidlTestBase::is_strongbox_enabled(void) const { if (check_feature(FEATURE_STRONGBOX_KEYSTORE)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_STRONGBOX_KEYSTORE + " is enabled"; return true; } return false; } // Check if chipset has received a waiver allowing it to be launched with Android S or T with // Keymaster 4.0 in StrongBox. bool KeyMintAidlTestBase::is_chipset_allowed_km4_strongbox(void) const { std::array<char, PROPERTY_VALUE_MAX> buffer; const int32_t first_api_level = property_get_int32("ro.board.first_api_level", 0); if (first_api_level <= 0 || first_api_level > __ANDROID_API_T__) return false; auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr); if (res <= 0) return false; const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"}; for (const string model : allowed_soc_models) { if (model.compare(buffer.data()) == 0) { GTEST_LOG_(INFO) << "QTI SOC Model " + model + " is allowed SB KM 4.0"; return true; } } return false; } // Skip the test if all the following conditions hold: // 1. ATTEST_KEY feature is disabled // 2. STRONGBOX is enabled // 3. The device is running one of the chipsets that have received a waiver // allowing it to be launched with Android S (or later) with Keymaster 4.0 // in StrongBox void KeyMintAidlTestBase::skipAttestKeyTest(void) const { // Check the chipset first as that doesn't require a round-trip to Package Manager. if (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() && is_attest_key_feature_disabled()) { GTEST_SKIP() << "Test is not applicable"; } } void verify_serial(X509* cert, const uint64_t expected_serial) { BIGNUM_Ptr ser(BN_new()); EXPECT_TRUE(ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), ser.get())); Loading security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h +14 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ using ::std::vector; constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF; const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key"; const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore"; class KeyMintAidlTestBase : public ::testing::TestWithParam<string> { public: struct KeyData { Loading Loading @@ -347,6 +350,17 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> { ErrorCode UseRsaKey(const vector<uint8_t>& rsaKeyBlob); ErrorCode UseEcdsaKey(const vector<uint8_t>& ecdsaKeyBlob); ErrorCode GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain); bool is_attest_key_feature_disabled(void) const; bool is_strongbox_enabled(void) const; bool is_chipset_allowed_km4_strongbox(void) const; void skipAttestKeyTest(void) const; protected: std::shared_ptr<IKeyMintDevice> keymint_; uint32_t os_version_; Loading Loading
security/keymint/aidl/vts/functional/AttestKeyTest.cpp +1 −88 Original line number Diff line number Diff line Loading @@ -88,96 +88,9 @@ string get_imei(int slot) { class AttestKeyTest : public KeyMintAidlTestBase { public: void SetUp() override { check_skip_test(); skipAttestKeyTest(); KeyMintAidlTestBase::SetUp(); } protected: const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key"; const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore"; ErrorCode GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { // The original specification for KeyMint v1 required ATTEST_KEY not be combined // with any other key purpose, but the original VTS tests incorrectly did exactly that. // This means that a device that launched prior to Android T (API level 33) may // accept or even require KeyPurpose::SIGN too. if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) { AuthorizationSet key_desc_plus_sign = key_desc; key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN); auto result = GenerateKey(key_desc_plus_sign, attest_key, key_blob, key_characteristics, cert_chain); if (result == ErrorCode::OK) { return result; } // If the key generation failed, it may be because the device is (correctly) // rejecting the combination of ATTEST_KEY+SIGN. Fall through to try again with // just ATTEST_KEY. } return GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain); } // Check if ATTEST_KEY feature is disabled bool is_attest_key_feature_disabled(void) const { if (!check_feature(FEATURE_KEYSTORE_APP_ATTEST_KEY)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_KEYSTORE_APP_ATTEST_KEY + " is disabled"; return true; } return false; } // Check if StrongBox KeyStore is enabled bool is_strongbox_enabled(void) const { if (check_feature(FEATURE_STRONGBOX_KEYSTORE)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_STRONGBOX_KEYSTORE + " is enabled"; return true; } return false; } // Check if chipset has received a waiver allowing it to be launched with Android S or T with // Keymaster 4.0 in StrongBox. bool is_chipset_allowed_km4_strongbox(void) const { std::array<char, PROPERTY_VALUE_MAX> buffer; const int32_t first_api_level = property_get_int32("ro.board.first_api_level", 0); if (first_api_level <= 0 || first_api_level > __ANDROID_API_T__) return false; auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr); if (res <= 0) return false; const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"}; for (const string model : allowed_soc_models) { if (model.compare(buffer.data()) == 0) { GTEST_LOG_(INFO) << "QTI SOC Model " + model + " is allowed SB KM 4.0"; return true; } } return false; } // Skip the test if all the following conditions hold: // 1. ATTEST_KEY feature is disabled // 2. STRONGBOX is enabled // 3. The device is running one of the chipsets that have received a waiver // allowing it to be launched with Android S (or later) with Keymaster 4.0 // in StrongBox void check_skip_test(void) const { // Check the chipset first as that doesn't require a round-trip to Package Manager. if (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() && is_attest_key_feature_disabled()) { GTEST_SKIP() << "Test is not applicable"; } } }; /* Loading
security/keymint/aidl/vts/functional/BootloaderStateTest.cpp +18 −17 Original line number Diff line number Diff line Loading @@ -34,20 +34,13 @@ using ::std::vector; // Since this test needs to talk to KeyMint HAL, it can only run as root. Thus, // bootloader can not be locked. class BootloaderStateTest : public testing::TestWithParam<std::string> { public: virtual void SetUp() override { ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str())); keyMint_ = IKeyMintDevice::fromBinder(binder); ASSERT_TRUE(keyMint_) << "Failed to get KM device"; } std::shared_ptr<IKeyMintDevice> keyMint_; }; class BootloaderStateTest : public KeyMintAidlTestBase {}; // Check that attested bootloader state is set to unlocked. TEST_P(BootloaderStateTest, IsUnlocked) { // Generate a key with attestation. vector<uint8_t> key_blob; vector<KeyCharacteristics> key_characteristics; AuthorizationSet keyDesc = AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .EcdsaSigningKey(EcCurve::P_256) Loading @@ -55,15 +48,23 @@ TEST_P(BootloaderStateTest, IsUnlocked) { .AttestationApplicationId("bar") .Digest(Digest::NONE) .SetDefaultValidity(); KeyCreationResult creationResult; auto kmStatus = keyMint_->generateKey(keyDesc.vector_data(), std::nullopt, &creationResult); ASSERT_TRUE(kmStatus.isOk()); vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain); auto result = GenerateKey(keyDesc, &key_blob, &key_characteristics); // If factory provisioned attestation key is not supported by Strongbox, // then create a key with self-signed attestation and use it as the // attestation key instead. if (SecLevel() == SecurityLevel::STRONGBOX && result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) { result = GenerateKeyWithSelfSignedAttestKey( AuthorizationSetBuilder() .EcdsaKey(EcCurve::P_256) .AttestKey() .SetDefaultValidity(), /* attest key params */ keyDesc, &key_blob, &key_characteristics); } ASSERT_EQ(ErrorCode::OK, result); // Parse attested AVB values. const auto& attestation_cert = key_cert_chain[0].encodedCertificate; X509_Ptr cert(parse_cert_blob(attestation_cert)); X509_Ptr cert(parse_cert_blob(cert_chain_[0].encodedCertificate)); ASSERT_TRUE(cert.get()); ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); Loading
security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +85 −2 Original line number Diff line number Diff line Loading @@ -322,11 +322,12 @@ ErrorCode KeyMintAidlTestBase::GenerateKeyWithSelfSignedAttestKey( const AuthorizationSet& attest_key_desc, const AuthorizationSet& key_desc, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { skipAttestKeyTest(); AttestationKey attest_key; vector<Certificate> attest_cert_chain; vector<KeyCharacteristics> attest_key_characteristics; // Generate a key with self signed attestation. auto error = GenerateKey(attest_key_desc, std::nullopt, &attest_key.keyBlob, auto error = GenerateAttestKey(attest_key_desc, std::nullopt, &attest_key.keyBlob, &attest_key_characteristics, &attest_cert_chain); if (error != ErrorCode::OK) { return error; Loading Loading @@ -1548,6 +1549,88 @@ ErrorCode KeyMintAidlTestBase::UseEcdsaKey(const vector<uint8_t>& ecdsaKeyBlob) return result; } ErrorCode KeyMintAidlTestBase::GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain) { // The original specification for KeyMint v1 required ATTEST_KEY not be combined // with any other key purpose, but the original VTS tests incorrectly did exactly that. // This means that a device that launched prior to Android T (API level 33) may // accept or even require KeyPurpose::SIGN too. if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) { AuthorizationSet key_desc_plus_sign = key_desc; key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN); auto result = GenerateKey(key_desc_plus_sign, attest_key, key_blob, key_characteristics, cert_chain); if (result == ErrorCode::OK) { return result; } // If the key generation failed, it may be because the device is (correctly) // rejecting the combination of ATTEST_KEY+SIGN. Fall through to try again with // just ATTEST_KEY. } return GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain); } // Check if ATTEST_KEY feature is disabled bool KeyMintAidlTestBase::is_attest_key_feature_disabled(void) const { if (!check_feature(FEATURE_KEYSTORE_APP_ATTEST_KEY)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_KEYSTORE_APP_ATTEST_KEY + " is disabled"; return true; } return false; } // Check if StrongBox KeyStore is enabled bool KeyMintAidlTestBase::is_strongbox_enabled(void) const { if (check_feature(FEATURE_STRONGBOX_KEYSTORE)) { GTEST_LOG_(INFO) << "Feature " + FEATURE_STRONGBOX_KEYSTORE + " is enabled"; return true; } return false; } // Check if chipset has received a waiver allowing it to be launched with Android S or T with // Keymaster 4.0 in StrongBox. bool KeyMintAidlTestBase::is_chipset_allowed_km4_strongbox(void) const { std::array<char, PROPERTY_VALUE_MAX> buffer; const int32_t first_api_level = property_get_int32("ro.board.first_api_level", 0); if (first_api_level <= 0 || first_api_level > __ANDROID_API_T__) return false; auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr); if (res <= 0) return false; const string allowed_soc_models[] = {"SM8450", "SM8475", "SM8550", "SXR2230P"}; for (const string model : allowed_soc_models) { if (model.compare(buffer.data()) == 0) { GTEST_LOG_(INFO) << "QTI SOC Model " + model + " is allowed SB KM 4.0"; return true; } } return false; } // Skip the test if all the following conditions hold: // 1. ATTEST_KEY feature is disabled // 2. STRONGBOX is enabled // 3. The device is running one of the chipsets that have received a waiver // allowing it to be launched with Android S (or later) with Keymaster 4.0 // in StrongBox void KeyMintAidlTestBase::skipAttestKeyTest(void) const { // Check the chipset first as that doesn't require a round-trip to Package Manager. if (is_chipset_allowed_km4_strongbox() && is_strongbox_enabled() && is_attest_key_feature_disabled()) { GTEST_SKIP() << "Test is not applicable"; } } void verify_serial(X509* cert, const uint64_t expected_serial) { BIGNUM_Ptr ser(BN_new()); EXPECT_TRUE(ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), ser.get())); Loading
security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h +14 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ using ::std::vector; constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF; const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key"; const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore"; class KeyMintAidlTestBase : public ::testing::TestWithParam<string> { public: struct KeyData { Loading Loading @@ -347,6 +350,17 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> { ErrorCode UseRsaKey(const vector<uint8_t>& rsaKeyBlob); ErrorCode UseEcdsaKey(const vector<uint8_t>& ecdsaKeyBlob); ErrorCode GenerateAttestKey(const AuthorizationSet& key_desc, const optional<AttestationKey>& attest_key, vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics, vector<Certificate>* cert_chain); bool is_attest_key_feature_disabled(void) const; bool is_strongbox_enabled(void) const; bool is_chipset_allowed_km4_strongbox(void) const; void skipAttestKeyTest(void) const; protected: std::shared_ptr<IKeyMintDevice> keymint_; uint32_t os_version_; Loading