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