Beispiel #1
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 #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
//----------------------------------------------------------------------
// 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 #4
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 #5
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;
}