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) 2015-2017, The Linux Foundation. 18 */ 19 20 /* 21 * Copyright (C) 2011 Deutsche Telekom, A.G. 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 36 package com.android.se.security.arf; 37 38 import android.util.Log; 39 40 import com.android.se.security.arf.pkcs15.PKCS15Exception; 41 42 import java.util.Arrays; 43 44 /** Base class for parsing PKCS#15 files */ 45 public class DERParser { 46 public final String mTag = "SecureElement-DERParser"; 47 // DER parameters 48 private byte[] mDERBuffer; 49 private short mDERSize, mDERIndex, mTLVDataSize = 0; 50 DERParser(byte[] buffer)51 public DERParser(byte[] buffer) throws PKCS15Exception { 52 mDERBuffer = buffer; 53 mDERIndex = 0; 54 mDERSize = 0; 55 if (mDERBuffer == null) return; 56 mDERSize = (short) mDERBuffer.length; 57 mTLVDataSize = mDERSize; 58 59 if (mDERSize == 0) return; 60 // Remove padding 61 if (mDERBuffer[mDERIndex] == ASN1.TAG_Padding) { 62 mTLVDataSize = 0; 63 while (++mDERIndex < mDERSize) { 64 if (mDERBuffer[mDERIndex] != ASN1.TAG_Padding) { 65 throw new PKCS15Exception("[Parser] Incorrect file format"); 66 } 67 } 68 } 69 } 70 71 /** 72 * Returns "Base 128" encoded integer 73 * 74 * @return Converted integer 75 */ readIntBase128()76 private int readIntBase128() { 77 int value = 0; 78 // If the MSb is set to 0, it is the last byte 79 do { 80 value = (value << 7) + (mDERBuffer[mDERIndex] & 0x7F); 81 } while ((mDERBuffer[mDERIndex++] & 0x80) != 0); 82 return value; 83 } 84 85 /** 86 * Returns size of the TLV encoded value 87 * 88 * @return Size of the TLV 89 */ getTLVSize()90 private short getTLVSize() throws PKCS15Exception { 91 int size, TLVSize = 0; 92 93 if (isEndofBuffer()) throw new PKCS15Exception("[Parser] Cannot retreive size"); 94 // Determine data size 95 if ((TLVSize = (mDERBuffer[mDERIndex++] & 0xff)) >= 128) { 96 size = TLVSize - 128; 97 for (TLVSize = 0; size > 0; size--) { 98 if (!isEndofBuffer()) { 99 TLVSize = (TLVSize << 8) + (mDERBuffer[mDERIndex++] & 0xff); 100 } else { 101 throw new PKCS15Exception("[Parser] Cannot retreive size"); 102 } 103 } 104 } 105 106 // Check if the buffer contains enough data 107 if ((mDERIndex + TLVSize) > mDERSize) throw new PKCS15Exception("[Parser] Not enough data"); 108 return (short) TLVSize; 109 } 110 111 /** 112 * Returns type of the TLV encoded value 113 * 114 * @return Type of the TLV 115 */ getTLVType()116 private byte getTLVType() throws PKCS15Exception { 117 if (isEndofBuffer()) throw new PKCS15Exception("[Parser] Cannot retreive type"); 118 return mDERBuffer[mDERIndex++]; 119 } 120 121 /** 122 * Determines if we reached the end of the buffer 123 * 124 * @return True if end of buffer is reached; False otherwise 125 */ isEndofBuffer()126 public boolean isEndofBuffer() throws PKCS15Exception { 127 if (mDERIndex == mDERSize) return true; 128 if (mDERBuffer[mDERIndex] == ASN1.TAG_Padding) { 129 // Remove padding 130 while (++mDERIndex < mDERSize) { 131 if (mDERBuffer[mDERIndex] != ASN1.TAG_Padding) { 132 throw new PKCS15Exception("[Parser] Incorrect file format"); 133 } 134 } 135 return true; 136 } 137 return false; 138 } 139 140 /** 141 * Parses TLV from current index 142 * 143 * @return Type of TLV structure 144 */ parseTLV()145 public byte parseTLV() throws PKCS15Exception { 146 byte type = getTLVType(); 147 mTLVDataSize = getTLVSize(); 148 return type; 149 } 150 151 /** 152 * Parses TLV from current index and check if type is correct 153 * 154 * @param type Type required 155 * @return Length of TLV data structure 156 */ parseTLV(byte type)157 public short parseTLV(byte type) throws PKCS15Exception { 158 byte typeInBuffer = getTLVType(); 159 if (typeInBuffer == type) { 160 mTLVDataSize = getTLVSize(); 161 } else { 162 Log.e(mTag, "parseTLV expected: " + type + " got:" + typeInBuffer); 163 Log.e(mTag, "parseTLV mDERIndex: " + mDERIndex + " mDERSize:" + mDERSize); 164 throw new PKCS15Exception("[Parser] Unexpected type"); 165 } 166 return mTLVDataSize; 167 } 168 169 /** Skips data of the current TLV structure */ skipTLVData()170 public void skipTLVData() { 171 mDERIndex += mTLVDataSize; 172 } 173 174 /** 175 * Returns data of the current TLV structure 176 * 177 * @return Data of current TLV structure 178 */ getTLVData()179 public byte[] getTLVData() { 180 byte[] data = Arrays.copyOfRange(mDERBuffer, mDERIndex, mDERIndex + mTLVDataSize); 181 mDERIndex += mTLVDataSize; 182 return data; 183 } 184 185 /** 186 * Takes snaptshot of the current context 187 * 188 * @return Saved context 189 */ saveContext()190 public short[] saveContext() { 191 short[] context = new short[2]; 192 context[0] = mDERIndex; 193 context[1] = mTLVDataSize; 194 return context; 195 } 196 197 /** 198 * Restores a context from a snapshot previously saved 199 * 200 * @param context Context snapshot 201 */ restoreContext(short[] context)202 public void restoreContext(short[] context) throws PKCS15Exception { 203 if ((context == null) || (context.length != 2)) { 204 throw new PKCS15Exception("[Parser] Invalid context"); 205 } 206 if ((context[0] < 0) || (context[0] > mDERSize)) { 207 throw new PKCS15Exception("[Parser] Index out of bound"); 208 } 209 mDERIndex = context[0]; 210 mTLVDataSize = context[1]; 211 } 212 213 /** 214 * Parses standardized OID 215 * 216 * @return String containing OID 217 */ parseOID()218 public String parseOID() throws PKCS15Exception { 219 if (parseTLV(ASN1.TAG_OID) == 0) throw new PKCS15Exception("[Parser] OID Length is null"); 220 221 int end = mDERIndex + mTLVDataSize; 222 StringBuffer oid = new StringBuffer(); 223 224 // First subidentifier 225 int subid = readIntBase128(); 226 // The first subidentifier contains the first two OID components 227 // X.Y is encoded as (X*40)+Y (0<=X<=2 and 0<=Y<=39 for X=0 or X=1) 228 if (subid <= 79) { 229 oid.append(subid / 40).append('.').append(subid % 40); 230 } else { 231 oid.append("2.").append(subid - 80); 232 } 233 234 while (mDERIndex < end) oid.append('.').append(readIntBase128()); 235 Log.i(mTag, "Found OID: " + oid.toString()); 236 return oid.toString(); 237 } 238 239 /** 240 * Parses PKCS#15 path attribute 241 * 242 * @return Path retreived from the attribute 243 */ parsePathAttributes()244 public byte[] parsePathAttributes() throws PKCS15Exception { 245 parseTLV(ASN1.TAG_Sequence); 246 parseTLV(ASN1.TAG_OctetString); 247 return getTLVData(); 248 } 249 } 250