Esempio n. 1
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);
}
Esempio n. 2
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;
}
Esempio n. 3
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);
   }