Commit ba3ad98f authored by Josh Ji's avatar Josh Ji

Client Pin not finished

parent d270c116
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
package com.josh.vku2f;
public class COSEKey {
private byte[] w ;
COSEKey(){
w = new byte[64];
}
public void setW(byte[] w){
this.w = w;
}
public byte[] getW(){
return w;
}
public void encode(CBOREncoder cborEncoder){
}
}
...@@ -24,22 +24,17 @@ import javacard.framework.ISOException; ...@@ -24,22 +24,17 @@ import javacard.framework.ISOException;
import javacard.framework.JCSystem; import javacard.framework.JCSystem;
import javacard.framework.UserException; import javacard.framework.UserException;
import javacard.framework.Util; import javacard.framework.Util;
import javacard.security.ECKey; import javacard.security.*;
import javacard.security.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.MessageDigest;
import javacard.security.Signature;
import javacardx.apdu.ExtendedLength; import javacardx.apdu.ExtendedLength;
import static com.josh.vku2f.CTAP2ErrorCode.*; import static com.josh.vku2f.CTAP2ErrorCode.*;
import static com.josh.vku2f.ClientPINSubCommand.*;
public class CTAP2 extends Applet implements ExtendedLength { public class CTAP2 extends Applet implements ExtendedLength {
private final CBORDecoder cborDecoder; private final CBORDecoder cborDecoder;
private final CBOREncoder cborEncoder; private final CBOREncoder cborEncoder;
private byte[] inputBuffer; private byte[] dataBuffer;
private byte[] scratch; private byte[] scratch;
private byte[] info; private byte[] info;
...@@ -52,11 +47,17 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -52,11 +47,17 @@ public class CTAP2 extends Applet implements ExtendedLength {
private final AttestationKeyPair attestationKeyPair; private final AttestationKeyPair attestationKeyPair;
private CredentialArray credentialArray; private CredentialArray credentialArray;
private AuthenticatorGetAssertion authenticatorGetAssertion;
private AuthenticatorMakeCredential authenticatorMakeCredential; private AuthenticatorMakeCredential authenticatorMakeCredential;
private AuthenticatorGetAssertion authenticatorGetAssertion;
private final KeyPair ecDhKeyPair; private final ClientPINCommand clientPINCommand;
private final boolean[] ecDhSet;
private byte MAX_PIN_RETRIES = (byte) 0x08;
private byte MAX_UV_RETRIES = (byte) 0x08;
private byte pinRetries;
private byte uvRetries;
// private final KeyPair ecDhKeyPair;
// private final boolean[] ecDhSet;
private PinUvAuthProtocolOne pinUvAuthProtocolOne;
private final boolean[] isChaining; private final boolean[] isChaining;
private final boolean[] isOutChaining; private final boolean[] isOutChaining;
private boolean personalizeComplete; private boolean personalizeComplete;
...@@ -96,9 +97,9 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -96,9 +97,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 {
inputBuffer = JCSystem.makeTransientByteArray((short) 1210, JCSystem.CLEAR_ON_DESELECT); dataBuffer = JCSystem.makeTransientByteArray((short) 1210, JCSystem.CLEAR_ON_DESELECT);
} catch (Exception e) { } catch (Exception e) {
inputBuffer = new byte[1210]; dataBuffer = new byte[1210];
} }
try { try {
scratch = JCSystem.makeTransientByteArray((short) 512, JCSystem.CLEAR_ON_DESELECT); scratch = JCSystem.makeTransientByteArray((short) 512, JCSystem.CLEAR_ON_DESELECT);
...@@ -122,8 +123,9 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -122,8 +123,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false); JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false);
ECPrivateKey ecDhPriv = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PRIVATE, ECPrivateKey ecDhPriv = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PRIVATE,
JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false); JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false);
ecDhKeyPair = new KeyPair(ecDhPub, ecDhPriv); clientPINCommand = new ClientPINCommand();
ecDhSet = JCSystem.makeTransientBooleanArray((short) 1, JCSystem.CLEAR_ON_RESET); // ecDhKeyPair = new KeyPair(ecDhPub, ecDhPriv);
// ecDhSet = JCSystem.makeTransientBooleanArray((short) 1, JCSystem.CLEAR_ON_RESET);
} }
...@@ -139,7 +141,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -139,7 +141,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
return; return;
} }
// Need to grab the CTAP command byte // Need to grab the CTAP command byte
switch (inputBuffer[0]) { switch (dataBuffer[0]) {
case FIDO2_AUTHENTICATOR_MAKE_CREDENTIAL: case FIDO2_AUTHENTICATOR_MAKE_CREDENTIAL:
authMakeCredential(apdu, tempVars[3]); authMakeCredential(apdu, tempVars[3]);
break; break;
...@@ -202,11 +204,11 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -202,11 +204,11 @@ public class CTAP2 extends Applet implements ExtendedLength {
returnError(apdu, CTAP1_ERR_INVALID_COMMAND); returnError(apdu, CTAP1_ERR_INVALID_COMMAND);
return; return;
} }
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
tempVars[0] = (short) (attestationKeyPair.getPubkey(inputBuffer, (short) 1) + 1); tempVars[0] = (short) (attestationKeyPair.getPubkey(dataBuffer, (short) 1) + 1);
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength(tempVars[0]); apdu.setOutgoingLength(tempVars[0]);
apdu.sendBytesLong(inputBuffer, (short) 0, tempVars[0]); apdu.sendBytesLong(dataBuffer, (short) 0, tempVars[0]);
} }
/** get counter's value */ /** get counter's value */
...@@ -214,8 +216,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -214,8 +216,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
short count = credentialArray.getCount(); short count = credentialArray.getCount();
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength((short)2); apdu.setOutgoingLength((short)2);
Util.setShort(inputBuffer,(short)0, count); Util.setShort(dataBuffer,(short)0, count);
apdu.sendBytesLong(inputBuffer,(short)0,(short)2); apdu.sendBytesLong(dataBuffer,(short)0,(short)2);
} }
/** /**
...@@ -229,12 +231,12 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -229,12 +231,12 @@ public class CTAP2 extends Applet implements ExtendedLength {
returnError(apdu, CTAP1_ERR_INVALID_COMMAND); returnError(apdu, CTAP1_ERR_INVALID_COMMAND);
return; return;
} }
Util.arrayCopy(inputBuffer, (short) 1, scratch, (short) 0, (short) (bufLen - 1)); Util.arrayCopy(dataBuffer, (short) 1, scratch, (short) 0, (short) (bufLen - 1));
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
tempVars[2] = attestationKeyPair.sign(scratch, (short) 0, tempVars[1], inputBuffer, (short) 1); tempVars[2] = attestationKeyPair.sign(scratch, (short) 0, tempVars[1], dataBuffer, (short) 1);
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength((short) (tempVars[2] + 1)); apdu.setOutgoingLength((short) (tempVars[2] + 1));
apdu.sendBytesLong(inputBuffer, (short) 0, (short) (tempVars[2] + 1)); apdu.sendBytesLong(dataBuffer, (short) 0, (short) (tempVars[2] + 1));
} }
public void attestSetCert(APDU apdu, short bufLen) { public void attestSetCert(APDU apdu, short bufLen) {
...@@ -243,19 +245,19 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -243,19 +245,19 @@ public class CTAP2 extends Applet implements ExtendedLength {
return; return;
} }
// We don't actually use any CBOR here, simplify copying // We don't actually use any CBOR here, simplify copying
attestationKeyPair.setCert(inputBuffer, (short) 1, (short) (bufLen - 1)); attestationKeyPair.setCert(dataBuffer, (short) 1, (short) (bufLen - 1));
MessageDigest dig = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false); MessageDigest dig = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
short len = (short) (dig.doFinal(attestationKeyPair.x509cert, (short) 0, attestationKeyPair.x509len, inputBuffer, (short) 3) + 3); short len = (short) (dig.doFinal(attestationKeyPair.x509cert, (short) 0, attestationKeyPair.x509len, dataBuffer, (short) 3) + 3);
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
Util.setShort(inputBuffer, (short) 1, attestationKeyPair.x509len); Util.setShort(dataBuffer, (short) 1, attestationKeyPair.x509len);
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength(len); apdu.setOutgoingLength(len);
apdu.sendBytesLong(inputBuffer, (short) 0, len); apdu.sendBytesLong(dataBuffer, (short) 0, len);
} }
public void authMakeCredential(APDU apdu, short bufLen) { public void authMakeCredential(APDU apdu, short bufLen) {
// Init the decoder // Init the decoder
cborDecoder.init(inputBuffer, (short) 1, bufLen); cborDecoder.init(dataBuffer, (short) 1, bufLen);
// create a credential object // create a credential object
try { try {
authenticatorMakeCredential = new AuthenticatorMakeCredential(cborDecoder); authenticatorMakeCredential = new AuthenticatorMakeCredential(cborDecoder);
...@@ -293,10 +295,10 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -293,10 +295,10 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Initialise the output buffer, for CBOR writing. // Initialise the output buffer, for CBOR writing.
// output buffer needs 0x00 as first byte as status code // output buffer needs 0x00 as first byte as status code
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
cborEncoder.init(inputBuffer, (short) 1, (short) 1199); cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
// Create a map in the buffer // Create a map in the buffer
tempVars[0] = cborEncoder.startMap((short) 3); tempVars[0] = cborEncoder.startMap((short) 3); // current offset
// Attestation stuff // Attestation stuff
cborEncoder.writeRawByte((byte) 0x01); cborEncoder.writeRawByte((byte) 0x01);
...@@ -310,14 +312,14 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -310,14 +312,14 @@ public class CTAP2 extends Applet implements ExtendedLength {
tempVars[7] = tempVars[0]; tempVars[7] = tempVars[0];
// Create the SHA256 hash of the RP ID // Create the SHA256 hash of the RP ID
tempCredential.rpEntity.getRp(scratch, (short) 0); tempCredential.rpEntity.getRp(scratch, (short) 0);
tempVars[0] += sha256MessageDigest.doFinal(scratch, (short) 0, tempCredential.rpEntity.getRpLen(), inputBuffer, tempVars[0]); tempVars[0] += sha256MessageDigest.doFinal(scratch, (short) 0, tempCredential.rpEntity.getRpLen(), dataBuffer, tempVars[0]);
// Set flags - User presence, user verified, attestation present // Set flags - User presence, user verified, attestation present
inputBuffer[tempVars[0]++] = (byte) 0x45; dataBuffer[tempVars[0]++] = (byte) 0x45;
// Set the signature counter // Set the signature counter
tempVars[0] += tempCredential.readCounter(inputBuffer, tempVars[0]); tempVars[0] += tempCredential.readCounter(dataBuffer, tempVars[0]);
// Read the credential details in // Read the credential details in
// Just note down where this starts for future ref // Just note down where this starts for future ref
tempVars[0] += tempCredential.getAttestedData(inputBuffer, tempVars[0]); tempVars[0] += tempCredential.getAttestedData(dataBuffer, tempVars[0]);
// Generate and then attach the attestation // Generate and then attach the attestation
cborEncoder.writeRawByte((byte) 0x03); cborEncoder.writeRawByte((byte) 0x03);
...@@ -337,7 +339,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -337,7 +339,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
// We sign over the client data hash and the attested data. // We sign over the client data hash and the attested data.
// AuthenticatorData is first. We noted down where it begins and know how long // AuthenticatorData is first. We noted down where it begins and know how long
// it is. // it is.
attestationKeyPair.update(inputBuffer, tempVars[7], (short) (tempCredential.getAttestedLen() + 37)); attestationKeyPair.update(dataBuffer, tempVars[7], (short) (tempCredential.getAttestedLen() + 37));
// The client data hash is next, which we use to finish off the signature. // The client data hash is next, which we use to finish off the signature.
tempVars[4] = attestationKeyPair.sign(authenticatorMakeCredential.dataHash, (short) 0, (short) authenticatorMakeCredential.dataHash.length, scratch, (short) 0); tempVars[4] = attestationKeyPair.sign(authenticatorMakeCredential.dataHash, (short) 0, (short) authenticatorMakeCredential.dataHash.length, scratch, (short) 0);
// Create the byte string for the signature // Create the byte string for the signature
...@@ -361,7 +363,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -361,7 +363,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
public void authGetAssertion(APDU apdu, short bufLen) { public void authGetAssertion(APDU apdu, short bufLen) {
nextAssertion[0] = (short) 0; nextAssertion[0] = (short) 0;
// Decode the CBOR array for the assertion // Decode the CBOR array for the assertion
cborDecoder.init(inputBuffer, (short) 1, bufLen); cborDecoder.init(dataBuffer, (short) 1, bufLen);
try { try {
authenticatorGetAssertion = new AuthenticatorGetAssertion(cborDecoder); authenticatorGetAssertion = new AuthenticatorGetAssertion(cborDecoder);
} catch (UserException e) { } catch (UserException e) {
...@@ -391,9 +393,9 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -391,9 +393,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Create the output // Create the output
// Status flags first // Status flags first
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
// Create the encoder // Create the encoder
cborEncoder.init(inputBuffer, (short) 1, (short) 1199); cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
// Determine if we need 4 or 5 in the array // Determine if we need 4 or 5 in the array
if (assertionCredentials.length > 1) { if (assertionCredentials.length > 1) {
doAssertionCommon(cborEncoder, (short) 5); doAssertionCommon(cborEncoder, (short) 5);
...@@ -425,11 +427,11 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -425,11 +427,11 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Copy the hash in // Copy the hash in
authenticatorGetAssertion.getHash(scratch, (short) 37); authenticatorGetAssertion.getHash(scratch, (short) 37);
// Create the output // Create the output
String a = "adfadsfa";
// Status flags first // Status flags first
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
// Create the encoder // Create the encoder
cborEncoder.init(inputBuffer, (short) 1, (short) 1199); cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
doAssertionCommon(cborEncoder, (short) 4); doAssertionCommon(cborEncoder, (short) 4);
nextAssertion[0]++; nextAssertion[0]++;
...@@ -440,35 +442,64 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -440,35 +442,64 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Process the AuthenticatorClientPin feature // Process the AuthenticatorClientPin feature
// Note: we only implement the keyAgreement bit // Note: we only implement the keyAgreement bit
public void clientPin(APDU apdu, short bufLen) { public void clientPin(APDU apdu, short bufferLength) {
try { try {
cborDecoder.init(inputBuffer, (short) 1, bufLen); cborDecoder.init(dataBuffer, (short) 1, bufferLength);
// Start reading // Start reading
cborDecoder.readMajorType(CBORBase.TYPE_MAP); clientPINCommand.decodeCommand(cborDecoder);
// Read pinUvAuthProtocol
if (cborDecoder.readInt8() != (byte) 0x01) { switch(clientPINCommand.getSubCommandCode()){
UserException.throwIt(CTAP2_ERR_INVALID_CBOR); case SUBCOMMAND_GET_PIN_RETRIES:
return; dataBuffer[0] = 0x00;
} cborEncoder.init(dataBuffer, (short)1, (short)(1199));
// Read subCommand cborEncoder.startMap(ClientPINResponse.PIN_RETRIES);
if (cborDecoder.readInt8() != (byte) 0x01) { cborEncoder.encodeUInt8(pinRetries);
UserException.throwIt(CTAP2_ERR_INVALID_CBOR); break;
return; case SUBCOMMAND_GET_KEY_AGREEMENT:
} dataBuffer[0] = 0x00;
// Subcommand now cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
if (cborDecoder.readInt8() != (byte) 0x02) { // Start a map
UserException.throwIt(CTAP2_ERR_INVALID_CBOR); cborEncoder.startMap((short) 1);
return; // Encode the COSE key identifier
} cborEncoder.encodeUInt8((byte) 0x01);
// Actual subcommand // Start the COSE map
switch (cborDecoder.readInt8()) { cborEncoder.startMap((short) 5);
case 0x02: // Kty tag
// Seems to be a Diffie-Hellman thing cborEncoder.encodeUInt8((byte) 0x01);
generateDH(apdu); // Kty value - EC2
cborEncoder.encodeUInt8((byte) 0x02);
// Alg tag
cborEncoder.encodeUInt8((byte) 0x03);
// Alg value - ES256 (-7, 6 in negative format)
cborEncoder.encodeNegativeUInt8((byte) 0x06);
// Crv tag - negative
cborEncoder.encodeNegativeUInt8((byte) 0x00);
// Crv value - P-256
cborEncoder.encodeUInt8((byte) 0x01);
// X-coord tag
cborEncoder.encodeNegativeUInt8((byte) 0x01);
// X-coord value
cborEncoder.encodeByteString(pinUvAuthProtocolOne.getPublicKey(), (short) 1, (short) 32);
// Y-coord tag
cborEncoder.encodeNegativeUInt8((byte) 0x02);
// Y-coord value
cborEncoder.encodeByteString(pinUvAuthProtocolOne.getPublicKey(), (short) 33, (short) 32);
break;
case SUBCOMMAND_SET_PIN:
break;
case SUBCOMMAND_CHANGE_PIN:
break;
case SUBCOMMAND_GET_PIN_TOKEN:
break;
case SUBCOMMAND_GET_PIN_UV_AUTH_TOKEN_UV:
break;
case SUBCOMMAND_GET_UV_RETRIES:
break;
case SUBCOMMAND_GET_PIN_UV_AUTH_TOKEN_PIN:
break; break;
default:
UserException.throwIt(CTAP2_ERR_UNSUPPORTED_OPTION);
} }
// That's it
sendLongChaining(apdu, cborEncoder.getCurrentOffset());
} catch (UserException e) { } catch (UserException e) {
returnError(apdu, e.getReason()); returnError(apdu, e.getReason());
} }
...@@ -483,58 +514,6 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -483,58 +514,6 @@ public class CTAP2 extends Applet implements ExtendedLength {
} }
} }
// Generate a session-specific ECDH P-256 key for Diffie-Hellman with the
// platform (Used for PIN ,but we only ever do it for hmac-secret)
private void generateDH(APDU apdu) {
byte[] w;
try {
w = JCSystem.makeTransientByteArray((short) 65, JCSystem.CLEAR_ON_RESET);
} catch (Exception e) {
w = new byte[65];
}
if (!ecDhSet[0]) {
// Grab the public key and set its parameters
KeyParams.sec256r1params((ECKey) ecDhKeyPair.getPublic());
// Generate a new key-pair
ecDhKeyPair.genKeyPair();
}
((ECPublicKey) ecDhKeyPair.getPublic()).getW(w, (short) 0);
// Return the data requested
inputBuffer[0] = 0x00;
cborEncoder.init(inputBuffer, (short) 1, (short) 1199);
// Start a map
cborEncoder.startMap((short) 1);
// Encode the COSE key identifier
cborEncoder.encodeUInt8((byte) 0x01);
// Start the COSE map
cborEncoder.startMap((short) 5);
// Kty tag
cborEncoder.encodeUInt8((byte) 0x01);
// Kty value - EC2
cborEncoder.encodeUInt8((byte) 0x02);
// Alg tag
cborEncoder.encodeUInt8((byte) 0x03);
// Alg value - ES256 (-7, 6 in negative format)
cborEncoder.encodeNegativeUInt8((byte) 0x06);
// Crv tag - negative
cborEncoder.encodeNegativeUInt8((byte) 0x00);
// Crv value - P-256
cborEncoder.encodeUInt8((byte) 0x01);
// X-coord tag
cborEncoder.encodeNegativeUInt8((byte) 0x01);
// X-coord value
cborEncoder.encodeByteString(w, (short) 1, (short) 32);
// Y-coord tag
cborEncoder.encodeNegativeUInt8((byte) 0x02);
// Y-coord value
cborEncoder.encodeByteString(w, (short) 33, (short) 32);
// That's it
sendLongChaining(apdu, cborEncoder.getCurrentOffset());
}
/** /**
* Finds all credentials scoped to the RpId, and optionally the allowList, in * Finds all credentials scoped to the RpId, and optionally the allowList, in
...@@ -669,8 +648,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -669,8 +648,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Create the authenticator info if not present. // Create the authenticator info if not present.
if (info == null) { if (info == null) {
// Create the authGetInfo - 0x00 is success // Create the authGetInfo - 0x00 is success
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
cborEncoder.init(inputBuffer, (short) 1, (short) 1199); cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
cborEncoder.startMap((short) 4); cborEncoder.startMap((short) 4);
// 0x01, versions // 0x01, versions
cborEncoder.encodeUInt8((byte) 0x01); cborEncoder.encodeUInt8((byte) 0x01);
...@@ -700,11 +679,11 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -700,11 +679,11 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Done // Done
JCSystem.beginTransaction(); JCSystem.beginTransaction();
info = new byte[cborEncoder.getCurrentOffset()]; info = new byte[cborEncoder.getCurrentOffset()];
Util.arrayCopy(inputBuffer, (short) 0, info, (short) 0, cborEncoder.getCurrentOffset()); Util.arrayCopy(dataBuffer, (short) 0, info, (short) 0, cborEncoder.getCurrentOffset());
JCSystem.commitTransaction(); JCSystem.commitTransaction();
} }
// Send it // Send it
Util.arrayCopyNonAtomic(info, (short) 0, inputBuffer, (short) 0, (short) info.length); Util.arrayCopyNonAtomic(info, (short) 0, dataBuffer, (short) 0, (short) info.length);
sendLongChaining(apdu, (short) info.length); sendLongChaining(apdu, (short) info.length);
} }
...@@ -845,22 +824,22 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -845,22 +824,22 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Copy buffer // Copy buffer
chainRam[1] = tempVars[4]; chainRam[1] = tempVars[4];
// chainRam[0] is the current point in the buffer we start from // chainRam[0] is the current point in the buffer we start from
chainRam[0] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), inputBuffer, chainRam[0], chainRam[1]); chainRam[0] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), dataBuffer, chainRam[0], chainRam[1]);
return 0x00; return 0x00;
} else if (isChaining[0]) { } else if (isChaining[0]) {
// Must be the last of the chaining - make the copy and return the length. // Must be the last of the chaining - make the copy and return the length.
chainRam[1] = tempVars[4]; chainRam[1] = tempVars[4];
chainRam[0] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), inputBuffer, chainRam[0], chainRam[1]); chainRam[0] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), dataBuffer, chainRam[0], chainRam[1]);
isChaining[0] = false; isChaining[0] = false;
isChaining[1] = true; isChaining[1] = true;
return chainRam[0]; return chainRam[0];
} else if (tempVars[3] == 0x01) { } else if (tempVars[3] == 0x01) {
inputBuffer[0] = buffer[apdu.getOffsetCdata()]; dataBuffer[0] = buffer[apdu.getOffsetCdata()];
return 0x01; return 0x01;
} else if (apdu.getCurrentState() == APDU.STATE_FULL_INCOMING) { } else if (apdu.getCurrentState() == APDU.STATE_FULL_INCOMING) {
// We need to do no more // We need to do no more
// Read the entirety of the buffer into the inBuf // Read the entirety of the buffer into the inBuf
Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), inputBuffer, (short) 0, tempVars[3]); Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), dataBuffer, (short) 0, tempVars[3]);
return tempVars[4]; return tempVars[4];
} else { } else {
// The APDU needs a multi-stage copy // The APDU needs a multi-stage copy
...@@ -871,7 +850,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -871,7 +850,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
tempVars[4] = 0; tempVars[4] = 0;
while (tempVars[3] > 0) { while (tempVars[3] > 0) {
// Copy data // Copy data
tempVars[4] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), inputBuffer, tempVars[4], tempVars[5]); tempVars[4] = Util.arrayCopyNonAtomic(buffer, apdu.getOffsetCdata(), dataBuffer, tempVars[4], tempVars[5]);
// Decrement vars[3] by the bytes copied // Decrement vars[3] by the bytes copied
tempVars[3] -= tempVars[5]; tempVars[3] -= tempVars[5];
// Pull more bytes // Pull more bytes
...@@ -895,7 +874,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -895,7 +874,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
// More to go after this // More to go after this
outChainRam[0] -= 256; outChainRam[0] -= 256;
byte[] buf = apdu.getBuffer(); byte[] buf = apdu.getBuffer();
Util.arrayCopyNonAtomic(inputBuffer, outChainRam[1], buf, (short) 0, (short) 256); Util.arrayCopyNonAtomic(dataBuffer, outChainRam[1], buf, (short) 0, (short) 256);
apdu.setOutgoingAndSend((short) 0, (short) 256); apdu.setOutgoingAndSend((short) 0, (short) 256);
outChainRam[1] += 256; outChainRam[1] += 256;
if (outChainRam[0] > 255) { if (outChainRam[0] > 255) {
...@@ -908,7 +887,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -908,7 +887,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
} else { } else {
// This is the last message // This is the last message
byte[] buf = apdu.getBuffer(); byte[] buf = apdu.getBuffer();
Util.arrayCopyNonAtomic(inputBuffer, outChainRam[1], buf, (short) 0, outChainRam[0]); Util.arrayCopyNonAtomic(dataBuffer, outChainRam[1], buf, (short) 0, outChainRam[0]);
apdu.setOutgoingAndSend((short) 0, outChainRam[0]); apdu.setOutgoingAndSend((short) 0, outChainRam[0]);
isOutChaining[0] = false; isOutChaining[0] = false;
outChainRam[0] = 0; outChainRam[0] = 0;
...@@ -932,7 +911,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -932,7 +911,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
outChainRam[0] = (short) (dataLen - 256); outChainRam[0] = (short) (dataLen - 256);
// Send the first 256 bytes out // Send the first 256 bytes out
byte[] buf = apdu.getBuffer(); byte[] buf = apdu.getBuffer();
Util.arrayCopyNonAtomic(inputBuffer, (short) 0, buf, (short) 0, (short) 256); Util.arrayCopyNonAtomic(dataBuffer, (short) 0, buf, (short) 0, (short) 256);
apdu.setOutgoingAndSend((short) 0, (short) 256); apdu.setOutgoingAndSend((short) 0, (short) 256);
outChainRam[1] = 256; outChainRam[1] = 256;
// Throw the 61 xx // Throw the 61 xx
...@@ -948,7 +927,7 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -948,7 +927,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
isOutChaining[0] = false; isOutChaining[0] = false;
apdu.setOutgoing(); apdu.setOutgoing();
apdu.setOutgoingLength(dataLen); apdu.setOutgoingLength(dataLen);
apdu.sendBytesLong(inputBuffer, (short) 0, dataLen); apdu.sendBytesLong(dataBuffer, (short) 0, dataLen);
ISOException.throwIt(ISO7816.SW_NO_ERROR); ISOException.throwIt(ISO7816.SW_NO_ERROR);
} }
} }
...@@ -963,8 +942,8 @@ public class CTAP2 extends Applet implements ExtendedLength { ...@@ -963,8 +942,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
} }
private void getCert(APDU apdu) { private void getCert(APDU apdu) {
inputBuffer[0] = 0x00; dataBuffer[0] = 0x00;
tempVars[0] = (short) (attestationKeyPair.getCert(inputBuffer, (short) 1) + 1); tempVars[0] = (short) (attestationKeyPair.getCert(dataBuffer, (short) 1) + 1);
sendLongChaining(apdu, tempVars[0]); sendLongChaining(apdu, tempVars[0]);
} }
......
package com.josh.vku2f;
import javacard.framework.JCSystem;
public class ClientPIN {
private short i; // counter
private byte[] PIN ;
private boolean[] checked;
ClientPIN(){
checked = JCSystem.makeTransientBooleanArray((short)1, JCSystem.CLEAR_ON_DESELECT);
}
public boolean checkPIN(byte[] pin){
if(PIN.length != pin.length){
return false;
}
for(i = 0; i < PIN.length; i++){
if(PIN[i] != pin[i]) {
return false;
}
}
checked[0] = true;
return true;
}
public void setPIN(){
}
}
package com.josh.vku2f;
import javacard.framework.UserException;
public class ClientPINCommand {
public static final byte PARAMETER_PROTOCOL = 0x01;
public static final byte PARAMETER_SUBCOMMAND = 0x02;
public static final byte PARAMETER_KEY_AGREEMENT = 0x03;
public static final byte PARAMETER_PIN_UV_AUTH_PARAM = 0x04;
public static final byte PARAMETER_NEW_PIN_ENC = 0x05;
public static final byte PARAMETER_PIN_HASH_ENC = 0x06;
public static final byte PARAMETER_PERMISSIONS = 0x09;
public static final byte PARAMETER_RP_ID = 0x0A;
private byte protocol; // unsigned int
private byte subCommandCode; // unsigned int
private byte[] keyAgreement; // COSE object
private byte[] pinUvAuthParam; // byte string
private byte[] newPinEnc; // byte string
private byte[] pinHashEnc; // byte string
private byte permissions; // unsigned int
private byte[] rpId; // text string
public void decodeCommand(CBORDecoder cborDecoder) throws UserException {
short commandLength = cborDecoder.readMajorType(CBORBase.TYPE_MAP);
do {
byte commandKey = cborDecoder.readInt8();
short valueLength;
switch (commandKey) {
case PARAMETER_PROTOCOL:
protocol = cborDecoder.readInt8();
break;
case PARAMETER_SUBCOMMAND:
subCommandCode = cborDecoder.readInt8();
break;
case PARAMETER_KEY_AGREEMENT:
valueLength = cborDecoder.readLength();
keyAgreement = new byte[valueLength];
cborDecoder.readRawByteArray(keyAgreement, (short) 0, valueLength);
break;
case PARAMETER_PIN_UV_AUTH_PARAM:
valueLength = cborDecoder.readLength();
pinUvAuthParam = new byte[valueLength];
cborDecoder.readRawByteArray(pinUvAuthParam, (short) 0, valueLength);
break;
case PARAMETER_NEW_PIN_ENC:
valueLength = cborDecoder.readLength();
newPinEnc = new byte[valueLength];
cborDecoder.readRawByteArray(newPinEnc, (short) 0, valueLength);
break;
case PARAMETER_PIN_HASH_ENC:
valueLength = cborDecoder.readLength();
pinHashEnc = new byte[valueLength];
cborDecoder.readRawByteArray(pinHashEnc, (short) 0, valueLength);
break;
case PARAMETER_PERMISSIONS:
permissions = cborDecoder.readInt8();
break;
case PARAMETER_RP_ID:
valueLength = cborDecoder.readLength();
rpId = new byte[valueLength];
cborDecoder.readRawByteArray(rpId, (short) 0, valueLength);
break;
}
commandLength--;
} while (commandLength >= 1);
}
public byte getProtocol() {
return protocol;
}
public byte getSubCommandCode() {
return subCommandCode;
}
public byte[] getKeyAgreement() {
return keyAgreement;
}
public byte[] getPinUvAuthParam() {
return pinUvAuthParam;
}
public byte[] getNewPinEnc() {
return newPinEnc;
}
public byte[] getPinHashEnc() {
return pinHashEnc;
}
public byte getPermissions() {
return permissions;
}
public byte[] getRpId() {
return rpId;
}
}
package com.josh.vku2f;
public class ClientPINResponse {
public static byte KEY_AGREEMENT = (byte)0x01;
public static byte PIN_UV_AUTH_TOKEN = (byte)0x02;
public static byte PIN_RETRIES = (byte)0x03;
public static byte POWER_CYCLE_STATE = (byte)0x04;
public static byte UV_RETRIES = (byte)0x05;
}
package com.josh.vku2f;
public class ClientPINSubCommand {
public static final byte SUBCOMMAND_GET_PIN_RETRIES = (byte) 0x01;
public static final byte SUBCOMMAND_GET_KEY_AGREEMENT = (byte) 0x02;
public static final byte SUBCOMMAND_SET_PIN = (byte) 0x03;
public static final byte SUBCOMMAND_CHANGE_PIN = (byte) 0x04;
public static final byte SUBCOMMAND_GET_PIN_TOKEN = (byte) 0x05;
public static final byte SUBCOMMAND_GET_PIN_UV_AUTH_TOKEN_UV = (byte) 0x06;
public static final byte SUBCOMMAND_GET_UV_RETRIES = (byte) 0x07;
// no 0x08
public static final byte SUBCOMMAND_GET_PIN_UV_AUTH_TOKEN_PIN = (byte) 0x09;
}
package com.josh.vku2f;
public abstract class PinUvAuthProtocol {
private PinUvAuthToken pinUvAuthToken;
public abstract void initialize();
public abstract void regenerate();
public abstract void resetPinUvAuthToken();
public abstract byte[] getPublicKey();
public abstract byte[] decapsulate(COSEKey peerCoseKey);
public abstract void decrypt(byte[] sharedSecret, byte[] cipherText);
public abstract void verify(byte[] key, byte[] message, byte[] signature);
}
package com.josh.vku2f;
import javacard.framework.JCSystem;
import javacard.security.*;
public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
private KeyPair ecDhKeyPair;
private boolean[] ecDhSet;
@Override
public void initialize() {
ECPublicKey ecDhPub = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PUBLIC,
JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false);
ECPrivateKey ecDhPriv = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_FP_PRIVATE,
JCSystem.MEMORY_TYPE_TRANSIENT_RESET, KeyBuilder.LENGTH_EC_FP_256, false);
ecDhKeyPair = new KeyPair(ecDhPub, ecDhPriv);
ecDhSet = JCSystem.makeTransientBooleanArray((short) 1, JCSystem.CLEAR_ON_RESET);
}
@Override
public void regenerate() {
}
@Override
public void resetPinUvAuthToken() {
}
@Override
public byte[] getPublicKey() {
byte[] w;
try {
w = JCSystem.makeTransientByteArray((short) 65, JCSystem.CLEAR_ON_RESET);
} catch (Exception e) {
w = new byte[65];
}
if (!ecDhSet[0]) {
// Grab the public key and set it's parameters
KeyParams.sec256r1params((ECKey) ecDhKeyPair.getPublic());
// Generate a new key-pair
ecDhKeyPair.genKeyPair();
ecDhSet[0] = true;
}
((ECPublicKey) ecDhKeyPair.getPublic()).getW(w, (short) 0);
// Return the data requested
return w;
}
public byte[] encapsulate(COSEKey peerCOSEKey){
return null;
}
@Override
public byte[] decapsulate(COSEKey peerCOSEKey) {
return null;
}
public byte[] encrypt(byte[] key, byte[] plaintext){
return null;
}
@Override
public void decrypt(byte[] sharedSecret, byte[] cipherText) {
}
public byte[] authenticate(byte[] key, byte[] message){
return null;
}
@Override
public void verify(byte[] key, byte[] message, byte[] signature) {
}
private byte[] ecdh(COSEKey peerCoseKey){
return null;
}
private byte[] kdf(byte[] Z){
return null;
}
}
package com.josh.vku2f;
public class PinUvAuthToken {
private byte[] token;
private byte protocol;
private byte permissionsRPID ;
private byte permissionsSet;
private byte usageTimer;
private boolean inUseFlag;
private byte initialUsageTimeLimit;
private byte userPresentTimeLimit;
private byte maxUsageTimePeriod;
private boolean userVerifiedFlag;
private boolean userPresentFlag;
PinUvAuthToken(){
resetTokenState();
}
public void generateNewToken(){
}
public void resetTokenState(){
permissionsRPID = 0x00;
permissionsSet = 0x00;
usageTimer = 0x00;
inUseFlag = false;
initialUsageTimeLimit = 0x00;
userPresentTimeLimit = 0x00;
maxUsageTimePeriod = 0x00;
userVerifiedFlag = false;
userPresentFlag = false;
}
public boolean isInUse(){
return inUseFlag;
}
}
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