Commit c9d0b00a authored by Josh Ji's avatar Josh Ji

setPin, getPinToken, usePinToken and some dummy or unnecessary stuff while testing and debugging

parent fc423e41
This diff is collapsed.
...@@ -26,6 +26,7 @@ public class AuthenticatorGetAssertion { ...@@ -26,6 +26,7 @@ public class AuthenticatorGetAssertion {
byte[] clientDataHash; byte[] clientDataHash;
boolean[] options; boolean[] options;
PublicKeyCredentialDescriptor[] allow; PublicKeyCredentialDescriptor[] allow;
private byte[] pinUvAuthParam;
public AuthenticatorGetAssertion(CBORDecoder decoder) throws UserException { public AuthenticatorGetAssertion(CBORDecoder decoder) throws UserException {
...@@ -117,8 +118,10 @@ public class AuthenticatorGetAssertion { ...@@ -117,8 +118,10 @@ public class AuthenticatorGetAssertion {
decoder.skipEntry(); decoder.skipEntry();
break; break;
case 0x06: case 0x06:
// Pin stuff // Pin UV Auth Param // 0x06
decoder.skipEntry(); pinUvAuthParam = new byte[16];
if(decoder.readByteString(pinUvAuthParam, (short)0 ) < (short)16)
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
break; break;
case 0x07: case 0x07:
// Pin protocol // Pin protocol
......
...@@ -27,6 +27,7 @@ public class AuthenticatorMakeCredential { ...@@ -27,6 +27,7 @@ public class AuthenticatorMakeCredential {
private PublicKeyCredentialUserEntity user; private PublicKeyCredentialUserEntity user;
private PublicKeyCredentialParams params; private PublicKeyCredentialParams params;
private boolean[] options = new boolean[2]; private boolean[] options = new boolean[2];
private byte[] pinUvAuthParam;
public PublicKeyCredentialDescriptor[] exclude; public PublicKeyCredentialDescriptor[] exclude;
...@@ -282,6 +283,14 @@ public class AuthenticatorMakeCredential { ...@@ -282,6 +283,14 @@ public class AuthenticatorMakeCredential {
} }
decoder.skipEntry(); decoder.skipEntry();
break; break;
case (short)8: // pinUvAuthToken
pinUvAuthParam = new byte[16];
if(decoder.readByteString(pinUvAuthParam, (short)0 ) < (short)16)
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
break;
case (short)9: // pinProtocol
short pinProtocol = decoder.readInt8();
break;
default: default:
// Skip it transparently // Skip it transparently
decoder.skipEntry(); decoder.skipEntry();
...@@ -290,12 +299,16 @@ public class AuthenticatorMakeCredential { ...@@ -290,12 +299,16 @@ public class AuthenticatorMakeCredential {
} }
}
if(pinUvAuthParam == null){
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
} }
// Check we've got stuff like the clientDataHash // Check we've got stuff like the clientDataHash
if(dataHash == null || rp == null || user == null || params == null) { if(dataHash == null || rp == null || user == null || params == null) {
UserException.throwIt(CTAP2_ERR_MISSING_PARAMETER); UserException.throwIt(CTAP2_ERR_MISSING_PARAMETER);
} }
// We're done, I guess // We're done, I guess
} }
...@@ -319,6 +332,14 @@ public class AuthenticatorMakeCredential { ...@@ -319,6 +332,14 @@ public class AuthenticatorMakeCredential {
return (exclude != null && exclude.length > 0); return (exclude != null && exclude.length > 0);
} }
/**
*
* @return pinUvAuthToken
*/
public byte[] getPinUvAuthParam(){
return pinUvAuthParam;
}
/** /**
* Reads the clientDataHash into a buffer. * Reads the clientDataHash into a buffer.
* *
...@@ -326,9 +347,8 @@ public class AuthenticatorMakeCredential { ...@@ -326,9 +347,8 @@ public class AuthenticatorMakeCredential {
* @param outOff the offset to begin at. * @param outOff the offset to begin at.
* @return the length of the data read out. * @return the length of the data read out.
*/ */
public short getDataHash(byte[] outBuf, short outOff) { public byte[] getDataHash() {
Util.arrayCopy(dataHash, (short) 0, outBuf, outOff, (short) dataHash.length); return dataHash;
return (short) dataHash.length;
} }
} }
This diff is collapsed.
...@@ -21,7 +21,7 @@ public class ClientPINCommand { ...@@ -21,7 +21,7 @@ public class ClientPINCommand {
private byte[] y = new byte[32]; // y-coordinate private byte[] y = new byte[32]; // y-coordinate
private byte[] pinUvAuthParam = new byte[64]; // byte string private byte[] pinUvAuthParam = new byte[64]; // byte string
private byte[] newPinEnc = new byte[64]; // byte string private byte[] newPinEnc = new byte[64]; // byte string
private byte[] pinHashEnc = new byte[32]; // byte string private byte[] pinHashEnc = new byte[16]; // byte string, aes256
private byte permissions; // unsigned int private byte permissions; // unsigned int
private byte[] rpId = new byte[64]; // text string private byte[] rpId = new byte[64]; // text string
byte[] scratch = JCSystem.makeTransientByteArray((short)64, JCSystem.CLEAR_ON_RESET); byte[] scratch = JCSystem.makeTransientByteArray((short)64, JCSystem.CLEAR_ON_RESET);
...@@ -61,15 +61,15 @@ public class ClientPINCommand { ...@@ -61,15 +61,15 @@ public class ClientPINCommand {
break; break;
case PARAMETER_PIN_UV_AUTH_PARAM: case PARAMETER_PIN_UV_AUTH_PARAM:
// cborDecoder.readByteString(pinUvAuthParam, (short) 0); cborDecoder.readByteString(pinUvAuthParam, (short) 0);
cborDecoder.skipEntry(); // cborDecoder.skipEntry();
break; break;
case PARAMETER_NEW_PIN_ENC: case PARAMETER_NEW_PIN_ENC:
cborDecoder.readByteString(newPinEnc, (short) 0); cborDecoder.readByteString(newPinEnc, (short) 0);
break; break;
case PARAMETER_PIN_HASH_ENC: case PARAMETER_PIN_HASH_ENC:
// cborDecoder.readByteString(pinHashEnc, (short) 0); cborDecoder.readByteString(pinHashEnc, (short) 0);
cborDecoder.skipEntry(); // cborDecoder.skipEntry();
break; break;
case PARAMETER_PERMISSIONS: case PARAMETER_PERMISSIONS:
// permissions = cborDecoder.readInt8(); // permissions = cborDecoder.readInt8();
...@@ -93,6 +93,10 @@ public class ClientPINCommand { ...@@ -93,6 +93,10 @@ public class ClientPINCommand {
return subCommandCode; return subCommandCode;
} }
/**
*
* @return 0x04 || x-coordinate || y-coordinate
*/
public byte[] getKeyAgreement() { public byte[] getKeyAgreement() {
keyAgreement[0] = 0x04; keyAgreement[0] = 0x04;
Util.arrayCopy(x, (short)0, keyAgreement, (short)1, (short)x.length); Util.arrayCopy(x, (short)0, keyAgreement, (short)1, (short)x.length);
......
...@@ -121,14 +121,19 @@ public class IDSecret { ...@@ -121,14 +121,19 @@ public class IDSecret {
return tempBufferLength; return tempBufferLength;
} }
public void writeTempBuffer(byte[] inputBuffer){ /**
if((short)inputBuffer.length > (short)tempBuffer.length){ *
* @param inputBuffer the buffer copy from
* @param offset output offset
*/
public void writeTempBuffer(byte[] inputBuffer, short offset){
if((short)(inputBuffer.length + offset) > (short)tempBuffer.length){
tempBuffer[0] = 'T'; // too tempBuffer[0] = 'T'; // too
tempBuffer[1] = 'L'; // long tempBuffer[1] = 'L'; // long
Util.setShort(tempBuffer, (short)2, (short)inputBuffer.length); // input length Util.setShort(tempBuffer, (short)2, (short)inputBuffer.length); // input length
return; return;
} }
Util.arrayCopy(inputBuffer, (short)0, tempBuffer, (short)0, (short)inputBuffer.length); Util.arrayCopy(inputBuffer, (short)0, tempBuffer, offset, (short)inputBuffer.length);
} }
/** /**
......
...@@ -10,5 +10,5 @@ public abstract class PinUvAuthProtocol { ...@@ -10,5 +10,5 @@ public abstract class PinUvAuthProtocol {
public abstract byte[] getPublicKey(); public abstract byte[] getPublicKey();
public abstract byte[] decapsulate(COSEKey peerCoseKey); public abstract byte[] decapsulate(COSEKey peerCoseKey);
public abstract byte[] decrypt(byte[] sharedSecret, byte[] cipherText); public abstract byte[] decrypt(byte[] sharedSecret, byte[] cipherText);
public abstract void verify(byte[] key, byte[] message, byte[] signature); public abstract boolean verify(byte[] key, byte[] message, byte[] signature);
} }
package com.josh.vku2f; package com.josh.vku2f;
import javacard.framework.JCSystem; import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.*; import javacard.security.*;
import javacardx.crypto.Cipher; import javacardx.crypto.Cipher;
import jdk.nashorn.internal.ir.Block;
public class PinUvAuthProtocolOne extends PinUvAuthProtocol{ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
...@@ -73,8 +75,20 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{ ...@@ -73,8 +75,20 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
return null; return null;
} }
/**
*
* @param key shared key from kdf()
* @param plaintext pinToken
* @return encrypted pinToken
*/
public byte[] encrypt(byte[] key, byte[] plaintext){ public byte[] encrypt(byte[] key, byte[] plaintext){
return null; byte[] cipherText = new byte[32];
aesKey.setKey(key, (short)0);
aesEncrypt.init(aesKey, Cipher.MODE_ENCRYPT, IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length);
aesEncrypt.update(plaintext, (short)0, (short)16, cipherText, (short)0);
aesEncrypt.doFinal(plaintext, (short)16, (short)16, cipherText, (short)16);
return cipherText;
} }
@Override @Override
...@@ -87,13 +101,45 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{ ...@@ -87,13 +101,45 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
return plainText; return plainText;
} }
/**
*
* @param key the key output from kdf()
* @param cipherText encrypted hashedPin
* @return hashed pin
*/
public byte[] decryptHashedPin(byte[] key, byte[] cipherText) {
byte[] hashedPin = new byte[16];
aesKey.setKey(key, (short)0);
aesDecrypt.init(aesKey, Cipher.MODE_DECRYPT, IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length);
aesDecrypt.doFinal(cipherText, (short)0, (short)16, hashedPin, (short)0);
return hashedPin;
}
/**
*
* @param key pinToken : 32 bytes
* @param message clientDataHash : 32 bytes
* @return signature
*/
public byte[] authenticate(byte[] key, byte[] message){ public byte[] authenticate(byte[] key, byte[] message){
return null; return hmac256(key, message);
} }
/**
*
* @param key pinToken 32 bytes
* @param message clientDataHash 32 bytes
* @param signature pinUvAuthToken 16 bytes : LEFT(hmac-sha-256(pinToken, clientDataHash), 16)
* @return boolean result
*/
@Override @Override
public void verify(byte[] key, byte[] message, byte[] signature) { public boolean verify(byte[] key, byte[] message, byte[] signature) {
byte[] authenticate = authenticate(key, message);
for(short i = 0; i < (short)signature.length; i++){
if(authenticate[i] != signature[i])
return false;
}
return true;
} }
public byte[] ecdh(byte[] peerKey){ public byte[] ecdh(byte[] peerKey){
...@@ -103,9 +149,71 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{ ...@@ -103,9 +149,71 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
keyAgreement.generateSecret(peerKey, (short)0, (short)65, sharedKey, (short)0); keyAgreement.generateSecret(peerKey, (short)0, (short)65, sharedKey, (short)0);
return kdf(sharedKey, (short)1); return kdf(sharedKey, (short)1);
} }
/**
*
* @param Z shared key from ecdh
* @param offset where the x-coordinate begin
* @return derivative key
*/
public byte[] kdf(byte[] Z, short offset){ public byte[] kdf(byte[] Z, short offset){
byte[] hashed = new byte[32]; byte[] hashed = new byte[32];
sha256.reset();
sha256.doFinal(Z, offset, (short)32, hashed, (short)0); sha256.doFinal(Z, offset, (short)32, hashed, (short)0);
return hashed; return hashed;
} }
/**
*
* @param pin pin
* @return hashed pin
*/
public byte[] hashPin(byte[] pin){
byte[] hashedPin = new byte[32];
sha256.reset();
sha256.doFinal(pin, (short)0, (short)pin.length, hashedPin, (short)0);
return hashedPin;
}
/**
*
* @param key key must <= 64 bytes
* @param message message must <= 32 bytes
* @return hmac
*/
public byte[] hmac256(byte[] key, byte[] message){
short BLOCKSIZE=64; // 512 bits
short HASHSIZE=32; // 256 bits
byte[] hashed = new byte[HASHSIZE];
byte[] hmacBuffer = new byte[(short)(BLOCKSIZE + hashed.length)];
for (short i=0; i < (short)key.length; i++){
hmacBuffer[i]= (byte) (key[i] ^ (0x36));
}
Util.arrayFillNonAtomic(hmacBuffer, (short)key.length, (short)(BLOCKSIZE-key.length), (byte)0x36); // ipad
Util.arrayCopyNonAtomic(message, (short)0, hmacBuffer, BLOCKSIZE, (short)message.length);
sha256.update(hmacBuffer, (short)0, HASHSIZE);
sha256.update(hmacBuffer, (short)32, HASHSIZE);
sha256.doFinal(hmacBuffer, BLOCKSIZE, (short)(message.length), hashed, (short)0);
for (short i=0; i< (short)key.length; i++){
hmacBuffer[i]= (byte) (key[i] ^ (0x5c));
}
Util.arrayFillNonAtomic(hmacBuffer, (short)key.length, (short)(BLOCKSIZE - key.length), (byte)0x5c); // opad
Util.arrayCopy(hashed, (short)0, hmacBuffer, BLOCKSIZE, (short)hashed.length);
sha256.update(hmacBuffer, (short)0, HASHSIZE);
sha256.update(hmacBuffer, (short)32, HASHSIZE);
sha256.doFinal(hmacBuffer, BLOCKSIZE, (short)(hashed.length), hashed, (short)0);
return hashed;
}
} }
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
package com.josh.vku2f; package com.josh.vku2f;
public class Utf8Strings { public class Utf8Strings {
public static final byte[] UTF8_UP = {'u', 'p'};
// Representation of "id" in UTF8 // Representation of "id" in UTF8
public static final byte[] UTF8_ID = {'i', 'd'}; public static final byte[] UTF8_ID = {'i', 'd'};
// Representation of "name" in UTF8 // Representation of "name" in UTF8
...@@ -26,20 +25,28 @@ public class Utf8Strings { ...@@ -26,20 +25,28 @@ public class Utf8Strings {
public static final byte[] UTF8_DISPLAYNAME = {'d', 'i', 's', 'p', 'l', 'a', 'y', 'n', 'a', 'm', 'e'}; public static final byte[] UTF8_DISPLAYNAME = {'d', 'i', 's', 'p', 'l', 'a', 'y', 'n', 'a', 'm', 'e'};
// Representation of "alg" in UTF8 // Representation of "alg" in UTF8
public static final byte[] UTF8_ALG = {'a', 'l', 'g'}; public static final byte[] UTF8_ALG = {'a', 'l', 'g'};
public static final byte[] UTF8_UV = {'u', 'v'};
public static final byte[] UTF8_RK = {'r', 'k'}; public static final byte[] UTF8_RK = {'r', 'k'};
public static final byte[] UTF8_UP = {'u', 'p'};
public static final byte[] UTF8_UV = {'u', 'v'};
public static final byte[] UTF8_plat = {'p', 'l', 'a', 't'};
public static final byte[] UTF8_CLIENT_PIN = {'c', 'l', 'i', 'e', 'n', 't', 'P', 'i', 'n'}; public static final byte[] UTF8_CLIENT_PIN = {'c', 'l', 'i', 'e', 'n', 't', 'P', 'i', 'n'};
public static final byte[] UTF8_CREDENTIAL_MGMT_PREVIEW = {'c', 'r', 'e', 'd', 'e', 'n', 't', 'i', 'a', 'l', 'M', 'g', 'm', 't', 'P', 'r', 'e', 'v', 'i', 'e', 'w', };
public static final byte[] UTF8_nfc = {'n', 'f', 'c'};
public static final byte[] UTF8_usb = {'u', 's', 'b'};
public static final byte[] UTF8_TYPE = {'t', 'y', 'p', 'e'}; public static final byte[] UTF8_TYPE = {'t', 'y', 'p', 'e'};
public static final byte[] UTF8_PACKED = {'p', 'a', 'c', 'k', 'e', 'd'}; public static final byte[] UTF8_PACKED = {'p', 'a', 'c', 'k', 'e', 'd'};
public static final byte[] UTF8_SIG = {'s', 'i', 'g'}; public static final byte[] UTF8_SIG = {'s', 'i', 'g'};
public static final byte[] UTF8_X5C = {'x', '5', 'c'}; public static final byte[] UTF8_X5C = {'x', '5', 'c'};
public static final byte[] UTF8_PUBLIC_KEY = {'p', 'u', 'b', 'l', 'i', 'c', '-', 'k', 'e', 'y'}; public static final byte[] UTF8_PUBLIC_KEY = {'p', 'u', 'b', 'l', 'i', 'c', '-', 'k', 'e', 'y'};
public static final byte[] UTF8_U2F_V2 = {'U', '2', 'F', '_', 'V', '2'};
public static final byte[] UTF8_FIDO2 = {'F', 'I', 'D', 'O', '_', '2', '_', '0'}; public static final byte[] UTF8_FIDO2 = {'F', 'I', 'D', 'O', '_', '2', '_', '0'};
public static final byte[] UTF8_FIDO_2_1_PRE = {'F', 'I', 'D', 'O', '_', '2', '_', '1', '_', 'P', 'R', 'E'};
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_PRLab = {'P', 'R', 'L', 'a', 'b'}; public static final byte[] UTF8_PRLab = {'P', 'R', 'L', 'a', 'b'};
public static final byte[] UTF8_credProtect = {'c','r','e','d','P','r','o','t','e','c','t'}; public static final byte[] UTF8_credProtect = {'c','r','e','d','P','r','o','t','e','c','t'};
public static final byte[] UTF8_hmac_secret = {'h','m','a','c','-','s','e','c','r','e','t'};
public static final byte[] UTF8_HMAC = {'H', 'M', 'A', 'C'}; public static final byte[] UTF8_HMAC = {'H', 'M', 'A', 'C'};
public static final byte[] UTF8_Cx = {'C', 'x'}; public static final byte[] UTF8_Cx = {'C', 'x'};
public static final byte[] UTF8_IDx = {'I', 'D', 'x'}; public static final byte[] UTF8_IDx = {'I', 'D', '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