192973c7820129b724e589268cfcba4600ffb168cWill Drewry//
292973c7820129b724e589268cfcba4600ffb168cWill Drewry// Copyright (C) 2017 The Android Open Source Project
392973c7820129b724e589268cfcba4600ffb168cWill Drewry//
492973c7820129b724e589268cfcba4600ffb168cWill Drewry// Licensed under the Apache License, Version 2.0 (the "License");
592973c7820129b724e589268cfcba4600ffb168cWill Drewry// you may not use this file except in compliance with the License.
692973c7820129b724e589268cfcba4600ffb168cWill Drewry// You may obtain a copy of the License at
792973c7820129b724e589268cfcba4600ffb168cWill Drewry//
892973c7820129b724e589268cfcba4600ffb168cWill Drewry//      http://www.apache.org/licenses/LICENSE-2.0
992973c7820129b724e589268cfcba4600ffb168cWill Drewry//
1092973c7820129b724e589268cfcba4600ffb168cWill Drewry// Unless required by applicable law or agreed to in writing, software
1192973c7820129b724e589268cfcba4600ffb168cWill Drewry// distributed under the License is distributed on an "AS IS" BASIS,
1292973c7820129b724e589268cfcba4600ffb168cWill Drewry// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1392973c7820129b724e589268cfcba4600ffb168cWill Drewry// See the License for the specific language governing permissions and
1492973c7820129b724e589268cfcba4600ffb168cWill Drewry// limitations under the License.
1592973c7820129b724e589268cfcba4600ffb168cWill Drewry//
1692973c7820129b724e589268cfcba4600ffb168cWill Drewry
1792973c7820129b724e589268cfcba4600ffb168cWill Drewrypackage com.android.verifiedboot.storage;
1892973c7820129b724e589268cfcba4600ffb168cWill Drewry
1992973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.framework.CardRuntimeException;
2092973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.framework.JCSystem;
2192973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.framework.Util;
2292973c7820129b724e589268cfcba4600ffb168cWill Drewry
2392973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.security.KeyBuilder;
2492973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.security.MessageDigest;
2592973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.security.RSAPublicKey;
2692973c7820129b724e589268cfcba4600ffb168cWill Drewryimport javacard.security.Signature;
2792973c7820129b724e589268cfcba4600ffb168cWill Drewry
2892973c7820129b724e589268cfcba4600ffb168cWill Drewryimport com.android.verifiedboot.storage.LockInterface;
2992973c7820129b724e589268cfcba4600ffb168cWill Drewryimport com.android.verifiedboot.globalstate.owner.OwnerInterface;
3092973c7820129b724e589268cfcba4600ffb168cWill Drewry
3192973c7820129b724e589268cfcba4600ffb168cWill Drewryclass CarrierLock implements LockInterface, BackupInterface {
3292973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte VERSION = (byte) 1;
3392973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte VERSION_SIZE = (byte) 8;
3492973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte NONCE_SIZE = (byte) 8;
3592973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte DEVICE_DATA_SIZE = (byte) (256 / 8);
3692973c7820129b724e589268cfcba4600ffb168cWill Drewry
3792973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte[] PK_EXP = { (byte) 0x01, (byte) 0x00, (byte) 0x01 };  /* 65537 */
38d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry    // Production key.
39d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry    private final static byte[] PK_MOD = {
40d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xA3, (byte) 0x19, (byte) 0x27, (byte) 0x0B, (byte) 0xC6,
41d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x3C, (byte) 0xC0, (byte) 0x92, (byte) 0x38, (byte) 0x7D,
42d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xE3, (byte) 0xC1, (byte) 0xAE, (byte) 0xDD, (byte) 0x2C,
43d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xAA, (byte) 0x1C, (byte) 0x93, (byte) 0x23, (byte) 0xAA,
44d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x13, (byte) 0xF2, (byte) 0x0D, (byte) 0x03, (byte) 0x5F,
45d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xB8, (byte) 0x98, (byte) 0xA8, (byte) 0xFA, (byte) 0x57,
46d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xE9, (byte) 0xBF, (byte) 0x15, (byte) 0xE3, (byte) 0xAC,
47d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xB5, (byte) 0x64, (byte) 0xE7, (byte) 0x18, (byte) 0x85,
48d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xE1, (byte) 0xE4, (byte) 0xF0, (byte) 0x36, (byte) 0x81,
49d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x57, (byte) 0xA8, (byte) 0x78, (byte) 0x70, (byte) 0xDF,
50d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x92, (byte) 0x06, (byte) 0xCF, (byte) 0xEE, (byte) 0x1A,
51d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x6B, (byte) 0xE8, (byte) 0x50, (byte) 0x28, (byte) 0xD9,
52d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x54, (byte) 0x03, (byte) 0x6E, (byte) 0xF2, (byte) 0x6C,
53d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x06, (byte) 0xCE, (byte) 0x02, (byte) 0x8A, (byte) 0xF4,
54d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x86, (byte) 0x07, (byte) 0xA8, (byte) 0xE6, (byte) 0x6C,
55d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x1F, (byte) 0xFE, (byte) 0xB4, (byte) 0x83, (byte) 0x79,
56d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x40, (byte) 0x02, (byte) 0x25, (byte) 0xBD, (byte) 0x6B,
57d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x67, (byte) 0x03, (byte) 0xEB, (byte) 0xF2, (byte) 0xC7,
58d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x74, (byte) 0xB9, (byte) 0xE8, (byte) 0x35, (byte) 0x76,
59d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x4C, (byte) 0x1D, (byte) 0xE7, (byte) 0x34, (byte) 0x72,
60d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x6C, (byte) 0x0E, (byte) 0xCE, (byte) 0xD6, (byte) 0x2C,
61d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x86, (byte) 0x59, (byte) 0x58, (byte) 0x10, (byte) 0x00,
62d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x7F, (byte) 0x70, (byte) 0xF7, (byte) 0x4A, (byte) 0x2F,
63d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xED, (byte) 0x39, (byte) 0x46, (byte) 0xAC, (byte) 0x3A,
64d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x32, (byte) 0x32, (byte) 0x0F, (byte) 0x7A, (byte) 0x5C,
65d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x8A, (byte) 0x07, (byte) 0xDE, (byte) 0xA1, (byte) 0x8F,
66d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x74, (byte) 0xD8, (byte) 0x99, (byte) 0x3A, (byte) 0xE0,
67d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x9A, (byte) 0x40, (byte) 0x80, (byte) 0x51, (byte) 0x1F,
68d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xAD, (byte) 0x4D, (byte) 0x2A, (byte) 0x1D, (byte) 0x53,
69d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xC3, (byte) 0x66, (byte) 0x65, (byte) 0x59, (byte) 0x6D,
70d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x40, (byte) 0xB8, (byte) 0x71, (byte) 0xB5, (byte) 0xD4,
71d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x50, (byte) 0x3E, (byte) 0x41, (byte) 0xE0, (byte) 0x14,
72d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x25, (byte) 0x80, (byte) 0xA9, (byte) 0x0C, (byte) 0x76,
73d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xD4, (byte) 0x6C, (byte) 0x48, (byte) 0x0F, (byte) 0x08,
74d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x5A, (byte) 0xCD, (byte) 0xE5, (byte) 0x28, (byte) 0x58,
75d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xA5, (byte) 0x35, (byte) 0x10, (byte) 0x5D, (byte) 0x05,
76d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xB0, (byte) 0xE1, (byte) 0x26, (byte) 0xD3, (byte) 0x08,
77d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xE9, (byte) 0x5D, (byte) 0xB3, (byte) 0x77, (byte) 0x19,
78d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xD7, (byte) 0xC3, (byte) 0xA7, (byte) 0x3E, (byte) 0x09,
79d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x01, (byte) 0x75, (byte) 0x14, (byte) 0x49, (byte) 0x5D,
80d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x21, (byte) 0xBA, (byte) 0x8D, (byte) 0x74, (byte) 0x0A,
81d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x45, (byte) 0xCA, (byte) 0x39, (byte) 0x24, (byte) 0x94,
82d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x33, (byte) 0x0F, (byte) 0x35, (byte) 0x40, (byte) 0x70,
83d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x0B, (byte) 0x6C, (byte) 0xF7, (byte) 0x93, (byte) 0x35,
84d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x9A, (byte) 0x40, (byte) 0x72, (byte) 0xD7, (byte) 0xDD,
85d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xA5, (byte) 0xAA, (byte) 0x2A, (byte) 0x7B, (byte) 0x32,
86d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xF6, (byte) 0x56, (byte) 0x71, (byte) 0xC6, (byte) 0xAB,
87d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xEB, (byte) 0xFB, (byte) 0xCD, (byte) 0x27, (byte) 0xA1,
88d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x4C, (byte) 0xDA, (byte) 0xA4, (byte) 0xB1, (byte) 0x66,
89d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0x2D, (byte) 0x57, (byte) 0x4B, (byte) 0x0D, (byte) 0x86,
90d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xD0, (byte) 0x98, (byte) 0x4B, (byte) 0x71, (byte) 0x8D,
91d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry        (byte) 0xF5,
92d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry    };
93d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry
94d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry
95d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry    /* Development key
9692973c7820129b724e589268cfcba4600ffb168cWill Drewry    private final static byte[] PK_MOD = {
9792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xAE, (byte) 0x14, (byte) 0xA4, (byte) 0x91, (byte) 0xA6,
9892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xC8, (byte) 0x2E, (byte) 0x4D, (byte) 0x6B, (byte) 0xB3,
9992973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x4E, (byte) 0x23, (byte) 0x96, (byte) 0x57, (byte) 0x7C,
10092973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x2C, (byte) 0x7E, (byte) 0x69, (byte) 0xE6, (byte) 0xBF,
10192973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x5A, (byte) 0x9C, (byte) 0xD7, (byte) 0xA8, (byte) 0x38,
10292973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x0C, (byte) 0x9A, (byte) 0x54, (byte) 0x43, (byte) 0x4C,
10392973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x3C, (byte) 0xDA, (byte) 0xC5, (byte) 0xB1, (byte) 0x58,
10492973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x56, (byte) 0x9B, (byte) 0x5A, (byte) 0x05, (byte) 0xBA,
10592973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x2C, (byte) 0xAB, (byte) 0xC6, (byte) 0x50, (byte) 0x34,
10692973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x3C, (byte) 0x3B, (byte) 0x8E, (byte) 0xD8, (byte) 0x55,
10792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xEB, (byte) 0xFA, (byte) 0x4F, (byte) 0x72, (byte) 0x81,
10892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xA3, (byte) 0x8F, (byte) 0xDD, (byte) 0x8E, (byte) 0x0E,
10992973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xF2, (byte) 0xF6, (byte) 0xEF, (byte) 0x18, (byte) 0x95,
11092973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xCF, (byte) 0x71, (byte) 0x7D, (byte) 0x33, (byte) 0xA1,
11192973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xAE, (byte) 0xBE, (byte) 0x8C, (byte) 0xA5, (byte) 0x50,
11292973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x4C, (byte) 0xF2, (byte) 0xDC, (byte) 0x7B, (byte) 0x6C,
11392973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xAE, (byte) 0x14, (byte) 0x95, (byte) 0xB7, (byte) 0xE7,
11492973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xCA, (byte) 0xEB, (byte) 0xB0, (byte) 0x24, (byte) 0x5B,
11592973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xC9, (byte) 0x24, (byte) 0x2B, (byte) 0xC6, (byte) 0x96,
11692973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x99, (byte) 0xE9, (byte) 0x8B, (byte) 0x10, (byte) 0xCA,
11792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x34, (byte) 0x2D, (byte) 0x84, (byte) 0x57, (byte) 0x09,
11892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x4C, (byte) 0x32, (byte) 0x35, (byte) 0x68, (byte) 0x37,
11992973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x53, (byte) 0x0E, (byte) 0xF6, (byte) 0x93, (byte) 0x6C,
12092973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x86, (byte) 0x84, (byte) 0xC1, (byte) 0x44, (byte) 0x70,
12192973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x4A, (byte) 0x12, (byte) 0xAA, (byte) 0xC2, (byte) 0x9F,
12292973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x68, (byte) 0x5C, (byte) 0x42, (byte) 0xC8, (byte) 0xEB,
12392973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xD3, (byte) 0xAF, (byte) 0xD6, (byte) 0x34, (byte) 0x7F,
12492973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x9D, (byte) 0xC9, (byte) 0xE8, (byte) 0x81, (byte) 0x4A,
12592973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x5C, (byte) 0xDA, (byte) 0x36, (byte) 0x33, (byte) 0xFD,
12692973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x5C, (byte) 0x67, (byte) 0xBB, (byte) 0x91, (byte) 0x1C,
12792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xF5, (byte) 0x21, (byte) 0xC0, (byte) 0x4E, (byte) 0x64,
12892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x87, (byte) 0x89, (byte) 0xB6, (byte) 0x8B, (byte) 0xFD,
12992973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xDA, (byte) 0x30, (byte) 0x74, (byte) 0x1E, (byte) 0x00,
13092973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x57, (byte) 0xE1, (byte) 0x5C, (byte) 0xC4, (byte) 0xF2,
13192973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xEE, (byte) 0xF7, (byte) 0x05, (byte) 0x1C, (byte) 0xCE,
13292973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xF1, (byte) 0xCA, (byte) 0x88, (byte) 0xA0, (byte) 0x28,
13392973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x53, (byte) 0x2C, (byte) 0x84, (byte) 0xCD, (byte) 0xA3,
13492973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x6C, (byte) 0x1D, (byte) 0x15, (byte) 0x00, (byte) 0x5A,
13592973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x5D, (byte) 0x80, (byte) 0x40, (byte) 0x59, (byte) 0xE5,
13692973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xEA, (byte) 0xD1, (byte) 0x2A, (byte) 0xD6, (byte) 0x5A,
13792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xE0, (byte) 0xE6, (byte) 0x9C, (byte) 0xEB, (byte) 0x23,
13892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x4D, (byte) 0xD0, (byte) 0xB1, (byte) 0x27, (byte) 0xEE,
13992973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x41, (byte) 0x0D, (byte) 0xAA, (byte) 0x25, (byte) 0xBD,
14092973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xA0, (byte) 0xD0, (byte) 0x20, (byte) 0x00, (byte) 0x16,
14192973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x1F, (byte) 0x54, (byte) 0xC6, (byte) 0x4A, (byte) 0xDD,
14292973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x2A, (byte) 0x7E, (byte) 0x32, (byte) 0x43, (byte) 0x7F,
14392973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0xD8, (byte) 0x74, (byte) 0x0F, (byte) 0x94, (byte) 0x88,
14492973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x3F, (byte) 0x26, (byte) 0x27, (byte) 0x54, (byte) 0x5D,
14592973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x01, (byte) 0x83, (byte) 0xAE, (byte) 0x47, (byte) 0x37,
14692973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x03, (byte) 0x6C, (byte) 0x80, (byte) 0xFD, (byte) 0x6E,
14792973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x08, (byte) 0xEB, (byte) 0xB4, (byte) 0x55, (byte) 0x81,
14892973c7820129b724e589268cfcba4600ffb168cWill Drewry        (byte) 0x13,
14992973c7820129b724e589268cfcba4600ffb168cWill Drewry    };
150d209f7146073eac530d0f46026a57839b10c8cf1Will Drewry    */
15192973c7820129b724e589268cfcba4600ffb168cWill Drewry
15292973c7820129b724e589268cfcba4600ffb168cWill Drewry    // Layout:
15392973c7820129b724e589268cfcba4600ffb168cWill Drewry    // LockValue (byte) || lastNonce (byte[8]) || deviceDataHash (byte[32])
15492973c7820129b724e589268cfcba4600ffb168cWill Drewry    private byte[] storage;
15592973c7820129b724e589268cfcba4600ffb168cWill Drewry    private short storageOffset;
15692973c7820129b724e589268cfcba4600ffb168cWill Drewry    RSAPublicKey verifyingKey;
15792973c7820129b724e589268cfcba4600ffb168cWill Drewry    Signature verifier;
15892973c7820129b724e589268cfcba4600ffb168cWill Drewry    MessageDigest md_sha256;  /* For creating the lock data hash from the input. */
15992973c7820129b724e589268cfcba4600ffb168cWill Drewry    OwnerInterface globalState;
16092973c7820129b724e589268cfcba4600ffb168cWill Drewry
16192973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
16292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Initializes the instance objects.
16392973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
16492973c7820129b724e589268cfcba4600ffb168cWill Drewry    public CarrierLock() {
16592973c7820129b724e589268cfcba4600ffb168cWill Drewry        try {
16692973c7820129b724e589268cfcba4600ffb168cWill Drewry            verifyingKey = (RSAPublicKey)KeyBuilder.buildKey(
16792973c7820129b724e589268cfcba4600ffb168cWill Drewry                KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false);
16892973c7820129b724e589268cfcba4600ffb168cWill Drewry            verifyingKey.setExponent(PK_EXP, (short)0, (short)PK_EXP.length);
16992973c7820129b724e589268cfcba4600ffb168cWill Drewry            verifyingKey.setModulus(PK_MOD, (short)0, (short)PK_MOD.length);
17092973c7820129b724e589268cfcba4600ffb168cWill Drewry        } catch (CardRuntimeException e) {
17192973c7820129b724e589268cfcba4600ffb168cWill Drewry          verifyingKey = null;
17292973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
17392973c7820129b724e589268cfcba4600ffb168cWill Drewry
17492973c7820129b724e589268cfcba4600ffb168cWill Drewry        try {
17592973c7820129b724e589268cfcba4600ffb168cWill Drewry            verifier = Signature.getInstance(Signature.ALG_RSA_SHA_256_PKCS1, false);
17692973c7820129b724e589268cfcba4600ffb168cWill Drewry            verifier.init(verifyingKey, Signature.MODE_VERIFY);
17792973c7820129b724e589268cfcba4600ffb168cWill Drewry        } catch (CardRuntimeException e) {
17892973c7820129b724e589268cfcba4600ffb168cWill Drewry          verifier = null;
17992973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
18092973c7820129b724e589268cfcba4600ffb168cWill Drewry        md_sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
18192973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
18292973c7820129b724e589268cfcba4600ffb168cWill Drewry
18392973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
18492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
18592973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
18692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Return the error states useful for diagnostics.
18792973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
18892973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
18992973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short initialized() {
19092973c7820129b724e589268cfcba4600ffb168cWill Drewry      if (storage == null) {
19192973c7820129b724e589268cfcba4600ffb168cWill Drewry          return 1;
19292973c7820129b724e589268cfcba4600ffb168cWill Drewry      }
19392973c7820129b724e589268cfcba4600ffb168cWill Drewry      if (verifyingKey == null) {
19492973c7820129b724e589268cfcba4600ffb168cWill Drewry          return 2;
19592973c7820129b724e589268cfcba4600ffb168cWill Drewry      }
19692973c7820129b724e589268cfcba4600ffb168cWill Drewry      if (verifier == null) {
19792973c7820129b724e589268cfcba4600ffb168cWill Drewry          return 3;
19892973c7820129b724e589268cfcba4600ffb168cWill Drewry      }
19992973c7820129b724e589268cfcba4600ffb168cWill Drewry      return 0;
20092973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
20192973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
20292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
20392973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
20492973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
20592973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
20692973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short getStorageNeeded() {
20792973c7820129b724e589268cfcba4600ffb168cWill Drewry        return NONCE_SIZE + DEVICE_DATA_SIZE + 1;
20892973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
20992973c7820129b724e589268cfcba4600ffb168cWill Drewry
21092973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
21192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Sets the backing store to use for state.
21292973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
21392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param globalStateOwner interface for querying global state
21492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param extStorage  external array to use for storage
21592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param extStorageOffset where to begin storing data
21692973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
21792973c7820129b724e589268cfcba4600ffb168cWill Drewry     * This should be called before use.
21892973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
21992973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
22092973c7820129b724e589268cfcba4600ffb168cWill Drewry    public void initialize(OwnerInterface globalStateOwner, byte[] extStorage,
22192973c7820129b724e589268cfcba4600ffb168cWill Drewry                           short extStorageOffset) {
22292973c7820129b724e589268cfcba4600ffb168cWill Drewry        globalState = globalStateOwner;
22392973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Zero it first (in case we are interrupted).
22492973c7820129b724e589268cfcba4600ffb168cWill Drewry        Util.arrayFillNonAtomic(extStorage, extStorageOffset,
22592973c7820129b724e589268cfcba4600ffb168cWill Drewry                                getStorageNeeded(), (byte) 0x00);
22692973c7820129b724e589268cfcba4600ffb168cWill Drewry        storage = extStorage;
22792973c7820129b724e589268cfcba4600ffb168cWill Drewry        storageOffset = extStorageOffset;
22892973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
22992973c7820129b724e589268cfcba4600ffb168cWill Drewry
23092973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
23192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
23292973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
23392973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
23492973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short get(byte[] lockOut, short outOffset) {
23592973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (storage == null) {
23692973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0x0001;
23792973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
23892973c7820129b724e589268cfcba4600ffb168cWill Drewry        try {
23992973c7820129b724e589268cfcba4600ffb168cWill Drewry            Util.arrayCopy(storage, lockOffset(),
24092973c7820129b724e589268cfcba4600ffb168cWill Drewry                           lockOut, outOffset, (short) 1);
24192973c7820129b724e589268cfcba4600ffb168cWill Drewry        } catch (CardRuntimeException e) {
24292973c7820129b724e589268cfcba4600ffb168cWill Drewry          return 0x0002;
24392973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
24492973c7820129b724e589268cfcba4600ffb168cWill Drewry        return 0;
24592973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
24692973c7820129b724e589268cfcba4600ffb168cWill Drewry
24792973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
24892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
24992973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
25092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Returns 0xffff if {@link #initialize()} has not yet been called.
25192973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
25292973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
25392973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short lockOffset() {
25492973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (storage == null) {
25592973c7820129b724e589268cfcba4600ffb168cWill Drewry            return (short) 0xffff;
25692973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
25792973c7820129b724e589268cfcba4600ffb168cWill Drewry        return storageOffset;
25892973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
25992973c7820129b724e589268cfcba4600ffb168cWill Drewry
26092973c7820129b724e589268cfcba4600ffb168cWill Drewry
26192973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
26292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
26392973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
26492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Returns 0xffff if {@link #initialize()} has not yet been called.
26592973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
26692973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
26792973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short metadataOffset() {
26892973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (storage == null) {
26992973c7820129b724e589268cfcba4600ffb168cWill Drewry            return (short) 0xffff;
27092973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
27192973c7820129b724e589268cfcba4600ffb168cWill Drewry        return (short)(storageOffset + NONCE_SIZE + 1);
27292973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
27392973c7820129b724e589268cfcba4600ffb168cWill Drewry
27492973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
27592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
27692973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
27792973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Returns length of metadata.
27892973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
27992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @return length of metadata.
28092973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
28192973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short metadataLength() {
28292973c7820129b724e589268cfcba4600ffb168cWill Drewry        return (short) DEVICE_DATA_SIZE;
28392973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
28492973c7820129b724e589268cfcba4600ffb168cWill Drewry
28592973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
28692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
28792973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
28892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Always returns false. Locking CarrierLock requires
28992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * device data and unlocking (val=0x0) requires a signed
29092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * assertion.
29192973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
29292973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
29392973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short set(byte val) {
29492973c7820129b724e589268cfcba4600ffb168cWill Drewry        return (short)0xffff;  // Not implemented.
29592973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
29692973c7820129b724e589268cfcba4600ffb168cWill Drewry
29792973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
29892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Performs the verification of the incoming unlock token.
29992973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
30092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * This will check the version code, the nonce value, and the signature.
30192973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
30292973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
30392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param deviceData
30492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param deviceDataOffset
30592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param lastNonce
30692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param lastNonceOffset
30792973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param unlockToken
30892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param unlockTokenOffset
30992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param unlockTokenLength
31092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @return 0x0 on verified and an error code if not.
31192973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
31292973c7820129b724e589268cfcba4600ffb168cWill Drewry    private short verifyUnlock(byte[] deviceData, short deviceDataOffset,
31392973c7820129b724e589268cfcba4600ffb168cWill Drewry                               byte[] lastNonce, short lastNonceOffset,
31492973c7820129b724e589268cfcba4600ffb168cWill Drewry                               byte[] unlockToken, short unlockTokenOffset,
31592973c7820129b724e589268cfcba4600ffb168cWill Drewry                               short unlockTokenLength) {
31692973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (unlockTokenLength < (short)(VERSION_SIZE + NONCE_SIZE + PK_MOD.length)) {
31792973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0x0002;
31892973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
31992973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Only supported version is the uint64le_t 1
32092973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (unlockToken[unlockTokenOffset] != VERSION) {
32192973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0x0003;
32292973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
32392973c7820129b724e589268cfcba4600ffb168cWill Drewry
32492973c7820129b724e589268cfcba4600ffb168cWill Drewry        byte[] message = JCSystem.makeTransientByteArray(
32592973c7820129b724e589268cfcba4600ffb168cWill Drewry            (short)(NONCE_SIZE + DEVICE_DATA_SIZE), JCSystem.CLEAR_ON_DESELECT);
32692973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Collect the incoming nonce.
32792973c7820129b724e589268cfcba4600ffb168cWill Drewry        Util.arrayCopy(unlockToken, (short)(unlockTokenOffset + VERSION_SIZE),
32892973c7820129b724e589268cfcba4600ffb168cWill Drewry                       message, (short) 0x0, (short) NONCE_SIZE);
32992973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Append the internallty stored device data.
33092973c7820129b724e589268cfcba4600ffb168cWill Drewry        Util.arrayCopy(deviceData, deviceDataOffset,
33192973c7820129b724e589268cfcba4600ffb168cWill Drewry            message, (short)NONCE_SIZE, (short) DEVICE_DATA_SIZE);
33292973c7820129b724e589268cfcba4600ffb168cWill Drewry
33392973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Verify it against the incoming signature.
33492973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (verifier.verify(
33592973c7820129b724e589268cfcba4600ffb168cWill Drewry                message, (short) 0, (short) message.length, unlockToken,
33692973c7820129b724e589268cfcba4600ffb168cWill Drewry                (short)(unlockTokenOffset + VERSION_SIZE + NONCE_SIZE),
33792973c7820129b724e589268cfcba4600ffb168cWill Drewry                (short)(unlockTokenLength - (VERSION_SIZE + NONCE_SIZE))) ==
33892973c7820129b724e589268cfcba4600ffb168cWill Drewry                false) {
33992973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0x0004;
34092973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
34192973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (littleEndianUnsignedGreaterThan(NONCE_SIZE,
34292973c7820129b724e589268cfcba4600ffb168cWill Drewry                unlockToken, (short)(unlockTokenOffset + VERSION_SIZE),
34392973c7820129b724e589268cfcba4600ffb168cWill Drewry                lastNonce, lastNonceOffset) == true) {
34492973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0;
34592973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
34692973c7820129b724e589268cfcba4600ffb168cWill Drewry        return 0x0005;
34792973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
34892973c7820129b724e589268cfcba4600ffb168cWill Drewry
34992973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
35092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Compares two little endian byte streams and returns
35192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * true if lhs is greater than rhs.
35292973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
35392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param len number of bytes to compare
35492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param lhs left hand size buffer
35592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param lhsBase starting offset
35692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param rhs right hand size buffer
35792973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param rhsBase starting offset
35892973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
35992973c7820129b724e589268cfcba4600ffb168cWill Drewry    private boolean littleEndianUnsignedGreaterThan(
36092973c7820129b724e589268cfcba4600ffb168cWill Drewry            byte len,
36192973c7820129b724e589268cfcba4600ffb168cWill Drewry            byte[] lhs, short lhsBase,
36292973c7820129b724e589268cfcba4600ffb168cWill Drewry            byte[] rhs, short rhsBase) {
36392973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Start with the most significant byte.
36492973c7820129b724e589268cfcba4600ffb168cWill Drewry        short i = len;
36592973c7820129b724e589268cfcba4600ffb168cWill Drewry        do {
36692973c7820129b724e589268cfcba4600ffb168cWill Drewry            i -= 1;
36792973c7820129b724e589268cfcba4600ffb168cWill Drewry            if (lhs[(short)(lhsBase +i)] > rhs[(short)(rhsBase + i)]) {
36892973c7820129b724e589268cfcba4600ffb168cWill Drewry                return true;
36992973c7820129b724e589268cfcba4600ffb168cWill Drewry            }
37092973c7820129b724e589268cfcba4600ffb168cWill Drewry            if (lhs[(short)(lhsBase +i)] < rhs[(short)(rhsBase + i)]) {
37192973c7820129b724e589268cfcba4600ffb168cWill Drewry                return false;
37292973c7820129b724e589268cfcba4600ffb168cWill Drewry            }
37392973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Only proceed if the current bytes are equal.
37492973c7820129b724e589268cfcba4600ffb168cWill Drewry        } while (i > 0);
37592973c7820129b724e589268cfcba4600ffb168cWill Drewry        return false;
37692973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
37792973c7820129b724e589268cfcba4600ffb168cWill Drewry
37892973c7820129b724e589268cfcba4600ffb168cWill Drewry
37992973c7820129b724e589268cfcba4600ffb168cWill Drewry
38092973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
38192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
38292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Returns true if the lock is changed with associated metadata.
38392973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
38492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * If |lockValue| is non-zero, then |lockMeta| should contain a series of
38592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * ASCII (or hex) values separated by short lengths.  These will be SHA256
38692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * hashed together to create a "device data hash". Its use is covered next.
38792973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
38892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * If |lockValue| is zero, then |lockMeta| should contain the following
38992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * (all little endian): 8-bit version tag (0x01) || byte[8] "64-bit nonce"
39092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * || byte[] Signature(nonce||deviceDataHash) The signature is using the
39192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * embedded key {@link #pkModulus} and the format is ALG_RSA_SHA_256_PKCS1.
39292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * If the signature verifies using the internally stored deviceDataHash and
39392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * the provided nonce, then one last check is applied.  If the nonce,
39492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * treated as a little endian uint64_t, is greater than the stored nonce then
39592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * it will be rejected.  Note, once unlocked, the device data hash is deleted
39692973c7820129b724e589268cfcba4600ffb168cWill Drewry     * and the CarrierLock cannot be reapplied unless the device is taken out
39792973c7820129b724e589268cfcba4600ffb168cWill Drewry     * of production mode (bootloader RMA path).
39892973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
39992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * If {@link #globalState} indicates that the device is not yet in production
40092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * mode, then the lock values can be toggled arbitrarily.
40192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * The lock values may also be changed in the bootloader or in the HLOS as
40292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * the transitions are either one-way (lock) or authenticated.  It is required
40392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * that the lock state is assigned prior to transitioning to production as that
40492973c7820129b724e589268cfcba4600ffb168cWill Drewry     * ensures that an unlocked device cannot be re-locked maliciously from the HLOS.
40592973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
40692973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
40792973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short setWithMetadata(byte lockValue, byte[] lockMeta,
40892973c7820129b724e589268cfcba4600ffb168cWill Drewry                                 short lockMetaOffset, short lockMetaLength) {
40992973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (storage == null) {
41092973c7820129b724e589268cfcba4600ffb168cWill Drewry            // TODO: move to constants.
41192973c7820129b724e589268cfcba4600ffb168cWill Drewry            return 0x0001;
41292973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
41392973c7820129b724e589268cfcba4600ffb168cWill Drewry        // Ensure we don't update the nonce if we didn't go through verify.
41492973c7820129b724e589268cfcba4600ffb168cWill Drewry        short resp = (short) 0xffff;
41592973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (lockValue == LOCK_UNLOCKED) {  // SHUT IT DOWN.
41692973c7820129b724e589268cfcba4600ffb168cWill Drewry            // If we're already unlocked, allow another call to make sure all the
41792973c7820129b724e589268cfcba4600ffb168cWill Drewry            // data is cleared.
41892973c7820129b724e589268cfcba4600ffb168cWill Drewry            if (storage[storageOffset] != LOCK_UNLOCKED &&
41992973c7820129b724e589268cfcba4600ffb168cWill Drewry                globalState.production() == true) {
42092973c7820129b724e589268cfcba4600ffb168cWill Drewry                // RSA PKCS#1 signature should be the same length as the modulus but we'll allow it to
42192973c7820129b724e589268cfcba4600ffb168cWill Drewry                // be larger because ???. XXX TODO
42292973c7820129b724e589268cfcba4600ffb168cWill Drewry                resp = verifyUnlock(storage, (short)(storageOffset + 1 + NONCE_SIZE),
42392973c7820129b724e589268cfcba4600ffb168cWill Drewry                                    storage, (short)(storageOffset + 1),
42492973c7820129b724e589268cfcba4600ffb168cWill Drewry                                    lockMeta, lockMetaOffset, lockMetaLength);
42592973c7820129b724e589268cfcba4600ffb168cWill Drewry                if (resp != (short) 0) {
42692973c7820129b724e589268cfcba4600ffb168cWill Drewry                  return resp;
42792973c7820129b724e589268cfcba4600ffb168cWill Drewry                }
42892973c7820129b724e589268cfcba4600ffb168cWill Drewry            }
42992973c7820129b724e589268cfcba4600ffb168cWill Drewry            JCSystem.beginTransaction();
43092973c7820129b724e589268cfcba4600ffb168cWill Drewry            storage[storageOffset] = lockValue;
43192973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Update the monotonically increasing "nonce" value.
43292973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Note that the nonce is only ever updated if a signed value
43392973c7820129b724e589268cfcba4600ffb168cWill Drewry            // was seen or if we're not production() to assure it doesn't get
43492973c7820129b724e589268cfcba4600ffb168cWill Drewry            // rolled forward.
43592973c7820129b724e589268cfcba4600ffb168cWill Drewry            if (resp == 0) {
4368055858133dca4e507f7d17b9c931f2547a988afWill Drewry                Util.arrayCopy(lockMeta, (short)(VERSION_SIZE + lockMetaOffset),
43792973c7820129b724e589268cfcba4600ffb168cWill Drewry                               storage, (short)(1 + storageOffset),
43892973c7820129b724e589268cfcba4600ffb168cWill Drewry                               (short)NONCE_SIZE);
43992973c7820129b724e589268cfcba4600ffb168cWill Drewry            }
44092973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Delete the device-unique data.
44192973c7820129b724e589268cfcba4600ffb168cWill Drewry            Util.arrayFillNonAtomic(storage, (short)(NONCE_SIZE + 1 + storageOffset),
44292973c7820129b724e589268cfcba4600ffb168cWill Drewry                (short)DEVICE_DATA_SIZE, (byte)0x00);
44392973c7820129b724e589268cfcba4600ffb168cWill Drewry            JCSystem.commitTransaction();
44492973c7820129b724e589268cfcba4600ffb168cWill Drewry        } else {  // Locking. Expect a lockMeta of the device data.
44592973c7820129b724e589268cfcba4600ffb168cWill Drewry            if (globalState.production() == true) {
44692973c7820129b724e589268cfcba4600ffb168cWill Drewry                // Locking can only be done prior to production.
44792973c7820129b724e589268cfcba4600ffb168cWill Drewry                return 0x0006;
44892973c7820129b724e589268cfcba4600ffb168cWill Drewry            }
44992973c7820129b724e589268cfcba4600ffb168cWill Drewry            md_sha256.reset();
45092973c7820129b724e589268cfcba4600ffb168cWill Drewry            JCSystem.beginTransaction();
45192973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Hash all the input data and store the result as the device data
45292973c7820129b724e589268cfcba4600ffb168cWill Drewry            // digest.
45392973c7820129b724e589268cfcba4600ffb168cWill Drewry            md_sha256.doFinal(lockMeta, lockMetaOffset, lockMetaLength,
45492973c7820129b724e589268cfcba4600ffb168cWill Drewry                              storage, metadataOffset());
45592973c7820129b724e589268cfcba4600ffb168cWill Drewry            // Note that we never clear or overwrite the nonce.
45692973c7820129b724e589268cfcba4600ffb168cWill Drewry            storage[storageOffset] = lockValue;
45792973c7820129b724e589268cfcba4600ffb168cWill Drewry            JCSystem.commitTransaction();
45892973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
45992973c7820129b724e589268cfcba4600ffb168cWill Drewry        return 0x0000;
46092973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
46192973c7820129b724e589268cfcba4600ffb168cWill Drewry
46292973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
46392973c7820129b724e589268cfcba4600ffb168cWill Drewry     * Given all the data, tests if the key actually works.
46492973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
46592973c7820129b724e589268cfcba4600ffb168cWill Drewry     * buffer should contain:
46692973c7820129b724e589268cfcba4600ffb168cWill Drewry     *   fakeLastNonce | fakeDeviceData | version (8) | testNonce | signature
46792973c7820129b724e589268cfcba4600ffb168cWill Drewry     *
46892973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param buffer Array with the test data.
46992973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param offset offset into the buffer.
47092973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @param length total length from offset.
47192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * @return 0x0 on verify and an error code otherwise.
47292973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
47392973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short testVector(byte[] buffer, short offset, short length) {
47492973c7820129b724e589268cfcba4600ffb168cWill Drewry        return verifyUnlock(buffer, (short)(offset + NONCE_SIZE), // device data
47592973c7820129b724e589268cfcba4600ffb168cWill Drewry                            buffer, offset,  // fake last nonce.
47692973c7820129b724e589268cfcba4600ffb168cWill Drewry                            // unlock data
47792973c7820129b724e589268cfcba4600ffb168cWill Drewry                            buffer, (short)(offset + NONCE_SIZE + DEVICE_DATA_SIZE),
47892973c7820129b724e589268cfcba4600ffb168cWill Drewry                            (short)(length - (NONCE_SIZE + DEVICE_DATA_SIZE)));
47992973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
48092973c7820129b724e589268cfcba4600ffb168cWill Drewry
48192973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
48292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
48392973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
48492973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
48592973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short backupSize() {
48692973c7820129b724e589268cfcba4600ffb168cWill Drewry        return getStorageNeeded();
48792973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
48892973c7820129b724e589268cfcba4600ffb168cWill Drewry
48992973c7820129b724e589268cfcba4600ffb168cWill Drewry
49092973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
49192973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
49292973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
49392973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
49492973c7820129b724e589268cfcba4600ffb168cWill Drewry    public short backup(byte[] outBytes, short outBytesOffset) {
49592973c7820129b724e589268cfcba4600ffb168cWill Drewry        Util.arrayCopy(storage, storageOffset,
49692973c7820129b724e589268cfcba4600ffb168cWill Drewry                       outBytes, outBytesOffset,
49792973c7820129b724e589268cfcba4600ffb168cWill Drewry                       backupSize());
49892973c7820129b724e589268cfcba4600ffb168cWill Drewry        return backupSize();
49992973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
50092973c7820129b724e589268cfcba4600ffb168cWill Drewry
50192973c7820129b724e589268cfcba4600ffb168cWill Drewry    /**
50292973c7820129b724e589268cfcba4600ffb168cWill Drewry     * {@inheritDoc}
50392973c7820129b724e589268cfcba4600ffb168cWill Drewry     */
50492973c7820129b724e589268cfcba4600ffb168cWill Drewry    @Override
50592973c7820129b724e589268cfcba4600ffb168cWill Drewry    public boolean restore(byte[] inBytes, short inBytesOffset,
50692973c7820129b724e589268cfcba4600ffb168cWill Drewry                           short inBytesLength) {
50792973c7820129b724e589268cfcba4600ffb168cWill Drewry        if (inBytesLength > backupSize() || inBytesLength == (short)0) {
50892973c7820129b724e589268cfcba4600ffb168cWill Drewry            return false;
50992973c7820129b724e589268cfcba4600ffb168cWill Drewry        }
51092973c7820129b724e589268cfcba4600ffb168cWill Drewry        Util.arrayCopy(inBytes, inBytesOffset,
51192973c7820129b724e589268cfcba4600ffb168cWill Drewry                       storage, storageOffset,
51292973c7820129b724e589268cfcba4600ffb168cWill Drewry                       inBytesLength);
51392973c7820129b724e589268cfcba4600ffb168cWill Drewry        return true;
51492973c7820129b724e589268cfcba4600ffb168cWill Drewry    }
51592973c7820129b724e589268cfcba4600ffb168cWill Drewry
51692973c7820129b724e589268cfcba4600ffb168cWill Drewry
51792973c7820129b724e589268cfcba4600ffb168cWill Drewry}
518