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.AID;
     20 import javacard.framework.CardRuntimeException;
     21 import javacard.framework.JCSystem;
     22 import javacard.framework.Shareable;
     23 import javacard.framework.Util;
     24 
     25 import com.nxp.ls.library.LSBackup;
     26 import com.nxp.ls.library.LSPullModeRestore;
     27 import com.nxp.ls.library.LSPushModeBackup;
     28 
     29 import com.android.verifiedboot.storage.DefaultOsBackupImpl;
     30 import com.android.verifiedboot.storage.OsBackupInterface;
     31 
     32 public class JcopBackupImpl extends DefaultOsBackupImpl implements LSBackup {
     33     final public static short MAGIC = (short)0xdeed;
     34 
     35     // From NXP, the AID of the LoaderService.
     36     private static final byte[] LS_AID = {
     37         // NXP RID
     38         (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x96,
     39         // NXP JCOP Applets
     40         (byte)0x54, (byte)0x43, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
     41         // Family
     42         (byte)0x00, (byte)0x0B,
     43         // Version
     44         (byte)0x00, // LS Application Instance
     45         // Type
     46         (byte)0x01, // LS Application
     47     };
     48 
     49 
     50     /**
     51      * Returns true on a successful reimport of data.
     52      *
     53      * @param iarray to read from
     54      * @param offset to begin copying from.
     55      */
     56     @Override
     57     public boolean restore(byte[] in, short offset) {
     58         LSPullModeRestore restore = getLSPullModeRestore();
     59         offset = (short) 0;
     60         if (restore == null) {
     61             return false;
     62         }
     63         if (restore.start() == (short) 0) {
     64             return false;
     65         }
     66         short length = (short) 5;
     67         if (restore.pullData(in, offset, length) == false) {
     68             return false;
     69         }
     70         byte tag = in[0];
     71         if (tag != TAG_MAGIC) {
     72             return false;
     73         }
     74         if (Util.getShort(in, (short)1) != (short)2) {
     75             return false;
     76         }
     77         if (Util.getShort(in, (short)3) != MAGIC) {
     78             return false;
     79         }
     80         // Magic is good. Let's process all the tags. They should be
     81         // serialized in order and if not, we abort.
     82         BackupInterface[] objects = tracked();
     83         short i = (short) 0;
     84         for ( ; i < objects.length; ++i) {
     85             // Get tag and length at the same time.
     86             length = 3;
     87             if (restore.pullData(in, (short)0, length) == false) {
     88                 return false;
     89             }
     90             tag = in[0];
     91             length = Util.getShort(in, (short)1);
     92             if (restore.pullData(in, (short)0, length) == false) {
     93                 return false;
     94             }
     95             if (tag == i && objects[i] != null) {
     96                 objects[i].restore(in, (short)0, length);
     97             } // else we skip it.
     98         }
     99 
    100         if (restore.end() == false) {
    101             return false;
    102         }
    103         return true;
    104     }
    105 
    106     /**
    107      * Retrieve the restore interface from the LoaderService.
    108      *
    109      * @return LSPullModeRestore interface or null
    110      */
    111     private static LSPullModeRestore getLSPullModeRestore() {
    112         try {
    113           return (LSPullModeRestore)JCSystem.getAppletShareableInterfaceObject(
    114             JCSystem.lookupAID(LS_AID, (short)(0), (byte)(LS_AID.length)),
    115             LSPullModeRestore.LS_PULL_MODE_RESTORE_PARAMETER);
    116         } catch (CardRuntimeException e) {
    117             return null;
    118         }
    119     }
    120 
    121     /**
    122      * Called via LSBackup for saving off data prior to an update.
    123      * Only lockStorage has to be stored, but it means that install() would
    124      * need to handle any changes in lock sizes.
    125      *
    126      * TODO(wad) In each LockInterface tag store with last metadataSize.
    127      *
    128      * @param backup interface to feed data to
    129      * @param buffer working buffer that is shared with LSPushModeBackup
    130      * @return true on success or false if there is a failure.
    131      */
    132     public boolean backup(LSPushModeBackup backup, byte[] buffer) {
    133         BackupInterface[] objects = tracked();
    134         short length = (short) 5;  // magic(TAG, SIZE, MAGIC)
    135         short i;
    136         for (i = (short)0; i < (short)objects.length; ++i) {
    137             length += 3;  // tag, length
    138             if (objects[i] != null) {
    139                 length += objects[i].backupSize();
    140             }
    141         }
    142         // Interface requires mod 16.
    143         if (length % 16 != 0) {
    144           length += (16 - (length % 16));
    145         }
    146         if (backup.start(length) == false) {
    147             return false;
    148         }
    149         // Set magic
    150         short offset = (short) 0;
    151         buffer[offset++] = TAG_MAGIC;
    152         Util.setShort(buffer, offset, (short)2);
    153         offset += 2;
    154         Util.setShort(buffer, offset, MAGIC);
    155         offset += 2;
    156 
    157         for (i = (short)0; i < (short)objects.length; ++i) {
    158             buffer[offset++] = (byte) i;  // TAG == index.
    159             if (objects[i] != null) {
    160                 Util.setShort(buffer, offset, objects[i].backupSize());
    161             } else {
    162                 Util.setShort(buffer, offset, (short)0);
    163             }
    164             offset += 2;
    165             if (objects[i] != null) {
    166                 offset += objects[i].backup(buffer, offset);
    167             }
    168         }
    169         // TODO(wad) Worth checking if offset != length.
    170         if (backup.pushData(buffer, (short)0, length) == false) {
    171             return false;
    172         }
    173         return backup.end();
    174     }
    175 
    176     /**
    177      * {@inheritDoc}
    178      *
    179      * Checks for the calling LoaderService applet first.
    180      */
    181     @Override
    182     public Shareable getShareableInterfaceObject(AID clientAid, byte arg) {
    183         AID lsAid = JCSystem.lookupAID(LS_AID, (short)(0), (byte)(LS_AID.length));
    184         if (clientAid.equals(lsAid)) {
    185             if (arg == LSBackup.LS_BACKUP_PARAMETER) {
    186                 return this;
    187             }
    188         }
    189         return null;
    190     }
    191 }
    192