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