Commit 3a6bee2d authored by Josh Ji's avatar Josh Ji

hkdf_chain finished

parent 97229b46
......@@ -25,7 +25,7 @@ repositories {
final def jcdk_dir = 'sdks/jc305u3_kit'
javacard{
config{
debugGpPro true
// debugGpPro true
jckit jcdk_dir
cap{
packageName 'com.josh.vku2f'
......
......@@ -114,9 +114,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
// 1210 bytes of a transient buffer for read-in and out
// We advertise 1200 bytes supported, but 10 bytes for protocol nonsense
try {
dataBuffer = JCSystem.makeTransientByteArray((short) 1510, JCSystem.CLEAR_ON_DESELECT);
dataBuffer = JCSystem.makeTransientByteArray((short) 1210, JCSystem.CLEAR_ON_DESELECT);
} catch (Exception e) {
dataBuffer = new byte[1510];
dataBuffer = new byte[1210];
}
try {
scratch = JCSystem.makeTransientByteArray((short) 512, JCSystem.CLEAR_ON_DESELECT);
......@@ -477,6 +477,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
KeyAgreement keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
keyAgreement.init(attestationKeyPair.getPrivate());
keyAgreement.generateSecret(idSecret.puK_idp, (short) 0, (short) 65, idSecret.sharedSecret, (short) 0);
sha256MessageDigest.doFinal(idSecret.sharedSecret, (short)0,(short)idSecret.sharedSecret.length,
idSecret.hashedSharedSecret,(short)0);
idSecret.initHKDFChain();
......@@ -674,8 +676,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
cborEncoder.startArray((short) 4);
cborEncoder.encodeByteString(idSecret.nonce, (short) 0, (short) idSecret.nonce.length);
cborEncoder.encodeByteString(idSecret.idHash, (short) 0, (short) idSecret.idHash.length);
cborEncoder.encodeByteString(idSecret.counterE, (short) 0, (short) idSecret.counter.length);
cborEncoder.encodeByteString(idSecret.hmacValue, (short) 0, (short) idSecret.hmacValue.length);
cborEncoder.encodeByteString(idSecret.counter, (short) 0, (short) idSecret.counter.length);
}
// We're actually done, send this out
......
......@@ -8,7 +8,7 @@ public class HKDF
private byte[] counter = new byte[1]; // for expand()
private byte[] temp;
public HKDF(){
hmac = new HMAC();
hmac = HMAC.getInstance();
temp = JCSystem.makeTransientByteArray((short)32, JCSystem.CLEAR_ON_RESET);
}
public void extract(byte[] salt, byte[] ikm, byte[] output, short offset){
......
......@@ -13,8 +13,15 @@ public class HMAC
private MessageDigest sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
private byte[] ikeypad;
private byte[] okeypad;
private static HMAC hmac;
public HMAC(){
public static HMAC getInstance(){
if (hmac == null) {
hmac = new HMAC();
}
return hmac;
}
private HMAC(){
key = new byte[BLOCK_SIZE];
ikeypad = new byte[BLOCK_SIZE];
okeypad = new byte[BLOCK_SIZE];
......
......@@ -18,16 +18,19 @@ public class IDSecret {
public final byte[] hashedSharedSecret = new byte[32];
public final byte[] HKDF_CHAIN_IV = new byte[32];
public final byte[] nonce = new byte[32];
public final byte[] nonce1 = new byte[32];
public final byte[] idHash = new byte[32];
public final byte[] idHash1 = new byte[32];
public final byte[] counter = new byte[4]; // for hkdfChain
public final byte[] counterE = new byte[4]; // for hkdfChain
public final byte[] hmacValue = new byte[32];
public final byte[] hmacKey = new byte[32];
public final short OKM_LENGTH = (short)32;
public final MessageDigest sha256;
public HKDFChain hkdfChain;
public final HMAC hmac = new HMAC();
public final HMAC hmac = HMAC.getInstance();
public final CBOREncoder encoder = new CBOREncoder();
public final byte[] temp = JCSystem.makeTransientByteArray((short)32, JCSystem.CLEAR_ON_DESELECT);
public final byte[] temp = JCSystem.makeTransientByteArray((short)64, JCSystem.CLEAR_ON_DESELECT);
public IDSecret(){
id = new DomString(Utf8Strings.UTF8_NULL, (short)Utf8Strings.UTF8_NULL.length);
......@@ -41,12 +44,16 @@ public class IDSecret {
}
public void PIVInfoNext(){
Random.getInstance().nextBytes(nonce, (short)0, (short)nonce.length);
sha256.doFinal(id.str, (short)0, id.len, temp, (short)0);
sha256.update(temp, (short)0, (short)temp.length);
sha256.doFinal(nonce, (short)0, (short)nonce.length, idHash, (short)0);
Random.getInstance().nextBytes(nonce, (short)0, (short)nonce.length); // n
sha256.doFinal(id.str, (short)0, id.len, temp, (short)0); // H(ID)
sha256.doFinal(nonce, (short)0, (short)nonce.length, temp, (short)32); // H(n)
sha256.doFinal(temp, (short)0, (short)temp.length, idHash, (short)0); // H(H(ID)||H(n))
hkdfChain.next(hmacKey, (short)0);
plusOne(counter);
plusOne(counter); // C += 1
plusOne(nonce, nonce1); // n += 1
sha256.doFinal(nonce1, (short)0, (short)nonce1.length, temp, (short)32); // H(n+1)
sha256.doFinal(temp, (short)0, (short)temp.length, temp, (short)0 ); // H(H(ID)||H(n+1))
xor(counter, temp, counterE); // XOR(counter, H(n+1))
hmac.setKey(hmacKey);
hmac.update(idHash);
hmac.doFinal(hmacValue, (short)0);
......@@ -57,18 +64,43 @@ public class IDSecret {
* return data length
*/
public short dump(byte[] apduBuffer, byte[] dataBuffer, CBOREncoder encoder){
PIVInfoNext();
// PIVInfoNext();
encoder.init(dataBuffer, (short)0, (short)1200);
encoder.startArray((short)9);
encoder.startMap((short)11);
encoder.encodeTextString(new byte[]{'i','d'}, (short)0, (short)2);
encoder.encodeTextString(id.str ,(short)0, id.len);
encoder.encodeTextString(new byte[]{'n'}, (short)0, (short)1);
encoder.encodeByteString(nonce ,(short)0, (short)nonce.length);
encoder.encodeTextString(new byte[]{'i','d','h'}, (short)0, (short)3);
encoder.encodeByteString(idHash ,(short)0, (short)idHash.length);
encoder.encodeTextString(new byte[]{'i','v'}, (short)0, (short)2);
encoder.encodeByteString(HKDF_CHAIN_IV ,(short)0, (short)HKDF_CHAIN_IV.length);
encoder.encodeTextString(new byte[]{'p','k'}, (short)0, (short)2);
encoder.encodeByteString(puK_idp ,(short)0, (short)puK_idp.length);
encoder.encodeTextString(new byte[]{'s','k'}, (short)0, (short)2);
encoder.encodeByteString(sharedSecret ,(short)0, (short)sharedSecret.length);
encoder.encodeTextString(new byte[]{'s','k','h'}, (short)0, (short)3);
encoder.encodeByteString(hashedSharedSecret ,(short)0, (short)hashedSharedSecret.length);
encoder.encodeTextString(new byte[]{'c'}, (short)0, (short)1);
encoder.encodeByteString(counter ,(short)0, (short)counter.length);
encoder.encodeTextString(new byte[]{'c', 'E'}, (short)0, (short)2);
encoder.encodeByteString(counterE ,(short)0, (short)counter.length);
encoder.encodeTextString(new byte[]{'h','k','e','y',}, (short)0, (short)4);
encoder.encodeByteString(hmacKey ,(short)0, (short)hmacKey.length);
encoder.encodeTextString(new byte[]{'h','m','a','c',}, (short)0, (short)4);
encoder.encodeByteString(hmacValue ,(short)0, (short)hmacValue.length);
return encoder.getCurrentOffset();
}
......@@ -93,6 +125,17 @@ public class IDSecret {
}
}
public void plusOne(byte[] input, byte[] output){
Util.arrayCopy(input, (short)0, output, (short)0, (short)input.length);
plusOne(output);
}
public void xor(byte[] a, byte[] b, byte[] output){
for(short i = 0; i< a.length; i++){
output[i] = (byte)(a[i] ^ b[i]);
}
}
private void testSharedObjects(byte[] apduBuffer){
/*
byte[] aid = new byte[]{(byte)0xa0,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x47,(byte)0x10,(byte)0x01};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment