AN156
19 of 23
Signing Data with SHAIB.C Module Figure 34
The helper method shown in Figure 34 can be broken down into the necessary low-level methods used to
implement signing data. Figure 35 illustrates this process for creating a data signature
Signing Data with Coprocessor with SHA18 Module Figure 35
For the data in the account file byte array to be a valid account file, it must have an inverted, two-byte
CRC16 at the end of the file. More detail on what makes a valid file on the 1-Wire File Structure can be
found in AN114.
Adding Inverted CRC16 to 1-Wire File Figure 36
Writing the account file to the data page of the DS1963S user token is fairly easy. There is a utility
function provided for writing a page of data, the exact function which is used to write the account data to
the coprocessor for signing in the above code block.
3.3 Authenticating the User Token
Authenticating the user token involves a simple challenge-response scheme. First, the coprocessor is used
to generate a 3-byte, pseudo-random challenge. This challenge is then written to the scratchpad of the
user token and the Read Authenticated Page command is issued (see DS1963S data sheet). This returns
the entire contents of the memory page followed by the value of the write cycle counter for the page and
the write cycle counter for the secret location. The scratchpad of the DS1963S user token will contain the
20-byte SHA result of the user’s unique authentication secret, the page number the data was read from,
/* calculate the inverted CRC16 */
setcrc16(user.portnum, user.accountPageNumber);
for (i = 0; i < 30; i++)
crc16 = docrc16(user.portnum,user.accountFile.raw[i]);
crc16 = ~crc16;
/* now the file is ready to be written */
user.accountFile.file.crc16[0] = (uchar)crc16;
user.accountFile.file.crc16
[1] = (uchar)(crc16>>8);
int addr = copr.signPageNumber<<5; // physical address of the page
uchar buffer[32];
/* write the account data to the signing page of the coprocessor */
WriteDataPageSHA18(copr.portnum, copr.signPageNumber, user.accountFile.raw, FALSE);
/* write the signScratchpad to the scratchpad of the coprocessor */
WriteScratchpadSHA18(copr.portnum, addr, signScratchpad, 32, TRUE);
/* sign the data and read the signature*/
SHAFunction18(copr.portnum, SHA_SIGN_DATA_PAGE, addr, TRUE);
ReadScratchpadSHA18(copr.portnum, 0, 0, buffer, TRUE);
/* place the resulting signature in the certificate */
System.arraycopy(user.accountFile.signature, &buffer[8], 20);
/* sign the data with the coprocessor and set the value of certificate signature */
CreateDataSignature(copr, user->accountFile.raw, signScratchpad,
user->accountFile.file.signature, TRUE);
AN156
20 of 23
the serial number of the user token, and the random challenge. The coprocessor is then used to reproduce
this SHA result, ensuring that the user token is a valid member of the system.
Authenticating User Token with SHADEBIT.C Module Figure 37
The process for verifying a user is the same for both signed and unsigned transactions. Naturally, this can
be broken down into simple steps using the SHAIB.C module. The code snippet presented in Figure 38
demonstrates the basic implementation of the user verification method in the protocol-layer module
(minus the error checking).
Authenticating User Token with SHAIB.C Module Figure 38
Figure 39 illustrates how to use the lowest-level module (SHA18.C) to produce a random challenge.
Using the Coprocessor to Generate a Random Challenge Figure 39
After performing the steps in Figure 39, the scratchpad buffer of the coprocessor now contains the 20-
byte result of a SHA calculation, starting at index 8. Since any three bytes are as good as any other three
for a challenge, it is safe to leave the result as it is in the scratchpad. Indices 20 to 22 of the coprocessor’s
scratchpad hold the challenge bytes that will be used for the Read Authenticated Page. Using these three
particular bytes makes it unnecessary to write the challenge back to the coprocessor later.
uchar scratchpad[32]; // temporary buffer
uchar chlg[3];
/* Use the coprocessor to generate the challenge, page number is irrelevant but a
* highly used page will generate a more random (less repeating) number */
EraseScratchpadSHA18(copr.portnum, 0, FALSE);
SHAFunction18(copr.portnum, SHA_COMPUTE_CHALLENGE, copr.signPageNumber<<5, TRUE);
ReadScratchpadSHA18(copr.portnum, 0, 0, scratchpad, TRUE);
/* copy the challenge bytes into challenge buffer */
memcpy(chlg, &scratchpad[20], 3);
uchar chlg[3]; // random challenge bytes
/* Use coprocessor to generate a random challenge */
CreateChallenge(copr, copr.signPageNumber, chlg, 0);
/* issue challenge to user getting back the account data, response MAC, and the
* value of the write-cycle counter */
AnswerChallenge(user, chlg);
/* use coprocessor to verify the authentication response */
VerifyAuthResponse(copr, user, chlg, TRUE);
/* Verify user tokens authentication response, same for signed and unsigned */
VerifyUser(copr, user, TRUE);
AN156
21 of 23
Answering a Random Challenge with a DS1963S User Token Figure 40
After retrieving the MAC (Message Authentication Code) from the user token, it is now the job of the
coprocessor to verify it. To verify the response, the user token’s unique secret is recreated in the
workspace secret of the coprocessor and the raw account data is signed with this workspace secret.
Validating the Authentication Response Figure 41
int acctAddr = user.accountPageNumber<<5; //physical address of account file
uchar scratchpad[32];
memcpy(&scratchpad[20], chlg, 3);
/* Write the challenge to the scratchpad of the user token */
EraseScratchpadSHA18(user.portnum, acctAddr, FALSE);
WriteScratchpadSHA18(user.portnum, acctAddr, scratchpad, 32, TRUE);
/* perform authenticated read to get the page data and the resulting MAC */
user.writeCycleCounter =
ReadAuthPageSHA18(user.portnum,
user.accountPageNumber,
user.accountFile.raw,
user.res
ponseMAC, TRUE);
int wcc = user.writeCycleCounter;
/* Bind DS1963S user token’s unique secret to coprocessor */
uchar fullBindCode[15];
/* Get the 7-byte binding code
memcpy(fullBindCode, copr.bindCode, 4);
memcpy(&fullBindCode[12], &copr.bindCode[4], 3);
/* get the page number of the account file and 7 bytes of the ROM ID */
fullBindCode[4] = user.accountPageNumber;
memcpy(&fullBindCode[5], user.devAN, 7);
/* recreate user token’s unique secret in workspace secret*/
BindSecretToiButton18(copr.authPageNumber, copr.bindData, fullBindCode,
copr.wspcPageNumber);
/* the scratchpad of the coprocessor now needs the user’s ROM ID and page number,
* In addition to the challenge bytes used and the write-cycle counter. */
memcpy(&scratchpad[12], fullBindCode[4], 8);
memcpy(&scratchpad[20], chlg, 3);
scratchpad[8] = (wcc&0x0ff);
scratchpad[9] = ((wcc>>=8)&0x0ff);
scratchpad[10] = ((wcc>>=8)&0x0ff);
scratchpad[11] = ((wcc>>=8)&0x0ff);
/* write to the coprocessor and validate */
int wspcAddr = copr.wspcPageNumber<<5; //physical address of wspc page
WriteDataPageSHA18(copr.portnum, copr.wspcPageNumber, user.accountFile.raw, FALSE);
WriteScratchpadSHA18(copr.portnum, wspcAddr, scratchpad, 32, TRUE);
SHAFunction18(copr.portnum, SHA_VALIDATE_DATA_PAGE, wspcAddr, TRUE);
if( MatchScratchpadSHA18(copr.portnum, user.responseMAC, TRUE) )
printf(“DS1963S Authentication Successful!”);

DS1963S-F5+

Mfr. #:
Manufacturer:
Maxim Integrated
Description:
iButtons & Accessories SHA iButton
Lifecycle:
New from this manufacturer.
Delivery:
DHL FedEx Ups TNT EMS
Payment:
T/T Paypal Visa MoneyGram Western Union

Products related to this Datasheet