1ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin/* 28effa36ca6440604cf10bbc34fba2b60ff304f54Alex Klyubin * Copyright (C) 2015 The Android Open Source Project 345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * 445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * Licensed under the Apache License, Version 2.0 (the "License"); 545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * you may not use this file except in compliance with the License. 645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * You may obtain a copy of the License at 745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * 88effa36ca6440604cf10bbc34fba2b60ff304f54Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * 1045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * Unless required by applicable law or agreed to in writing, software 1145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * distributed under the License is distributed on an "AS IS" BASIS, 1245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * See the License for the specific language governing permissions and 1445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * limitations under the License. 1545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker */ 1645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 1745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerpackage android.security.keymaster; 1845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 1945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerimport android.os.Parcel; 2045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerimport android.os.Parcelable; 2145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 22ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubinimport java.math.BigInteger; 2345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerimport java.util.ArrayList; 2445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerimport java.util.Date; 2545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerimport java.util.List; 2645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 2745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker/** 2845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * Utility class for the java side of user specified Keymaster arguments. 2945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * <p> 3045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * Serialization code for this and subclasses must be kept in sync with system/security/keystore 3145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker * @hide 3245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker */ 3345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubakerpublic class KeymasterArguments implements Parcelable { 34ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 35ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private static final long UINT32_RANGE = 1L << 32; 36ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public static final long UINT32_MAX_VALUE = UINT32_RANGE - 1; 37ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 38ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private static final BigInteger UINT64_RANGE = BigInteger.ONE.shiftLeft(64); 39ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public static final BigInteger UINT64_MAX_VALUE = UINT64_RANGE.subtract(BigInteger.ONE); 40ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 41ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private List<KeymasterArgument> mArguments; 4245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 4345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public static final Parcelable.Creator<KeymasterArguments> CREATOR = new 4445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker Parcelable.Creator<KeymasterArguments>() { 455927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin @Override 4645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public KeymasterArguments createFromParcel(Parcel in) { 4745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return new KeymasterArguments(in); 4845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 495927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin 505927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin @Override 5145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public KeymasterArguments[] newArray(int size) { 5245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return new KeymasterArguments[size]; 5345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 5445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker }; 5545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 5645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public KeymasterArguments() { 5745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker mArguments = new ArrayList<KeymasterArgument>(); 5845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 5945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 6045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker private KeymasterArguments(Parcel in) { 6145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker mArguments = in.createTypedArrayList(KeymasterArgument.CREATOR); 6245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 6345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 64ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 65ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds an enum tag with the provided value. 66ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 67ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not an enum tag. 68ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 69ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addEnum(int tag, int value) { 70ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin int tagType = KeymasterDefs.getTagType(tag); 71ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if ((tagType != KeymasterDefs.KM_ENUM) && (tagType != KeymasterDefs.KM_ENUM_REP)) { 72ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not an enum or repeating enum tag: " + tag); 73ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 74ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin addEnumTag(tag, value); 7545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 7645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 77ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 78ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds a repeated enum tag with the provided values. 79ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 80ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a repeating enum tag. 81ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 82ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addEnums(int tag, int... values) { 83ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM_REP) { 84ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a repeating enum tag: " + tag); 85ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 865927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin for (int value : values) { 87ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin addEnumTag(tag, value); 885927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin } 895927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin } 905927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin 91ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 92ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns the value of the specified enum tag or {@code defaultValue} if the tag is not 93ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * present. 94ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 95ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not an enum tag. 96ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 97ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public int getEnum(int tag, int defaultValue) { 98ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM) { 99ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not an enum tag: " + tag); 100b543b393549ccb2f1aa2cf3a198811fafbc309ebChad Brubaker } 101ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin KeymasterArgument arg = getArgumentByTag(tag); 102ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (arg == null) { 103ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return defaultValue; 104ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 105ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return getEnumTagValue(arg); 106b543b393549ccb2f1aa2cf3a198811fafbc309ebChad Brubaker } 107b543b393549ccb2f1aa2cf3a198811fafbc309ebChad Brubaker 108ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 109ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns all values of the specified repeating enum tag. 110ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 111ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * throws IllegalArgumentException if {@code tag} is not a repeating enum tag. 112ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 113ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public List<Integer> getEnums(int tag) { 114ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ENUM_REP) { 115ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a repeating enum tag: " + tag); 116ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 117ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin List<Integer> values = new ArrayList<Integer>(); 118ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin for (KeymasterArgument arg : mArguments) { 119ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (arg.tag == tag) { 120ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin values.add(getEnumTagValue(arg)); 121ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 122ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 123ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return values; 12445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 12545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 126ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private void addEnumTag(int tag, int value) { 127ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterIntArgument(tag, value)); 12845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 12945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 130ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private int getEnumTagValue(KeymasterArgument arg) { 131ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return ((KeymasterIntArgument) arg).value; 13245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 13345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 134ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 135ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds an unsigned 32-bit int tag with the provided value. 136ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 137ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag or if 138ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * {@code value} is outside of the permitted range [0; 2^32). 139ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 140ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addUnsignedInt(int tag, long value) { 141ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin int tagType = KeymasterDefs.getTagType(tag); 1423e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin if ((tagType != KeymasterDefs.KM_UINT) && (tagType != KeymasterDefs.KM_UINT_REP)) { 143ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not an int or repeating int tag: " + tag); 144ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 1453e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin // Keymaster's KM_UINT is unsigned 32 bit. 146ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if ((value < 0) || (value > UINT32_MAX_VALUE)) { 147ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Int tag value out of range: " + value); 148ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 149ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterIntArgument(tag, (int) value)); 15045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 15145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 152ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 153ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns the value of the specified unsigned 32-bit int tag or {@code defaultValue} if the tag 154ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * is not present. 155ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 156ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not an unsigned 32-bit int tag. 157ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 158ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public long getUnsignedInt(int tag, long defaultValue) { 1593e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_UINT) { 160ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not an int tag: " + tag); 161ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 162ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin KeymasterArgument arg = getArgumentByTag(tag); 163ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (arg == null) { 164ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return defaultValue; 165d6c7799b9a8b00d160a1d2d32c7326132cbc7b7bAlex Klyubin } 1663e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin // Keymaster's KM_UINT is unsigned 32 bit. 167ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return ((KeymasterIntArgument) arg).value & 0xffffffffL; 168d6c7799b9a8b00d160a1d2d32c7326132cbc7b7bAlex Klyubin } 169d6c7799b9a8b00d160a1d2d32c7326132cbc7b7bAlex Klyubin 170ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 171ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds an unsigned 64-bit long tag with the provided value. 172ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 173ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not an unsigned 64-bit long tag or if 174ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * {@code value} is outside of the permitted range [0; 2^64). 175ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 176ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addUnsignedLong(int tag, BigInteger value) { 177ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin int tagType = KeymasterDefs.getTagType(tag); 1783e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin if ((tagType != KeymasterDefs.KM_ULONG) && (tagType != KeymasterDefs.KM_ULONG_REP)) { 179ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a long or repeating long tag: " + tag); 180ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 181ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin addLongTag(tag, value); 182ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 183ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 184ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 185ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns all values of the specified repeating unsigned 64-bit long tag. 186ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 187ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a repeating unsigned 64-bit long tag. 188ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 189ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public List<BigInteger> getUnsignedLongs(int tag) { 1903e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_ULONG_REP) { 191ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Tag is not a repeating long: " + tag); 192ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 193ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin List<BigInteger> values = new ArrayList<BigInteger>(); 19445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker for (KeymasterArgument arg : mArguments) { 19545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (arg.tag == tag) { 196ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin values.add(getLongTagValue(arg)); 19745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 19845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 199ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return values; 20045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 20145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 202ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private void addLongTag(int tag, BigInteger value) { 2033e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin // Keymaster's KM_ULONG is unsigned 64 bit. 204ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if ((value.signum() == -1) || (value.compareTo(UINT64_MAX_VALUE) > 0)) { 205ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Long tag value out of range: " + value); 206ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 207ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterLongArgument(tag, value.longValue())); 208ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 209ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 210ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private BigInteger getLongTagValue(KeymasterArgument arg) { 2113e7a9e4ec611a1306f8aa5e593c95237030bb5baAlex Klyubin // Keymaster's KM_ULONG is unsigned 64 bit. We're forced to use BigInteger for type safety 212ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin // because there's no unsigned long type. 213ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return toUint64(((KeymasterLongArgument) arg).value); 214ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 215ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 216ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 217ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds the provided boolean tag. Boolean tags are considered to be set to {@code true} if 218ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * present and {@code false} if absent. 219ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 220ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a boolean tag. 221ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 222ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addBoolean(int tag) { 223ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) { 224ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a boolean tag: " + tag); 225ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 226ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterBooleanArgument(tag)); 22745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 22845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 229ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 230ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns {@code true} if the provided boolean tag is present, {@code false} if absent. 231ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 232ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a boolean tag. 233ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 234ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public boolean getBoolean(int tag) { 235ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) { 236ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a boolean tag: " + tag); 23745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 23845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker KeymasterArgument arg = getArgumentByTag(tag); 23945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (arg == null) { 240ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return false; 24145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 242ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return true; 24345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 24445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 245ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 246ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds a bytes tag with the provided value. 247ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 248ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a bytes tag. 249ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 250ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addBytes(int tag, byte[] value) { 251ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) { 252ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a bytes tag: " + tag); 253ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 254ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (value == null) { 255ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new NullPointerException("value == nulll"); 256ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 257ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterBlobArgument(tag, value)); 258ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 259ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 260ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 261ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns the value of the specified bytes tag or {@code defaultValue} if the tag is not 262ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * present. 263ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 264ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a bytes tag. 265ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 266ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public byte[] getBytes(int tag, byte[] defaultValue) { 267ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) { 268ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a bytes tag: " + tag); 26945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 27045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker KeymasterArgument arg = getArgumentByTag(tag); 27145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (arg == null) { 27245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return defaultValue; 27345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 274ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return ((KeymasterBlobArgument) arg).blob; 27545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 27645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 277ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 278ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds a date tag with the provided value. 279ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 280ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a date tag or if {@code value} is 281ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * before the start of Unix epoch. 282ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 283ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addDate(int tag, Date value) { 28445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) { 285ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a date tag: " + tag); 28645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 287ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (value == null) { 288ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new NullPointerException("value == nulll"); 289ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 290ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin // Keymaster's KM_DATE is unsigned, but java.util.Date is signed, thus preventing us from 291ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin // using values larger than 2^63 - 1. 292ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (value.getTime() < 0) { 293ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Date tag value out of range: " + value); 29445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 295ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin mArguments.add(new KeymasterDateArgument(tag, value)); 29645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 29745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 298ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 299ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Adds a date tag with the provided value, if the value is not {@code null}. Does nothing if 300ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * the {@code value} is null. 301ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 302ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a date tag or if {@code value} is 303ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * before the start of Unix epoch. 304ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 305ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public void addDateIfNotNull(int tag, Date value) { 306ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) { 307ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Not a date tag: " + tag); 30845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 309ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (value != null) { 310ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin addDate(tag, value); 31145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 31245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 31345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 314ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 315ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Returns the value of the specified date tag or {@code defaultValue} if the tag is not 316ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * present. 317ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * 318ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * @throws IllegalArgumentException if {@code tag} is not a date tag or if the tag's value 319ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * represents a time instant which is after {@code 2^63 - 1} milliseconds since Unix 320ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * epoch. 321ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 322ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public Date getDate(int tag, Date defaultValue) { 323ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) { 324ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Tag is not a date type: " + tag); 32545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 32645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker KeymasterArgument arg = getArgumentByTag(tag); 32745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (arg == null) { 32845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return defaultValue; 32945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 330ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin Date result = ((KeymasterDateArgument) arg).date; 331ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin // Keymaster's KM_DATE is unsigned, but java.util.Date is signed, thus preventing us from 332ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin // using values larger than 2^63 - 1. 333ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (result.getTime() < 0) { 334ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new IllegalArgumentException("Tag value too large. Tag: " + tag); 335ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 336ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return result; 33745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 33845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 339ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin private KeymasterArgument getArgumentByTag(int tag) { 34045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker for (KeymasterArgument arg : mArguments) { 34145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker if (arg.tag == tag) { 342ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return arg; 34345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 34445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 345ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return null; 34645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 34745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 348ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public boolean containsTag(int tag) { 349ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return getArgumentByTag(tag) != null; 350b543b393549ccb2f1aa2cf3a198811fafbc309ebChad Brubaker } 351b543b393549ccb2f1aa2cf3a198811fafbc309ebChad Brubaker 35245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public int size() { 35345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return mArguments.size(); 35445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 35545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 35645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker @Override 35745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public void writeToParcel(Parcel out, int flags) { 35845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker out.writeTypedList(mArguments); 35945ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 36045ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 36145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public void readFromParcel(Parcel in) { 36245ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker in.readTypedList(mArguments, KeymasterArgument.CREATOR); 36345ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 36445ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker 36545ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker @Override 36645ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker public int describeContents() { 36745ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker return 0; 36845ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker } 369ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin 370ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin /** 371ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * Converts the provided value to non-negative {@link BigInteger}, treating the sign bit of the 372ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin * provided value as the most significant bit of the result. 373ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin */ 374ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin public static BigInteger toUint64(long value) { 375ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (value >= 0) { 376ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return BigInteger.valueOf(value); 377ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } else { 378ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin return BigInteger.valueOf(value).add(UINT64_RANGE); 379ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 380ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 38145ff13ea28005b5af0caa80dbdeb09d49bd73fafChad Brubaker} 382