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 number Diff line number Diff line change
Expand Up @@ -1093,12 +1093,4 @@ public KMAttestationCert factoryAttestKey(KMAttestationKey key, byte mode) {
factoryAttestKey = key;
return this;
}

//Check
/*
* private void print(byte[] buf, short start, short length){ StringBuilder sb =
* new StringBuilder(length * 2); for(short i = start; i < (start+length); i
* ++){ sb.append(String.format("%02x", buf[i])); } System.out.println(
* sb.toString()); }
*/
}
2 changes: 1 addition & 1 deletion Applet/src/com/android/javacard/kmdevice/KMEnumTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static void create() {
enums =
new Object[]{
new byte[]{RSA, DES, EC, AES, HMAC},
new byte[]{P_224, P_256, P_384, P_521},
new byte[]{P_224, P_256, P_384, P_521, CURVE_25519},
new byte[]{STANDALONE, REQUIRES_FILE_SYSTEM},
new byte[]{USER_AUTH_NONE, PASSWORD, FINGERPRINT, BOTH, ANY},
new byte[]{GENERATED, DERIVED, IMPORTED, UNKNOWN, SECURELY_IMPORTED},
Expand Down
16 changes: 13 additions & 3 deletions Applet/src/com/android/javacard/kmdevice/KMKeymintDevice.java
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,10 @@ public short generateBcc(boolean testMode, byte[] scratchPad) {
// do sign
short len = seProvider.ecSign256(deviceUniqueKey, scratchPad, (short) 0, temp, scratchPad,
temp);
len =
KMPKCS8Decoder.instance().
decodeEcdsa256Signature(KMByteBlob.instance(scratchPad, temp, len), scratchPad, temp);

coseSignStructure = KMByteBlob.instance(scratchPad, temp, len);

// construct cose_sign1
Expand Down Expand Up @@ -581,11 +585,17 @@ public short validateCertChain(boolean validateEekRoot, byte expCertAlg,
KMArray.get(ptr1, KMCose.COSE_SIGN1_PAYLOAD_OFFSET));
encodedLen = encodeToApduBuffer(signStructure, scratchPad,
keySize, RemotelyProvisionedComponentDevice.MAX_COSE_BUF_SIZE);

short signatureLen =
rkp.encodeES256CoseSignSignature(
KMByteBlob.getBuffer(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)),
KMByteBlob.getStartOff(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)),
KMByteBlob.length(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)),
scratchPad,
(short) (keySize + encodedLen));

if (!seProvider.ecVerify256(scratchPad, (short) 0, keySize, scratchPad, keySize, encodedLen,
KMByteBlob.getBuffer(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)),
KMByteBlob.getStartOff(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)),
KMByteBlob.length(KMArray.get(ptr1, KMCose.COSE_SIGN1_SIGNATURE_OFFSET)))) {
scratchPad, (short) (keySize + encodedLen), signatureLen)) {
KMException.throwIt(KMError.STATUS_FAILED);
}
prevCoseKey = ptr2;
Expand Down
33 changes: 33 additions & 0 deletions Applet/src/com/android/javacard/kmdevice/KMPKCS8Decoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,34 @@ private void updateModulus(short blob) {
KMByteBlob.setLength(blob, --len);
}
}

private short readEcdsa256SigIntegerHeader() {
short len = header(ASN1_INTEGER);
if (len == 33) {
if (0 != getByte()) {
KMException.throwIt(KMError.INVALID_DATA);
}
len--;
} else if (len > 33) {
KMException.throwIt(KMError.INVALID_DATA);
}
return len;
}

// Seq [Int, Int]
public short decodeEcdsa256Signature(short blob, byte[] scratchPad, short scratchPadOff) {
init(blob);
short len = header(ASN1_SEQUENCE);
len = readEcdsa256SigIntegerHeader();
// concatenate r and s in the buffer (r||s)
Util.arrayFillNonAtomic(scratchPad, scratchPadOff, (short) 64, (byte) 0);
// read r
getBytes(scratchPad, (short) (scratchPadOff + 32 - len), len);
len = readEcdsa256SigIntegerHeader();
// read s
getBytes(scratchPad, (short) (scratchPadOff + 64 - len), len);
return (short) 64;
}

