Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 268 additions & 52 deletions Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public short getIssuer() {
return 0;
}

@Override
public boolean isKeyAgreementSupported() {
return false;
}

private short getProvisionedCertificateData(KMSEProvider kmseProvider, byte dataType) {
short len = seProvider.getProvisionedDataLength(dataType);
if (len == 0) {
Expand All @@ -169,4 +174,28 @@ private short getProvisionedCertificateData(KMSEProvider kmseProvider, byte data
return ptr;
}

@Override
public short getConfirmationToken(short confToken, short keyParams) {
short cToken =
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.CONFIRMATION_TOKEN, keyParams);
if (cToken == KMType.INVALID_VALUE) {
KMException.throwIt(KMError.NO_USER_CONFIRMATION);
}
return KMByteTag.cast(cToken).getValue();
}

@Override
public short getKMVerificationTokenExp() {
return KMVerificationToken.exp2();
}

@Override
public short getMacFromVerificationToken(short verToken) {
return KMVerificationToken.cast(verToken).getMac((short)0x04);
}

@Override
public boolean isAttestSupportedInImport() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,32 @@ public short getNotBefore(short params) {
public short getIssuer() {
return 0;
}

@Override
public boolean isKeyAgreementSupported() {
return true;
}

@Override
public short getConfirmationToken(short confToken, short keyParams) {
if (0 == KMByteBlob.cast(confToken).length()) {
KMException.throwIt(KMError.NO_USER_CONFIRMATION);
}
return confToken;
}

@Override
public short getKMVerificationTokenExp() {
return KMVerificationToken.exp1();
}

@Override
public short getMacFromVerificationToken(short verToken) {
return KMVerificationToken.cast(verToken).getMac((short)0x02);
}

@Override
public boolean isAttestSupportedInImport() {
return true;
}
}
10 changes: 10 additions & 0 deletions Applet/src/com/android/javacard/keymaster/KMSpecification.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,14 @@ KMAttestationCert makeCommonCert(short swParams, short hwParams, short keyParams
short getNotBefore(short params);

short getIssuer();

boolean isKeyAgreementSupported();

short getConfirmationToken(short confToken, short keyParams);

short getKMVerificationTokenExp();

short getMacFromVerificationToken(short verToken);

boolean isAttestSupportedInImport();
}
50 changes: 34 additions & 16 deletions Applet/src/com/android/javacard/keymaster/KMVerificationToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,34 @@ public class KMVerificationToken extends KMType {

public static final byte CHALLENGE = 0x00;
public static final byte TIMESTAMP = 0x01;
public static final byte MAC = 0x02;
public static final byte PARAMETERS_VERIFIED = 0x02;
public static final byte SECURITY_LEVEL = 0x03;
public static final byte MAC1 = 0x02;
public static final byte MAC2 = 0x04;

private static KMVerificationToken prototype;

private KMVerificationToken() {
}

public static short exp() {
public static short exp1() {
short arrPtr = KMArray.instance((short) 3);
KMArray arr = KMArray.cast(arrPtr);
arr.add(CHALLENGE, KMInteger.exp());
arr.add(TIMESTAMP, KMInteger.exp());
arr.add(MAC, KMByteBlob.exp());
arr.add(MAC1, KMByteBlob.exp());
return instance(arrPtr);
}

public static short exp2() {
short arrPtr = KMArray.instance((short) 5);
KMArray arr = KMArray.cast(arrPtr);
arr.add(CHALLENGE, KMInteger.exp());
arr.add(TIMESTAMP, KMInteger.exp());
//arr.add(PARAMETERS_VERIFIED, KMKeyParameters.exp());
arr.add(PARAMETERS_VERIFIED, KMByteBlob.exp());
arr.add(SECURITY_LEVEL, KMEnum.instance(KMType.HARDWARE_TYPE));
arr.add(MAC2, KMByteBlob.exp());
return instance(arrPtr);
}

Expand All @@ -55,18 +70,28 @@ private static KMVerificationToken proto(short ptr) {
return prototype;
}

public static short instance() {
public static short instance1() {
short arrPtr = KMArray.instance((short) 3);
KMArray arr = KMArray.cast(arrPtr);
arr.add(CHALLENGE, KMInteger.uint_16((short) 0));
arr.add(TIMESTAMP, KMInteger.uint_16((short) 0));
arr.add(MAC, KMByteBlob.instance((short) 0));
arr.add(MAC1, KMByteBlob.instance((short) 0));
return instance(arrPtr);
}

public static short instance2() {
short arrPtr = KMArray.instance((short) 5);
KMArray arr = KMArray.cast(arrPtr);
arr.add(CHALLENGE, KMInteger.uint_16((short) 0));
arr.add(TIMESTAMP, KMInteger.uint_16((short) 0));
arr.add(PARAMETERS_VERIFIED, KMByteBlob.instance((short) 0));
arr.add(SECURITY_LEVEL, KMEnum.instance(KMType.HARDWARE_TYPE, KMType.STRONGBOX));
arr.add(MAC2, KMByteBlob.instance((short) 0));
return instance(arrPtr);
}

public static short instance(short vals) {
KMArray arr = KMArray.cast(vals);
if (arr.length() != 3) {
if (arr.length() != 3 && arr.length() != 5) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
short ptr = KMType.instance(VERIFICATION_TOKEN_TYPE, (short) 2);
Expand Down Expand Up @@ -116,15 +141,8 @@ public void setTimestamp(short vals) {
KMArray.cast(arrPtr).add(TIMESTAMP, vals);
}

public short getMac() {
public short getMac(short macIndex) {
short arrPtr = getVals();
return KMArray.cast(arrPtr).get(MAC);
return KMArray.cast(arrPtr).get(macIndex);
}

public void setMac(short vals) {
KMByteBlob.cast(vals);
short arrPtr = getVals();
KMArray.cast(arrPtr).add(MAC, vals);
}

}
36 changes: 21 additions & 15 deletions Keymaster_HAL/keymaster/4.1/JavacardKeymaster4Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ Return<void> JavacardKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, ret) = decodeData(cborConverter_, std::vector<uint8_t>(resp.begin(), resp.end()-2),
false, oprCtx_);
if (item != nullptr) {
if (ret == ErrorCode::OK) {
std::vector<uint8_t> temp;
if(!cborConverter_.getUint64(item, 0, securityLevel) ||
!cborConverter_.getBinaryArray(item, 1, jcKeymasterName) ||
Expand Down Expand Up @@ -494,7 +494,7 @@ Return<void> JavacardKeymaster4Device::getHmacSharingParameters(getHmacSharingPa
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborData.begin(), cborData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getHmacSharingParameters(item, 1, hmacSharingParameters)) {
LOG(ERROR) << "javacard strongbox : Failed to convert cbor data of INS_GET_HMAC_SHARING_PARAM_CMD";
errorCode = ErrorCode::UNKNOWN_ERROR;
Expand Down Expand Up @@ -555,7 +555,7 @@ Return<void> JavacardKeymaster4Device::computeSharedHmac(const hidl_vec<HmacShar
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
std::vector<uint8_t> bstr;
if(!cborConverter_.getBinaryArray(item, 1, bstr)) {
LOG(ERROR) << "INS_COMPUTE_SHARED_HMAC_CMD: failed to convert cbor sharing check value";
Expand Down Expand Up @@ -626,7 +626,7 @@ Return<void> JavacardKeymaster4Device::generateKey(const hidl_vec<KeyParameter>&
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getBinaryArray(item, 1, keyBlob) ||
!cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) {
//Clear the buffer.
Expand All @@ -649,6 +649,7 @@ Return<void> JavacardKeymaster4Device::importKey(const hidl_vec<KeyParameter>& k
std::vector<uint8_t> cborOutData;
ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR;
KeyCharacteristics keyCharacteristics;
std::vector<KeyParameter> emptyParameters;
cppbor::Array subArray;
// Send earlyBootEnded if there is any pending earlybootEnded event.
handleSendEarlyBootEndedEvent();
Expand All @@ -662,6 +663,9 @@ Return<void> JavacardKeymaster4Device::importKey(const hidl_vec<KeyParameter>& k
array.add(static_cast<uint32_t>(keyFormat)); //javacard accepts only RAW.

array.add(std::vector<uint8_t>(keyData));
array.add(std::vector<uint8_t>()); //dummy attest key blob
cborConverter_.addKeyparameters(array, emptyParameters); //empty attest key param
array.add(std::vector<uint8_t>()); //dummy issuer
std::vector<uint8_t> cborData = array.encode();

errorCode = sendData(Instruction::INS_IMPORT_KEY_CMD, cborData, cborOutData);
Expand All @@ -670,7 +674,7 @@ Return<void> JavacardKeymaster4Device::importKey(const hidl_vec<KeyParameter>& k
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getBinaryArray(item, 1, keyBlob) ||
!cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) {
//Clear the buffer.
Expand Down Expand Up @@ -728,7 +732,7 @@ Return<void> JavacardKeymaster4Device::importWrappedKey(const hidl_vec<uint8_t>&
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getBinaryArray(item, 1, keyBlob) ||
!cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) {
//Clear the buffer.
Expand Down Expand Up @@ -761,7 +765,7 @@ Return<void> JavacardKeymaster4Device::getKeyCharacteristics(const hidl_vec<uint
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getKeyCharacteristics(item, 1, keyCharacteristics)) {
keyCharacteristics.softwareEnforced.setToExternal(nullptr, 0);
keyCharacteristics.hardwareEnforced.setToExternal(nullptr, 0);
Expand Down Expand Up @@ -836,7 +840,7 @@ Return<void> JavacardKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToA
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getMultiBinaryArray(item, 1, temp)) {
errorCode = ErrorCode::UNKNOWN_ERROR;
LOG(ERROR) << "INS_ATTEST_KEY_CMD: error in converting cbor data, status: " << (int32_t) errorCode;
Expand All @@ -849,7 +853,7 @@ Return<void> JavacardKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToA
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(),
cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
std::vector<uint8_t> chain;
if(!cborConverter_.getBinaryArray(item, 1, chain)) {
errorCode = ErrorCode::UNKNOWN_ERROR;
Expand Down Expand Up @@ -890,7 +894,7 @@ Return<void> JavacardKeymaster4Device::upgradeKey(const hidl_vec<uint8_t>& keyBl
//Skip last 2 bytes in cborData, it contains status.
std::tie(item, errorCode) = decodeData(cborConverter_, std::vector<uint8_t>(cborOutData.begin(), cborOutData.end()-2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if(!cborConverter_.getBinaryArray(item, 1, upgradedKeyBlob)) {
errorCode = ErrorCode::UNKNOWN_ERROR;
LOG(ERROR) << "INS_UPGRADE_KEY_CMD: error in converting cbor data, status: " << (int32_t) errorCode;
Expand Down Expand Up @@ -1078,7 +1082,7 @@ ErrorCode JavacardKeymaster4Device::handleBeginPrivateKeyOperation(
decodeData(cborConverter_,
std::vector<uint8_t>(cborOutData.begin(), cborOutData.end() - 2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
if (!cborConverter_.getKeyParameters(item, 1, outParams) ||
!cborConverter_.getUint64(item, 2, operationHandle)) {
errorCode = ErrorCode::UNKNOWN_ERROR;
Expand Down Expand Up @@ -1215,7 +1219,7 @@ JavacardKeymaster4Device::update(uint64_t operationHandle, const hidl_vec<KeyPar
decodeData(cborConverter_,
std::vector<uint8_t>(cborOutData.begin(), cborOutData.end() - 2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
/*Ignore inputConsumed from javacard SE since HAL consumes all the input */
// cborConverter_.getUint64(item, 1, inputConsumed);
// This callback function may gets called multiple times so parse and get the
Expand All @@ -1225,7 +1229,7 @@ JavacardKeymaster4Device::update(uint64_t operationHandle, const hidl_vec<KeyPar
// the tempOut(std::vector<uint8_t>).
if ((outParams.size() == 0 &&
!cborConverter_.getKeyParameters(item, 2, outParams)) ||
!cborConverter_.getBinaryArray(item, 3, tempOut)) {
!cborConverter_.getBinaryArray(item, 1, tempOut)) {
outParams.setToExternal(nullptr, 0);
tempOut.clear();
errorCode = ErrorCode::UNKNOWN_ERROR;
Expand Down Expand Up @@ -1317,6 +1321,7 @@ JavacardKeymaster4Device::finish(uint64_t operationHandle, const hidl_vec<KeyPar
std::vector<uint8_t> cborOutData;
int keyParamPos, outputPos;
std::vector<uint8_t> asn1ParamsVerified;
const hidl_vec<uint8_t> confToken = {}; //dummy

if (ErrorCode::OK !=
(errorCode = encodeParametersVerified(verificationToken, asn1ParamsVerified))) {
Expand Down Expand Up @@ -1358,10 +1363,11 @@ JavacardKeymaster4Device::finish(uint64_t operationHandle, const hidl_vec<KeyPar
array.add(data);
ins = Instruction::INS_UPDATE_OPERATION_CMD;
keyParamPos = 2;
outputPos = 3;
outputPos = 1;
}
cborConverter_.addHardwareAuthToken(array, authToken);
cborConverter_.addVerificationToken(array, verificationToken, asn1ParamsVerified);
array.add(std::vector<uint8_t>(confToken));
std::vector<uint8_t> cborData = array.encode();
errorCode = sendData(ins, cborData, cborOutData);

Expand All @@ -1371,7 +1377,7 @@ JavacardKeymaster4Device::finish(uint64_t operationHandle, const hidl_vec<KeyPar
decodeData(cborConverter_,
std::vector<uint8_t>(cborOutData.begin(), cborOutData.end() - 2),
true, oprCtx_);
if (item != nullptr) {
if (errorCode == ErrorCode::OK) {
// There is a change that this finish callback may gets called multiple times if
// the input data size is larger the MAX_ALLOWED_INPUT_SIZE (Refer
// OperationContext) so parse and get the outParams only once. Otherwise there
Expand Down
14 changes: 4 additions & 10 deletions Keymaster_HAL/keymaster/include/CborConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,10 @@ class CborConverter
std::tie(item, pos, message) = parse(response);

if(item != nullptr && hasErrorCode) {
if(MajorType::ARRAY == getType(item)) {
if(!getErrorCode(item, 0, errorCode))
item = nullptr;
} else if (MajorType::UINT == getType(item)) {
uint64_t err;
if(getUint64(item, err)) {
errorCode = static_cast<T>(err);
}
item = nullptr; /*Already read the errorCode. So no need of sending item to client */
}
if(MajorType::ARRAY == getType(item)) {
if(!getErrorCode(item, 0, errorCode))
return {nullptr, T::UNKNOWN_ERROR};
}
}
return {std::move(item), errorCode};
}
Expand Down