Java Code Examples for javacard.framework.Util#setShort()

The following examples show how to use javacard.framework.Util#setShort() . 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: 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 2
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * This function returns a 2 byte bit mask of the available PINs that are currently in
 * use. Each set bit corresponds to an active PIN.
 * 
 *  ins: 0x48
 *  p1: 0x00
 *  p2: 0x00
 *  data: none
 *  return: [RFU(1b) | PIN_mask(1b)]
 */
private short ListPINs(APDU apdu, byte[] buffer) {
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	// Checking P1 & P2
	if (buffer[ISO7816.OFFSET_P1] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P1);
	if (buffer[ISO7816.OFFSET_P2] != (byte) 0x00)
		ISOException.throwIt(SW_INCORRECT_P2);
	byte expectedBytes = (byte) (buffer[ISO7816.OFFSET_LC]);
	if (expectedBytes != (short) 2)
		ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
	// Build the PIN bit mask
	short mask = (short) 0x00;
	short b;
	for (b = (short) 0; b < MAX_NUM_PINS; b++)
		if (pins[b] != null)
			mask |= (short) (((short) 0x01) << b);
	// Fill the buffer
	Util.setShort(buffer, (short) 0, mask);
	// Send response
	return (short)2;
}
 
Example 3
Source File: PasswordManagerApplet.java    From sim-password-manager with Apache License 2.0 6 votes vote down vote up
private void prng(byte[] buff, short offset, short len) {
    if (len > AES_BLOCK_LEN) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    Util.arrayCopyNonAtomic(prngNonce, OFFSET_ZERO, cipherBuff,
            OFFSET_ZERO, (short) prngNonce.length);
    Util.setShort(cipherBuff, (short) (AES_BLOCK_LEN - 2), prngCounter);

    try {
        aesCipher.RoundKeysSchedule(prngKey, (short) 0, roundKeysBuff);

        // encrypts in place
        boolean success = aesCipher.AESEncryptBlock(cipherBuff,
                OFFSET_ZERO, roundKeysBuff);
        if (!success) {
            ISOException.throwIt(ISO7816.SW_DATA_INVALID);
        }
        prngCounter++;

        Util.arrayCopyNonAtomic(cipherBuff, OFFSET_ZERO, buff, offset, len);
    } finally {
        clearCipherState();
    }
}
 
Example 4
Source File: ECKeyGenerator.java    From ECTester with MIT License 6 votes vote down vote up
/**
 * Exports selected parameters from a given keyPairs key.
 * Raw parameter data is always prepended by its length as a
 * short value. The order of parameters is the usual one from
 * EC_Consts: field,a,b,g,r,k,w,s.
 *
 * @param keypair keyPair to export from
 * @param key     key to export from (KEY_PUBLIC || KEY_PRIVATE)
 * @param params  params to export (EC_Consts.PARAMETER_* | ...)
 * @param buffer  buffer to export to
 * @param offset  offset to start writing in buffer
 * @return length of data written
 */
public short exportParameters(KeyPair keypair, byte key, short params, byte[] buffer, short offset) {
    sw = ISO7816.SW_NO_ERROR;
    if (params == EC_Consts.PARAMETERS_NONE) {
        return sw;
    }

    short length = 0;
    short paramMask = EC_Consts.PARAMETER_FP;
    while (paramMask <= EC_Consts.PARAMETER_S) {
        short masked = (short) (paramMask & params);
        if (masked != 0) {
            short len = exportParameter(keypair, key, masked, buffer, (short) (offset + 2));
            if (len == 0) {
                paramMask = (short) (paramMask << 1);
                continue;
            }
            Util.setShort(buffer, offset, len);
            offset += len + 2;
            length += len + 2;
        }
        paramMask = (short) (paramMask << 1);
    }
    return length;
}
 
Example 5
Source File: TransitApplet.java    From JCMathLib with MIT License 6 votes vote down vote up
/**
 * Gets/returns the balance.
 * 
 * Request Message: []
 * 
 * Response Message: [2-bytes Balance]
 * 
 * @param buffer
 *            The APDU buffer
 * @param messageOffset
 *            The offset of the request message content in the APDU buffer
 * @param messageLength
 *            The length of the request message content.
 * @return The offset at which content can be appended to the response
 *         message
 */