// Seq [Int, Blob]
public void decodeCommon(short version, byte[] alg) {
Expand Down Expand Up @@ -217,6 +245,11 @@ private void getBytes(short blob) {
KMByteBlob.getStartOff(blob), len);
incrementCursor(len);
}

private void getBytes(byte[] buffer, short offset, short len) {
Util.arrayCopyNonAtomic(data, cur, buffer, offset, len);
incrementCursor(len);
}

private short getLength() {
byte len = getByte();
Expand Down
2 changes: 1 addition & 1 deletion Applet/src/com/android/javacard/kmdevice/KMType.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public abstract class KMType {
public static final byte P_256 = 0x01;
public static final byte P_384 = 0x02;
public static final byte P_521 = 0x03;
public static final byte CURVE_25519 = 0x04;

// KeyBlobUsageRequirements Enum Tag key and values.
public static final short BLOB_USAGE_REQ = 0x012D;
Expand Down Expand Up @@ -233,7 +234,6 @@ public abstract class KMType {
public static final short ORIGINATION_EXPIRE_DATETIME = 0x0191;
public static final short USAGE_EXPIRE_DATETIME = 0x0192;
public static final short CREATION_DATETIME = 0x02BD;
;
public static final short CERTIFICATE_NOT_BEFORE = 0x03F0;
public static final short CERTIFICATE_NOT_AFTER = 0x03F1;
// Integer Array Tags - ULONG_REP and UINT_REP.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class RemotelyProvisionedComponentDevice {
private static final byte FALSE = 0x00;
// RKP Version
private static final short RKP_VERSION = (short) 0x01;
private static byte[] GOOGLE;
// Boot params
private static final byte OS_VERSION_ID = 0x00;
private static final byte SYSTEM_PATCH_LEVEL_ID = 0x01;
Expand Down Expand Up @@ -150,6 +151,7 @@ public RemotelyProvisionedComponentDevice(KMKeymintDevice KMApplet, KMEncoder en
}

public static void initStatics() {
GOOGLE = new byte[]{0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65};
// Device Info labels
BRAND = new byte[]{0x62, 0x72, 0x61, 0x6E, 0x64};
MANUFACTURER = new byte[]{0x6D, 0x61, 0x6E, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75,
Expand Down Expand Up @@ -267,11 +269,10 @@ private short getEntryLength(short index) {
private void processGetRkpHwInfoCmd(APDU apdu) {
// Make the response
// Author name - Google.
final byte[] google = {0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65};
short respPtr = KMArray.instance((short) 4);
KMArray.add(respPtr, (short) 0, KMInteger.uint_16(KMError.OK));
KMArray.add(respPtr, (short) 1, KMInteger.uint_16(RKP_VERSION));
KMArray.add(respPtr, (short) 2, KMByteBlob.instance(google, (short) 0, (short) google.length));
KMArray.add(respPtr, (short) 2, KMByteBlob.instance(GOOGLE, (short) 0, (short) GOOGLE.length));
KMArray.add(respPtr, (short) 3, KMInteger.uint_8(KMType.RKP_CURVE_P256));
KMAppletInst.sendOutgoing(apdu, respPtr);
}
Expand Down Expand Up @@ -847,6 +848,9 @@ private short createSignedMac(KMDeviceUniqueKey deviceUniqueKey, byte[] scratchP
scratchPad,
signStructure
);
len =
KMPKCS8Decoder.instance().
decodeEcdsa256Signature(KMByteBlob.instance(scratchPad, signStructure, len), scratchPad, signStructure);
signStructure = KMByteBlob.instance(scratchPad, signStructure, len);

/* Construct unprotected headers */
Expand Down Expand Up @@ -1081,6 +1085,11 @@ private short ecdhHkdfDeriveKey(byte[] privKeyA, short privKeyAOff, short privKe
pubKeyBLen, scratchPad, (short) 0);
key = KMByteBlob.instance(scratchPad, (short) 0, key);

// ignore 0x04 for ephemerical public key as kdfContext should not include 0x04.
pubKeyAOff += 1;
pubKeyALen -= 1;
pubKeyBOff += 1;
pubKeyBLen -= 1;
short kdfContext =
kmCoseInst.constructKdfContext(pubKeyA, pubKeyAOff, pubKeyALen, pubKeyB, pubKeyBOff,
pubKeyBLen,
Expand Down Expand Up @@ -1447,4 +1456,71 @@ private short getEcAttestKeyParameters() {
KMArray.add(arrPtr, tagIndex, KMBoolTag.instance(KMType.NO_AUTH_REQUIRED));
return KMKeyParameters.instance(arrPtr);
}

private boolean isSignedByte(byte b) {
return ((b & 0x0080) != 0);
}

private short writeIntegerHeader(short valueLen, byte[] data, short offset) {
// write length
data[offset] = (byte) valueLen;
// write INTEGER tag
offset--;
data[offset] = 0x02;
return offset;
}

private short writeSequenceHeader(short valueLen, byte[] data, short offset) {
// write length
data[offset] = (byte) valueLen;
// write INTEGER tag
offset--;
data[offset] = 0x30;
return offset;
}

private short writeSignatureData(byte[] input, short inputOff, short inputlen, byte[] output, short offset) {
Util.arrayCopyNonAtomic(input, inputOff, output, offset, inputlen);
if (isSignedByte(input[inputOff])) {
offset--;
output[offset] = (byte) 0;
}
return offset;
}

public short encodeES256CoseSignSignature(byte[] input, short offset, short len, byte[] scratchPad, short scratchPadOff) {
// SEQ [ INTEGER(r), INTEGER(s)]
// write from bottom to the top
if (len != 64) {
KMException.throwIt(KMError.INVALID_DATA);
}
short maxTotalLen = 72;
short end = (short) (scratchPadOff + maxTotalLen);
// write s.
short start = (short) (end - 32);
start = writeSignatureData(input, (short) (offset + 32), (short) 32, scratchPad, start);
// write length and header
short length = (short) (end - start);
start--;
start = writeIntegerHeader(length, scratchPad, start);
// write r
short rEnd = start;
start = (short) (start - 32);
start = writeSignatureData(input, offset, (short) 32, scratchPad, start);
// write length and header
length = (short) (rEnd - start);
start--;
start = writeIntegerHeader(length, scratchPad, start);
// write length and sequence header
length = (short) (end - start);
start--;
start = writeSequenceHeader(length, scratchPad, start);
length = (short) (end - start);
if (start > scratchPadOff) {
// re adjust the buffer
Util.arrayCopyNonAtomic(scratchPad, start, scratchPad, scratchPadOff, length);
}
return length;
}

}
12 changes: 9 additions & 3 deletions HAL/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ cc_library {
],
cflags:["-O0",],
shared_libs: [
"android.hardware.security.keymint-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"lib_android_keymaster_keymint_utils",
"android.hardware.security.keymint-V1-ndk",
"libbase",
"libcppbor_external",
"libkeymaster_portable",
Expand Down Expand Up @@ -73,6 +72,7 @@ cc_library {
"libcrypto",
"libcutils",
"libjc_km_transport",
"android.se.omapi-V1-ndk",
"libbinder_ndk",
],
export_include_dirs: [
Expand All @@ -85,14 +85,18 @@ cc_library {
name: "libjc_km_transport",
vendor_available: true,
srcs: [
"OmapiTransport.cpp",
"SocketTransport.cpp",
],
export_include_dirs: [
"."
],
shared_libs: [
"libbinder",
"libbase",
"liblog",
"libbinder_ndk",
"android.se.omapi-V1-ndk",
],
}

Expand Down Expand Up @@ -164,6 +168,7 @@ cc_binary {
"libcrypto",
"libjc_keymaster",
"libjc_keymaster_portable",
"android.se.omapi-V1-ndk",
],
required: [
"android.hardware.keymaster_strongbox_keystore.xml",
Expand All @@ -184,8 +189,8 @@ cc_binary {
"-Wextra",
],
shared_libs: [
"android.hardware.security.keymint-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"android.hardware.security.keymint-V1-ndk",
"libbase",
"libbinder_ndk",
"libcppbor_external",
Expand All @@ -196,6 +201,7 @@ cc_binary {
"liblog",
"libutils",
"libjc_keymaster_portable",
"android.se.omapi-V1-ndk",
],
srcs: [
"keymintService.cpp",
Expand Down
5 changes: 2 additions & 3 deletions HAL/JavacardKeyMintDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <JavacardKeyMintUtils.h>
#include <JavacardKeymaster.h>
#include <KMUtils.h>
#include <KeyMintUtils.h>
#include <algorithm>
#include <android-base/logging.h>
#include <android-base/properties.h>
Expand Down Expand Up @@ -266,7 +265,7 @@ ScopedAStatus JavacardKeyMintDevice::begin(KeyPurpose purpose, const std::vector
paramSet.Reinitialize(KmParamSet(params));
::keymaster::HardwareAuthToken legacyToken;
std::unique_ptr<JavacardKeymasterOperation> operation;
legacyHardwareAuthToken(aToken, &legacyToken);
km_utils::legacyHardwareAuthToken(aToken, &legacyToken);
auto err = jcImpl_->begin(static_cast<keymaster_purpose_t>(purpose), keyBlob, paramSet,
legacyToken, &outParams, operation);
if (err != KM_ERROR_OK) {
Expand All @@ -284,7 +283,7 @@ JavacardKeyMintDevice::deviceLocked(bool passwordOnly,
const std::optional<TimeStampToken>& timestampToken) {
TimeStampToken tToken = timestampToken.value_or(TimeStampToken());
vector<uint8_t> encodedTimestampToken;
auto err = encodeTimestampToken(tToken, &encodedTimestampToken);
auto err = km_utils::encodeTimestampToken(tToken, &encodedTimestampToken);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "In deviceLocked failed to encode TimeStampToken" << (int32_t)err;
return km_utils::kmError2ScopedAStatus(err);
Expand Down
13 changes: 6 additions & 7 deletions HAL/JavacardKeyMintOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

#include "JavacardKeyMintOperation.h"
#include <JavacardKeyMintUtils.h>
#include <KeyMintUtils.h>
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
#include <android-base/logging.h>
Expand All @@ -35,8 +34,8 @@ ScopedAStatus JavacardKeyMintOperation::updateAad(const vector<uint8_t>& input,
vector<uint8_t> encodedTimestampToken;
HardwareAuthToken aToken = authToken.value_or(HardwareAuthToken());
TimeStampToken tToken = timestampToken.value_or(TimeStampToken());
legacyHardwareAuthToken(aToken, &legacyToken);
encodeTimestampToken(tToken, &encodedTimestampToken);
km_utils::legacyHardwareAuthToken(aToken, &legacyToken);
km_utils::encodeTimestampToken(tToken, &encodedTimestampToken);
auto err = jcKmOprImpl_->updateAad(input, legacyToken, encodedTimestampToken);
return km_utils::kmError2ScopedAStatus(err);
}
Expand All @@ -49,8 +48,8 @@ ScopedAStatus JavacardKeyMintOperation::update(const vector<uint8_t>& input,
vector<uint8_t> encodedTimestampToken;
HardwareAuthToken aToken = authToken.value_or(HardwareAuthToken());
TimeStampToken tToken = timestampToken.value_or(TimeStampToken());
legacyHardwareAuthToken(aToken, &legacyToken);
encodeTimestampToken(tToken, &encodedTimestampToken);
km_utils::legacyHardwareAuthToken(aToken, &legacyToken);
km_utils::encodeTimestampToken(tToken, &encodedTimestampToken);
auto err = jcKmOprImpl_->update(input, nullopt, legacyToken, encodedTimestampToken, nullptr,
nullptr, output);
return km_utils::kmError2ScopedAStatus(err);
Expand All @@ -71,8 +70,8 @@ ScopedAStatus JavacardKeyMintOperation::finish(const optional<vector<uint8_t>>&
// If confirmation token is empty, then create empty vector. This is to
// differentiate between the keymaster and keymint.
std::optional<vector<uint8_t>> confToken = confirmationToken.value_or(vector<uint8_t>());
legacyHardwareAuthToken(aToken, &legacyToken);
encodeTimestampToken(tToken, &encodedTimestampToken);
km_utils::legacyHardwareAuthToken(aToken, &legacyToken);
km_utils::encodeTimestampToken(tToken, &encodedTimestampToken);
auto err = jcKmOprImpl_->finish(inputData, nullopt, signatureData, legacyToken,
encodedTimestampToken, confToken, nullptr, output);
return km_utils::kmError2ScopedAStatus(err);
Expand Down
Loading