javacard.security.Signature Java Examples

The following examples show how to use javacard.security.Signature. 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: SigMsgRecApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Only this class's install method should create the applet object.
 */
protected SigMsgRecApplet(byte[] bArray, short bOffset, byte bLength){       
    byte aidLen = bArray[bOffset];
    if (aidLen== (byte)0){
        //System.out.println("using dfault");
        register();
    } else {
        //System.out.println("using provided");
        register(bArray, (short)(bOffset+1), aidLen);
    }                    
    pubKey = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,KeyBuilder.LENGTH_RSA_512,false);
    privKey = (RSAPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE,KeyBuilder.LENGTH_RSA_512,false);
    privKey.setExponent(RSA_PRIV_KEY_EXP,(short)0,(short)RSA_PRIV_KEY_EXP.length);
    privKey.setModulus(RSA_PUB_PRIV_KEY_MOD,(short)0,(short)RSA_PUB_PRIV_KEY_MOD.length);
    pubKey.setExponent(RSA_PUB_KEY_EXP,(short)0,(short)RSA_PUB_KEY_EXP.length);
    pubKey.setModulus(RSA_PUB_PRIV_KEY_MOD,(short)0,(short)RSA_PUB_PRIV_KEY_MOD.length);
    sigBuff = JCSystem.makeTransientByteArray((short)(SIG_LENGTH+2),JCSystem.CLEAR_ON_DESELECT);
    sig = (SignatureMessageRecovery)Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796_MR,false);
    recState = (byte)0;
}
 
Example #2
Source File: SigMsgRecApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
* For the purposes of this sample, Assumed that all the data to be
* signed fits into one APDU buffer
**/
private void testCryptoSign(APDU apdu){
    byte []buffer = apdu.getBuffer();
    short bytesRead = apdu.setIncomingAndReceive();
    short []m1Data = JCSystem.makeTransientShortArray((short)1,JCSystem.CLEAR_ON_DESELECT);

    sig.init(privKey,Signature.MODE_SIGN);
    sigLen=sig.sign(buffer,ISO7816.OFFSET_CDATA,bytesRead,sigBuff,(short)0,m1Data,(short)0);
    
    //set m1Length into sigBuff array
    sigBuff[sigLen] = (byte)((short)(m1Data[(short)0] & ((short)0xFF00)) >> ((short)8));
    sigBuff[(short)(sigLen+1)] = (byte)(m1Data[(short)0] & ((short)0x00FF));
    
    apdu.setOutgoing();
    apdu.setOutgoingLength((short)(sigLen+2));//The extra 2 bytes for m1Length
    apdu.sendBytesLong(sigBuff,(short)0,(short)(sigLen+2));
}
 
Example #3
Source File: SigMsgRecApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
* in this case, all the message is inside the signature.
* We only expect one APDU with signature
**/
private void testCryptoVerifyFullMsgRecovery(APDU apdu){
    sig.init(pubKey,Signature.MODE_VERIFY);
    boolean verified=false;
    byte []buffer = apdu.getBuffer();
    short dataLength = (short)(buffer[ISO7816.OFFSET_LC] & (short)0xFF);
     //get the signature from APDU
    short bytesRead = apdu.setIncomingAndReceive();
    Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, sigBuff, (short)0,bytesRead);
    short m1Length = sig.beginVerify(sigBuff,(short)0,bytesRead);
    verified = sig.verify(sigBuff,(short)0,(short)0);        
    //In either case m1 is consumed by this applet
    if(!verified){
        ISOException.throwIt(ERROR_VERIFICATION_FAILED);
    }
}
 
Example #4
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * This function returns the authentikey public key (uniquely derived from the Bip32 seed).
 * The function returns the x-coordinate of the authentikey, self-signed.
 * The authentikey full public key can be recovered from the signature.
 * 
 *  ins: 0x73
 *  p1: 0x00 
 *  p2: 0x00 
 *  data: none
 *  return: [coordx_size(2b) | coordx | sig_size(2b) | sig]
 */
private short getBIP32AuthentiKey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	// check whether the seed is initialized
	if (!bip32_seeded)
		ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED);
	
	// compute the partial authentikey public key...
       keyAgreement.init(bip32_authentikey);        
       short coordx_size= (short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
	Util.setShort(buffer, (short)0, coordx_size);
       // self signed public key
       sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(coordx_size+2), sign_size);
       
       // return x-coordinate of public key+signature
       // the client can recover full public-key from the signature or
       // by guessing the compression value () and verifying the signature... 
       // buffer= [coordx_size(2) | coordx | sigsize(2) | sig]
       return (short)(coordx_size+sign_size+4);
}
 
Example #5
Source File: TransitApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Checks the request message signature.
 * 
 * @param buffer
 *            The APDU buffer
 * @return true if the message signature is correct; false otherwise
 */
private boolean checkMAC(byte[] buffer) {
    byte numBytes = buffer[ISO7816.OFFSET_LC];

    if (numBytes <= MAC_LENGTH) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Initialize signature with current session key for verification
    signature.init(sessionKey, Signature.MODE_VERIFY);
    // Verify request message signature
    return signature.verify(buffer, ISO7816.OFFSET_CDATA,
            (short) (numBytes - MAC_LENGTH), buffer,
            (short) (ISO7816.OFFSET_CDATA + numBytes - MAC_LENGTH),
     MAC_LENGTH);
}
 