private short getBalance(byte[] buffer, short messageOffset,
        short messageLength) {

    // Check access authorization
    if (!pin.isValidated()) {
        ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
    }

    // Request Message: []

    if (messageLength != 0) {
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }

    // Response Message: [2-bytes Balance]

    short offset = 0;

    // Append balance to response message
    offset = Util.setShort(buffer, offset, balance);

    return offset;
}
 
Example 6
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Append a fixed length byte buffer as a TLV
 *
 * @param src    the source data, must be <= 127 bytes
 * @param out    the destination for the tlv
 * @param offset the offset into out
 * @return the offset to the next byte to be written
 */
private short addShortTLV(short tag, byte[] src, byte[] out, short offset) {
  if ((short) (tag & (short) 0xFF00) != (short) 0) {
    Util.setShort(out, offset, tag);
    offset += 2;
  } else {
    out[offset++] = (byte) tag;
  }
  out[offset++] = (byte) src.length;
  return Util.arrayCopyNonAtomic(src, (short) 0, out, offset, (short) src.length);
}
 
Example 7
Source File: GidsPINManager.java    From GidsApplet with GNU General Public License v3.0 5 votes vote down vote up
/**
 * \brief return information regarding the PIN
 */
public void returnPINStatus(APDU apdu, short id) {
    byte[] buf = apdu.getBuffer();
    GidsPIN pin = null;
    switch(id) {
    default:
        ISOException.throwIt(ErrorCode.SW_REFERENCE_DATA_NOT_FOUND);
        break;
    case (short) 0x7F71:
    case (short) 0x7F72:
        pin = pin_pin;
        break;
    }

    Util.setShort(buf, (short) 0, id);
    buf[2] = (byte) 0x06;
    buf[3] = (byte) 0x97;
    buf[4] = (byte) 0x01;
    buf[5] = pin.getTriesRemaining();
    buf[6] = (byte) 0x93;
    buf[7] = (byte) 0x01;
    buf[8] = pin.getTryLimit();
    apdu.setOutgoing();
    apdu.setOutgoingLength((short)9);
    apdu.sendBytes((short) 0, (short) 9);

}
 
Example 8
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Create and initialize the CAPABILITIES file
 *
 * @param dataSize to be allocated
 * @param dataReadAccess to put in the CC
 * @param dataWriteAccess to put in the CC
 * @return an array for use as the CC file
 */
private byte[] makeCaps(short dataSize,
                        byte dataReadAccess, byte dataWriteAccess) {
    short capsLen = (short)(CC_LEN_HEADER + 2 + CC_LEN_NDEF_FILE_CONTROL);
    byte[] caps = new byte[capsLen];

    short pos = 0;

    // CC length
    pos = Util.setShort(caps, pos, capsLen);
    // mapping version
    caps[pos++] = NDEF_MAPPING_VERSION;
    // maximum read size
    pos = Util.setShort(caps, pos, NDEF_MAX_READ);
    // maximum write size
    pos = Util.setShort(caps, pos, NDEF_MAX_WRITE);

    // NDEF File Control TLV
    caps[pos++] = CC_TAG_NDEF_FILE_CONTROL;
    caps[pos++] = CC_LEN_NDEF_FILE_CONTROL;
    // file ID
    pos = Util.setShort(caps, pos, FILEID_NDEF_DATA);
    // file size
    pos = Util.setShort(caps, pos, dataSize);
    // read access
    caps[pos++] = dataReadAccess;
    // write access
    caps[pos++] = dataWriteAccess;

    // check consistency
    if(pos != capsLen) {
        ISOException.throwIt(ISO7816.SW_UNKNOWN);
    }

    // return the file
    return caps;
}
 
Example 9
Source File: NdefApplet.java    From openjavacard-ndef with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Create and initialize the CAPABILITIES file
 *
 * @param dataSize to be allocated
 * @return an array for use as the CC file
 */
private byte[] makeCaps(short dataSize) {
    short capsLen = (short)(CC_LEN_HEADER + 2 + CC_LEN_NDEF_FILE_CONTROL);
    byte[] caps = new byte[capsLen];

    short pos = 0;

    // CC length
    pos = Util.setShort(caps, pos,  capsLen);
    // mapping version
    caps[pos++] = NDEF_MAPPING_VERSION;
    // maximum read size
    pos = Util.setShort(caps, pos, NDEF_MAX_READ);
    // maximum write size
    pos = Util.setShort(caps, pos, NDEF_MAX_WRITE);

    // NDEF File Control TLV
    caps[pos++] = CC_TAG_NDEF_FILE_CONTROL;
    caps[pos++] = CC_LEN_NDEF_FILE_CONTROL;
    // file ID
    pos = Util.setShort(caps, pos, FILEID_NDEF_DATA);
    // file size
    pos = Util.setShort(caps, pos, dataSize);
    // read access
    caps[pos++] = NDEF_READ_ACCESS;
    // write access
    caps[pos++] = NDEF_WRITE_ACCESS;

    // check consistency
    if(pos != capsLen) {
        ISOException.throwIt(ISO7816.SW_UNKNOWN);
    }

    // return the file
    return caps;
}
 
