//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // shadebitvm.c - Transaction-level functions for SHA Debits without a // hardware coprocessor. Also, this file contains some // Protocol-level functions to replace their 'hardware-only' // counterparts.. // // Version: 2.10 #include "ownet.h" #include "shaibutton.h" #define INITIAL_BALANCE 100000 #define MAX_RETRY_CNT 255 // static functions static int GetSecretVM(char* name, uchar** secret); // static global vars static uchar sign_secret[8]; static uchar auth_secret[8]; static uchar wspc_secret[8]; //------------------------------------------------------------------------- // 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) { 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( InstallSystemSecret(user->portnum, user->accountPageNumber, user->accountPageNumber&7, secret, secret_length, FALSE), OWERROR_INSTALL_SECRET_FAILED, FALSE ); } else if(user->devAN[0]==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) { OWASSERT( BindSecretToiButton(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 = ReadAuthPageSHA(user->portnum, user->accountPageNumber, user->accountFile.raw, NULL, TRUE); } else if(user->devAN[0]==0x33) { OWASSERT( BindSecretToiButton33(user->portnum, user->accountPageNumber, user->accountPageNumber&7, 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; } //setup user account file with initial balance IntToBytes(user->accountFile.file.balanceBytes,3,INITIAL_BALANCE); // set transaction ID user->accountFile.file.transID[0] = 0; user->accountFile.file.transID[0] = 0; //sign the data with coprocessor and write it out return UpdateServiceData(copr, user); } //------------------------------------------------------------------------- // 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]; // make sure length is right. user->accountFile.file.fileLength = 29; // update transaction ID // doesn't matter what it is, just needs to change user->accountFile.file.transID[0] += 1; if(user->accountFile.file.transID[0]==0) user->accountFile.file.transID[1] += 1; // conversion factor - 2 data bytes user->accountFile.file.convFactor[0] = (uchar)0x8B; user->accountFile.file.convFactor[1] = (uchar)0x48; // clear out the old signature and CRC memcpy(user->accountFile.file.signature, copr->initSignature, 20); memset(user->accountFile.file.crc16, 0x00, 2); // reset data type code user->accountFile.file.dataTypeCode = 0; if(user->devAN[0]!=0x33) { // --- 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.raw, scratchpad, user->accountFile.file.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.raw[i]); crc16 = ~crc16; user->accountFile.file.crc16[0] = (uchar)crc16; user->accountFile.file.crc16[1] = (uchar)(crc16>>8); // set the serial number to that of the user owSerialNum(user->portnum, user->devAN, FALSE); if(user->devAN[0]==0x18) { //DS1963S - not too tough OWASSERT( WriteDataPageSHA(user->portnum, user->accountPageNumber, user->accountFile.raw, FALSE), OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); } else if(user->devAN[0]==0x33) { //DS1961S - a bit tougher //assumes wspc_secret already contains device's unique secret. uchar pageContents[32], data[32]; uchar MAC[20]; int addr = user->accountPageNumber << 5; OWASSERT( ReadMemoryPageSHA33(user->portnum, user->accountPageNumber, pageContents, FALSE), OWERROR_READ_MEMORY_PAGE_FAILED, FALSE ); //PrintHexLabeled("Page contents", pageContents, 32); //PrintHexLabeled("Replace with", user->accountFile.raw, 32); for(i=0; i<32; i+=8) { if(memcmp(&pageContents[i],&user->accountFile.raw[i],8) != 0) { //PrintHexLabeled("Current Page contents", pageContents, 32); //PrintHexLabeled(" 8 bytes to replace", &pageContents[i], 8); //PrintHexLabeled(" with these 8 bytes", &user->accountFile.raw[i], 8); memcpy(data, pageContents, 28); memcpy(&data[28], &user->accountFile.raw[i], 4); memcpy(&scratchpad[8], &user->accountFile.raw[i+4], 4); scratchpad[12] = (uchar)(user->accountPageNumber&0x3F); memcpy(&scratchpad[13], user->devAN, 7); memset(&scratchpad[20], 0xFF, 3); OWASSERT( CreateDataSignatureVM(copr, wspc_secret, data, scratchpad, MAC, TRUE), OWERROR_SIGN_SERVICE_DATA_FAILED, FALSE); OWASSERT( WriteScratchpadSHA33(user->portnum, addr+i, &user->accountFile.raw[i], TRUE), OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); OWASSERT( CopyScratchpadSHA33(user->portnum, addr+i, MAC, TRUE), OWERROR_COPY_SCRATCHPAD_FAILED, FALSE ); memcpy(&pageContents[i], &user->accountFile.raw[i], 8); } } } else return FALSE; return TRUE; } //------------------------------------------------------------------------- // Verifies a user token as a valid member of the system. First, a random // challenge is generated. Then, the user must answer that challenge. // The user's response signature is then verified against the proper // response.. // // 'copr' - Structure for holding coprocessor information. // 'user' - Structure for holding user token information. // '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, user was verified. // If FALSE, an error occurred or user verification failed. // SMALLINT VerifyUser(SHACopr* copr, SHAUser* user, SMALLINT doBind) { uchar chlg[3]; int randomNum, i; // Create Challenge randomNum = rand(); for (i = 0; i < 3; i++) { chlg[i] = (uchar)randomNum; randomNum >>= 8; } OWASSERT( AnswerChallenge(user, chlg)>=0, OWERROR_ANSWER_CHALLENGE_FAILED, FALSE ); OWASSERT( VerifyAuthResponseVM(copr, user, chlg, doBind), OWERROR_VERIFY_AUTH_RESPONSE_FAILED, FALSE ); return TRUE; } //------------------------------------------------------------------------- // Verifies service data on a user token as a valid member of the system. // Pre-condition: must call verify user first. // // 'copr' - Structure for holding coprocessor information. // 'user' - Structure for holding user token information. // // Return: If TRUE, data was verified. // If FALSE, an error occurred or data verification failed. // SMALLINT VerifyData(SHACopr* copr, SHAUser* user) { uchar scratchpad[32]; uchar acctFile[32]; if(user->devAN[0]==0x33) { //DS1961S carry unsigned transaction data, //no need to verify return TRUE; } memset(scratchpad, 0x00, 32); if(user->writeCycleCounter>0) IntToBytes(&scratchpad[8], 4, user->writeCycleCounter); 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); // make a copy of the account file memcpy(acctFile, user->accountFile.raw, 32); // clear out the old signature and CRC memcpy(&acctFile[8], copr->initSignature, 20); memset(&acctFile[30], 0x00, 2); OWASSERT( CreateDataSignatureVM(copr, sign_secret, acctFile, scratchpad, user->accountFile.file.signature, FALSE), OWERROR_MATCH_SERVICE_SIGNATURE_FAILED, FALSE ); return TRUE; } //------------------------------------------------------------------------- // Performs debit of service data on a user token, re-signs the data, and // writes it back to the user token. // Pre-condition: must call verify user first. // // 'copr' - Structure for holding coprocessor information. // 'user' - Structure for holding user token information. // 'debitAmount' - the amount of money to debit from balance in cents. // 'verifySuccess' - Paranoid double-check of account write by re-calling // VerifyUser(copr,user) // // Return: If TRUE, data was updated. // If FALSE, an error occurred or couldn't verify success. // SMALLINT ExecuteTransaction(SHACopr* copr, SHAUser* user, int debitAmount, SMALLINT verifySuccess ) { SMALLINT success, dataOK = TRUE; uchar oldAcctData[32], newAcctData[32]; int cnt = MAX_RETRY_CNT; int balance, oldBalance ; memcpy(oldAcctData, user->accountFile.raw, 32); oldBalance = BytesToInt(user->accountFile.file.balanceBytes, 3); if(oldBalance<=0) { OWERROR(OWERROR_BAD_SERVICE_DATA); return FALSE; } balance = oldBalance - debitAmount; IntToBytes(user->accountFile.file.balanceBytes, 3, balance); success = UpdateServiceData(copr, user); //if write didn't succeeded or if we need to perform //a verification step anyways, let's double-check what //the user has on the button. if(verifySuccess || !success) { dataOK = FALSE; //save what the account data is supposed to look like memcpy(newAcctData, user->accountFile.raw, 32); do { //calling verify user re-issues a challenge-response //and reloads the cached account data in the user object. //Does not re-bind the user's unique secret if(VerifyUser(copr,user,FALSE)) { //compare the user's account data against the working //copy and the backup copy. if( memcmp(user->accountFile.raw, newAcctData, 32) == 0 ) { //looks like it worked dataOK = TRUE; } else if( memcmp(user->accountFile.raw, oldAcctData, 32) == 0 ) { //if it matches the backup copy, we didn't write anything //and the data is still okay, but we didn't do a debit dataOK = TRUE; success = FALSE; OWERROR(OWERROR_SERVICE_DATA_NOT_UPDATED); } else { // retry the write success = UpdateServiceData(copr, user); //save what the account data is supposed to look like memcpy(newAcctData, user->accountFile.raw, 32); } } } while(dataOK==FALSE && cnt-->0); } if(!dataOK) { //couldn't fix the data after 255 retries OWERROR(OWERROR_CATASTROPHIC_SERVICE_FAILURE); success = FALSE; } return success; } //------------------------------------------------------------------------- // Verifies the authentication response of a user token without a // hardware coprocessor. // // '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 VerifyAuthResponseVM(SHACopr* copr, SHAUser* user, uchar* chlg, SMALLINT doBind) { int wcc = user->writeCycleCounter; uchar scratchpad[32]; uchar fullBindCode[15]; uchar temp_buf[32]; // M-X control byte uchar MXP = 0x00; 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); // copy wcc LSB first IntToBytes(&scratchpad[8], 4, wcc); } else if(user->devAN[0]==0x33) { // Leave bindCode FF for DS1961S // Use AuthenticateHost command MXP = 0x40; // 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); // Fix the M-X control bits scratchpad[12] = (uchar)((scratchpad[12]&0x3F)|(MXP&0xC0)); //PrintHexLabeled("bindData",copr->bindData,32); //PrintHexLabeled("fullBindCode",fullBindCode,15); memset(temp_buf, 0x00, 32); memcpy(&temp_buf[8],fullBindCode,15); //PrintHexLabeled("spad buf",temp_buf,32); // install user's unique secret on the wspc secret // Just like BindSecretToiButton for standard coprocessor if(doBind) { OWASSERT( CreateDataSignatureVM(copr, auth_secret, copr->bindData, temp_buf, temp_buf, TRUE), OWERROR_BIND_SECRET_FAILED, FALSE ); memcpy(wspc_secret, temp_buf, 8); //PrintHexLabeled("auth_secret", auth_secret, 8); } //PrintHexLabeled("wspc_secret",wspc_secret,8); //PrintHexLabeled("Account data",user->accountFile.raw,32); //PrintHexLabeled("Scratchpad",scratchpad,32); //PrintHexLabeled("User's signature",user->responseMAC,20); // recreate the signature and verify OWASSERT( CreateDataSignatureVM(copr, wspc_secret, user->accountFile.raw, scratchpad, user->responseMAC, FALSE), OWERROR_VERIFY_SIG_FAILED, FALSE ); return TRUE; } //------------------------------------------------------------------------- // Creates a data signature for the given data buffer without a 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 CreateDataSignatureVM(SHACopr* copr, uchar* secret, uchar* data, uchar* scratchpad, uchar* signature, SMALLINT readSignature) { SMALLINT i,j,offset; long hash[5], temp; uchar digestBuff[64]; //Set up the 64 byte buffer for computing the digest. memcpy(digestBuff,secret,4); memcpy(&digestBuff[4],data,32); memcpy(&digestBuff[36],&scratchpad[8],12); memcpy(&digestBuff[48],&secret[4],4); memcpy(&digestBuff[52],&scratchpad[20],3); //digest buffer padding digestBuff[55] = (uchar)0x80; memset(&digestBuff[56], 0x00, 6); digestBuff[62] = (uchar)0x01; digestBuff[63] = (uchar)0xB8; ComputeSHAVM(digestBuff, hash); //iButtons use LSB first, so we have to turn //the result around a little bit. Instead of //result A-B-C-D-E, our result is E-D-C-B-A, //where each letter represents four bytes of //the result. for(j=4; j>=0; j--) { temp = hash[j]; offset = (4-j)*4; for(i=0; i<4; i++) { if(readSignature) { //reading the signature into a buffer signature[i+offset] = (uchar)temp; } else { //trying to match the signature; OWASSERT( signature[i+offset] == (uchar)temp, OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE ); } temp >>= 8; } } //PrintHexLabeled("signature", signature, 20); return TRUE; } //---------------------------------------------------------------------- // Installs new system secret for VM. 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). // // 'copr' - Structure for holding coprocessor information. // 'input_secret' - the input secret buffer used. // 'secret_length' - the length of the input secret buffer, divisibly // by 47. // 'dst_secret' - the buffer where resulting secret is copied. // // Return: TRUE - Install successfull // FALSE - error occurred during secret installation. // SMALLINT InstallSystemSecretVM(SHACopr* copr, uchar* secret, int secret_length, uchar* dst_secret) { int offset = 0, bytes_left = 0; uchar data[32],scratchpad[32]; //PrintHexLabeled("Installing secret",secret,secret_length); for(offset=0; offset32) { memcpy(&scratchpad[8], &secret[offset+32], (bytes_left<47?bytes_left-32:15)); } // fix the M-X control bits scratchpad[12] = scratchpad[12] & 0x3F; //PrintHexLabeled(" using secret",dst_secret,8); //PrintHexLabeled(" using data",data,32); //PrintHexLabeled(" using spad",scratchpad,32); // install user's unique secret on the wspc secret // Just like BindSecretToiButton for standard coprocessor OWASSERT( CreateDataSignatureVM(copr, dst_secret, data, scratchpad, scratchpad, TRUE), OWERROR_BIND_SECRET_FAILED, FALSE ); memcpy(dst_secret, scratchpad, 8); } return TRUE; } //---------------------------------------------------------------------- // Installs new system signing secret for VM. 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). // // 'copr' - Structure for holding coprocessor information. // '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. // // Return: TRUE - Install successfull // FALSE - error occurred during secret installation. // SMALLINT InstallSignSecretVM(SHACopr* copr, uchar* secret, int secret_length) { int i; memset(sign_secret, 0x00, 8); i = InstallSystemSecretVM(copr, secret, secret_length, sign_secret); return i; } //---------------------------------------------------------------------- // Installs new system signing secret for VM. 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). // Note: as a side-effect, the random number generator is seeded in this // function as well. // // 'copr' - Structure for holding coprocessor information. // '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. // // Return: TRUE - Install successfull // FALSE - error occurred during secret installation. // SMALLINT InstallAuthSecretVM(SHACopr* copr, uchar* secret, int secret_length) { int i; memset(auth_secret, 0x00, 8); i = InstallSystemSecretVM(copr, secret, secret_length, auth_secret); // at bare minimum, InstallAuthSecretVM must be called before the // VM coprocessor can be used. We can take advantage of this fact // and use this opportunity to seed the random number generator. srand( ((unsigned int)time(NULL)) ^ ((secret[3]) | (secret[5]<<8) | (secret[7]<<16) | (secret[11]<<24)) ); //is that random? although deterministic, it's got to be at the //very least hard to predict. it depends on user input which should //be kept top secret. return i; } //---------------------------------------------------------------------- // Loads the Coprocessor VM's config info from either a config file or // an emulated coprocessor. // // 'copr' - Structure for holding coprocessor information. // 'fe' - FileEntry to look for on emulated coprocessor // // Return: TRUE - GetCoprocessor successfull // FALSE - error occurred // SMALLINT GetCoprVM(SHACopr* copr, FileEntry* fe) { FILE* fp; uchar *signSecret,*authSecret; int signlen, authlen, len; long lvalue = 1; char test[2] = { 'y', 0 }; uchar buffer[255]; printf("How would you like to initialize the VM?"); EnterNum("\n 1) Load VM info from file\n " "2) Emulate another coprocessor\n", 1, &lvalue, 1, 2); if(lvalue==1) { // open up a file, maybe "shaVM.cnf" fp = fopen(SHACoprFilename, "rb"); if(fp==NULL) { printf("file not found: %s\n", SHACoprFilename); return FALSE; } len = fread(buffer, 1, 255, fp); if(len<=0) { printf("Could not read coprocessor config file\n"); return FALSE; } GetCoprFromRawData(copr, buffer, len); } else { if(!FindCoprSHA(copr, fe)) { printf("no coprocessor found!\n"); return FALSE; } } signlen = GetSecretVM("System Signing Secret", &signSecret); authlen = GetSecretVM("System Authentication Secret", &authSecret); EnterString("Reformat the secret for DS1961S compatibility", test, 1, 1); if(test[0] == 'y') { ReformatSecretFor1961S(authSecret, authlen); PrintHex(authSecret, authlen); printf("\n"); copr->ds1961Scompatible = 0x55; } InstallAuthSecretVM(copr, authSecret, authlen); InstallSignSecretVM(copr, signSecret, signlen); return TRUE; } //---------------------------------------------------------------------- // Used for querying the user for secret information // // 'name' - type of secret (authentication or signing) // 'secret' - resulting secret data // // Returns: The length of the secret // static int GetSecretVM(char* name, uchar** secret) { uchar inputBuffer[255]; long lvalue=1, length; printf("How would you like to enter the %s?\n", name); EnterNum("\n 1) Hex\n 2) Text\n", 1, &lvalue, 1, 2); lvalue = getData(inputBuffer, 255, (lvalue==1)); if(lvalue%47!=0) length = ((lvalue/47) + 1)*47; else length = lvalue; *secret = malloc(length); memset(*secret, 0x00, length); memcpy(*secret, inputBuffer, lvalue); printf("length=%ld\n",length); PrintHex(*secret, length); printf("\n"); return length; }