/** * Modifies this SHA iButton so that it refers to another DS1963S container. This function only * copies the reference to the OneWireContainer, copes the reference to it's 1-Wire address, and * then asserts that the iButton contains a valid acccount info file associated with the system. * * @param owc The <code>OneWireContainer18</code> this object will refer to. * @return <code>true</code> if a valid account service file exists on this <code> * OneWireContainer18</code>. * @throws 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'. * @throws OneWireException on a communication or setup error with the 1-Wire adapter */ public synchronized boolean setiButton18(OneWireContainer18 owc) throws OneWireException, OneWireIOException { // hold container reference this.ibc = owc; // and address this.address = owc.getAddress(); // getAddress() doesn't malloc! // clear account information this.accountPageNumber = -1; // make sure account info is properly setup if (!checkAccountPageInfo(owc)) return false; // setup the fullBindCode with rest of info this.fullBindCode[4] = (byte) this.accountPageNumber; System.arraycopy(this.address, 0, this.fullBindCode, 5, 7); // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if (DEBUG) { IOHelper.writeLine("------------------------------------"); IOHelper.writeLine("Loaded User"); IOHelper.writeLine("address"); IOHelper.writeBytesHex(owc.getAddress()); IOHelper.writeLine("accountPageNumber: " + accountPageNumber); IOHelper.writeLine("serviceFilename: " + strServiceFilename); IOHelper.writeLine("------------------------------------"); } // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ return true; }
/** * 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. * * @param coprBindData The Coprocessor Bind Data, used to create a unique secret for this user * token. * @param coprBindCode The Coprocessor Bind Code without the user-specific information, used to * create a unique secret for this user token. * @param fileName The file name for the account info. * @param fileNameExt The file extenstion for the account info * @param owc The DS1963S iButton that this object will refer to. * @param formatDevice If <code>true</code>, the TMEX filesystem will be formatted before the * account service file is created. * @param authSecret The master authentication secret for the systm. * @throws 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'. * @throws OneWireException on a communication or setup error with the 1-Wire adapter * @see #SHAiButtonUser18(SHAiButtonCopr,OneWireContainer18) * @see #SHAiButtonUser18(SHAiButtonCopr) */ public SHAiButtonUser18( byte[] coprBindData, byte[] coprBindCode, byte[] fileName, int fileNameExt, OneWireContainer18 owc, boolean formatDevice, byte[] authSecret) throws OneWireException, OneWireIOException { // hold container reference this.ibc = owc; // and address this.address = owc.getAddress(); System.arraycopy(fileName, 0, this.serviceFile, 0, 4); // create string representation of service filename this.strServiceFilename = new String(fileName) + "." + (int) fileNameExt; if (!createServiceFile(owc, strServiceFilename, formatDevice)) throw new OneWireException("Failed to create service file."); // save a copy of the binding code System.arraycopy(coprBindCode, 0, this.fullBindCode, 0, 7); System.arraycopy(this.fullBindCode, 4, this.fullBindCode, 12, 3); // setup the fullBindCode with rest of info this.fullBindCode[4] = (byte) this.accountPageNumber; System.arraycopy(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, coprBindData, 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.getAddress()); IOHelper.writeLine("serviceFilename: " + strServiceFilename); IOHelper.writeLine("accountPageNumber: " + accountPageNumber); IOHelper.writeLine("authSecret"); IOHelper.writeBytesHex(authSecret); IOHelper.writeLine("bindCode"); IOHelper.writeBytesHex(coprBindCode); IOHelper.writeLine("------------------------------------"); } // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ }
/** * 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. * * @param dataBuffer the buffer to copy the account data from * @param offset the index into the buffer where copying should begin * @return whether or not the data write succeeded * @throws 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'. * @throws OneWireException on a communication or setup error with the 1-Wire adapter */ public synchronized boolean writeAccountData(byte[] dataBuffer, int offset) throws OneWireException, OneWireIOException { // init local vars OneWireContainer18 ibcL = this.ibc; // make sure account info is properly setup if (!checkAccountPageInfo(ibcL)) return false; int numBytes = Math.min(32, dataBuffer.length - offset); System.arraycopy(dataBuffer, offset, this.accountData, 0, numBytes); if (ibcL.writeDataPage(this.accountPageNumber, this.accountData)) { if (this.writeCycleCounter >= 0) this.writeCycleCounter++; return true; } // if write failed, we don't know what the write cycle counter is this.writeCycleCounter = -1; // and this cache should be marked dirty this.accountData[0] = 0; return false; }
/** * Reads the account data off the SHAiButton using a standard READ command. First, this function * asserts that the account page number is known as well as the length of the account file. The 32 * byte account data page is copied into dataBuffer starting at the given offset. * * @param dataBuffer the buffer to copy the account data into * @param offset the index into the buffer where copying should begin * @return whether or not the read was successful * @throws 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'. * @throws OneWireException on a communication or setup error with the 1-Wire adapter */ public synchronized boolean readAccountData(byte[] dataBuffer, int offset) throws OneWireException, OneWireIOException { // init local vars OneWireContainer18 ibcL = this.ibc; // make sure account info is properly setup if (!checkAccountPageInfo(ibcL)) { return false; } // if the cache is empty if (this.accountData[0] == 0) { // read directly into local cache ibcL.readMemoryPage(this.accountPageNumber, this.accountData, 0); } // copy cached data into user's buffer System.arraycopy(this.accountData, 0, dataBuffer, offset, 32); // had to work, right? return true; }
/** * Reads the account data off the SHAiButton using a READ_AUTHENTICATE command. First, this * function asserts that the account page number is known as well as the length of the account * file. Then it copies the 3 byte challenge to the scratchpad before sending the command for * READ_AUTHENTICATE. The 32 byte account data page is copied into dataBuffer starting at * dataStart. * * <p>In addition to the account data, this function also returns a calculated MAC. The MAC * requires 20 bytes after the start index. The return value is the write cycle counter value for * the account data page * * <p> * * @param chlg the buffer containing a 3-byte random challenge. * @param chlgStart the index into the buffer where the 3 byte challenge begins. * @param dataBuffer the buffer to copy the account data into * @param dataStart the index into the buffer where copying should begin * @param mac the buffer to copy the resulting Message Authentication Code * @param macStart the index into the mac buffer to start copying * @return the value of the write cycle counter for the page * @throws 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'. * @throws OneWireException on a communication or setup error with the 1-Wire adapter */ public synchronized int readAccountData( byte[] chlg, int chlgStart, byte[] dataBuffer, int dataStart, byte[] mac, int macStart) throws OneWireException, OneWireIOException { // init local variables OneWireContainer18 ibcL = this.ibc; byte[] rawData = this.readAccountData_rawData; byte[] scratchpad = this.readAccountData_scratchpad; // make sure account info is properly setup if (this.accountPageNumber < 0) { // user not setup return -1; } // copy challenge into scratchpad buffer System.arraycopy(chlg, 0, scratchpad, 20, 3); if (ibcL.eraseScratchPad(this.accountPageNumber)) { // send 1 byte RESUME, instead of 9 byte SELECT ibcL.useResume(true); // write the challenge to the device scratchpad if (ibcL.writeScratchPad(this.accountPageNumber, 0, scratchpad, 0, 32)) { // reads 42 bytes = 32 bytes of page data // + 4 bytes page counter // + 4 bytes secret counter // + 2 bytes CRC boolean readOK = ibcL.readAuthenticatedPage(this.accountPageNumber, rawData, 0); // read the scratchpad for mac int len = ibcL.readScratchPad(scratchpad, 0); // disable RESUME ibcL.useResume(false); if ((!readOK) || (len < 0)) { // read authenticate failed return -1; } // get the value of the write cycle counter int wcc = (rawData[35] & 0x0ff); wcc = (wcc << 8) | (rawData[34] & 0x0ff); wcc = (wcc << 8) | (rawData[33] & 0x0ff); wcc = (wcc << 8) | (rawData[32] & 0x0ff); // put the accountData in our local cache System.arraycopy(rawData, 0, this.accountData, 0, 32); // put the account data into return buffer System.arraycopy(rawData, 0, dataBuffer, dataStart, 32); // copy the mac into the return buffer System.arraycopy(scratchpad, 8, mac, macStart, 20); // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if (DEBUG) { IOHelper.writeLine("----------------------------------------------------------"); IOHelper.writeLine("User's ReadAuthPage"); IOHelper.write("address: "); IOHelper.writeBytesHex(this.address); IOHelper.writeLine("speed: " + this.ibc.getAdapter().getSpeed()); IOHelper.writeLine("RawData: "); IOHelper.writeBytesHex(rawData); IOHelper.writeLine("mac: "); IOHelper.writeBytesHex(mac, macStart, 20); IOHelper.writeLine("wcc: " + wcc); IOHelper.writeLine("----------------------------------------------------------"); } // \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // cache the write cycle counter this.writeCycleCounter = wcc; return wcc; } // write scratchpad failed return -1; } // erase scratchpad failed return -1; }