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 * Copyright (c) 2017, The Linux Foundation. 18 */ 19 20 /* 21 * Copyright 2012 Giesecke & Devrient GmbH. 22 * 23 * Licensed under the Apache License, Version 2.0 (the "License"); 24 * you may not use this file except in compliance with the License. 25 * You may obtain a copy of the License at 26 * 27 * http://www.apache.org/licenses/LICENSE-2.0 28 * 29 * Unless required by applicable law or agreed to in writing, software 30 * distributed under the License is distributed on an "AS IS" BASIS, 31 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 * See the License for the specific language governing permissions and 33 * limitations under the License. 34 */ 35 package com.android.se.security.gpac; 36 37 import java.io.ByteArrayOutputStream; 38 import java.io.IOException; 39 40 /** 41 * This class represents the Access rule data object (AR-DO), according to GP Secure Element Control 42 * Access. 43 * 44 * <p>The AR-DO contains one or two access rules of type APDU or NFC. 45 */ 46 public class AR_DO extends BerTlv { 47 48 public static final int TAG = 0xE3; 49 50 private APDU_AR_DO mApduAr = null; 51 private NFC_AR_DO mNfcAr = null; 52 private PERM_AR_DO mPermAr = null; 53 AR_DO(byte[] rawData, int valueIndex, int valueLength)54 public AR_DO(byte[] rawData, int valueIndex, int valueLength) { 55 super(rawData, TAG, valueIndex, valueLength); 56 } 57 AR_DO(APDU_AR_DO apduArDo, NFC_AR_DO nfcArDo, PERM_AR_DO permArDo)58 public AR_DO(APDU_AR_DO apduArDo, NFC_AR_DO nfcArDo, PERM_AR_DO permArDo) { 59 super(null, TAG, 0, 0); 60 mApduAr = apduArDo; 61 mNfcAr = nfcArDo; 62 mPermAr = permArDo; 63 } 64 AR_DO(APDU_AR_DO apduArDo, NFC_AR_DO nfcArDo)65 public AR_DO(APDU_AR_DO apduArDo, NFC_AR_DO nfcArDo) { 66 super(null, TAG, 0, 0); 67 mApduAr = apduArDo; 68 mNfcAr = nfcArDo; 69 mPermAr = null; 70 } 71 AR_DO(PERM_AR_DO permArDo)72 public AR_DO(PERM_AR_DO permArDo) { 73 super(null, TAG, 0, 0); 74 mApduAr = null; 75 mNfcAr = null; 76 mPermAr = permArDo; 77 } 78 getApduArDo()79 public APDU_AR_DO getApduArDo() { 80 return mApduAr; 81 } 82 getNfcArDo()83 public NFC_AR_DO getNfcArDo() { 84 return mNfcAr; 85 } 86 getPermArDo()87 public PERM_AR_DO getPermArDo() { 88 return mPermAr; 89 } 90 91 @Override 92 /** 93 * Interpret value. 94 * 95 * <p>Tag: E3 96 * 97 * <p>Value: 98 * 1. Value can contain APDU-AR-DO or NFC-AR-DO or APDU-AR-DO | NFC-AR-DO A 99 * concatenation of one or two AR-DO(s). If two AR-DO(s) are present these must have 100 * different types. 101 * 2. PERM-AR-DO 102 */ interpret()103 public void interpret() throws ParserException { 104 105 this.mApduAr = null; 106 this.mNfcAr = null; 107 this.mPermAr = null; 108 109 byte[] data = getRawData(); 110 int index = getValueIndex(); 111 112 if (index + getValueLength() > data.length) { 113 throw new ParserException("Not enough data for AR_DO!"); 114 } 115 116 do { 117 BerTlv temp = BerTlv.decode(data, index); 118 119 if (temp.getTag() == APDU_AR_DO.TAG) { // APDU-AR-DO 120 mApduAr = new APDU_AR_DO(data, temp.getValueIndex(), temp.getValueLength()); 121 mApduAr.interpret(); 122 } else if (temp.getTag() == NFC_AR_DO.TAG) { // NFC-AR-DO 123 mNfcAr = new NFC_AR_DO(data, temp.getValueIndex(), temp.getValueLength()); 124 mNfcAr.interpret(); 125 } else if (temp.getTag() == PERM_AR_DO.TAG) { // PERM-AR-DO 126 mPermAr = new PERM_AR_DO(data, temp.getValueIndex(), temp.getValueLength()); 127 mPermAr.interpret(); 128 } else { 129 // un-comment following line if a more restrictive 130 // behavior is necessary. 131 // throw new ParserException("Invalid DO in AR-DO!"); 132 } 133 index = temp.getValueIndex() + temp.getValueLength(); 134 } while (getValueIndex() + getValueLength() > index); 135 136 if (mApduAr == null && mNfcAr == null && mPermAr == null) { 137 throw new ParserException("No valid DO in AR-DO!"); 138 } 139 } 140 141 @Override 142 /** 143 * Interpret value. 144 * 145 * <p>Tag: E3 146 * 147 * <p>Value: 148 * 1. Value can contain APDU-AR-DO or NFC-AR-DO or APDU-AR-DO | NFC-AR-DO A 149 * concatenation of one or two AR-DO(s). If two AR-DO(s) are present these must have 150 * different types. 151 * 2. PERM-AR-DO 152 */ build(ByteArrayOutputStream stream)153 public void build(ByteArrayOutputStream stream) throws DO_Exception { 154 155 // write tag 156 stream.write(getTag()); 157 158 ByteArrayOutputStream temp = new ByteArrayOutputStream(); 159 if (mApduAr != null) { 160 mApduAr.build(temp); 161 } 162 163 if (mNfcAr != null) { 164 mNfcAr.build(temp); 165 } 166 167 if (mPermAr != null) { 168 mPermAr.build(temp); 169 } 170 171 BerTlv.encodeLength(temp.size(), stream); 172 try { 173 stream.write(temp.toByteArray()); 174 } catch (IOException e) { 175 throw new DO_Exception("AR-DO Memory IO problem! " + e.getMessage()); 176 } 177 } 178 } 179