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