From d37a4710676ebd9b8c7c21cbb2a1815d3808d1c1 Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine Date: Mon, 22 May 2017 16:18:56 +0200 Subject: [PATCH] OpenPGP card v3.3 : support KDF-DO --- src/fr/anssi/smartpgp/Constants.java | 9 ++++++++- src/fr/anssi/smartpgp/Persistent.java | 20 +++++++++++++++++++- src/fr/anssi/smartpgp/SmartPGPApplet.java | 22 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/fr/anssi/smartpgp/Constants.java b/src/fr/anssi/smartpgp/Constants.java index 276775e..db6db26 100644 --- a/src/fr/anssi/smartpgp/Constants.java +++ b/src/fr/anssi/smartpgp/Constants.java @@ -32,6 +32,11 @@ public final class Constants { protected static final short APDU_MAX_LENGTH = (short)256; + protected static final short KEY_DERIVATION_FUNCTION_MIN_LENGTH = 2; + protected static final short KEY_DERIVATION_FUNCTION_MAX_LENGTH = 160; + protected static final byte[] KEY_DERIVATION_FUNCTION_DEFAULT = { + (byte)0xF9, (byte)0x00 + }; protected static final byte USER_PIN_RETRY_COUNT = 3; protected static final byte USER_PIN_MIN_SIZE = 0x06; @@ -100,6 +105,7 @@ public final class Constants { protected static final short TAG_PRIVATE_DO_0103 = (short)0x0103; protected static final short TAG_PRIVATE_DO_0104 = (short)0x0104; protected static final short TAG_AES_KEY = (short)0x00d5; + protected static final short TAG_KEY_DERIVATION_FUNCTION = (short)0x00f9; protected static final short CRT_AUTHENTICATION_KEY = (short)0xa400; protected static final short CRT_SECURE_MESSAGING_KEY = (short)0xa600; @@ -157,7 +163,8 @@ public final class Constants { 0x10 | /* support pw status changes */ 0x08 | /* support private DOs (0101-0104) */ 0x04 | /* support algorithm attributes changes */ - 0x02), /* support PSO:DEC AES */ + 0x02 | /* support PSO:DEC AES */ + 0x01), /* support KDF-DO */ (byte)0x01, /* SM 0x01 = 128 bits, 0x02 = 256 bits */ (byte)0x00, (byte)0x20, /* max length get challenge */ (byte)0x04, (byte)0x80, /* max length of carholder certificate */ diff --git a/src/fr/anssi/smartpgp/Persistent.java b/src/fr/anssi/smartpgp/Persistent.java index e69a40c..c829c40 100644 --- a/src/fr/anssi/smartpgp/Persistent.java +++ b/src/fr/anssi/smartpgp/Persistent.java @@ -71,9 +71,12 @@ public final class Persistent { protected byte[] do_0104; protected short do_0104_length; + protected AESKey aes_key; + protected byte[] key_derivation_function; + protected short key_derivation_function_length; protected final OwnerPIN user_pin; /* PW1 */ protected byte user_pin_length; @@ -128,6 +131,9 @@ public final class Persistent { pgp_keys[i] = new PGPKey(false); } + key_derivation_function = new byte[Constants.KEY_DERIVATION_FUNCTION_MAX_LENGTH]; + key_derivation_function_length = 0; + user_pin = new OwnerPIN(Constants.USER_PIN_RETRY_COUNT, Constants.USER_PIN_MAX_SIZE); user_puk = new OwnerPIN(Constants.USER_PUK_RETRY_COUNT, Constants.USER_PUK_MAX_SIZE); admin_pin = new OwnerPIN(Constants.ADMIN_PIN_RETRY_COUNT, Constants.ADMIN_PIN_MAX_SIZE); @@ -169,7 +175,9 @@ public final class Persistent { if(lang_length > 0) { Util.arrayFillNonAtomic(lang, (short)0, lang_length, (byte)0); } - Util.arrayCopyNonAtomic(Constants.LANG_DEFAULT, (short)0, lang, (short)0, (short)Constants.LANG_DEFAULT.length); + Util.arrayCopyNonAtomic(Constants.LANG_DEFAULT, (short)0, + lang, (short)0, + (short)Constants.LANG_DEFAULT.length); lang_length = (byte)Constants.LANG_DEFAULT.length; JCSystem.commitTransaction(); @@ -214,6 +222,16 @@ public final class Persistent { user_pin_force_verify_signature = Constants.USER_PIN_DEFAULT_FORCE_VERIFY_SIGNATURE; + JCSystem.beginTransaction(); + if(key_derivation_function_length > 0) { + Util.arrayFillNonAtomic(key_derivation_function, (short)0, key_derivation_function_length, (byte)0); + } + Util.arrayCopyNonAtomic(Constants.KEY_DERIVATION_FUNCTION_DEFAULT, (short)0, + key_derivation_function, (short)0, + (short)Constants.KEY_DERIVATION_FUNCTION_DEFAULT.length); + key_derivation_function_length = (short)Constants.KEY_DERIVATION_FUNCTION_DEFAULT.length; + JCSystem.commitTransaction(); + JCSystem.beginTransaction(); user_pin_length = (byte)Constants.USER_PIN_DEFAULT.length; user_pin.update(Constants.USER_PIN_DEFAULT, (short)0, user_pin_length); diff --git a/src/fr/anssi/smartpgp/SmartPGPApplet.java b/src/fr/anssi/smartpgp/SmartPGPApplet.java index 9b4bfee..681d6b0 100644 --- a/src/fr/anssi/smartpgp/SmartPGPApplet.java +++ b/src/fr/anssi/smartpgp/SmartPGPApplet.java @@ -447,6 +447,12 @@ public final class SmartPGPApplet extends Applet { k.certificate_length); break; + case Constants.TAG_KEY_DERIVATION_FUNCTION: + off = Util.arrayCopyNonAtomic(data.key_derivation_function, (short)0, + buf, off, + data.key_derivation_function_length); + break; + default: ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND); return 0; @@ -1031,6 +1037,22 @@ public final class SmartPGPApplet extends Applet { JCSystem.commitTransaction(); break; + case Constants.TAG_KEY_DERIVATION_FUNCTION: + assertAdmin(); + if((lc < Constants.KEY_DERIVATION_FUNCTION_MIN_LENGTH) || + (lc > Constants.KEY_DERIVATION_FUNCTION_MAX_LENGTH)) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + return; + } + JCSystem.beginTransaction(); + if(data.key_derivation_function_length > 0) { + Util.arrayFillNonAtomic(data.key_derivation_function, (short)0, data.key_derivation_function_length, (byte)0); + } + Util.arrayCopyNonAtomic(buf, (short)0, data.key_derivation_function, (short)0, lc); + data.key_derivation_function_length = (byte)lc; + JCSystem.commitTransaction(); + break; + default: ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND); return;