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
Original file line numberDiff line numberDiff line change
Expand Up@@ -47,6 +47,8 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeLis
INS_KEYMINT_PROVIDER_APDU_START + 6;
private static final byte INS_PROVISION_ADDITIONAL_CERT_CHAIN_CMD =
INS_KEYMINT_PROVIDER_APDU_START + 7;
private static final byte INS_SET_BOOT_ENDED_CMD =
INS_KEYMINT_PROVIDER_APDU_START + 8;

private static final byte INS_KEYMINT_PROVIDER_APDU_END = 0x1F;
public static final byte BOOT_KEY_MAX_SIZE = 32;
Expand DownExpand Up@@ -100,6 +102,13 @@ public void process(APDU apdu) {
case INS_SET_BOOT_PARAMS_CMD:
processSetBootParamsCmd(apdu);
break;

case INS_SET_BOOT_ENDED_CMD:
//set the flag to mark boot ended
repository.setBootEndedStatus(true);
sendError(apdu, KMError.OK);
break;

default:
super.process(apdu);
break;
Expand DownExpand Up@@ -308,7 +317,8 @@ private void processGetProvisionStatusCmd(APDU apdu) {

private void processSetBootParamsCmd(APDU apdu) {
short argsProto = KMArray.instance((short) 5);


byte[] scratchPad = apdu.getBuffer();
// Array of 4 expected arguments
// Argument 0 Boot Patch level
KMArray.cast(argsProto).add((short) 0, KMInteger.exp());
Expand DownExpand Up@@ -353,6 +363,11 @@ private void processSetBootParamsCmd(APDU apdu) {
enumVal = KMEnum.cast(bootParam).getVal();
((KMAndroidSEProvider) seProvider).setDeviceLocked(enumVal == KMType.DEVICE_LOCKED_TRUE);


// Clear the Computed SharedHmac and Hmac nonce from persistent memory.
Util.arrayFillNonAtomic(scratchPad, (short) 0, KMRepository.COMPUTED_HMAC_KEY_SIZE, (byte) 0);
seProvider.createComputedHmacKey(scratchPad, (short) 0, KMRepository.COMPUTED_HMAC_KEY_SIZE);

super.reboot();
sendError(apdu, KMError.OK);
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,6 +65,7 @@ public class KMAndroidSEProvider implements KMSEProvider {
public static final short SHARED_SECRET_KEY_SIZE = 32;
public static final byte POWER_RESET_FALSE = (byte) 0xAA;
public static final byte POWER_RESET_TRUE = (byte) 0x00;
private static final short COMPUTED_HMAC_KEY_SIZE = 32;

private static KeyAgreement keyAgreement;

Expand DownExpand Up@@ -117,6 +118,7 @@ public class KMAndroidSEProvider implements KMSEProvider {
private KMECDeviceUniqueKey testKey;
private KMECDeviceUniqueKey deviceUniqueKey;
private KMHmacKey preSharedKey;
private KMHmacKey computedHmacKey;
private byte[] additionalCertChain;
private byte[] bcc;
private boolean isProvisionLocked;
Expand DownExpand Up@@ -167,6 +169,8 @@ public KMAndroidSEProvider() {
createAttestationKey(tmpArray, (short) 0, (short) 32);
// Pre-shared secret key length is 32 bytes.
createPresharedKey(tmpArray, (short) 0, (short) SHARED_SECRET_KEY_SIZE);
// Initialize the Computed Hmac Key object.
createComputedHmacKey(tmpArray, (short)0, (short) 32);
}
androidSEProvider = this;
resetFlag = JCSystem.makeTransientByteArray((short) 1,
Expand DownExpand Up@@ -593,13 +597,6 @@ public short hmacSign(HMACKey key, byte[] data, short dataStart,
return hmacSignature.sign(data, dataStart, dataLength, mac, macStart);
}

public boolean hmacVerify(HMACKey key, byte[] data, short dataStart,
short dataLength, byte[] mac, short macStart, short macLength) {
hmacSignature.init(key, Signature.MODE_VERIFY);
return hmacSignature.verify(data, dataStart, dataLength, mac, macStart,
macLength);
}

@Override
public short hmacSign(byte[] keyBuf, short keyStart, short keyLength,
byte[] data, short dataStart, short dataLength, byte[] mac, short macStart) {
Expand All@@ -623,12 +620,12 @@ public short hmacKDF(KMMasterKey masterkey, byte[] data, short dataStart,
}

@Override
public boolean hmacVerify(byte[] keyBuf, short keyStart, short keyLength,
byte[] data, short dataStart, short dataLength, byte[] mac,
short macStart, short macLength) {
HMACKey key = createHMACKey(keyBuf, keyStart, keyLength);
return hmacVerify(key, data, dataStart, dataLength, mac, macStart,
macLength);
public boolean hmacVerify(KMComputedHmacKey key, byte[] data, short dataStart,
short dataLength, byte[] mac, short macStart, short macLength) {
KMHmacKey hmacKey = (KMHmacKey) key;
hmacSignature.init(hmacKey.getKey(), Signature.MODE_VERIFY);
return hmacSignature.verify(data, dataStart, dataLength, mac, macStart,
macLength);
}

@Override
Expand DownExpand Up@@ -739,7 +736,7 @@ public KMOperation createSymmetricCipher(short alg, short purpose, short macLeng
}
short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0);
KMOperation operation =
poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength);
poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, false);
((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, ivBuffer, ivStart, ivLength);
return operation;
}
Expand All@@ -751,11 +748,23 @@ public KMOperation createHmacSignerVerifier(short purpose, short digest,
}
KMOperation operation =
poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256,
KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE);
KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, false);
HMACKey key = createHMACKey(secret, secretStart, secretLength);
((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0);
return operation;
}

private KMOperation createHmacSignerVerifier(short purpose, short digest, HMACKey key, boolean isTrustedConf) {
if (digest != KMType.SHA2_256) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
KMOperation operation =
poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256,
KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, isTrustedConf);

((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0);
return operation;
}

@Override
public KMOperation initSymmetricOperation(byte purpose, byte alg,
Expand All@@ -781,12 +790,18 @@ public KMOperation initSymmetricOperation(byte purpose, byte alg,
return opr;
}

@Override
public KMOperation initTrustedConfirmationSymmetricOperation(KMComputedHmacKey computedHmacKey) {
KMHmacKey key = (KMHmacKey) computedHmacKey;
return createHmacSignerVerifier(KMType.VERIFY, KMType.SHA2_256, key.getKey(), true);
}

public KMOperation createRsaSigner(short digest, short padding, byte[] secret,
short secretStart, short secretLength, byte[] modBuffer, short modOff,
short modLength) {
byte alg = mapSignature256Alg(KMType.RSA, (byte) padding, (byte) digest);
KMOperation operation = poolMgr.getOperationImpl(KMType.SIGN, alg, KMType.RSA, padding,
KMType.INVALID_VALUE, KMType.INVALID_VALUE);
KMType.INVALID_VALUE, KMType.INVALID_VALUE, false);
RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate();
key.setExponent(secret, secretStart, secretLength);
key.setModulus(modBuffer, modOff, modLength);
Expand All@@ -799,7 +814,7 @@ public KMOperation createRsaDecipher(short padding, short mgfDigest, byte[] secr
short modLength) {
byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte) mgfDigest);
KMOperation operation = poolMgr.getOperationImpl(KMType.DECRYPT, cipherAlg, KMType.RSA, padding,
KMType.INVALID_VALUE, KMType.INVALID_VALUE);
KMType.INVALID_VALUE, KMType.INVALID_VALUE, false);
RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate();
key.setExponent(secret, secretStart, secretLength);
key.setModulus(modBuffer, modOff, modLength);
Expand All@@ -814,7 +829,7 @@ public KMOperation createEcSigner(short digest, byte[] secret,
key.setS(secret, secretStart, secretLength);
KMOperation operation = poolMgr
.getOperationImpl(KMType.SIGN, alg, KMType.EC, KMType.INVALID_VALUE,
KMType.INVALID_VALUE, KMType.INVALID_VALUE);
KMType.INVALID_VALUE, KMType.INVALID_VALUE, false);
((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0);
return operation;
}
Expand All@@ -825,7 +840,7 @@ public KMOperation createKeyAgreement(byte[] secret, short secretStart,
key.setS(secret, secretStart, secretLength);
KMOperation operation = poolMgr
.getOperationImpl(KMType.AGREE_KEY, KeyAgreement.ALG_EC_SVDP_DH_PLAIN,
KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE);
KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, false);
((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, null, (short) 0, (short) 0);
return operation;
}
Expand DownExpand Up@@ -1001,6 +1016,20 @@ public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short len
return (KMPreSharedKey) preSharedKey;
}

@Override
public KMComputedHmacKey createComputedHmacKey(byte[] keyData, short offset, short length) {
if (length != COMPUTED_HMAC_KEY_SIZE) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
if (computedHmacKey == null) {
HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short) (length * 8),
false);
computedHmacKey = new KMHmacKey(key);
}
computedHmacKey.setKey(keyData, offset, length);
return (KMComputedHmacKey) computedHmacKey;
}

