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