Example #6
Source File: OpenPGPSecureMessaging.java    From javacard-openpgpcard with GNU General Public License v2.0 6 votes vote down vote up
/**
 * 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 #7
Source File: OpenPGPSecureMessaging.java    From javacard-openpgpcard with GNU General Public License v2.0 6 votes vote down vote up
/**
 * 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 #8
Source File: ECPoint_Helper.java    From JCMathLib with MIT License 5 votes vote down vote up
public ECPoint_Helper(ResourceManager rm) {
    super(rm);
    
    FLAG_FAST_EC_MULT_VIA_KA = false; // set true only if succesfully allocated and tested below
    try {
        //fnc_multiplication_x_keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DHC, false);
        //fnc_SignVerifyECDSA_signEngine = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
        //fnc_multiplication_x_keyAgreement = KeyAgreement.getInstance(Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY, false);
        fnc_multiplication_x_keyAgreement = KeyAgreement.getInstance(KeyAgreement_ALG_EC_SVDP_DH_PLAIN, false);
        fnc_SignVerifyECDSA_signEngine = Signature.getInstance(Signature_ALG_ECDSA_SHA_256, false);
        FLAG_FAST_EC_MULT_VIA_KA = true;
    } catch (Exception ignored) {
    } // Discard any exception        
}
 
Example #9
Source File: Bip32.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
public static void deriveSeed(byte seedLength) {
	if (Crypto.signatureHmac != null) {
		Crypto.keyHmac2.setKey(BITCOIN_SEED, (short)0, (short)BITCOIN_SEED.length);
		if ((LedgerWalletApplet.proprietaryAPI != null) && (LedgerWalletApplet.proprietaryAPI.hasHmacSHA512())) {
			LedgerWalletApplet.proprietaryAPI.hmacSHA512(Crypto.keyHmac2, LedgerWalletApplet.scratch256, (short)0, seedLength, LedgerWalletApplet.masterDerived, (short)0);
		}
		else {
			Crypto.signatureHmac.init(Crypto.keyHmac2, Signature.MODE_SIGN);
			Crypto.signatureHmac.sign(LedgerWalletApplet.scratch256, (short)0, seedLength, LedgerWalletApplet.masterDerived, (short)0);
		}
	}
	else {
		HmacSha512.hmac(BITCOIN_SEED, (short)0, (short)BITCOIN_SEED.length, LedgerWalletApplet.scratch256, (short)0, seedLength, LedgerWalletApplet.masterDerived, (short)0, LedgerWalletApplet.scratch256, (short)64);
	}
}
 
Example #10
Source File: LedgerWalletApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
private static void handleAirgapKeyAgreement(APDU apdu) throws ISOException {
    short offset = (short)0;
    byte[] buffer = apdu.getBuffer();
    apdu.setIncomingAndReceive();
    checkAirgapPersonalizationAvailable();
    if (buffer[ISO7816.OFFSET_P1] == P1_INITIATE_PAIRING) {
        if (buffer[ISO7816.OFFSET_LC] != (byte)65) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        pairingDone = false;
        Crypto.keyPair.genKeyPair();
        Crypto.keyAgreement.init((ECPrivateKey)Crypto.keyPair.getPrivate());
        Crypto.keyAgreement.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short)65, scratch256, (short)0);
        pairingKey.setKey(scratch256, (short)0);
        ((ECPublicKey)Crypto.keyPair.getPublic()).getW(buffer, offset);
        offset += (short)65;
        Crypto.signature.init(attestationPrivate, Signature.MODE_SIGN);
        Crypto.signature.sign(buffer, (short)0, (short)65, buffer, offset);
        offset += (short)(buffer[(short)(offset + 1)] + 2);
        apdu.setOutgoingAndSend((short)0, offset);
    }
    else
    if (buffer[ISO7816.OFFSET_P1] == P1_CONFIRM_PAIRING) {
        if (buffer[ISO7816.OFFSET_LC] != (byte)32) {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        Crypto.initCipherAES(pairingKey, false);
        Crypto.blobEncryptDecryptAES.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)32, scratch256, (short)0);
        pairingKey.setKey(scratch256, (short)0);
        pairingDone = true;
    }
    else {
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
}
 
Example #11
Source File: Crypto.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
public static void signTransientPrivate(byte[] keyBuffer, short keyOffset, byte[] dataBuffer, short dataOffset, byte[] targetBuffer, short targetOffset) {
	initTransientPrivate(keyBuffer, keyOffset);
    Util.arrayFillNonAtomic(keyBuffer, keyOffset, (short)32, (byte)0x00);
    // recheck with the target platform, initializing once instead might be possible and save a few flash write
    // (this part is unspecified in the Java Card API)
    signature.init(transientPrivate, Signature.MODE_SIGN);
    signature.sign(dataBuffer, dataOffset, (short)32, targetBuffer, targetOffset);
    if (transientPrivateTransient) {
        transientPrivate.clearKey();
    }
}
 
Example #12
Source File: OpenPGPSecureMessaging.java    From javacard-openpgpcard with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Set the MAC 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 setSessionKeyMAC(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 {     	
		keyMAC.setKey(buffer, offset);
    
		signer.init(keyMAC, Signature.MODE_SIGN);
		verifier.init(keyMAC, Signature.MODE_VERIFY);
	}
}
 
Example #13
Source File: Crypto.java    From ledger-javacard with GNU Affero General Public License v3.0 5 votes vote down vote up
public static boolean verifyPublic(byte[] keyBuffer, short keyOffset, byte[] dataBuffer, short dataOffset, byte[] signatureBuffer, short signatureOffset) {
	publicKey.setW(keyBuffer, keyOffset, (short)65);
	signature.init(publicKey, Signature.MODE_VERIFY);
	try {
		return signature.verify(dataBuffer, dataOffset, (short)32, signatureBuffer, signatureOffset, (short)(signatureBuffer[(short)(signatureOffset + 1)] + 2));
	}
	catch(Exception e) {
		return false;
	}
}
 
Example #14
Source File: SigMsgRecApplet.java    From JCMathLib with MIT License 5 votes vote down vote up
/**
* This method is called when there is partial message recovery. The recoverable
* message inside the signature is consumed by this applet. In this case, the
* first APDU contains the signature and returns true if recovery successful
* the second APDU contains the remainder of the message and the return value
* represents signature verification
**/
private void testCryptoVerifyPartMsgRecovery(APDU apdu){
    byte []buffer = apdu.getBuffer();
    short dataLength = (short)(buffer[ISO7816.OFFSET_LC] & (short)0xFF);
    //get the signature from APDU
    short bytesRead = apdu.setIncomingAndReceive();
    Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, sigBuff, (short)0,bytesRead);
    if(recState == 0){
        //recover the recoverable message from signature
        sig.init(pubKey,Signature.MODE_VERIFY);
        short m1Length = sig.beginVerify(sigBuff,(short)0,bytesRead);
        //consume the recoverable message. Theen discard it
        sigBuff[0] = (byte)((short)(m1Length & ((short)0xFF00)) >> ((short)8));
        sigBuff[1] = (byte)(m1Length & ((short)0x00FF));
        //return back the length of recoverable message
        apdu.setOutgoing();
        apdu.setOutgoingLength((short)2);
        apdu.sendBytesLong(sigBuff,(short)0,(short)2);
        recState = 1;
    }else{
        recState = 0;
        //rest of message sent. verify
        if(!sig.verify(sigBuff,(short)0,bytesRead)){
            ISOException.throwIt(ERROR_VERIFICATION_FAILED);
        }
    }
}
 
