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

hkdf_chain finished

parent 97229b46
...@@ -25,7 +25,7 @@ repositories { ...@@ -25,7 +25,7 @@ repositories {
final def jcdk_dir = 'sdks/jc305u3_kit' final def jcdk_dir = 'sdks/jc305u3_kit'
javacard{ javacard{
config{ config{
debugGpPro true // debugGpPro true
jckit jcdk_dir jckit jcdk_dir
cap{ cap{
packageName 'com.josh.vku2f' packageName 'com.josh.vku2f'
......
...@@ -114,9 +114,9 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -114,9 +114,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
// 1210 bytes of a transient buffer for read-in and out // 1210 bytes of a transient buffer for read-in and out
// We advertise 1200 bytes supported, but 10 bytes for protocol nonsense // We advertise 1200 bytes supported, but 10 bytes for protocol nonsense
try { try {
dataBuffer = JCSystem.makeTransientByteArray((short) 1510, JCSystem.CLEAR_ON_DESELECT); dataBuffer = JCSystem.makeTransientByteArray((short) 1210, JCSystem.CLEAR_ON_DESELECT);
} catch (Exception e) { } catch (Exception e) {
dataBuffer = new byte[1510]; dataBuffer = new byte[1210];
} }
try { try {
scratch = JCSystem.makeTransientByteArray((short) 512, JCSystem.CLEAR_ON_DESELECT); scratch = JCSystem.makeTransientByteArray((short) 512, JCSystem.CLEAR_ON_DESELECT);
...@@ -477,6 +477,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -477,6 +477,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
KeyAgreement keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false); KeyAgreement keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
keyAgreement.init(attestationKeyPair.getPrivate()); keyAgreement.init(attestationKeyPair.getPrivate());
keyAgreement.generateSecret(idSecret.puK_idp, (short) 0, (short) 65, idSecret.sharedSecret, (short) 0); 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(); idSecret.initHKDFChain();
...@@ -674,8 +676,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -674,8 +676,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
cborEncoder.startArray((short) 4); cborEncoder.startArray((short) 4);
cborEncoder.encodeByteString(idSecret.nonce, (short) 0, (short) idSecret.nonce.length); cborEncoder.encodeByteString(idSecret.nonce, (short) 0, (short) idSecret.nonce.length);
cborEncoder.encodeByteString(idSecret.idHash, (short) 0, (short) idSecret.idHash.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.hmacValue, (short) 0, (short) idSecret.hmacValue.length);
cborEncoder.encodeByteString(idSecret.counter, (short) 0, (short) idSecret.counter.length);
} }
// We're actually done, send this out // We're actually done, send this out
......
...@@ -8,7 +8,7 @@ public class HKDF ...@@ -8,7 +8,7 @@ public class HKDF
private byte[] counter = new byte[1]; // for expand() private byte[] counter = new byte[1]; // for expand()
private byte[] temp; private byte[] temp;
public HKDF(){ public HKDF(){
hmac = new HMAC(); hmac = HMAC.getInstance();
temp = JCSystem.makeTransientByteArray((short)32, JCSystem.CLEAR_ON_RESET); temp = JCSystem.makeTransientByteArray((short)32, JCSystem.CLEAR_ON_RESET);
} }
public void extract(byte[] salt, byte[] ikm, byte[] output, short offset){ public void extract(byte[] salt, byte[] ikm, byte[] output, short offset){
......
...@@ -13,8 +13,15 @@ public class HMAC ...@@ -13,8 +13,15 @@ public class HMAC
private MessageDigest sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false); private MessageDigest sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
private byte[] ikeypad; private byte[] ikeypad;
private byte[] okeypad; 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]; key = new byte[BLOCK_SIZE];
ikeypad = new byte[BLOCK_SIZE]; ikeypad = new byte[BLOCK_SIZE];
okeypad = new byte[BLOCK_SIZE]; okeypad = new byte[BLOCK_SIZE];
......
...@@ -18,16 +18,19 @@ public class IDSecret { ...@@ -18,16 +18,19 @@ public class IDSecret {
public final byte[] hashedSharedSecret = new byte[32]; public final byte[] hashedSharedSecret = new byte[32];
public final byte[] HKDF_CHAIN_IV = new byte[32]; public final byte[] HKDF_CHAIN_IV = new byte[32];
public final byte[] nonce = 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[] idHash = new byte[32];
public final byte[] idHash1 = new byte[32];
public final byte[] counter = new byte[4]; // for hkdfChain 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[] hmacValue = new byte[32];
public final byte[] hmacKey = new byte[32]; public final byte[] hmacKey = new byte[32];
public final short OKM_LENGTH = (short)32; public final short OKM_LENGTH = (short)32;
public final MessageDigest sha256; public final MessageDigest sha256;
public HKDFChain hkdfChain; public HKDFChain hkdfChain;
public final HMAC hmac = new HMAC(); public final HMAC hmac = HMAC.getInstance();
public final CBOREncoder encoder = new CBOREncoder(); 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(){ public IDSecret(){
id = new DomString(Utf8Strings.UTF8_NULL, (short)Utf8Strings.UTF8_NULL.length); id = new DomString(Utf8Strings.UTF8_NULL, (short)Utf8Strings.UTF8_NULL.length);
...@@ -41,12 +44,16 @@ public class IDSecret { ...@@ -41,12 +44,16 @@ public class IDSecret {
} }
public void PIVInfoNext(){ public void PIVInfoNext(){
Random.getInstance().nextBytes(nonce, (short)0, (short)nonce.length); Random.getInstance().nextBytes(nonce, (short)0, (short)nonce.length); // n
sha256.doFinal(id.str, (short)0, id.len, temp, (short)0); sha256.doFinal(id.str, (short)0, id.len, temp, (short)0); // H(ID)
sha256.update(temp, (short)0, (short)temp.length); sha256.doFinal(nonce, (short)0, (short)nonce.length, temp, (short)32); // H(n)
sha256.doFinal(nonce, (short)0, (short)nonce.length, idHash, (short)0); sha256.doFinal(temp, (short)0, (short)temp.length, idHash, (short)0); // H(H(ID)||H(n))
hkdfChain.next(hmacKey, (short)0); 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.setKey(hmacKey);
hmac.update(idHash); hmac.update(idHash);
hmac.doFinal(hmacValue, (short)0); hmac.doFinal(hmacValue, (short)0);
...@@ -57,18 +64,43 @@ public class IDSecret { ...@@ -57,18 +64,43 @@ public class IDSecret {
* return data length * return data length
*/ */
public short dump(byte[] apduBuffer, byte[] dataBuffer, CBOREncoder encoder){ public short dump(byte[] apduBuffer, byte[] dataBuffer, CBOREncoder encoder){
PIVInfoNext(); // PIVInfoNext();
encoder.init(dataBuffer, (short)0, (short)1200); 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(id.str ,(short)0, id.len);
encoder.encodeTextString(new byte[]{'n'}, (short)0, (short)1);
encoder.encodeByteString(nonce ,(short)0, (short)nonce.length); 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.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.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.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.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.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.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); encoder.encodeByteString(hmacValue ,(short)0, (short)hmacValue.length);
return encoder.getCurrentOffset(); return encoder.getCurrentOffset();
} }
...@@ -93,6 +125,17 @@ public class IDSecret { ...@@ -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){ private void testSharedObjects(byte[] apduBuffer){
/* /*
byte[] aid = new byte[]{(byte)0xa0,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x47,(byte)0x10,(byte)0x01}; 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