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