Example #15
Source File: ECPoint.java    From JCMathLib with MIT License 4 votes vote down vote up
public static boolean SignVerifyECDSA(ECPrivateKey privateKey, ECPublicKey publicKey, Signature signEngine, byte[] tmpSignArray) {
    signEngine.init(privateKey, Signature.MODE_SIGN);
    short signLen = signEngine.sign(msg, (short) 0, (short) msg.length, tmpSignArray, (short) 0);
    signEngine.init(publicKey, Signature.MODE_VERIFY);
    return signEngine.verify(msg, (short) 0, (short) msg.length, tmpSignArray, (short) 0, signLen);
}
 
Example #16
Source File: Bip32.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static boolean derive(byte[] apduBuffer) {
	boolean isZero = true;
	byte i;
	if ((LedgerWalletApplet.scratch256[OFFSET_DERIVATION_INDEX] & (byte)0x80) == 0) {
		if (LedgerWalletApplet.proprietaryAPI != null) {
			LedgerWalletApplet.proprietaryAPI.getUncompressedPublicPoint(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, OFFSET_TMP);				
		}
		else {				
			if (!Bip32Cache.copyLastPublic(LedgerWalletApplet.scratch256, OFFSET_TMP)) {
				return false;
			}
		}
		AddressUtils.compressPublicKey(LedgerWalletApplet.scratch256, OFFSET_TMP);
	}
	else {
		LedgerWalletApplet.scratch256[OFFSET_TMP] = 0;
		Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 1), (short)32);
	}
	Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, OFFSET_DERIVATION_INDEX, LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 33), (short)4);
	if (Crypto.signatureHmac != null) {
		Crypto.keyHmac.setKey(LedgerWalletApplet.scratch256, (short)32, (short)32);
		if ((LedgerWalletApplet.proprietaryAPI != null) && (LedgerWalletApplet.proprietaryAPI.hasHmacSHA512())) {
			LedgerWalletApplet.proprietaryAPI.hmacSHA512(Crypto.keyHmac, LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP);
		}
		else {
			Crypto.signatureHmac.init(Crypto.keyHmac, Signature.MODE_SIGN);
			Crypto.signatureHmac.sign(LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP);
		}
	}
	else {
		HmacSha512.hmac(LedgerWalletApplet.scratch256, (short)32, (short)32, LedgerWalletApplet.scratch256, OFFSET_TMP, (short)37, LedgerWalletApplet.scratch256, OFFSET_TMP, apduBuffer, OFFSET_BLOCK);
	}
	if (MathMod256.ucmp(LedgerWalletApplet.scratch256, OFFSET_TMP, Secp256k1.SECP256K1_R, (short)0) >= 0) {
		return false;
	}
	MathMod256.addm(LedgerWalletApplet.scratch256, (short)0, LedgerWalletApplet.scratch256, OFFSET_TMP, LedgerWalletApplet.scratch256, (short)0, Secp256k1.SECP256K1_R, (short)0);
	for (i=0; i<(byte)32; i++) {
		if (LedgerWalletApplet.scratch256[i] != 0) {
			isZero = false;
			break;
		}
	}
	if (isZero) {
		return false;
	}
	Util.arrayCopyNonAtomic(LedgerWalletApplet.scratch256, (short)(OFFSET_TMP + 32), LedgerWalletApplet.scratch256, (short)32, (short)32);		
	return true;
}
 
