/* * Copyright 2020 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. */ package android.security.identity; import android.annotation.NonNull; import android.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; /** * An object that contains the result of retrieving data from a credential. This is used to return * data requested from a {@link IdentityCredential}. */ class CredstoreResultData extends ResultData { int mFeatureVersion = 0; byte[] mStaticAuthenticationData = null; byte[] mAuthenticatedData = null; byte[] mMessageAuthenticationCode = null; byte[] mSignature = null; private Map> mData = new LinkedHashMap<>(); private static class EntryData { @Status int mStatus; byte[] mValue; EntryData(byte[] value, @Status int status) { this.mValue = value; this.mStatus = status; } } CredstoreResultData() {} @Override public @NonNull byte[] getAuthenticatedData() { return mAuthenticatedData; } @Override public @Nullable byte[] getMessageAuthenticationCode() { return mMessageAuthenticationCode; } @Override @Nullable byte[] getSignature() { if (mFeatureVersion < 202301) { throw new UnsupportedOperationException(); } return mSignature; } @Override public @NonNull byte[] getStaticAuthenticationData() { return mStaticAuthenticationData; } @Override public @NonNull Collection getNamespaces() { return Collections.unmodifiableCollection(mData.keySet()); } @Override public @Nullable Collection getEntryNames(@NonNull String namespaceName) { Map innerMap = mData.get(namespaceName); if (innerMap == null) { return null; } return Collections.unmodifiableCollection(innerMap.keySet()); } @Override public @Nullable Collection getRetrievedEntryNames(@NonNull String namespaceName) { Map innerMap = mData.get(namespaceName); if (innerMap == null) { return null; } LinkedList result = new LinkedList(); for (Map.Entry entry : innerMap.entrySet()) { if (entry.getValue().mStatus == STATUS_OK) { result.add(entry.getKey()); } } return result; } private EntryData getEntryData(@NonNull String namespaceName, @NonNull String name) { Map innerMap = mData.get(namespaceName); if (innerMap == null) { return null; } return innerMap.get(name); } @Override @Status public int getStatus(@NonNull String namespaceName, @NonNull String name) { EntryData value = getEntryData(namespaceName, name); if (value == null) { return STATUS_NOT_REQUESTED; } return value.mStatus; } @Override public @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name) { EntryData value = getEntryData(namespaceName, name); if (value == null) { return null; } return value.mValue; } static class Builder { private CredstoreResultData mResultData; Builder(int featureVersion, byte[] staticAuthenticationData, byte[] authenticatedData, byte[] messageAuthenticationCode, byte[] signature) { this.mResultData = new CredstoreResultData(); this.mResultData.mFeatureVersion = featureVersion; this.mResultData.mStaticAuthenticationData = staticAuthenticationData; this.mResultData.mAuthenticatedData = authenticatedData; this.mResultData.mMessageAuthenticationCode = messageAuthenticationCode; this.mResultData.mSignature = signature; } private Map getOrCreateInnerMap(String namespaceName) { Map innerMap = mResultData.mData.get(namespaceName); if (innerMap == null) { innerMap = new LinkedHashMap<>(); mResultData.mData.put(namespaceName, innerMap); } return innerMap; } Builder addEntry(String namespaceName, String name, byte[] value) { Map innerMap = getOrCreateInnerMap(namespaceName); innerMap.put(name, new EntryData(value, STATUS_OK)); return this; } Builder addErrorStatus(String namespaceName, String name, @Status int status) { Map innerMap = getOrCreateInnerMap(namespaceName); innerMap.put(name, new EntryData(null, status)); return this; } CredstoreResultData build() { return mResultData; } } }