1 /* 2 * Copyright 2020 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 package android.security.identity; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 import java.util.Collection; 23 import java.util.Collections; 24 import java.util.LinkedHashMap; 25 import java.util.LinkedList; 26 import java.util.Map; 27 28 /** 29 * An object that contains the result of retrieving data from a credential. This is used to return 30 * data requested from a {@link IdentityCredential}. 31 */ 32 class CredstoreResultData extends ResultData { 33 34 byte[] mStaticAuthenticationData = null; 35 byte[] mAuthenticatedData = null; 36 byte[] mMessageAuthenticationCode = null; 37 38 private Map<String, Map<String, EntryData>> mData = new LinkedHashMap<>(); 39 40 private static class EntryData { 41 @Status 42 int mStatus; 43 byte[] mValue; 44 EntryData(byte[] value, @Status int status)45 EntryData(byte[] value, @Status int status) { 46 this.mValue = value; 47 this.mStatus = status; 48 } 49 } 50 CredstoreResultData()51 CredstoreResultData() {} 52 53 @Override getAuthenticatedData()54 public @NonNull byte[] getAuthenticatedData() { 55 return mAuthenticatedData; 56 } 57 58 @Override getMessageAuthenticationCode()59 public @Nullable byte[] getMessageAuthenticationCode() { 60 return mMessageAuthenticationCode; 61 } 62 63 @Override getStaticAuthenticationData()64 public @NonNull byte[] getStaticAuthenticationData() { 65 return mStaticAuthenticationData; 66 } 67 68 @Override getNamespaces()69 public @NonNull Collection<String> getNamespaces() { 70 return Collections.unmodifiableCollection(mData.keySet()); 71 } 72 73 @Override getEntryNames(@onNull String namespaceName)74 public @Nullable Collection<String> getEntryNames(@NonNull String namespaceName) { 75 Map<String, EntryData> innerMap = mData.get(namespaceName); 76 if (innerMap == null) { 77 return null; 78 } 79 return Collections.unmodifiableCollection(innerMap.keySet()); 80 } 81 82 @Override getRetrievedEntryNames(@onNull String namespaceName)83 public @Nullable Collection<String> getRetrievedEntryNames(@NonNull String namespaceName) { 84 Map<String, EntryData> innerMap = mData.get(namespaceName); 85 if (innerMap == null) { 86 return null; 87 } 88 LinkedList<String> result = new LinkedList<String>(); 89 for (Map.Entry<String, EntryData> entry : innerMap.entrySet()) { 90 if (entry.getValue().mStatus == STATUS_OK) { 91 result.add(entry.getKey()); 92 } 93 } 94 return result; 95 } 96 getEntryData(@onNull String namespaceName, @NonNull String name)97 private EntryData getEntryData(@NonNull String namespaceName, @NonNull String name) { 98 Map<String, EntryData> innerMap = mData.get(namespaceName); 99 if (innerMap == null) { 100 return null; 101 } 102 return innerMap.get(name); 103 } 104 105 @Override 106 @Status getStatus(@onNull String namespaceName, @NonNull String name)107 public int getStatus(@NonNull String namespaceName, @NonNull String name) { 108 EntryData value = getEntryData(namespaceName, name); 109 if (value == null) { 110 return STATUS_NOT_REQUESTED; 111 } 112 return value.mStatus; 113 } 114 115 @Override getEntry(@onNull String namespaceName, @NonNull String name)116 public @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name) { 117 EntryData value = getEntryData(namespaceName, name); 118 if (value == null) { 119 return null; 120 } 121 return value.mValue; 122 } 123 124 static class Builder { 125 private CredstoreResultData mResultData; 126 Builder(byte[] staticAuthenticationData, byte[] authenticatedData, byte[] messageAuthenticationCode)127 Builder(byte[] staticAuthenticationData, 128 byte[] authenticatedData, 129 byte[] messageAuthenticationCode) { 130 this.mResultData = new CredstoreResultData(); 131 this.mResultData.mStaticAuthenticationData = staticAuthenticationData; 132 this.mResultData.mAuthenticatedData = authenticatedData; 133 this.mResultData.mMessageAuthenticationCode = messageAuthenticationCode; 134 } 135 getOrCreateInnerMap(String namespaceName)136 private Map<String, EntryData> getOrCreateInnerMap(String namespaceName) { 137 Map<String, EntryData> innerMap = mResultData.mData.get(namespaceName); 138 if (innerMap == null) { 139 innerMap = new LinkedHashMap<>(); 140 mResultData.mData.put(namespaceName, innerMap); 141 } 142 return innerMap; 143 } 144 addEntry(String namespaceName, String name, byte[] value)145 Builder addEntry(String namespaceName, String name, byte[] value) { 146 Map<String, EntryData> innerMap = getOrCreateInnerMap(namespaceName); 147 innerMap.put(name, new EntryData(value, STATUS_OK)); 148 return this; 149 } 150 addErrorStatus(String namespaceName, String name, @Status int status)151 Builder addErrorStatus(String namespaceName, String name, @Status int status) { 152 Map<String, EntryData> innerMap = getOrCreateInnerMap(namespaceName); 153 innerMap.put(name, new EntryData(null, status)); 154 return this; 155 } 156 build()157 CredstoreResultData build() { 158 return mResultData; 159 } 160 } 161 162 } 163