Example #17
Source File: JCardSIMProprietaryAPI.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
@Override
public void signDeterministicECDSASHA256(Key key, byte[] in, short inBuffer, short inLength, byte[] out, short outOffset) {		
       signature.init(key, Signature.MODE_SIGN);
       signature.sign(in, inBuffer, inLength, out, outOffset);				
}
 
Example #18
Source File: IsoApplet.java    From IsoApplet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * \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 #19
Source File: U2FApplet.java    From ledger-u2f-javacard with Apache License 2.0 4 votes vote down vote up
/**
 * Handle U2F_AUTHENTICATE.
 *
 * @param apdu
 * @throws ISOException
 */
private void handleSign(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short len = apdu.setIncomingAndReceive();
    short dataOffset = apdu.getOffsetCdata();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    boolean sign = false;
    short keyHandleLength;
    boolean extendedLength = (dataOffset != ISO7816.OFFSET_CDATA);
    short outOffset = SCRATCH_PAD;
    if (len < 65) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    switch (p1) {
        case P1_SIGN_OPERATION:
            sign = true;
            break;
        case P1_SIGN_CHECK_ONLY:
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    // Check if the counter overflowed
    if (counterOverflowed) {
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Verify key handle
    if (localPrivateTransient) {
        Secp256r1.setCommonCurveParameters(localPrivateKey);
    }
    keyHandleLength = (short) (buffer[(short) (dataOffset + 64)] & 0xff);
    if (!fidoImpl.unwrap(buffer, (short) (dataOffset + 65), keyHandleLength, buffer, (short) (dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (sign ? localPrivateKey : null))) {
        ISOException.throwIt(FIDO_SW_INVALID_KEY_HANDLE);
    }
    // If not signing, return with the "correct" exception
    if (!sign) {
        ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
    }
    // If signing, only proceed if user presence can be validated
    if ((flags & INSTALL_FLAG_DISABLE_USER_PRESENCE) == 0) {
        if (scratchPersistent[0] != 0) {
            ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
        }
    }
    scratchPersistent[0] = (byte) 1;
    // Increase the counter
    boolean carry = false;
    JCSystem.beginTransaction();
    for (byte i = 0; i < 4; i++) {
        short addValue = (i == 0 ? (short) 1 : (short) 0);
        short val = (short) ((short) (counter[(short) (4 - 1 - i)] & 0xff) + addValue);
        if (carry) {
            val++;
        }
        carry = (val > 255);
        counter[(short) (4 - 1 - i)] = (byte) val;
    }
    JCSystem.commitTransaction();
    if (carry) {
        // Game over
        counterOverflowed = true;
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Prepare reply
    scratch[outOffset++] = FLAG_USER_PRESENCE_VERIFIED;
    outOffset = Util.arrayCopyNonAtomic(counter, (short) 0, scratch, outOffset, (short) 4);
    localSignature.init(localPrivateKey, Signature.MODE_SIGN);
    localSignature.update(buffer, (short) (dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (short) 32);
    localSignature.update(scratch, SCRATCH_PAD, (short) 5);
    outOffset += localSignature.sign(buffer, (short) (dataOffset + APDU_CHALLENGE_OFFSET), (short) 32, scratch, outOffset);
    if (extendedLength) {
        // If using extended length, the message can be completed and sent immediately
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
        Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short) 0, outOffset);
        apdu.setOutgoingAndSend((short) 0, (short) (outOffset - SCRATCH_PAD));
    } else {
        // Otherwise send the first chunk
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_NOT_EXTENDED;
        Util.setShort(scratch, SCRATCH_CURRENT_OFFSET, (short) 0);
        Util.setShort(scratch, SCRATCH_SIGNATURE_LENGTH, (short) 0);
        Util.setShort(scratch, SCRATCH_NONCERT_LENGTH, (short) (outOffset - SCRATCH_PAD));
        Util.setShort(scratch, SCRATCH_FULL_LENGTH, (short) (outOffset - SCRATCH_PAD));
        scratch[SCRATCH_INCLUDE_CERT] = (byte) 0;
        handleGetData(apdu);
    }
}
 
Example #20
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
	 * This function allows to initiate a Secure Channel
	 *  
	 *  ins: 0x81
	 *  p1: 0x00
	 *  p2: 0x00
	 *  data: [client-pubkey(65b)]
	 *  return: [coordx_size(2b) | authentikey-coordx | sig_size(2b) | self-sig | sig2_size(optional) | authentikey-sig(optional)]
	 */
	private short InitiateSecureChannel(APDU apdu, byte[] buffer){
		
		// get client pubkey
		short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
		if (bytesLeft < (short)65)
			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
		if (buffer[ISO7816.OFFSET_CDATA] != (byte)0x04)
			ISOException.throwIt(SW_INVALID_PARAMETER);
			
		// generate a new ephemeral key
		sc_ephemeralkey.clearKey();
		Secp256k1.setCommonCurveParameters(sc_ephemeralkey);// keep public params!
		randomData.generateData(recvBuffer, (short)0, BIP32_KEY_SIZE);
		sc_ephemeralkey.setS(recvBuffer, (short)0, BIP32_KEY_SIZE); //random value first
		
		// compute the shared secret...
        keyAgreement.init(sc_ephemeralkey);        
        short coordx_size= (short)32;
    	keyAgreement.generateSecret(buffer, ISO7816.OFFSET_CDATA, (short) 65, recvBuffer, (short)0); //pubkey in uncompressed form
    	// derive sc_sessionkey & sc_mackey
    	HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)6, (short)6, recvBuffer, (short)33);
        Util.arrayCopyNonAtomic(recvBuffer, (short)33, sc_buffer, OFFSET_SC_MACKEY, SIZE_SC_MACKEY);
        HmacSha160.computeHmacSha160(recvBuffer, (short)1, (short)32, CST_SC, (short)0, (short)6, recvBuffer, (short)33);
    	sc_sessionkey.setKey(recvBuffer,(short)33); // AES-128: 16-bytes key!!       
//    	//alternatively: derive session_key (sha256 of coordx)
//    	sha256.reset();
//    	sha256.doFinal(recvBuffer, (short)1, (short)32, recvBuffer, (short) 0);
//    	sc_sessionkey.setKey(recvBuffer,(short)0); // AES-128: 16-bytes key!!
//    	//derive mac_key
//    	sha256.reset();
//    	sha256.doFinal(recvBuffer, (short)0, (short)32, sc_mackey, (short) 0);
    	
    	//reset IV counter
    	Util.arrayFillNonAtomic(sc_buffer, OFFSET_SC_IV, SIZE_SC_IV, (byte) 0);
		
		// self signed ephemeral pubkey
		keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
		Util.setShort(buffer, (short)0, coordx_size);
		sigECDSA.init(sc_ephemeralkey, Signature.MODE_SIGN);
        short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
        Util.setShort(buffer, (short)(coordx_size+2), sign_size);
        
		// hash signed by authentikey if seed is initialized
        short offset= (short)(2+coordx_size+2+sign_size);
        if (bip32_seeded){
            sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN);
            short sign2_size= sigECDSA.sign(buffer, (short)0, offset, buffer, (short)(offset+2));
            Util.setShort(buffer, offset, sign2_size);
            offset+=(short)(2+sign2_size); 
        }else{
        	Util.setShort(buffer, offset, (short)0);
        	offset+=(short)2;
        }
		
        initialized_secure_channel= true;
        
        // return x-coordinate of public key+signature
        // the client can recover full public-key from the signature or
        // by guessing the compression value () and verifying the signature... 
        // buffer= [coordx_size(2) | coordx | sigsize(2) | sig | sig2_size(optional) | sig2(optional)]
        return offset;
	}
 
