/// <summary>
        /// Does the writing of transaction data to the user button as well
        /// as actually signing the data with the coprocessor.
        ///
        /// No need to synchronize wince the methods that call this
        /// private method will be synchronized.
        /// </summary>
        private bool writeTransactionData(SHAiButtonUser user, int transID, int balance, byte[] accountData)
        {
            //init local vars
            int acctPageNum = user.AccountPageNumber;

            // data type code - dynamic: 0x00, static: 0x01
            accountData[I_DATA_TYPE_CODE] = 0x01;

            // conversion factor - 2 data bytes
            accountData[I_CONVERSION_FACTOR + 0] = 0x8B;
            accountData[I_CONVERSION_FACTOR + 1] = 0x48;

            // zero-out the don't care bytes
            accountData[I_DONT_CARE]     = 0x00;
            accountData[I_DONT_CARE + 1] = 0x00;
            accountData[I_DONT_CARE + 2] = 0x00;
            accountData[I_DONT_CARE + 3] = 0x00;

            if (accountData[I_FILE_LENGTH] == RECORD_A_LENGTH)
            {
                OneWireEventSource.Log.Debug("Was A, now using B");

                // length of the TMEX file
                accountData[I_FILE_LENGTH] = RECORD_B_LENGTH;

                // account balance - 3 data bytes
                Convert.toByteArray(balance, accountData, I_BALANCE_B, 3);

                // transaction ID - 2 data bytes
                accountData[I_TRANSACTION_ID_B + 0] = (byte)transID;
                accountData[I_TRANSACTION_ID_B + 1] = (byte)((int)((uint)transID >> 8));

                // continuation pointer for TMEX file
                accountData[I_CONTINUATION_PTR_B] = 0x00;

                // clear out the crc16 - 2 data bytes
                accountData[I_FILE_CRC16_B + 0] = 0x00;
                accountData[I_FILE_CRC16_B + 1] = 0x00;

                // dump in the inverted CRC
                int crc = ~CRC16.compute(accountData, 0, accountData[I_FILE_LENGTH] + 1, acctPageNum);
                accountData[I_FILE_CRC16_B + 0] = (byte)crc;
                accountData[I_FILE_CRC16_B + 1] = (byte)(crc >> 8);
            }
            else
            {
                OneWireEventSource.Log.Debug("Was B, now using A");

                // length of the TMEX file
                accountData[I_FILE_LENGTH] = RECORD_A_LENGTH;

                // account balance - 3 data bytes
                Convert.toByteArray(balance, accountData, I_BALANCE_A, 3);

                // transaction ID - 2 data bytes
                accountData[I_TRANSACTION_ID_A + 0] = (byte)transID;
                accountData[I_TRANSACTION_ID_A + 1] = (byte)((int)((uint)transID >> 8));

                // continuation pointer for TMEX file
                accountData[I_CONTINUATION_PTR_A] = 0x00;

                // clear out the crc16 - 2 data bytes
                accountData[I_FILE_CRC16_A + 0] = 0x00;
                accountData[I_FILE_CRC16_A + 1] = 0x00;

                // dump in the inverted CRC
                int crc = ~CRC16.compute(accountData, 0, accountData[I_FILE_LENGTH] + 1, acctPageNum);
                accountData[I_FILE_CRC16_A + 0] = (byte)crc;
                accountData[I_FILE_CRC16_A + 1] = (byte)(crc >> 8);
            }

            OneWireEventSource.Log.Debug("------------------------------------");
            OneWireEventSource.Log.Debug("writing transaction data");
            OneWireEventSource.Log.Debug("acctPageNum: " + acctPageNum);
            OneWireEventSource.Log.Debug("accountData: " + Convert.toHexString(accountData));
            OneWireEventSource.Log.Debug("------------------------------------");

            // write it to the button
            try
            {
                if (user.writeAccountData(accountData, 0))
                {
                    return(true);
                }
            }
            catch (OneWireException owe)
            {
                OneWireEventSource.Log.Debug(owe.ToString());
            }

            this.lastError = SHATransaction.USER_WRITE_DATA_FAILED;
            return(false);
        }
