Functional KDF support

This commit is contained in:
Arnaud Fontaine 2020-01-23 19:35:22 +01:00
parent f78db3e999
commit 9b77f6c26b
2 changed files with 124 additions and 25 deletions

View File

@ -260,4 +260,25 @@ public final class Persistent {
isTerminated = false; isTerminated = false;
} }
protected final boolean keyDerivationIsActive() {
return ((3 <= key_derivation_function_length) &&
(key_derivation_function[0] == (byte)0x81) &&
(key_derivation_function[2] != (byte)0));
}
protected final byte keyDerivationSize() {
if(keyDerivationIsActive() &&
(6 <= key_derivation_function_length)) {
switch(key_derivation_function[5]) {
case (byte)0x08:
return (byte)32;
case (byte)0x0A:
return (byte)64;
default:
return (byte)0;
}
}
return (byte)0;
}
} }

View File

@ -149,9 +149,16 @@ public final class SmartPGPApplet extends Applet {
private final short writePwStatus(final byte[] buf, short off) { private final short writePwStatus(final byte[] buf, short off) {
buf[off++] = (byte)(data.user_pin_force_verify_signature ? 0x00 : 0x01); buf[off++] = (byte)(data.user_pin_force_verify_signature ? 0x00 : 0x01);
if(data.keyDerivationIsActive()) {
final byte size = data.keyDerivationSize();
buf[off++] = size;
buf[off++] = size;
buf[off++] = size;
} else {
buf[off++] = Constants.USER_PIN_MAX_SIZE; buf[off++] = Constants.USER_PIN_MAX_SIZE;
buf[off++] = Constants.USER_PUK_MAX_SIZE; buf[off++] = Constants.USER_PUK_MAX_SIZE;
buf[off++] = Constants.ADMIN_PIN_MAX_SIZE; buf[off++] = Constants.ADMIN_PIN_MAX_SIZE;
}
buf[off++] = data.user_pin.getTriesRemaining(); buf[off++] = data.user_pin.getTriesRemaining();
buf[off++] = data.user_puk.getTriesRemaining(); buf[off++] = data.user_puk.getTriesRemaining();
@ -525,11 +532,18 @@ public final class SmartPGPApplet extends Applet {
switch(p2) { switch(p2) {
case (byte)0x81: case (byte)0x81:
case (byte)0x82: case (byte)0x82:
if(data.keyDerivationIsActive()) {
if(lc != data.keyDerivationSize()) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((lc < Constants.USER_PIN_MIN_SIZE) || if((lc < Constants.USER_PIN_MIN_SIZE) ||
(lc > Constants.USER_PIN_MAX_SIZE)) { (lc > Constants.USER_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return; return;
} }
}
if(p2 == (byte)0x81) { if(p2 == (byte)0x81) {
transients.setUserPinMode81(false); transients.setUserPinMode81(false);
@ -550,11 +564,18 @@ public final class SmartPGPApplet extends Applet {
return; return;
case (byte)0x83: case (byte)0x83:
if(data.keyDerivationIsActive()) {
if(lc != data.keyDerivationSize()) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((lc < Constants.ADMIN_PIN_MIN_SIZE) || if((lc < Constants.ADMIN_PIN_MIN_SIZE) ||
(lc > Constants.ADMIN_PIN_MAX_SIZE)) { (lc > Constants.ADMIN_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return; return;
} }
}
if(!data.admin_pin.check(transients.buffer, (short)0, (byte)lc)) { if(!data.admin_pin.check(transients.buffer, (short)0, (byte)lc)) {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
@ -606,6 +627,7 @@ public final class SmartPGPApplet extends Applet {
sensitiveData(); sensitiveData();
byte off; byte off;
byte minlen;
if(p1 != 0) { if(p1 != 0) {
ISOException.throwIt(ISO7816.SW_WRONG_P1P2); ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
@ -614,28 +636,51 @@ public final class SmartPGPApplet extends Applet {
switch(p2) { switch(p2) {
case (byte)0x81: case (byte)0x81:
if((lc < (Constants.USER_PIN_MIN_SIZE + Constants.USER_PIN_MIN_SIZE)) || minlen = Constants.USER_PIN_MIN_SIZE;
(lc > (Constants.USER_PIN_MAX_SIZE + Constants.USER_PIN_MAX_SIZE))) { if(data.keyDerivationIsActive()) {
minlen += data.keyDerivationSize();
} else {
minlen += Constants.USER_PIN_MIN_SIZE;
}
if(lc < minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return; return;
} }
transients.setUserPinMode81(false);
transients.setUserPinMode82(false);
off = data.user_pin_length; off = data.user_pin_length;
if(!data.user_pin.check(transients.buffer, (short)0, off)) { if(!data.user_pin.check(transients.buffer, (short)0, off)) {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
return; return;
} }
transients.setUserPinMode81(false); minlen = (byte)(lc - off);
transients.setUserPinMode82(false); if(data.keyDerivationIsActive()) {
if(data.keyDerivationSize() != minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((minlen < Constants.USER_PIN_MIN_SIZE) ||
(minlen > Constants.USER_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
}
JCSystem.beginTransaction(); JCSystem.beginTransaction();
data.user_pin_length = (byte)(lc - off); data.user_pin_length = minlen;
data.user_pin.update(transients.buffer, off, data.user_pin_length); data.user_pin.update(transients.buffer, off, data.user_pin_length);
JCSystem.commitTransaction(); JCSystem.commitTransaction();
data.user_pin.resetAndUnblock(); data.user_pin.resetAndUnblock();
break; break;
case (byte)0x83: case (byte)0x83:
if((lc < (Constants.ADMIN_PIN_MIN_SIZE + Constants.ADMIN_PIN_MIN_SIZE)) || minlen = Constants.ADMIN_PIN_MIN_SIZE;
(lc > (Constants.ADMIN_PIN_MAX_SIZE + Constants.ADMIN_PIN_MAX_SIZE))) { if(data.keyDerivationIsActive()) {
minlen += data.keyDerivationSize();
} else {
minlen += Constants.ADMIN_PIN_MIN_SIZE;
}
if(lc < minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return; return;
} }
@ -644,11 +689,25 @@ public final class SmartPGPApplet extends Applet {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
return; return;
} }
minlen = (byte)(lc - off);
if(data.keyDerivationIsActive()) {
if(data.keyDerivationSize() != minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((minlen < Constants.ADMIN_PIN_MIN_SIZE) ||
(minlen > Constants.ADMIN_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
}
JCSystem.beginTransaction(); JCSystem.beginTransaction();
data.admin_pin_length = (byte)(lc - off); data.admin_pin_length = minlen;
data.admin_pin.update(transients.buffer, off, data.admin_pin_length); data.admin_pin.update(transients.buffer, off, data.admin_pin_length);
JCSystem.commitTransaction(); JCSystem.commitTransaction();
data.admin_pin.resetAndUnblock();; data.admin_pin.resetAndUnblock();
data.admin_pin.check(transients.buffer, off, data.admin_pin_length);
break; break;
default: default:
@ -663,6 +722,7 @@ public final class SmartPGPApplet extends Applet {
sensitiveData(); sensitiveData();
byte off = 0; byte off = 0;
byte minlen;
if(p2 != (byte)0x81) { if(p2 != (byte)0x81) {
ISOException.throwIt(ISO7816.SW_WRONG_P1P2); ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
@ -671,20 +731,38 @@ public final class SmartPGPApplet extends Applet {
switch(p1) { switch(p1) {
case (byte)0x00: case (byte)0x00:
if((lc < (Constants.USER_PUK_MIN_SIZE + Constants.USER_PIN_MIN_SIZE)) || minlen = Constants.USER_PUK_MIN_SIZE;
(lc > (Constants.USER_PUK_MAX_SIZE + Constants.USER_PIN_MAX_SIZE))) { if(data.keyDerivationIsActive()) {
minlen += data.keyDerivationSize();
} else {
minlen += Constants.USER_PIN_MIN_SIZE;
}
if(lc < minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return; return;
} }
transients.setUserPinMode81(false);
transients.setUserPinMode82(false);
off = data.user_puk_length; off = data.user_puk_length;
if(!data.user_puk.check(transients.buffer, (short)0, off)) { if(!data.user_puk.check(transients.buffer, (short)0, off)) {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
return; return;
} }
transients.setUserPinMode81(false); minlen = (byte)(lc - off);
transients.setUserPinMode82(false); if(data.keyDerivationIsActive()) {
if(data.keyDerivationSize() != minlen) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((minlen < Constants.USER_PIN_MIN_SIZE) ||
(minlen > Constants.USER_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
}
JCSystem.beginTransaction(); JCSystem.beginTransaction();
data.user_pin_length = (byte)(lc - off); data.user_pin_length = minlen;
data.user_pin.update(transients.buffer, off, data.user_pin_length); data.user_pin.update(transients.buffer, off, data.user_pin_length);
JCSystem.commitTransaction(); JCSystem.commitTransaction();
data.user_pin.resetAndUnblock(); data.user_pin.resetAndUnblock();