Example #21
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
   * This function signs a given transaction hash with a std or the last extended key
   * If 2FA is enabled, a HMAC must be provided as an additional security layer. 
* 
   * ins: 0x7A
* p1: key number or 0xFF for the last derived Bip32 extended key  
* p2: 0x00
* data: [hash(32b) | option: 2FA-flag(2b)|hmac(20b)]
* 
* return: [sig ]
* 
   */
  private short SignTransactionHash(APDU apdu, byte[] buffer){
  	
  	// check that PIN[0] has been entered previously
if (!pins[0].isValidated())
	ISOException.throwIt(SW_UNAUTHORIZED);

  	byte key_nb = buffer[ISO7816.OFFSET_P1];
if ( (key_nb!=(byte)0xFF) && ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) )
	ISOException.throwIt(SW_INCORRECT_P1);

  	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
if (bytesLeft<MessageDigest.LENGTH_SHA_256)
	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  	
  	// check whether the seed is initialized
if (key_nb==(byte)0xFF && !bip32_seeded)
	ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED);
  	
// check 2FA if required
if(needs_2FA){
	// check data length
	if (bytesLeft<MessageDigest.LENGTH_SHA_256+MessageDigest.LENGTH_SHA+(short)2)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	// check flag for 2fa_hmac_chalresp
	short hmac_flags= Util.getShort(buffer, (short)(ISO7816.OFFSET_CDATA+32));
	if (hmac_flags!=HMAC_CHALRESP_2FA)
		ISOException.throwIt(SW_INCORRECT_ALG);
	// hmac of 64-bytes msg: ( 32bytes tx_hash | 32bytes 0xCC-padding)
	Util.arrayCopyNonAtomic(buffer, (short)ISO7816.OFFSET_CDATA, recvBuffer, (short)0, (short)32);
	Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0xCC);
	HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
	if (Util.arrayCompare(buffer, (short)(ISO7816.OFFSET_CDATA+32+2), recvBuffer, (short)64, (short)20)!=0)
		ISOException.throwIt(SW_SIGNATURE_INVALID);
}

