Home | History | Annotate | Download | only in recovery
      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 
     17 package android.security.keystore.recovery;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.NonNull;
     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 import java.lang.annotation.Retention;
     28 import 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
     37 public 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