Example 10
Source File: LWNFCForumApplet.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static void writeHeader(short textSize) {
    short offset = (short)0;
    Util.setShort(FILE_DATA, offset, (short)(textSize + 1 + 5 + 4 + 2 + 1)); // prefix with size of full record
    offset += (short)(2 + 4);
    Util.setShort(FILE_DATA, offset, (short)(textSize + 1 + 5)); // size of text record payload
}
 
Example 11
Source File: OpenPGPSecureMessaging.java    From javacard-openpgpcard with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Wraps (encrypts and build MAC) the response data and places it in the
 * APDU buffer starting at offset 0. The buffer can be any buffer including
 * the APDU buffer itself. If the length is zero the buffer will not be
 * addressed and no response data will be present in the wrapped output.
 * 
 * @param buffer byte array containing the data which needs to be wrapped.
 * @param offset location of the data in the buffer.
 * @param length of the data in the buffer (in bytes).
 * @param status word which has to be wrapped in the response APDU.
 * @return the length of the wrapped data in the <apdu> buffer
 */
public short wrapResponseAPDU(byte[] buffer, short offset, short length, 
        short status) {
    byte[] apdu = APDU.getCurrentAPDUBuffer();
    short apdu_p = 0;
    // smallest multiple of 8 strictly larger than plaintextLen (length + padding)
    short do87DataLen = (short) ((((short) (length + 8)) / 8) * 8);
    // for 0x01 marker (indicating padding is used)
    do87DataLen++;
    short do87DataLenBytes = (short)(do87DataLen > 0xff? 2 : 1);
    short do87HeaderBytes = getApduBufferOffset(length);
    short do87Bytes = (short)(do87HeaderBytes + do87DataLen - 1); // 0x01 is counted twice 
    boolean hasDo87 = length > 0;

    incrementSSC();

    short ciphertextLength=0;
    if(hasDo87) {
        // Copy the plain text to temporary buffer to avoid data corruption.
        Util.arrayCopyNonAtomic(buffer, offset, tmp, (short) 0, length);
        // Put the cipher text in the proper position.
        ciphertextLength = cipher.doFinal(tmp, (short) 0, length, apdu, 
                do87HeaderBytes);
    }
    //sanity check
    //note that this check
    //  (possiblyPaddedPlaintextLength != (short)(do87DataLen -1))
    //does not always hold because some algs do the padding in the final, some in the init.
    if (hasDo87 && (((short) (do87DataLen - 1) != ciphertextLength)))
        ISOException.throwIt(SW_INTERNAL_ERROR);
    
    if (hasDo87) {
        // build do87
        apdu[apdu_p++] = (byte) 0x87;
        if(do87DataLen < 0x80) {
            apdu[apdu_p++] = (byte)do87DataLen; 
        } else {
            apdu[apdu_p++] = (byte) (0x80 + do87DataLenBytes);
            for(short i = (short) (do87DataLenBytes - 1); i >= 0; i--) {
                apdu[apdu_p++] = (byte) ((do87DataLen >>> (i * 8)) & 0xff);
            }
        }
        apdu[apdu_p++] = 0x01;
    }

    if(hasDo87) {
        apdu_p = do87Bytes;
    }
    
    // build do99
    apdu[apdu_p++] = (byte) 0x99;
    apdu[apdu_p++] = 0x02;
    Util.setShort(apdu, apdu_p, status);
    apdu_p += 2;

    // calculate and write mac
    signer.update(ssc, (short) 0, (short) ssc.length);
    signer.sign(apdu, (short) 0, apdu_p, apdu, (short) (apdu_p + 2));

    // write do8e
    apdu[apdu_p++] = (byte) 0x8e;
    apdu[apdu_p++] = 0x08;
    apdu_p += 8; // for mac written earlier

    return apdu_p;
}
 