// hash+sign singlehash
  	if (key_nb==(byte)0xFF)
  		sigECDSA.init(bip32_extendedkey, Signature.MODE_SIGN);
  	else{
  		Key key= eckeys[key_nb];
  		// check type and size
  		if ((key == null) || !key.isInitialized())
  			ISOException.throwIt(SW_INCORRECT_P1);
  		if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE)
  			ISOException.throwIt(SW_INCORRECT_ALG);		
  		if (key.getSize()!= LENGTH_EC_FP_256)
  			ISOException.throwIt(SW_INCORRECT_ALG);
  		sigECDSA.init(key, Signature.MODE_SIGN);
  	}
      short sign_size= sigECDSA.signPreComputedHash(buffer, ISO7816.OFFSET_CDATA, MessageDigest.LENGTH_SHA_256, buffer, (short)0);
      return sign_size;
  }
 
Example #22
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
   * This function signs the current hash transaction with a std or the last extended key
   * The hash provided in the APDU is compared to the version stored inside the chip.
* Depending of the total amount in the transaction and the predefined limit, 
* a HMAC must be provided as an additional security layer. 
* 
   * ins: 0x6F
* p1: key number or 0xFF for the last derived Bip32 extended key  
* p2: 0x00
* data: [hash(32b) | option: 2FA-flag(2b)|hmac(20b)]
* 
* return: [sig ]
*
   */
  private short SignTransaction(APDU apdu, byte[] buffer){
// check that PIN[0] has been entered previously
if (!pins[0].isValidated())
	ISOException.throwIt(SW_UNAUTHORIZED);

  	byte key_nb = buffer[ISO7816.OFFSET_P1];
if ( (key_nb!=(byte)0xFF) && ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS)) )
	ISOException.throwIt(SW_INCORRECT_P1);

  	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
if (bytesLeft<MessageDigest.LENGTH_SHA_256)
	ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  	
  	// check whether the seed is initialized
if (key_nb==(byte)0xFF && !bip32_seeded)
	ISOException.throwIt(SW_BIP32_UNINITIALIZED_SEED);

// check doublehash value in buffer with cached singlehash value
sha256.reset();
sha256.doFinal(transactionData, OFFSET_TRANSACTION_HASH, MessageDigest.LENGTH_SHA_256, recvBuffer, (short)0);
if ((byte)0 != Util.arrayCompare(buffer, ISO7816.OFFSET_CDATA, recvBuffer, (short)0, MessageDigest.LENGTH_SHA_256))
	ISOException.throwIt(SW_INCORRECT_TXHASH);

// check challenge-response answer if necessary
if(needs_2FA){
	if(	Biginteger.lessThan(data2FA, OFFSET_2FA_LIMIT, transactionData, OFFSET_TRANSACTION_AMOUNT, (short)8)){
		if (bytesLeft<MessageDigest.LENGTH_SHA_256+MessageDigest.LENGTH_SHA+(short)2)
			ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
		// check flag for 2fa_hmac_chalresp
		short hmac_flags= Util.getShort(buffer, (short)(ISO7816.OFFSET_CDATA+32));
		if (hmac_flags!=HMAC_CHALRESP_2FA)
			ISOException.throwIt(SW_INCORRECT_ALG);
		// hmac of 64-bytes msg: (doublesha256(raw_tx) | 32bytes zero-padding)
		Util.arrayFillNonAtomic(recvBuffer, (short)32, (short)32, (byte)0x00);
		HmacSha160.computeHmacSha160(data2FA, OFFSET_2FA_HMACKEY, (short)20, recvBuffer, (short)0, (short)64, recvBuffer, (short)64);
		if (Util.arrayCompare(buffer, (short)(ISO7816.OFFSET_CDATA+32+2), recvBuffer, (short)64, (short)20)!=0)
			ISOException.throwIt(SW_SIGNATURE_INVALID);
		// reset total amount
		Util.arrayFillNonAtomic(transactionData, OFFSET_TRANSACTION_TOTAL, (short)8, (byte)0x00);
	}
	else{					
		//update total amount
		Util.arrayCopyNonAtomic(transactionData, OFFSET_TRANSACTION_AMOUNT, transactionData, OFFSET_TRANSACTION_TOTAL, (short)8);
	}
}

// hash+sign singlehash
  	if (key_nb==(byte)0xFF)
  		sigECDSA.init(bip32_extendedkey, Signature.MODE_SIGN);
  	else{
  		Key key= eckeys[key_nb];
  		// check type and size
  		if ((key == null) || !key.isInitialized())
  			ISOException.throwIt(SW_INCORRECT_P1);
  		if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE)
  			ISOException.throwIt(SW_INCORRECT_ALG);		
  		if (key.getSize()!= LENGTH_EC_FP_256)
  			ISOException.throwIt(SW_INCORRECT_ALG);
  		sigECDSA.init(key, Signature.MODE_SIGN);
  	}
      short sign_size= sigECDSA.sign(transactionData, OFFSET_TRANSACTION_HASH, (short)32, buffer, (short)0);
      return sign_size;
  }
 
