1 /* 2 * Copyright 2019 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 21 import java.util.ArrayList; 22 import java.util.Collection; 23 import java.util.Collections; 24 import java.util.LinkedHashMap; 25 import java.util.List; 26 27 /** 28 * An object that holds personalization data. 29 * 30 * This data includes access control profiles and a set of data entries and values, grouped by 31 * namespace. 32 * 33 * This is used to provision data into a {@link WritableIdentityCredential}. 34 * 35 * @see WritableIdentityCredential#personalize 36 */ 37 public class PersonalizationData { 38 PersonalizationData()39 private PersonalizationData() { 40 } 41 42 private ArrayList<AccessControlProfile> mProfiles = new ArrayList<>(); 43 44 private LinkedHashMap<String, NamespaceData> mNamespaces = new LinkedHashMap<>(); 45 getAccessControlProfiles()46 Collection<AccessControlProfile> getAccessControlProfiles() { 47 return Collections.unmodifiableCollection(mProfiles); 48 } 49 getNamespaces()50 Collection<String> getNamespaces() { 51 return Collections.unmodifiableCollection(mNamespaces.keySet()); 52 } 53 getNamespaceData(String namespace)54 NamespaceData getNamespaceData(String namespace) { 55 return mNamespaces.get(namespace); 56 } 57 58 static class NamespaceData { 59 60 private String mNamespace; 61 private LinkedHashMap<String, EntryData> mEntries = new LinkedHashMap<>(); 62 NamespaceData(String namespace)63 private NamespaceData(String namespace) { 64 this.mNamespace = namespace; 65 } 66 getNamespaceName()67 String getNamespaceName() { 68 return mNamespace; 69 } 70 getEntryNames()71 Collection<String> getEntryNames() { 72 return Collections.unmodifiableCollection(mEntries.keySet()); 73 } 74 getAccessControlProfileIds(String name)75 Collection<AccessControlProfileId> getAccessControlProfileIds(String name) { 76 EntryData value = mEntries.get(name); 77 if (value != null) { 78 return value.mAccessControlProfileIds; 79 } 80 return null; 81 } 82 getEntryValue(String name)83 byte[] getEntryValue(String name) { 84 EntryData value = mEntries.get(name); 85 if (value != null) { 86 return value.mValue; 87 } 88 return null; 89 } 90 } 91 92 private static class EntryData { 93 byte[] mValue; 94 Collection<AccessControlProfileId> mAccessControlProfileIds; 95 EntryData(byte[] value, Collection<AccessControlProfileId> accessControlProfileIds)96 EntryData(byte[] value, Collection<AccessControlProfileId> accessControlProfileIds) { 97 this.mValue = value; 98 this.mAccessControlProfileIds = accessControlProfileIds; 99 } 100 } 101 102 /** 103 * A builder for {@link PersonalizationData}. 104 */ 105 public static final class Builder { 106 private PersonalizationData mData; 107 108 /** 109 * Creates a new builder for a given namespace. 110 */ Builder()111 public Builder() { 112 this.mData = new PersonalizationData(); 113 } 114 115 /** 116 * Adds a new entry to the builder. 117 * 118 * @param namespace The namespace to use, e.g. {@code org.iso.18013-5.2019}. 119 * @param name The name of the entry, e.g. {@code height}. 120 * @param accessControlProfileIds A set of access control profiles to use. 121 * @param value The value to add, in CBOR encoding. 122 * @return The builder. 123 */ putEntry(@onNull String namespace, @NonNull String name, @NonNull Collection<AccessControlProfileId> accessControlProfileIds, @NonNull byte[] value)124 public @NonNull Builder putEntry(@NonNull String namespace, @NonNull String name, 125 @NonNull Collection<AccessControlProfileId> accessControlProfileIds, 126 @NonNull byte[] value) { 127 NamespaceData namespaceData = mData.mNamespaces.get(namespace); 128 if (namespaceData == null) { 129 namespaceData = new NamespaceData(namespace); 130 mData.mNamespaces.put(namespace, namespaceData); 131 } 132 // TODO: validate/verify that value is proper CBOR. 133 namespaceData.mEntries.put(name, new EntryData(value, accessControlProfileIds)); 134 return this; 135 } 136 137 /** 138 * Adds a new access control profile to the builder. 139 * 140 * @param profile The access control profile. 141 * @return The builder. 142 */ addAccessControlProfile(@onNull AccessControlProfile profile)143 public @NonNull Builder addAccessControlProfile(@NonNull AccessControlProfile profile) { 144 mData.mProfiles.add(profile); 145 return this; 146 } 147 148 /** 149 * Creates a new {@link PersonalizationData} with all the entries added to the builder. 150 * 151 * @return A new {@link PersonalizationData} instance. 152 */ build()153 public @NonNull PersonalizationData build() { 154 return mData; 155 } 156 } 157 158 } 159