Commit 2a5c69e0 authored by Josh Ji's avatar Josh Ji

put hmac and Cx in attestation object extensions

parent fb45103c
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -427,6 +427,10 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -427,6 +427,10 @@ public class CTAP2 extends Applet implements ExtendedLength {
short length = attestationKeyPair.getPubkey(scratch, (short)0); short length = attestationKeyPair.getPubkey(scratch, (short)0);
cborEncoder.encodeByteString(scratch, (short)0, length); cborEncoder.encodeByteString(scratch, (short)0, length);
cborEncoder.encodeByteString(idSecret.encryptedCx, (short)0, (short)idSecret.encryptedCx.length); cborEncoder.encodeByteString(idSecret.encryptedCx, (short)0, (short)idSecret.encryptedCx.length);
//for test
idSecret.getHMAC(scratch, (short)0);
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength(cborEncoder.getCurrentOffset()); apdu.setOutgoingLength(cborEncoder.getCurrentOffset());
apdu.sendBytesLong(dataBuffer, (short)0, cborEncoder.getCurrentOffset()); apdu.sendBytesLong(dataBuffer, (short)0, cborEncoder.getCurrentOffset());
...@@ -548,8 +552,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -548,8 +552,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Start to build into the cbor array manually, to avoid arrayCopy // Start to build into the cbor array manually, to avoid arrayCopy
// Create a map with 3 things // Create a map with 3 things
// cborEncoder.startMap((short) 3);
cborEncoder.startMap((short) 3); cborEncoder.startMap((short) 4);
// Add the alg label // Add the alg label
cborEncoder.encodeTextString(Utf8Strings.UTF8_ALG, (short) 0, (short) 3); cborEncoder.encodeTextString(Utf8Strings.UTF8_ALG, (short) 0, (short) 3);
// Add the actual algorithm - -7 is 6 as a negative // Add the actual algorithm - -7 is 6 as a negative
...@@ -571,6 +575,29 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -571,6 +575,29 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Supposedly we need an array here // Supposedly we need an array here
cborEncoder.startArray((short) 1); cborEncoder.startArray((short) 1);
cborEncoder.encodeByteString(attestationKeyPair.x509cert, (short) 0, attestationKeyPair.x509len); cborEncoder.encodeByteString(attestationKeyPair.x509cert, (short) 0, attestationKeyPair.x509len);
/**
* extension
*/
// add extension label
cborEncoder.encodeTextString(Utf8Strings.UTF8_EXTENSIONS, (short)0, (short)Utf8Strings.UTF8_EXTENSIONS.length);
// add extension element
cborEncoder.startArray((short)2);
// add HMAC
// cborEncoder.encodeTextString(Utf8Strings.UTF8_HMAC, (short)0, (short)Utf8Strings.UTF8_HMAC.length );
cborEncoder.encodeByteString(idSecret.hmac, (short)0, (short)idSecret.hmac.length);
// // add Cx
// cborEncoder.encodeTextString(Utf8Strings.UTF8_Cx, (short)0, (short)Utf8Strings.UTF8_Cx.length);
cborEncoder.encodeByteString(idSecret.encryptedCx, (short)0, (short)idSecret.encryptedCx.length);
/**
* end extension
*/
// We're actually done, send this out // We're actually done, send this out
sendLongChaining(apdu, cborEncoder.getCurrentOffset()); sendLongChaining(apdu, cborEncoder.getCurrentOffset());
......
package com.josh.vku2f; package com.josh.vku2f;
import javacard.framework.JCSystem;
import javacard.framework.Util; import javacard.framework.Util;
import javacard.security.AESKey; import javacard.security.AESKey;
import javacard.security.KeyBuilder; import javacard.security.KeyBuilder;
...@@ -18,14 +19,17 @@ public class IDSecret { ...@@ -18,14 +19,17 @@ public class IDSecret {
private final byte[] RxRp = new byte[4]; private final byte[] RxRp = new byte[4];
public final byte[] PuKp = new byte[65]; public final byte[] PuKp = new byte[65];
public final byte[] sharedSecret = new byte[20]; public final byte[] sharedSecret = new byte[20];
public final byte[] aesRawKey = new byte[32];
public final byte[] Cx = new byte[16]; public final byte[] Cx = new byte[16];
public final byte[] encryptedCx = new byte[16]; public final byte[] encryptedCx = new byte[16];
public final byte[] aesRawKey = new byte[32]; public final byte[] hmac = new byte[32];
private AESKey aesKey; private AESKey aesKey;
private Cipher aesEncrypt; private Cipher aesEncrypt;
private Cipher aesDecrypt; private Cipher aesDecrypt;
private final byte[] IV_ZERO_AES = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private final byte[] IV_ZERO_AES = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
private MessageDigest sha256; private MessageDigest sha256;
private byte[] scratch;
private final short SCRATCH_LENGTH = (short)128 ;
public IDSecret(){ public IDSecret(){
IDx = new DomString(Utf8Strings.UTF8_NULL, (short)Utf8Strings.UTF8_NULL.length); IDx = new DomString(Utf8Strings.UTF8_NULL, (short)Utf8Strings.UTF8_NULL.length);
...@@ -37,9 +41,10 @@ public class IDSecret { ...@@ -37,9 +41,10 @@ public class IDSecret {
Util.arrayFill(PuKp, (short)1, (byte)(PuKp.length-1), (byte)0); Util.arrayFill(PuKp, (short)1, (byte)(PuKp.length-1), (byte)0);
Util.arrayFill(sharedSecret, (short)0, (byte)sharedSecret.length, (byte)0); Util.arrayFill(sharedSecret, (short)0, (byte)sharedSecret.length, (byte)0);
Util.arrayFill(aesRawKey, (short)0, (byte)aesRawKey.length, (byte)0);
Random.getInstance().nextBytes(Cx, (short)0, (short)Cx.length); Random.getInstance().nextBytes(Cx, (short)0, (short)Cx.length);
Util.arrayFill(encryptedCx, (short)0, (byte)encryptedCx.length, (byte)0); Util.arrayFill(encryptedCx, (short)0, (byte)encryptedCx.length, (byte)0);
Util.arrayFill(aesRawKey, (short)0, (byte)aesRawKey.length, (byte)0); Util.arrayFill(hmac, (short)0, (byte)hmac.length, (byte)0);
aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
...@@ -47,6 +52,7 @@ public class IDSecret { ...@@ -47,6 +52,7 @@ public class IDSecret {
aesDecrypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); aesDecrypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
// //
sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false); sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
scratch = JCSystem.makeTransientByteArray(SCRATCH_LENGTH, JCSystem.CLEAR_ON_DESELECT);
} }
private byte i = (short)0; private byte i = (short)0;
public byte[] getRxRp(){ public byte[] getRxRp(){
...@@ -67,13 +73,33 @@ public class IDSecret { ...@@ -67,13 +73,33 @@ public class IDSecret {
aesEncrypt.doFinal(Cx, (short)0, (short)Cx.length, encryptedCx, (short)0); aesEncrypt.doFinal(Cx, (short)0, (short)Cx.length, encryptedCx, (short)0);
} }
/**
* AES(aesRawKey, SHA256(IDx||Cx))
*/
public void getHMAC(byte[] outputBuffer, short outputOffset){
Util.arrayCopy(IDx.str, (short)0, scratch, (short)0, (short)IDx.str.length);
Util.arrayCopy(Cx, (short)0, scratch, (short)IDx.str.length, (short)Cx.length);
short scratchLength = (short)(IDx.str.length + Cx.length);
short updateOffset = (short)0;
while(scratchLength > (byte)32){
sha256.update(scratch, updateOffset, (byte)32);
scratchLength -= (byte)32;
updateOffset += (byte)32;
}
sha256.doFinal(scratch, updateOffset, scratchLength, scratch, (short)0);
aesEncrypt.update(scratch, (short)0, (short)16, outputBuffer, outputOffset);
aesEncrypt.doFinal(scratch, (short)16, (short)16 , outputBuffer, (short)(outputOffset+16) );
Util.arrayCopy(scratch, (short)0, hmac, (short)0, (short)32 );
}
/** /**
* put IDSecret data with CBOR form in dataBuffer * put IDSecret data with CBOR form in dataBuffer
* return data length * return data length
*/ */
public short dump(byte[] dataBuffer, CBOREncoder encoder){ public short dump(byte[] dataBuffer, CBOREncoder encoder){
encoder.init(dataBuffer, (short)0, (short)1200); encoder.init(dataBuffer, (short)0, (short)1200);
encoder.startArray((short)9); encoder.startArray((short)10);
encoder.encodeTextString(IDx.str, (short)0, IDx.len); encoder.encodeTextString(IDx.str, (short)0, IDx.len);
encoder.encodeByteString(Rx, (short)0, (short)Rx.length); encoder.encodeByteString(Rx, (short)0, (short)Rx.length);
encoder.encodeByteString(Rp, (short)0, (short)Rp.length); encoder.encodeByteString(Rp, (short)0, (short)Rp.length);
...@@ -83,6 +109,7 @@ public class IDSecret { ...@@ -83,6 +109,7 @@ public class IDSecret {
encoder.encodeByteString(aesRawKey, (short)0 , (short)aesRawKey.length); encoder.encodeByteString(aesRawKey, (short)0 , (short)aesRawKey.length);
encoder.encodeByteString(Cx, (short)0, (short)Cx.length); encoder.encodeByteString(Cx, (short)0, (short)Cx.length);
encoder.encodeByteString(encryptedCx, (short)0, (short)encryptedCx.length); encoder.encodeByteString(encryptedCx, (short)0, (short)encryptedCx.length);
encoder.encodeByteString(hmac, (short)0, (short)hmac.length );
return encoder.getCurrentOffset(); return encoder.getCurrentOffset();
} }
......
...@@ -37,4 +37,7 @@ public class Utf8Strings { ...@@ -37,4 +37,7 @@ public class Utf8Strings {
public static final byte[] UTF8_ICON = {'i', 'c', 'o', 'n'}; public static final byte[] UTF8_ICON = {'i', 'c', 'o', 'n'};
public static final byte[] UTF8_NULL = {'n', 'u', 'l', 'l'}; public static final byte[] UTF8_NULL = {'n', 'u', 'l', 'l'};
public static final byte[] UTF8_EXTENSIONS = {'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's'}; public static final byte[] UTF8_EXTENSIONS = {'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's'};
public static final byte[] UTF8_HMAC = {'H', 'M', 'A', 'C'};
public static final byte[] UTF8_Cx = {'C', 'x'};
} }
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