Example #23
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * This function imports a Bip32 seed to the applet and derives the master key and chain code.
 * It also derives a second ECC that uniquely authenticates the HDwallet: the authentikey.
 * Lastly, it derives a 32-bit AES key that is used to encrypt/decrypt Bip32 object stored in secure memory 
 * If the seed already exists, it is reset if the logged identities allow it.
 * 
 * The function returns the x-coordinate of the authentikey, self-signed.
 * The authentikey full public key can be recovered from the signature.
 *  
 *  ins: 0x6C
 *  p1: seed_size(1b) 
 *  p2: 0x00 
 *  data: [seed_data (seed_size)]
 *  return: [coordx_size(2b) | coordx | sig_size(2b) | sig]
 */
private short importBIP32Seed(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	// if already seeded, must call resetBIP32Seed first!
	if (bip32_seeded)
		ISOException.throwIt(SW_BIP32_INITIALIZED_SEED);
	
	short bytesLeft = Util.makeShort((byte) 0x00, buffer[ISO7816.OFFSET_LC]);
	
	// get seed bytesize (max 64 bytes)
	byte bip32_seedsize = buffer[ISO7816.OFFSET_P1]; 
	if (bip32_seedsize <0 || bip32_seedsize>64)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	
	short offset= (short)ISO7816.OFFSET_CDATA;
	
	// derive master key!
	HmacSha512.computeHmacSha512(BITCOIN_SEED, (short)0, (short)BITCOIN_SEED.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)0);
	bip32_masterkey.setKey(recvBuffer, (short)0); // data must be exactly 32 bytes long
	bip32_masterchaincode.setKey(recvBuffer, (short)32); // data must be exactly 32 bytes long
	
	// derive 2 more keys from seed:
	// - AES encryption key for secure storage of extended keys in object
	// - ECC key for authentication of sensitive data returned by the applet (hash, pubkeys)
	HmacSha512.computeHmacSha512(BITCOIN_SEED2, (short)0, (short)BITCOIN_SEED2.length, buffer, offset, (short)bip32_seedsize, recvBuffer, (short)64);
	bip32_authentikey.setS(recvBuffer, (short)64, BIP32_KEY_SIZE);
	bip32_encryptkey.setKey(recvBuffer, (short)96); // AES-128: 16-bytes key!!
	
	// bip32 is now seeded
	bip32_seeded= true;
	
	// clear recvBuffer
	Util.arrayFillNonAtomic(recvBuffer, (short)0, (short)128, (byte)0);
	
	// compute the partial authentikey public key...
       keyAgreement.init(bip32_authentikey);
       short coordx_size= (short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, authentikey_pubkey, (short)0); //pubkey in uncompressed form
    Util.setShort(buffer, (short)0, coordx_size);
       Util.arrayCopyNonAtomic(authentikey_pubkey, (short)1, buffer, (short)2, coordx_size);
       // self signed public key
       sigECDSA.init(bip32_authentikey, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(2+coordx_size), sign_size);
       
       // return x-coordinate of public key+signature
       // the client can recover full public-key from the signature or
       // by guessing the compression value () and verifying the signature... 
       // buffer= [coordx_size(2) | coordx | sigsize(2) | sig]
       return (short)(2+coordx_size+2+sign_size);
}
 
Example #24
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 4 votes vote down vote up
/** 
 * This function returns the public key associated with a particular private key stored 
 * in the applet. The exact key blob contents depend on the key�s algorithm and type. 
 * 
 * ins: 0x35
 * p1: private key number (0x00-0x0F)
 * p2: 0x00
 * data: none 
 * return(SECP256K1): [coordx_size(2b) | pubkey_coordx | sig_size(2b) | sig]
 */
private short getPublicKeyFromPrivate(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	
	byte key_nb = buffer[ISO7816.OFFSET_P1];
	if ((key_nb < 0) || (key_nb >= MAX_NUM_KEYS))
		ISOException.throwIt(SW_INCORRECT_P1);
	
	Key key = eckeys[key_nb];
	// check type and size
	if ((key == null) || !key.isInitialized())
		ISOException.throwIt(SW_INCORRECT_P1);
	if (key.getType() != KeyBuilder.TYPE_EC_FP_PRIVATE)
		ISOException.throwIt(SW_INCORRECT_ALG);		
	if (key.getSize()!= LENGTH_EC_FP_256)
		ISOException.throwIt(SW_INCORRECT_ALG);
	// check the curve param
	if(!Secp256k1.checkCurveParameters((ECPrivateKey)key, recvBuffer, (short)0))
		ISOException.throwIt(SW_INCORRECT_ALG);
			
	// compute the corresponding partial public key...
       keyAgreement.init((ECPrivateKey)key);
       short coordx_size=(short)32;
   	keyAgreement.generateSecret(Secp256k1.SECP256K1, Secp256k1.OFFSET_SECP256K1_G, (short) 65, buffer, (short)1); //pubkey in uncompressed form
    Util.setShort(buffer, (short)0, coordx_size);
       
       // sign fixed message
       sigECDSA.init(key, Signature.MODE_SIGN);
       short sign_size= sigECDSA.sign(buffer, (short)0, (short)(coordx_size+2), buffer, (short)(coordx_size+4));
       Util.setShort(buffer, (short)(coordx_size+2), sign_size);
       
       // return x-coordinate of public key+signature
       // the client can recover full public-key from the signature or
       // by guessing the compression value () and verifying the signature... 
       return (short)(2+coordx_size+2+sign_size);
}
 
Example #25
Source File: AppletUtil.java    From ECTester with MIT License 4 votes vote down vote up
public static short signCheck(Signature signature) {
    return nullCheck(signature, AppletBase.SW_SIGNATURE_NULL);
}
 
Example #26
Source File: U2FApplet.java    From CCU2F with Apache License 2.0 4 votes vote down vote up
private void handleSign(APDU apdu) throws ISOException {
    byte[] buffer = apdu.getBuffer();
    short len = apdu.setIncomingAndReceive();
    short dataOffset = apdu.getOffsetCdata();
    byte p1 = buffer[ISO7816.OFFSET_P1];
    boolean sign = false;
    boolean counterOverflow = true;
    short keyHandleLength;
    boolean extendedLength = (dataOffset != ISO7816.OFFSET_CDATA);
    short outOffset = SCRATCH_PAD;
    if (len < 65) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    switch(p1) {
    case P1_SIGN_OPERATION:
        sign = true;
        break;
    case P1_SIGN_CHECK_ONLY:
        break;
    default:
        ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
    }
    // Check if the counter overflowed
    if (counterOverflowed) {
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Verify key handle
    if (localPrivateTransient) {
        Secp256r1.setCommonCurveParameters(localPrivateKey);
    }
    keyHandleLength = (short)(buffer[(short)(dataOffset + 64)] & 0xff);
    if (!fidoImpl.unwrap(buffer, (short)(dataOffset + 65), keyHandleLength, buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (sign ? localPrivateKey : null))) {
        ISOException.throwIt(FIDO_SW_INVALID_KEY_HANDLE);
    }
    // If not signing, return with the "correct" exception
    if (!sign) {
        ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
    }
    // If signing, only proceed if user presence can be validated
    if ((flags & INSTALL_FLAG_DISABLE_USER_PRESENCE) == 0) {
        if (scratchPersistent[0] != 0) {
            ISOException.throwIt(FIDO_SW_TEST_OF_PRESENCE_REQUIRED);
        }
    }
    scratchPersistent[0] = (byte)1;
    // Increase the counter
    boolean carry = false;
    JCSystem.beginTransaction();
    for (byte i=0; i<4; i++) {
        short addValue = (i == 0 ? (short)1 : (short)0);
        short val = (short)((short)(counter[(short)(4 - 1 - i)] & 0xff) + addValue);
        if (carry) {
            val++;
        }
        carry = (val > 255);
        counter[(short)(4 - 1 - i)] = (byte)val;
    }
    JCSystem.commitTransaction();
    if (carry) {
        // Game over
        counterOverflowed = true;
        ISOException.throwIt(ISO7816.SW_FILE_FULL);
    }
    // Prepare reply
    scratch[outOffset++] = FLAG_USER_PRESENCE_VERIFIED;
    outOffset = Util.arrayCopyNonAtomic(counter, (short)0, scratch, outOffset, (short)4);
    localSignature.init(localPrivateKey, Signature.MODE_SIGN);
    localSignature.update(buffer, (short)(dataOffset + APDU_APPLICATION_PARAMETER_OFFSET), (short)32);
    localSignature.update(scratch, SCRATCH_PAD, (short)5);
    outOffset += localSignature.sign(buffer, (short)(dataOffset + APDU_CHALLENGE_OFFSET), (short)32, scratch, outOffset);
  
    if (extendedLength) {
        // If using extended length, the message can be completed and sent immediately
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_EXTENDED;
        Util.arrayCopyNonAtomic(scratch, SCRATCH_PAD, buffer, (short)0, outOffset);
        apdu.setOutgoingAndSend((short)0, (short)(outOffset - SCRATCH_PAD));
    }
    else {
        // Otherwise send the first chunk
        scratch[SCRATCH_TRANSPORT_STATE] = TRANSPORT_NOT_EXTENDED;
        Util.setShort(scratch, SCRATCH_CURRENT_OFFSET, (short)0);
        Util.setShort(scratch, SCRATCH_SIGNATURE_LENGTH, (short)0);
        Util.setShort(scratch, SCRATCH_NONCERT_LENGTH, (short)(outOffset - SCRATCH_PAD));
        Util.setShort(scratch, SCRATCH_FULL_LENGTH, (short)(outOffset - SCRATCH_PAD));
        scratch[SCRATCH_INCLUDE_CERT] = (byte)0;
        handleGetData(apdu);
    }
}
 
Example #27
Source File: TransitApplet.java    From JCMathLib with MIT License 3 votes vote down vote up
/**
 * Generates the response message MAC: generates the MAC and appends the MAC
 * to the response message.
 * 
 * @param buffer
 *            The APDU buffer
 * @param offset
 *            The offset of the MAC in the buffer
 * @return The resulting length of the response message
 */
private short generateMAC(byte[] buffer, short offset) {
    // Initialize signature with current session key for signing
    signature.init(sessionKey, Signature.MODE_SIGN);
    // Sign response message and append the MAC to the response message
    short sigLength = signature.sign(buffer, (short) 0, offset, buffer,
            offset);
    return (short) (offset + sigLength);
}