Example 12
Source File: Uint32Helper.java    From ledger-javacard with GNU Affero General Public License v3.0 4 votes vote down vote up
public static void setShort(byte[] buffer, short offset, short value) {
    clear(buffer, offset);
    Util.setShort(buffer, (short)(offset + 2), value);
}
 
Example 13
Source File: EC_Consts.java    From ECTester with MIT License 4 votes vote down vote up
public static short transformParameter(short transformation, byte[] buffer, short offset, short length) {
    if (transformation == TRANSFORMATION_NONE) {
        return length;
    }

    short transformationMask = TRANSFORMATION_FIXED;
    while (transformationMask <= TRANSFORMATION_04_MASK) {
        short transformationPart = (short) (transformationMask & transformation);
        switch (transformationPart) {
            case (short) 0:
                break;
            case TRANSFORMATION_FIXED:
                if (length >= 1) {
                    buffer[offset] = (byte) 0xcc;
                    buffer[(short) (offset + length - 1)] = (byte) 0xcc;
                }
                break;
            case TRANSFORMATION_FULLRANDOM:
                randomData.generateData(buffer, offset, length);
                break;
            case TRANSFORMATION_ONEBYTERANDOM:
                short first = Util.getShort(buffer, (short) 0); // save first two bytes

                randomData.generateData(buffer, (short) 0, (short) 2); // generate position
                short rngPos = Util.getShort(buffer, (short) 0); // save generated position

                Util.setShort(buffer, (short) 0, first); // restore first two bytes

                if (rngPos < 0) { // make positive
                    rngPos = (short) -rngPos;
                }
                rngPos %= length; // make < param length

                byte original = buffer[rngPos];
                do {
                    randomData.generateData(buffer, rngPos, (short) 1);
                } while (original == buffer[rngPos]);
                break;
            case TRANSFORMATION_ZERO:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                break;
            case TRANSFORMATION_ONE:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                buffer[(short) (offset + length)] = (byte) 1;
                break;
            case TRANSFORMATION_MAX:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 1);
                break;
            case TRANSFORMATION_INCREMENT:
                short index = (short) (offset + length - 1);
                byte value;
                do {
                    value = buffer[index];
                    buffer[index--] = ++value;
                } while (value == (byte) 0 && index >= offset);
                break;
            case TRANSFORMATION_INFINITY:
                Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
                length = 1;
                break;
            case TRANSFORMATION_COMPRESS_HYBRID:
            case TRANSFORMATION_COMPRESS:
                if ((short) (length % 2) != 1) {
                    // an uncompressed point should have odd length (since 1 byte type, + 2 * coords)
                    ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
                }
                short half = (short) ((short) (length - 1) / 2);
                byte yLSB = buffer[(short) (offset + length)];
                byte yBit = (byte) (yLSB & 0x01);
                if (yBit == 1) {
                    buffer[offset] = 3;
                } else {
                    buffer[offset] = 2;
                }

                if (transformationPart == TRANSFORMATION_COMPRESS) {
                    length = (short) (half + 1);
                } else {
                    buffer[offset] += 4;
                }
                break;
            case TRANSFORMATION_04_MASK:
                buffer[offset] = 4;
                break;
            default:
                ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
        }
        transformationMask = (short) (transformationMask << 1);
    }
    return length;
}
 
Example 14
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 4 votes vote down vote up
/**
 * GENERATE KEY APDU implementation.
 */
