//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // sha18.c - Low-level memory and SHA functions for the DS1963S. // // Version: 2.10 // #include "ownet.h" #include "shaibutton.h" //-------------------------------------------------------------------------- // Attempt to erase the scratchpad of the specified SHA iButton for DS1963S. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - value for TA2/TA1 (Note: TA2/TA1 aren't always set by // Erase Scratchpad command.) // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Returns: TRUE, success, scratchpad erased // FALSE, failure to erase scratchpad // SMALLINT EraseScratchpadSHA(int portnum, int address, SMALLINT resume) { uchar send_block[50]; int num_verf; short send_cnt=0; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } // change number of verification bytes if in overdrive num_verf = (in_overdrive[portnum]) ? 6 : 2; // erase scratchpad command send_block[send_cnt++] = CMD_ERASE_SCRATCHPAD; // TA1 send_block[send_cnt++] = (uchar)(address & 0xFF); // TA2 send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); // now add the verification bytes //for (i = 0; i < num_verf; i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, num_verf); send_cnt += num_verf; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // check verification OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || ((send_block[send_cnt-1] & 0xF0) == 0xA0), OWERROR_NO_COMPLETION_BYTE, FALSE); return TRUE; } //---------------------------------------------------------------------- // Read the scratchpad with CRC16 verification for DS1963S. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - pointer to address that is read from scratchpad // 'es' - pointer to offset byte read from scratchpad // 'data' - pointer data buffer read from scratchpad // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - scratch read, address, es, and data returned // FALSE - error reading scratch, device not present // // SMALLINT ReadScratchpadSHA(int portnum, int* address, uchar* es, uchar* data, SMALLINT resume) { short send_cnt=0; uchar send_block[40]; SMALLINT i, add = 0; ushort lastcrc16; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; add = 1; } // read scratchpad command send_block[send_cnt++] = CMD_READ_SCRATCHPAD; // now add the read bytes for data bytes and crc16 //for (i = 0; i < 37; i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, 37); send_cnt += 37; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // calculate CRC16 of result setcrc16(portnum,0); for (i = add; i < send_cnt ; i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); // copy data to return buffers if(address) *address = (send_block[2+add] << 8) | send_block[1+add]; if(es) *es = send_block[3+add]; for (i=0; i < 32; i++) data[i] = send_block[4 + i + add]; // success return TRUE; } //---------------------------------------------------------------------- // Write the scratchpad with CRC16 verification for DS1963S. The data // is padded until the offset is 0x1F so that the CRC16 is retrieved. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - address to write data to // 'data' - data to write // 'data_len' - number of bytes of data to write // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - write to scratch verified // FALSE - error writing scratch, device not present, or HIDE // flag is in incorrect state for address being written. // SMALLINT WriteScratchpadSHA(int portnum, int address, uchar *data, SMALLINT data_len, SMALLINT resume) { uchar send_block[50]; short send_cnt=0,i; ushort lastcrc16; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } setcrc16(portnum,0); // write scratchpad command send_block[send_cnt] = CMD_WRITE_SCRATCHPAD; docrc16(portnum,send_block[send_cnt++]); // address 1 send_block[send_cnt] = (uchar)(address & 0xFF); docrc16(portnum,send_block[send_cnt++]); // address 2 send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); docrc16(portnum,send_block[send_cnt++]); // data for (i = 0; i < data_len; i++) { send_block[send_cnt] = data[i]; docrc16(portnum,send_block[send_cnt++]); } // pad if needed for (i = 0; i < (0x1F - ((address + data_len - 1) & 0x1F)); i++) { send_block[send_cnt] = 0xFF; docrc16(portnum,send_block[send_cnt++]); } // CRC16 send_block[send_cnt++] = 0xFF; send_block[send_cnt++] = 0xFF; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // perform CRC16 of last 2 byte in packet for (i = send_cnt - 2; i < send_cnt; i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); // success return TRUE; } //---------------------------------------------------------------------- // Copy the scratchpad with verification for DS1963S. Assume that the // data was padded to get the CRC16 verification on write scratchpad. // This will result in the 'es' byte to be 0x1F. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'address' - address of destination // 'len' - length of data // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - copy scratch verified // FALSE - error during copy scratch, device not present, or HIDE // flag is in incorrect state for address being written. // SMALLINT CopyScratchpadSHA(int portnum, int address, SMALLINT len, SMALLINT resume) { short send_cnt=0; uchar send_block[10]; int num_verf; uchar es = (address + len - 1) & 0x1F; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } // change number of verification bytes if in overdrive num_verf = (in_overdrive[portnum]) ? 4 : 2; // copy scratchpad command send_block[send_cnt++] = CMD_COPY_SCRATCHPAD; // address 1 send_block[send_cnt++] = (uchar)(address & 0xFF); // address 2 send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); // es send_block[send_cnt++] = es; // verification bytes //for (i = 0; i < num_verf; i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, num_verf); send_cnt += num_verf; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // check verification OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || ((send_block[send_cnt-1] & 0xF0) == 0xA0), OWERROR_NO_COMPLETION_BYTE, FALSE ); return TRUE; } //---------------------------------------------------------------------- // Perform a scratchpad match using provided data. Fixed data length // of 20 bytes. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'data' - data to use in match scratch operation // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - valid match // FALSE - no match or device not present // SMALLINT MatchScratchpadSHA(int portnum, uchar* data, SMALLINT resume) { short send_cnt=0; uchar send_block[50]; int i; ushort lastcrc16; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } setcrc16(portnum,0); // match scratchpad command send_block[send_cnt] = CMD_MATCH_SCRATCHPAD; docrc16(portnum,send_block[send_cnt++]); // send 20 data bytes for (i = 0; i < 20; i++) { send_block[send_cnt] = data[i]; docrc16(portnum,send_block[send_cnt++]); } // send two crc bytes and verification byte //for (i = 0; i < 3; i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, 3); send_cnt += 3; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // check the CRC for (i = (send_cnt - 3); i < (send_cnt - 1); i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); // check verification if(send_block[send_cnt - 1] != (uchar)0xFF) return TRUE; else return FALSE; } //---------------------------------------------------------------------- // Read Memory Page for DS1963S. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'pagenum' - page number to do a read authenticate // 'data' - buffer to read into from page // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - Read successfull // FALSE - error occurred during read. // SMALLINT ReadMemoryPageSHA(int portnum, SMALLINT pagenum, uchar* data, SMALLINT resume) { short send_cnt=0; uchar send_block[36]; int address = pagenum << 5; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1 ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } // create the send block // Read Memory command send_block[send_cnt++] = CMD_READ_MEMORY; // TA1 send_block[send_cnt++] = (uchar)(address & 0xFF); // TA2 send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); // now add the read bytes for data bytes memset(&send_block[send_cnt], 0x0FF, 32); send_cnt += 32; // now send the block OWASSERT( owBlock(portnum,TRUE,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); // transfer the results memcpy(data, &send_block[send_cnt-32], 32); return TRUE; } //---------------------------------------------------------------------- // Read Authenticated Page for DS1963S. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'pagenum' - page number to do a read authenticate // 'data' - buffer to read into from page // 'sign' - buffer for storing sha computation // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: Value of write cycle counter for the page // -1 for error // int ReadAuthPageSHA(int portnum, SMALLINT pagenum, uchar* data, uchar* sign, SMALLINT resume) { short send_cnt=0; uchar send_block[55]; short num_verf; SMALLINT i; ushort lastcrc16; int address = pagenum*32, wcc = -1; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1 ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } //seed the crc setcrc16(portnum,0); // change number of verification bytes if in overdrive num_verf = (in_overdrive[portnum]) ? 10 : 2; // create the send block // Read Authenticated Page command send_block[send_cnt] = CMD_READ_AUTH_PAGE; docrc16(portnum, send_block[send_cnt++]); // TA1 send_block[send_cnt] = (uchar)(address & 0xFF); docrc16(portnum,send_block[send_cnt++]); // TA2 send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); docrc16(portnum,send_block[send_cnt++]); // now add the read bytes for data bytes, counter, and crc16, verification //for (i = 0; i < (42 + num_verf); i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, 42+num_verf); send_cnt += 42+num_verf; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, -1 ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // check the CRC for (i = resume?4:3; i < (send_cnt - num_verf); i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, -1); // check verification OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || ((send_block[send_cnt-1] & 0xF0) == 0xA0), OWERROR_NO_COMPLETION_BYTE, -1); // transfer results //cnt = 0; //for (i = send_cnt - 42 - num_verf; i < (send_cnt - 10 - num_verf); i++) // data[cnt++] = send_block[i]; memcpy(data, &send_block[send_cnt-42-num_verf], 32); wcc = BytesToInt(&send_block[send_cnt-10-num_verf], 4); if(sign!=NULL) { OWASSERT( ReadScratchpadSHA(portnum, 0, 0, send_block, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); //for(i=0; i<20; i++) // sign[i] = send_block[i+8]; memcpy(sign, &send_block[8], 20); } return wcc; } //---------------------------------------------------------------------- // Write Data Page for DS1963S. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'pagenum' - page number to write to // 'data' - buffer to write into page // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - Write successfull // FALSE - error occurred during write. // SMALLINT WriteDataPageSHA(int portnum, SMALLINT pagenum, uchar* data, SMALLINT resume) { uchar buffer[32]; int addr = pagenum << 5, addr_buff; uchar es = 0; OWASSERT( EraseScratchpadSHA(portnum, addr, resume), OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE ); OWASSERT( WriteScratchpadSHA(portnum, addr, data, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); OWASSERT( ReadScratchpadSHA(portnum, &addr_buff, &es, buffer, TRUE), OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); // verify that what we read is exactly what we wrote OWASSERT( (addr == addr_buff) && (es == 0x1F) && (memcmp(buffer, data, 32)==0), OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); OWASSERT( CopyScratchpadSHA(portnum, addr, 32, TRUE), OWERROR_COPY_SCRATCHPAD_FAILED, FALSE ); return TRUE; } //---------------------------------------------------------------------- // Compute sha command based on control_byte and page address. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'control_byte' - control byte used in sha operation // 'address' - address used in compute sha operation // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - compute sha finished // FALSE - CRC error, device not present // SMALLINT SHAFunction(int portnum, uchar control_byte, int address, SMALLINT resume) { short send_cnt=0; uchar send_block[18]; int i,num_verf; ushort lastcrc16; if(!resume) { // access the device OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); } else { // transmit RESUME command send_block[send_cnt++] = ROM_CMD_RESUME; } setcrc16(portnum,0); // change number of verification bytes if in overdrive num_verf = (in_overdrive[portnum]) ? 10 : 2; // Compute SHA Command send_block[send_cnt] = CMD_COMPUTE_SHA; docrc16(portnum,send_block[send_cnt++]); // address 1 send_block[send_cnt] = (uchar)(address & 0xFF); docrc16(portnum,send_block[send_cnt++]); // address 2 send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); docrc16(portnum,send_block[send_cnt++]); // control byte send_block[send_cnt] = control_byte; docrc16(portnum,send_block[send_cnt++]); // now read bytes crc16, and verification //for (i = 0; i < 2 + num_verf; i++) // send_block[send_cnt++] = 0xFF; memset(&send_block[send_cnt], 0x0FF, 2+num_verf); send_cnt += 2+num_verf; // now send the block OWASSERT( owBlock(portnum,resume,send_block,send_cnt), OWERROR_BLOCK_FAILED, FALSE ); //\\//\\//\\//\\//\\//\\//\\//\\//\\// #ifdef DEBUG_DUMP debugout(send_block,send_cnt); #endif //\\//\\//\\//\\//\\//\\//\\//\\//\\// // check the CRC for (i = resume?5:4; i < (send_cnt - num_verf); i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); // check verification OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || ((send_block[send_cnt-1] & 0xF0) == 0xA0), OWERROR_NO_COMPLETION_BYTE, FALSE ); return TRUE; } //---------------------------------------------------------------------- // Copies hidden scratchpad data into specified secret. Resume command // is used by default. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'secretnum' - secret number to replace with scratchpad data. // // Return: TRUE - copy secret succeeded // FALSE - error or device not present // SMALLINT CopySecretSHA(int portnum, SMALLINT secretnum) { // change number of verification bytes if in overdrive SMALLINT num_verf = (in_overdrive[portnum]) ? 10 : 2; // each page has 4 secrets, so look at 2 LS bits to // determine offset in the page. SMALLINT secret_offset = (secretnum&3) << 3; // secrets 0-3 are stored starting at address 0200h // and 4-7 are stored starting at address 0220h. int address = (secretnum<4 ? 0x0200 : 0x0220) + secret_offset; SMALLINT length = 32 - secret_offset; SMALLINT send_cnt = 0, i; uchar send_block[37]; ushort lastcrc16; //Since other functions must be called before this one //that are communicating with the button, resume is assumed. send_block[send_cnt++] = ROM_CMD_RESUME; send_block[send_cnt++] = CMD_WRITE_SCRATCHPAD; send_block[send_cnt++] = (uchar)address; send_block[send_cnt++] = (uchar)(address>>8); //for(i=0; i32) { memcpy(&scratchpad[8], &secret[offset+32], (bytes_left<47?bytes_left-32:15)); } // write secret data into data page OWASSERT( WriteDataPageSHA(portnum, pagenum, data, resume), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); // write secret data into scratchpad OWASSERT( WriteScratchpadSHA(portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); // perform secret computation OWASSERT( SHAFunction(portnum, (uchar)(offset==0 ? SHA_COMPUTE_FIRST_SECRET : SHA_COMPUTE_NEXT_SECRET), addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE ); // copy the resulting secret into secret location OWASSERT( CopySecretSHA(portnum, secretnum), OWERROR_COPY_SECRET_FAILED, FALSE); resume = TRUE; } return TRUE; } //---------------------------------------------------------------------- // Binds unique secret to DS1963S. bindData must be 32 bytes and // bindCode must be 15 bytes. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'pagenum' - page number to do a read authenticate // 'secretnum' - destination secret for computation results // 'bindData' - the input data written to the data page for unique // secret computation. // 'bindCode' - the input data written to the scratchpad for unique // secret computation. // 'resume' - if true, device access is resumed using the RESUME // ROM command (0xA5). Otherwise, a a MATCH ROM is // used along with the device's entire address number. // // Return: TRUE - bind successfull // FALSE - error occurred during secret installation. // SMALLINT BindSecretToiButton(int portnum, SMALLINT pagenum, SMALLINT secretnum, uchar* bindData, uchar* bindCode, SMALLINT resume) { int addr = pagenum << 5; uchar scratchpad[32]; memset(scratchpad, 0x00, 32); memcpy(&scratchpad[8], bindCode, 15); // write secret data into data page OWASSERT( WriteDataPageSHA(portnum, pagenum, bindData, resume), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); // write secret data into scratchpad OWASSERT( WriteScratchpadSHA(portnum, addr, scratchpad, 32, TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); // perform secret computation OWASSERT( SHAFunction(portnum, (uchar)SHA_COMPUTE_NEXT_SECRET, addr, TRUE), OWERROR_SHA_FUNCTION_FAILED, FALSE ); // copy the resulting secret into secret location OWASSERT( CopySecretSHA(portnum, secretnum), OWERROR_COPY_SECRET_FAILED, FALSE); return TRUE; }