1 /* 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 17 package android.security.keystore.recovery; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import com.android.internal.util.Preconditions; 26 27 /** 28 * Helper class with data necessary recover a single application key, given a recovery key. 29 * 30 * <ul> 31 * <li>Alias - Keystore alias of the key. 32 * <li>Encrypted key material. 33 * </ul> 34 * 35 * Note that Application info is not included. Recovery Agent can only make its own keys 36 * recoverable. 37 * 38 * @hide 39 */ 40 @SystemApi 41 public final class WrappedApplicationKey implements Parcelable { 42 private String mAlias; 43 // The only supported format is AES-256 symmetric key. 44 private byte[] mEncryptedKeyMaterial; 45 // The optional metadata that's authenticated (but unencrypted) with the key material. 46 private byte[] mMetadata; 47 48 // IMPORTANT! PLEASE READ! 49 // ----------------------- 50 // If you edit this file (e.g., to add new fields), please MAKE SURE to also do the following: 51 // - Update the #writeToParcel(Parcel) method below 52 // - Update the #(Parcel) constructor below 53 // - Update android.security.keystore.recovery.KeyChainSnapshotTest to make sure nobody 54 // accidentally breaks your fields in the Parcel in the future. 55 // - Update com.android.server.locksettings.recoverablekeystore.serialization 56 // .KeyChainSnapshotSerializer to correctly serialize your new field 57 // - Update com.android.server.locksettings.recoverablekeystore.serialization 58 // .KeyChainSnapshotSerializer to correctly deserialize your new field 59 // - Update com.android.server.locksettings.recoverablekeystore.serialization 60 // .KeychainSnapshotSerializerTest to make sure nobody breaks serialization of your field 61 // in the future. 62 63 /** 64 * Builder for creating {@link WrappedApplicationKey}. 65 */ 66 public static class Builder { 67 private WrappedApplicationKey mInstance = new WrappedApplicationKey(); 68 69 /** 70 * Sets Application-specific alias of the key. 71 * 72 * @param alias The alias. 73 * @return This builder. 74 */ setAlias(@onNull String alias)75 public @NonNull Builder setAlias(@NonNull String alias) { 76 mInstance.mAlias = alias; 77 return this; 78 } 79 80 /** 81 * Sets key material encrypted by recovery key. 82 * 83 * @param encryptedKeyMaterial The key material 84 * @return This builder 85 */ setEncryptedKeyMaterial(@onNull byte[] encryptedKeyMaterial)86 public @NonNull Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) { 87 mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial; 88 return this; 89 } 90 91 /** 92 * Sets the metadata that is authenticated (but unecrypted) with the key material. 93 * 94 * @param metadata The metadata 95 * @return This builder 96 */ setMetadata(@ullable byte[] metadata)97 public @NonNull Builder setMetadata(@Nullable byte[] metadata) { 98 mInstance.mMetadata = metadata; 99 return this; 100 } 101 102 /** 103 * Creates a new {@link WrappedApplicationKey} instance. 104 * 105 * @return new instance 106 * @throws NullPointerException if some required fields were not set. 107 */ build()108 public @NonNull WrappedApplicationKey build() { 109 Preconditions.checkNotNull(mInstance.mAlias); 110 Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial); 111 return mInstance; 112 } 113 } 114 WrappedApplicationKey()115 private WrappedApplicationKey() { } 116 117 /** 118 * @deprecated Use the builder instead. 119 * @hide 120 */ 121 @Deprecated WrappedApplicationKey(@onNull String alias, @NonNull byte[] encryptedKeyMaterial)122 public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) { 123 mAlias = Preconditions.checkNotNull(alias); 124 mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial); 125 } 126 127 /** 128 * Application-specific alias of the key. 129 * 130 * @see java.security.KeyStore.aliases 131 */ getAlias()132 public @NonNull String getAlias() { 133 return mAlias; 134 } 135 136 /** Key material encrypted by recovery key. */ getEncryptedKeyMaterial()137 public @NonNull byte[] getEncryptedKeyMaterial() { 138 return mEncryptedKeyMaterial; 139 } 140 141 /** The metadata with the key. */ getMetadata()142 public @Nullable byte[] getMetadata() { 143 return mMetadata; 144 } 145 146 public static final @NonNull Parcelable.Creator<WrappedApplicationKey> CREATOR = 147 new Parcelable.Creator<WrappedApplicationKey>() { 148 public WrappedApplicationKey createFromParcel(Parcel in) { 149 return new WrappedApplicationKey(in); 150 } 151 152 public WrappedApplicationKey[] newArray(int length) { 153 return new WrappedApplicationKey[length]; 154 } 155 }; 156 157 @Override writeToParcel(Parcel out, int flags)158 public void writeToParcel(Parcel out, int flags) { 159 out.writeString(mAlias); 160 out.writeByteArray(mEncryptedKeyMaterial); 161 out.writeByteArray(mMetadata); 162 } 163 164 /** 165 * @hide 166 */ WrappedApplicationKey(Parcel in)167 protected WrappedApplicationKey(Parcel in) { 168 mAlias = in.readString(); 169 mEncryptedKeyMaterial = in.createByteArray(); 170 // Check if there is still data to be read. 171 if (in.dataAvail() > 0) { 172 mMetadata = in.createByteArray(); 173 } 174 } 175 176 @Override describeContents()177 public int describeContents() { 178 return 0; 179 } 180 } 181