diff options
| author | petrs | 2017-06-08 14:56:23 +0200 |
|---|---|---|
| committer | GitHub | 2017-06-08 14:56:23 +0200 |
| commit | 359b4bb5be1a822e389e54b9697504f4f0b43d34 (patch) | |
| tree | 771dac996ecab9e676a0b1b3c6d14692c5dad8a9 /src/cz/crcs/ectester/applet/ECKeyGenerator.java | |
| parent | 7cf4a9d7272c1abd97a160c92ec1534d5ff82373 (diff) | |
| parent | 3f1483635615a0c599ae2e75858be4e39eb08a64 (diff) | |
| download | ECTester-359b4bb5be1a822e389e54b9697504f4f0b43d34.tar.gz ECTester-359b4bb5be1a822e389e54b9697504f4f0b43d34.tar.zst ECTester-359b4bb5be1a822e389e54b9697504f4f0b43d34.zip | |
Merge pull request #1 from petrs/devel
Merge current dev version
Diffstat (limited to 'src/cz/crcs/ectester/applet/ECKeyGenerator.java')
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECKeyGenerator.java | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/src/cz/crcs/ectester/applet/ECKeyGenerator.java b/src/cz/crcs/ectester/applet/ECKeyGenerator.java new file mode 100644 index 0000000..0c20333 --- /dev/null +++ b/src/cz/crcs/ectester/applet/ECKeyGenerator.java @@ -0,0 +1,447 @@ +package cz.crcs.ectester.applet; + +import javacard.framework.CardRuntimeException; +import javacard.framework.ISO7816; +import javacard.framework.ISOException; +import javacard.framework.Util; +import javacard.security.ECPrivateKey; +import javacard.security.ECPublicKey; +import javacard.security.KeyPair; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class ECKeyGenerator { + + private short sw = ISO7816.SW_NO_ERROR; + + /** + * @param keyClass + * @param keyLength + * @return + */ + public KeyPair allocatePair(byte keyClass, short keyLength) { + sw = ISO7816.SW_NO_ERROR; + KeyPair ecKeyPair = null; + try { + ecKeyPair = new KeyPair(keyClass, keyLength); + + if (ecKeyPair.getPublic() == null || ecKeyPair.getPrivate() == null) { + try { + ecKeyPair.genKeyPair(); + } catch (Exception ignored) { + } + } + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return ecKeyPair; + } + + /** + * + * @param keypair + * @param key + * @return + */ + public short clearPair(KeyPair keypair, byte key) { + try { + sw = AppletUtil.keypairCheck(keypair); + if ((key & EC_Consts.KEY_PUBLIC) != 0) keypair.getPublic().clearKey(); + if ((key & EC_Consts.KEY_PRIVATE) != 0) keypair.getPrivate().clearKey(); + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return sw; + } + + /** + * @param keypair + * @return + */ + public short generatePair(KeyPair keypair) { + try { + sw = AppletUtil.keypairCheck(keypair); + keypair.genKeyPair(); + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return sw; + } + + /** + * + * @param keypair + * @param curve + * @param buffer + * @param offset + * @return + */ + public short setCurve(KeyPair keypair, byte curve, byte[] buffer, short offset) { + return setCurve(keypair, curve, EC_Consts.PARAMETERS_ALL, buffer, offset); + } + + /** + * + * @param keypair + * @param curve + * @param params + * @param buffer + * @param offset + * @return + */ + public short setCurve(KeyPair keypair, byte curve, short params, byte[] buffer, short offset) { + return setCurve(keypair, EC_Consts.KEY_BOTH, curve, params, buffer, offset); + } + + /** + * + * @param keypair + * @param key + * @param curve + * @param params + * @param buffer + * @param offset + * @return + */ + public short setCurve(KeyPair keypair, byte key, byte curve, short params, byte[] buffer, short offset) { + byte alg = EC_Consts.getCurveType(curve); + sw = ISO7816.SW_NO_ERROR; + + if (params == EC_Consts.PARAMETERS_NONE) { + return sw; + } + + short length; + //handle fp and f2m differently, as a FP KeyPair doesnt contain a F2M field and vice versa. + if (alg == KeyPair.ALG_EC_FP && (params & EC_Consts.PARAMETER_FP) != 0) { + length = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_FP, buffer, offset); + sw = setParameter(keypair, key, EC_Consts.PARAMETER_FP, buffer, offset, length); + } else if (alg == KeyPair.ALG_EC_F2M && (params & EC_Consts.PARAMETER_F2M) != 0) { + length = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_F2M, buffer, offset); + sw = setParameter(keypair, key, EC_Consts.PARAMETER_F2M, buffer, offset, length); + } + if (sw != ISO7816.SW_NO_ERROR) return sw; + + //go through all params + short paramMask = EC_Consts.PARAMETER_A; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (paramMask & params); + if (masked != 0) { + length = EC_Consts.getCurveParameter(curve, masked, buffer, offset); + sw = setParameter(keypair, key, masked, buffer, offset, length); + if (sw != ISO7816.SW_NO_ERROR) break; + } + paramMask = (short) (paramMask << 1); + } + return sw; + } + + /** + * @param keypair + * @param corruptParams + * @param corruption + * @param buffer + * @param offset + * @return + */ + public short corruptCurve(KeyPair keypair, short corruptParams, byte corruption, byte[] buffer, short offset) { + return corruptCurve(keypair, EC_Consts.KEY_BOTH, corruptParams, corruption, buffer, offset); + } + + /** + * @param keypair + * @param key + * @param corruptParams + * @param corruption + * @param buffer + * @param offset + * @return + */ + public short corruptCurve(KeyPair keypair, byte key, short corruptParams, byte corruption, byte[] buffer, short offset) { + sw = ISO7816.SW_NO_ERROR; + if (corruptParams == EC_Consts.PARAMETERS_NONE) { + return sw; + } + + //go through param bit by bit, and invalidate all selected params + short paramMask = EC_Consts.PARAMETER_FP; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (paramMask & corruptParams); + if (masked != 0) { + short length = exportParameter(keypair, key, masked, buffer, offset); + length = EC_Consts.corruptParameter(corruption, buffer, offset, length); + sw = setParameter(keypair, key, masked, buffer, offset, length); + if (sw != ISO7816.SW_NO_ERROR) break; + } + paramMask = (short) (paramMask << 1); + } + return sw; + } + + /** + * @param key + * @param param + * @param data + * @param offset + * @param length + * @return + */ + public short setParameter(KeyPair keypair, byte key, short param, byte[] data, short offset, short length) { + try { + sw = AppletUtil.keypairCheck(keypair); + + ECPublicKey ecPublicKey = (ECPublicKey) keypair.getPublic(); + ECPrivateKey ecPrivateKey = (ECPrivateKey) keypair.getPrivate(); + + switch (param) { + case EC_Consts.PARAMETER_FP: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldFP(data, offset, length); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldFP(data, offset, length); + break; + case EC_Consts.PARAMETER_F2M: + if (length == 4) { + short i = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i); + } else if (length == 8) { + short i1 = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); + short i2 = Util.makeShort(data[(short) (offset + 4)], data[(short) (offset + 5)]); + short i3 = Util.makeShort(data[(short) (offset + 6)], data[(short) (offset + 7)]); +// if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i1, i2, i3); +// if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i1, i2, i3); + // TODO: fix this, ^^ fails on jcardsim, but is up to spec + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i3, i2, i1); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i3, i2, i1); + } else { + sw = ISO7816.SW_UNKNOWN; + } + break; + case EC_Consts.PARAMETER_A: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setA(data, offset, length); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setA(data, offset, length); + break; + case EC_Consts.PARAMETER_B: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setB(data, offset, length); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setB(data, offset, length); + break; + case EC_Consts.PARAMETER_G: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setG(data, offset, length); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setG(data, offset, length); + break; + case EC_Consts.PARAMETER_R: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setR(data, offset, length); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setR(data, offset, length); + break; + case EC_Consts.PARAMETER_K: + short k = 0; + if (length > 2 || length <= 0) { + sw = ISO7816.SW_UNKNOWN; + break; + } else if (length == 2) { + k = Util.getShort(data, offset); + } else if (length == 1) { + k = data[offset]; + } + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setK(k); + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setK(k); + break; + case EC_Consts.PARAMETER_S: + if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setS(data, offset, length); + break; + case EC_Consts.PARAMETER_W: + if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setW(data, offset, length); + break; + default: + ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); + } + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return sw; + } + + /** + * @param keypair + * @param params + * @param inBuffer + * @param inOffset + * @return + */ + public short setExternalCurve(KeyPair keypair, short params, byte[] inBuffer, short inOffset) { + return setExternalCurve(keypair, EC_Consts.KEY_BOTH, params, inBuffer, inOffset); + } + + /** + * @param keypair + * @param key + * @param params + * @param inBuffer + * @param inOffset + * @return + */ + public short setExternalCurve(KeyPair keypair, byte key, short params, byte[] inBuffer, short inOffset) { + sw = ISO7816.SW_NO_ERROR; + if (params == EC_Consts.PARAMETERS_NONE) { + return sw; + } + + short paramMask = EC_Consts.PARAMETER_FP; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (paramMask & params); + if (masked != 0) { + short paramLength = Util.getShort(inBuffer, inOffset); + inOffset += 2; + sw = setParameter(keypair, key, masked, inBuffer, inOffset, paramLength); + inOffset += paramLength; + if (sw != ISO7816.SW_NO_ERROR) break; + } + paramMask = (short) (paramMask << 1); + } + return sw; + } + + /** + * Exports a selected parameter from a given keyPairs key. + * + * @param keypair keypair to export from + * @param key key to export from (KEY_PUBLIC || KEY_PRIVATE) + * @param param parameter to export (EC_Consts.PARAMETER_* || ...) + * @param outputBuffer buffer to write to + * @param outputOffset offset to start writing in buffer + * @return length of data written + */ + public short exportParameter(KeyPair keypair, byte key, short param, byte[] outputBuffer, short outputOffset) { + short length = 0; + try { + sw = AppletUtil.keypairCheck(keypair); + ECPublicKey ecPublicKey = (ECPublicKey) keypair.getPublic(); + ECPrivateKey ecPrivateKey = (ECPrivateKey) keypair.getPrivate(); + + switch (param) { + case EC_Consts.PARAMETER_FP: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getField(outputBuffer, outputOffset); + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getField(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_F2M: + if ((key & EC_Consts.KEY_PUBLIC) != 0) { + Util.setShort(outputBuffer, outputOffset, ecPublicKey.getSize()); + length = 2; + length += ecPublicKey.getField(outputBuffer, (short) (outputOffset + 2)); + } + if ((key & EC_Consts.KEY_PRIVATE) != 0) { + Util.setShort(outputBuffer, outputOffset, ecPrivateKey.getSize()); + length = 2; + length += ecPrivateKey.getField(outputBuffer, (short) (outputOffset + 2)); + } + break; + case EC_Consts.PARAMETER_A: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getA(outputBuffer, outputOffset); + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getA(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_B: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getB(outputBuffer, outputOffset); + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getB(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_G: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getG(outputBuffer, outputOffset); + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getG(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_R: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getR(outputBuffer, outputOffset); + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getR(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_K: + length = 2; + if ((key & EC_Consts.KEY_PUBLIC) != 0) + Util.setShort(outputBuffer, outputOffset, ecPublicKey.getK()); + if ((key & EC_Consts.KEY_PRIVATE) != 0) + Util.setShort(outputBuffer, outputOffset, ecPrivateKey.getK()); + break; + case EC_Consts.PARAMETER_W: + if ((key & EC_Consts.KEY_PUBLIC) != 0) length = ecPublicKey.getW(outputBuffer, outputOffset); + break; + case EC_Consts.PARAMETER_S: + if ((key & EC_Consts.KEY_PRIVATE) != 0) length = ecPrivateKey.getS(outputBuffer, outputOffset); + break; + default: + ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); + } + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return length; + } + + /** + * Exports selected parameters from a given keyPairs key. + * Raw parameter data is always prepended by its length as a + * short value. The order of parameters is the usual one from + * EC_Consts: field,a,b,g,r,k,w,s. + * + * @param keypair keyPair to export from + * @param key key to export from (KEY_PUBLIC || KEY_PRIVATE) + * @param params params to export (EC_Consts.PARAMETER_* | ...) + * @param buffer buffer to export to + * @param offset offset to start writing in buffer + * @return length of data written + */ + public short exportParameters(KeyPair keypair, byte key, short params, byte[] buffer, short offset) { + sw = ISO7816.SW_NO_ERROR; + if (params == EC_Consts.PARAMETERS_NONE) { + return sw; + } + + short length = 0; + short paramMask = EC_Consts.PARAMETER_FP; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (paramMask & params); + if (masked != 0) { + short len = exportParameter(keypair, key, masked, buffer, (short) (offset + 2)); + if (len == 0) { + paramMask = (short) (paramMask << 1); + continue; + } + Util.setShort(buffer, offset, len); + offset += len + 2; + length += len + 2; + } + paramMask = (short) (paramMask << 1); + } + return length; + } + + /** + * Copies this KeyPairs curve parameters to another ECKeyGenerator. + * + * @param from keyPair to copy from + * @param to keyPair to copy to + * @param params parameters to copy + * @param buffer buffer to use for copying + * @param offset offset to use in buffer + * @return sw + */ + public short copyCurve(KeyPair from, KeyPair to, short params, byte[] buffer, short offset) { + try { + sw = AppletUtil.keypairCheck(from); + sw = AppletUtil.keypairCheck(to); + + short param = EC_Consts.PARAMETER_FP; + while (param <= EC_Consts.PARAMETER_K) { + short masked = (short) (param & params); + if (masked != 0) { + short paramLength = exportParameter(from, EC_Consts.KEY_PUBLIC, masked, buffer, offset); + setParameter(to, EC_Consts.KEY_BOTH, masked, buffer, offset, paramLength); + } + param = (short) (param << 1); + } + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return sw; + } + + public short getSW() { + return sw; + } +} |
