blob: 98e458930a7f2e9709a185c2b3e88f544dd934ec [file] [log] [blame]
Eran Messeri852c8f12017-11-15 05:55:52 +00001/*
2 * Copyright (C) 2017 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 android.security.keystore;
18
Eran Messeri852c8f12017-11-15 05:55:52 +000019import android.os.Parcel;
Rubin Xub3a13e12019-12-24 13:35:02 +000020import android.os.Parcelable;
Eran Messeri852c8f12017-11-15 05:55:52 +000021
22import java.math.BigInteger;
23import java.security.spec.AlgorithmParameterSpec;
24import java.security.spec.ECGenParameterSpec;
25import java.security.spec.RSAKeyGenParameterSpec;
26import java.util.Date;
27
28import javax.security.auth.x500.X500Principal;
29
30/**
31 * A parcelable version of KeyGenParameterSpec
32 * @hide only used for communicating with the DPMS.
33 */
34public final class ParcelableKeyGenParameterSpec implements Parcelable {
35 private static final int ALGORITHM_PARAMETER_SPEC_NONE = 1;
36 private static final int ALGORITHM_PARAMETER_SPEC_RSA = 2;
37 private static final int ALGORITHM_PARAMETER_SPEC_EC = 3;
38
39 private final KeyGenParameterSpec mSpec;
40
41 public ParcelableKeyGenParameterSpec(
42 KeyGenParameterSpec spec) {
43 mSpec = spec;
44 }
45
46 public int describeContents() {
47 return 0;
48 }
49
50 private static void writeOptionalDate(Parcel out, Date date) {
51 if (date != null) {
52 out.writeBoolean(true);
53 out.writeLong(date.getTime());
54 } else {
55 out.writeBoolean(false);
56 }
57 }
58
59 public void writeToParcel(Parcel out, int flags) {
60 out.writeString(mSpec.getKeystoreAlias());
61 out.writeInt(mSpec.getPurposes());
62 out.writeInt(mSpec.getUid());
63 out.writeInt(mSpec.getKeySize());
64
65 // Only needs to support RSAKeyGenParameterSpec and ECGenParameterSpec.
66 AlgorithmParameterSpec algoSpec = mSpec.getAlgorithmParameterSpec();
67 if (algoSpec == null) {
68 out.writeInt(ALGORITHM_PARAMETER_SPEC_NONE);
69 } else if (algoSpec instanceof RSAKeyGenParameterSpec) {
70 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algoSpec;
71 out.writeInt(ALGORITHM_PARAMETER_SPEC_RSA);
72 out.writeInt(rsaSpec.getKeysize());
73 out.writeByteArray(rsaSpec.getPublicExponent().toByteArray());
74 } else if (algoSpec instanceof ECGenParameterSpec) {
75 ECGenParameterSpec ecSpec = (ECGenParameterSpec) algoSpec;
76 out.writeInt(ALGORITHM_PARAMETER_SPEC_EC);
77 out.writeString(ecSpec.getName());
78 } else {
79 throw new IllegalArgumentException(
80 String.format("Unknown algorithm parameter spec: %s", algoSpec.getClass()));
81 }
82 out.writeByteArray(mSpec.getCertificateSubject().getEncoded());
83 out.writeByteArray(mSpec.getCertificateSerialNumber().toByteArray());
Eran Messeri47670542017-12-09 21:25:04 +000084 out.writeLong(mSpec.getCertificateNotBefore().getTime());
85 out.writeLong(mSpec.getCertificateNotAfter().getTime());
Eran Messeri852c8f12017-11-15 05:55:52 +000086 writeOptionalDate(out, mSpec.getKeyValidityStart());
87 writeOptionalDate(out, mSpec.getKeyValidityForOriginationEnd());
88 writeOptionalDate(out, mSpec.getKeyValidityForConsumptionEnd());
Eran Messeri47670542017-12-09 21:25:04 +000089 if (mSpec.isDigestsSpecified()) {
90 out.writeStringArray(mSpec.getDigests());
91 } else {
92 out.writeStringArray(null);
93 }
Eran Messeri852c8f12017-11-15 05:55:52 +000094 out.writeStringArray(mSpec.getEncryptionPaddings());
95 out.writeStringArray(mSpec.getSignaturePaddings());
96 out.writeStringArray(mSpec.getBlockModes());
97 out.writeBoolean(mSpec.isRandomizedEncryptionRequired());
98 out.writeBoolean(mSpec.isUserAuthenticationRequired());
99 out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100100 out.writeBoolean(mSpec.isUserPresenceRequired());
Eran Messeri852c8f12017-11-15 05:55:52 +0000101 out.writeByteArray(mSpec.getAttestationChallenge());
102 out.writeBoolean(mSpec.isUniqueIdIncluded());
103 out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
104 out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100105 out.writeBoolean(mSpec.isStrongBoxBacked());
106 out.writeBoolean(mSpec.isUserConfirmationRequired());
107 out.writeBoolean(mSpec.isUnlockedDeviceRequired());
Rubin Xub3a13e12019-12-24 13:35:02 +0000108 out.writeBoolean(mSpec.isCriticalToDeviceEncryption());
Eran Messeri852c8f12017-11-15 05:55:52 +0000109 }
110
111 private static Date readDateOrNull(Parcel in) {
112 boolean hasDate = in.readBoolean();
113 if (hasDate) {
114 return new Date(in.readLong());
115 } else {
116 return null;
117 }
118 }
119
120 private ParcelableKeyGenParameterSpec(Parcel in) {
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100121 final String keystoreAlias = in.readString();
122 final int purposes = in.readInt();
123 final int uid = in.readInt();
124 final int keySize = in.readInt();
Eran Messeri852c8f12017-11-15 05:55:52 +0000125
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100126 final int keySpecType = in.readInt();
Eran Messeri852c8f12017-11-15 05:55:52 +0000127 AlgorithmParameterSpec algorithmSpec = null;
128 if (keySpecType == ALGORITHM_PARAMETER_SPEC_NONE) {
129 algorithmSpec = null;
130 } else if (keySpecType == ALGORITHM_PARAMETER_SPEC_RSA) {
131 int rsaKeySize = in.readInt();
132 BigInteger publicExponent = new BigInteger(in.createByteArray());
133 algorithmSpec = new RSAKeyGenParameterSpec(rsaKeySize, publicExponent);
134 } else if (keySpecType == ALGORITHM_PARAMETER_SPEC_EC) {
135 String stdName = in.readString();
136 algorithmSpec = new ECGenParameterSpec(stdName);
137 } else {
138 throw new IllegalArgumentException(
Eran Messeri47670542017-12-09 21:25:04 +0000139 String.format("Unknown algorithm parameter spec: %d", keySpecType));
Eran Messeri852c8f12017-11-15 05:55:52 +0000140 }
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100141
142 final X500Principal certificateSubject = new X500Principal(in.createByteArray());
143 final BigInteger certificateSerialNumber = new BigInteger(in.createByteArray());
144 final Date certificateNotBefore = new Date(in.readLong());
145 final Date certificateNotAfter = new Date(in.readLong());
146 final Date keyValidityStartDate = readDateOrNull(in);
147 final Date keyValidityForOriginationEnd = readDateOrNull(in);
148 final Date keyValidityForConsumptionEnd = readDateOrNull(in);
149 final String[] digests = in.createStringArray();
150 final String[] encryptionPaddings = in.createStringArray();
151 final String[] signaturePaddings = in.createStringArray();
152 final String[] blockModes = in.createStringArray();
153 final boolean randomizedEncryptionRequired = in.readBoolean();
154 final boolean userAuthenticationRequired = in.readBoolean();
155 final int userAuthenticationValidityDurationSeconds = in.readInt();
156 final boolean userPresenceRequired = in.readBoolean();
157 final byte[] attestationChallenge = in.createByteArray();
158 final boolean uniqueIdIncluded = in.readBoolean();
159 final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
160 final boolean invalidatedByBiometricEnrollment = in.readBoolean();
161 final boolean isStrongBoxBacked = in.readBoolean();
162 final boolean userConfirmationRequired = in.readBoolean();
163 final boolean unlockedDeviceRequired = in.readBoolean();
Rubin Xub3a13e12019-12-24 13:35:02 +0000164 final boolean criticalToDeviceEncryption = in.readBoolean();
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100165 // The KeyGenParameterSpec is intentionally not constructed using a Builder here:
166 // The intention is for this class to break if new parameters are added to the
167 // KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
168 mSpec = new KeyGenParameterSpec(
169 keystoreAlias,
170 uid,
171 keySize,
172 algorithmSpec,
173 certificateSubject,
174 certificateSerialNumber,
175 certificateNotBefore,
176 certificateNotAfter,
177 keyValidityStartDate,
178 keyValidityForOriginationEnd,
179 keyValidityForConsumptionEnd,
180 purposes,
181 digests,
182 encryptionPaddings,
183 signaturePaddings,
184 blockModes,
185 randomizedEncryptionRequired,
186 userAuthenticationRequired,
187 userAuthenticationValidityDurationSeconds,
188 userPresenceRequired,
189 attestationChallenge,
190 uniqueIdIncluded,
191 userAuthenticationValidWhileOnBody,
192 invalidatedByBiometricEnrollment,
193 isStrongBoxBacked,
194 userConfirmationRequired,
Rubin Xub3a13e12019-12-24 13:35:02 +0000195 unlockedDeviceRequired,
196 criticalToDeviceEncryption);
Eran Messeri852c8f12017-11-15 05:55:52 +0000197 }
198
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700199 public static final @android.annotation.NonNull Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() {
Eran Messeri852c8f12017-11-15 05:55:52 +0000200 @Override
201 public ParcelableKeyGenParameterSpec createFromParcel(Parcel in) {
202 return new ParcelableKeyGenParameterSpec(in);
203 }
204
205 @Override
206 public ParcelableKeyGenParameterSpec[] newArray(int size) {
207 return new ParcelableKeyGenParameterSpec[size];
208 }
209 };
210
211 public KeyGenParameterSpec getSpec() {
212 return mSpec;
213 }
214}