1 /*
2  * Copyright 2020, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include "km_compat.h"
20 #include <keymint_support/keymint_tags.h>
21 
22 #include <aidl/android/hardware/security/keymint/Algorithm.h>
23 #include <aidl/android/hardware/security/keymint/BlockMode.h>
24 #include <aidl/android/hardware/security/keymint/Digest.h>
25 #include <aidl/android/hardware/security/keymint/PaddingMode.h>
26 #include <android/binder_manager.h>
27 
28 #include <openssl/evp.h>
29 #include <openssl/x509.h>
30 
31 #define DEFINE_OPENSSL_OBJECT_POINTER(name) using name##_Ptr = bssl::UniquePtr<name>
32 
33 DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY);
34 DEFINE_OPENSSL_OBJECT_POINTER(X509);
35 
36 using ::aidl::android::hardware::security::keymint::Algorithm;
37 using ::aidl::android::hardware::security::keymint::BlockMode;
38 using ::aidl::android::hardware::security::keymint::Certificate;
39 using ::aidl::android::hardware::security::keymint::Digest;
40 using ::aidl::android::hardware::security::keymint::PaddingMode;
41 using ::aidl::android::hardware::security::keymint::SecurityLevel;
42 using ::aidl::android::hardware::security::keymint::Tag;
43 using ::aidl::android::security::compat::IKeystoreCompatService;
44 
45 namespace KMV1 = ::aidl::android::hardware::security::keymint;
46 
47 extern "C" int32_t addKeyMintDeviceService();
48 
getDevice()49 static std::variant<std::shared_ptr<IKeyMintDevice>, ScopedAStatus> getDevice() {
50     addKeyMintDeviceService();
51     std::shared_ptr<IKeyMintDevice> device;
52     auto service = IKeystoreCompatService::fromBinder(
53         ndk::SpAIBinder(AServiceManager_getService("android.security.compat")));
54     if (!service) {
55         return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
56     }
57     service->getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT, &device);
58     if (!device) {
59         return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
60     }
61     return device;
62 }
63 
64 static std::variant<std::vector<Certificate>, ScopedAStatus>
getCertificate(std::shared_ptr<IKeyMintDevice> device,const std::vector<KeyParameter> & keyParams)65 getCertificate(std::shared_ptr<IKeyMintDevice> device, const std::vector<KeyParameter>& keyParams) {
66     KeyCreationResult creationResult;
67     auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
68     if (!status.isOk()) {
69         return status;
70     }
71     return creationResult.certificateChain;
72 }
73 
ensureCertChainSize(const std::variant<std::vector<Certificate>,ScopedAStatus> & result,uint32_t size)74 static void ensureCertChainSize(const std::variant<std::vector<Certificate>, ScopedAStatus>& result,
75                                 uint32_t size) {
76     ASSERT_TRUE(std::holds_alternative<std::vector<Certificate>>(result));
77     auto certChain = std::get<std::vector<Certificate>>(result);
78     ASSERT_EQ(certChain.size(), size);
79 }
80 
verify(const Certificate & certificate)81 static void verify(const Certificate& certificate) {
82     const uint8_t* p = certificate.encodedCertificate.data();
83     X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)certificate.encodedCertificate.size()));
84     EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
85     ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
86 }
87 
getRSAKeyParams(const std::vector<KeyParameter> & extraParams)88 static std::vector<KeyParameter> getRSAKeyParams(const std::vector<KeyParameter>& extraParams) {
89     auto keyParams = std::vector<KeyParameter>({
90         KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::RSA),
91         KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 2048),
92         KMV1::makeKeyParameter(KMV1::TAG_RSA_PUBLIC_EXPONENT, 65537),
93         KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, 0),
94         KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, 253402300799000),
95     });
96     keyParams.insert(keyParams.end(), extraParams.begin(), extraParams.end());
97     return keyParams;
98 }
99 
TEST(CertificateTest,TestRSAKeygen)100 TEST(CertificateTest, TestRSAKeygen) {
101     auto keyParams = getRSAKeyParams({
102         KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
103         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::RSA_PSS),
104         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED),
105         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
106     });
107     auto device = getDevice();
108     if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
109         auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
110         ensureCertChainSize(result, 1);
111     }
112 }
113 
TEST(CertificateTest,TestAES)114 TEST(CertificateTest, TestAES) {
115     auto keyParams = {
116         KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::AES),
117         KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 128),
118         KMV1::makeKeyParameter(KMV1::TAG_BLOCK_MODE, BlockMode::CBC),
119         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::NONE),
120         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
121     };
122     auto device = getDevice();
123     if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
124         auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
125         ensureCertChainSize(result, 0);
126     }
127 }
128 
TEST(CertificateTest,TestAttestation)129 TEST(CertificateTest, TestAttestation) {
130     auto keyParams = getRSAKeyParams({
131         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
132         KMV1::makeKeyParameter(KMV1::TAG_ATTESTATION_CHALLENGE, 42),
133         KMV1::makeKeyParameter(KMV1::TAG_ATTESTATION_APPLICATION_ID, 42),
134     });
135     auto device = getDevice();
136     if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
137         auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
138         ensureCertChainSize(result, 3);
139         verify(std::get<std::vector<Certificate>>(result).back());
140     }
141 }
142 
TEST(CertificateTest,TestRSAKeygenNoEncryptNoAuthRequired)143 TEST(CertificateTest, TestRSAKeygenNoEncryptNoAuthRequired) {
144     auto keyParams = getRSAKeyParams({
145         KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
146         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::RSA_PSS),
147         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
148         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
149     });
150     auto device = getDevice();
151     if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
152         auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
153         ensureCertChainSize(result, 1);
154         verify(std::get<std::vector<Certificate>>(result)[0]);
155     }
156 }
157 
TEST(CertificateTest,TestRSAKeygenNoEncryptAuthRequired)158 TEST(CertificateTest, TestRSAKeygenNoEncryptAuthRequired) {
159     auto keyParams = getRSAKeyParams({
160         KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
161         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::RSA_PSS),
162         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
163     });
164     auto device = getDevice();
165     if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
166         auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
167         ensureCertChainSize(result, 1);
168     }
169 }
170