javacardx.crypto.Cipher Java Examples
The following examples show how to use
javacardx.crypto.Cipher.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 7 votes |
private void internalAuthenticate(APDU apdu) { byte[] buffer = apdu.getBuffer(); // PW1 with 0x82 if (!pins[PIN_INDEX_PW1].isValidated() || !pinSubmitted[1]) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } short len = apdu.setIncomingAndReceive(); if (len > (short) 102 || len != (buffer[ISO7816.OFFSET_LC] & 0xFF)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (!authenticationKey.getPrivate().isInitialized()) { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } cipherRSA.init(authenticationKey.getPrivate(), Cipher.MODE_ENCRYPT); cipherRSA.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short) 0); apdu.setOutgoingAndSend((short) 0, RSA_KEY_LENGTH_BYTES); }
Example #2
Source File: Bignat.java From JCMathLib with MIT License | 6 votes |
/** * Calculates {@code res := base ** exp mod mod} using RSA engine. * Requirements: * 1. Modulo must be either 521, 1024, 2048 or other lengths supported by RSA (see appendzeros() and mod() method) * 2. Base must have the same size as modulo (see prependzeros()) * @param baseLen length of base rounded to size of RSA engine * @param base value of base (if size is not equal to baseLen then zeroes are appended) * @param exponent array with exponent * @param exponentLen length of exponent * @param modulo value of modulo * @param resultArray array for the computed result * @param resultOffset start offset of resultArray */ private short n_mod_exp(short baseLen, Bignat base, byte[] exponent, short exponentLen, Bignat modulo, byte[] resultArray, short resultOffset) { // Verify if pre-allocated engine match the required values if (bnh.fnc_NmodE_pubKey.getSize() < (short) (modulo.length() * 8)) { // attempt to perform modulu with higher or smaller than supported length - try change constant MODULO_ENGINE_MAX_LENGTH ISOException.throwIt(ReturnCodes.SW_BIGNAT_MODULOTOOLARGE); } if (bnh.fnc_NmodE_pubKey.getSize() < (short) (base.length() * 8)) { ISOException.throwIt(ReturnCodes.SW_BIGNAT_MODULOTOOLARGE); } // Potential problem: we are changing key value for publicKey already used before with occ.bnHelper.modCipher. // Simulator and potentially some cards fail to initialize this new value properly (probably assuming that same key object will always have same value) // Fix (if problem occure): generate new key object: RSAPublicKey publicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, (short) (baseLen * 8), false); bnh.fnc_NmodE_pubKey.setExponent(exponent, (short) 0, exponentLen); bnh.lock(bnh.fnc_deep_resize_tmp); modulo.append_zeros(baseLen, bnh.fnc_deep_resize_tmp, (short) 0); bnh.fnc_NmodE_pubKey.setModulus(bnh.fnc_deep_resize_tmp, (short) 0, baseLen); bnh.fnc_NmodE_cipher.init(bnh.fnc_NmodE_pubKey, Cipher.MODE_DECRYPT); base.prepend_zeros(baseLen, bnh.fnc_deep_resize_tmp, (short) 0); // BUGBUG: Check if input is not all zeroes (causes out-of-bound exception on some cards) short len = bnh.fnc_NmodE_cipher.doFinal(bnh.fnc_deep_resize_tmp, (short) 0, baseLen, resultArray, resultOffset); bnh.unlock(bnh.fnc_deep_resize_tmp); return len; }
Example #3
Source File: FIDOStandalone.java From ledger-u2f-javacard with Apache License 2.0 | 6 votes |
/** * Init cipher engines and allocate memory. */ public FIDOStandalone() { scratch = JCSystem.makeTransientByteArray((short) 64, JCSystem.CLEAR_ON_DESELECT); keyPair = new KeyPair( (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false), (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false)); Secp256r1.setCommonCurveParameters((ECKey) keyPair.getPrivate()); Secp256r1.setCommonCurveParameters((ECKey) keyPair.getPublic()); random = RandomData.getInstance(RandomData.ALG_KEYGENERATION); // Initialize the unique wrapping key chipKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); random.nextBytes(scratch, (short) 0, (short) 32); chipKey.setKey(scratch, (short) 0); cipherEncrypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); cipherEncrypt.init(chipKey, Cipher.MODE_ENCRYPT, IV_ZERO_AES, (short) 0, (short) IV_ZERO_AES.length); cipherDecrypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); cipherDecrypt.init(chipKey, Cipher.MODE_DECRYPT, IV_ZERO_AES, (short) 0, (short) IV_ZERO_AES.length); }
Example #4
Source File: GidsBaseTestClass.java From GidsApplet with GNU General Public License v3.0 | 6 votes |
protected void authenticateGeneral(byte[] key, boolean successexpected) { byte[] challenge, challengeresponse = new byte[8]; Cipher cipherDES = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); DESKey deskey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); deskey.setKey(key, (short) 0); // select admin key execute("00 22 81 A4 03 83 01 80"); // get a challenge ResponseAPDU response = execute("00 87 00 00 04 7C 02 81 00 00"); if (!Arrays.equals(Arrays.copyOfRange(response.getBytes(), 0, 4), new byte[] {0x7C,0x0A,(byte) 0x81,0x08})) { fail("not a challenge:" + DatatypeConverter.printHexBinary(response.getBytes())); } // compute the response challenge = Arrays.copyOfRange(response.getBytes(), 4, 12); //solve challenge cipherDES.init(deskey, Cipher.MODE_ENCRYPT); cipherDES.doFinal(challenge, (short) 0, (short)8, challengeresponse, (short) 0); // send the response execute("00 87 00 00 0C 7C 0A 82 08" + DatatypeConverter.printHexBinary(challengeresponse), (successexpected?0x9000: 0x6982)); }
Example #5
Source File: PinTests.java From GidsApplet with GNU General Public License v3.0 | 6 votes |
@Test public void authenticateGeneralReplayAttack() { byte[] challenge, challengeresponse = new byte[8]; byte[] key = DatatypeConverter.parseHexBinary("010203040506070801020304050607080102030405060708"); Cipher cipherDES = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); DESKey deskey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); deskey.setKey(key, (short) 0); // select admin key execute("00 22 81 A4 03 83 01 80"); // get a challenge ResponseAPDU response = execute("00 87 00 00 04 7C 02 81 00 00"); if (!Arrays.equals(Arrays.copyOfRange(response.getBytes(), 0, 4), new byte[] {0x7C,0x0A,(byte) 0x81,0x08})) { fail("not a challenge:" + DatatypeConverter.printHexBinary(response.getBytes())); } // compute the response challenge = Arrays.copyOfRange(response.getBytes(), 4, 12); //solve challenge cipherDES.init(deskey, Cipher.MODE_ENCRYPT); cipherDES.doFinal(challenge, (short) 0, (short)8, challengeresponse, (short) 0); // send the response execute("00 87 00 00 0C 7C 0A 82 08" + DatatypeConverter.printHexBinary(challengeresponse), 0x9000); execute("00 87 00 00 0C 7C 0A 82 08" + DatatypeConverter.printHexBinary(challengeresponse), 0x6985); }
Example #6
Source File: OpenPGPSecureMessaging.java From javacard-openpgpcard with GNU General Public License v2.0 | 6 votes |
/** * Set the MAC and encryption (and decryption) session keys. Each key is a * 16 byte 3DES EDE key. This method may be called at any time and will * immediately replace the session key. * * @param buffer byte array containing the session keys. * @param offset location of the session keys in the buffer. */ public void setSessionKeys(byte[] buffer, short offset) { // Check for empty keys if(Util.arrayCompare(buffer, (short)0, EMPTY_KEY, (short)0, KEY_SIZE) == 0 || Util.arrayCompare(buffer, KEY_SIZE, EMPTY_KEY, (short)0, KEY_SIZE) == 0) { keyMAC.clearKey(); keyENC.clearKey(); } else { keyMAC.setKey(buffer, offset); keyENC.setKey(buffer, (short) (offset + KEY_SIZE)); signer.init(keyMAC, Signature.MODE_SIGN); verifier.init(keyMAC, Signature.MODE_VERIFY); cipher.init(keyENC, Cipher.MODE_ENCRYPT); decipher.init(keyENC, Cipher.MODE_DECRYPT); } }
Example #7
Source File: OpenPGPSecureMessaging.java From javacard-openpgpcard with GNU General Public License v2.0 | 6 votes |
/** * Construct a new secure messaging wrapper. */ public OpenPGPSecureMessaging() { ssc = JCSystem.makeTransientByteArray(SSC_SIZE, JCSystem.CLEAR_ON_DESELECT); tmp = JCSystem.makeTransientByteArray(TMP_SIZE, JCSystem.CLEAR_ON_DESELECT); signer = Signature.getInstance( Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3, false); verifier = Signature.getInstance( Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3, false); cipher = Cipher.getInstance( Cipher.ALG_DES_CBC_ISO9797_M2, false); decipher = Cipher.getInstance( Cipher.ALG_DES_CBC_ISO9797_M2, false); keyMAC = (DESKey) KeyBuilder.buildKey( KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_DES3_2KEY, false); keyENC = (DESKey) KeyBuilder.buildKey( KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_DES3_2KEY, false); ssc_set = JCSystem.makeTransientBooleanArray((short)1, JCSystem.CLEAR_ON_DESELECT); ssc_set[0] = false; }
Example #8
Source File: Crypto.java From status-keycard with Apache License 2.0 | 6 votes |
Crypto() { random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM); sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false); ecdh = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false); sha512 = MessageDigest.getInstance(MessageDigest.ALG_SHA_512, false); aesCbcIso9797m2 = Cipher.getInstance(Cipher.ALG_AES_CBC_ISO9797_M2,false); try { hmacSHA512 = Signature.getInstance(Signature.ALG_HMAC_SHA_512, false); hmacKey = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false); } catch (CryptoException e) { hmacSHA512 = null; hmacBlock = JCSystem.makeTransientByteArray(HMAC_BLOCK_SIZE, JCSystem.CLEAR_ON_RESET); } }
Example #9
Source File: SecureChannel.java From status-keycard with Apache License 2.0 | 6 votes |
/** * Decrypts the given APDU buffer. The plaintext is written in-place starting at the ISO7816.OFFSET_CDATA offset. The * MAC and padding are stripped. The LC byte is overwritten with the plaintext length. If the MAC cannot be verified * the secure channel is reset and the SW 0x6982 is thrown. * * @param apduBuffer the APDU buffer * @return the length of the decrypted */ public short preprocessAPDU(byte[] apduBuffer) { if (!isOpen()) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } short apduLen = (short)((short) apduBuffer[ISO7816.OFFSET_LC] & 0xff); if (!verifyAESMAC(apduBuffer, apduLen)) { reset(); ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED); } crypto.aesCbcIso9797m2.init(scEncKey, Cipher.MODE_DECRYPT, secret, (short) 0, SC_BLOCK_SIZE); Util.arrayCopyNonAtomic(apduBuffer, ISO7816.OFFSET_CDATA, secret, (short) 0, SC_BLOCK_SIZE); short len = crypto.aesCbcIso9797m2.doFinal(apduBuffer, (short)(ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE), (short) (apduLen - SC_BLOCK_SIZE), apduBuffer, ISO7816.OFFSET_CDATA); apduBuffer[ISO7816.OFFSET_LC] = (byte) len; return len; }
Example #10
Source File: SecureChannel.java From status-keycard with Apache License 2.0 | 6 votes |
/** * Decrypts the content of the APDU by generating an AES key using EC-DH. Usable only with specific commands. * @param apduBuffer the APDU buffer */ public void oneShotDecrypt(byte[] apduBuffer) { crypto.ecdh.init(scKeypair.getPrivate()); short off = (short)(ISO7816.OFFSET_CDATA + 1); try { crypto.ecdh.generateSecret(apduBuffer, off, apduBuffer[ISO7816.OFFSET_CDATA], secret, (short) 0); off = (short)(off + apduBuffer[ISO7816.OFFSET_CDATA]); } catch(Exception e) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); return; } scEncKey.setKey(secret, (short) 0); crypto.aesCbcIso9797m2.init(scEncKey, Cipher.MODE_DECRYPT, apduBuffer, off, SC_BLOCK_SIZE); off = (short)(off + SC_BLOCK_SIZE); apduBuffer[ISO7816.OFFSET_LC] = (byte) crypto.aesCbcIso9797m2.doFinal(apduBuffer, off, (short)((short)(apduBuffer[ISO7816.OFFSET_LC] & 0xff) - off + ISO7816.OFFSET_CDATA), apduBuffer, ISO7816.OFFSET_CDATA); }
Example #11
Source File: GaussKeyCard.java From gauss-key-card with Apache License 2.0 | 6 votes |
private void processAuthenticate(APDU apdu) { final byte[] buffer = apdu.getBuffer(); final short incomingLength = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); if (incomingLength < (short)0x51) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } ecdh.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short)65, buffer, (short)16); aes_key.setKey(buffer, (short)16); aes_ecb.init(aes_key, Cipher.MODE_ENCRYPT); // Generate the random salt. rng.generateData(buffer, OFFSET_CHALLENGE, (short)4); short len = aes_ecb.doFinal(buffer, OFFSET_CHALLENGE, (short)16, buffer, (short)0); final short le = apdu.setOutgoing(); len = le > 0 ? (le > len ? len : le) : len; apdu.setOutgoingLength(len); apdu.sendBytes((short)0, len); }
Example #12
Source File: OpenPGPSecureMessaging.java From javacard-openpgpcard with GNU General Public License v2.0 | 5 votes |
/** * Set the encryption session key. Each key is a 16 byte 3DES EDE key. This method * may be called at any time and will immediately replace the session key. * * @param buffer byte array containing the session key. * @param offset location of the session key in the buffer. */ public void setSessionKeyEncryption(byte[] buffer, short offset) { // Check for empty keys if(Util.arrayCompare(buffer, (short)0, EMPTY_KEY, (short)0, KEY_SIZE) == 0) { keyMAC.clearKey(); keyENC.clearKey(); } else { keyENC.setKey(buffer, (short) (offset + KEY_SIZE)); cipher.init(keyENC, Cipher.MODE_ENCRYPT); decipher.init(keyENC, Cipher.MODE_DECRYPT); } }
Example #13
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 5 votes |
private void computeSignature(APDU apdu) { byte[] buffer = apdu.getBuffer(); short length = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); // Make sure that DigestInfo is <= 40% of the RSA key length. if ((short) (length * 4) > (short) (RSA_KEY_LENGTH_BYTES * 10) || apdu.setIncomingAndReceive() != length) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (!pinSubmitted[PIN_INDEX_PW1] || !pins[PIN_INDEX_PW1].isValidated()) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } if (!signatureKey.getPrivate().isInitialized()) { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } if (pinValidForMultipleSignatures == (byte) 0) { pinSubmitted[PIN_INDEX_PW1] = false; } cipherRSA.init(signatureKey.getPrivate(), Cipher.MODE_ENCRYPT); cipherRSA.doFinal(buffer, ISO7816.OFFSET_CDATA, length, buffer, (short) 0); JCSystem.beginTransaction(); if (signatureCounter[2] != (byte) 0xFF) { signatureCounter[2] = (byte) ((signatureCounter[2] & 0xFF) + 1); } else { signatureCounter[2] = 0; if (signatureCounter[1] != (byte) 0xFF) { signatureCounter[1] = (byte) ((signatureCounter[1] & 0xFF) + 1); } else if (signatureCounter[0] != (byte) 0xFF) { signatureCounter[1] = 0; signatureCounter[0] = (byte) ((signatureCounter[0] & 0xFF) + 1); } else { JCSystem.abortTransaction(); ISOException.throwIt(ISO7816.SW_FILE_FULL); } } JCSystem.commitTransaction(); apdu.setOutgoingAndSend((short) 0, RSA_KEY_LENGTH_BYTES); }
Example #14
Source File: PinTests.java From GidsApplet with GNU General Public License v3.0 | 5 votes |
@Test public void authenticateMutualReplayAttack() { byte[] key = DatatypeConverter.parseHexBinary("010203040506070801020304050607080102030405060708"); byte[] myChallenge= new byte [16], globalchallenge = new byte[40], challengeresponse = new byte[40]; byte[] challenge; Cipher cipherDES = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); DESKey deskey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); deskey.setKey(key, (short) 0); RandomData randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM); randomData.generateData(myChallenge, (short) 0, (short) myChallenge.length); // select admin key execute("00 22 81 A4 03 83 01 80"); // get a challenge ResponseAPDU response = execute("00 87 00 00 14 7C 12 81 10" + DatatypeConverter.printHexBinary(myChallenge) + "00"); if (!Arrays.equals(Arrays.copyOfRange(response.getBytes(), 0, 4), new byte[] {0x7C,0x12,(byte) 0x81,0x10})) { fail("not a challenge:" + DatatypeConverter.printHexBinary(response.getBytes())); } // compute the response challenge = Arrays.copyOfRange(response.getBytes(), 4, 20); //solve challenge //R2 System.arraycopy(challenge, 0, globalchallenge, 0, 16); //R1 System.arraycopy(myChallenge, 0, globalchallenge, 16, 16); // keep Z1 random globalchallenge[(short)39] = (byte) 0x80; cipherDES.init(deskey, Cipher.MODE_ENCRYPT); cipherDES.doFinal(globalchallenge, (short) 0, (short)40, challengeresponse, (short) 0); // send the response execute("00 87 00 00 2C 7C 2A 82 28" + DatatypeConverter.printHexBinary(challengeresponse), 0x9000); execute("00 87 00 00 2C 7C 2A 82 28" + DatatypeConverter.printHexBinary(challengeresponse), 0x6985); }
Example #15
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 5 votes |
/** * This function allows to set the 2FA key and enable 2FA. * Once activated, 2FA can only be deactivated when the seed is reset. * * ins: 0x79 * p1: 0x00 * p2: 0x00 * data: [hmacsha1_key(20b) | amount_limit(8b)] * return: (none) */ private short set2FAKey(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // cannot modify an existing 2FA! if (needs_2FA) ISOException.throwIt(SW_2FA_INITIALIZED_KEY); //check input length short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); if (bytesLeft < (short)(20+8)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); if (!done_once_2FA){ data2FA= new byte[OFFSET_2FA_SIZE]; randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM); aes128_cbc= Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); key_2FA= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); done_once_2FA= true; } short offset= ISO7816.OFFSET_CDATA; Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_HMACKEY, (short)20); offset+=(short)20; Util.arrayCopyNonAtomic(buffer, offset, data2FA, OFFSET_2FA_LIMIT, (short)8); offset+=(short)8; // hmac derivation for id_2FA & key_2FA HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)0, (short)6, data2FA, OFFSET_2FA_ID); HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, CST_2FA, (short)6, (short)7, recvBuffer, (short)0); key_2FA.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!! needs_2FA= true; return (short)0; }
Example #16
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 4 votes |
private void decrypt(APDU apdu) { byte[] buffer = apdu.getBuffer(); // PW1 with 0x82 if (!pins[PIN_INDEX_PW1].isValidated() || !pinSubmitted[1]) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } if (!confidentialityKey.getPrivate().isInitialized()) { ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); } boolean firstCommand = (commandChainingBuffer[TEMP_INS] != buffer[ISO7816.OFFSET_INS]); // Mark the command chain as bad so it stays in this state in case of exception. short len = apdu.setIncomingAndReceive(); if (len < 1) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (firstCommand) { Util.arrayCopyNonAtomic(buffer, (short) (ISO7816.OFFSET_CDATA + 1), commandChainingBuffer, TEMP_GET_RESPONSE_DATA, (short) (len - 1)); len = (short) (len - 1); } else { short existing = Util.getShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH); if ((short) (len + existing) > RSA_KEY_LENGTH_BYTES) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, commandChainingBuffer, (short) (TEMP_GET_RESPONSE_DATA + existing), len); len += existing; } if (len < RSA_KEY_LENGTH_BYTES) { commandChainingBuffer[TEMP_INS] = CMD_COMPUTE_PSO; Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH, len); return; // For compatibily with GPG } // We have enough bytes to decrypt. cipherRSA.init(confidentialityKey.getPrivate(), Cipher.MODE_DECRYPT); len = cipherRSA.doFinal(commandChainingBuffer, TEMP_GET_RESPONSE_DATA, RSA_KEY_LENGTH_BYTES, buffer, (short) 0); // Clear command chaining buffer to make ready for next operation. Util.arrayFillNonAtomic(commandChainingBuffer, (short) 0, (short) commandChainingBuffer.length, (byte) 0); apdu.setOutgoingAndSend((short) 0, len); }
Example #17
Source File: Gpg.java From OpenPGP-Card with GNU General Public License v3.0 | 4 votes |
/** * Only this class's install method should create the applet object. */ protected Gpg(byte[] parameters, short offset, byte length) { pinLength = new byte[3]; pins = new OwnerPIN[3]; pins[PIN_INDEX_PW1] = new OwnerPIN(MAX_TRIES_PIN1, MAX_PIN_LENGTH); pins[PIN_INDEX_PW1].update(defaultPIN, (short) 0, MIN_PIN1_LENGTH); pinLength[PIN_INDEX_PW1] = MIN_PIN1_LENGTH; pins[PIN_INDEX_PW3] = new OwnerPIN(MAX_TRIES_PIN3, MAX_PIN_LENGTH); pins[PIN_INDEX_PW3].update(defaultPIN, (short) 0, MIN_PIN3_LENGTH); pinLength[PIN_INDEX_PW3] = MIN_PIN3_LENGTH; // The resetting code is disabled by default. pins[PIN_INDEX_RC] = new OwnerPIN(MAX_TRIES_RC, MAX_PIN_LENGTH); pinLength[PIN_INDEX_RC] = 0; pinSubmitted = JCSystem.makeTransientBooleanArray((short) 2, JCSystem.CLEAR_ON_DESELECT); commandChainingBuffer = JCSystem.makeTransientByteArray((short) (TEMP_PUT_KEY_ACCUMULATOR + RSA_KEY_LENGTH_BYTES), JCSystem.CLEAR_ON_DESELECT); privateDO1 = new byte[255]; privateDO2 = new byte[255]; privateDO3 = new byte[255]; privateDO4 = new byte[255]; loginData = new byte[(short) 255]; url = new byte[(short) 255]; name = new byte[(short) 40]; language = new byte[(short) 9]; sex = new byte[(short) 1]; fingerprints = new byte[(short) 60]; caFingerprints = new byte[(short) 60]; generationDates = new byte[(short) 12]; signatureCounter = new byte[(short) 3]; pinValidForMultipleSignatures = (byte) 0; signatureKey = new KeyPair(KeyPair.ALG_RSA_CRT, (short) 2048); confidentialityKey = new KeyPair(KeyPair.ALG_RSA_CRT, (short) 2048); authenticationKey = new KeyPair(KeyPair.ALG_RSA_CRT, (short) 2048); cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false); randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM); register(); }
Example #18
Source File: Crypto.java From ledger-javacard with GNU Affero General Public License v3.0 | 4 votes |
public static void initCipherAES(AESKey key, boolean encrypt) { blobEncryptDecryptAES.init(key, (encrypt ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT), IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length); }
Example #19
Source File: Crypto.java From ledger-javacard with GNU Affero General Public License v3.0 | 4 votes |
public static void initCipher(DESKey key, boolean encrypt) { blobEncryptDecrypt.init(key, (encrypt ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT), IV_ZERO, (short)0, (short)IV_ZERO.length); }
Example #20
Source File: IsoApplet.java From IsoApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Compute a digital signature of the data from the apdu * using the private key referenced by an earlier * MANAGE SECURITY ENVIRONMENT apdu. * * \attention The apdu should contain a hash, not raw data for RSA keys. * PKCS1 padding will be applied if neccessary. * * \param apdu The PERFORM SECURITY OPERATION apdu with P1=9E and P2=9A. * * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH * and SW_UNKNOWN. */ private void computeDigitalSignature(APDU apdu) throws ISOException { byte[] buf = apdu.getBuffer(); short offset_cdata; short lc; short sigLen = 0; switch(currentAlgorithmRef[0]) { case ALG_RSA_PAD_PKCS1: // Receive. // Bytes received must be Lc. lc = apdu.setIncomingAndReceive(); if(lc != apdu.getIncomingLength()) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } offset_cdata = apdu.getOffsetCdata(); // RSA signature operation. RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) keys[currentPrivateKeyRef[0]]; if(lc > (short) 247) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } rsaPkcs1Cipher.init(rsaKey, Cipher.MODE_ENCRYPT); sigLen = rsaPkcs1Cipher.doFinal(buf, offset_cdata, lc, ram_buf, (short)0); if(sigLen != 256) { ISOException.throwIt(ISO7816.SW_UNKNOWN); } // A single short APDU can handle 256 bytes - only one send operation neccessary. short le = apdu.setOutgoing(); if(le < sigLen) { ISOException.throwIt(ISO7816.SW_CORRECT_LENGTH_00); } apdu.setOutgoingLength(sigLen); apdu.sendBytesLong(ram_buf, (short) 0, sigLen); break; case ALG_ECDSA_SHA1: // Get the key - it must be a EC private key, // checks have been done in MANAGE SECURITY ENVIRONMENT. ECPrivateKey ecKey = (ECPrivateKey) keys[currentPrivateKeyRef[0]]; // Initialisation should be done when: // - No command chaining is performed at all. // - Command chaining is performed and this is the first apdu in the chain. if(ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] == (short) 0) { ecdsaSignature.init(ecKey, Signature.MODE_SIGN); if(isCommandChainingCLA(apdu)) { ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = (short) 1; } } short recvLen = apdu.setIncomingAndReceive(); offset_cdata = apdu.getOffsetCdata(); // Receive data. For extended APDUs, the data is received piecewise // and aggregated in the hash. When using short APDUs, command // chaining is performed. while (recvLen > 0) { ecdsaSignature.update(buf, offset_cdata, recvLen); recvLen = apdu.receiveBytes(offset_cdata); } if(!isCommandChainingCLA(apdu)) { sigLen = ecdsaSignature.sign(buf, (short)0, (short)0, buf, (short) 0); ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS] = (short) 0; apdu.setOutgoingAndSend((short) 0, sigLen); } else { ram_chaining_cache[RAM_CHAINING_CACHE_OFFSET_CURRENT_POS]++; } break; default: // Wrong/unknown algorithm. ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } }
Example #21
Source File: PayPass.java From CardExamples with The Unlicense | 4 votes |
public PayPass(byte[] bArray, short bOffset, byte bLength) { if (bLength != 27) ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); // transaction starts JCSystem.beginTransaction(); // set up and initialize all the DES encryption/descrytion ciphers used in the app DESKEY_KD_PERSO_L_EN = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false); DESKEY_KD_PERSO_R_DE = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false); DESKEY_KD_PERSO_L_DE = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false); DESKEY_KD_PERSO_R_EN = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false); CIPHER_KD_PERSO_L_EN = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false); CIPHER_KD_PERSO_R_DE = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false); CIPHER_KD_PERSO_L_DE = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false); CIPHER_KD_PERSO_R_EN = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false); // transaction ends JCSystem.commitTransaction(); // define RAM buffers for faster operation CVC3_DATA = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_DESELECT); CMD_BUF = JCSystem.makeTransientByteArray((short) 261, JCSystem.CLEAR_ON_DESELECT); MAC = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_DESELECT); // on initialize the current state is not_alive state = not_alive; PROFILE = new Profile(); // testing area // pre-personalization data // issuer supply PROFILE.VER_KMC = (byte) 0x01; // MC version PROFILE.VER_KMC = bArray[bOffset]; // MC version PROFILE.KMC_ID[0] = (byte) 0x54; // key id PROFILE.KMC_ID[1] = (byte) 0x13; PROFILE.KMC_ID[2] = (byte) 0x12; PROFILE.KMC_ID[3] = (byte) 0xFF; PROFILE.KMC_ID[4] = (byte) 0xFF; PROFILE.KMC_ID[5] = (byte) 0xFF; Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 1), PROFILE.KMC_ID, (short) 0, (short) 6); PROFILE.KD_PERSO[0] = (byte) 0xA8; // personalization key PROFILE.KD_PERSO[1] = (byte) 0x6A; PROFILE.KD_PERSO[2] = (byte) 0x3D; PROFILE.KD_PERSO[3] = (byte) 0x06; PROFILE.KD_PERSO[4] = (byte) 0xCA; PROFILE.KD_PERSO[5] = (byte) 0xE7; PROFILE.KD_PERSO[6] = (byte) 0x04; PROFILE.KD_PERSO[7] = (byte) 0x6A; PROFILE.KD_PERSO[8] = (byte) 0x10; PROFILE.KD_PERSO[9] = (byte) 0x63; PROFILE.KD_PERSO[10] = (byte) 0x58; PROFILE.KD_PERSO[11] = (byte) 0xD5; PROFILE.KD_PERSO[12] = (byte) 0xB8; PROFILE.KD_PERSO[13] = (byte) 0x23; PROFILE.KD_PERSO[14] = (byte) 0x9C; PROFILE.KD_PERSO[15] = (byte) 0xBE; Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 7), PROFILE.KD_PERSO, (short) 0, (short) 16); PROFILE.CSN[0] = (byte) 0x89; PROFILE.CSN[1] = (byte) 0xAA; PROFILE.CSN[2] = (byte) 0x7F; PROFILE.CSN[3] = (byte) 0x00; Util.arrayCopyNonAtomic(bArray, (short) (bOffset + 23), PROFILE.CSN, (short) 0, (short) 4); // end issuer supply // profile can now be considered in personalization state PROFILE.STATE = PERSO; }
Example #22
Source File: IsoApplet.java From IsoApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Decipher the data from the apdu using the private key referenced by * an earlier MANAGE SECURITY ENVIRONMENT apdu. * * \param apdu The PERFORM SECURITY OPERATION apdu with P1=80 and P2=86. * * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH and * SW_WRONG_DATA */ private void decipher(APDU apdu) { short offset_cdata; short lc; short decLen = -1; lc = doChainingOrExtAPDU(apdu); offset_cdata = 0; // Padding indicator should be "No further indication". if(ram_buf[offset_cdata] != (byte) 0x00) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } switch(currentAlgorithmRef[0]) { case ALG_RSA_PAD_PKCS1: // Get the key - it must be an RSA private key, // checks have been done in MANAGE SECURITY ENVIRONMENT. RSAPrivateCrtKey theKey = (RSAPrivateCrtKey) keys[currentPrivateKeyRef[0]]; // Check the length of the cipher. // Note: The first byte of the data field is the padding indicator // and therefor not part of the ciphertext. if((short)(lc-1) != (short)(theKey.getSize() / 8)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } rsaPkcs1Cipher.init(theKey, Cipher.MODE_DECRYPT); try { decLen = rsaPkcs1Cipher.doFinal(ram_buf, (short)(offset_cdata+1), (short)(lc-1), apdu.getBuffer(), (short) 0); } catch(CryptoException e) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } // We have to send at most 256 bytes. A short APDU can handle that - only one send operation neccessary. apdu.setOutgoingAndSend((short)0, decLen); break; default: ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } }
Example #23
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function allows to decrypt a secure channel message * * ins: 0x82 * * p1: 0x00 (RFU) * p2: 0x00 (RFU) * data: [IV(16b) | data_size(2b) | encrypted_command | mac_size(2b) | mac] * * return: [decrypted command] * */ private short ProcessSecureChannel(APDU apdu, byte[] buffer){ short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); short offset = ISO7816.OFFSET_CDATA; if (!initialized_secure_channel){ ISOException.throwIt(SW_SECURE_CHANNEL_UNINITIALIZED); } // check hmac if (bytesLeft<18) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizein = Util.getShort(buffer, (short) (offset+SIZE_SC_IV)); if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizemac= Util.getShort(buffer, (short) (offset+SIZE_SC_IV+2+sizein)); if (sizemac != (short)20) ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC); if (bytesLeft<(short)(SIZE_SC_IV+2+sizein+2+sizemac)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); HmacSha160.computeHmacSha160(sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY, buffer, offset, (short)(SIZE_SC_IV+2+sizein), recvBuffer, (short)0); if ( Util.arrayCompare(recvBuffer, (short)0, buffer, (short)(offset+SIZE_SC_IV+2+sizein+2), (short)20) != (byte)0 ) ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_MAC); // process IV // IV received from client should be odd and strictly greater than locally saved IV // IV should be random (the 12 first bytes), never reused (the last 4 bytes counter) and different for send and receive if ((buffer[(short)(offset+SIZE_SC_IV-(short)1)] & (byte)0x01)==0x00)// should be odd ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV); if ( !Biginteger.lessThan(sc_buffer, OFFSET_SC_IV_COUNTER, buffer, (short)(offset+SIZE_SC_IV_RANDOM), SIZE_SC_IV_COUNTER ) ) //and greater than local IV ISOException.throwIt(SW_SECURE_CHANNEL_WRONG_IV); // update local IV Util.arrayCopy(buffer, (short)(offset+SIZE_SC_IV_RANDOM), sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER); Biginteger.add1_carry(sc_buffer, OFFSET_SC_IV_COUNTER, SIZE_SC_IV_COUNTER); randomData.generateData(sc_buffer, OFFSET_SC_IV_RANDOM, SIZE_SC_IV_RANDOM); sc_aes128_cbc.init(sc_sessionkey, Cipher.MODE_DECRYPT, buffer, offset, SIZE_SC_IV); offset+=SIZE_SC_IV; bytesLeft-=SIZE_SC_IV; //decrypt command offset+=2; bytesLeft-=2; if (bytesLeft<sizein) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); short sizeout=sc_aes128_cbc.doFinal(buffer, offset, sizein, buffer, (short) (0)); return sizeout; }
Example #24
Source File: CardEdge.java From SatochipApplet with GNU Affero General Public License v3.0 | 4 votes |
/** * This function encrypts/decrypt a given message with a 16bytes secret key derived from the 2FA key. * It also returns an id derived from the 2FA key. * This is used to privately exchange tx data between the hw wallet and the 2FA device. * * Algorithms: * id_2FA is hmac-sha1(secret_2FA, "id_2FA"), * key_2FA is hmac-sha1(secret_2FA, "key_2FA"), * message encrypted using AES * * ins: 0x76 * p1: 0x00 for encryption, 0x01 for decryption * p2: Init-Update-Finalize * data(init): IF_ENCRYPT: none ELSE: [IV(16b)] * data(update/finalize): [chunk_size(2b) | chunk_data] * * return(init): IF_ENCRYPT:[IV(16b) | id_2FA(20b)] ELSE: none * return(update/finalize): [chunk_size(2b) | chunk_data] * * */ private short CryptTransaction2FA(APDU apdu, byte[] buffer){ // check that PIN[0] has been entered previously if (!pins[0].isValidated()) ISOException.throwIt(SW_UNAUTHORIZED); // check that 2FA is enabled if (!needs_2FA) ISOException.throwIt(SW_2FA_UNINITIALIZED_KEY); byte ciph_dir = buffer[ISO7816.OFFSET_P1]; byte ciph_op = buffer[ISO7816.OFFSET_P2]; short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]); short dataOffset = ISO7816.OFFSET_CDATA; short IVlength=(short)16; switch(ciph_op){ case OP_INIT: if (ciph_dir!=Cipher.MODE_ENCRYPT && ciph_dir!=Cipher.MODE_DECRYPT ) ISOException.throwIt(SW_INVALID_PARAMETER); if (ciph_dir==Cipher.MODE_ENCRYPT){ randomData.generateData(buffer,(short)0, IVlength); aes128_cbc.init(key_2FA, Cipher.MODE_ENCRYPT, buffer, (short)0, IVlength); Util.arrayCopyNonAtomic(data2FA, OFFSET_2FA_ID, buffer, (short)IVlength, (short)20); return (short)(IVlength + 20); } if (ciph_dir==Cipher.MODE_DECRYPT){ aes128_cbc.init(key_2FA, Cipher.MODE_DECRYPT, buffer, dataOffset, IVlength); return (short)0; } break; case OP_PROCESS: case OP_FINALIZE: if (bytesLeft < 2) ISOException.throwIt(SW_INVALID_PARAMETER); short size = Util.getShort(buffer, dataOffset); if (bytesLeft < (short) (2 + size)) ISOException.throwIt(SW_INVALID_PARAMETER); short sizeout=0; if (ciph_op == OP_PROCESS){ sizeout=aes128_cbc.update(buffer, (short) (dataOffset + 2), size, buffer, (short) 2); } else {// ciph_op == OP_FINALIZE sizeout=aes128_cbc.doFinal(buffer, (short) (dataOffset + 2), size, buffer, (short) 2); } // Also copies the Short size information Util.setShort(buffer,(short)0, sizeout); return (short) (sizeout + 2); default: ISOException.throwIt(SW_INCORRECT_P2); } return (short)0; }
Example #25
Source File: GidsBaseTestClass.java From GidsApplet with GNU General Public License v3.0 | 4 votes |
protected void authenticateMutual(byte[] key, boolean successexpected) { byte[] myChallenge= new byte [16], globalchallenge = new byte[40], challengeresponse = new byte[40]; byte[] cardChallenge; Cipher cipherDES = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); DESKey deskey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); deskey.setKey(key, (short) 0); new Random().nextBytes(myChallenge); // select admin key execute("00 22 81 A4 03 83 01 80"); // get a challenge ResponseAPDU response = execute("00 87 00 00 14 7C 12 81 10" + DatatypeConverter.printHexBinary(myChallenge) + "00"); if (!Arrays.equals(Arrays.copyOfRange(response.getBytes(), 0, 4), new byte[] {0x7C,0x12,(byte) 0x81,0x10})) { fail("not a challenge:" + DatatypeConverter.printHexBinary(response.getBytes())); } // compute the response cardChallenge = Arrays.copyOfRange(response.getBytes(), 4, 20); //solve challenge //R2 System.arraycopy(cardChallenge, 0, globalchallenge, 0, 16); //R1 System.arraycopy(myChallenge, 0, globalchallenge, 16, 16); // keep Z1 random globalchallenge[(short)39] = (byte) 0x80; cipherDES.init(deskey, Cipher.MODE_ENCRYPT); cipherDES.doFinal(globalchallenge, (short) 0, (short)40, challengeresponse, (short) 0); // send the response String command = "00 87 00 00 2C 7C 2A 82 28" + DatatypeConverter.printHexBinary(challengeresponse); ResponseAPDU responseAPDU = execute(command, true); if (!successexpected) { if(responseAPDU.getSW() != 0x6982) { fail("expected: " + Integer.toHexString(0x6982) + " but was: " + Integer.toHexString(response.getSW())); } return; } if(responseAPDU.getSW() != 0x9000) { fail("expected: " + Integer.toHexString(0x9000) + " but was: " + Integer.toHexString(response.getSW())); } byte[] cardresponse = responseAPDU.getBytes(); if (!Arrays.equals(Arrays.copyOfRange(cardresponse, 0, 4), new byte[] {0x7C,0x2A,(byte)0x82,0x28})) { fail("header verification failed"); } byte[] decryptedCardResponse = new byte[40]; cipherDES.init(deskey, Cipher.MODE_DECRYPT); cipherDES.doFinal(cardresponse, (short) 4, (short)40, decryptedCardResponse, (short) 0); if (!Arrays.equals(Arrays.copyOfRange(decryptedCardResponse, 0, 16), myChallenge)) { fail("R1 verification failed"); } if (!Arrays.equals(Arrays.copyOfRange(decryptedCardResponse, 16, 32), cardChallenge)) { fail("R2 verification failed"); } if (decryptedCardResponse[(short)39] != (byte) 0x80) { fail("padding failed"); } }
Example #26
Source File: GidsApplet.java From GidsApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Compute a digital signature of the data from the apdu * using the private key referenced by an earlier * MANAGE SECURITY ENVIRONMENT apdu. * * \attention The apdu should contain a hash, not raw data for RSA keys. * PKCS1 padding will be applied if neccessary. * * \param apdu The PERFORM SECURITY OPERATION apdu with P1=9E and P2=9A. * * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH * and SW_UNKNOWN. */ private void computeDigitalSignature(APDU apdu) throws ISOException { byte[] buf = apdu.getBuffer(); short lc, le; short sigLen = 0; PrivateKey rsaKey = null; byte[] ram_buf = transmitManager.GetRamBuffer(); CRTKeyFile key = (CRTKeyFile) currentKey[0]; switch((byte) (currentAlgorithmRef[0] & 0xF0)) { case (byte) 0x10: // padding made off card -> raw encryption to be performed lc = transmitManager.doChainingOrExtAPDU(apdu); // RSA signature operation. rsaKey = key.GetKey().getPrivate(); rsaRawCipher.init(rsaKey, Cipher.MODE_ENCRYPT); sigLen = rsaRawCipher.doFinal(ram_buf, (short) 0, lc, ram_buf, (short)0); transmitManager.sendDataFromRamBuffer(apdu, (short)0, sigLen); break; case (byte) 0x50: // rsa padding made by the card, only the hash is provided // Receive. // Bytes received must be Lc. lc = apdu.setIncomingAndReceive(); // RSA signature operation. rsaKey = key.GetKey().getPrivate(); if(lc > (short) 247) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } rsaPkcs1Cipher.init(rsaKey, Cipher.MODE_ENCRYPT); sigLen = rsaPkcs1Cipher.doFinal(buf, ISO7816.OFFSET_CDATA, lc, ram_buf, (short)0); /*if(sigLen != 256) { ISOException.throwIt(ISO7816.SW_UNKNOWN); }*/ transmitManager.sendDataFromRamBuffer(apdu, (short)0, sigLen); break; default: // Wrong/unknown algorithm. ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } }
Example #27
Source File: GidsApplet.java From GidsApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Decipher the data from the apdu using the private key referenced by * an earlier MANAGE SECURITY ENVIRONMENT apdu. * * \param apdu The PERFORM SECURITY OPERATION apdu with P1=80 and P2=86. * * \throw ISOException SW_CONDITIONS_NOT_SATISFIED, SW_WRONG_LENGTH and * SW_WRONG_DATA */ private void decipher(APDU apdu) { byte[] buf = apdu.getBuffer(); short offset_cdata; short lc; short decLen = -1; byte[] ram_buf = transmitManager.GetRamBuffer(); Cipher cipher = null; lc = transmitManager.doChainingOrExtAPDU(apdu); offset_cdata = 0; // Padding indicator should be "No further indication". if(buf[offset_cdata] != (byte) 0x00) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } switch((byte) (currentAlgorithmRef[0] & 0xF0)) { case (byte) 0x80: cipher = rsaOaepCipher; break; case (byte) 0x40: cipher = rsaPkcs1Cipher; break; case (byte) 0x00: cipher = rsaRawCipher; break; default: ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); } // Get the key - it must be an RSA private key, // checks have been done in MANAGE SECURITY ENVIRONMENT. CRTKeyFile key = (CRTKeyFile) currentKey[0]; PrivateKey theKey = key.GetKey().getPrivate(); // Check the length of the cipher. // Note: The first byte of the data field is the padding indicator // and therefor not part of the ciphertext. if(lc != (short)(theKey.getSize() / 8)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } cipher.init(theKey, Cipher.MODE_DECRYPT); try { decLen = cipher.doFinal(ram_buf, (short) 0, lc, buf, (short) 0); } catch(CryptoException e) { ISOException.throwIt(ISO7816.SW_WRONG_DATA); } // We have to send at most 256 bytes. A short APDU can handle that - only one send operation neccessary. apdu.setOutgoingAndSend((short)0, decLen); }
Example #28
Source File: GidsApplet.java From GidsApplet with GNU General Public License v3.0 | 4 votes |
/** * \brief Only this class's install method should create the applet object. */ protected GidsApplet() { // by default the pin manager is in "initialization mode" pinManager = new GidsPINManager(); transmitManager = new TransmitManager(); currentAlgorithmRef = JCSystem.makeTransientByteArray((short)1, JCSystem.CLEAR_ON_DESELECT); currentKey = JCSystem.makeTransientObjectArray((short)1, JCSystem.CLEAR_ON_DESELECT); rsaPkcs1Cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false); try { rsaOaepCipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1_OAEP, false); } catch (CryptoException e) { if(e.getReason() == CryptoException.NO_SUCH_ALGORITHM) { rsaOaepCipher = null; } else { throw e; } } rsaRawCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); byte mechanisms = (byte) 0xC0; fs = new GidsFileSystem(pinManager, transmitManager, (short) 0x3F00, // FCP new byte[] { (byte)0x62, (byte)0x08, (byte)0x82, (byte)0x01, (byte)0x38, // File descriptor byte. (byte)0x8C, (byte)0x03, (byte)0x03, (byte)0x30, (byte)0x30,// security attribute }, // FCI new byte[] { 0x61, 0X12, 0x4F, 0x0B, (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x97, (byte) 0x42, (byte) 0x54, (byte) 0x46, (byte) 0x59, 0x02, 0x01, // AID 0x73, 0x03, 0x40, 0x01, mechanisms, // cryptographic mechanism }, // FMD new byte[] { (byte)0x64, (byte)0x09, (byte)0x5F, (byte)0x2F, (byte) 0x01, (byte) 0x60, // pin usage policy (byte)0x7F, (byte)0x65, 0x02, (byte) 0x80, 0x00 } ); // FCI / FMD / FCP are hard coded register(); }
Example #29
Source File: SecureChannel.java From status-keycard with Apache License 2.0 | 4 votes |
/** * Sends the response to the command. This the given SW is appended to the data automatically. The response data 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 apdu the APDU object * @param len the length of the plaintext */ public void respond(APDU apdu, short len, short sw) { byte[] apduBuffer = apdu.getBuffer(); Util.setShort(apduBuffer, (short) (SC_OUT_OFFSET + len), sw); len += 2; crypto.aesCbcIso9797m2.init(scEncKey, Cipher.MODE_ENCRYPT, secret, (short) 0, SC_BLOCK_SIZE); len = crypto.aesCbcIso9797m2.doFinal(apduBuffer, SC_OUT_OFFSET, len, apduBuffer, (short)(ISO7816.OFFSET_CDATA + SC_BLOCK_SIZE)); apduBuffer[0] = (byte) (len + SC_BLOCK_SIZE); computeAESMAC(len, apduBuffer); Util.arrayCopyNonAtomic(apduBuffer, ISO7816.OFFSET_CDATA, secret, (short) 0, SC_BLOCK_SIZE); len += SC_BLOCK_SIZE; apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len); }
Example #30
Source File: Bignat_Helper.java From JCMathLib with MIT License | 4 votes |
void initialize(short modRSAEngineMaxBits, short multRSAEngineMaxBits) { MODULO_RSA_ENGINE_MAX_LENGTH_BITS = modRSAEngineMaxBits; MULT_RSA_ENGINE_MAX_LENGTH_BITS = multRSAEngineMaxBits; fnc_deep_resize_tmp = rm.helper_BN_array1; fnc_mult_resultArray1 = rm.helper_BN_array1; fnc_mult_resultArray2 = rm.helper_BN_array2; fnc_same_value_array1 = rm.helper_BN_array1; fnc_same_value_hash = rm.helper_BN_array2; fnc_shift_bytes_right_tmp = rm.helper_BN_array1; // BN below are just reassigned allocated helper_BN_? so that same helper_BN_? is not used in parallel (checked by lock() unlock()) fnc_mod_add_tmp = rm.helper_BN_A; fnc_mod_sub_tmpThis = rm.helper_BN_A; fnc_mod_sub_tmp = rm.helper_BN_B; fnc_mod_sub_tmpOther = rm.helper_BN_C; fnc_mult_mod_tmpThis = rm.helper_BN_A; fnc_mult_mod_tmp_mod = rm.helper_BN_B; fnc_mult_mod_tmp_x = rm.helper_BN_C; fnc_exponentiation_tmp = rm.helper_BN_A; fnc_exponentiation_i = rm.helper_BN_B; fnc_mod_minus_2 = rm.helper_BN_B; fnc_negate_tmp = rm.helper_BN_B; fnc_sqrt_S = rm.helper_BN_A; fnc_sqrt_exp = rm.helper_BN_A; fnc_sqrt_p_1 = rm.helper_BN_B; fnc_sqrt_Q = rm.helper_BN_C; fnc_sqrt_tmp = rm.helper_BN_D; fnc_sqrt_z = rm.helper_BN_E; fnc_mod_mult_tmpThis = rm.helper_BN_E; // mod_mult is called from fnc_sqrt => requires helper_BN_E not being locked in fnc_sqrt when mod_mult is called fnc_divide_tmpThis = rm.helper_BN_E; // divide is called from fnc_sqrt => requires helper_BN_E not being locked in fnc_sqrt when divide is called fnc_mod_exp_modBN = rm.helper_BN_F; // mod_exp is called from fnc_sqrt => requires helper_BN_F not being locked in fnc_sqrt when mod_exp is called fnc_int_add_tmpMag = rm.helper_BN_A; fnc_int_multiply_mod = rm.helper_BN_A; fnc_int_multiply_tmpThis = rm.helper_BN_B; fnc_int_divide_tmpThis = rm.helper_BN_A; // Allocate BN constants always in EEPROM (only reading) ONE = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, this); ONE.one(); TWO = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, this); TWO.two(); THREE = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, this); THREE.three(); tmp_array_short = rm.memAlloc.allocateByteArray((short) 2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); // only 2b RAM for faster add(short) fnc_NmodE_cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); fnc_NmodE_pubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, MODULO_RSA_ENGINE_MAX_LENGTH_BITS, false); // Speedup for fast multiplication fnc_mult_keypair = new KeyPair(KeyPair.ALG_RSA_CRT, MULT_RSA_ENGINE_MAX_LENGTH_BITS); fnc_mult_keypair.genKeyPair(); fnc_mult_pubkey_pow2 = (RSAPublicKey) fnc_mult_keypair.getPublic(); //mult_privkey_pow2 = (RSAPrivateCrtKey) mult_keypair.getPrivate(); fnc_mult_pubkey_pow2.setExponent(CONST_TWO, (short) 0, (short) CONST_TWO.length); fnc_mult_cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); hashEngine = rm.hashEngine; FLAG_FAST_MULT_VIA_RSA = false; // set true only if succesfully allocated and tested below try { // Subsequent code may fail on some real (e.g., Infineon CJTOP80K) cards - catch exception fnc_mult_cipher.init(fnc_mult_pubkey_pow2, Cipher.MODE_ENCRYPT); // Try operation - if doesn't work, exception SW_CANTALLOCATE_BIGNAT is emitted Util.arrayFillNonAtomic(fnc_mult_resultArray1, (short) 0, (short) fnc_mult_resultArray1.length, (byte) 6); fnc_mult_cipher.doFinal(fnc_mult_resultArray1, (short) 0, (short) fnc_mult_resultArray1.length, fnc_mult_resultArray1, (short) 0); FLAG_FAST_MULT_VIA_RSA = true; } catch (Exception ignored) { } // discard exception }