1 /*
2  * Copyright 2019, 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 #define LOG_TAG "IdentityCredentialStore"
18 
19 #include <android-base/logging.h>
20 #include <android/binder_manager.h>
21 
22 #include "IdentityCredential.h"
23 #include "IdentityCredentialStore.h"
24 #include "PresentationSession.h"
25 #include "WritableIdentityCredential.h"
26 
27 namespace aidl::android::hardware::identity {
28 
29 using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
30 
IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,optional<string> remotelyProvisionedComponent)31 IdentityCredentialStore::IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
32                                                  optional<string> remotelyProvisionedComponent)
33     : hwProxyFactory_(hwProxyFactory),
34       remotelyProvisionedComponentName_(remotelyProvisionedComponent) {
35     hardwareInformation_.credentialStoreName = "Identity Credential Reference Implementation";
36     hardwareInformation_.credentialStoreAuthorName = "Google";
37     hardwareInformation_.dataChunkSize = kGcmChunkSize;
38     hardwareInformation_.isDirectAccess = false;
39     hardwareInformation_.supportedDocTypes = {};
40     hardwareInformation_.isRemoteKeyProvisioningSupported =
41             remotelyProvisionedComponentName_.has_value();
42 }
43 
getHardwareInformation(HardwareInformation * hardwareInformation)44 ndk::ScopedAStatus IdentityCredentialStore::getHardwareInformation(
45         HardwareInformation* hardwareInformation) {
46     *hardwareInformation = hardwareInformation_;
47     return ndk::ScopedAStatus::ok();
48 }
49 
createCredential(const string & docType,bool testCredential,shared_ptr<IWritableIdentityCredential> * outWritableCredential)50 ndk::ScopedAStatus IdentityCredentialStore::createCredential(
51         const string& docType, bool testCredential,
52         shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
53     sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
54     shared_ptr<WritableIdentityCredential> wc =
55             ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential,
56                                                                  hardwareInformation_);
57     if (!wc->initialize()) {
58         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
59                 IIdentityCredentialStore::STATUS_FAILED,
60                 "Error initializing WritableIdentityCredential"));
61     }
62     *outWritableCredential = wc;
63     return ndk::ScopedAStatus::ok();
64 }
65 
getCredential(CipherSuite cipherSuite,const vector<uint8_t> & credentialData,shared_ptr<IIdentityCredential> * outCredential)66 ndk::ScopedAStatus IdentityCredentialStore::getCredential(
67         CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
68         shared_ptr<IIdentityCredential>* outCredential) {
69     // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
70     if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
71         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
72                 IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED,
73                 "Unsupported cipher suite"));
74     }
75 
76     shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
77             hwProxyFactory_, credentialData, nullptr /* session */, hardwareInformation_);
78     auto ret = credential->initialize();
79     if (ret != IIdentityCredentialStore::STATUS_OK) {
80         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
81                 int(ret), "Error initializing IdentityCredential"));
82     }
83     *outCredential = credential;
84     return ndk::ScopedAStatus::ok();
85 }
86 
createPresentationSession(CipherSuite cipherSuite,shared_ptr<IPresentationSession> * outSession)87 ndk::ScopedAStatus IdentityCredentialStore::createPresentationSession(
88         CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) {
89     // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
90     if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
91         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
92                 IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED,
93                 "Unsupported cipher suite"));
94     }
95 
96     sp<SecureHardwareSessionProxy> hwProxy = hwProxyFactory_->createSessionProxy();
97     shared_ptr<PresentationSession> session = ndk::SharedRefBase::make<PresentationSession>(
98             hwProxyFactory_, hwProxy, hardwareInformation_);
99     auto ret = session->initialize();
100     if (ret != IIdentityCredentialStore::STATUS_OK) {
101         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
102                 int(ret), "Error initializing PresentationSession"));
103     }
104     *outSession = session;
105     return ndk::ScopedAStatus::ok();
106 }
107 
getRemotelyProvisionedComponent(shared_ptr<IRemotelyProvisionedComponent> * outRemotelyProvisionedComponent)108 ndk::ScopedAStatus IdentityCredentialStore::getRemotelyProvisionedComponent(
109         shared_ptr<IRemotelyProvisionedComponent>* outRemotelyProvisionedComponent) {
110     if (!remotelyProvisionedComponentName_) {
111         return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
112                 EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
113     }
114 
115     ndk::SpAIBinder binder(
116             AServiceManager_waitForService(remotelyProvisionedComponentName_->c_str()));
117     if (binder.get() == nullptr) {
118         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
119                 IIdentityCredentialStore::STATUS_FAILED,
120                 "Unable to get remotely provisioned component"));
121     }
122 
123     *outRemotelyProvisionedComponent = IRemotelyProvisionedComponent::fromBinder(binder);
124     return ndk::ScopedAStatus::ok();
125 }
126 
127 }  // namespace aidl::android::hardware::identity
128