KeyDerivationParams.java revision 86f5bb1a8cfe2d169767fb723d315955dda3a0e6
1/* 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.recovery; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.annotation.SystemApi; 22import android.os.Parcel; 23import android.os.Parcelable; 24 25import com.android.internal.util.Preconditions; 26 27import java.lang.annotation.Retention; 28import java.lang.annotation.RetentionPolicy; 29 30/** 31 * Collection of parameters which define a key derivation function. 32 * Currently only supports salted SHA-256. 33 * 34 * @hide 35 */ 36@SystemApi 37public final class KeyDerivationParams implements Parcelable { 38 39 // IMPORTANT! PLEASE READ! 40 // ----------------------- 41 // If you edit this file (e.g., to add new fields), please MAKE SURE to also do the following: 42 // - Update the #writeToParcel(Parcel) method below 43 // - Update the #(Parcel) constructor below 44 // - Update android.security.keystore.recovery.KeyChainSnapshotTest to make sure nobody 45 // accidentally breaks your fields in the Parcel in the future. 46 // - Update com.android.server.locksettings.recoverablekeystore.serialization 47 // .KeyChainSnapshotSerializer to correctly serialize your new field 48 // - Update com.android.server.locksettings.recoverablekeystore.serialization 49 // .KeyChainSnapshotSerializer to correctly deserialize your new field 50 // - Update com.android.server.locksettings.recoverablekeystore.serialization 51 // .KeychainSnapshotSerializerTest to make sure nobody breaks serialization of your field 52 // in the future. 53 54 private final int mAlgorithm; 55 private final byte[] mSalt; 56 private final int mMemoryDifficulty; 57 58 /** @hide */ 59 @Retention(RetentionPolicy.SOURCE) 60 @IntDef(prefix = {"ALGORITHM_"}, value = {ALGORITHM_SHA256, ALGORITHM_SCRYPT}) 61 public @interface KeyDerivationAlgorithm { 62 } 63 64 /** 65 * Salted SHA256. 66 */ 67 public static final int ALGORITHM_SHA256 = 1; 68 69 /** 70 * SCRYPT. 71 */ 72 public static final int ALGORITHM_SCRYPT = 2; 73 74 /** 75 * Creates instance of the class to to derive keys using salted SHA256 hash. 76 * 77 * <p>The salted SHA256 hash is computed over the concatenation of four byte strings, salt_len + 78 * salt + key_material_len + key_material, where salt_len and key_material_len are 4-byte, and 79 * denote the number of bytes for salt and key_material, respectively. 80 */ 81 public static @NonNull KeyDerivationParams createSha256Params(@NonNull byte[] salt) { 82 return new KeyDerivationParams(ALGORITHM_SHA256, salt); 83 } 84 85 /** 86 * Creates instance of the class to to derive keys using the password hashing algorithm SCRYPT. 87 * 88 * <p>We expose only one tuning parameter of SCRYPT, which is the memory cost parameter (i.e. N 89 * in <a href="https://www.tarsnap.com/scrypt/scrypt.pdf">the SCRYPT paper</a>). Regular/default 90 * values are used for the other parameters, to keep the overall running time low. Specifically, 91 * the parallelization parameter p is 1, the block size parameter r is 8, and the hashing output 92 * length is 32-byte. 93 */ 94 public static @NonNull KeyDerivationParams createScryptParams( 95 @NonNull byte[] salt, int memoryDifficulty) { 96 return new KeyDerivationParams(ALGORITHM_SCRYPT, salt, memoryDifficulty); 97 } 98 99 /** 100 * @hide 101 */ 102 private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) { 103 this(algorithm, salt, /*memoryDifficulty=*/ -1); 104 } 105 106 /** 107 * @hide 108 */ 109 private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt, 110 int memoryDifficulty) { 111 mAlgorithm = algorithm; 112 mSalt = Preconditions.checkNotNull(salt); 113 mMemoryDifficulty = memoryDifficulty; 114 } 115 116 /** 117 * Gets algorithm. 118 */ 119 public @KeyDerivationAlgorithm int getAlgorithm() { 120 return mAlgorithm; 121 } 122 123 /** 124 * Gets salt. 125 */ 126 public @NonNull byte[] getSalt() { 127 return mSalt; 128 } 129 130 /** 131 * Gets the memory difficulty parameter for the hashing algorithm. 132 * 133 * <p>The effect of this parameter depends on the algorithm in use. For example, please see 134 * {@link #createScryptParams(byte[], int)} for choosing the parameter for SCRYPT. 135 * 136 * <p>If the specific algorithm does not support such a memory difficulty parameter, its value 137 * should be -1. 138 */ 139 public int getMemoryDifficulty() { 140 return mMemoryDifficulty; 141 } 142 143 public static final Parcelable.Creator<KeyDerivationParams> CREATOR = 144 new Parcelable.Creator<KeyDerivationParams>() { 145 public KeyDerivationParams createFromParcel(Parcel in) { 146 return new KeyDerivationParams(in); 147 } 148 149 public KeyDerivationParams[] newArray(int length) { 150 return new KeyDerivationParams[length]; 151 } 152 }; 153 154 @Override 155 public void writeToParcel(Parcel out, int flags) { 156 out.writeInt(mAlgorithm); 157 out.writeByteArray(mSalt); 158 out.writeInt(mMemoryDifficulty); 159 } 160 161 /** 162 * @hide 163 */ 164 protected KeyDerivationParams(Parcel in) { 165 mAlgorithm = in.readInt(); 166 mSalt = in.createByteArray(); 167 mMemoryDifficulty = in.readInt(); 168 } 169 170 @Override 171 public int describeContents() { 172 return 0; 173 } 174} 175