📄 shaibuttoncoprvm.java
字号:
* from this page but can be copied into another secret. User iButtons should * bind to the same page the secret was installed on. Coprocessor iButtons * must copy to a new secret to preserve the general system authentication * secret.</p> * * <p>The binding should be either 7 bytes long or 15 bytes long. * A 15-length <code>byte</code> array is unaltered and placed in the scratchpad * for the binding. A 7-length <code>byte</code> array is combined with the page * number and DS1963S unique address and then placed in the scratchpad. * Coprocessors should use a pre-formatted 15-length <code>byte</code> array. * User iButtons should let the method format for them (i.e. * use the 7-length <code>byte</code> array option).</p> * * @param page the page number that has the master secret already installed * @param bind_data 32 bytes of binding data used to bind the iButton to the system * @param bind_code the 7-byte or 15-byte binding code * @param secret_number secret number to copy the resulting secret to * * @return <code>true</code> if successful * * @see #installMasterSecret(int,byte[],int) */ public synchronized boolean bindSecretToiButton (int pageNum, byte[] bindData, byte[] bindCode, int secretNum) { //local vars byte[] scratchpad = this.bindSecretToiButton_scratchpad; //write the bind_code to the scratchpad if(bindCode.length==7) { System.arraycopy(bindCode,0,scratchpad,8,4); scratchpad[12] = (byte)pageNum; System.arraycopy(this.address,0,scratchpad,13,7); System.arraycopy(bindCode,4,scratchpad,20,3); } else { System.arraycopy(bindCode, 0, scratchpad, 8, (bindCode.length>15 ? 15 : bindCode.length)); } //compute the MAC if(!SHAFunction(OneWireContainer18.COMPUTE_NEXT_SECRET, secretPage[pageNum&7], bindData, scratchpad, null, pageNum, 0)) return false; //install the secret System.arraycopy(scratchpad,0,secretPage[secretNum&7],0,8); return true; } /** * <p>Installs a secret on this virtual DS1963S. The secret is written in partial phrases * of 47 bytes (32 bytes to a memory page, 15 bytes to the scratchpad) and * is cumulative until the entire secret is processed. Secrets are associated * with a page number. See the datasheet for more information on this * association.</p> * * <p>In most cases, <code>page</code> should be equal to <code>secret_number</code> * or <code>secret_number+8</code>, based on the association of secrets and page numbers. * A secret is 8 bytes and there are 8 secrets. These 8 secrets are associated with the * first 16 pages of memory.</p> * * <p>On TINI, this method will be slightly faster if the secret's length is divisible by 47. * However, since secret key generation is a part of initialization, it is probably * not necessary.</p> * * @param page the page number used to write the partial secrets to * @param secret the entire secret to be installed * @param secret_number the secret 'page' to use (0 - 7) * * @return <code>true</code> if successful * * @see #bindSecretToiButton(int,byte[],byte[],int) */ public boolean installMasterSecret(int pageNum, byte[] secret, int secretNum) { //47 is a magic number here because every time a partial secret //is to be computed, 32 bytes goes in the page and 15 goes in //the scratchpad, so it's going to be easier in the computations //if i know the input buffer length is divisible by 47 if (secret.length == 0) return false; byte[] input_secret = null; int secret_mod_length = secret.length % 47; if (secret_mod_length == 0) //if the length of the secret is divisible by 47 input_secret = secret; else { /* i figure in the case where secret is not divisible by 47 it will be quicker to just create a new array once and copy the data in, rather than on every partial secret calculation do bounds checking */ input_secret = new byte [secret.length + (47 - secret_mod_length)]; System.arraycopy(secret, 0, input_secret, 0, secret.length); } //the current offset into the input_secret buffer secretNum = secretNum&7; int offset = 0; byte cmd = OneWireContainer18.COMPUTE_FIRST_SECRET; byte[] scratchpad = new byte[32]; byte[] dataPage = new byte[32]; while (offset < input_secret.length) { for(int i=0; i<32; i++) scratchpad[i] = (byte)0x0FF; System.arraycopy(input_secret,offset,dataPage,0,32); System.arraycopy(input_secret,offset+32,scratchpad,8,15); if(!SHAFunction(cmd, secretPage[pageNum&7], dataPage, scratchpad, null, signPageNumber, 0)) { return false; } //install the secret System.arraycopy(scratchpad,0,secretPage[secretNum],0,8); offset += 47; cmd = OneWireContainer18.COMPUTE_NEXT_SECRET; } return true; } /** * <p>Performs one of the DS1963S's cryptographic functions on this * virtual SHA iButton. See the datasheet for more information on * these functions.</p> * * <p>Valid parameters for the <code>function</code> argument are: * <ul> * <li> COMPUTE_FIRST_SECRET </li> * <li> COMPUTE_NEXT_SECRET </li> * <li> VALIDATE_DATA_PAGE </li> * <li> SIGN_DATA_PAGE </li> * <li> COMPUTE_CHALLENGE </li> * <li> AUTH_HOST </li> * </ul></p> * * @param function the SHA function code * @param shaSecret the secret used in SHA caclulation * @param shaPage the 32-byte page used in SHA caculation * @param scratchpad the 32-byte scratchpad data used in SHA caculation. * MAC is returned in this buffer starting at offset 8, unless * the function is COMPUTE_FIRST_SECRET or COMPUTE_NEXT_SECRET, * when the 4-byte parts E and D are repeated throughout the * scratchpad, starting at offset zero. * @param romID 1-Wire address. Only necessary for a * READ_AUTHENTICATED_PAGE command and COMPUTE_CHALLENGE command. * @param pageNum the page number on which the shaPage resides. only * necessary for a READ_AUTHENTICATED_PAGE command and * COMPUTE_CHALLENGE command. * @param writeCycleCounter the counter is only necessary for a * READ_AUTHENTICATED_PAGE command and COMPUTE_CHALLENGE command. * * @return <code>true</code> if the function successfully completed, * <code>false</code> if the operation failed or if invalid * command. * */ private synchronized boolean SHAFunction (byte function, byte[] shaSecret, byte[] shaPage, byte[] scratchpad, byte[] romID, int pageNum, int writeCycleCounter) { //offset for location in scratchpad to copy the MAC int offset = 8; //byte used for the M-X control bits //Since never matching, I assume M bit is never set... //but I'm not confident that won't change if more functionality //is added to this class. byte shaMX = 0x00; switch(function) { //Compute first secret, compute next secret, validate and sign data page case OneWireContainer18.COMPUTE_FIRST_SECRET: shaSecret = NullSecret; case OneWireContainer18.COMPUTE_NEXT_SECRET: //starts copying at location zero, for secret placement. //secret is repeated 4 times in scratchpad. offset = 0; case OneWireContainer18.VALIDATE_DATA_PAGE: case OneWireContainer18.SIGN_DATA_PAGE: //M-X-P byte scratchpad[12] = (byte)((scratchpad[12]&0x3F)|(shaMX&0xC0)); break; //Authenticate host case OneWireContainer18.AUTH_HOST: //for authenticate host, X bit is set. shaMX |= 0x40; //M-X-P byte scratchpad[12] = (byte)((scratchpad[12]&0x3F)|(shaMX&0xC0)); break; //compute challenge and read authenticated page case OneWireContainer18.COMPUTE_CHALLENGE: //for Compute_Challenge, X bit is set. shaMX |= 0x40; case OneWireContainer18.READ_AUTHENTICATED_PAGE: //place the write cycle counter into the scratchpad scratchpad[8] = (byte)(writeCycleCounter&0x0FF); scratchpad[9] = (byte)((writeCycleCounter>>>8)&0x0FF); scratchpad[10] = (byte)((writeCycleCounter>>>16)&0x0FF); scratchpad[11] = (byte)((writeCycleCounter>>>24)&0x0FF); //M-X-P byte scratchpad[12] = (byte)((pageNum&0x0F)|(shaMX&0xC0)); //place the RomID into the scratchpad System.arraycopy(romID,0,scratchpad,13,7); break; //Bad function input, can't perform SHA. default: return false; } //Set up the 64 byte buffer for computing the digest. System.arraycopy(shaSecret,0,digestBuff,0,4); System.arraycopy(shaPage,0,digestBuff,4,32); System.arraycopy(scratchpad,8,digestBuff,36,12); System.arraycopy(shaSecret,4,digestBuff,48,4); System.arraycopy(scratchpad,20,digestBuff,52,3); //init. digest buffer padding digestBuff[55] = (byte)0x80; for(int i=56; i<62; i++) digestBuff[i] = (byte)0x00; digestBuff[62] = (byte)0x01; digestBuff[63] = (byte)0xB8; //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if(DEBUG) { IOHelper.writeLine("------------------------------------------------------------"); if(function==OneWireContainer18.VALIDATE_DATA_PAGE) IOHelper.writeLine("Validating data page"); else if(function==OneWireContainer18.AUTH_HOST) IOHelper.writeLine("Authenticating Host"); else if(function==OneWireContainer18.SIGN_DATA_PAGE) IOHelper.writeLine("Signing Data Page"); else if(function==OneWireContainer18.COMPUTE_NEXT_SECRET) IOHelper.writeLine("Computing Next Secret"); else if(function==OneWireContainer18.COMPUTE_FIRST_SECRET) IOHelper.writeLine("Computing FIRST Secret"); else IOHelper.writeLine("SHA Function" + function); IOHelper.writeLine("pageNum: " + pageNum); IOHelper.writeLine("DigestBuffer: "); IOHelper.writeBytesHex(digestBuff); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //compute the MAC SHA.ComputeSHA(digestBuff,scratchpad,offset); //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if(DEBUG) { IOHelper.writeLine("SHA Result: "); IOHelper.writeBytesHex(scratchpad,offset,20); IOHelper.writeLine("------------------------------------------------------------"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //is this a secret computation? if(offset==0) { //Repeat E and D throughout scratchpad, just like hardware //not sure if this is necessary, maybe for NEXT_SECRET? System.arraycopy(scratchpad,0,scratchpad,8,8); System.arraycopy(scratchpad,0,scratchpad,16,8); System.arraycopy(scratchpad,0,scratchpad,24,8); } return true; } // *********************************************************************** // End SHA iButton Methods // *********************************************************************** /** * Returns a string representing the 1-Wire address of this SHAiButton. * * @return a string containing the 8-byte address of this 1-Wire device. */ public String toString () { return "COPRVM: "+ Address.toString(this.address) + ", provider: " + this.providerName + ", version: " + this.version; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -