blob: 9c9773e5d145b96ab82d1625adea593141540cb9 [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());
Max Bires04b682d2020-01-14 16:10:36 -0800100 out.writeInt(mSpec.getUserAuthenticationType());
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100101 out.writeBoolean(mSpec.isUserPresenceRequired());
Eran Messeri852c8f12017-11-15 05:55:52 +0000102 out.writeByteArray(mSpec.getAttestationChallenge());
103 out.writeBoolean(mSpec.isUniqueIdIncluded());
104 out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
105 out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100106 out.writeBoolean(mSpec.isStrongBoxBacked());
107 out.writeBoolean(mSpec.isUserConfirmationRequired());
108 out.writeBoolean(mSpec.isUnlockedDeviceRequired());
Rubin Xub3a13e12019-12-24 13:35:02 +0000109 out.writeBoolean(mSpec.isCriticalToDeviceEncryption());
Eran Messeri852c8f12017-11-15 05:55:52 +0000110 }
111
112 private static Date readDateOrNull(Parcel in) {
113 boolean hasDate = in.readBoolean();
114 if (hasDate) {
115 return new Date(in.readLong());
116 } else {
117 return null;
118 }
119 }
120
121 private ParcelableKeyGenParameterSpec(Parcel in) {
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100122 final String keystoreAlias = in.readString();
123 final int purposes = in.readInt();
124 final int uid = in.readInt();
125 final int keySize = in.readInt();
Eran Messeri852c8f12017-11-15 05:55:52 +0000126
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100127 final int keySpecType = in.readInt();
Eran Messeri852c8f12017-11-15 05:55:52 +0000128 AlgorithmParameterSpec algorithmSpec = null;
129 if (keySpecType == ALGORITHM_PARAMETER_SPEC_NONE) {
130 algorithmSpec = null;
131 } else if (keySpecType == ALGORITHM_PARAMETER_SPEC_RSA) {
132 int rsaKeySize = in.readInt();
133 BigInteger publicExponent = new BigInteger(in.createByteArray());
134 algorithmSpec = new RSAKeyGenParameterSpec(rsaKeySize, publicExponent);
135 } else if (keySpecType == ALGORITHM_PARAMETER_SPEC_EC) {
136 String stdName = in.readString();
137 algorithmSpec = new ECGenParameterSpec(stdName);
138 } else {
139 throw new IllegalArgumentException(
Eran Messeri47670542017-12-09 21:25:04 +0000140 String.format("Unknown algorithm parameter spec: %d", keySpecType));
Eran Messeri852c8f12017-11-15 05:55:52 +0000141 }
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100142
143 final X500Principal certificateSubject = new X500Principal(in.createByteArray());
144 final BigInteger certificateSerialNumber = new BigInteger(in.createByteArray());
145 final Date certificateNotBefore = new Date(in.readLong());
146 final Date certificateNotAfter = new Date(in.readLong());
147 final Date keyValidityStartDate = readDateOrNull(in);
148 final Date keyValidityForOriginationEnd = readDateOrNull(in);
149 final Date keyValidityForConsumptionEnd = readDateOrNull(in);
150 final String[] digests = in.createStringArray();
151 final String[] encryptionPaddings = in.createStringArray();
152 final String[] signaturePaddings = in.createStringArray();
153 final String[] blockModes = in.createStringArray();
154 final boolean randomizedEncryptionRequired = in.readBoolean();
155 final boolean userAuthenticationRequired = in.readBoolean();
156 final int userAuthenticationValidityDurationSeconds = in.readInt();
Max Bires04b682d2020-01-14 16:10:36 -0800157 final int userAuthenticationTypes = in.readInt();
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100158 final boolean userPresenceRequired = in.readBoolean();
159 final byte[] attestationChallenge = in.createByteArray();
160 final boolean uniqueIdIncluded = in.readBoolean();
161 final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
162 final boolean invalidatedByBiometricEnrollment = in.readBoolean();
163 final boolean isStrongBoxBacked = in.readBoolean();
164 final boolean userConfirmationRequired = in.readBoolean();
165 final boolean unlockedDeviceRequired = in.readBoolean();
Rubin Xub3a13e12019-12-24 13:35:02 +0000166 final boolean criticalToDeviceEncryption = in.readBoolean();
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100167 // The KeyGenParameterSpec is intentionally not constructed using a Builder here:
168 // The intention is for this class to break if new parameters are added to the
169 // KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
170 mSpec = new KeyGenParameterSpec(
171 keystoreAlias,
172 uid,
173 keySize,
174 algorithmSpec,
175 certificateSubject,
176 certificateSerialNumber,
177 certificateNotBefore,
178 certificateNotAfter,
179 keyValidityStartDate,
180 keyValidityForOriginationEnd,
181 keyValidityForConsumptionEnd,
182 purposes,
183 digests,
184 encryptionPaddings,
185 signaturePaddings,
186 blockModes,
187 randomizedEncryptionRequired,
188 userAuthenticationRequired,
189 userAuthenticationValidityDurationSeconds,
Max Bires04b682d2020-01-14 16:10:36 -0800190 userAuthenticationTypes,
Eran Messeri5a5c6e02018-06-28 11:20:44 +0100191 userPresenceRequired,
192 attestationChallenge,
193 uniqueIdIncluded,
194 userAuthenticationValidWhileOnBody,
195 invalidatedByBiometricEnrollment,
196 isStrongBoxBacked,
197 userConfirmationRequired,
Rubin Xub3a13e12019-12-24 13:35:02 +0000198 unlockedDeviceRequired,
199 criticalToDeviceEncryption);
Eran Messeri852c8f12017-11-15 05:55:52 +0000200 }
201
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700202 public static final @android.annotation.NonNull Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() {
Eran Messeri852c8f12017-11-15 05:55:52 +0000203 @Override
204 public ParcelableKeyGenParameterSpec createFromParcel(Parcel in) {
205 return new ParcelableKeyGenParameterSpec(in);
206 }
207
208 @Override
209 public ParcelableKeyGenParameterSpec[] newArray(int size) {
210 return new ParcelableKeyGenParameterSpec[size];
211 }
212 };
213
214 public KeyGenParameterSpec getSpec() {
215 return mSpec;
216 }
217}