/* * Copyright 2021, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "PresentationSession" #include "PresentationSession.h" #include "IdentityCredentialStore.h" #include <android/hardware/identity/support/IdentityCredentialSupport.h> #include <string.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <cppbor.h> #include <cppbor_parse.h> #include "FakeSecureHardwareProxy.h" #include "IdentityCredential.h" #include "PresentationSession.h" namespace aidl::android::hardware::identity { using ::std::optional; using namespace ::android::hardware::identity; PresentationSession::~PresentationSession() {} int PresentationSession::initialize() { if (!hwProxy_->initialize()) { LOG(ERROR) << "hwProxy->initialize failed"; return IIdentityCredentialStore::STATUS_FAILED; } optional<uint64_t> id = hwProxy_->getId(); if (!id) { LOG(ERROR) << "Error getting id for session"; return IIdentityCredentialStore::STATUS_FAILED; } id_ = id.value(); optional<uint64_t> authChallenge = hwProxy_->getAuthChallenge(); if (!authChallenge) { LOG(ERROR) << "Error getting authChallenge for session"; return IIdentityCredentialStore::STATUS_FAILED; } authChallenge_ = authChallenge.value(); return IIdentityCredentialStore::STATUS_OK; } ndk::ScopedAStatus PresentationSession::getEphemeralKeyPair(vector<uint8_t>* outKeyPair) { if (ephemeralKeyPair_.size() == 0) { optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair(); if (!ephemeralKeyPriv) { LOG(ERROR) << "Error getting ephemeral private key for session"; return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error getting ephemeral private key for session")); } optional<vector<uint8_t>> ephemeralKeyPair = support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value()); if (!ephemeralKeyPair) { LOG(ERROR) << "Error creating ephemeral key-pair"; return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error creating ephemeral key-pair")); } ephemeralKeyPair_ = ephemeralKeyPair.value(); } *outKeyPair = ephemeralKeyPair_; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PresentationSession::getAuthChallenge(int64_t* outChallenge) { *outChallenge = authChallenge_; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PresentationSession::setReaderEphemeralPublicKey( const vector<uint8_t>& publicKey) { // We expect the reader ephemeral public key to be same size and curve // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH // won't work. So its length should be 65 bytes and it should be // starting with 0x04. if (publicKey.size() != 65 || publicKey[0] != 0x04) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Reader public key is not in expected format")); } readerPublicKey_ = publicKey; vector<uint8_t> pubKeyP256(publicKey.begin() + 1, publicKey.end()); if (!hwProxy_->setReaderEphemeralPublicKey(pubKeyP256)) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error setting readerEphemeralPublicKey for session")); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PresentationSession::setSessionTranscript( const vector<uint8_t>& sessionTranscript) { sessionTranscript_ = sessionTranscript; if (!hwProxy_->setSessionTranscript(sessionTranscript)) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error setting SessionTranscript for session")); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PresentationSession::getCredential( const vector<uint8_t>& credentialData, shared_ptr<IIdentityCredential>* outCredential) { shared_ptr<PresentationSession> p = ref<PresentationSession>(); shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>( hwProxyFactory_, credentialData, p, hardwareInformation_); int ret = credential->initialize(); if (ret != IIdentityCredentialStore::STATUS_OK) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( ret, "Error initializing IdentityCredential")); } *outCredential = std::move(credential); return ndk::ScopedAStatus::ok(); } uint64_t PresentationSession::getSessionId() { return id_; } vector<uint8_t> PresentationSession::getSessionTranscript() { return sessionTranscript_; } vector<uint8_t> PresentationSession::getReaderEphemeralPublicKey() { return readerPublicKey_; } } // namespace aidl::android::hardware::identity