Beispiel #1
0
//----------------------------------------------------------------------
// 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 WriteDataPageSHA18(int portnum, SMALLINT pagenum,
                          uchar* data, SMALLINT resume)
{
   uchar buffer[32];
   int addr = pagenum << 5, addr_buff;
   uchar es = 0;

   OWASSERT( EraseScratchpadSHA18(portnum, addr, resume),
             OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE );

   OWASSERT( WriteScratchpadSHA18(portnum, addr, data, 32, TRUE),
              OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE );

   OWASSERT( ReadScratchpadSHA18(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( CopyScratchpadSHA18(portnum, addr, 32, TRUE),
             OWERROR_COPY_SCRATCHPAD_FAILED, FALSE );

   return TRUE;

}
Beispiel #2
0
//-------------------------------------------------------------------------
// Creates a random challenge using the SHA engine of the given
// coprocessor.
//
// 'copr'      - Structure for holding coprocessor information.
// 'pagenum'   - pagenumber to use for calculation.
// 'chlg'      - 3-byte return buffer for challenge.
// 'offset'    - offset into resulting MAC to pull challenge data from.
//
// Return: TRUE - create challenge succeeded.
//         FALSE - an error occurred.
//
SMALLINT CreateChallenge(SHACopr* copr, SMALLINT pageNum,
                         uchar* chlg, SMALLINT offset)
{
   uchar scratchpad[32];
   int   addr = pageNum << 5;
   uchar es = 0x1F;
   int   start = 8;

   if(offset>0 && offset<17)
      start += offset;

   //set the serial number
   owSerialNum(copr->portnum, copr->devAN, FALSE);

   OWASSERT( EraseScratchpadSHA18(copr->portnum, addr, FALSE),
             OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE );

   OWASSERT( SHAFunction18(copr->portnum, SHA_COMPUTE_CHALLENGE, addr, TRUE),
             OWERROR_SHA_FUNCTION_FAILED, FALSE );

   OWASSERT( ReadScratchpadSHA18(copr->portnum, &addr, &es, scratchpad, TRUE),
             OWERROR_READ_SCRATCHPAD_FAILED, FALSE );

   memcpy(chlg,&scratchpad[start],3);

   return TRUE;
}
Beispiel #3
0
//----------------------------------------------------------------------
// 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 BindSecretToiButton18(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( WriteDataPageSHA18(portnum, pagenum, bindData, resume),
              OWERROR_WRITE_DATA_PAGE_FAILED, FALSE );

   // write secret data into scratchpad
   OWASSERT( WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE),
              OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE );

   // perform secret computation
   OWASSERT( SHAFunction18(portnum, (uchar)SHA_COMPUTE_NEXT_SECRET,
                         addr, TRUE),
             OWERROR_SHA_FUNCTION_FAILED, FALSE );

   // copy the resulting secret into secret location
   OWASSERT( CopySecretSHA18(portnum, secretnum),
             OWERROR_COPY_SECRET_FAILED, FALSE);

   return TRUE;
}
Beispiel #4
0
//----------------------------------------------------------------------
// 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 MatchScratchpadSHA18(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;
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);

   // send 20 data bytes
   for (i = 0; i < 20; i++)
   {
      send_block[send_cnt] = data[i];
      lastcrc16 = 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;
}
Beispiel #5
0
//----------------------------------------------------------------------
// 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 ReadScratchpadSHA18(int portnum, int* address, uchar* es,
                           uchar* data, SMALLINT resume)
{
   short send_cnt=0;
   uchar send_block[40];
   SMALLINT 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;
      resume = 1; // for addition later
   }

   // 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 = resume; 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+resume] << 8) | send_block[1+resume];
   if(es)
      *es = send_block[3+resume];

   memcpy(data, &send_block[4+resume], 32);

   // success
   return TRUE;
}
Beispiel #6
0
//----------------------------------------------------------------------
// 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 CopyScratchpadSHA18(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&0x0FF]) ? 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 += (short)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;
}
Beispiel #7
0
//----------------------------------------------------------------------
// Installs new system secret for DS1931S.  input_secret must be
// divisible by 47.  Then, each block of 47 is split up with 32 bytes
// written to a data page and 15 bytes are written to the scratchpad.
// Then, Compute first secret is called (or compute next if the secret
// is divisible by 47 more than once).
//
// '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
// 'input_secret'  - the input secret buffer used.
// 'secret_length' - the length of the input secret buffer, divisibly
//                   by 47.
// '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 - Install successfull
//         FALSE - error occurred during secret installation.
//
SMALLINT InstallSystemSecret18(int portnum, SMALLINT pagenum,
                               SMALLINT secretnum, uchar* secret,
                               int secret_length, SMALLINT resume)
{
   int addr = pagenum << 5;
   int offset = 0, bytes_left = 0;
   uchar data[32],scratchpad[32];

   for(offset=0; offset<secret_length; offset+=47)
   {
      // clear the buffer
      memset(data, 0x0FF, 32);
      memset(scratchpad, 0x0FF, 32);

      // Determine the amount of bytes remaining to be installed.
      bytes_left = secret_length - offset;

      // copy secret data into page buffer and scratchpad buffer
      memcpy(data, &secret[offset], (bytes_left<32?bytes_left:32));
      if(bytes_left>32)
      {
         memcpy(&scratchpad[8], &secret[offset+32],
                (bytes_left<47?bytes_left-32:15));
      }

      // write secret data into data page
      OWASSERT( WriteDataPageSHA18(portnum, pagenum, data, resume),
                 OWERROR_WRITE_DATA_PAGE_FAILED, FALSE );

      // write secret data into scratchpad
      OWASSERT( WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE),
                 OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE );

      // perform secret computation
      OWASSERT( SHAFunction18(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( CopySecretSHA18(portnum, secretnum),
                OWERROR_COPY_SECRET_FAILED, FALSE);

      resume = TRUE;
   }

   return TRUE;
}
Beispiel #8
0
//-------------------------------------------------------------------------
// Answers a random challenge by performing an authenticated read of the
// user's account information.
//
// 'user'      - Structure for holding user token information.
// 'chlg'      - 3-byte buffer of challenge data.
//
// Return: the value of the write cycle counter for the account page.
//         or -1 if there is an error
//
int AnswerChallenge(SHAUser* user, uchar* chlg)
{
   int addr = user->accountPageNumber << 5;

   user->writeCycleCounter = -1;
   memcpy(&user->accountFile[20], chlg, 3);

   //set the serial number
   owSerialNum(user->portnum, user->devAN, FALSE);

   if(user->devAN[0]==0x18)
   {
      // for the DS1963S
      OWASSERT( EraseScratchpadSHA18(user->portnum, addr, FALSE),
                OWERROR_ERASE_SCRATCHPAD_FAILED, -1 );

      OWASSERT( WriteScratchpadSHA18(user->portnum, addr,
                                     user->accountFile, 32,
                                     TRUE),
                 OWERROR_WRITE_SCRATCHPAD_FAILED, -1 );

      user->writeCycleCounter =
         ReadAuthPageSHA18(user->portnum,
                           user->accountPageNumber,
                           user->accountFile,
                           user->responseMAC, TRUE);
   }
   else if(user->devAN[0]==0x33||user->devAN[0]==0xB3)
   {
      // for the DS1961S
      OWASSERT( WriteScratchpadSHA33(user->portnum, addr,
                                     &user->accountFile[16],
                                     FALSE),
                 OWERROR_WRITE_SCRATCHPAD_FAILED, -1 );

      user->writeCycleCounter =
         ReadAuthPageSHA33(user->portnum,
                           user->accountPageNumber,
                           user->accountFile,
                           user->responseMAC, TRUE);
   }
   return user->writeCycleCounter;
}
Beispiel #9
0
//----------------------------------------------------------------------
// 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 ReadMemoryPageSHA18(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;
}
Beispiel #10
0
//-------------------------------------------------------------------------
// Creates a data signature for the given data buffer using the hardware
// coprocessor.
//
// 'copr'          - Structure for holding coprocessor information.
// 'data'          - data written to the data page to sign
// 'scratchpad'    - data written to the scratchpad to sign
// 'signature'     - data buffer which is either holding the signature that
//                   must match exactly what is generated on the coprocessor
//                   -or- will hold the resulting signature created by the
//                   coprocessor.
// 'readSignature' - implies whether or not the signature buffer
//                   receives the contents of the scratchpad or is used to
//                   match the contents of the scratchpad.  If true,
//                   scratchpad contents are read into the signature buffer.
//
// Return: If TRUE, the user's authentication response matched exactly the
//            signature generated by the coprocessor or the signature was
//            successfully copied into the return buffer.
//         If FALSE, an error occurred or the signature did not match.
//
SMALLINT CreateDataSignature(SHACopr* copr, uchar* data,
                             uchar* scratchpad, uchar* signature,
                             SMALLINT readSignature)
{
   int addr = copr->signPageNumber << 5;

   // set the serial number to that of the coprocessor
   owSerialNum(copr->portnum, copr->devAN, FALSE);

   OWASSERT( WriteDataPageSHA18(copr->portnum, copr->signPageNumber,
                              data, FALSE),
              OWERROR_WRITE_DATA_PAGE_FAILED, FALSE );

   OWASSERT( WriteScratchpadSHA18(copr->portnum, addr,
                                scratchpad, 32, TRUE),
              OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE );

   OWASSERT( SHAFunction18(copr->portnum, SHA_SIGN_DATA_PAGE,
                         addr, TRUE),
             OWERROR_SHA_FUNCTION_FAILED, FALSE );

   if(readSignature)
   {
      OWASSERT( ReadScratchpadSHA18(copr->portnum, 0, 0,
                                  scratchpad, TRUE),
                 OWERROR_READ_SCRATCHPAD_FAILED, FALSE );
   }
   else
   {
      OWASSERT( MatchScratchpadSHA18(copr->portnum,
                                   signature, TRUE),
                 OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE );
   }

   memcpy(signature, &scratchpad[8], 20);

   return TRUE;
}
Beispiel #11
0
//-------------------------------------------------------------------------
// Updates service data on a user token.  This includes signing the
// data if the part is a DS1963S.
//
// 'copr'      - Structure for holding coprocessor information.
// 'user'      - Structure for holding user token information.
//
// Return: If TRUE, update succeeded.
//         If FALSE, an error occurred.
//
SMALLINT UpdateServiceData(SHACopr* copr, SHAUser* user)
{
   ushort crc16, i;
   uchar scratchpad[32];

   if(user->devAN[0] == 0x18)
   {
      DebitFile* accountFile = (DebitFile*)user->accountFile;

      // make sure length is right.
      accountFile->fileLength = 29;

      // update transaction ID
      // doesn't matter what it is, just needs to change
      accountFile->transID[0] += 1;
      if(accountFile->transID[0]==0)
        accountFile->transID[1] += 1;

      // conversion factor - 2 data bytes
      accountFile->convFactor[0] = (uchar)0x8B;
      accountFile->convFactor[1] = (uchar)0x48;

      // clear out the old signature and CRC
      memcpy(accountFile->signature, copr->initSignature, 20);
      memset(accountFile->crc16, 0x00, 2);

      // reset data type code
      accountFile->dataTypeCode = 1;

      //file doesn't continue on another page
      accountFile->contPtr = 0;

      // ---  Set up the scratchpad for signing
      memset(scratchpad, 0x00, 32);
      // the write cycle counter +1 (since we are about to write this to it)
      if(user->writeCycleCounter>0)
         IntToBytes(&scratchpad[8], 4, user->writeCycleCounter+1);
      else
         // user doesn't have write cycle counter (DS1961S)
         memset(&scratchpad[8], 0x0FF, 4);
      // the pagenumber
      scratchpad[12] = (uchar)user->accountPageNumber;
      // and 7 bytes of the address of current device
      memcpy(&scratchpad[13], user->devAN, 7);
      // the coprocessor's signing challenge
      memcpy(&scratchpad[20], copr->signChlg, 3);

      OWASSERT( CreateDataSignatureVM(copr, sign_secret,
                                      user->accountFile,
                                      scratchpad,
                                      accountFile->signature,
                                      TRUE),
                OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE );

      //add the crc at the end of the data.
      setcrc16(user->portnum, user->accountPageNumber);
      for (i = 0; i < 30; i++)
         crc16 = docrc16(user->portnum,user->accountFile[i]);
      crc16 = ~crc16;
      accountFile->crc16[0] = (uchar)crc16;
      accountFile->crc16[1] = (uchar)(crc16>>8);
   }
Beispiel #12
0
//----------------------------------------------------------------------
// 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 CopySecretSHA18(int portnum, SMALLINT secretnum)
{
   // change number of verification bytes if in overdrive
   SMALLINT num_verf = (in_overdrive[portnum&0x0FF]) ? 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[38];
   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; i<length+2; i++)
   //   send_block[send_cnt++] = (uchar)0x0FF;
   memset(&send_block[send_cnt], 0x0FF, 2+length);
   send_cnt += 2+length;


   // now send the block
   OWASSERT( owBlock(portnum,TRUE,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 = 1; i < send_cnt ; i++)
      lastcrc16 = docrc16(portnum,send_block[i]);

   // verify CRC16 is correct
   OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE );

   // Now read TA1/TA2 and ES, but not rest of data;
   send_cnt = 1;
   send_block[send_cnt++] = CMD_READ_SCRATCHPAD;

   //for(i=0; i<3; i++)
   //   send_block[send_cnt++] = (uchar)0x0FF;
   memset(&send_block[send_cnt], 0x0FF, 3);
   send_cnt += 3;

   // now send the block to get TA1/TA2 and ES
   OWASSERT( owBlock(portnum,TRUE,send_block,send_cnt),
             OWERROR_BLOCK_FAILED, FALSE );

   //\\//\\//\\//\\//\\//\\//\\//\\//\\//
   #ifdef DEBUG_DUMP
      debugout(send_block,send_cnt);
   #endif
   //\\//\\//\\//\\//\\//\\//\\//\\//\\//

   // Use the same buffer to call copyScratchpad with proper
   // authorization bytes.
   send_block[1] = CMD_COPY_SCRATCHPAD;

   //for(i=0; i<num_verf; i++)
   //   send_block[send_cnt++] = (uchar)0x0FF;
   memset(&send_block[send_cnt], 0x0FF, num_verf);
   send_cnt += num_verf;

   // now send the block
   OWASSERT( owBlock(portnum,TRUE,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;
}
Beispiel #13
0
//----------------------------------------------------------------------
// 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 SHAFunction18(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&0x0FF]) ? 10 : 2;

   // Compute SHA Command
   send_block[send_cnt] = CMD_COMPUTE_SHA;
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // address 1
   send_block[send_cnt] = (uchar)(address & 0xFF);
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // address 2
   send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // control byte
   send_block[send_cnt] = control_byte;
   lastcrc16 = 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;
}
Beispiel #14
0
//----------------------------------------------------------------------
// 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 ReadAuthPageSHA18(int portnum, SMALLINT pagenum, uchar* data,
                    uchar* sign, SMALLINT resume)
{
   short send_cnt=0;
   uchar send_block[56];
   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&0x0FF]) ? 10 : 2;

   // create the send block
   // Read Authenticated Page command
   send_block[send_cnt] = CMD_READ_AUTH_PAGE;
   lastcrc16 = docrc16(portnum, send_block[send_cnt++]);

   // TA1
   send_block[send_cnt] = (uchar)(address & 0xFF);
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);

   // TA2
   send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
   lastcrc16 = 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( ReadScratchpadSHA18(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;
}
Beispiel #15
0
//-------------------------------------------------------------------------
// Verifies the authentication response of a user token.
//
// 'copr'      - Structure for holding coprocessor information.
// 'user'      - Structure for holding user token information.
// 'chlg'      - 3-byte buffer of challenge data.
// 'doBind'    - if true, the user's unique secret is recreated on the
//               coprocessor.  If this function is called multiple times,
//               it is acceptable to skip the bind for all calls after
//               the first on the same user token.
//
// Return: If TRUE, the user's authentication response matched exactly the
//            signature generated by the coprocessor.
//         If FALSE, an error occurred or the signature did not match.
//
SMALLINT VerifyAuthResponse(SHACopr* copr, SHAUser* user,
                            uchar* chlg, SMALLINT doBind)
{
   int addr = copr->wspcPageNumber << 5;
   int wcc = user->writeCycleCounter;
   uchar sign_cmd;
   uchar scratchpad[32];
   uchar fullBindCode[15];

   memset(scratchpad, 0x00, 32);
   memset(fullBindCode, 0x0FF, 15);

   // format the bind code properly
   if(user->devAN[0]==0x18)
   {
      // Format for DS1963S
      memcpy(fullBindCode, copr->bindCode, 4);
      memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);
      // use ValidateDataPage command
      sign_cmd = SHA_VALIDATE_DATA_PAGE;
      // copy wcc LSB first
      if(!IntToBytes(&scratchpad[8], 4, wcc))
         OWERROR(OWERROR_NO_ERROR_SET);
   }
   else if(user->devAN[0]==0x33||user->devAN[0]==0xB3)
   {
      // Leave bindCode FF for DS1961S
      // Use AuthenticateHost command
      sign_cmd = SHA_AUTHENTICATE_HOST;
      // the user doesn't have a write cycle counter
      memset(&scratchpad[8], 0x0FF, 4);
   }
   else
   {
      OWERROR(OWERROR_WRONG_TYPE);
      return FALSE;
   }

   // the pagenumber
   fullBindCode[4] = (uchar)user->accountPageNumber;
   // and 7 bytes of the address of current device
   memcpy(&fullBindCode[5], user->devAN, 7);

   // get the user address and page num from fullBindCode
   memcpy(&scratchpad[12], &fullBindCode[4], 8);
   // set the same challenge bytes
   memcpy(&scratchpad[20], chlg, 3);

   // set the serial number to that of the coprocessor
   owSerialNum(copr->portnum, copr->devAN, FALSE);

   // install user's unique secret on the wspc secret
   if(doBind)
   {
      OWASSERT( BindSecretToiButton18(copr->portnum,
                                      copr->authPageNumber,
                                      copr->wspcPageNumber&7,
                                      copr->bindData, fullBindCode, FALSE),
                OWERROR_BIND_SECRET_FAILED, FALSE );
      if(user->devAN[0]==0x33||user->devAN[0]==0xB3)
      {
         // also copy the resulting secret into secret location 0, to
         // replace the signing secret.  Necessary for producing the
         // DS1961S's write-authorization MAC.
         OWASSERT( CopySecretSHA18(copr->portnum, 0),
                   OWERROR_COPY_SECRET_FAILED, FALSE);
      }
   }

   // recreate the signature and verify
   OWASSERT( WriteDataPageSHA18(copr->portnum, copr->wspcPageNumber,
                              user->accountFile, doBind),
              OWERROR_WRITE_DATA_PAGE_FAILED, FALSE );

   OWASSERT( WriteScratchpadSHA18(copr->portnum, addr, scratchpad, 32, TRUE),
              OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE );

   OWASSERT( SHAFunction18(copr->portnum, sign_cmd, addr, TRUE),
             OWERROR_SHA_FUNCTION_FAILED, FALSE );

   OWASSERT( MatchScratchpadSHA18(copr->portnum,
                                user->responseMAC, TRUE),
             OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE );

   return TRUE;
}
Beispiel #16
0
//-------------------------------------------------------------------------
// Installs new service data on a user token.
//
// 'copr'      - Structure for holding coprocessor information.
// 'user'      - Structure for holding user token information.
// 'secret'    - the authentication secret to install on user token.
//
// Return: If TRUE, new service installation succeeded.
//         If FALSE, an error occurred.
//
SMALLINT InstallServiceData(SHACopr* copr, SHAUser* user,
                            uchar* secret, int secret_length,
                            int initialBalance)
{
   short handle;
   int maxwrite;
   FileEntry fe;
   uchar fullBindCode[15];

   //make sure user has a file directory structure
   memcpy(fe.Name, copr->serviceFilename, 4);
   fe.Ext = copr->serviceFilename[4];

   // install master authentication secret
   if(user->devAN[0]==0x18)
   {
      //need to format the device
      if(!owFormat(user->portnum, user->devAN))
         return FALSE;

      //and create an empty stub for his account information
      if(!owCreateFile(user->portnum, user->devAN,
                       &maxwrite, &handle, &fe))
         return FALSE;

      //need to know what page the stub is on
      user->accountPageNumber = fe.Spage;

      // set the serial number to that of the user
      owSerialNum(user->portnum, user->devAN, FALSE);
      OWASSERT( InstallSystemSecret18(user->portnum,
                                      user->accountPageNumber,
                                      user->accountPageNumber&7,
                                      secret, secret_length, FALSE),
                OWERROR_INSTALL_SECRET_FAILED, FALSE );
   }
   else if((user->devAN[0]&0x7F)==0x33)
   {
      // set the serial number to that of the user
      owSerialNum(user->portnum, user->devAN, FALSE);
      //because of copy-authorization, we need to install the
      //secret first on the DS1961S and _then_ format the system
      OWASSERT( InstallSystemSecret33(user->portnum,
                                      0,
                                      0,
                                      secret, secret_length, FALSE),
                OWERROR_INSTALL_SECRET_FAILED, FALSE );

      //need to format the device
      if(!owFormat(user->portnum, user->devAN))
         return FALSE;

      //and create an empty stub for his account information
      if(!owCreateFile(user->portnum, user->devAN,
                       &maxwrite, &handle, &fe))
         return FALSE;

      //need to know what page the stub is on
      user->accountPageNumber = fe.Spage;
   }
   else
   {
      return FALSE;
   }

   // format the bind code properly
   // first four bytes of bind code
   memcpy(fullBindCode, copr->bindCode, 4);
   // followed by the pagenumber
   fullBindCode[4] = (uchar)user->accountPageNumber;
   // and 7 bytes of the address of current device
   memcpy(&fullBindCode[5], user->devAN, 7);
   // followed by the last 3 bytes of bind code
   memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3);

   // create a unique secret for iButton
   if(user->devAN[0]==0x18)
   {
	  DebitFile* accountFile = (DebitFile*)user->accountFile;

      OWASSERT( BindSecretToiButton18(user->portnum,
                                      user->accountPageNumber,
                                      user->accountPageNumber&7,
                                      copr->bindData, fullBindCode, TRUE),
                OWERROR_BIND_SECRET_FAILED, FALSE );

      // do a read just to get value of writecycle counter
      user->writeCycleCounter = ReadAuthPageSHA18(user->portnum,
                                                user->accountPageNumber,
                                                user->accountFile,
                                                NULL,
                                                TRUE);

      //setup user account file with initial balance
      IntToBytes(accountFile->balanceBytes,3,initialBalance);

      // set transaction ID
      accountFile->transID[0] = 0;
      accountFile->transID[0] = 0;

   }
   else if((user->devAN[0]&0x7F)==0x33)
   {
      DebitFile33* accountFile33 = (DebitFile33*)user->accountFile;

      OWASSERT( BindSecretToiButton33(user->portnum,
                                      user->accountPageNumber,
                                      0,
                                      copr->bindData, fullBindCode, TRUE),
                OWERROR_BIND_SECRET_FAILED, FALSE );

      // Call VerifyUser just to get the user's secret in wspc
      if(!VerifyUser(copr, user, TRUE))
         return FALSE;

      //Record A
      //setup user account file with initial balance
      IntToBytes(accountFile33->balanceBytes_A,3,initialBalance);

      // set transaction ID
      accountFile33->transID_A[0] = 0;
      accountFile33->transID_A[0] = 0;

      //Record B
	   //setup user account file with initial balance
      IntToBytes(accountFile33->balanceBytes_B,3,initialBalance);

      // set transaction ID
      accountFile33->transID_B[0] = 0;
      accountFile33->transID_B[0] = 0;
   }

   //sign the data with coprocessor and write it out
   return UpdateServiceData(copr, user);
}
Beispiel #17
0
//----------------------------------------------------------------------
// 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 WriteScratchpadSHA18(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;
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // address 1
   send_block[send_cnt] = (uchar)(address & 0xFF);
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // address 2
   send_block[send_cnt] = (uchar)((address >> 8) & 0xFF);
   lastcrc16 = docrc16(portnum,send_block[send_cnt++]);
   // data
   for (i = 0; i < data_len; i++)
   {
      send_block[send_cnt] = data[i];
      lastcrc16 = 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;
      lastcrc16 = 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;
}