@Override
public KMMasterKey getMasterKey() {
return (KMMasterKey) masterKey;
Expand DownExpand Up@@ -1486,4 +1515,40 @@ public void setProvisionLocked(boolean locked) {
public boolean isProvisionLocked() {
return isProvisionLocked;
}

@Override
public short messageDigest256(byte[] inBuff, short inOffset,
short inLength, byte[] outBuff, short outOffset) {
MessageDigest.OneShot mDigest = null;
short len = 0;
try {
mDigest = MessageDigest.OneShot.open(MessageDigest.ALG_SHA_256);
len = mDigest.doFinal(inBuff, inOffset, inLength, outBuff, outOffset);
} finally {
if (mDigest != null) {
mDigest.close();
mDigest = null;
}
}
return len;
}

@Override
public KMComputedHmacKey getComputedHmacKey() {
return computedHmacKey;
}

private byte mapPurpose(short purpose) {
switch (purpose) {
case KMType.ENCRYPT:
return Cipher.MODE_ENCRYPT;
case KMType.DECRYPT:
return Cipher.MODE_DECRYPT;
case KMType.SIGN:
return Signature.MODE_SIGN;
case KMType.VERIFY:
return Signature.MODE_VERIFY;
}
return -1;
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
package com.android.javacard.seprovider;


public interface KMComputedHmacKey {
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,7 +19,7 @@

import javacard.security.HMACKey;

public class KMHmacKey implements KMPreSharedKey {
public class KMHmacKey implements KMPreSharedKey, KMComputedHmacKey {

private HMACKey hmacKey;

Expand All@@ -34,7 +34,11 @@ public void setKey(byte[] keyData, short kOff, short length) {
public byte getKey(byte[] keyData, short kOff) {
return hmacKey.getKey(keyData, kOff);
}


public HMACKey getKey() {
return hmacKey;
}

public short getKeySizeBits() {
return hmacKey.getSize();
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,7 @@ public class KMOperationImpl implements KMOperation {
private static final short PURPOSE_OFFSET = 0x02;
private static final short BLOCK_MODE_OFFSET = 0x03;
private static final short MAC_LENGTH_OFFSET = 0x04;
private final byte[] EMPTY = {};
//This will hold the length of the buffer stored inside the
//Java Card after the GCM update operation.
private static final short AES_GCM_UPDATE_LEN_OFFSET = 0x05;
Expand DownExpand Up@@ -340,6 +341,24 @@ public boolean verify(byte[] inputDataBuf, short inputDataStart,

@Override
public void abort() {
// Few simulators does not reset the Hmac signer instance on init so as
// a workaround to reset the hmac signer instance in case of abort/failure of the operation
// the corresponding sign / verify function is called.
if (operationInst[0] != null) {
if ((parameters[PURPOSE_OFFSET] == KMType.SIGN || parameters[PURPOSE_OFFSET] == KMType.VERIFY) &&
(((Signature) operationInst[0]).getAlgorithm() == Signature.ALG_HMAC_SHA_256)) {
Signature signer = (Signature) operationInst[0];
try {
if (parameters[PURPOSE_OFFSET] == KMType.SIGN) {
signer.sign(EMPTY, (short) 0, (short) 0, EMPTY, (short) 0);
} else {
signer.verify(EMPTY, (short) 0, (short) 0, EMPTY, (short) 0, (short) 0);
}
} catch(Exception e) {
// Ignore.
}
}
}
reset();
}

Expand Down
Loading