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.Util;
     21 
     22 import com.android.verifiedboot.storage.BackupInterface;
     23 import com.android.verifiedboot.globalstate.owner.OwnerInterface;
     24 
     25 class VersionStorage implements BackupInterface {
     26     final public static byte NUM_SLOTS = (byte) 8;
     27     final public static byte SLOT_BYTES = (byte) 8;
     28     final private static byte EXPORT_VERSION = (byte)0x01;
     29     private OwnerInterface globalState;
     30     private byte[] storage;
     31 
     32     public VersionStorage(OwnerInterface globalStateRef) {
     33       storage = new byte[NUM_SLOTS * SLOT_BYTES];
     34       globalState = globalStateRef;
     35       Util.arrayFillNonAtomic(storage, (short) 0, (short) storage.length, (byte) 0x00);
     36     }
     37 
     38     /**
     39      * Copies content from the given slot in |out| and returns true.
     40      *
     41      * @param slot slot number to retrieve
     42      * @param out array to copy the slot data to.
     43      * @param oOffset offset into |out| to start the copy at.
     44      * @return 0x0 on success and an error otherwise.
     45      */
     46     public short getSlot(byte slot, byte[] out, short oOffset) {
     47         if (slot > NUM_SLOTS - 1) {
     48             return 0x0001;
     49         }
     50         try {
     51             Util.arrayCopy(storage, (short)(SLOT_BYTES * slot),
     52                          out, oOffset, SLOT_BYTES);
     53         } catch (CardRuntimeException e) {
     54             return 0x0002;
     55         }
     56         return 0x0;
     57     }
     58 
     59     /**
     60      * Copies content for the given slot from |in| and returns true.
     61      *
     62      * @param slot slot number to retrieve
     63      * @param in array to copy the slot data from.
     64      * @param iOffset into |in| to start the copy at.
     65      * @return 0x0 on success or an error code.
     66      */
     67     public short setSlot(byte slot, byte[] in, short iOffset) {
     68         if (slot > NUM_SLOTS - 1) {
     69             return 0x0001;
     70         }
     71         // Slots can be set only if we're in the bootloader
     72         // or we're not yet in production.
     73         if (globalState.production() == true &&
     74             globalState.inBootloader() == false) {
     75             return 0x0003;
     76         }
     77         try {
     78             Util.arrayCopy(in, iOffset,
     79                      storage, (short)(SLOT_BYTES * slot), SLOT_BYTES);
     80         } catch (CardRuntimeException e) {
     81             return 0x0002;
     82         }
     83         return 0;
     84     }
     85 
     86     /**
     87      * {@inheritDoc}
     88      *
     89      * Checks the size and version prefix prior to copying.
     90      */
     91     @Override
     92     public boolean restore(byte[] inBytes, short inBytesOffset, short inBytesLength) {
     93         if (inBytesLength == (short) 0 ||
     94             inBytesLength > (short)(storage.length + 1)) {
     95             return false;
     96         }
     97         if (inBytes[0] != EXPORT_VERSION) {
     98             return false;
     99         }
    100         try {
    101             Util.arrayCopy(inBytes, inBytesOffset, storage, (short) 0, inBytesLength);
    102         } catch (CardRuntimeException e) {
    103             return false;
    104         }
    105         return true;
    106     }
    107 
    108     /**
    109      * {@inheritDoc}
    110      *
    111      * Copies storage to outBytes with a leading version byte which can be
    112      * checked on restore.
    113      */
    114     @Override
    115     public short backup(byte[] outBytes, short outBytesOffset) {
    116         try {
    117             // Tag the export version that way if any internal storage format changes
    118             // occur, they can be handled.
    119             outBytes[(short)(outBytesOffset + 1)] = EXPORT_VERSION;
    120             Util.arrayCopy(storage, (short) 0, outBytes, (short)(outBytesOffset + 1),
    121                            (short)storage.length);
    122             return (short)(storage.length + 1);
    123         } catch (CardRuntimeException e) {
    124             return 0x0;
    125         }
    126     }
    127 
    128     /**
    129      * {@inheritDoc}
    130      */
    131     @Override
    132     public short backupSize() {
    133       return (short)(storage.length + 1);
    134     }
    135 }
    136