Merge "credstore: Pass additional information to Identity Credential HAL."
This commit is contained in:
commit
50678f526b
4 changed files with 115 additions and 5 deletions
|
@ -261,7 +261,35 @@ Status Credential::getEntries(const vector<uint8_t>& requestMessage,
|
||||||
signingKeyBlob = authKey->keyBlob;
|
signingKeyBlob = authKey->keyBlob;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status =
|
// Pass the HAL enough information to allow calculating the size of
|
||||||
|
// DeviceNameSpaces ahead of time.
|
||||||
|
vector<RequestNamespace> halRequestNamespaces;
|
||||||
|
for (const RequestNamespaceParcel& rns : requestNamespaces) {
|
||||||
|
RequestNamespace ns;
|
||||||
|
ns.namespaceName = rns.namespaceName;
|
||||||
|
for (const RequestEntryParcel& rep : rns.entries) {
|
||||||
|
optional<EntryData> entryData = data_->getEntryData(rns.namespaceName, rep.name);
|
||||||
|
if (entryData) {
|
||||||
|
RequestDataItem di;
|
||||||
|
di.name = rep.name;
|
||||||
|
di.size = entryData.value().size;
|
||||||
|
di.accessControlProfileIds = entryData.value().accessControlProfileIds;
|
||||||
|
ns.items.push_back(di);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ns.items.size() > 0) {
|
||||||
|
halRequestNamespaces.push_back(ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This is not catastrophic, we might be dealing with a version 1 implementation which
|
||||||
|
// doesn't have this method.
|
||||||
|
Status status = halBinder_->setRequestedNamespaces(halRequestNamespaces);
|
||||||
|
if (!status.isOk()) {
|
||||||
|
LOG(INFO) << "Failed setting expected requested namespaces assuming V1 HAL "
|
||||||
|
<< "and continuing";
|
||||||
|
}
|
||||||
|
|
||||||
|
status =
|
||||||
halBinder_->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage, signingKeyBlob,
|
halBinder_->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage, signingKeyBlob,
|
||||||
sessionTranscript, readerSignature, requestCounts);
|
sessionTranscript, readerSignature, requestCounts);
|
||||||
if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
|
if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
|
||||||
|
|
|
@ -38,6 +38,8 @@ using ::std::vector;
|
||||||
using ::android::hardware::identity::CipherSuite;
|
using ::android::hardware::identity::CipherSuite;
|
||||||
using ::android::hardware::identity::IIdentityCredential;
|
using ::android::hardware::identity::IIdentityCredential;
|
||||||
using ::android::hardware::identity::IIdentityCredentialStore;
|
using ::android::hardware::identity::IIdentityCredentialStore;
|
||||||
|
using ::android::hardware::identity::RequestDataItem;
|
||||||
|
using ::android::hardware::identity::RequestNamespace;
|
||||||
|
|
||||||
class Credential : public BnCredential {
|
class Credential : public BnCredential {
|
||||||
public:
|
public:
|
||||||
|
@ -80,6 +82,11 @@ class Credential : public BnCredential {
|
||||||
sp<CredentialData> data_;
|
sp<CredentialData> data_;
|
||||||
|
|
||||||
sp<IIdentityCredential> halBinder_;
|
sp<IIdentityCredential> halBinder_;
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
calcExpectedDeviceNameSpacesSize(const vector<uint8_t>& requestMessage,
|
||||||
|
const vector<RequestNamespaceParcel>& requestNamespaces,
|
||||||
|
uint32_t authorizedAcps);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace identity
|
} // namespace identity
|
||||||
|
|
|
@ -39,10 +39,10 @@ using ::android::hardware::identity::SecureAccessControlProfile;
|
||||||
using ::android::hardware::identity::support::chunkVector;
|
using ::android::hardware::identity::support::chunkVector;
|
||||||
|
|
||||||
WritableCredential::WritableCredential(const string& dataPath, const string& credentialName,
|
WritableCredential::WritableCredential(const string& dataPath, const string& credentialName,
|
||||||
const string& /*docType*/, size_t dataChunkSize,
|
const string& docType, size_t dataChunkSize,
|
||||||
sp<IWritableIdentityCredential> halBinder)
|
sp<IWritableIdentityCredential> halBinder)
|
||||||
: dataPath_(dataPath), credentialName_(credentialName), dataChunkSize_(dataChunkSize),
|
: dataPath_(dataPath), credentialName_(credentialName), docType_(docType),
|
||||||
halBinder_(halBinder) {}
|
dataChunkSize_(dataChunkSize), halBinder_(halBinder) {}
|
||||||
|
|
||||||
WritableCredential::~WritableCredential() {}
|
WritableCredential::~WritableCredential() {}
|
||||||
|
|
||||||
|
@ -89,6 +89,62 @@ Status WritableCredential::getCredentialKeyCertificateChain(const vector<uint8_t
|
||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t WritableCredential::calcExpectedProofOfProvisioningSize(
|
||||||
|
const vector<AccessControlProfileParcel>& accessControlProfiles,
|
||||||
|
const vector<EntryNamespaceParcel>& entryNamespaces) {
|
||||||
|
|
||||||
|
// Right now, we calculate the size by simply just calculating the
|
||||||
|
// CBOR. There's a little bit of overhead associated with this (as compared
|
||||||
|
// to just adding up sizes) but it's a lot simpler and robust. In the future
|
||||||
|
// if this turns out to be a problem, we can optimize it.
|
||||||
|
//
|
||||||
|
|
||||||
|
cppbor::Array acpArray;
|
||||||
|
for (const AccessControlProfileParcel& profile : accessControlProfiles) {
|
||||||
|
cppbor::Map map;
|
||||||
|
map.add("id", profile.id);
|
||||||
|
if (profile.readerCertificate.size() > 0) {
|
||||||
|
map.add("readerCertificate", cppbor::Bstr(profile.readerCertificate));
|
||||||
|
}
|
||||||
|
if (profile.userAuthenticationRequired) {
|
||||||
|
map.add("userAuthenticationRequired", profile.userAuthenticationRequired);
|
||||||
|
map.add("timeoutMillis", profile.userAuthenticationTimeoutMillis);
|
||||||
|
}
|
||||||
|
acpArray.add(std::move(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
cppbor::Map dataMap;
|
||||||
|
for (const EntryNamespaceParcel& ensParcel : entryNamespaces) {
|
||||||
|
cppbor::Array entriesArray;
|
||||||
|
for (const EntryParcel& eParcel : ensParcel.entries) {
|
||||||
|
// TODO: ideally do do this without parsing the data (but still validate data is valid
|
||||||
|
// CBOR).
|
||||||
|
auto [itemForValue, _, _2] = cppbor::parse(eParcel.value);
|
||||||
|
if (itemForValue == nullptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cppbor::Map entryMap;
|
||||||
|
entryMap.add("name", eParcel.name);
|
||||||
|
entryMap.add("value", std::move(itemForValue));
|
||||||
|
cppbor::Array acpIdsArray;
|
||||||
|
for (int32_t id : eParcel.accessControlProfileIds) {
|
||||||
|
acpIdsArray.add(id);
|
||||||
|
}
|
||||||
|
entryMap.add("accessControlProfiles", std::move(acpIdsArray));
|
||||||
|
entriesArray.add(std::move(entryMap));
|
||||||
|
}
|
||||||
|
dataMap.add(ensParcel.namespaceName, std::move(entriesArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
cppbor::Array array;
|
||||||
|
array.add("ProofOfProvisioning");
|
||||||
|
array.add(docType_);
|
||||||
|
array.add(std::move(acpArray));
|
||||||
|
array.add(std::move(dataMap));
|
||||||
|
array.add(false); // testCredential
|
||||||
|
return array.encode().size();
|
||||||
|
}
|
||||||
|
|
||||||
Status
|
Status
|
||||||
WritableCredential::personalize(const vector<AccessControlProfileParcel>& accessControlProfiles,
|
WritableCredential::personalize(const vector<AccessControlProfileParcel>& accessControlProfiles,
|
||||||
const vector<EntryNamespaceParcel>& entryNamespaces,
|
const vector<EntryNamespaceParcel>& entryNamespaces,
|
||||||
|
@ -113,7 +169,21 @@ WritableCredential::personalize(const vector<AccessControlProfileParcel>& access
|
||||||
entryCounts.push_back(ensParcel.entries.size());
|
entryCounts.push_back(ensParcel.entries.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status = halBinder_->startPersonalization(accessControlProfiles.size(), entryCounts);
|
ssize_t expectedPoPSize =
|
||||||
|
calcExpectedProofOfProvisioningSize(accessControlProfiles, entryNamespaces);
|
||||||
|
if (expectedPoPSize < 0) {
|
||||||
|
return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
|
||||||
|
"Data is not valid CBOR");
|
||||||
|
}
|
||||||
|
// This is not catastrophic, we might be dealing with a version 1 implementation which
|
||||||
|
// doesn't have this method.
|
||||||
|
Status status = halBinder_->setExpectedProofOfProvisioningSize(expectedPoPSize);
|
||||||
|
if (!status.isOk()) {
|
||||||
|
LOG(INFO) << "Failed setting expected ProofOfProvisioning size, assuming V1 HAL "
|
||||||
|
<< "and continuing";
|
||||||
|
}
|
||||||
|
|
||||||
|
status = halBinder_->startPersonalization(accessControlProfiles.size(), entryCounts);
|
||||||
if (!status.isOk()) {
|
if (!status.isOk()) {
|
||||||
return halStatusToGenericError(status);
|
return halStatusToGenericError(status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,10 +50,15 @@ class WritableCredential : public BnWritableCredential {
|
||||||
private:
|
private:
|
||||||
string dataPath_;
|
string dataPath_;
|
||||||
string credentialName_;
|
string credentialName_;
|
||||||
|
string docType_;
|
||||||
size_t dataChunkSize_;
|
size_t dataChunkSize_;
|
||||||
sp<IWritableIdentityCredential> halBinder_;
|
sp<IWritableIdentityCredential> halBinder_;
|
||||||
vector<uint8_t> attestationCertificate_;
|
vector<uint8_t> attestationCertificate_;
|
||||||
|
|
||||||
|
ssize_t calcExpectedProofOfProvisioningSize(
|
||||||
|
const vector<AccessControlProfileParcel>& accessControlProfiles,
|
||||||
|
const vector<EntryNamespaceParcel>& entryNamespaces);
|
||||||
|
|
||||||
Status ensureAttestationCertificateExists(const vector<uint8_t>& challenge);
|
Status ensureAttestationCertificateExists(const vector<uint8_t>& challenge);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue