Home | History | Annotate | Download | only in storage
      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      */
    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
    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
    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
    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
    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
    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
    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      */
    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
    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      */
    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      */
    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
    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      */
    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
    485     public short backupSize() {
    486         return getStorageNeeded();
    487     }
    488 
    489 
    490     /**
    491      * {@inheritDoc}
    492      */
    493     @Override
    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
    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