Version without elliptic curves and secure messaging compatible with JavaCard 3.0.1

This commit is contained in:
Arnaud Fontaine
2017-07-18 15:03:15 +02:00
parent ab7baa6a55
commit 309dbbad8a
12 changed files with 24 additions and 2020 deletions

View File

@@ -37,22 +37,13 @@ public final class PGPKey {
protected final byte[] attributes;
protected byte attributes_length;
protected final boolean is_secure_messaging_key;
private KeyPair keys;
protected PGPKey(final boolean for_secure_messaging) {
protected PGPKey() {
is_secure_messaging_key = for_secure_messaging;
if(is_secure_messaging_key) {
fingerprint = null;
generation_date = null;
} else {
fingerprint = new Fingerprint();
generation_date = new byte[Constants.GENERATION_DATE_SIZE];
}
fingerprint = new Fingerprint();
generation_date = new byte[Constants.GENERATION_DATE_SIZE];
certificate = new byte[Constants.cardholderCertificateMaxLength()];
certificate_length = 0;
@@ -75,11 +66,9 @@ public final class PGPKey {
Util.arrayFillNonAtomic(certificate, (short)0, certificate_length, (byte)0);
}
if(!is_secure_messaging_key) {
fingerprint.reset();
fingerprint.reset();
Util.arrayFillNonAtomic(generation_date, (short)0, Constants.GENERATION_DATE_SIZE, (byte)0);
}
Util.arrayFillNonAtomic(generation_date, (short)0, Constants.GENERATION_DATE_SIZE, (byte)0);
}
protected final void reset() {
@@ -91,17 +80,10 @@ public final class PGPKey {
attributes_length = (byte)0;
}
if(is_secure_messaging_key) {
Util.arrayCopyNonAtomic(Constants.ALGORITHM_ATTRIBUTES_DEFAULT_SECURE_MESSAGING, (short)0,
attributes, (short)0,
(short)Constants.ALGORITHM_ATTRIBUTES_DEFAULT_SECURE_MESSAGING.length);
attributes_length = (byte)Constants.ALGORITHM_ATTRIBUTES_DEFAULT_SECURE_MESSAGING.length;
} else {
Util.arrayCopyNonAtomic(Constants.ALGORITHM_ATTRIBUTES_DEFAULT, (short)0,
attributes, (short)0,
(short)Constants.ALGORITHM_ATTRIBUTES_DEFAULT.length);
attributes_length = (byte)Constants.ALGORITHM_ATTRIBUTES_DEFAULT.length;
}
Util.arrayCopyNonAtomic(Constants.ALGORITHM_ATTRIBUTES_DEFAULT, (short)0,
attributes, (short)0,
(short)Constants.ALGORITHM_ATTRIBUTES_DEFAULT.length);
attributes_length = (byte)Constants.ALGORITHM_ATTRIBUTES_DEFAULT.length;
JCSystem.commitTransaction();
}
@@ -133,8 +115,7 @@ public final class PGPKey {
Util.arrayCopy(buf, off, generation_date, (short)0, len);
}
protected final void setAttributes(final ECCurves ec,
final byte[] buf, final short off, final short len) {
protected final void setAttributes(final byte[] buf, final short off, final short len) {
if((len < Constants.ALGORITHM_ATTRIBUTES_MIN_LENGTH) ||
(len > Constants.ALGORITHM_ATTRIBUTES_MAX_LENGTH)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
@@ -143,7 +124,7 @@ public final class PGPKey {
switch(buf[0]) {
case 0x01:
if((len != 6) || is_secure_messaging_key) {
if(len != 6) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return;
}
@@ -155,24 +136,6 @@ public final class PGPKey {
}
break;
case 0x12:
case 0x13:
if(len < 2) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return;
}
final byte delta = (buf[(short)(len - 1)] == (byte)0xff) ? (byte)1 : (byte)0;
final ECParams params = ec.findByOid(buf, (short)(off + 1), (byte)(len - 1 - delta));
if(params == null) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return;
}
if((buf[0] != 0x12) && is_secure_messaging_key) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
return;
}
break;
default:
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
return;
@@ -202,17 +165,6 @@ public final class PGPKey {
return Util.getShort(attributes, (short)3);
}
protected final boolean isEc() {
return ((attributes[0] == (byte)0x12) ||
(attributes[0] == (byte)0x13));
}
protected final ECParams ecParams(final ECCurves ec) {
final byte delta = (attributes[(short)(attributes_length - 1)] == (byte)0xff) ? (byte)1 : (byte)0;
return ec.findByOid(attributes, (short)1, (byte)(attributes_length - 1 - delta));
}
private final KeyPair generateRSA() {
final PrivateKey priv = (PrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, rsaModulusBitSize(), false);
final RSAPublicKey pub = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, rsaModulusBitSize(), false);
@@ -227,32 +179,12 @@ public final class PGPKey {
}
private final KeyPair generateEC(final ECCurves ec) {
final ECParams params = ecParams(ec);
final ECPrivateKey priv = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, params.nb_bits, false);
final ECPublicKey pub = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, params.nb_bits, false);
if((priv == null) || (pub == null)) {
return null;
}
params.setParams(priv);
params.setParams(pub);
return new KeyPair(pub, priv);
}
protected final void generate(final ECCurves ec) {
protected final void generate() {
KeyPair nkeys = null;
if(isRsa()) {
nkeys = generateRSA();
} else if(isEc()) {
nkeys = generateEC(ec);
}
if(nkeys == null) {
@@ -361,70 +293,8 @@ public final class PGPKey {
return new KeyPair(pub, priv);
}
private final KeyPair importECKey(final ECCurves ec,
final byte[] buf,
final short boff, final short len,
final byte tag_count, final byte[] tag_val, final short[] tag_len) {
final ECParams params = ecParams(ec);
final ECPrivateKey priv = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE,
params.nb_bits,
false);
final ECPublicKey pub = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,
params.nb_bits,
false);
if((priv == null) || (pub == null)) {
return null;
}
params.setParams(priv);
params.setParams(pub);
short off = boff;
byte i = 0;
while(i < tag_count) {
if((short)((short)(off - boff) + tag_len[i]) > len) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return null;
}
switch(tag_val[i]) {
case (byte)0x92:
if(tag_len[i] > Common.bitsToBytes(params.nb_bits)) {
return null;
}
priv.setS(buf, off, tag_len[i]);
break;
case (byte)0x99:
if(tag_len[i] > (short)(2 * Common.bitsToBytes(params.nb_bits) + 1)) {
return null;
}
if(((byte)(tag_len[i] - 1) & (byte)0x1) != 0) {
return null;
}
pub.setW(buf, off, tag_len[i]);
break;
default:
return null;
}
off += tag_len[i];
++i;
}
if(!priv.isInitialized() || !pub.isInitialized()) {
return null;
}
return new KeyPair(pub, priv);
}
protected final void importKey(final ECCurves ec,
final byte[] buf, final short boff, final short len) {
protected final void importKey(final byte[] buf, final short boff, final short len) {
short off = boff;
@@ -499,8 +369,6 @@ public final class PGPKey {
if(isRsa()) {
nkeys = importRSAKey(buf, data_off, data_len, data_tag_count, data_tag_val, data_tag_len);
} else if(isEc()) {
nkeys = importECKey(ec, buf, data_off, data_len, data_tag_count, data_tag_val, data_tag_len);
}
if(nkeys == null) {
@@ -552,28 +420,6 @@ public final class PGPKey {
return off;
} else if(isEc()) {
final ECPublicKey ecpub = (ECPublicKey)pub;
final short qsize = (short)(1 + 2 * (short)((ecpub.getSize() / 8) + (((ecpub.getSize() % 8) == 0) ? 0 : 1)));
short rsize = (short)(1 + qsize);
if(qsize > 0x7f) {
rsize = (short)(rsize + 2);
} else {
rsize = (short)(rsize + 1);
}
off = Common.writeLength(buf, off, rsize);
buf[off++] = (byte)0x86;
off = Common.writeLength(buf, off, qsize);
off += ecpub.getW(buf, off);
return off;
}
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
@@ -634,88 +480,6 @@ public final class PGPKey {
buf, (short)0,
off);
} else if(isEc()) {
byte alg;
if(lc == MessageDigest.LENGTH_SHA) {
alg = Signature.ALG_ECDSA_SHA;
} else if(lc == MessageDigest.LENGTH_SHA_224) {
alg = Signature.ALG_ECDSA_SHA_224;
} else if(lc == MessageDigest.LENGTH_SHA_256) {
alg = Signature.ALG_ECDSA_SHA_256;
} else if(lc == MessageDigest.LENGTH_SHA_384) {
alg = Signature.ALG_ECDSA_SHA_384;
} else if(lc == MessageDigest.LENGTH_SHA_512) {
alg = Signature.ALG_ECDSA_SHA_512;
} else {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
return 0;
}
final Signature sig = Signature.getInstance(alg, false);
sig.init(priv, Signature.MODE_SIGN);
final short sig_size = sig.signPreComputedHash(buf, (short)0, lc,
buf, lc);
off = (short)(lc + 1);
if((buf[off] & (byte)0x80) != (byte)0) {
++off;
}
++off;
if((buf[off++] != (byte)0x02)) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
if((buf[off] & (byte)0x80) != (byte)0) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
final short r_size = Util.makeShort((byte)0, buf[off++]);
final short r_off = off;
off += r_size;
if((buf[off++] != (byte)0x02)) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
if((buf[off] & (byte)0x80) != (byte)0) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
final short s_size = Util.makeShort((byte)0, buf[off++]);
final short s_off = off;
off = (short)(lc + sig_size);
if(r_size < s_size) {
off = Util.arrayFillNonAtomic(buf, off, (short)(s_size - r_size), (byte)0);
}
off = Util.arrayCopyNonAtomic(buf, r_off,
buf, off, r_size);
if(s_size < r_size) {
off = Util.arrayFillNonAtomic(buf, off, (short)(r_size - s_size), (byte)0);
}
off = Util.arrayCopyNonAtomic(buf, s_off,
buf, off, s_size);
off = Util.arrayCopyNonAtomic(buf, (short)(lc + sig_size),
buf, (short)0,
(short)(off - lc - sig_size));
Util.arrayFillNonAtomic(buf, off, (short)(lc + sig_size - off), (byte)0);
return off;
}
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
@@ -723,7 +487,7 @@ public final class PGPKey {
}
protected final short decipher(final ECCurves ec, final byte[] buf, final short lc) {
protected final short decipher(final byte[] buf, final short lc) {
if(!isInitialized()) {
ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND);
@@ -761,64 +525,6 @@ public final class PGPKey {
return off;
} else if(isEc()) {
final ECParams params = ecParams(ec);
if((lc <= 7) || (lc > (short)(7 + 1 + (short)(2 * Common.bitsToBytes(params.nb_bits))))) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
if(buf[off] != (byte)0xA6) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
++off;
if(buf[off] != (byte)(lc - off - 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return 0;
}
++off;
if(Util.getShort(buf, off) != (short)(0x7f49)) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
off += 2;
if(buf[off] != (byte)(lc - off - 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return 0;
}
++off;
if(buf[off] != (byte)0x86) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
return 0;
}
++off;
if(buf[off] != (byte)(lc - off - 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return 0;
}
++off;
final KeyAgreement ka = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false);
ka.init(priv);
final short len = ka.generateSecret(buf, off, (short)(lc - off),
buf, lc);
off = Util.arrayCopyNonAtomic(buf, lc,
buf, (short)0,
len);
Util.arrayFillNonAtomic(buf, lc, len, (byte)0);
return off;
}
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);