• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2017 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 package com.android.verifiedboot.storage;
18 
19 import javacard.framework.CardRuntimeException;
20 import javacard.framework.JCSystem;
21 import javacard.framework.Util;
22 
23 import javacard.security.KeyBuilder;
24 import javacard.security.MessageDigest;
25 import javacard.security.RSAPublicKey;
26 import javacard.security.Signature;
27 
28 import com.android.verifiedboot.storage.LockInterface;
29 import com.android.verifiedboot.globalstate.owner.OwnerInterface;
30 
31 class CarrierLock implements LockInterface, BackupInterface {
32     private final static byte VERSION = (byte) 1;
33     private final static byte VERSION_SIZE = (byte) 8;
34     private final static byte NONCE_SIZE = (byte) 8;
35     private final static byte DEVICE_DATA_SIZE = (byte) (256 / 8);
36 
37     private final static byte[] PK_EXP = { (byte) 0x01, (byte) 0x00, (byte) 0x01 };  /* 65537 */
38     // Production key.
39     private final static byte[] PK_MOD = {
40         (byte) 0xA3, (byte) 0x19, (byte) 0x27, (byte) 0x0B, (byte) 0xC6,
41         (byte) 0x3C, (byte) 0xC0, (byte) 0x92, (byte) 0x38, (byte) 0x7D,
42         (byte) 0xE3, (byte) 0xC1, (byte) 0xAE, (byte) 0xDD, (byte) 0x2C,
43         (byte) 0xAA, (byte) 0x1C, (byte) 0x93, (byte) 0x23, (byte) 0xAA,
44         (byte) 0x13, (byte) 0xF2, (byte) 0x0D, (byte) 0x03, (byte) 0x5F,
45         (byte) 0xB8, (byte) 0x98, (byte) 0xA8, (byte) 0xFA, (byte) 0x57,
46         (byte) 0xE9, (byte) 0xBF, (byte) 0x15, (byte) 0xE3, (byte) 0xAC,
47         (byte) 0xB5, (byte) 0x64, (byte) 0xE7, (byte) 0x18, (byte) 0x85,
48         (byte) 0xE1, (byte) 0xE4, (byte) 0xF0, (byte) 0x36, (byte) 0x81,
49         (byte) 0x57, (byte) 0xA8, (byte) 0x78, (byte) 0x70, (byte) 0xDF,
50         (byte) 0x92, (byte) 0x06, (byte) 0xCF, (byte) 0xEE, (byte) 0x1A,
51         (byte) 0x6B, (byte) 0xE8, (byte) 0x50, (byte) 0x28, (byte) 0xD9,
52         (byte) 0x54, (byte) 0x03, (byte) 0x6E, (byte) 0xF2, (byte) 0x6C,
53         (byte) 0x06, (byte) 0xCE, (byte) 0x02, (byte) 0x8A, (byte) 0xF4,
54         (byte) 0x86, (byte) 0x07, (byte) 0xA8, (byte) 0xE6, (byte) 0x6C,
55         (byte) 0x1F, (byte) 0xFE, (byte) 0xB4, (byte) 0x83, (byte) 0x79,
56         (byte) 0x40, (byte) 0x02, (byte) 0x25, (byte) 0xBD, (byte) 0x6B,
57         (byte) 0x67, (byte) 0x03, (byte) 0xEB, (byte) 0xF2, (byte) 0xC7,
58         (byte) 0x74, (byte) 0xB9, (byte) 0xE8, (byte) 0x35, (byte) 0x76,
59         (byte) 0x4C, (byte) 0x1D, (byte) 0xE7, (byte) 0x34, (byte) 0x72,
60         (byte) 0x6C, (byte) 0x0E, (byte) 0xCE, (byte) 0xD6, (byte) 0x2C,
61         (byte) 0x86, (byte) 0x59, (byte) 0x58, (byte) 0x10, (byte) 0x00,
62         (byte) 0x7F, (byte) 0x70, (byte) 0xF7, (byte) 0x4A, (byte) 0x2F,
63         (byte) 0xED, (byte) 0x39, (byte) 0x46, (byte) 0xAC, (byte) 0x3A,
64         (byte) 0x32, (byte) 0x32, (byte) 0x0F, (byte) 0x7A, (byte) 0x5C,
65         (byte) 0x8A, (byte) 0x07, (byte) 0xDE, (byte) 0xA1, (byte) 0x8F,
66         (byte) 0x74, (byte) 0xD8, (byte) 0x99, (byte) 0x3A, (byte) 0xE0,
67         (byte) 0x9A, (byte) 0x40, (byte) 0x80, (byte) 0x51, (byte) 0x1F,
68         (byte) 0xAD, (byte) 0x4D, (byte) 0x2A, (byte) 0x1D, (byte) 0x53,
69         (byte) 0xC3, (byte) 0x66, (byte) 0x65, (byte) 0x59, (byte) 0x6D,
70         (byte) 0x40, (byte) 0xB8, (byte) 0x71, (byte) 0xB5, (byte) 0xD4,
71         (byte) 0x50, (byte) 0x3E, (byte) 0x41, (byte) 0xE0, (byte) 0x14,
72         (byte) 0x25, (byte) 0x80, (byte) 0xA9, (byte) 0x0C, (byte) 0x76,
73         (byte) 0xD4, (byte) 0x6C, (byte) 0x48, (byte) 0x0F, (byte) 0x08,
74         (byte) 0x5A, (byte) 0xCD, (byte) 0xE5, (byte) 0x28, (byte) 0x58,
75         (byte) 0xA5, (byte) 0x35, (byte) 0x10, (byte) 0x5D, (byte) 0x05,
76         (byte) 0xB0, (byte) 0xE1, (byte) 0x26, (byte) 0xD3, (byte) 0x08,
77         (byte) 0xE9, (byte) 0x5D, (byte) 0xB3, (byte) 0x77, (byte) 0x19,
78         (byte) 0xD7, (byte) 0xC3, (byte) 0xA7, (byte) 0x3E, (byte) 0x09,
79         (byte) 0x01, (byte) 0x75, (byte) 0x14, (byte) 0x49, (byte) 0x5D,
80         (byte) 0x21, (byte) 0xBA, (byte) 0x8D, (byte) 0x74, (byte) 0x0A,
81         (byte) 0x45, (byte) 0xCA, (byte) 0x39, (byte) 0x24, (byte) 0x94,
82         (byte) 0x33, (byte) 0x0F, (byte) 0x35, (byte) 0x40, (byte) 0x70,
83         (byte) 0x0B, (byte) 0x6C, (byte) 0xF7, (byte) 0x93, (byte) 0x35,
84         (byte) 0x9A, (byte) 0x40, (byte) 0x72, (byte) 0xD7, (byte) 0xDD,
85         (byte) 0xA5, (byte) 0xAA, (byte) 0x2A, (byte) 0x7B, (byte) 0x32,
86         (byte) 0xF6, (byte) 0x56, (byte) 0x71, (byte) 0xC6, (byte) 0xAB,
87         (byte) 0xEB, (byte) 0xFB, (byte) 0xCD, (byte) 0x27, (byte) 0xA1,
88         (byte) 0x4C, (byte) 0xDA, (byte) 0xA4, (byte) 0xB1, (byte) 0x66,
89         (byte) 0x2D, (byte) 0x57, (byte) 0x4B, (byte) 0x0D, (byte) 0x86,
90         (byte) 0xD0, (byte) 0x98, (byte) 0x4B, (byte) 0x71, (byte) 0x8D,
91         (byte) 0xF5,
92     };
93 
94 
95     /* Development key
96     private final static byte[] PK_MOD = {
97         (byte) 0xAE, (byte) 0x14, (byte) 0xA4, (byte) 0x91, (byte) 0xA6,
98         (byte) 0xC8, (byte) 0x2E, (byte) 0x4D, (byte) 0x6B, (byte) 0xB3,
99         (byte) 0x4E, (byte) 0x23, (byte) 0x96, (byte) 0x57, (byte) 0x7C,
100         (byte) 0x2C, (byte) 0x7E, (byte) 0x69, (byte) 0xE6, (byte) 0xBF,
101         (byte) 0x5A, (byte) 0x9C, (byte) 0xD7, (byte) 0xA8, (byte) 0x38,
102         (byte) 0x0C, (byte) 0x9A, (byte) 0x54, (byte) 0x43, (byte) 0x4C,
103         (byte) 0x3C, (byte) 0xDA, (byte) 0xC5, (byte) 0xB1, (byte) 0x58,
104         (byte) 0x56, (byte) 0x9B, (byte) 0x5A, (byte) 0x05, (byte) 0xBA,
105         (byte) 0x2C, (byte) 0xAB, (byte) 0xC6, (byte) 0x50, (byte) 0x34,
106         (byte) 0x3C, (byte) 0x3B, (byte) 0x8E, (byte) 0xD8, (byte) 0x55,
107         (byte) 0xEB, (byte) 0xFA, (byte) 0x4F, (byte) 0x72, (byte) 0x81,
108         (byte) 0xA3, (byte) 0x8F, (byte) 0xDD, (byte) 0x8E, (byte) 0x0E,
109         (byte) 0xF2, (byte) 0xF6, (byte) 0xEF, (byte) 0x18, (byte) 0x95,
110         (byte) 0xCF, (byte) 0x71, (byte) 0x7D, (byte) 0x33, (byte) 0xA1,
111         (byte) 0xAE, (byte) 0xBE, (byte) 0x8C, (byte) 0xA5, (byte) 0x50,
112         (byte) 0x4C, (byte) 0xF2, (byte) 0xDC, (byte) 0x7B, (byte) 0x6C,
113         (byte) 0xAE, (byte) 0x14, (byte) 0x95, (byte) 0xB7, (byte) 0xE7,
114         (byte) 0xCA, (byte) 0xEB, (byte) 0xB0, (byte) 0x24, (byte) 0x5B,
115         (byte) 0xC9, (byte) 0x24, (byte) 0x2B, (byte) 0xC6, (byte) 0x96,
116         (byte) 0x99, (byte) 0xE9, (byte) 0x8B, (byte) 0x10, (byte) 0xCA,
117         (byte) 0x34, (byte) 0x2D, (byte) 0x84, (byte) 0x57, (byte) 0x09,
118         (byte) 0x4C, (byte) 0x32, (byte) 0x35, (byte) 0x68, (byte) 0x37,
119         (byte) 0x53, (byte) 0x0E, (byte) 0xF6, (byte) 0x93, (byte) 0x6C,
120         (byte) 0x86, (byte) 0x84, (byte) 0xC1, (byte) 0x44, (byte) 0x70,
121         (byte) 0x4A, (byte) 0x12, (byte) 0xAA, (byte) 0xC2, (byte) 0x9F,
122         (byte) 0x68, (byte) 0x5C, (byte) 0x42, (byte) 0xC8, (byte) 0xEB,
123         (byte) 0xD3, (byte) 0xAF, (byte) 0xD6, (byte) 0x34, (byte) 0x7F,
124         (byte) 0x9D, (byte) 0xC9, (byte) 0xE8, (byte) 0x81, (byte) 0x4A,
125         (byte) 0x5C, (byte) 0xDA, (byte) 0x36, (byte) 0x33, (byte) 0xFD,
126         (byte) 0x5C, (byte) 0x67, (byte) 0xBB, (byte) 0x91, (byte) 0x1C,
127         (byte) 0xF5, (byte) 0x21, (byte) 0xC0, (byte) 0x4E, (byte) 0x64,
128         (byte) 0x87, (byte) 0x89, (byte) 0xB6, (byte) 0x8B, (byte) 0xFD,
129         (byte) 0xDA, (byte) 0x30, (byte) 0x74, (byte) 0x1E, (byte) 0x00,
130         (byte) 0x57, (byte) 0xE1, (byte) 0x5C, (byte) 0xC4, (byte) 0xF2,
131         (byte) 0xEE, (byte) 0xF7, (byte) 0x05, (byte) 0x1C, (byte) 0xCE,
132         (byte) 0xF1, (byte) 0xCA, (byte) 0x88, (byte) 0xA0, (byte) 0x28,
133         (byte) 0x53, (byte) 0x2C, (byte) 0x84, (byte) 0xCD, (byte) 0xA3,
134         (byte) 0x6C, (byte) 0x1D, (byte) 0x15, (byte) 0x00, (byte) 0x5A,
135         (byte) 0x5D, (byte) 0x80, (byte) 0x40, (byte) 0x59, (byte) 0xE5,
136         (byte) 0xEA, (byte) 0xD1, (byte) 0x2A, (byte) 0xD6, (byte) 0x5A,
137         (byte) 0xE0, (byte) 0xE6, (byte) 0x9C, (byte) 0xEB, (byte) 0x23,
138         (byte) 0x4D, (byte) 0xD0, (byte) 0xB1, (byte) 0x27, (byte) 0xEE,
139         (byte) 0x41, (byte) 0x0D, (byte) 0xAA, (byte) 0x25, (byte) 0xBD,
140         (byte) 0xA0, (byte) 0xD0, (byte) 0x20, (byte) 0x00, (byte) 0x16,
141         (byte) 0x1F, (byte) 0x54, (byte) 0xC6, (byte) 0x4A, (byte) 0xDD,
142         (byte) 0x2A, (byte) 0x7E, (byte) 0x32, (byte) 0x43, (byte) 0x7F,
143         (byte) 0xD8, (byte) 0x74, (byte) 0x0F, (byte) 0x94, (byte) 0x88,
144         (byte) 0x3F, (byte) 0x26, (byte) 0x27, (byte) 0x54, (byte) 0x5D,
145         (byte) 0x01, (byte) 0x83, (byte) 0xAE, (byte) 0x47, (byte) 0x37,
146         (byte) 0x03, (byte) 0x6C, (byte) 0x80, (byte) 0xFD, (byte) 0x6E,
147         (byte) 0x08, (byte) 0xEB, (byte) 0xB4, (byte) 0x55, (byte) 0x81,
148         (byte) 0x13,
149     };
150     */
151 
152     // Layout:
153     // LockValue (byte) || lastNonce (byte[8]) || deviceDataHash (byte[32])
154     private byte[] storage;
155     private short storageOffset;
156     RSAPublicKey verifyingKey;
157     Signature verifier;
158     MessageDigest md_sha256;  /* For creating the lock data hash from the input. */
159     OwnerInterface globalState;
160 
161     /**
162      * Initializes the instance objects.
163      */
CarrierLock()164     public CarrierLock() {
165         try {
166             verifyingKey = (RSAPublicKey)KeyBuilder.buildKey(
167                 KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false);
168             verifyingKey.setExponent(PK_EXP, (short)0, (short)PK_EXP.length);
169             verifyingKey.setModulus(PK_MOD, (short)0, (short)PK_MOD.length);
170         } catch (CardRuntimeException e) {
171           verifyingKey = null;
172         }
173 
174         try {
175             verifier = Signature.getInstance(Signature.ALG_RSA_SHA_256_PKCS1, false);
176             verifier.init(verifyingKey, Signature.MODE_VERIFY);
177         } catch (CardRuntimeException e) {
178           verifier = null;
179         }
180         md_sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
181     }
182 
183     /**
184      * {@inheritDoc}
185      *
186      * Return the error states useful for diagnostics.
187      */
188     @Override
initialized()189     public short initialized() {
190       if (storage == null) {
191           return 1;
192       }
193       if (verifyingKey == null) {
194           return 2;
195       }
196       if (verifier == null) {
197           return 3;
198       }
199       return 0;
200     }
201     /**
202      * {@inheritDoc}
203      *
204      */
205     @Override
getStorageNeeded()206     public short getStorageNeeded() {
207         return NONCE_SIZE + DEVICE_DATA_SIZE + 1;
208     }
209 
210     /**
211      * Sets the backing store to use for state.
212      *
213      * @param globalStateOwner interface for querying global state
214      * @param extStorage  external array to use for storage
215      * @param extStorageOffset where to begin storing data
216      *
217      * This should be called before use.
218      */
219     @Override
initialize(OwnerInterface globalStateOwner, byte[] extStorage, short extStorageOffset)220     public void initialize(OwnerInterface globalStateOwner, byte[] extStorage,
221                            short extStorageOffset) {
222         globalState = globalStateOwner;
223         // Zero it first (in case we are interrupted).
224         Util.arrayFillNonAtomic(extStorage, extStorageOffset,
225                                 getStorageNeeded(), (byte) 0x00);
226         storage = extStorage;
227         storageOffset = extStorageOffset;
228     }
229 
230     /**
231      * {@inheritDoc}
232      */
233     @Override
get(byte[] lockOut, short outOffset)234     public short get(byte[] lockOut, short outOffset) {
235         if (storage == null) {
236             return 0x0001;
237         }
238         try {
239             Util.arrayCopy(storage, lockOffset(),
240                            lockOut, outOffset, (short) 1);
241         } catch (CardRuntimeException e) {
242           return 0x0002;
243         }
244         return 0;
245     }
246 
247     /**
248      * {@inheritDoc}
249      *
250      * Returns 0xffff if {@link #initialize()} has not yet been called.
251      */
252     @Override
lockOffset()253     public short lockOffset() {
254         if (storage == null) {
255             return (short) 0xffff;
256         }
257         return storageOffset;
258     }
259 
260 
261     /**
262      * {@inheritDoc}
263      *
264      * Returns 0xffff if {@link #initialize()} has not yet been called.
265      */
266     @Override
metadataOffset()267     public short metadataOffset() {
268         if (storage == null) {
269             return (short) 0xffff;
270         }
271         return (short)(storageOffset + NONCE_SIZE + 1);
272     }
273 
274     /**
275      * {@inheritDoc}
276      *
277      * Returns length of metadata.
278      *
279      * @return length of metadata.
280      */
metadataLength()281     public short metadataLength() {
282         return (short) DEVICE_DATA_SIZE;
283     }
284 
285     /**
286      * {@inheritDoc}
287      *
288      * Always returns false. Locking CarrierLock requires
289      * device data and unlocking (val=0x0) requires a signed
290      * assertion.
291      */
292     @Override
set(byte val)293     public short set(byte val) {
294         return (short)0xffff;  // Not implemented.
295     }
296 
297     /**
298      * Performs the verification of the incoming unlock token.
299      *
300      * This will check the version code, the nonce value, and the signature.
301      *
302      *
303      * @param deviceData
304      * @param deviceDataOffset
305      * @param lastNonce
306      * @param lastNonceOffset
307      * @param unlockToken
308      * @param unlockTokenOffset
309      * @param unlockTokenLength
310      * @return 0x0 on verified and an error code if not.
311      */
verifyUnlock(byte[] deviceData, short deviceDataOffset, byte[] lastNonce, short lastNonceOffset, byte[] unlockToken, short unlockTokenOffset, short unlockTokenLength)312     private short verifyUnlock(byte[] deviceData, short deviceDataOffset,
313                                byte[] lastNonce, short lastNonceOffset,
314                                byte[] unlockToken, short unlockTokenOffset,
315                                short unlockTokenLength) {
316         if (unlockTokenLength < (short)(VERSION_SIZE + NONCE_SIZE + PK_MOD.length)) {
317             return 0x0002;
318         }
319         // Only supported version is the uint64le_t 1
320         if (unlockToken[unlockTokenOffset] != VERSION) {
321             return 0x0003;
322         }
323 
324         byte[] message = JCSystem.makeTransientByteArray(
325             (short)(NONCE_SIZE + DEVICE_DATA_SIZE), JCSystem.CLEAR_ON_DESELECT);
326         // Collect the incoming nonce.
327         Util.arrayCopy(unlockToken, (short)(unlockTokenOffset + VERSION_SIZE),
328                        message, (short) 0x0, (short) NONCE_SIZE);
329         // Append the internallty stored device data.
330         Util.arrayCopy(deviceData, deviceDataOffset,
331             message, (short)NONCE_SIZE, (short) DEVICE_DATA_SIZE);
332 
333         // Verify it against the incoming signature.
334         if (verifier.verify(
335                 message, (short) 0, (short) message.length, unlockToken,
336                 (short)(unlockTokenOffset + VERSION_SIZE + NONCE_SIZE),
337                 (short)(unlockTokenLength - (VERSION_SIZE + NONCE_SIZE))) ==
338                 false) {
339             return 0x0004;
340         }
341         if (littleEndianUnsignedGreaterThan(NONCE_SIZE,
342                 unlockToken, (short)(unlockTokenOffset + VERSION_SIZE),
343                 lastNonce, lastNonceOffset) == true) {
344             return 0;
345         }
346         return 0x0005;
347     }
348 
349     /**
350      * Compares two little endian byte streams and returns
351      * true if lhs is greater than rhs.
352      *
353      * @param len number of bytes to compare
354      * @param lhs left hand size buffer
355      * @param lhsBase starting offset
356      * @param rhs right hand size buffer
357      * @param rhsBase starting offset
358      */
littleEndianUnsignedGreaterThan( byte len, byte[] lhs, short lhsBase, byte[] rhs, short rhsBase)359     private boolean littleEndianUnsignedGreaterThan(
360             byte len,
361             byte[] lhs, short lhsBase,
362             byte[] rhs, short rhsBase) {
363         // Start with the most significant byte.
364         short i = len;
365         do {
366             i -= 1;
367             if (lhs[(short)(lhsBase +i)] > rhs[(short)(rhsBase + i)]) {
368                 return true;
369             }
370             if (lhs[(short)(lhsBase +i)] < rhs[(short)(rhsBase + i)]) {
371                 return false;
372             }
373             // Only proceed if the current bytes are equal.
374         } while (i > 0);
375         return false;
376     }
377 
378 
379 
380     /**
381      * {@inheritDoc}
382      * Returns true if the lock is changed with associated metadata.
383      *
384      * If |lockValue| is non-zero, then |lockMeta| should contain a series of
385      * ASCII (or hex) values separated by short lengths.  These will be SHA256
386      * hashed together to create a "device data hash". Its use is covered next.
387      *
388      * If |lockValue| is zero, then |lockMeta| should contain the following
389      * (all little endian): 8-bit version tag (0x01) || byte[8] "64-bit nonce"
390      * || byte[] Signature(nonce||deviceDataHash) The signature is using the
391      * embedded key {@link #pkModulus} and the format is ALG_RSA_SHA_256_PKCS1.
392      * If the signature verifies using the internally stored deviceDataHash and
393      * the provided nonce, then one last check is applied.  If the nonce,
394      * treated as a little endian uint64_t, is greater than the stored nonce then
395      * it will be rejected.  Note, once unlocked, the device data hash is deleted
396      * and the CarrierLock cannot be reapplied unless the device is taken out
397      * of production mode (bootloader RMA path).
398      *
399      * If {@link #globalState} indicates that the device is not yet in production
400      * mode, then the lock values can be toggled arbitrarily.
401      * The lock values may also be changed in the bootloader or in the HLOS as
402      * the transitions are either one-way (lock) or authenticated.  It is required
403      * that the lock state is assigned prior to transitioning to production as that
404      * ensures that an unlocked device cannot be re-locked maliciously from the HLOS.
405      */
406     @Override
setWithMetadata(byte lockValue, byte[] lockMeta, short lockMetaOffset, short lockMetaLength)407     public short setWithMetadata(byte lockValue, byte[] lockMeta,
408                                  short lockMetaOffset, short lockMetaLength) {
409         if (storage == null) {
410             // TODO: move to constants.
411             return 0x0001;
412         }
413         // Ensure we don't update the nonce if we didn't go through verify.
414         short resp = (short) 0xffff;
415         if (lockValue == LOCK_UNLOCKED) {  // SHUT IT DOWN.
416             // If we're already unlocked, allow another call to make sure all the
417             // data is cleared.
418             if (storage[storageOffset] != LOCK_UNLOCKED &&
419                 globalState.production() == true) {
420                 // RSA PKCS#1 signature should be the same length as the modulus but we'll allow it to
421                 // be larger because ???. XXX TODO
422                 resp = verifyUnlock(storage, (short)(storageOffset + 1 + NONCE_SIZE),
423                                     storage, (short)(storageOffset + 1),
424                                     lockMeta, lockMetaOffset, lockMetaLength);
425                 if (resp != (short) 0) {
426                   return resp;
427                 }
428             }
429             JCSystem.beginTransaction();
430             storage[storageOffset] = lockValue;
431             // Update the monotonically increasing "nonce" value.
432             // Note that the nonce is only ever updated if a signed value
433             // was seen or if we're not production() to assure it doesn't get
434             // rolled forward.
435             if (resp == 0) {
436                 Util.arrayCopy(lockMeta, (short)(VERSION_SIZE + lockMetaOffset),
437                                storage, (short)(1 + storageOffset),
438                                (short)NONCE_SIZE);
439             }
440             // Delete the device-unique data.
441             Util.arrayFillNonAtomic(storage, (short)(NONCE_SIZE + 1 + storageOffset),
442                 (short)DEVICE_DATA_SIZE, (byte)0x00);
443             JCSystem.commitTransaction();
444         } else {  // Locking. Expect a lockMeta of the device data.
445             if (globalState.production() == true) {
446                 // Locking can only be done prior to production.
447                 return 0x0006;
448             }
449             md_sha256.reset();
450             JCSystem.beginTransaction();
451             // Hash all the input data and store the result as the device data
452             // digest.
453             md_sha256.doFinal(lockMeta, lockMetaOffset, lockMetaLength,
454                               storage, metadataOffset());
455             // Note that we never clear or overwrite the nonce.
456             storage[storageOffset] = lockValue;
457             JCSystem.commitTransaction();
458         }
459         return 0x0000;
460     }
461 
462     /**
463      * Given all the data, tests if the key actually works.
464      *
465      * buffer should contain:
466      *   fakeLastNonce | fakeDeviceData | version (8) | testNonce | signature
467      *
468      * @param buffer Array with the test data.
469      * @param offset offset into the buffer.
470      * @param length total length from offset.
471      * @return 0x0 on verify and an error code otherwise.
472      */
testVector(byte[] buffer, short offset, short length)473     public short testVector(byte[] buffer, short offset, short length) {
474         return verifyUnlock(buffer, (short)(offset + NONCE_SIZE), // device data
475                             buffer, offset,  // fake last nonce.
476                             // unlock data
477                             buffer, (short)(offset + NONCE_SIZE + DEVICE_DATA_SIZE),
478                             (short)(length - (NONCE_SIZE + DEVICE_DATA_SIZE)));
479     }
480 
481     /**
482      * {@inheritDoc}
483      */
484     @Override
backupSize()485     public short backupSize() {
486         return getStorageNeeded();
487     }
488 
489 
490     /**
491      * {@inheritDoc}
492      */
493     @Override
backup(byte[] outBytes, short outBytesOffset)494     public short backup(byte[] outBytes, short outBytesOffset) {
495         Util.arrayCopy(storage, storageOffset,
496                        outBytes, outBytesOffset,
497                        backupSize());
498         return backupSize();
499     }
500 
501     /**
502      * {@inheritDoc}
503      */
504     @Override
restore(byte[] inBytes, short inBytesOffset, short inBytesLength)505     public boolean restore(byte[] inBytes, short inBytesOffset,
506                            short inBytesLength) {
507         if (inBytesLength > backupSize() || inBytesLength == (short)0) {
508             return false;
509         }
510         Util.arrayCopy(inBytes, inBytesOffset,
511                        storage, storageOffset,
512                        inBytesLength);
513         return true;
514     }
515 
516 
517 }
518