private void generateAsymetricKey(APDU apdu) {
  byte[] buffer = apdu.getBuffer();
  if (apdu.setIncomingAndReceive() != 2) {
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
  }
  KeyPair key = getKey(buffer[ISO7816.OFFSET_CDATA]);
  if (buffer[ISO7816.OFFSET_P1] == (byte) 0x81) {
    if (!(key.getPublic()).isInitialized()) {
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
    }
  } else {
    if (!pins[PIN_INDEX_PW3].isValidated()) {
      ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
    }
    JCSystem.beginTransaction();
    key.genKeyPair();
    if (buffer[ISO7816.OFFSET_CDATA] == (byte)0xB6) {
      signatureCounter[0] = 0;
      signatureCounter[1] = 0;
      signatureCounter[2] = 0;
    }
    JCSystem.commitTransaction();
  }
  // Send the TLV data and public exponent using the APDU buffer.
  buffer[ISO7816.OFFSET_CDATA] = 0x7F;
  buffer[(short) (ISO7816.OFFSET_CDATA + 1)] = 0x49;
  buffer[(short) (ISO7816.OFFSET_CDATA + 2)] = (byte) 0x82;
  buffer[(short) (ISO7816.OFFSET_CDATA + 5)] = (byte) 0x82;
  short length = ((RSAPublicKey) key.getPublic()).getExponent(
      buffer, (short) (ISO7816.OFFSET_CDATA + 7));
  buffer[(short) (ISO7816.OFFSET_CDATA + 6)] = (byte) length;
  short pos = (short) (ISO7816.OFFSET_CDATA + 7 + length);
  buffer[pos] = (byte) 0x81;
  buffer[(short) (pos + 1)] = (byte) 0x82;
  Util.setShort(buffer, (short) (pos + 2), RSA_KEY_LENGTH_BYTES);
  Util.setShort(buffer, (short) (ISO7816.OFFSET_CDATA + 3),
                (short) (pos + RSA_KEY_LENGTH_BYTES - ISO7816.OFFSET_CDATA - 1));
  apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short) (length + 11));

  // And the modulus using get response.
  Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_LENGTH, RSA_KEY_LENGTH_BYTES);
  ((RSAPublicKey) key.getPublic()).getModulus(commandChainingBuffer, TEMP_GET_RESPONSE_DATA);
  // Skip leading zero byte.
  if (commandChainingBuffer[TEMP_GET_RESPONSE_DATA] == 0) {
    Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_OFFSET,
                  (short) (TEMP_GET_RESPONSE_DATA + 1));
  } else {
    Util.setShort(commandChainingBuffer, TEMP_GET_RESPONSE_OFFSET, TEMP_GET_RESPONSE_DATA);
  }
  commandChainingBuffer[TEMP_INS] = buffer[ISO7816.OFFSET_INS];
  ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00);
}
 
Example 15
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 16
Source File: Gpg.java    From OpenPGP-Card with GNU General Public License v3.0 4 votes vote down vote up
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: 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 18
Source File: Bignat.java    From JCMathLib with MIT License 4 votes vote down vote up
/**
 * Add short value to this bignat
 * @param other short value to add 
 */
public void add(short other) {
    Util.setShort(bnh.tmp_array_short, (short) 0, other); // serialize other into array
    this.add_carry(bnh.tmp_array_short, (short) 0, (short) 2); // add as array
}
 
Example 19
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 3 votes vote down vote up
/**
 * DEPRECATED - Not necessary anymore when recovering the pubkey with ALG_EC_SVDP_DH_PLAIN_XY
 * A minimalist API is maintained for backward compatibility.
 * 
 * This function allows to compute the authentikey pubkey externally and 
 * store it in the secure memory cache for future use. 
 * This allows to speed up computation during derivation of non-hardened child.
 * 
 * ins: 0x75
 * p1: 
 * p2:
 * data: [coordx_size(2b) | coordx | sig_size(2b) | sig][coordy_size(2b) | coordy]
    *
 * returns: none
 */
private short setBIP32AuthentikeyPubkey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
       short pos=0;
	Util.setShort(buffer, pos, bip32_om.nb_elem_free); // number of slot available 
	pos += (short) 2;
	Util.setShort(buffer, pos, bip32_om.nb_elem_used); // number of slot used 
	pos += (short) 2;
	return pos;
}
 
Example 20
Source File: CardEdge.java    From SatochipApplet with GNU Affero General Public License v3.0 3 votes vote down vote up
/**
 * DEPRECATED - Not necessary anymore when recovering the pubkey with ALG_EC_SVDP_DH_PLAIN_XY
 * A minimalist API is maintained for backward compatibility.
 * 
 * This function allows to compute an extended pubkey externally and 
 * store it in the secure BIP32 memory cache for future use. 
 * This allows to speed up computation during derivation of non-hardened child.
 * 
 * ins: 0x74
 * p1: 
 * p2:
 * data: [chaincode(32b) | coordx_size(2b) | coordx | sig_size(2b) | sig | sig_size(2b) | sig2 ]
 * 			[ coordy_size(2b) | coordy]
 *  returns: none
 */
private short setBIP32ExtendedPubkey(APDU apdu, byte[] buffer){
	// check that PIN[0] has been entered previously
	if (!pins[0].isValidated())
		ISOException.throwIt(SW_UNAUTHORIZED);
	
	short pos=0;
	Util.setShort(buffer, pos, bip32_om.nb_elem_free); // number of slot available 
	pos += (short) 2;
	Util.setShort(buffer, pos, bip32_om.nb_elem_used); // number of slot used 
	pos += (short) 2;
	return pos;
}