Merge "Keymaster INT, LONG and DATE tag values are unsigned." into mnc-dev
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2015, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -19,6 +19,7 @@ package android.security.keymaster;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -30,8 +31,8 @@ public class KeyCharacteristics implements Parcelable {
|
||||
public KeymasterArguments swEnforced;
|
||||
public KeymasterArguments hwEnforced;
|
||||
|
||||
public static final Parcelable.Creator<KeyCharacteristics> CREATOR = new
|
||||
Parcelable.Creator<KeyCharacteristics>() {
|
||||
public static final Parcelable.Creator<KeyCharacteristics> CREATOR =
|
||||
new Parcelable.Creator<KeyCharacteristics>() {
|
||||
@Override
|
||||
public KeyCharacteristics createFromParcel(Parcel in) {
|
||||
return new KeyCharacteristics(in);
|
||||
@@ -65,73 +66,85 @@ public class KeyCharacteristics implements Parcelable {
|
||||
hwEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
public Integer getInteger(int tag) {
|
||||
/**
|
||||
* Returns the value of the specified enum tag or {@code defaultValue} if the tag is not
|
||||
* present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an enum tag.
|
||||
*/
|
||||
public Integer getEnum(int tag) {
|
||||
if (hwEnforced.containsTag(tag)) {
|
||||
return hwEnforced.getInt(tag, -1);
|
||||
return hwEnforced.getEnum(tag, -1);
|
||||
} else if (swEnforced.containsTag(tag)) {
|
||||
return swEnforced.getInt(tag, -1);
|
||||
return swEnforced.getEnum(tag, -1);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt(int tag, int defaultValue) {
|
||||
Integer result = getInteger(tag);
|
||||
return (result != null) ? result : defaultValue;
|
||||
}
|
||||
|
||||
public List<Integer> getInts(int tag) {
|
||||
/**
|
||||
* Returns all values of the specified repeating enum tag.
|
||||
*
|
||||
* throws IllegalArgumentException if {@code tag} is not a repeating enum tag.
|
||||
*/
|
||||
public List<Integer> getEnums(int tag) {
|
||||
List<Integer> result = new ArrayList<Integer>();
|
||||
result.addAll(hwEnforced.getInts(tag));
|
||||
result.addAll(swEnforced.getInts(tag));
|
||||
result.addAll(hwEnforced.getEnums(tag));
|
||||
result.addAll(swEnforced.getEnums(tag));
|
||||
return result;
|
||||
}
|
||||
|
||||
public Long getLong(int tag) {
|
||||
/**
|
||||
* Returns the value of the specified unsigned 32-bit int tag or {@code defaultValue} if the tag
|
||||
* is not present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag.
|
||||
*/
|
||||
public long getUnsignedInt(int tag, long defaultValue) {
|
||||
if (hwEnforced.containsTag(tag)) {
|
||||
return hwEnforced.getLong(tag, -1);
|
||||
} else if (swEnforced.containsTag(tag)) {
|
||||
return swEnforced.getLong(tag, -1);
|
||||
return hwEnforced.getUnsignedInt(tag, defaultValue);
|
||||
} else {
|
||||
return null;
|
||||
return swEnforced.getUnsignedInt(tag, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public long getLong(int tag, long defaultValue) {
|
||||
Long result = getLong(tag);
|
||||
return (result != null) ? result : defaultValue;
|
||||
}
|
||||
|
||||
public List<Long> getLongs(int tag) {
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
result.addAll(hwEnforced.getLongs(tag));
|
||||
result.addAll(swEnforced.getLongs(tag));
|
||||
/**
|
||||
* Returns all values of the specified repeating unsigned 64-bit long tag.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a repeating unsigned 64-bit long tag.
|
||||
*/
|
||||
public List<BigInteger> getUnsignedLongs(int tag) {
|
||||
List<BigInteger> result = new ArrayList<BigInteger>();
|
||||
result.addAll(hwEnforced.getUnsignedLongs(tag));
|
||||
result.addAll(swEnforced.getUnsignedLongs(tag));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified date tag or {@code null} if the tag is not present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a date tag or if the tag's value
|
||||
* represents a time instant which is after {@code 2^63 - 1} milliseconds since Unix
|
||||
* epoch.
|
||||
*/
|
||||
public Date getDate(int tag) {
|
||||
Date result = hwEnforced.getDate(tag, null);
|
||||
if (result == null) {
|
||||
result = swEnforced.getDate(tag, null);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Date getDate(int tag, Date defaultValue) {
|
||||
if (hwEnforced.containsTag(tag)) {
|
||||
return hwEnforced.getDate(tag, null);
|
||||
} else if (hwEnforced.containsTag(tag)) {
|
||||
return swEnforced.getDate(tag, null);
|
||||
} else {
|
||||
return defaultValue;
|
||||
Date result = swEnforced.getDate(tag, null);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return hwEnforced.getDate(tag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided boolean tag is present, {@code false} if absent.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a boolean tag.
|
||||
*/
|
||||
public boolean getBoolean(int tag) {
|
||||
if (hwEnforced.containsTag(tag)) {
|
||||
return hwEnforced.getBoolean(tag, false);
|
||||
return hwEnforced.getBoolean(tag);
|
||||
} else {
|
||||
return swEnforced.getBoolean(tag, false);
|
||||
return swEnforced.getBoolean(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ abstract class KeymasterArgument implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<KeymasterArgument> CREATOR = new
|
||||
Parcelable.Creator<KeymasterArgument>() {
|
||||
@Override
|
||||
public KeymasterArgument createFromParcel(Parcel in) {
|
||||
final int pos = in.dataPosition();
|
||||
final int tag = in.readInt();
|
||||
@@ -55,6 +56,8 @@ abstract class KeymasterArgument implements Parcelable {
|
||||
throw new ParcelFormatException("Bad tag: " + tag + " at " + pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeymasterArgument[] newArray(int size) {
|
||||
return new KeymasterArgument[size];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2015, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -19,6 +19,7 @@ package android.security.keymaster;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -30,7 +31,14 @@ import java.util.List;
|
||||
* @hide
|
||||
*/
|
||||
public class KeymasterArguments implements Parcelable {
|
||||
List<KeymasterArgument> mArguments;
|
||||
|
||||
private static final long UINT32_RANGE = 1L << 32;
|
||||
public static final long UINT32_MAX_VALUE = UINT32_RANGE - 1;
|
||||
|
||||
private static final BigInteger UINT64_RANGE = BigInteger.ONE.shiftLeft(64);
|
||||
public static final BigInteger UINT64_MAX_VALUE = UINT64_RANGE.subtract(BigInteger.ONE);
|
||||
|
||||
private List<KeymasterArgument> mArguments;
|
||||
|
||||
public static final Parcelable.Creator<KeymasterArguments> CREATOR = new
|
||||
Parcelable.Creator<KeymasterArguments>() {
|
||||
@@ -53,42 +61,279 @@ public class KeymasterArguments implements Parcelable {
|
||||
mArguments = in.createTypedArrayList(KeymasterArgument.CREATOR);
|
||||
}
|
||||
|
||||
public void addInt(int tag, int value) {
|
||||
/**
|
||||
* Adds an enum tag with the provided value.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an enum tag.
|
||||
*/
|
||||
public void addEnum(int tag, int value) {
|
||||
int tagType = KeymasterDefs.getTagType(tag);
|
||||
if ((tagType != KeymasterDefs.KM_ENUM) && (tagType != KeymasterDefs.KM_ENUM_REP)) {
|
||||
throw new IllegalArgumentException("Not an enum or repeating enum tag: " + tag);
|
||||
}
|
||||
addEnumTag(tag, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a repeated enum tag with the provided values.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a repeating enum tag.
|
||||
*/
|
||||
public void addEnums(int tag, int... values) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM_REP) {
|
||||
throw new IllegalArgumentException("Not a repeating enum tag: " + tag);
|
||||
}
|
||||
for (int value : values) {
|
||||
addEnumTag(tag, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified enum tag or {@code defaultValue} if the tag is not
|
||||
* present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an enum tag.
|
||||
*/
|
||||
public int getEnum(int tag, int defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM) {
|
||||
throw new IllegalArgumentException("Not an enum tag: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return getEnumTagValue(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all values of the specified repeating enum tag.
|
||||
*
|
||||
* throws IllegalArgumentException if {@code tag} is not a repeating enum tag.
|
||||
*/
|
||||
public List<Integer> getEnums(int tag) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM_REP) {
|
||||
throw new IllegalArgumentException("Not a repeating enum tag: " + tag);
|
||||
}
|
||||
List<Integer> values = new ArrayList<Integer>();
|
||||
for (KeymasterArgument arg : mArguments) {
|
||||
if (arg.tag == tag) {
|
||||
values.add(getEnumTagValue(arg));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private void addEnumTag(int tag, int value) {
|
||||
mArguments.add(new KeymasterIntArgument(tag, value));
|
||||
}
|
||||
|
||||
public void addInts(int tag, int... values) {
|
||||
for (int value : values) {
|
||||
addInt(tag, value);
|
||||
}
|
||||
private int getEnumTagValue(KeymasterArgument arg) {
|
||||
return ((KeymasterIntArgument) arg).value;
|
||||
}
|
||||
|
||||
public void addLongs(int tag, long... values) {
|
||||
for (long value : values) {
|
||||
addLong(tag, value);
|
||||
/**
|
||||
* Adds an unsigned 32-bit int tag with the provided value.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag or if
|
||||
* {@code value} is outside of the permitted range [0; 2^32).
|
||||
*/
|
||||
public void addUnsignedInt(int tag, long value) {
|
||||
int tagType = KeymasterDefs.getTagType(tag);
|
||||
if ((tagType != KeymasterDefs.KM_INT) && (tagType != KeymasterDefs.KM_INT_REP)) {
|
||||
throw new IllegalArgumentException("Not an int or repeating int tag: " + tag);
|
||||
}
|
||||
// Keymaster's KM_INT is unsigned 32 bit.
|
||||
if ((value < 0) || (value > UINT32_MAX_VALUE)) {
|
||||
throw new IllegalArgumentException("Int tag value out of range: " + value);
|
||||
}
|
||||
mArguments.add(new KeymasterIntArgument(tag, (int) value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified unsigned 32-bit int tag or {@code defaultValue} if the tag
|
||||
* is not present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag.
|
||||
*/
|
||||
public long getUnsignedInt(int tag, long defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_INT) {
|
||||
throw new IllegalArgumentException("Not an int tag: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
// Keymaster's KM_INT is unsigned 32 bit.
|
||||
return ((KeymasterIntArgument) arg).value & 0xffffffffL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an unsigned 64-bit long tag with the provided value.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not an unsigned 64-bit long tag or if
|
||||
* {@code value} is outside of the permitted range [0; 2^64).
|
||||
*/
|
||||
public void addUnsignedLong(int tag, BigInteger value) {
|
||||
int tagType = KeymasterDefs.getTagType(tag);
|
||||
if ((tagType != KeymasterDefs.KM_LONG) && (tagType != KeymasterDefs.KM_LONG_REP)) {
|
||||
throw new IllegalArgumentException("Not a long or repeating long tag: " + tag);
|
||||
}
|
||||
addLongTag(tag, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all values of the specified repeating unsigned 64-bit long tag.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a repeating unsigned 64-bit long tag.
|
||||
*/
|
||||
public List<BigInteger> getUnsignedLongs(int tag) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_LONG_REP) {
|
||||
throw new IllegalArgumentException("Tag is not a repeating long: " + tag);
|
||||
}
|
||||
List<BigInteger> values = new ArrayList<BigInteger>();
|
||||
for (KeymasterArgument arg : mArguments) {
|
||||
if (arg.tag == tag) {
|
||||
values.add(getLongTagValue(arg));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private void addLongTag(int tag, BigInteger value) {
|
||||
// Keymaster's KM_LONG is unsigned 64 bit.
|
||||
if ((value.signum() == -1) || (value.compareTo(UINT64_MAX_VALUE) > 0)) {
|
||||
throw new IllegalArgumentException("Long tag value out of range: " + value);
|
||||
}
|
||||
mArguments.add(new KeymasterLongArgument(tag, value.longValue()));
|
||||
}
|
||||
|
||||
private BigInteger getLongTagValue(KeymasterArgument arg) {
|
||||
// Keymaster's KM_LONG is unsigned 64 bit. We're forced to use BigInteger for type safety
|
||||
// because there's no unsigned long type.
|
||||
return toUint64(((KeymasterLongArgument) arg).value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided boolean tag. Boolean tags are considered to be set to {@code true} if
|
||||
* present and {@code false} if absent.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a boolean tag.
|
||||
*/
|
||||
public void addBoolean(int tag) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) {
|
||||
throw new IllegalArgumentException("Not a boolean tag: " + tag);
|
||||
}
|
||||
mArguments.add(new KeymasterBooleanArgument(tag));
|
||||
}
|
||||
|
||||
public void addLong(int tag, long value) {
|
||||
mArguments.add(new KeymasterLongArgument(tag, value));
|
||||
/**
|
||||
* Returns {@code true} if the provided boolean tag is present, {@code false} if absent.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a boolean tag.
|
||||
*/
|
||||
public boolean getBoolean(int tag) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) {
|
||||
throw new IllegalArgumentException("Not a boolean tag: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addBlob(int tag, byte[] value) {
|
||||
/**
|
||||
* Adds a bytes tag with the provided value.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a bytes tag.
|
||||
*/
|
||||
public void addBytes(int tag, byte[] value) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) {
|
||||
throw new IllegalArgumentException("Not a bytes tag: " + tag);
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value == nulll");
|
||||
}
|
||||
mArguments.add(new KeymasterBlobArgument(tag, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified bytes tag or {@code defaultValue} if the tag is not
|
||||
* present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a bytes tag.
|
||||
*/
|
||||
public byte[] getBytes(int tag, byte[] defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) {
|
||||
throw new IllegalArgumentException("Not a bytes tag: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((KeymasterBlobArgument) arg).blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a date tag with the provided value.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a date tag or if {@code value} is
|
||||
* before the start of Unix epoch.
|
||||
*/
|
||||
public void addDate(int tag, Date value) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
|
||||
throw new IllegalArgumentException("Not a date tag: " + tag);
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value == nulll");
|
||||
}
|
||||
// Keymaster's KM_DATE is unsigned, but java.util.Date is signed, thus preventing us from
|
||||
// using values larger than 2^63 - 1.
|
||||
if (value.getTime() < 0) {
|
||||
throw new IllegalArgumentException("Date tag value out of range: " + value);
|
||||
}
|
||||
mArguments.add(new KeymasterDateArgument(tag, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a date tag with the provided value, if the value is not {@code null}. Does nothing if
|
||||
* the {@code value} is null.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a date tag or if {@code value} is
|
||||
* before the start of Unix epoch.
|
||||
*/
|
||||
public void addDateIfNotNull(int tag, Date value) {
|
||||
if (value != null) {
|
||||
mArguments.add(new KeymasterDateArgument(tag, value));
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
|
||||
throw new IllegalArgumentException("Not a date tag: " + tag);
|
||||
}
|
||||
if (value != null) {
|
||||
addDate(tag, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified date tag or {@code defaultValue} if the tag is not
|
||||
* present.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code tag} is not a date tag or if the tag's value
|
||||
* represents a time instant which is after {@code 2^63 - 1} milliseconds since Unix
|
||||
* epoch.
|
||||
*/
|
||||
public Date getDate(int tag, Date defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
|
||||
throw new IllegalArgumentException("Tag is not a date type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
Date result = ((KeymasterDateArgument) arg).date;
|
||||
// Keymaster's KM_DATE is unsigned, but java.util.Date is signed, thus preventing us from
|
||||
// using values larger than 2^63 - 1.
|
||||
if (result.getTime() < 0) {
|
||||
throw new IllegalArgumentException("Tag value too large. Tag: " + tag);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private KeymasterArgument getArgumentByTag(int tag) {
|
||||
@@ -104,107 +349,6 @@ public class KeymasterArguments implements Parcelable {
|
||||
return getArgumentByTag(tag) != null;
|
||||
}
|
||||
|
||||
public int getInt(int tag, int defaultValue) {
|
||||
switch (KeymasterDefs.getTagType(tag)) {
|
||||
case KeymasterDefs.KM_ENUM:
|
||||
case KeymasterDefs.KM_INT:
|
||||
break; // Accepted types
|
||||
case KeymasterDefs.KM_INT_REP:
|
||||
case KeymasterDefs.KM_ENUM_REP:
|
||||
throw new IllegalArgumentException("Repeatable tags must use getInts: " + tag);
|
||||
default:
|
||||
throw new IllegalArgumentException("Tag is not an int type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((KeymasterIntArgument) arg).value;
|
||||
}
|
||||
|
||||
public long getLong(int tag, long defaultValue) {
|
||||
switch (KeymasterDefs.getTagType(tag)) {
|
||||
case KeymasterDefs.KM_LONG:
|
||||
break; // Accepted type
|
||||
case KeymasterDefs.KM_LONG_REP:
|
||||
throw new IllegalArgumentException("Repeatable tags must use getLongs: " + tag);
|
||||
default:
|
||||
throw new IllegalArgumentException("Tag is not a long type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((KeymasterLongArgument) arg).value;
|
||||
}
|
||||
|
||||
public Date getDate(int tag, Date defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
|
||||
throw new IllegalArgumentException("Tag is not a date type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((KeymasterDateArgument) arg).date;
|
||||
}
|
||||
|
||||
public boolean getBoolean(int tag, boolean defaultValue) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) {
|
||||
throw new IllegalArgumentException("Tag is not a boolean type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] getBlob(int tag, byte[] defaultValue) {
|
||||
switch (KeymasterDefs.getTagType(tag)) {
|
||||
case KeymasterDefs.KM_BYTES:
|
||||
case KeymasterDefs.KM_BIGNUM:
|
||||
break; // Allowed types.
|
||||
default:
|
||||
throw new IllegalArgumentException("Tag is not a blob type: " + tag);
|
||||
}
|
||||
KeymasterArgument arg = getArgumentByTag(tag);
|
||||
if (arg == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((KeymasterBlobArgument) arg).blob;
|
||||
}
|
||||
|
||||
public List<Integer> getInts(int tag) {
|
||||
switch (KeymasterDefs.getTagType(tag)) {
|
||||
case KeymasterDefs.KM_INT_REP:
|
||||
case KeymasterDefs.KM_ENUM_REP:
|
||||
break; // Allowed types.
|
||||
default:
|
||||
throw new IllegalArgumentException("Tag is not a repeating type: " + tag);
|
||||
}
|
||||
List<Integer> values = new ArrayList<Integer>();
|
||||
for (KeymasterArgument arg : mArguments) {
|
||||
if (arg.tag == tag) {
|
||||
values.add(((KeymasterIntArgument) arg).value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public List<Long> getLongs(int tag) {
|
||||
if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_LONG_REP) {
|
||||
throw new IllegalArgumentException("Tag is not a repeating long: " + tag);
|
||||
}
|
||||
List<Long> values = new ArrayList<Long>();
|
||||
for (KeymasterArgument arg : mArguments) {
|
||||
if (arg.tag == tag) {
|
||||
values.add(((KeymasterLongArgument) arg).value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return mArguments.size();
|
||||
}
|
||||
@@ -222,4 +366,16 @@ public class KeymasterArguments implements Parcelable {
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the provided value to non-negative {@link BigInteger}, treating the sign bit of the
|
||||
* provided value as the most significant bit of the result.
|
||||
*/
|
||||
public static BigInteger toUint64(long value) {
|
||||
if (value >= 0) {
|
||||
return BigInteger.valueOf(value);
|
||||
} else {
|
||||
return BigInteger.valueOf(value).add(UINT64_RANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||
import android.security.keystore.UserNotAuthenticatedException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -663,14 +664,14 @@ public class KeyStore {
|
||||
"Failed to obtained key characteristics",
|
||||
getKeyStoreException(getKeyCharacteristicsErrorCode));
|
||||
}
|
||||
List<Long> keySids =
|
||||
keyCharacteristics.getLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
|
||||
List<BigInteger> keySids =
|
||||
keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
|
||||
if (keySids.isEmpty()) {
|
||||
// Key is not bound to any SIDs -- no amount of authentication will help here.
|
||||
return new KeyPermanentlyInvalidatedException();
|
||||
}
|
||||
long rootSid = GateKeeper.getSecureUserId();
|
||||
if ((rootSid != 0) && (keySids.contains(Long.valueOf(rootSid)))) {
|
||||
if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
|
||||
// One of the key's SIDs is the current root SID -- user can be authenticated
|
||||
// against that SID.
|
||||
return new UserNotAuthenticatedException();
|
||||
@@ -678,7 +679,7 @@ public class KeyStore {
|
||||
|
||||
long fingerprintOnlySid = getFingerprintOnlySid();
|
||||
if ((fingerprintOnlySid != 0)
|
||||
&& (keySids.contains(Long.valueOf(fingerprintOnlySid)))) {
|
||||
&& (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
|
||||
// One of the key's SIDs is the current fingerprint SID -- user can be
|
||||
// authenticated against that SID.
|
||||
return new UserNotAuthenticatedException();
|
||||
|
||||
@@ -207,7 +207,7 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
|
||||
protected final void addAlgorithmSpecificParametersToBegin(
|
||||
@NonNull KeymasterArguments keymasterArgs) {
|
||||
super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mTagLengthBits);
|
||||
keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mTagLengthBits);
|
||||
}
|
||||
|
||||
protected final int getTagLengthBits() {
|
||||
@@ -288,11 +288,11 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
|
||||
+ " practices.");
|
||||
}
|
||||
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
if (mIv != null) {
|
||||
keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
|
||||
keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
|
||||
mIvHasBeenUsed = true;
|
||||
|
||||
// NOTE: Keymaster doesn't always return an IV, even if it's used.
|
||||
byte[] returnedIv = keymasterArgs.getBlob(KeymasterDefs.KM_TAG_NONCE, null);
|
||||
byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
|
||||
if ((returnedIv != null) && (returnedIv.length == 0)) {
|
||||
returnedIv = null;
|
||||
}
|
||||
@@ -406,7 +406,7 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
|
||||
@Override
|
||||
public OperationResult update(byte[] input) {
|
||||
KeymasterArguments keymasterArgs = new KeymasterArguments();
|
||||
keymasterArgs.addBlob(KeymasterDefs.KM_TAG_ASSOCIATED_DATA, input);
|
||||
keymasterArgs.addBytes(KeymasterDefs.KM_TAG_ASSOCIATED_DATA, input);
|
||||
|
||||
// KeyStore does not reflect AAD in inputConsumed, but users of Stream rely on this
|
||||
// field. We fix this discrepancy here. KeyStore.update contract is that all of AAD
|
||||
|
||||
@@ -89,11 +89,13 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
|
||||
if (errorCode != KeyStore.NO_ERROR) {
|
||||
throw getKeyStore().getInvalidKeyException(key.getAlias(), errorCode);
|
||||
}
|
||||
int keySizeBits = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
|
||||
long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
|
||||
if (keySizeBits == -1) {
|
||||
throw new InvalidKeyException("Size of key not known");
|
||||
} else if (keySizeBits > Integer.MAX_VALUE) {
|
||||
throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
|
||||
}
|
||||
mGroupSizeBytes = (keySizeBits + 7) / 8;
|
||||
mGroupSizeBytes = (int) ((keySizeBits + 7) / 8);
|
||||
|
||||
super.initKey(key);
|
||||
}
|
||||
@@ -112,8 +114,8 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
|
||||
@Override
|
||||
protected void addAlgorithmSpecificParametersToBegin(
|
||||
@NonNull KeymasterArguments keymasterArgs) {
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_EC);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_EC);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -159,9 +159,9 @@ public abstract class AndroidKeyStoreHmacSpi extends MacSpi implements KeyStoreC
|
||||
}
|
||||
|
||||
KeymasterArguments keymasterArgs = new KeymasterArguments();
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits);
|
||||
|
||||
OperationResult opResult = mKeyStore.begin(
|
||||
mKey.getAlias(),
|
||||
|
||||
@@ -268,12 +268,12 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
|
||||
}
|
||||
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
||||
args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
|
||||
args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
|
||||
args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
|
||||
args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
spec.isUserAuthenticationRequired(),
|
||||
spec.getUserAuthenticationValidityDurationSeconds());
|
||||
|
||||
@@ -160,7 +160,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
private int[] mKeymasterSignaturePaddings;
|
||||
private int[] mKeymasterDigests;
|
||||
|
||||
private long mRSAPublicExponent;
|
||||
private BigInteger mRSAPublicExponent;
|
||||
|
||||
protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) {
|
||||
mOriginalKeymasterAlgorithm = keymasterAlgorithm;
|
||||
@@ -320,7 +320,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
mKeymasterDigests = null;
|
||||
mKeySizeBits = 0;
|
||||
mSpec = null;
|
||||
mRSAPublicExponent = -1;
|
||||
mRSAPublicExponent = null;
|
||||
mEncryptionAtRestRequired = false;
|
||||
mRng = null;
|
||||
mKeyStore = null;
|
||||
@@ -353,12 +353,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"RSA public exponent must be positive: " + publicExponent);
|
||||
}
|
||||
if (publicExponent.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
|
||||
if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported RSA public exponent: " + publicExponent
|
||||
+ ". Only exponents <= " + Long.MAX_VALUE + " supported");
|
||||
+ ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
|
||||
}
|
||||
mRSAPublicExponent = publicExponent.longValue();
|
||||
mRSAPublicExponent = publicExponent;
|
||||
break;
|
||||
}
|
||||
case KeymasterDefs.KM_ALGORITHM_EC:
|
||||
@@ -404,13 +404,13 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
}
|
||||
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
||||
args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
|
||||
args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
|
||||
args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
|
||||
args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
|
||||
args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
|
||||
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
mSpec.isUserAuthenticationRequired(),
|
||||
@@ -493,7 +493,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
|
||||
private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) {
|
||||
switch (mKeymasterAlgorithm) {
|
||||
case KeymasterDefs.KM_ALGORITHM_RSA:
|
||||
keymasterArgs.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
|
||||
keymasterArgs.addUnsignedLong(
|
||||
KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
|
||||
break;
|
||||
case KeymasterDefs.KM_ALGORITHM_EC:
|
||||
break;
|
||||
|
||||
@@ -226,8 +226,8 @@ public class AndroidKeyStoreProvider extends Provider {
|
||||
}
|
||||
final byte[] x509EncodedPublicKey = exportResult.exportData;
|
||||
|
||||
int keymasterAlgorithm = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
|
||||
if (keymasterAlgorithm == -1) {
|
||||
Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
|
||||
if (keymasterAlgorithm == null) {
|
||||
throw new UnrecoverableKeyException("Key algorithm unknown");
|
||||
}
|
||||
|
||||
@@ -277,13 +277,12 @@ public class AndroidKeyStoreProvider extends Provider {
|
||||
.initCause(KeyStore.getKeyStoreException(errorCode));
|
||||
}
|
||||
|
||||
int keymasterAlgorithm = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
|
||||
if (keymasterAlgorithm == -1) {
|
||||
Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
|
||||
if (keymasterAlgorithm == null) {
|
||||
throw new UnrecoverableKeyException("Key algorithm unknown");
|
||||
}
|
||||
|
||||
List<Integer> keymasterDigests =
|
||||
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST);
|
||||
List<Integer> keymasterDigests = keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST);
|
||||
int keymasterDigest;
|
||||
if (keymasterDigests.isEmpty()) {
|
||||
keymasterDigest = -1;
|
||||
|
||||
@@ -374,7 +374,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
||||
protected final void addAlgorithmSpecificParametersToBegin(
|
||||
KeymasterArguments keymasterArgs) {
|
||||
super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -500,11 +500,13 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
||||
if (errorCode != KeyStore.NO_ERROR) {
|
||||
throw getKeyStore().getInvalidKeyException(keystoreKey.getAlias(), errorCode);
|
||||
}
|
||||
int keySizeBits = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
|
||||
long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
|
||||
if (keySizeBits == -1) {
|
||||
throw new InvalidKeyException("Size of key not known");
|
||||
} else if (keySizeBits > Integer.MAX_VALUE) {
|
||||
throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
|
||||
}
|
||||
mModulusSizeBytes = (keySizeBits + 7) / 8;
|
||||
mModulusSizeBytes = (int) ((keySizeBits + 7) / 8);
|
||||
|
||||
setKey(keystoreKey);
|
||||
}
|
||||
@@ -527,14 +529,14 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
|
||||
@Override
|
||||
protected void addAlgorithmSpecificParametersToBegin(
|
||||
@NonNull KeymasterArguments keymasterArgs) {
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
int purposeOverride = getKeymasterPurposeOverride();
|
||||
if ((purposeOverride != -1)
|
||||
&& ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN)
|
||||
|| (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) {
|
||||
// Keymaster sign/verify requires digest to be specified. For raw sign/verify it's NONE.
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,8 +157,8 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
|
||||
@Override
|
||||
protected final void addAlgorithmSpecificParametersToBegin(
|
||||
@NonNull KeymasterArguments keymasterArgs) {
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,26 +93,29 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
|
||||
insideSecureHardware = true;
|
||||
origin = KeyProperties.Origin.fromKeymaster(
|
||||
keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1));
|
||||
keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
|
||||
} else if (keyCharacteristics.swEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
|
||||
insideSecureHardware = false;
|
||||
origin = KeyProperties.Origin.fromKeymaster(
|
||||
keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1));
|
||||
keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
|
||||
} else {
|
||||
throw new ProviderException("Key origin not available");
|
||||
}
|
||||
Integer keySizeInteger = keyCharacteristics.getInteger(KeymasterDefs.KM_TAG_KEY_SIZE);
|
||||
if (keySizeInteger == null) {
|
||||
long keySizeUnsigned =
|
||||
keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
|
||||
if (keySizeUnsigned == -1) {
|
||||
throw new ProviderException("Key size not available");
|
||||
} else if (keySizeUnsigned > Integer.MAX_VALUE) {
|
||||
throw new ProviderException("Key too large: " + keySizeUnsigned + " bits");
|
||||
}
|
||||
keySize = keySizeInteger;
|
||||
keySize = (int) keySizeUnsigned;
|
||||
purposes = KeyProperties.Purpose.allFromKeymaster(
|
||||
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PURPOSE));
|
||||
keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PURPOSE));
|
||||
|
||||
List<String> encryptionPaddingsList = new ArrayList<String>();
|
||||
List<String> signaturePaddingsList = new ArrayList<String>();
|
||||
// Keymaster stores both types of paddings in the same array -- we split it into two.
|
||||
for (int keymasterPadding : keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PADDING)) {
|
||||
for (int keymasterPadding : keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PADDING)) {
|
||||
try {
|
||||
@KeyProperties.EncryptionPaddingEnum String jcaPadding =
|
||||
KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding);
|
||||
@@ -135,13 +138,13 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]);
|
||||
|
||||
digests = KeyProperties.Digest.allFromKeymaster(
|
||||
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST));
|
||||
keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST));
|
||||
blockModes = KeyProperties.BlockMode.allFromKeymaster(
|
||||
keyCharacteristics.getInts(KeymasterDefs.KM_TAG_BLOCK_MODE));
|
||||
keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_BLOCK_MODE));
|
||||
keymasterSwEnforcedUserAuthenticators =
|
||||
keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
|
||||
keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
|
||||
keymasterHwEnforcedUserAuthenticators =
|
||||
keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
|
||||
keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ProviderException("Unsupported key characteristic", e);
|
||||
}
|
||||
@@ -153,8 +156,12 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
keyCharacteristics.getDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME);
|
||||
boolean userAuthenticationRequired =
|
||||
!keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
int userAuthenticationValidityDurationSeconds =
|
||||
keyCharacteristics.getInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
|
||||
long userAuthenticationValidityDurationSeconds =
|
||||
keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
|
||||
if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) {
|
||||
throw new ProviderException("User authentication timeout validity too long: "
|
||||
+ userAuthenticationValidityDurationSeconds + " seconds");
|
||||
}
|
||||
boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
|
||||
&& (keymasterHwEnforcedUserAuthenticators != 0)
|
||||
&& (keymasterSwEnforcedUserAuthenticators == 0);
|
||||
@@ -172,7 +179,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
|
||||
digests,
|
||||
blockModes,
|
||||
userAuthenticationRequired,
|
||||
userAuthenticationValidityDurationSeconds,
|
||||
(int) userAuthenticationValidityDurationSeconds,
|
||||
userAuthenticationRequirementEnforcedBySecureHardware);
|
||||
}
|
||||
|
||||
|
||||
@@ -398,18 +398,18 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
|
||||
importArgs = new KeymasterArguments();
|
||||
try {
|
||||
importArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM,
|
||||
importArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
|
||||
KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
|
||||
key.getAlgorithm()));
|
||||
@KeyProperties.PurposeEnum int purposes = spec.getPurposes();
|
||||
importArgs.addInts(KeymasterDefs.KM_TAG_PURPOSE,
|
||||
importArgs.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
|
||||
KeyProperties.Purpose.allToKeymaster(purposes));
|
||||
if (spec.isDigestsSpecified()) {
|
||||
importArgs.addInts(KeymasterDefs.KM_TAG_DIGEST,
|
||||
importArgs.addEnums(KeymasterDefs.KM_TAG_DIGEST,
|
||||
KeyProperties.Digest.allToKeymaster(spec.getDigests()));
|
||||
}
|
||||
|
||||
importArgs.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE,
|
||||
importArgs.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE,
|
||||
KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()));
|
||||
int[] keymasterEncryptionPaddings =
|
||||
KeyProperties.EncryptionPadding.allToKeymaster(
|
||||
@@ -429,8 +429,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
}
|
||||
}
|
||||
}
|
||||
importArgs.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
|
||||
importArgs.addInts(KeymasterDefs.KM_TAG_PADDING,
|
||||
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
|
||||
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
|
||||
KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
|
||||
KeymasterUtils.addUserAuthArgs(importArgs,
|
||||
spec.isUserAuthenticationRequired(),
|
||||
@@ -567,7 +567,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
|
||||
|
||||
int[] keymasterDigests;
|
||||
if (params.isDigestsSpecified()) {
|
||||
@@ -606,7 +606,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
keymasterDigests = EmptyArray.INT;
|
||||
}
|
||||
}
|
||||
args.addInts(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
|
||||
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
|
||||
if (keymasterDigests.length == 0) {
|
||||
throw new KeyStoreException("At least one digest algorithm must be specified"
|
||||
@@ -630,14 +630,14 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
}
|
||||
}
|
||||
}
|
||||
args.addInts(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
|
||||
args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
|
||||
if (params.getSignaturePaddings().length > 0) {
|
||||
throw new KeyStoreException("Signature paddings not supported for symmetric keys");
|
||||
}
|
||||
int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
|
||||
params.getEncryptionPaddings());
|
||||
args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
|
||||
KeymasterUtils.addUserAuthArgs(args,
|
||||
params.isUserAuthenticationRequired(),
|
||||
params.getUserAuthenticationValidityDurationSeconds());
|
||||
|
||||
@@ -240,11 +240,11 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
|
||||
+ " practices.");
|
||||
}
|
||||
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
|
||||
keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
|
||||
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
|
||||
if ((mIvRequired) && (mIv != null)) {
|
||||
keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
|
||||
keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
|
||||
mIvHasBeenUsed = true;
|
||||
|
||||
// NOTE: Keymaster doesn't always return an IV, even if it's used.
|
||||
byte[] returnedIv = keymasterArgs.getBlob(KeymasterDefs.KM_TAG_NONCE, null);
|
||||
byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
|
||||
if ((returnedIv != null) && (returnedIv.length == 0)) {
|
||||
returnedIv = null;
|
||||
}
|
||||
|
||||
@@ -110,8 +110,9 @@ public abstract class KeymasterUtils {
|
||||
"At least one fingerprint must be enrolled to create keys requiring user"
|
||||
+ " authentication for every use");
|
||||
}
|
||||
args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, fingerprintOnlySid);
|
||||
args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
|
||||
KeymasterArguments.toUint64(fingerprintOnlySid));
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
} else {
|
||||
// The key is authorized for use for the specified amount of time after the user has
|
||||
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
|
||||
@@ -120,10 +121,11 @@ public abstract class KeymasterUtils {
|
||||
throw new IllegalStateException("Secure lock screen must be enabled"
|
||||
+ " to create keys requiring user authentication");
|
||||
}
|
||||
args.addLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, rootSid);
|
||||
args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
|
||||
KeymasterArguments.toUint64(rootSid));
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
|
||||
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
|
||||
userAuthenticationValidityDurationSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,14 +702,13 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
|
||||
private KeyCharacteristics generateRsaKey(String name) throws Exception {
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
|
||||
RSAKeyGenParameterSpec.F4.longValue());
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, RSAKeyGenParameterSpec.F4);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
int result = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
|
||||
@@ -726,14 +725,13 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
byte[] entropy = new byte[] {1,2,3,4,5};
|
||||
String name = "test";
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
|
||||
RSAKeyGenParameterSpec.F4.longValue());
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, RSAKeyGenParameterSpec.F4);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
int result = mKeyStore.generateKey(name, args, entropy, 0, outCharacteristics);
|
||||
@@ -759,16 +757,15 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
String name = "test";
|
||||
byte[] id = new byte[] {0x01, 0x02, 0x03};
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, id);
|
||||
args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
|
||||
RSAKeyGenParameterSpec.F4.longValue());
|
||||
args.addBytes(KeymasterDefs.KM_TAG_APPLICATION_ID, id);
|
||||
args.addUnsignedLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, RSAKeyGenParameterSpec.F4);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
int result = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
|
||||
@@ -795,12 +792,12 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
public void testAesGcmEncryptSuccess() throws Exception {
|
||||
String name = "test";
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
@@ -808,10 +805,10 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
|
||||
|
||||
args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 128);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 128);
|
||||
OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT,
|
||||
true, args, null);
|
||||
IBinder token = result.token;
|
||||
@@ -832,12 +829,12 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
|
||||
private int importAesKey(String name, byte[] key, int size, int mode) {
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mode);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, size);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mode);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, size);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
return mKeyStore.importKey(name, args, KeymasterDefs.KM_KEY_FORMAT_RAW, key, 0,
|
||||
new KeyCharacteristics());
|
||||
@@ -877,9 +874,9 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
hexToBytes("b6ed21b99ca6f4f9f153e7b1beafed1d"),
|
||||
hexToBytes("23304b7a39f9f3ff067d8d8f9e24ecc7")};
|
||||
KeymasterArguments beginArgs = new KeymasterArguments();
|
||||
beginArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
beginArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
beginArgs.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
beginArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
beginArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
beginArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
for (int i = 0; i < testVectors.length; i++) {
|
||||
byte[] cipherText = doOperation(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, testVectors[i],
|
||||
beginArgs);
|
||||
@@ -897,12 +894,12 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
public void testOperationPruning() throws Exception {
|
||||
String name = "test";
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
|
||||
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
@@ -910,9 +907,9 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
|
||||
|
||||
args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
|
||||
OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT,
|
||||
true, args, null);
|
||||
assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
|
||||
@@ -930,13 +927,13 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
|
||||
public void testAuthNeeded() throws Exception {
|
||||
String name = "test";
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_PKCS7);
|
||||
args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 1);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_PKCS7);
|
||||
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 1);
|
||||
|
||||
KeyCharacteristics outCharacteristics = new KeyCharacteristics();
|
||||
int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
|
||||
|
||||
Reference in New Issue
Block a user