Mirror KeyProtection.setCriticalToDeviceEncryption so the flag can also be set on keys generated by keystore. Bug: 72178550 Test: atest android.security.keystore.KeyGenParameterSpecTest Test: atest android.security.ParcelableKeyGenParameterSpecTest Change-Id: I7f102c82e60f211028c694d499ffd2838b89bb2b
193 lines
9.1 KiB
Java
193 lines
9.1 KiB
Java
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.security;
|
|
|
|
import static org.hamcrest.Matchers.is;
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertThat;
|
|
|
|
import android.os.Parcel;
|
|
import android.security.keystore.KeyGenParameterSpec;
|
|
import android.security.keystore.KeyProperties;
|
|
import android.security.keystore.ParcelableKeyGenParameterSpec;
|
|
|
|
import androidx.test.runner.AndroidJUnit4;
|
|
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
|
|
import java.math.BigInteger;
|
|
import java.security.spec.ECGenParameterSpec;
|
|
import java.security.spec.RSAKeyGenParameterSpec;
|
|
import java.util.Date;
|
|
|
|
import javax.security.auth.x500.X500Principal;
|
|
|
|
/** Unit tests for {@link ParcelableKeyGenParameterSpec}. */
|
|
@RunWith(AndroidJUnit4.class)
|
|
public final class ParcelableKeyGenParameterSpecTest {
|
|
static final String ALIAS = "keystore-alias";
|
|
static final String ANOTHER_ALIAS = "another-keystore-alias";
|
|
static final int KEY_PURPOSES = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY;
|
|
static final int UID = 1230;
|
|
static final int KEYSIZE = 2048;
|
|
static final X500Principal SUBJECT = new X500Principal("CN=subject");
|
|
static final BigInteger SERIAL = new BigInteger("1234567890");
|
|
static final Date NOT_BEFORE = new Date(1511799590);
|
|
static final Date NOT_AFTER = new Date(1511899590);
|
|
static final Date KEY_VALIDITY_START = new Date(1511799591);
|
|
static final Date KEY_VALIDITY_FOR_ORIG_END = new Date(1511799593);
|
|
static final Date KEY_VALIDITY_FOR_CONSUMPTION_END = new Date(1511799594);
|
|
static final String DIGEST = KeyProperties.DIGEST_SHA256;
|
|
static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1;
|
|
static final String SIGNATURE_PADDING = KeyProperties.SIGNATURE_PADDING_RSA_PSS;
|
|
static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
|
|
static final int USER_AUTHENTICATION_DURATION = 300;
|
|
static final byte[] ATTESTATION_CHALLENGE = new byte[] {'c', 'h'};
|
|
|
|
public static KeyGenParameterSpec configureDefaultSpec() {
|
|
return new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
|
|
.setUid(UID)
|
|
.setKeySize(KEYSIZE)
|
|
.setCertificateSubject(SUBJECT)
|
|
.setCertificateSerialNumber(SERIAL)
|
|
.setCertificateNotBefore(NOT_BEFORE)
|
|
.setCertificateNotAfter(NOT_AFTER)
|
|
.setKeyValidityStart(KEY_VALIDITY_START)
|
|
.setKeyValidityForOriginationEnd(KEY_VALIDITY_FOR_ORIG_END)
|
|
.setKeyValidityForConsumptionEnd(KEY_VALIDITY_FOR_CONSUMPTION_END)
|
|
.setDigests(DIGEST)
|
|
.setEncryptionPaddings(ENCRYPTION_PADDING)
|
|
.setSignaturePaddings(SIGNATURE_PADDING)
|
|
.setBlockModes(BLOCK_MODE)
|
|
.setRandomizedEncryptionRequired(true)
|
|
.setUserAuthenticationRequired(true)
|
|
.setUserAuthenticationValidityDurationSeconds(USER_AUTHENTICATION_DURATION)
|
|
.setAttestationChallenge(ATTESTATION_CHALLENGE)
|
|
.setUniqueIdIncluded(true)
|
|
.setUserAuthenticationValidWhileOnBody(true)
|
|
.setInvalidatedByBiometricEnrollment(true)
|
|
.setIsStrongBoxBacked(true)
|
|
.setUserConfirmationRequired(true)
|
|
.setUnlockedDeviceRequired(true)
|
|
.setCriticalToDeviceEncryption(true)
|
|
.build();
|
|
}
|
|
|
|
public static void validateSpecValues(KeyGenParameterSpec spec, int uid, String alias) {
|
|
assertThat(spec.getKeystoreAlias(), is(alias));
|
|
assertThat(spec.getPurposes(), is(KEY_PURPOSES));
|
|
assertThat(spec.getUid(), is(uid));
|
|
assertThat(spec.getKeySize(), is(KEYSIZE));
|
|
assertThat(spec.getCertificateSubject(), is(SUBJECT));
|
|
assertThat(spec.getCertificateSerialNumber(), is(SERIAL));
|
|
assertThat(spec.getCertificateNotBefore(), is(NOT_BEFORE));
|
|
assertThat(spec.getCertificateNotAfter(), is(NOT_AFTER));
|
|
assertThat(spec.getKeyValidityStart(), is(KEY_VALIDITY_START));
|
|
assertThat(spec.getKeyValidityForOriginationEnd(), is(KEY_VALIDITY_FOR_ORIG_END));
|
|
assertThat(spec.getKeyValidityForConsumptionEnd(), is(KEY_VALIDITY_FOR_CONSUMPTION_END));
|
|
assertThat(spec.getDigests(), is(new String[] {DIGEST}));
|
|
assertThat(spec.getEncryptionPaddings(), is(new String[] {ENCRYPTION_PADDING}));
|
|
assertThat(spec.getSignaturePaddings(), is(new String[] {SIGNATURE_PADDING}));
|
|
assertThat(spec.getBlockModes(), is(new String[] {BLOCK_MODE}));
|
|
assertThat(spec.isRandomizedEncryptionRequired(), is(true));
|
|
assertThat(spec.isUserAuthenticationRequired(), is(true));
|
|
assertThat(
|
|
spec.getUserAuthenticationValidityDurationSeconds(),
|
|
is(USER_AUTHENTICATION_DURATION));
|
|
assertThat(spec.getAttestationChallenge(), is(ATTESTATION_CHALLENGE));
|
|
assertThat(spec.isUniqueIdIncluded(), is(true));
|
|
assertThat(spec.isUserAuthenticationValidWhileOnBody(), is(true));
|
|
assertThat(spec.isInvalidatedByBiometricEnrollment(), is(true));
|
|
assertThat(spec.isStrongBoxBacked(), is(true));
|
|
assertThat(spec.isUserConfirmationRequired(), is(true));
|
|
assertThat(spec.isUnlockedDeviceRequired(), is(true));
|
|
assertThat(spec.isCriticalToDeviceEncryption(), is(true));
|
|
}
|
|
|
|
private Parcel parcelForReading(ParcelableKeyGenParameterSpec spec) {
|
|
Parcel parcel = Parcel.obtain();
|
|
spec.writeToParcel(parcel, spec.describeContents());
|
|
|
|
parcel.setDataPosition(0);
|
|
return parcel;
|
|
}
|
|
|
|
@Test
|
|
public void testParcelingWithAllValues() {
|
|
ParcelableKeyGenParameterSpec spec =
|
|
new ParcelableKeyGenParameterSpec(configureDefaultSpec());
|
|
Parcel parcel = parcelForReading(spec);
|
|
ParcelableKeyGenParameterSpec fromParcel =
|
|
ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel);
|
|
validateSpecValues(fromParcel.getSpec(), UID, ALIAS);
|
|
assertThat(parcel.dataAvail(), is(0));
|
|
}
|
|
|
|
@Test
|
|
public void testParcelingWithNullValues() {
|
|
ParcelableKeyGenParameterSpec spec = new ParcelableKeyGenParameterSpec(
|
|
new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES).build());
|
|
|
|
Parcel parcel = parcelForReading(spec);
|
|
KeyGenParameterSpec fromParcel = ParcelableKeyGenParameterSpec.CREATOR
|
|
.createFromParcel(parcel)
|
|
.getSpec();
|
|
assertThat(fromParcel.getKeystoreAlias(), is(ALIAS));
|
|
assertThat(fromParcel.getPurposes(), is(KEY_PURPOSES));
|
|
assertThat(fromParcel.getCertificateNotBefore(), is(new Date(0L)));
|
|
assertThat(fromParcel.getCertificateNotAfter(), is(new Date(2461449600000L)));
|
|
assertThat(parcel.dataAvail(), is(0));
|
|
}
|
|
|
|
@Test
|
|
public void testParcelingRSAAlgoParameter() {
|
|
RSAKeyGenParameterSpec rsaSpec =
|
|
new RSAKeyGenParameterSpec(2048, new BigInteger("5231123"));
|
|
ParcelableKeyGenParameterSpec spec = new ParcelableKeyGenParameterSpec(
|
|
new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
|
|
.setAlgorithmParameterSpec(rsaSpec)
|
|
.build());
|
|
|
|
Parcel parcel = parcelForReading(spec);
|
|
KeyGenParameterSpec fromParcel =
|
|
ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel).getSpec();
|
|
RSAKeyGenParameterSpec parcelSpec =
|
|
(RSAKeyGenParameterSpec) fromParcel.getAlgorithmParameterSpec();
|
|
// Compare individual fields as RSAKeyGenParameterSpec, on android, does not
|
|
// implement equals()
|
|
assertEquals(parcelSpec.getKeysize(), rsaSpec.getKeysize());
|
|
assertEquals(parcelSpec.getPublicExponent(), rsaSpec.getPublicExponent());
|
|
}
|
|
|
|
@Test
|
|
public void testParcelingECAlgoParameter() {
|
|
ECGenParameterSpec ecSpec = new ECGenParameterSpec("P-256");
|
|
ParcelableKeyGenParameterSpec spec = new ParcelableKeyGenParameterSpec(
|
|
new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
|
|
.setAlgorithmParameterSpec(ecSpec)
|
|
.build());
|
|
Parcel parcel = parcelForReading(spec);
|
|
KeyGenParameterSpec fromParcel =
|
|
ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel).getSpec();
|
|
// Compare individual fields as ECGenParameterSpec, on android, does not
|
|
// implement equals()
|
|
ECGenParameterSpec parcelSpec = (ECGenParameterSpec) fromParcel.getAlgorithmParameterSpec();
|
|
assertEquals(parcelSpec.getName(), ecSpec.getName());
|
|
}
|
|
}
|