document SecureChannel
This commit is contained in:
parent
8729768478
commit
74594092c8
|
@ -3,10 +3,12 @@ package im.status.wallet;
|
|||
import javacard.framework.APDU;
|
||||
import javacard.framework.ISO7816;
|
||||
import javacard.framework.JCSystem;
|
||||
import javacard.framework.Util;
|
||||
import javacard.security.*;
|
||||
import javacardx.crypto.Cipher;
|
||||
|
||||
/**
|
||||
* Implements all methods related to the secure channel as specified in the SECURE_CHANNEL.md document.
|
||||
*/
|
||||
public class SecureChannel {
|
||||
public static final short SC_KEY_LENGTH = 256;
|
||||
public static final short SC_SECRET_LENGTH = 32;
|
||||
|
@ -21,8 +23,13 @@ public class SecureChannel {
|
|||
private KeyPair scKeypair;
|
||||
private byte[] secret;
|
||||
|
||||
/**
|
||||
* Instatiates a Secure Channel. All memory allocations needed for the secure channel are peformed here. The keypair
|
||||
* used for the EC-DH algorithm is also generated here.
|
||||
*/
|
||||
public SecureChannel() {
|
||||
scCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||
scCipher = Cipher.getInstance(Cipher.ALG_AES_CBC_ISO9797_M2,false);
|
||||
|
||||
scKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
|
||||
|
||||
scKeypair = new KeyPair(KeyPair.ALG_EC_FP, SC_KEY_LENGTH);
|
||||
|
@ -36,7 +43,11 @@ public class SecureChannel {
|
|||
secret = JCSystem.makeTransientByteArray(SC_SECRET_LENGTH, JCSystem.CLEAR_ON_DESELECT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes the OPEN SECURE CHANNEL command.
|
||||
*
|
||||
* @param apdu the JCRE-owned APDU object.
|
||||
*/
|
||||
public void openSecureChannel(APDU apdu) {
|
||||
apdu.setIncomingAndReceive();
|
||||
byte[] apduBuffer = apdu.getBuffer();
|
||||
|
@ -48,41 +59,55 @@ public class SecureChannel {
|
|||
apdu.setOutgoingAndSend((short) 0, SC_SECRET_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the given APDU buffer. The plaintext is written in-place starting at the ISO7816.OFFSET_CDATA offset. The
|
||||
* IV and padding are stripped. The LC byte is overwritten with the plaintext length.
|
||||
*
|
||||
* @param apduBuffer the APDU buffer
|
||||
* @return the length of the decrypted
|
||||
*/
|
||||
public short decryptAPDU(byte[] apduBuffer) {
|
||||
short apduLen = (short)((short) apduBuffer[ISO7816.OFFSET_LC] & 0xff);
|
||||
|
||||
scCipher.init(scKey, Cipher.MODE_DECRYPT, apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
||||
short len = scCipher.doFinal(apduBuffer, (short)(ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), (short) (apduLen - SC_BLOCK_SIZE), apduBuffer, ISO7816.OFFSET_CDATA);
|
||||
|
||||
while(apduBuffer[(short)(ISO7816.OFFSET_CDATA+len-1)] != (byte) 0x80) {
|
||||
len--;
|
||||
}
|
||||
|
||||
len--;
|
||||
|
||||
apduBuffer[ISO7816.OFFSET_LC] = (byte) len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the APDU buffer. The plaintext must be placed starting at the SecureChannel.SC_OUT_OFFSET offset, to leave
|
||||
* place for the SecureChannel-specific data at the beginning of the APDU.
|
||||
*
|
||||
* @param apduBuffer the APDU buffer
|
||||
* @param len the length of the plaintext
|
||||
* @return the length of the encrypted APDU
|
||||
*/
|
||||
public short encryptAPDU(byte[] apduBuffer, short len) {
|
||||
apduBuffer[(short)(SC_OUT_OFFSET + len)] = (byte) 0x80;
|
||||
len++;
|
||||
short padding = (short) ((SC_BLOCK_SIZE - (short) (len % SC_BLOCK_SIZE)) % SC_BLOCK_SIZE);
|
||||
Util.arrayFillNonAtomic(apduBuffer, (short)(SC_OUT_OFFSET + len), padding, (byte) 0x00);
|
||||
len += padding;
|
||||
|
||||
Crypto.random.generateData(apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
||||
scCipher.init(scKey, Cipher.MODE_ENCRYPT, apduBuffer, ISO7816.OFFSET_CDATA, SC_BLOCK_SIZE);
|
||||
len = scCipher.doFinal(apduBuffer, SC_OUT_OFFSET, len, apduBuffer, (short)(ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE));
|
||||
return (short)(len + SC_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the public key used for EC-DH in the given buffer.
|
||||
*
|
||||
* @param buf the buffer
|
||||
* @param off the offset in the buffer
|
||||
* @return the length of the public key
|
||||
*/
|
||||
public short copyPublicKey(byte[] buf, byte off) {
|
||||
ECPublicKey pk = (ECPublicKey) scKeypair.getPublic();
|
||||
return pk.getW(buf, off);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a secure channel is currently established or not.
|
||||
* @return whether a secure channel is currently established or not.
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return scKey.isInitialized();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue