/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (c) 2015-2017, The Linux Foundation.
*/
/*
* Copyright (C) 2011 Deutsche Telekom, A.G.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Contributed by: Giesecke & Devrient GmbH.
*/
package com.android.se.security.arf.pkcs15;
import android.util.Log;
import com.android.se.internal.ByteArrayConverter;
import com.android.se.internal.Util;
import com.android.se.security.arf.DERParser;
import com.android.se.security.arf.SecureElement;
import com.android.se.security.arf.SecureElementException;
import java.io.IOException;
/** EF_ODF related features */
public class EFODF extends EF {
// Standardized ID for EF_ODF file
public static final byte[] EFODF_PATH = {0x50, 0x31};
public final String mTag = "SecureElement-ARF-EFODF";
byte[] mCDFPath = null;
/**
* Constructor
*
* @param secureElement SE on which ISO7816 commands are applied
*/
public EFODF(SecureElement handle) {
super(handle);
}
/**
* Decodes EF_ODF file
*
* @param buffer ASN.1 data
* @return Path to "EF_DODF" from "DODF Tag" entry; null
otherwise
*/
private byte[] decodeDER(byte[] buffer) throws PKCS15Exception {
DERParser der = new DERParser(buffer);
while (!der.isEndofBuffer()) {
if (der.parseTLV() == (byte) 0xA5) { // CDF
mCDFPath = der.parsePathAttributes();
Log.i(
mTag,
"ODF content found mCDFPath :" + ByteArrayConverter.byteArrayToHexString(
mCDFPath));
} else {
der.skipTLVData();
}
}
DERParser der2 = new DERParser(buffer);
while (!der2.isEndofBuffer()) {
if (der2.parseTLV() == (byte) 0xA7) { // DODF
return der2.parsePathAttributes();
} else {
der2.skipTLVData();
}
}
return null;
}
public byte[] getCDFPath() {
return mCDFPath;
}
/**
* Selects and Analyses EF_ODF file
*
* @return Path to "EF_DODF" from "DODF Tag" entry; null
otherwise
*/
public byte[] analyseFile(byte[] pkcs15Path) throws IOException, PKCS15Exception,
SecureElementException {
Log.i(mTag, "Analysing EF_ODF...");
// 2012-04-12
// extend path if ODF path was determined from EF DIR.
byte[] path = null;
if (pkcs15Path != null) {
path = new byte[pkcs15Path.length + EFODF_PATH.length];
System.arraycopy(pkcs15Path, 0, path, 0, pkcs15Path.length);
System.arraycopy(EFODF_PATH, 0, path, pkcs15Path.length, EFODF_PATH.length);
} else {
path = EFODF_PATH;
}
// ---
if (selectFile(path) != APDU_SUCCESS) {
// let's give it another try..
try {
synchronized (this) {
wait(1000);
}
} catch (InterruptedException e) {
Log.e(mTag, "Interupted while waiting for EF_ODF : " + e);
}
if (selectFile(path) != APDU_SUCCESS) throw new PKCS15Exception("EF_ODF not found!!");
}
return decodeDER(readBinary(0, Util.END));
}
}