/// <summary> /// <P>Initialize a DS1961S as a fresh user iButton for a given SHA service. /// This constructor not only creates the service file for the user iButton /// using the TMEX file structure, but it also installs the master /// authentication secret and binds it to the iButton (making it unique for /// a particular button). Optionally, the device can be formatted before /// the service file is installed.</P> /// /// <P>Note: With this constructor, the master secret is installed and bound /// to the iButton, so the final secret is none by the object. For that /// reason, a hardware coprocessor is not necessary for generating the /// write-authorization MAC.</P> /// </summary> /// <param name="copr"> The SHAiButtonCopr to which the user object is tied. This /// Coprocessor contains the necessary binding code and service /// filename, necessary for both locating a user and recreating his /// unique secret. </param> /// <param name="owc"> The DS1963S iButton that this object will refer to. </param> /// <param name="formatDevice"> If <code>true</code>, the TMEX filesystem will be /// formatted before the account service file is created. </param> /// <param name="authSecret"> The master authentication secret for the systm. /// </param> /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as /// reading an incorrect CRC from a 1-Wire device. This could be /// caused by a physical interruption in the 1-Wire Network due to /// shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception> /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire /// adapter /// </exception> /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr,OneWireContainer33) </seealso> /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr) </seealso> public SHAiButtonUser33(SHAiButtonCopr copr, OneWireContainer33 owc, bool formatDevice, byte[] authSecret) : this(copr, copr) { //setup service filename //hold container reference this.ibc33 = owc; //and address this.address = owc.Address; //clear out old secret first byte[] NullSecret = new byte[8]; for (int i = 0; i < 8; i++) { NullSecret[i] = 0x00; } if (!this.ibc33.loadFirstSecret(NullSecret, 0)) { throw new OneWireException("Failed to null out device secret."); } if (!owc.installMasterSecret(0, authSecret)) { throw new OneWireException("Install Master Secret failed"); } if (!createServiceFile(owc, strServiceFilename, formatDevice)) { throw new OneWireException("Failed to create service file."); } //setup the fullBindCode with rest of info this.fullBindCode[4] = (byte)this.accountPageNumber; Array.Copy(this.address, 0, this.fullBindCode, 5, 7); if (!owc.bindSecretToiButton(this.accountPageNumber, copr.BindData)) { throw new OneWireException("Bind Secret to iButton failed"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if (DEBUG) { IOHelper.writeLine("------------------------------------"); IOHelper.writeLine("Initialized DS1961S User"); IOHelper.writeLine("address"); IOHelper.writeBytesHex(owc.Address); IOHelper.writeLine("serviceFilename: " + strServiceFilename); IOHelper.writeLine("accountPageNumber: " + accountPageNumber); IOHelper.writeLine("authSecret"); IOHelper.writeBytesHex(authSecret); IOHelper.writeLine("bindData"); IOHelper.writeBytesHex(copr.bindData); IOHelper.writeLine("bindCode"); IOHelper.writeBytesHex(copr.bindCode); IOHelper.writeLine("------------------------------------"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ }
/// <summary> /// <P>Creates a mostly unitialized SHAiButtonUser object. This constructor /// merely copies the coprocessors 7 byte binding code into a local cache /// and stores the name of the account service file used for all user /// iButtons.</P> /// /// <P>Since this constructor leaves data unitialized, you should be very /// careful with the use of it. It is expected that after calling this /// constructor, the user will call <code>setiButton</code> to finish the /// initialization process. On memory-starved platforms, this should help /// optimize memory usage.</P> /// </summary> /// <param name="copr"> The SHAiButtonCopr to which the user object is tied. This /// Coprocessor contains the necessary binding code and service /// filename, necessary for both locating a user and recreating his /// unique secret. /// </param> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr,OneWireContainer18,bool,byte[]) </seealso> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr) </seealso> public SHAiButtonUser18(SHAiButtonCopr copr) { //save a copy of the binding code copr.getBindCode(this.fullBindCode, 0); Array.Copy(this.fullBindCode, 4, this.fullBindCode, 12, 3); //create string representation of service filename copr.getFilename(this.serviceFile, 0); this.strServiceFilename = Encoding.Unicode.GetString(this.serviceFile) + "." + (int)copr.FilenameExt; }
/// <summary> /// <P>Creates a valid SHAiButtonUser object. If the service file, /// whose name is taken from the <code>SHAiButtonCopr</code>, is not /// found on the user iButton, a OneWireException is thrown with the /// message "Invalid SHA user".</P> /// </summary> /// <param name="copr"> The SHAiButtonCopr to which the user object is tied. This /// Coprocessor contains the necessary binding code and service /// filename, necessary for both locating a user and recreating his /// unique secret. </param> /// <param name="owc"> The DS1963S iButton that this object will refer to. /// </param> /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as /// reading an incorrect CRC from a 1-Wire device. This could be /// caused by a physical interruption in the 1-Wire Network due to /// shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception> /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire /// adapter /// </exception> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr,OneWireContainer18,bool,byte[]) </seealso> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr) </seealso> public SHAiButtonUser18(SHAiButtonCopr copr, OneWireContainer18 owc) : this(copr) { //setup service filename //hold container reference and address if (!setiButton18(owc)) { throw new OneWireException("Invalid SHA user"); } }
/// <summary> /// <P>Initialize a DS1963S as a fresh user iButton for a given SHA service. /// This constructor not only creates the service file for the user iButton /// using the TMEX file structure, but it also installs the master /// authentication secret and binds it to the iButton (making it unique for /// a particular button). Optionally, the device can be formatted before /// the service file is installed.</P> /// </summary> /// <param name="copr"> The SHAiButtonCopr to which the user object is tied. This /// Coprocessor contains the necessary binding code and service /// filename, necessary for both locating a user and recreating his /// unique secret. </param> /// <param name="owc"> The DS1963S iButton that this object will refer to. </param> /// <param name="formatDevice"> If <code>true</code>, the TMEX filesystem will be /// formatted before the account service file is created. </param> /// <param name="authSecret"> The master authentication secret for the systm. /// </param> /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as /// reading an incorrect CRC from a 1-Wire device. This could be /// caused by a physical interruption in the 1-Wire Network due to /// shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception> /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire /// adapter /// </exception> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr,OneWireContainer18) </seealso> /// <seealso cref= #SHAiButtonUser18(SHAiButtonCopr) </seealso> public SHAiButtonUser18(SHAiButtonCopr copr, OneWireContainer18 owc, bool formatDevice, byte[] authSecret) : this(copr) { //setup service filename //hold container reference this.ibc = owc; //and address this.address = owc.Address; if (!createServiceFile(owc, strServiceFilename, formatDevice)) { throw new OneWireException("Failed to create service file."); } //save a copy of the binding code copr.getBindCode(this.fullBindCode, 0); Array.Copy(this.fullBindCode, 4, this.fullBindCode, 12, 3); //setup the fullBindCode with rest of info this.fullBindCode[4] = (byte)this.accountPageNumber; Array.Copy(this.address, 0, this.fullBindCode, 5, 7); if (!owc.installMasterSecret(accountPageNumber, authSecret, accountPageNumber & 7)) { throw new OneWireException("Install Master Secret failed"); } //not in critical path, so getBindBlah() is okay. if (!owc.bindSecretToiButton(accountPageNumber, copr.BindData, this.fullBindCode, accountPageNumber & 7)) { throw new OneWireException("Bind Secret to iButton failed"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if (DEBUG) { IOHelper.writeLine("------------------------------------"); IOHelper.writeLine("Initialized User"); IOHelper.writeLine("address"); IOHelper.writeBytesHex(owc.Address); IOHelper.writeLine("serviceFilename: " + strServiceFilename); IOHelper.writeLine("accountPageNumber: " + accountPageNumber); IOHelper.writeLine("authSecret"); IOHelper.writeBytesHex(authSecret); IOHelper.writeLine("bindData"); IOHelper.writeBytesHex(copr.bindData); IOHelper.writeLine("bindCode"); IOHelper.writeBytesHex(copr.bindCode); IOHelper.writeLine("------------------------------------"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ }
/// <summary> /// <P>Creates a mostly unitialized SHAiButtonUser object. This constructor /// merely copies the coprocessors 7 byte binding code into a local cache /// and stores the name of the account service file used for all user /// iButtons.</P> /// /// <P>Since this constructor leaves data unitialized, you should be very /// careful with the use of it. It is expected that after calling this /// constructor, the user will call <code>setiButton</code> to finish the /// initialization process. On memory-starved platforms, this should help /// optimize memory usage.</P> /// /// <P>Note: The same coprocessor can be used for write-authorization as /// authentication if you're transaction system is using unsigned transaction /// data.</P> /// </summary> /// <param name="copr"> The SHAiButtonCopr to which the user object is tied. This /// Coprocessor contains the necessary binding code and service /// filename, necessary for both locating a user and recreating his /// unique secret. </param> /// <param name="authCopr"> The SHAiButtonCopr used to generate the write-authorization /// MAC for the copy-scratchpad command of the DS1961S. /// /// </param> /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,OneWireContainer33,bool,byte[]) </seealso> /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr,OneWireContainer33) </seealso> public SHAiButtonUser33(SHAiButtonCopr copr, SHAiButtonCopr authCopr) { //hold a reference to the coprocessor this.copr = authCopr; //make sure fullBindCode has appropriate ff padding Array.Copy(ffBlock, 0, this.fullBindCode, 0, 15); //create string representation of service filename copr.getFilename(this.serviceFile, 0); this.strServiceFilename = Encoding.Unicode.GetString(this.serviceFile) + "." + (int)copr.FilenameExt; }
/// <summary> /// Method main /// /// </summary> /// <param name="args"> /// </param> /// <exception cref="OneWireException"> </exception> /// <exception cref="OneWireIOException"> /// </exception> public static void Main3(string[] args) { //coprocessor long coprID = 0; // attempt to open the sha.properties file sha_properties = new Properties(); if (!sha_properties.loadLocalFile("sha.properties")) { Debug.WriteLine("loading default sha.properties!"); Assembly asm = typeof(SHADebitDemo.MainPage).GetTypeInfo().Assembly; sha_properties.loadResourceFile(asm, "SHADebitDemo.sha.properties"); } // ------------------------------------------------------------ // Instantiate coprocessor containers // ------------------------------------------------------------ SHAiButtonCopr copr = null; OneWireContainer18 copr18 = new OneWireContainer18(); copr18.setSpeed(DSPortAdapter.SPEED_REGULAR, false); copr18.SpeedCheck = false; // ------------------------------------------------------------ // Setup the adapter for the coprocessor // ------------------------------------------------------------ DSPortAdapter coprAdapter = null; string coprAdapterName = null, coprPort = null; try { coprAdapterName = sha_properties.getProperty("copr.adapter", "{DS9097U}"); coprPort = sha_properties.getProperty("copr.port", "COM1"); if (string.ReferenceEquals(coprPort, null) || string.ReferenceEquals(coprAdapterName, null)) { coprAdapter = OneWireAccessProvider.DefaultAdapter; } else { coprAdapter = OneWireAccessProvider.getAdapter(coprAdapterName, coprPort); } IOHelper.writeLine("Coprocessor adapter loaded, adapter: " + coprAdapter.AdapterName + " port: " + coprAdapter.PortName); coprAdapter.adapterDetected(); coprAdapter.targetFamily(0x18); coprAdapter.beginExclusive(true); coprAdapter.setSearchAllDevices(); coprAdapter.reset(); } catch (Exception e) { IOHelper.writeLine("Error initializing coprocessor adapter"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } // ------------------------------------------------------------ // Find the coprocessor // ------------------------------------------------------------ if (sha_properties.getPropertyBoolean("copr.simulated.isSimulated", false)) { string coprVMfilename = sha_properties.getProperty("copr.simulated.filename"); // --------------------------------------------------------- // Load emulated coprocessor // --------------------------------------------------------- try { copr = new SHAiButtonCoprVM(coprVMfilename); } catch (Exception e) { IOHelper.writeLine("Invalid Coprocessor Data File"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } } else { // --------------------------------------------------------- // Get the name of the coprocessor service file // --------------------------------------------------------- string filename = sha_properties.getProperty("copr.filename", "COPR.0"); // --------------------------------------------------------- // Check for hardcoded coprocessor address // --------------------------------------------------------- byte[] coprAddress = sha_properties.getPropertyBytes("copr.address", null); long lookupID = 0; if (coprAddress != null) { lookupID = Address.toLong(coprAddress); IOHelper.write("Looking for coprocessor: "); IOHelper.writeLineHex(lookupID); } // --------------------------------------------------------- // Find hardware coprocessor // --------------------------------------------------------- try { bool next = coprAdapter.findFirstDevice(); while (copr == null && next) { try { long tmpCoprID = coprAdapter.AddressAsLong; if (coprAddress == null || tmpCoprID == lookupID) { IOHelper.write("Loading coprocessor file: " + filename + " from device: "); IOHelper.writeLineHex(tmpCoprID); copr18.setupContainer(coprAdapter, tmpCoprID); copr = new SHAiButtonCopr(copr18, filename); //save coprocessor ID coprID = tmpCoprID; } } catch (Exception e) { IOHelper.writeLine(e); } next = coprAdapter.findNextDevice(); } } catch (Exception) { ; } } if (copr == null) { IOHelper.writeLine("No Coprocessor found!"); return; } IOHelper.writeLine(copr); IOHelper.writeLine(); // ------------------------------------------------------------ // Create the SHADebit transaction types // ------------------------------------------------------------ //stores DS1963S transaction data SHATransaction trans = null; string transType = sha_properties.getProperty("ds1961s.transaction.type", "Signed"); if (transType.ToLower().IndexOf("unsigned", StringComparison.Ordinal) >= 0) { trans = new SHADebitUnsigned(copr, 10000, 50); } else { trans = new SHADebit(copr, 10000, 50); } // ------------------------------------------------------------ // Create the User Buttons objects // ------------------------------------------------------------ //holds DS1963S user buttons OneWireContainer33 owc33 = new OneWireContainer33(); owc33.setSpeed(DSPortAdapter.SPEED_REGULAR, false); //owc33.setSpeedCheck(false); // ------------------------------------------------------------ // Get the adapter for the user // ------------------------------------------------------------ DSPortAdapter adapter = null; string userAdapterName = null, userPort = null; try { userAdapterName = sha_properties.getProperty("user.adapter", "{DS9097U}"); userPort = sha_properties.getProperty("user.port", "COM9"); if (string.ReferenceEquals(userPort, null) || string.ReferenceEquals(userAdapterName, null)) { if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null)) { adapter = OneWireAccessProvider.DefaultAdapter; } else { adapter = coprAdapter; } } else if (userAdapterName.Equals(coprAdapterName) && userPort.Equals(coprPort)) { adapter = coprAdapter; } else { adapter = OneWireAccessProvider.getAdapter(userAdapterName, userPort); } IOHelper.writeLine("User adapter loaded, adapter: " + adapter.AdapterName + " port: " + adapter.PortName); byte[] families = new byte[] { 0x33, unchecked ((byte)0xB3) }; adapter.adapterDetected(); adapter.targetFamily(families); adapter.beginExclusive(false); adapter.setSearchAllDevices(); adapter.reset(); } catch (Exception e) { IOHelper.writeLine("Error initializing user adapter."); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } // --------------------------------------------------------------- // Search for the button // --------------------------------------------------------------- try { long tmpID = -1; bool next = adapter.findFirstDevice(); for (; tmpID == -1 && next; next = adapter.findNextDevice()) { tmpID = adapter.AddressAsLong; if (tmpID == coprID) { tmpID = -1; } else { owc33.setupContainer(adapter, tmpID); } } if (tmpID == -1) { IOHelper.writeLine("No buttons found!"); return; } } catch (Exception) { IOHelper.writeLine("Adapter error while searching."); return; } IOHelper.write("Setting up user button: "); IOHelper.writeBytesHex(owc33.Address); IOHelper.writeLine(); IOHelper.writeLine("How would you like to enter the authentication secret (unlimited bytes)? "); byte[] auth_secret = getBytes(0); IOHelper.writeBytes(auth_secret); IOHelper.writeLine(); auth_secret = SHAiButtonCopr.reformatFor1961S(auth_secret); IOHelper.writeLine("Reformatted for compatibility with 1961S buttons"); IOHelper.writeBytes(auth_secret); IOHelper.writeLine(""); IOHelper.writeLine("Initial Balance in Cents? "); int initialBalance = IOHelper.readInt(100); trans.setParameter(SHADebit.INITIAL_AMOUNT, initialBalance); SHAiButtonUser user = new SHAiButtonUser33(copr, owc33, true, auth_secret); if (trans.setupTransactionData(user)) { IOHelper.writeLine("Transaction data installation succeeded"); } else { IOHelper.writeLine("Failed to initialize transaction data"); } IOHelper.writeLine(user); }
/// <summary> /// <P>Writes the account data to the SHAiButton. First, this function /// asserts that the account page number is known. The account data is /// copied from dataBuffer starting at the offset. If there are less /// than 32 bytes available to copy, this function only copies the bytes /// that are available.</P> /// /// <P>Note that for the DS1961S user button, an authorization MAC must /// be generated for the copy-scratchpad command. Since the scratchpad /// is only 8 bytes long, this must be done 4 times to write a page of /// data. So, this function only writes (in 8 byte blocks) the bytes /// that have changed.</P> /// </summary> /// <param name="dataBuffer"> the buffer to copy the account data from </param> /// <param name="offset"> the index into the buffer where copying should begin </param> /// <returns> whether or not the data write succeeded /// </returns> /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as /// reading an incorrect CRC from a 1-Wire device. This could be /// caused by a physical interruption in the 1-Wire Network due to /// shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception> /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire /// adapter </exception> public override bool writeAccountData(byte[] dataBuffer, int offset) { lock (this) { //local vars. OneWireContainer33 ibcL = this.ibc33; byte[] copyAuth = this.writeAccountData_copyAuth; byte[] scratchpad = this.writeAccountData_scratchpad; byte[] pageData = this.writeAccountData_pageData; byte[] fullBindCode = this.fullBindCode; SHAiButtonCopr coprL = this.copr; //make sure account info is properly setup if (!checkAccountPageInfo(ibcL)) { return(false); } //if the part is being initialized, the container class "knows" //the secret already. no need for a coprocessor. if (ibcL.ContainerSecretSet) { //use container to write the data page, since it knows the secret ibcL.writeDataPage(this.accountPageNumber, dataBuffer); //update the data cache Array.Copy(dataBuffer, offset, this.accountData, 0, 32); } else { //since the container's secret is not set, we have to use the //coprocessor for generating the copy scratchpad authorization. if (coprL == null) { throw new OneWireException("No Write Authorization Coprocessor Available!"); } //copy the data cache into a working page; Array.Copy(this.accountData, 0, pageData, 0, 32); //takes four write/copies to actually write the data page. for (int i = 24; i >= 0; i -= 8) { int index = offset + i; //only perform any action if the data needs to be updated if ((dataBuffer[index] != accountData[i]) || (dataBuffer[index + 1] != accountData[i + 1]) || (dataBuffer[index + 2] != accountData[i + 2]) || (dataBuffer[index + 3] != accountData[i + 3]) || (dataBuffer[index + 4] != accountData[i + 4]) || (dataBuffer[index + 5] != accountData[i + 5]) || (dataBuffer[index + 6] != accountData[i + 6]) || (dataBuffer[index + 7] != accountData[i + 7])) { //format the working page for generating the //appropriate copy authorization mac pageData[28] = dataBuffer[index]; pageData[29] = dataBuffer[index + 1]; pageData[30] = dataBuffer[index + 2]; pageData[31] = dataBuffer[index + 3]; //format the scratchpad for generating the //appropriate copy authorization mac scratchpad[8] = dataBuffer[index + 4]; scratchpad[9] = dataBuffer[index + 5]; scratchpad[10] = dataBuffer[index + 6]; scratchpad[11] = dataBuffer[index + 7]; //add in the page num and address Array.Copy(this.fullBindCode, 4, scratchpad, 12, 11); //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if (DEBUG) { IOHelper.writeLine("------------------------------------------------------------"); IOHelper.writeLine("SHAiButtonUser33 - writeAccountData loop "); IOHelper.writeLine("current account data state: "); IOHelper.writeBytesHex(this.accountData); IOHelper.writeLine("current byte block: " + i); IOHelper.writeLine("New bytes for block: "); IOHelper.writeBytesHex(dataBuffer, index, 8); IOHelper.writeLine("------------------------------------------------------------"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //get the copy authorization mac coprL.createDataSignatureAuth(pageData, scratchpad, copyAuth, 0, fullBindCode); //only need to pass it to coprocessor once fullBindCode = null; //write 8 bytes of data to the DS1961S scratchpad if (!ibcL.writeScratchpad(this.accountPageNumber, i, dataBuffer, index, 8)) { //operation failed return(false); } //copy scratchpad to page if (!ibcL.copyScratchpad(this.accountPageNumber, i, copyAuth, 0)) { //operation failed return(false); } //update cache of account data Array.Copy(dataBuffer, index, this.accountData, i, 8); //update our working copy of the account data Array.Copy(this.accountData, 0, pageData, 0, 32); } } } return(true); } }
/// <summary> /// Method main /// /// </summary> /// <param name="args"> /// </param> /// <exception cref="OneWireException"> </exception> /// <exception cref="OneWireIOException"> /// </exception> public static void Main1(string[] args) { byte[] sign_secret = null; byte[] auth_secret = null; // attempt to open the sha.properties file sha_properties = new Properties(); if (!sha_properties.loadLocalFile("sha.properties")) { Debug.WriteLine("loading default sha.properties!"); Assembly asm = typeof(SHADebitDemo.MainPage).GetTypeInfo().Assembly; sha_properties.loadResourceFile(asm, "SHADebitDemo.sha.properties"); } // ------------------------------------------------------------ // Instantiate coprocessor containers // ------------------------------------------------------------ SHAiButtonCopr copr = null; OneWireContainer18 copr18 = new OneWireContainer18(); //TODO copr18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false); copr18.SpeedCheck = false; // ------------------------------------------------------------ // Setup the adapter for the coprocessor // ------------------------------------------------------------ DSPortAdapter coprAdapter = null; string coprAdapterName = null, coprPort = null; try { coprAdapterName = sha_properties.getProperty("copr.adapter"); coprPort = sha_properties.getProperty("copr.port"); if (string.ReferenceEquals(coprPort, null) || string.ReferenceEquals(coprAdapterName, null)) { coprAdapter = OneWireAccessProvider.DefaultAdapter; } else { coprAdapter = OneWireAccessProvider.getAdapter(coprAdapterName, coprPort); } Debug.WriteLine("Coprocessor adapter loaded, adapter: " + coprAdapter.AdapterName + " port: " + coprAdapter.PortName); coprAdapter.adapterDetected(); coprAdapter.targetFamily(0x18); coprAdapter.beginExclusive(true); coprAdapter.reset(); coprAdapter.setSearchAllDevices(); coprAdapter.reset(); coprAdapter.putByte(0x3c); //TODO coprAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } catch (Exception e) { Debug.WriteLine("Error initializing coprocessor adapter"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } // --------------------------------------------------------- // Get the name of the coprocessor service file // --------------------------------------------------------- string filename = sha_properties.getProperty("copr.filename", "COPR.0"); bool next = false; bool vmSaveSecrets = true; string coprVMfilename = null; // ------------------------------------------------------------ // Find the coprocessor // ------------------------------------------------------------ if (sha_properties.getPropertyBoolean("copr.simulated.isSimulated", false)) { coprVMfilename = sha_properties.getProperty("copr.simulated.filename"); vmSaveSecrets = sha_properties.getPropertyBoolean("copr.simulated.saveSecrets", true); // --------------------------------------------------------- // Load emulated coprocessor // --------------------------------------------------------- Debug.WriteLine("Setting up simulated Copressor."); Debug.WriteLine("Would you like to emulate another coprocessor? (y)"); //if (IOHelper.readLine().ToUpper()[0] == 'Y') //{ // // OneWireContainer18 ibc = new OneWireContainer18(); // ibc.SpeedCheck = false; // try // { // next = coprAdapter.findFirstDevice(); // while (next && copr == null) // { // try // { // Debug.WriteLine(coprAdapter.AddressAsLong); // ibc.setupContainer(coprAdapter, coprAdapter.AddressAsLong); // copr = new SHAiButtonCopr(ibc, filename); // } // catch (Exception e) // { // Debug.WriteLine(e.ToString()); // Debug.Write(e.StackTrace); // } // next = coprAdapter.findNextDevice(); // } // } // catch (Exception) // { // ; // } // if (copr == null) // { // Debug.WriteLine("No coprocessor found to emulate"); // return; // } // Debug.WriteLine(""); // Debug.WriteLine("Emulating Coprocessor: " + ibc.AddressAsString); // Debug.WriteLine(""); // //now that we got all that, we need a signing secret and an authentication secret // Debug.WriteLine("How would you like to enter the signing secret (unlimited bytes)? "); // sign_secret = new byte[] { 0, 0, 0, 0 }; //TODO // IOHelper.writeBytes(sign_secret); // Debug.WriteLine(""); // Debug.WriteLine("How would you like to enter the authentication secret (unlimited bytes)? "); // auth_secret = new byte[] { 0, 0, 0, 0 }; //TODO // IOHelper.writeBytes(auth_secret); // Debug.WriteLine(""); // if (copr.DS1961Scompatible) // { // //reformat the auth_secret // auth_secret = SHAiButtonCopr.reformatFor1961S(auth_secret); // IOHelper.writeBytes(auth_secret); // } // Debug.WriteLine(""); // copr = new SHAiButtonCoprVM(ibc, filename, sign_secret, auth_secret); // ((SHAiButtonCoprVM)copr).save(coprVMfilename, true); // Debug.WriteLine(copr); // return; //} } //else { // --------------------------------------------------------- // Check for hardcoded coprocessor address // --------------------------------------------------------- byte[] coprAddress = sha_properties.getPropertyBytes("copr.address", null); long lookupID = 0, coprID = -1; if (coprAddress != null) { lookupID = com.dalsemi.onewire.utils.Address.toLong(coprAddress); Debug.Write("Looking for coprocessor: " + lookupID.ToString("x")); } // --------------------------------------------------------- // Find hardware coprocessor // --------------------------------------------------------- try { next = coprAdapter.findFirstDevice(); while (copr == null && next) { try { long tmpCoprID = coprAdapter.AddressAsLong; if (coprAddress == null || tmpCoprID == lookupID) { Debug.WriteLine("Loading coprocessor file: " + filename + " from device: " + tmpCoprID.ToString("x")); copr18.setupContainer(coprAdapter, tmpCoprID); //save coprocessor ID coprID = tmpCoprID; } } catch (Exception e) { Debug.WriteLine(e); } next = coprAdapter.findNextDevice(); } } catch (Exception) { ; } if (coprID == -1) { Debug.WriteLine("No Coprocessor found!"); return; } Debug.WriteLine("Setting up DS1963S as Coprocessor: " + com.dalsemi.onewire.utils.Address.ToString(copr18.Address)); } // Now that we've got a suitable button for creating a coprocessor, // let's ask the user for all the necessary paramters. Debug.Write("Enter the name of the coprocessor file (usually 'COPR') : "); byte[] coprname = { (byte)'C', (byte)'O', (byte)'P', (byte)'R' }; //com.dalsemi.onewire.utils.IOHelper.readBytesAsc(4, ' '); Debug.Write("Enter the file extension of the coprocessor file (0) : "); int coprext = 0; // com.dalsemi.onewire.utils.IOHelper.readInt(0); Debug.Write("Enter the name of the service file (4 characters) : "); byte[] name = { (byte)'S', (byte)'V', (byte)'C', (byte)'F' }; // com.dalsemi.onewire.utils.IOHelper.readBytesAsc(4, ' '); Debug.Write("Enter the file extension of the service file (102 for Money) : "); byte ext = 102; // (byte)com.dalsemi.onewire.utils.IOHelper.readInt(102); Debug.Write("Enter authentication page number (7) : "); int auth_page = 7; // com.dalsemi.onewire.utils.IOHelper.readInt(7); if (auth_page < 7) { Debug.WriteLine("Authentication page too low, default to 7"); auth_page = 7; } if (auth_page == 8) { Debug.WriteLine("Page already taken, default to 7"); auth_page = 7; } Debug.Write("Enter workspace page number (9) : "); int work_page = 9; //TODO com.dalsemi.onewire.utils.IOHelper.readInt(9); if (work_page < 7) { Debug.WriteLine("Workspace page too low, default to 9"); work_page = 9; } if ((work_page == 8) || (work_page == auth_page)) { Debug.WriteLine("Page already taken, default to 9"); work_page = 9; } Debug.Write("Enter version number (1) : "); int version = 1; //TODO com.dalsemi.onewire.utils.IOHelper.readInt(1); Debug.WriteLine("How would you like to enter the binding data (32 bytes)? "); byte[] bind_data = getBytes(32); Debug.WriteLine("How would you like to enter the binding code (7 bytes)? "); byte[] bind_code = getBytes(7); // This could be done on the button //java.util.Random random = new java.util.Random(); //random.nextBytes(chlg); // Need to know what the challenge is so that I can reproduce it! byte[] chlg = new byte[] { 0x00, 0x00, 0x00 }; Debug.WriteLine("Enter a human-readable provider name: "); string provider_name = com.dalsemi.onewire.utils.IOHelper.readLine(); Debug.WriteLine("Enter an initial signature in HEX (all 0' default): "); byte[] sig_ini = com.dalsemi.onewire.utils.IOHelper.readBytesHex(20, 0); Debug.WriteLine("Enter any additional text you would like store on the coprocessor: "); string aux_data = com.dalsemi.onewire.utils.IOHelper.readLine(); Debug.WriteLine("Enter an encryption code (0): "); int enc_code = com.dalsemi.onewire.utils.IOHelper.readInt(0); //now that we got all that, we need a signing secret and an authentication secret Debug.WriteLine("How would you like to enter the signing secret (unlimited bytes)? "); sign_secret = new byte[] { 0, 0, 0, 0 }; //TODO com.dalsemi.onewire.utils.IOHelper.writeBytes(sign_secret); Debug.WriteLine(""); Debug.WriteLine("How would you like to enter the authentication secret (unlimited bytes)? "); auth_secret = new byte[] { 0, 0, 0, 0 }; //TODO com.dalsemi.onewire.utils.IOHelper.writeBytes(auth_secret); Debug.WriteLine(""); Debug.WriteLine("Would you like to reformat the authentication secret for the 1961S? (y or n)"); string s = com.dalsemi.onewire.utils.IOHelper.readLine(); if (s.ToUpper()[0] == 'Y') { //reformat the auth_secret auth_secret = SHAiButtonCopr.reformatFor1961S(auth_secret); com.dalsemi.onewire.utils.IOHelper.writeLine("authentication secret"); com.dalsemi.onewire.utils.IOHelper.writeBytes(auth_secret); com.dalsemi.onewire.utils.IOHelper.writeLine(); } // signing page must be 8, using secret 0 int sign_page = 8; if (!string.ReferenceEquals(coprVMfilename, null)) { byte[] RomID = new byte[] { 0x18, 0x20, 0xAF, 0x02, 0x00, 0x00, 0x00, 0xE7 }; RomID = sha_properties.getPropertyBytes("copr.simulated.address", RomID); copr = new SHAiButtonCoprVM(RomID, sign_page, auth_page, work_page, version, enc_code, ext, name, Encoding.UTF8.GetBytes(provider_name), bind_data, bind_code, Encoding.UTF8.GetBytes(aux_data), sig_ini, chlg, sign_secret, auth_secret); ((SHAiButtonCoprVM)copr).save(coprVMfilename, vmSaveSecrets); } else { string coprFilename = coprname.ToString() + "." + coprext; // initialize this OneWireContainer18 as a valid coprocessor copr = new SHAiButtonCopr(copr18, coprFilename, true, sign_page, auth_page, work_page, version, enc_code, ext, name, Encoding.UTF8.GetBytes(provider_name), bind_data, bind_code, Encoding.UTF8.GetBytes(aux_data), sig_ini, chlg, sign_secret, auth_secret); } Debug.WriteLine("Initialized Coprocessor"); Debug.WriteLine(copr.ToString()); Debug.WriteLine("done"); }
/// <summary> /// SHADebitUnsigned constructor. <code>copr</code> is the SHAiButtonCopr /// that is used to perform this transaction. After saving a /// reference to the SHA coprocessor, this constructor resets all /// parameters for this type of transaction to their default values. /// </summary> /// <param name="copr"> The coprocessor used for authentication and data /// signing in this transaction. </param> public SHADebitUnsigned(SHAiButtonCopr copr) : base(copr) { resetParameters(); }
/// <summary> /// SHADebitUnsigned constructor. <code>copr</code> is the SHAiButtonCopr /// that is used to perform this transaction. After saving a /// reference to the SHA coprocessor, this constructor resets all /// parameters for this type of transaction to their default values. /// </summary> /// <param name="copr"> The coprocessor used for authentication and data /// signing in this transaction. </param> public SHADebitUnsigned(SHAiButtonCopr copr, int initialAmount, int debitAmount) : base(copr) { this.initialAmount = initialAmount; this.debitAmount = debitAmount; }
public static void Main0(string[] args) { //coprocessor long coprID = 0; long lookupID = 0; bool next; // ------------------------------------------------------------ // Check for valid path to sha.properties file on the cmd line. // ------------------------------------------------------------ for (int i = 0; i < args.Length; i++) { string arg = args[i].ToUpper(); if (arg.IndexOf("-P", StringComparison.Ordinal) == 0) { string sha_props_path; if (arg.Length == 2) { sha_props_path = args[++i]; } else { sha_props_path = arg.Substring(2); } // attempt to open the sha.properties file sha_properties = new Properties(); if (!sha_properties.loadLocalFile("sha.properties")) { Debug.WriteLine("loading default sha.properties!"); Assembly asm = typeof(SHADebitDemo.MainPage).GetTypeInfo().Assembly; sha_properties.loadResourceFile(asm, "SHADebitDemo.sha.properties"); } } else { printUsageString(); return; } } // ------------------------------------------------------------ // Instantiate coprocessor containers // ------------------------------------------------------------ SHAiButtonCopr copr = null; OneWireContainer18 copr18 = new OneWireContainer18(); copr18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false); copr18.SpeedCheck = false; // ------------------------------------------------------------ // Setup the adapter for the coprocessor // ------------------------------------------------------------ DSPortAdapter coprAdapter = null; string coprAdapterName = null, coprPort = null; try { coprAdapterName = sha_properties.getProperty("copr.adapter"); coprPort = sha_properties.getProperty("copr.port"); if (string.ReferenceEquals(coprPort, null) || string.ReferenceEquals(coprAdapterName, null)) { coprAdapter = OneWireAccessProvider.DefaultAdapter; } else { coprAdapter = OneWireAccessProvider.getAdapter(coprAdapterName, coprPort); } IOHelper.writeLine("Coprocessor adapter loaded, adapter: " + coprAdapter.AdapterName + " port: " + coprAdapter.PortName); coprAdapter.adapterDetected(); coprAdapter.targetFamily(0x18); coprAdapter.beginExclusive(true); coprAdapter.reset(); coprAdapter.setSearchAllDevices(); coprAdapter.reset(); coprAdapter.putByte(0x3c); coprAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } catch (Exception e) { IOHelper.writeLine("Error initializing coprocessor adapter"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } // ------------------------------------------------------------ // Find the coprocessor // ------------------------------------------------------------ if (sha_properties.getPropertyBoolean("copr.simulated.isSimulated", false)) { string coprVMfilename = sha_properties.getProperty("copr.simulated.filename"); // --------------------------------------------------------- // Load emulated coprocessor // --------------------------------------------------------- try { copr = new SHAiButtonCoprVM(coprVMfilename); } catch (Exception e) { IOHelper.writeLine("Invalid Coprocessor Data File"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } } else { // --------------------------------------------------------- // Get the name of the coprocessor service file // --------------------------------------------------------- string filename = sha_properties.getProperty("copr.filename", "COPR.0"); // --------------------------------------------------------- // Check for hardcoded coprocessor address // --------------------------------------------------------- byte[] coprAddress = sha_properties.getPropertyBytes("copr.address", null); lookupID = 0; if (coprAddress != null) { lookupID = Address.toLong(coprAddress); IOHelper.write("Looking for coprocessor: "); IOHelper.writeLineHex(lookupID); } // --------------------------------------------------------- // Find hardware coprocessor // --------------------------------------------------------- try { next = coprAdapter.findFirstDevice(); while (copr == null && next) { try { long tmpCoprID = coprAdapter.AddressAsLong; if (coprAddress == null || tmpCoprID == lookupID) { IOHelper.write("Loading coprocessor file: " + filename + " from device: "); IOHelper.writeLineHex(tmpCoprID); copr18.setupContainer(coprAdapter, tmpCoprID); copr = new SHAiButtonCopr(copr18, filename); //save coprocessor ID coprID = tmpCoprID; } } catch (Exception e) { IOHelper.writeLine(e); } next = coprAdapter.findNextDevice(); } } catch (Exception) { ; } } if (copr == null) { IOHelper.writeLine("No Coprocessor found!"); return; } IOHelper.writeLine(copr); IOHelper.writeLine(); // ------------------------------------------------------------ // Create the SHADebit transaction types // ------------------------------------------------------------ //stores DS1963S transaction type SHATransaction debit18 = null; string transType18 = sha_properties.getProperty("transaction.type", "signed"); transType18 = transType18.ToLower(); if (transType18.Equals("signed")) { debit18 = new SHADebit(copr, 10000, 50); } else { debit18 = new SHADebitUnsigned(copr, 10000, 50); } //stores DS1961S transaction type SHATransaction debit33 = null; string transType33 = sha_properties.getProperty("ds1961s.transaction.type", "unsigned"); transType33 = transType33.ToLower(); if (transType33.Equals(transType18)) { debit33 = debit18; } else if (transType33.IndexOf("unsigned", StringComparison.Ordinal) >= 0) { //everything is seemless if you use the authentication secret //as the button's secret. debit33 = new SHADebitUnsigned(copr, 10000, 50); } else { //if the 1961S uses the authentication secret, //you'll need another button for generating the //write authorization MAC, but you can share the //1963S debit code for signed data. debit33 = new SHADebit(copr, 10000, 50); } //Transaction super class, swap variable SHATransaction trans = null; // ------------------------------------------------------------ // Get the write-authorization coprocessor for ds1961S // ------------------------------------------------------------ //first get the write authorization adapter DSPortAdapter authAdapter = null; string authAdapterName = null, authPort = null; try { authAdapterName = sha_properties.getProperty("ds1961s.copr.adapter"); authPort = sha_properties.getProperty("ds1961s.copr.port"); if (string.ReferenceEquals(authAdapterName, null) || string.ReferenceEquals(authAdapterName, null)) { if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null)) { authAdapter = OneWireAccessProvider.DefaultAdapter; } else { authAdapter = coprAdapter; } } else if (coprAdapterName.Equals(authAdapterName) && coprPort.Equals(authPort)) { authAdapter = coprAdapter; } else { authAdapter = OneWireAccessProvider.getAdapter(authAdapterName, authPort); } IOHelper.writeLine("Write-Authorization adapter loaded, adapter: " + authAdapter.AdapterName + " port: " + authAdapter.PortName); byte[] families = new byte[] { 0x18 }; authAdapter.adapterDetected(); authAdapter.targetFamily(families); authAdapter.beginExclusive(false); authAdapter.reset(); authAdapter.setSearchAllDevices(); authAdapter.reset(); authAdapter.putByte(0x3c); authAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } catch (Exception e) { IOHelper.writeLine("Error initializing write-authorization adapter."); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } //now find the coprocessor SHAiButtonCopr authCopr = null; // ----------------------------------------------------------- // Check for hardcoded write-authorizaton coprocessor address // ----------------------------------------------------------- byte[] authCoprAddress = sha_properties.getPropertyBytes("ds1961s.copr.address", null); lookupID = 0; if (authCoprAddress != null) { lookupID = Address.toLong(authCoprAddress); IOHelper.write("Looking for coprocessor: "); IOHelper.writeLineHex(lookupID); } if (lookupID == coprID) { //it's the same as the standard coprocessor. //valid only if we're not signing the data authCopr = copr; } else { // --------------------------------------------------------- // Find write-authorization coprocessor // --------------------------------------------------------- try { string filename = sha_properties.getProperty("ds1961s.copr.filename", "COPR.1"); OneWireContainer18 auth18 = new OneWireContainer18(); auth18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false); auth18.SpeedCheck = false; next = authAdapter.findFirstDevice(); while (authCopr == null && next) { try { long tmpAuthID = authAdapter.AddressAsLong; if (authCoprAddress == null || tmpAuthID == lookupID) { IOHelper.write("Loading coprocessor file: " + filename + " from device: "); IOHelper.writeLineHex(tmpAuthID); auth18.setupContainer(authAdapter, tmpAuthID); authCopr = new SHAiButtonCopr(auth18, filename); } } catch (Exception e) { IOHelper.writeLine(e); } next = authAdapter.findNextDevice(); } } catch (Exception e) { IOHelper.writeLine(e); } if (authCopr == null) { IOHelper.writeLine("no write-authorization coprocessor found"); if (copr is SHAiButtonCoprVM) { authCopr = copr; IOHelper.writeLine("Re-using SHAiButtonCoprVM"); } } } IOHelper.writeLine(authCopr); IOHelper.writeLine(); // ------------------------------------------------------------ // Create the User Buttons objects // ------------------------------------------------------------ //holds DS1963S user buttons SHAiButtonUser18 user18 = new SHAiButtonUser18(copr); OneWireContainer18 owc18 = new OneWireContainer18(); owc18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false); owc18.SpeedCheck = false; //holds DS1961S user buttons SHAiButtonUser33 user33 = new SHAiButtonUser33(copr, authCopr); OneWireContainer33 owc33 = new OneWireContainer33(); owc33.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false); //owc33.setSpeedCheck(false); //Holds generic user type, swap variable SHAiButtonUser user = null; // ------------------------------------------------------------ // Get the adapter for the user // ------------------------------------------------------------ DSPortAdapter adapter = null; string userAdapterName = null, userPort = null; try { userAdapterName = sha_properties.getProperty("user.adapter"); userPort = sha_properties.getProperty("user.port"); if (string.ReferenceEquals(userPort, null) || string.ReferenceEquals(userAdapterName, null)) { if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null)) { if (!string.ReferenceEquals(authAdapterName, null) && !string.ReferenceEquals(authPort, null)) { adapter = OneWireAccessProvider.DefaultAdapter; } else { adapter = authAdapter; } } else { adapter = coprAdapter; } } else if (userAdapterName.Equals(authAdapterName) && userPort.Equals(authPort)) { adapter = authAdapter; } else if (userAdapterName.Equals(coprAdapterName) && userPort.Equals(coprPort)) { adapter = coprAdapter; } else { adapter = OneWireAccessProvider.getAdapter(userAdapterName, userPort); } IOHelper.writeLine("User adapter loaded, adapter: " + adapter.AdapterName + " port: " + adapter.PortName); byte[] families = new byte[] { 0x18, 0x33 }; families = sha_properties.getPropertyBytes("transaction.familyCodes", families); IOHelper.write("Supporting the following family codes: "); IOHelper.writeBytesHex(" ", families, 0, families.Length); adapter.adapterDetected(); adapter.targetFamily(families); adapter.beginExclusive(true); adapter.reset(); adapter.setSearchAllDevices(); adapter.reset(); adapter.putByte(0x3c); adapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } catch (Exception e) { IOHelper.writeLine("Error initializing user adapter."); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); return; } //timing variables long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0; //address of current device byte[] address = new byte[8]; //result of findNextDevice/findFirstDevice next = false; //holds list of known buttons long[] buttons = new long[16]; //count of how many buttons are in buttons array int index = 0; //temporary id representing current button long tmpID = -1; //array of buttons looked at during this search long[] temp = new long[16]; //count of how many buttons in temp array int cIndex = 0; //flag indiciating whether or not temp array represents //the complete list of buttons on the network. bool wholeList = false; Debug.WriteLine(""); Debug.WriteLine(""); Debug.WriteLine("**********************************************************"); Debug.WriteLine(" Beginning The Main Application Loop (Search & Debit)"); Debug.WriteLine(" Press Enter to Exit Application"); Debug.WriteLine("**********************************************************"); Debug.WriteLine(""); //application infinite loop for (bool applicationFinished = false; !applicationFinished;) { try { if (coprAdapter != adapter) { //in case coprocessor communication got hosed, make sure //the coprocessor adapter is in overdrive coprAdapter.Speed = DSPortAdapter.SPEED_REGULAR; coprAdapter.reset(); coprAdapter.putByte(0x3c); //overdrive skip rom coprAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } if (authAdapter != coprAdapter && authAdapter != adapter) { //in case coprocessor communication with the write- //authorization coprocessor got hosed, make sure //the coprocessor adapter is in overdrive authAdapter.Speed = DSPortAdapter.SPEED_REGULAR; authAdapter.reset(); authAdapter.putByte(0x3c); //overdrive skip rom authAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; } } catch (Exception) { ; } // --------------------------------------------------------- // Search for new buttons // --------------------------------------------------------- bool buttonSearch = true; //Button search loop, waits forever until new button appears. while (buttonSearch && !applicationFinished) { wholeList = false; t0 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; try { //Go into overdrive adapter.Speed = DSPortAdapter.SPEED_REGULAR; adapter.reset(); adapter.putByte(0x3c); //overdrive skip rom adapter.Speed = DSPortAdapter.SPEED_OVERDRIVE; // Begin search for new buttons if (!next) { wholeList = true; next = adapter.findFirstDevice(); } for (tmpID = -1, cIndex = 0; next && (tmpID == -1); next = adapter.findNextDevice()) { tmpID = adapter.AddressAsLong; if (tmpID != coprID) { temp[cIndex++] = tmpID; for (int i = 0; i < index; i++) { if (buttons[i] == tmpID) { //been here all along tmpID = -1; i = index; } } if (tmpID != -1) { //populate address array adapter.getAddress(address); } } else { tmpID = -1; } } //if we found a new button if (tmpID != -1) { //add it to the main list buttons[index++] = tmpID; //quite searching, we got one! buttonSearch = false; } else if (wholeList) { //went through whole list with nothing new //update the main list of buttons buttons = temp; index = cIndex; //if user presses the enter key, we'll quit and clean up nicely //TODO applicationFinished = (System.in.available() > 0); } } catch (Exception e) { if (DEBUG) { IOHelper.writeLine("adapter hiccup while searching"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); } } } if (applicationFinished) { continue; } // --------------------------------------------------------- // Perform the transaction // --------------------------------------------------------- try { t1 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; //de-ref the user user = null; //check for button family code if ((tmpID & 0x18) == (byte)0x18) { //get transactions for ds1963s trans = debit18; owc18.setupContainer(adapter, address); if (user18.setiButton18(owc18)) { user = user18; } } else if ((tmpID & 0x33) == (byte)0x33) { //get transactions for 1961S trans = debit33; owc33.setupContainer(adapter, address); if (user33.setiButton33(owc33)) { user = user33; } } if (user != null) { Debug.WriteLine(""); Debug.WriteLine(user.ToString()); t2 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; if (trans.verifyUser(user)) { t3 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; if (trans.verifyTransactionData(user)) { t4 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; if (!trans.executeTransaction(user, true)) { Debug.WriteLine("Execute Transaction Failed"); } t5 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond; Debug.WriteLine(" Debit Amount: $00.50"); Debug.Write("User's balance: $"); int balance = trans.getParameter(SHADebit.USER_BALANCE); Debug.WriteLine(com.dalsemi.onewire.utils.Convert.ToString(balance / 100d, 2)); } else { Debug.WriteLine("Verify Transaction Data Failed"); } } else { Debug.WriteLine("Verify User Authentication Failed"); } } else { Debug.WriteLine("Not a SHA user of this service"); } Debug.Write("Total time: "); Debug.WriteLine(t5 - t0); Debug.Write("Executing transaction took: "); Debug.WriteLine(t5 - t4); Debug.Write("Verifying data took: "); Debug.WriteLine(t4 - t3); Debug.Write("Verifying user took: "); Debug.WriteLine(t3 - t2); Debug.Write("Loading user data took: "); Debug.WriteLine(t2 - t1); Debug.Write("Finding user took: "); Debug.WriteLine(t1 - t0); //report all errors if (trans.LastError != 0) { IOHelper.writeLine("Last Error Code: "); IOHelper.writeLine(trans.LastError); if (trans.LastError == SHATransaction.COPROCESSOR_FAILURE) { IOHelper.writeLine("COPR Error Code: "); IOHelper.writeLine(copr.LastError); } } } catch (Exception e) { Debug.WriteLine("Transaction failed!"); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); } } // -------------------------------------------------------------- // Some Friendly Cleanup // -------------------------------------------------------------- adapter.endExclusive(); coprAdapter.endExclusive(); authAdapter.endExclusive(); }
/// <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); }
/// <summary> /// SHADebit constructor. <code>copr</code> is the SHAiButtonCopr /// that is used to perform this transaction. After saving a /// reference to the SHA coprocessor, this constructor resets all /// parameters for this type of transaction to their default values. /// </summary> /// <param name="copr"> The coprocessor used for authentication and data /// signing in this transaction. </param> /// <param name="extra_data"> The 7 bytes of extra data to be used instead /// of the balance. </param> /// <param name="len"> The len, 7 or less of the data. It is 0 padded. </param> public SHASoftAuth(SHAiButtonCopr copr, byte[] extra_data, int len) : base(copr) { Array.Copy(extra_data, 0, this.master_ver_data, 0, len); }
/// <summary> /// SHADebit constructor. <code>copr</code> is the SHAiButtonCopr /// that is used to perform this transaction. After saving a /// reference to the SHA coprocessor, this constructor resets all /// parameters for this type of transaction to their default values. /// </summary> /// <param name="copr"> The coprocessor used for authentication and data /// signing in this transaction. </param> public SHASoftAuth(SHAiButtonCopr copr) : base(copr) { resetParameters(); }
/// <summary> /// <P>Creates a new SHATransaction, ensuring that reference to /// the coprocessor is saved and the errors are cleared.</P> /// </summary> protected internal SHATransaction(SHAiButtonCopr copr) { this.copr = copr; this.lastError = 0; }