blob: 17a16bf5906b2c494bcb664ebf3af3b7f594fda1 [file] [log] [blame]
Robert Berry25f51352018-03-28 20:26:57 +01001/*
2 * Copyright (C) 2018 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
17package com.android.server.locksettings.recoverablekeystore.serialization;
18
19
20import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.CERT_PATH_ENCODING;
21import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.NAMESPACE;
22import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.OUTPUT_ENCODING;
23import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_ALGORITHM;
24import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_ALIAS;
25import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEY;
26import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEYS;
Robert Berry56588372018-03-29 12:07:17 +010027
28import static com.android.server.locksettings.recoverablekeystore.serialization
29 .KeyChainSnapshotSchema.TAG_BACKEND_PUBLIC_KEY;
Robert Berry25f51352018-03-28 20:26:57 +010030import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_COUNTER_ID;
31import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_RECOVERY_KEY_MATERIAL;
32import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS;
33import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST;
34import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_SNAPSHOT;
35import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_DERIVATION_PARAMS;
36import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_MATERIAL;
37import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_LOCK_SCREEN_UI_TYPE;
38import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MAX_ATTEMPTS;
39import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MEMORY_DIFFICULTY;
40import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SALT;
41import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SERVER_PARAMS;
42import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SNAPSHOT_VERSION;
43import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_TRUSTED_HARDWARE_CERT_PATH;
44import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_USER_SECRET_TYPE;
45
46import android.security.keystore.recovery.KeyChainProtectionParams;
47import android.security.keystore.recovery.KeyChainSnapshot;
48import android.security.keystore.recovery.KeyDerivationParams;
49import android.security.keystore.recovery.WrappedApplicationKey;
50import android.util.Base64;
51import android.util.Xml;
52
53import org.xmlpull.v1.XmlSerializer;
54
55import java.io.IOException;
56import java.io.OutputStream;
57import java.security.cert.CertPath;
58import java.security.cert.CertificateEncodingException;
59import java.util.List;
60
61/**
62 * Serializes a {@link KeyChainSnapshot} instance to XML.
63 */
64public class KeyChainSnapshotSerializer {
65
66 /**
67 * Serializes {@code keyChainSnapshot} to XML, writing to {@code outputStream}.
68 *
69 * @throws IOException if there was an IO error writing to the stream.
70 * @throws CertificateEncodingException if the {@link CertPath} from
71 * {@link KeyChainSnapshot#getTrustedHardwareCertPath()} is not encoded correctly.
72 */
73 public static void serialize(KeyChainSnapshot keyChainSnapshot, OutputStream outputStream)
74 throws IOException, CertificateEncodingException {
75 XmlSerializer xmlSerializer = Xml.newSerializer();
76 xmlSerializer.setOutput(outputStream, OUTPUT_ENCODING);
77 xmlSerializer.startDocument(
78 /*encoding=*/ null,
79 /*standalone=*/ null);
80 xmlSerializer.startTag(NAMESPACE, TAG_KEY_CHAIN_SNAPSHOT);
81 writeKeyChainSnapshotProperties(xmlSerializer, keyChainSnapshot);
82 writeKeyChainProtectionParams(xmlSerializer,
83 keyChainSnapshot.getKeyChainProtectionParams());
84 writeApplicationKeys(xmlSerializer,
85 keyChainSnapshot.getWrappedApplicationKeys());
86 xmlSerializer.endTag(NAMESPACE, TAG_KEY_CHAIN_SNAPSHOT);
87 xmlSerializer.endDocument();
88 }
89
90 private static void writeApplicationKeys(
91 XmlSerializer xmlSerializer, List<WrappedApplicationKey> wrappedApplicationKeys)
92 throws IOException {
93 xmlSerializer.startTag(NAMESPACE, TAG_APPLICATION_KEYS);
94 for (WrappedApplicationKey key : wrappedApplicationKeys) {
95 xmlSerializer.startTag(NAMESPACE, TAG_APPLICATION_KEY);
96 writeApplicationKeyProperties(xmlSerializer, key);
97 xmlSerializer.endTag(NAMESPACE, TAG_APPLICATION_KEY);
98 }
99 xmlSerializer.endTag(NAMESPACE, TAG_APPLICATION_KEYS);
100 }
101
102 private static void writeApplicationKeyProperties(
103 XmlSerializer xmlSerializer, WrappedApplicationKey applicationKey) throws IOException {
104 writePropertyTag(xmlSerializer, TAG_ALIAS, applicationKey.getAlias());
105 writePropertyTag(xmlSerializer, TAG_KEY_MATERIAL, applicationKey.getEncryptedKeyMaterial());
106 }
107
108 private static void writeKeyChainProtectionParams(
109 XmlSerializer xmlSerializer,
110 List<KeyChainProtectionParams> keyChainProtectionParamsList) throws IOException {
111 xmlSerializer.startTag(NAMESPACE, TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST);
112 for (KeyChainProtectionParams keyChainProtectionParams : keyChainProtectionParamsList) {
113 xmlSerializer.startTag(NAMESPACE, TAG_KEY_CHAIN_PROTECTION_PARAMS);
114 writeKeyChainProtectionParamsProperties(xmlSerializer, keyChainProtectionParams);
115 xmlSerializer.endTag(NAMESPACE, TAG_KEY_CHAIN_PROTECTION_PARAMS);
116 }
117 xmlSerializer.endTag(NAMESPACE, TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST);
118 }
119
120 private static void writeKeyChainProtectionParamsProperties(
121 XmlSerializer xmlSerializer, KeyChainProtectionParams keyChainProtectionParams)
122 throws IOException {
123 writePropertyTag(xmlSerializer, TAG_USER_SECRET_TYPE,
124 keyChainProtectionParams.getUserSecretType());
125 writePropertyTag(xmlSerializer, TAG_LOCK_SCREEN_UI_TYPE,
126 keyChainProtectionParams.getLockScreenUiFormat());
127
128 // NOTE: Do not serialize the 'secret' field. It should never be set anyway for snapshots
129 // we generate.
130
131 writeKeyDerivationParams(xmlSerializer, keyChainProtectionParams.getKeyDerivationParams());
132 }
133
134 private static void writeKeyDerivationParams(
135 XmlSerializer xmlSerializer, KeyDerivationParams keyDerivationParams)
136 throws IOException {
137 xmlSerializer.startTag(NAMESPACE, TAG_KEY_DERIVATION_PARAMS);
138 writeKeyDerivationParamsProperties(
139 xmlSerializer, keyDerivationParams);
140 xmlSerializer.endTag(NAMESPACE, TAG_KEY_DERIVATION_PARAMS);
141 }
142
143 private static void writeKeyDerivationParamsProperties(
144 XmlSerializer xmlSerializer, KeyDerivationParams keyDerivationParams)
145 throws IOException {
146 writePropertyTag(xmlSerializer, TAG_ALGORITHM, keyDerivationParams.getAlgorithm());
147 writePropertyTag(xmlSerializer, TAG_SALT, keyDerivationParams.getSalt());
148 writePropertyTag(xmlSerializer, TAG_MEMORY_DIFFICULTY,
149 keyDerivationParams.getMemoryDifficulty());
150 }
151
152 private static void writeKeyChainSnapshotProperties(
153 XmlSerializer xmlSerializer, KeyChainSnapshot keyChainSnapshot)
154 throws IOException, CertificateEncodingException {
155
156 writePropertyTag(xmlSerializer, TAG_SNAPSHOT_VERSION,
157 keyChainSnapshot.getSnapshotVersion());
158 writePropertyTag(xmlSerializer, TAG_MAX_ATTEMPTS, keyChainSnapshot.getMaxAttempts());
159 writePropertyTag(xmlSerializer, TAG_COUNTER_ID, keyChainSnapshot.getCounterId());
160 writePropertyTag(xmlSerializer, TAG_RECOVERY_KEY_MATERIAL,
161 keyChainSnapshot.getEncryptedRecoveryKeyBlob());
162 writePropertyTag(xmlSerializer, TAG_SERVER_PARAMS, keyChainSnapshot.getServerParams());
163 writePropertyTag(xmlSerializer, TAG_TRUSTED_HARDWARE_CERT_PATH,
164 keyChainSnapshot.getTrustedHardwareCertPath());
Robert Berry56588372018-03-29 12:07:17 +0100165 if (keyChainSnapshot.getTrustedHardwarePublicKey() != null) {
166 writePropertyTag(xmlSerializer, TAG_BACKEND_PUBLIC_KEY,
167 keyChainSnapshot.getTrustedHardwarePublicKey());
168 }
Robert Berry25f51352018-03-28 20:26:57 +0100169 }
170
171 private static void writePropertyTag(
172 XmlSerializer xmlSerializer, String propertyName, long propertyValue)
173 throws IOException {
174 xmlSerializer.startTag(NAMESPACE, propertyName);
175 xmlSerializer.text(Long.toString(propertyValue));
176 xmlSerializer.endTag(NAMESPACE, propertyName);
177 }
178
179 private static void writePropertyTag(
180 XmlSerializer xmlSerializer, String propertyName, String propertyValue)
181 throws IOException {
182 xmlSerializer.startTag(NAMESPACE, propertyName);
183 xmlSerializer.text(propertyValue);
184 xmlSerializer.endTag(NAMESPACE, propertyName);
185 }
186
187 private static void writePropertyTag(
188 XmlSerializer xmlSerializer, String propertyName, byte[] propertyValue)
189 throws IOException {
190 xmlSerializer.startTag(NAMESPACE, propertyName);
191 xmlSerializer.text(Base64.encodeToString(propertyValue, /*flags=*/ Base64.DEFAULT));
192 xmlSerializer.endTag(NAMESPACE, propertyName);
193 }
194
195 private static void writePropertyTag(
196 XmlSerializer xmlSerializer, String propertyName, CertPath certPath)
197 throws IOException, CertificateEncodingException {
198 writePropertyTag(xmlSerializer, propertyName, certPath.getEncoded(CERT_PATH_ENCODING));
199 }
200
201 // Statics only
202 private KeyChainSnapshotSerializer() {}
203}