Example #2
0
        /// <summary>
        /// Does the writing of transaction data to the user button as well
        /// as actually signing the data with the coprocessor.
        /// </summary>
        private bool writeTransactionData(SHAiButtonUser user, int transID, int balance, byte[] accountData)
        {
            //init local vars
            SHAiButtonCopr copr        = this.copr;
            int            acctPageNum = user.AccountPageNumber;

            byte[] scratchpad = this.writeTransactionData_scratchpad;

            // length of the TMEX file - 28 data, 1 cont. ptr
            accountData[I_FILE_LENGTH] = (byte)29;

            // transaction ID - 2 data bytes
            accountData[I_TRANSACTION_ID + 0] = (byte)transID;
            accountData[I_TRANSACTION_ID + 1] = (byte)((int)((uint)transID >> 8));

            // conversion factor - 2 data bytes
            accountData[I_CONVERSION_FACTOR + 0] = 0x8B;
            accountData[I_CONVERSION_FACTOR + 1] = 0x48;

            // account balance - 3 data bytes
            Convert.toByteArray(balance, accountData, I_BALANCE, 3);

            // initial signature - 20 data bytes
            copr.getInitialSignature(accountData, I_SIGNATURE);

            // data type code - dynamic: 0x00, static: 0x01
            accountData[I_DATA_TYPE_CODE] = 0x01;

            // continuation pointer for TMEX file
            accountData[I_CONTINUATION_PTR] = 0x00;

            // clear out the crc16 - 2 data bytes
            accountData[I_FILE_CRC16 + 0] = 0x00;
            accountData[I_FILE_CRC16 + 1] = 0x00;

            //we need to increment the writeCycleCounter since we will be writing to the part
            int wcc = user.WriteCycleCounter;

            if (wcc > 0)
            {
                //copy the write cycle counter into scratchpad
                Convert.toByteArray(wcc + 1, scratchpad, 8, 4);
            }
            else
            {
                if (user.hasWriteCycleCounter())
                {
                    // failed to read account data
                    this.lastError = SHATransaction.USER_READ_AUTH_FAILED;
                    return(false);
                }
                Array.Copy(ffBlock, 0, scratchpad, 8, 4);
            }

            // svcPageNumber, followed by address of device
            scratchpad[12] = (byte)acctPageNum;
            user.getAddress(scratchpad, 13, 7);

            // copy in the signing challenge
            copr.getSigningChallenge(scratchpad, 20);

            // sign the data, return the mac right into accountData
            copr.createDataSignature(accountData, scratchpad, accountData, I_SIGNATURE);

            //after signature make sure to dump in the inverted CRC
            int crc = ~CRC16.compute(accountData, 0, accountData[I_FILE_LENGTH] + 1, acctPageNum);

            //set the the crc16 bytes
            accountData[I_FILE_CRC16 + 0] = (byte)crc;
            accountData[I_FILE_CRC16 + 1] = (byte)(crc >> 8);

            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
            OneWireEventSource.Log.Debug("------------------------------------");
            OneWireEventSource.Log.Debug("writing transaction data");
            OneWireEventSource.Log.Debug("acctPageNum: " + acctPageNum);
            OneWireEventSource.Log.Debug("accountData: " + Convert.toHexString(accountData));
            OneWireEventSource.Log.Debug("------------------------------------");
            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//

            // write it to the button
            try
            {
                if (user.writeAccountData(accountData, 0))
                {
                    return(true);
                }
            }
            catch (OneWireException owe)
            {
                OneWireEventSource.Log.Debug(owe.ToString());
            }

            this.lastError = SHATransaction.USER_WRITE_DATA_FAILED;
            return(false);
        }