1 /*
2  * Copyright 2021, 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 "PresentationSession"
18 
19 #include "PresentationSession.h"
20 #include "IdentityCredentialStore.h"
21 
22 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
23 
24 #include <string.h>
25 
26 #include <android-base/logging.h>
27 #include <android-base/stringprintf.h>
28 
29 #include <cppbor.h>
30 #include <cppbor_parse.h>
31 
32 #include "FakeSecureHardwareProxy.h"
33 #include "IdentityCredential.h"
34 #include "PresentationSession.h"
35 
36 namespace aidl::android::hardware::identity {
37 
38 using ::std::optional;
39 
40 using namespace ::android::hardware::identity;
41 
~PresentationSession()42 PresentationSession::~PresentationSession() {}
43 
initialize()44 int PresentationSession::initialize() {
45     if (!hwProxy_->initialize()) {
46         LOG(ERROR) << "hwProxy->initialize failed";
47         return IIdentityCredentialStore::STATUS_FAILED;
48     }
49 
50     optional<uint64_t> id = hwProxy_->getId();
51     if (!id) {
52         LOG(ERROR) << "Error getting id for session";
53         return IIdentityCredentialStore::STATUS_FAILED;
54     }
55     id_ = id.value();
56 
57     optional<uint64_t> authChallenge = hwProxy_->getAuthChallenge();
58     if (!authChallenge) {
59         LOG(ERROR) << "Error getting authChallenge for session";
60         return IIdentityCredentialStore::STATUS_FAILED;
61     }
62     authChallenge_ = authChallenge.value();
63 
64     return IIdentityCredentialStore::STATUS_OK;
65 }
66 
getEphemeralKeyPair(vector<uint8_t> * outKeyPair)67 ndk::ScopedAStatus PresentationSession::getEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
68     if (ephemeralKeyPair_.size() == 0) {
69         optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair();
70         if (!ephemeralKeyPriv) {
71             LOG(ERROR) << "Error getting ephemeral private key for session";
72             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
73                     IIdentityCredentialStore::STATUS_FAILED,
74                     "Error getting ephemeral private key for session"));
75         }
76         optional<vector<uint8_t>> ephemeralKeyPair =
77                 support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value());
78         if (!ephemeralKeyPair) {
79             LOG(ERROR) << "Error creating ephemeral key-pair";
80             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
81                     IIdentityCredentialStore::STATUS_FAILED, "Error creating ephemeral key-pair"));
82         }
83         ephemeralKeyPair_ = ephemeralKeyPair.value();
84     }
85     *outKeyPair = ephemeralKeyPair_;
86     return ndk::ScopedAStatus::ok();
87 }
88 
getAuthChallenge(int64_t * outChallenge)89 ndk::ScopedAStatus PresentationSession::getAuthChallenge(int64_t* outChallenge) {
90     *outChallenge = authChallenge_;
91     return ndk::ScopedAStatus::ok();
92 }
93 
setReaderEphemeralPublicKey(const vector<uint8_t> & publicKey)94 ndk::ScopedAStatus PresentationSession::setReaderEphemeralPublicKey(
95         const vector<uint8_t>& publicKey) {
96     // We expect the reader ephemeral public key to be same size and curve
97     // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
98     // won't work. So its length should be 65 bytes and it should be
99     // starting with 0x04.
100     if (publicKey.size() != 65 || publicKey[0] != 0x04) {
101         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
102                 IIdentityCredentialStore::STATUS_FAILED,
103                 "Reader public key is not in expected format"));
104     }
105     readerPublicKey_ = publicKey;
106     vector<uint8_t> pubKeyP256(publicKey.begin() + 1, publicKey.end());
107     if (!hwProxy_->setReaderEphemeralPublicKey(pubKeyP256)) {
108         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
109                 IIdentityCredentialStore::STATUS_FAILED,
110                 "Error setting readerEphemeralPublicKey for session"));
111     }
112     return ndk::ScopedAStatus::ok();
113 }
114 
setSessionTranscript(const vector<uint8_t> & sessionTranscript)115 ndk::ScopedAStatus PresentationSession::setSessionTranscript(
116         const vector<uint8_t>& sessionTranscript) {
117     sessionTranscript_ = sessionTranscript;
118     if (!hwProxy_->setSessionTranscript(sessionTranscript)) {
119         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
120                 IIdentityCredentialStore::STATUS_FAILED,
121                 "Error setting SessionTranscript for session"));
122     }
123     return ndk::ScopedAStatus::ok();
124 }
125 
getCredential(const vector<uint8_t> & credentialData,shared_ptr<IIdentityCredential> * outCredential)126 ndk::ScopedAStatus PresentationSession::getCredential(
127         const vector<uint8_t>& credentialData, shared_ptr<IIdentityCredential>* outCredential) {
128     shared_ptr<PresentationSession> p = ref<PresentationSession>();
129     shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
130             hwProxyFactory_, credentialData, p, hardwareInformation_);
131     int ret = credential->initialize();
132     if (ret != IIdentityCredentialStore::STATUS_OK) {
133         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
134                 ret, "Error initializing IdentityCredential"));
135     }
136     *outCredential = std::move(credential);
137 
138     return ndk::ScopedAStatus::ok();
139 }
140 
getSessionId()141 uint64_t PresentationSession::getSessionId() {
142     return id_;
143 }
144 
getSessionTranscript()145 vector<uint8_t> PresentationSession::getSessionTranscript() {
146     return sessionTranscript_;
147 }
148 
getReaderEphemeralPublicKey()149 vector<uint8_t> PresentationSession::getReaderEphemeralPublicKey() {
150     return readerPublicKey_;
151 }
152 
153 }  // namespace aidl::android::hardware::identity
154