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