1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
24 // Branding Policy.
25 //--------------------------------------------------------------------------
26 //
27 // mbSHAEE.c - Reads and writes to memory locations for the SHAEE memory bank.
28 // version 1.00
29 //
30
31 // Include Files
32 #include "ownet.h"
33 #include "mbshaee.h"
34
35 // External functions
36 extern SMALLINT owBlock(int,int,uchar *,int);
37 extern SMALLINT owReadByte(int);
38 extern SMALLINT owWriteByte(int,int);
39 extern void output_status(int, char *);
40 extern void msDelay(int);
41 extern void owSerialNum(int,uchar *,int);
42 extern SMALLINT owAccess(int);
43 extern SMALLINT owWriteByte(int,int);
44 extern void setcrc16(int,ushort);
45 extern ushort docrc16(int,ushort);
46 extern SMALLINT owWriteBytePower(int,int);
47 extern SMALLINT owLevel(int,int);
48 extern SMALLINT doSpeed(int,int);
49
50 // Local functions
51 SMALLINT writeSpad(int portnum, int addr, uchar *out_buf, int len);
52 SMALLINT readSpad(int portnum, ushort *addr, uchar *es, uchar *data);
53 SMALLINT copySpad(int portnum, int addr, uchar *SNum, uchar *extra_buf,
54 uchar *memory);
55 SMALLINT ReadAuthPage(SMALLINT bank, int portnum, int addr, uchar *SNum,
56 uchar *data, uchar *extra);
57 void ComputeSHA(unsigned int *MT,long *A,long *B, long *C, long *D,long *E);
58 long KTN (int n);
59 long NLF (long B, long C, long D, int n);
60
61
62 // General command defines
63 #define READ_MEMORY_SHAEE 0xF0
64 #define WRITE_SCRATCHPAD_SHAEE 0x0F
65 #define READ_SCRATCHPAD_SHAEE 0xAA
66 #define LOAD_FIRST_SECRET_SHAEE 0x5A
67 #define COPY_SCRATCHPAD_SHAEE 0x55
68 #define READ_AUTH_PAGE_SHAEE 0xA5
69 #define NEXT_SECRET_SHAEE 0x33
70
71 // Local defines
72 #define PAGE_LENGTH_SHAEE 32
73 #define SIZE_SHAEE_MB_0_1 32
74 #define SIZE_SHAEE_MB_2 32
75
76 // Global variables
77 char *bankDescriptionSHAEE = "";
78 SMALLINT writeVerificationSHAEE = TRUE;
79 SMALLINT generalPurposeMemorySHAEE = TRUE;
80 SMALLINT readWriteSHAEE = TRUE; // check memory status
81 SMALLINT writeOnceSHAEE = FALSE; // check memory status
82 SMALLINT readOnlySHAEE = FALSE; // check memory status
83 SMALLINT nonVolatileSHAEE = TRUE;
84 SMALLINT needProgramPulseSHAEE = FALSE;
85 SMALLINT needPowerDeliverySHAEE = FALSE;
86 SMALLINT ExtraInfoSHAEE = TRUE; // memory status page doesn't, so check bank
87 SMALLINT extraInfoLengthSHAEE = 20;
88 char *extraInfoDescSHAEE = "The MAC for the SHA Engine";
89 SMALLINT pageAutoCRCSHAEE = TRUE; // memory status page doesn't, so check bank
90
91 // Global variables to write and read from part
92 uchar local_secret[8];
93 uchar challenge[8];
94
95
96 /**
97 * Read memory in the current bank with no CRC checking (device or
98 * data). The resulting data from this API may or may not be what is on
99 * the 1-Wire device. It is recommends that the data contain some kind
100 * of checking (CRC) like in the readPagePacketSHAEE() method or have
101 * the 1-Wire device provide the CRC as in readPageCRCSHAEE(). readPageCRCSHAEE()
102 * however is not supported on all memory types, see 'hasPageAutoCRCSHAEE()'.
103 * If neither is an option then this method could be called more
104 * then once to at least verify that the same thing is read consistantly.
105 *
106 * bank to tell what memory bank of the ibutton to use.
107 * portnum the port number of the port being used for the
108 * 1-Wire Network.
109 * SNum the serial number for the part that the read is
110 * to be done on.
111 * str_add starting physical address
112 * rd_cont if 'true' then device read is continued without
113 * re-selecting. This can only be used if the new
114 * read() continious where the last one led off
115 * and it is inside a 'beginExclusive/endExclusive'
116 * block.
117 * buff byte array to place read data into
118 * len length in bytes to read
119 *
120 * @return 'true' if the read was complete
121 */
readSHAEE(SMALLINT bank,int portnum,uchar * SNum,int str_add,SMALLINT rd_cont,uchar * buff,int len)122 SMALLINT readSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add,
123 SMALLINT rd_cont, uchar *buff, int len)
124 {
125 int i;
126 int addr;
127 uchar raw_buf[3];
128
129 // check if read exceeds memory
130 if ((str_add + len) > (PAGE_LENGTH_SHAEE * getNumberPagesSHAEE(bank,SNum)))
131 {
132 OWERROR(OWERROR_READ_OUT_OF_RANGE);
133 return FALSE;
134 }
135
136 // see if need to access the device
137 if (!rd_cont)
138 {
139 // select the device
140 if (!owAccess(portnum))
141 {
142 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
143 return FALSE;
144 }
145
146 // build start reading memory block
147 addr = str_add + getStartingAddressSHAEE(bank,SNum);
148
149 raw_buf[0] = READ_MEMORY_SHAEE;
150 raw_buf[1] = addr & 0xFF;
151 raw_buf[2] = ((addr & 0xFFFF) >> 8) & 0xFF;
152
153 // do the first block for command, address
154 if(!owBlock(portnum,FALSE,raw_buf,3))
155 {
156 OWERROR(OWERROR_BLOCK_FAILED);
157 return FALSE;
158 }
159 }
160
161 // pre-fill readBuf with 0xFF
162 for(i=0;i<len;i++)
163 buff[i] = 0xFF;
164
165 if(!owBlock(portnum,FALSE,buff,len))
166 {
167 OWERROR(OWERROR_BLOCK_FAILED);
168 return FALSE;
169 }
170 return TRUE;
171 }
172
173 /**
174 * Write memory in the current bank. It is recommended that
175 * when writing data that some structure in the data is created
176 * to provide error free reading back with readSHAEE(). Or the
177 * method 'writePagePacketSHAEE()' could be used which automatically
178 * wraps the data in a length and CRC.
179 *
180 * When using on Write-Once devices care must be taken to write into
181 * into empty space. If write() is used to write over an unlocked
182 * page on a Write-Once device it will fail.
183 *
184 * bank to tell what memory bank of the ibutton to use.
185 * portnum the port number of the port being used for the
186 * 1-Wire Network.
187 * SNum the serial number for the part that the write is
188 * to be done on.
189 * str_add starting address
190 * buff byte array containing data to write
191 * len length in bytes to write
192 *
193 * @return 'true' if the write was complete.
194 */
writeSHAEE(SMALLINT bank,int portnum,uchar * SNum,int str_add,uchar * buff,int len)195 SMALLINT writeSHAEE(SMALLINT bank, int portnum, uchar *SNum, int str_add,
196 uchar *buff, int len)
197 {
198 int i, room_left;
199 int startx, nextx, abs_addr, pl;
200 uchar raw_buf[8];
201 uchar extra[20];
202 uchar memory[64];
203
204 // return if nothing to do
205 if (len == 0)
206 return TRUE;
207
208 // check if write exceeds memory
209 if ((str_add + len) > getSizeSHAEE(bank,SNum))
210 {
211 OWERROR(OWERROR_WRITE_OUT_OF_RANGE);
212 return FALSE;
213 }
214
215 // check if trying to write read only bank
216 if(isReadOnlySHAEE(bank,portnum,SNum))
217 {
218 OWERROR(OWERROR_READ_ONLY);
219 return FALSE;
220 }
221
222 // loop while still have pages to write
223 startx = 0;
224 nextx = 0; // (start and next index into writeBuf)
225 pl = 8;
226 abs_addr = getStartingAddressSHAEE(bank,SNum) + str_add;
227
228 if(!readSHAEE(bank,portnum,SNum,(str_add/PAGE_LENGTH_SHAEE)*PAGE_LENGTH_SHAEE,
229 FALSE,memory,PAGE_LENGTH_SHAEE))
230 return FALSE;
231
232 do
233 {
234 // calculate room left in current page
235 room_left = pl - ((abs_addr + startx) % pl);
236
237 // check if block left will cross end of page
238 if ((len - startx) > room_left)
239 nextx = startx + room_left;
240 else
241 nextx = len;
242
243 if((str_add+startx) >= PAGE_LENGTH_SHAEE)
244 if(!readSHAEE(bank,portnum,SNum,((str_add+startx)/PAGE_LENGTH_SHAEE)*PAGE_LENGTH_SHAEE,
245 FALSE,memory,PAGE_LENGTH_SHAEE))
246 return FALSE;
247
248 if((str_add+startx) >= PAGE_LENGTH_SHAEE)
249 for(i=0;i<8;i++)
250 raw_buf[i] = memory[((((startx+str_add)/8)*8)-32)+i];
251 else
252 for(i=0;i<8;i++)
253 raw_buf[i] = memory[(((startx+str_add)/8)*8)+i];
254
255 if((nextx-startx) == 8)
256 for(i=0;i<8;i++)
257 raw_buf[i] = buff[startx+i];
258 else
259 if(((str_add+nextx)%8) == 0)
260 for(i=0;i<(8-((str_add+startx)%8));i++)
261 raw_buf[((str_add+startx)%8)+i] = buff[startx+i];
262 else
263 for(i=0;i<(((str_add+nextx)%8)-((str_add+startx)%8));i++)
264 raw_buf[((str_add+startx)%8)+i] = buff[startx+i];
265
266 // write the page of data to scratchpad
267 if(!writeSpad(portnum,abs_addr+startx+room_left-8,raw_buf,8))
268 return FALSE;
269
270 // Copy data from scratchpad into memory
271 if(abs_addr > 127)
272 for(i=0;i<8;i++)
273 memory[i] = local_secret[i];
274
275 if(!copySpad(portnum,abs_addr+startx+room_left-8,SNum,extra,memory))
276 return FALSE;
277
278 if(str_add >= PAGE_LENGTH_SHAEE)
279 for(i=0;i<8;i++)
280 memory[((((startx+str_add)/8)*8)-32)+i] = raw_buf[i];
281 else
282 for(i=0;i<8;i++)
283 memory[(((startx+str_add)/8)*8)+i] = raw_buf[i];
284
285 // point to next index
286 startx = nextx;
287 }
288 while (nextx < len);
289
290 return TRUE;
291 }
292
293 /**
294 * Read page in the current bank with no
295 * CRC checking (device or data). The resulting data from this API
296 * may or may not be what is on the 1-Wire device. It is recommends
297 * that the data contain some kind of checking (CRC) like in the
298 * readPagePacketSHAEE() method or have the 1-Wire device provide the
299 * CRC as in readPageCRCSHAEE(). readPageCRCSHAEE() however is not
300 * supported on all memory types, see 'hasPageAutoCRCSHAEE()'.
301 * If neither is an option then this method could be called more
302 * then once to at least verify that the same thing is read consistantly.
303 *
304 * bank to tell what memory bank of the ibutton to use.
305 * portnum the port number of the port being used for the
306 * 1-Wire Network.
307 * SNum the serial number for the part.
308 * page the page to read
309 * rd_cont if 'true' then device read is continued without
310 * re-selecting. This can only be used if the new
311 * read() continious where the last one led off
312 * and it is inside a 'beginExclusive/endExclusive'
313 * block.
314 * buff byte array containing data that was read.
315 * len length in bytes to write
316 *
317 * @return - returns '0' if the read page wasn't completed.
318 * '1' if the operation is complete.
319 */
readPageSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff)320 SMALLINT readPageSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page,
321 SMALLINT rd_cont, uchar *buff)
322 {
323 return readSHAEE(bank,portnum,SNum,page*PAGE_LENGTH_SHAEE,FALSE,buff,PAGE_LENGTH_SHAEE);
324 }
325
326 /**
327 * Read page with extra information in the current bank with no
328 * CRC checking (device or data). The resulting data from this API
329 * may or may not be what is on the 1-Wire device. It is recommends
330 * that the data contain some kind of checking (CRC) like in the
331 * readPagePacketSHAEE() method or have the 1-Wire device provide the
332 * CRC as in readPageCRCSHAEE(). readPageCRCSHAEE() however is not
333 * supported on all memory types, see 'hasPageAutoCRCSHAEE()'.
334 * If neither is an option then this method could be called more
335 * then once to at least verify that the same thing is read consistantly.
336 * See the method 'hasExtraInfoSHAEE()' for a description of the optional
337 * extra information some devices have.
338 *
339 * bank to tell what memory bank of the ibutton to use.
340 * portnum the port number of the port being used for the
341 * 1-Wire Network.
342 * SNum the serial number for the part.
343 * page the page to read
344 * rd_cont if 'true' then device read is continued without
345 * re-selecting. This can only be used if the new
346 * read() continious where the last one led off
347 * and it is inside a 'beginExclusive/endExclusive'
348 * block.
349 * buff byte array containing data that was read
350 * len length in bytes to write
351 * extra the extra information
352 *
353 * @return - returns '0' if the read page wasn't completed with extra info.
354 * '1' if the operation is complete.
355 */
readPageExtraSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,uchar * extra)356 SMALLINT readPageExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page,
357 SMALLINT rd_cont, uchar *buff, uchar *extra)
358 {
359 int addr;
360
361 // if(!checked)
362 // checked = ib.checkStatus();
363
364 if(!hasExtraInfoSHAEE(bank,SNum))
365 {
366 OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED);
367 return FALSE;
368 }
369
370 // build start reading memory block
371 addr = page*PAGE_LENGTH_SHAEE;
372 if(!ReadAuthPage(bank,portnum,addr,SNum,buff,extra))
373 return FALSE;
374
375 return TRUE;
376 }
377
378 /**
379 * Read a complete memory page with CRC verification provided by the
380 * device with extra information. Not supported by all devices.
381 * See the method 'hasPageAutoCRC()'.
382 * See the method 'haveExtraInfo()' for a description of the optional
383 * extra information.
384 *
385 * bank to tell what memory bank of the ibutton to use.
386 * portnum the port number of the port being used for the
387 * 1-Wire Network.
388 * SNum the serial number for the part.
389 * page the page to read
390 * buff byte array containing data that was read.
391 * extra the extra information
392 *
393 * @return - returns '0' if the read page wasn't completed with extra info.
394 * '1' if the operation is complete.
395 */
readPageExtraCRCSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * read_buff,uchar * extra)396 SMALLINT readPageExtraCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page,
397 uchar *read_buff, uchar *extra)
398 {
399 int addr;
400
401 // if(!checked)
402 /// checked = ib.checkStatus();
403
404 if(!hasPageAutoCRCSHAEE(bank,SNum))
405 {
406 OWERROR(OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED);
407 return FALSE;
408 }
409
410 // build start reading memory block
411 addr = page * PAGE_LENGTH_SHAEE;
412 if(!ReadAuthPage(bank,portnum,addr,SNum,read_buff,extra))
413 return FALSE;
414
415 return TRUE;
416 }
417
418 /**
419 * Read a complete memory page with CRC verification provided by the
420 * device. Not supported by all devices. See the method
421 * 'hasPageAutoCRCSHAEE()'.
422 *
423 * bank to tell what memory bank of the ibutton to use.
424 * portnum the port number of the port being used for the
425 * 1-Wire Network.
426 * SNum the serial number for the part.
427 * page the page to read
428 * buff byte array containing data that was read
429 *
430 * @return - returns '0' if the read page wasn't completed.
431 * '1' if the operation is complete.
432 */
readPageCRCSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * buff)433 SMALLINT readPageCRCSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff)
434 {
435 return readSHAEE(bank,portnum,SNum,page*PAGE_LENGTH_SHAEE,FALSE,buff,PAGE_LENGTH_SHAEE);
436 }
437
438 /**
439 * Read a Universal Data Packet.
440 *
441 * The Universal Data Packet always starts on page boundaries but
442 * can end anywhere in the page. The structure specifies the length of
443 * data bytes not including the length byte and the CRC16 bytes.
444 * There is one length byte. The CRC16 is first initialized to
445 * the page number. This provides a check to verify the page that
446 * was intended is being read. The CRC16 is then calculated over
447 * the length and data bytes. The CRC16 is then iNVerted and stored
448 * low byte first followed by the high byte. This is structure is
449 * used by this method to verify the data but is not returned, only
450 * the data payload is returned.
451 *
452 * bank to tell what memory bank of the ibutton to use.
453 * portnum the port number of the port being used for the
454 * 1-Wire Network.
455 * SNum the serial number for the part.
456 * page the page to read
457 * rd_cont if 'true' then device read is continued without
458 * re-selecting. This can only be used if the new
459 * read() continious where the last one led off
460 * and it is inside a 'beginExclusive/endExclusive'
461 * block.
462 * buff byte array containing data that was read.
463 * len length of the packet
464 *
465 * @return - returns '0' if the read page packet wasn't completed
466 * '1' if the operation is complete.
467 */
readPagePacketSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len)468 SMALLINT readPagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page,
469 SMALLINT rd_cont, uchar *buff, int *len)
470 {
471 uchar raw_buf[PAGE_LENGTH_SHAEE];
472 ushort lastcrc16;
473 int i;
474
475 // read the page
476 if(!readPageSHAEE(bank,portnum,SNum,page,rd_cont,&raw_buf[0]))
477 return FALSE;
478
479 // check if length is realistic
480 if((raw_buf[0] & 0x00FF) > getMaxPacketDataLengthSHAEE(bank,SNum))
481 {
482 OWERROR(OWERROR_INVALID_PACKET_LENGTH);
483 return FALSE;
484 }
485 else if(raw_buf[0] == 0)
486 {
487 *len = raw_buf[0];
488 return TRUE;
489 }
490
491 // verify the CRC is correct
492 setcrc16(portnum,(ushort)((getStartingAddressSHAEE(bank,SNum)/PAGE_LENGTH_SHAEE) + page));
493 for(i=0;i<(raw_buf[0]+3);i++)
494 lastcrc16 = docrc16(portnum,raw_buf[i]);
495
496 if(lastcrc16 == 0x0000B001)
497 {
498 // extract the data out of the packet
499 for(i=0;i<raw_buf[0];i++)
500 buff[i] = raw_buf[i+1];
501
502 // extract the length
503 *len = (int) raw_buf[0];
504 }
505 else
506 {
507 OWERROR(OWERROR_CRC_FAILED);
508 return FALSE;
509 }
510
511 return TRUE;
512 }
513
514 /**
515 * Read a Universal Data Packet and extra information. See the
516 * method 'readPagePacketSHAEE()' for a description of the packet structure.
517 * See the method 'hasExtraInfoSHAEE()' for a description of the optional
518 * extra information some devices have.
519 *
520 * bank to tell what memory bank of the ibutton to use.
521 * portnum the port number of the port being used for the
522 * 1-Wire Network.
523 * SNum the serial number for the part.
524 * page the page to read
525 * rd_cont if 'true' then device read is continued without
526 * re-selecting. This can only be used if the new
527 * read() continious where the last one led off
528 * and it is inside a 'beginExclusive/endExclusive'
529 * block.
530 * buff byte array containing data that was read.
531 * len length of the packet
532 * extra extra information
533 *
534 * @return - returns '0' if the read page packet wasn't completed
535 * '1' if the operation is complete.
536 */
readPagePacketExtraSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len,uchar * extra)537 SMALLINT readPagePacketExtraSHAEE(SMALLINT bank, int portnum, uchar *SNum,
538 int page, SMALLINT rd_cont, uchar *buff,
539 int *len, uchar *extra)
540 {
541 uchar raw_buf[PAGE_LENGTH_SHAEE];
542 int addr;
543 int i;
544 ushort lastcrc16;
545
546 if(!hasExtraInfoSHAEE(bank,SNum))
547 {
548 OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED);
549 return FALSE;
550 }
551
552 addr = page * PAGE_LENGTH_SHAEE;
553
554 // read the page
555 if(!ReadAuthPage(bank,portnum,addr,SNum,&raw_buf[0],extra))
556 return FALSE;
557
558 // check if length is realistic
559 if ((raw_buf[0] & 0x00FF) > getMaxPacketDataLengthSHAEE(bank,SNum))
560 {
561 OWERROR(OWERROR_INVALID_PACKET_LENGTH);
562 return FALSE;
563 }
564 else if(raw_buf[0] == 0)
565 {
566 *len = raw_buf[0];
567 return TRUE;
568 }
569
570 // verify the CRC is correct
571 setcrc16(portnum,(ushort)((getStartingAddressSHAEE(bank,SNum)/PAGE_LENGTH_SHAEE) + page));
572 for(i=0;i<(raw_buf[0]+3);i++)
573 lastcrc16 = docrc16(portnum,raw_buf[i]);
574
575 if(lastcrc16 == 0x0000B001)
576 {
577 // extract the data out of the packet
578 for(i=0;i<raw_buf[0];i++)
579 buff[i] = raw_buf[i+1];
580
581 // return the length
582 *len = (int) raw_buf[0];
583 }
584 else
585 {
586 OWERROR(OWERROR_CRC_FAILED);
587 return FALSE;
588 }
589
590 return TRUE;
591
592 }
593
594 /**
595 * Write a Universal Data Packet. See the method 'readPagePacketSHAEE()'
596 * for a description of the packet structure.
597 *
598 * bank to tell what memory bank of the ibutton to use.
599 * portnum the port number of the port being used for the
600 * 1-Wire Network.
601 * SNum the serial number for the part.
602 * page the page the packet is being written to.
603 * rd_cont if 'true' then device read is continued without
604 * re-selecting. This can only be used if the new
605 * read() continious where the last one led off
606 * and it is inside a 'beginExclusive/endExclusive'
607 * block.
608 * buff byte array containing data that to write.
609 * len length of the packet
610 *
611 * @return - returns '0' if the write page packet wasn't completed
612 * '1' if the operation is complete.
613 */
writePagePacketSHAEE(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * buff,int len)614 SMALLINT writePagePacketSHAEE(SMALLINT bank, int portnum, uchar *SNum, int page,
615 uchar *buff, int len)
616 {
617 uchar raw_buf[PAGE_LENGTH_SHAEE];
618 ushort crc;
619 int i;
620
621 // make sure length does not exceed max
622 if(len > getMaxPacketDataLengthSHAEE(bank,SNum))
623 {
624 OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE);
625 return FALSE;
626 }
627
628 // see if this bank is general read/write
629 if (!isGeneralPurposeMemorySHAEE(bank,SNum))
630 {
631 OWERROR(OWERROR_NOT_GENERAL_PURPOSE);
632 return FALSE;
633 }
634
635 // construct the packet to write
636 raw_buf[0] = (uchar) len;
637
638 for(i=0;i<len;i++)
639 raw_buf[i+1] = buff[i];
640
641 // calculate crc
642 setcrc16(portnum,(ushort)((getStartingAddressSHAEE(bank,SNum)/PAGE_LENGTH_SHAEE) + page));
643 for(i=0;i<(len+1);i++)
644 crc = docrc16(portnum,raw_buf[i]);
645
646 raw_buf[len + 1] = (uchar) ~crc & 0xFF;
647 raw_buf[len + 2] = (uchar) ((~crc & 0xFFFF) >> 8) & 0xFF;
648
649 // write the packet, return result
650 if(!writeSHAEE(bank,portnum,SNum,page*PAGE_LENGTH_SHAEE,raw_buf,len+3))
651 return FALSE;
652
653 return TRUE;
654 }
655
656 /**
657 * Query to get the number of pages in current memory bank.
658 *
659 * bank to tell what memory bank of the ibutton to use.
660 * SNum the serial number for the part.
661 *
662 * @return number of pages in current memory bank
663 */
getNumberPagesSHAEE(SMALLINT bank,uchar * SNum)664 SMALLINT getNumberPagesSHAEE(SMALLINT bank, uchar *SNum)
665 {
666 SMALLINT pages;
667
668 if(bank == 2)
669 pages = 2;
670 else
671 pages = 1;
672
673 return pages;
674 }
675
676 /**
677 * Query to get the memory bank size in bytes.
678 *
679 * bank to tell what memory bank of the ibutton to use.
680 * SNum the serial number for the part.
681 *
682 * @return memory bank size in bytes.
683 */
getSizeSHAEE(SMALLINT bank,uchar * SNum)684 int getSizeSHAEE(SMALLINT bank, uchar *SNum)
685 {
686 int size;
687
688 if(bank == 2)
689 size = 64;
690 else
691 size = 32;
692
693 return size;
694 }
695
696 /**
697 * Query to get the starting physical address of this bank. Physical
698 * banks are sometimes sub-divided into logical banks due to changes
699 * in attributes.
700 *
701 * bank to tell what memory bank of the ibutton to use.
702 * SNum the serial number for the part.
703 *
704 * @return physical starting address of this logical bank.
705 */
getStartingAddressSHAEE(SMALLINT bank,uchar * SNum)706 int getStartingAddressSHAEE(SMALLINT bank, uchar *SNum)
707 {
708 int start = 0;
709
710 switch(bank)
711 {
712 case 0:
713 start = 0;
714 break;
715
716 case 1:
717 start = 32;
718 break;
719
720 case 2:
721 start = 64;
722 break;
723
724 case 3:
725 start = 128;
726 break;
727
728 default:
729 start = 0;
730 break;
731 }
732
733 return start;
734 }
735
736 /**
737 * Query to get page length in bytes in current memory bank.
738 *
739 * bank to tell what memory bank of the ibutton to use.
740 * SNum the serial number for the part.
741 *
742 * @return page length in bytes in current memory bank
743 */
getPageLengthSHAEE(SMALLINT bank,uchar * SNum)744 SMALLINT getPageLengthSHAEE(SMALLINT bank, uchar *SNum)
745 {
746 return PAGE_LENGTH_SHAEE;
747 }
748
749 /**
750 * Query to see get a string description of the current memory bank.
751 *
752 * bank to tell what memory bank of the ibutton to use.
753 * SNum the serial number for the part.
754 *
755 * @return String containing the memory bank description
756 */
getBankDescriptionSHAEE(SMALLINT bank,uchar * SNum)757 char *getBankDescriptionSHAEE(SMALLINT bank, uchar *SNum)
758 {
759 switch(bank)
760 {
761 case 0:
762 return "Page Zero with write protection.";
763 break;
764
765 case 1:
766 return "Page One with EPROM mode and write protection.";
767 break;
768
769 case 2:
770 return "Page Two and Three with write protection.";
771 break;
772
773 case 3:
774 return "Status Page that contains the secret and the status.";
775 break;
776
777 default:
778 return bankDescriptionSHAEE;
779 break;
780 }
781
782 return bankDescriptionSHAEE;
783 }
784
785 /**
786 * Query to see if the current memory bank is general purpose
787 * user memory. If it is NOT then it is Memory-Mapped and writing
788 * values to this memory will affect the behavior of the 1-Wire
789 * device.
790 *
791 * bank to tell what memory bank of the ibutton to use.
792 * SNum the serial number for the part.
793 *
794 * @return 'true' if current memory bank is general purpose
795 */
isGeneralPurposeMemorySHAEE(SMALLINT bank,uchar * SNum)796 SMALLINT isGeneralPurposeMemorySHAEE(SMALLINT bank, uchar *SNum)
797 {
798 SMALLINT gp = generalPurposeMemorySHAEE;
799
800 if(bank == 3)
801 gp = FALSE;
802
803 return gp;
804 }
805
806 /**
807 * Query to see if current memory bank is read/write.
808 *
809 * bank to tell what memory bank of the ibutton to use.
810 * SNum the serial number for the part.
811 *
812 * @return 'true' if current memory bank is read/write
813 */
isReadWriteSHAEE(SMALLINT bank,int portnum,uchar * SNum)814 SMALLINT isReadWriteSHAEE(SMALLINT bank, int portnum, uchar *SNum)
815 {
816 uchar status[8];
817 SMALLINT rw = readWriteSHAEE;
818
819 if(!readSHAEE(3,portnum,SNum,8,FALSE,&status[0],8))
820 return FALSE;
821
822 switch(bank)
823 {
824 case 0:
825 if( ((status[1] == 0xAA) || (status[1] == 0x55)) ||
826 ((status[5] == 0xAA) || (status[5] == 0x55)) )
827 rw = FALSE;
828 break;
829
830 case 1:
831 if((status[5] == 0xAA) || (status[5] == 0x55))
832 rw = FALSE;
833 break;
834
835 case 2:
836 if((status[5] == 0xAA) || (status[5] == 0x55))
837 rw = FALSE;
838
839 case 3:
840 rw = FALSE;
841 break;
842
843 default:
844 rw = readWriteSHAEE;
845 break;
846 }
847
848 return rw;
849 }
850
851 /**
852 * Query to see if current memory bank is write write once such
853 * as with EPROM technology.
854 *
855 * bank to tell what memory bank of the ibutton to use.
856 * SNum the serial number for the part.
857 *
858 * @return 'true' if current memory bank can only be written once
859 */
isWriteOnceSHAEE(SMALLINT bank,int portnum,uchar * SNum)860 SMALLINT isWriteOnceSHAEE(SMALLINT bank, int portnum, uchar *SNum)
861 {
862 uchar status[8];
863 SMALLINT once = writeOnceSHAEE;
864
865 if(bank == 1)
866 {
867 if(!readSHAEE(3,portnum,SNum,8,FALSE,&status[0],8))
868 return FALSE;
869
870 if((status[4] == 0xAA) || (status[4] == 0x55))
871 once = TRUE;
872 }
873
874 return once;
875 }
876
877 /**
878 * Query to see if current memory bank is read only.
879 *
880 * @return 'true' if current memory bank can only be read
881 */
isReadOnlySHAEE(SMALLINT bank,int portnum,uchar * SNum)882 SMALLINT isReadOnlySHAEE(SMALLINT bank, int portnum, uchar *SNum)
883 {
884 uchar status[8];
885 SMALLINT ro = readOnlySHAEE;
886
887 if(!readSHAEE(3,portnum,SNum,8,FALSE,&status[0],8))
888 return FALSE;
889
890 switch(bank)
891 {
892 case 0:
893 if( ((status[1] == 0xAA) || (status[1] == 0x55)) ||
894 ((status[5] == 0xAA) || (status[5] == 0x55)) )
895 ro = TRUE;
896 break;
897
898 case 1:
899 if((status[1] == 0xAA) || (status[1] == 0x55))
900 ro = TRUE;
901 break;
902
903 case 2:
904 if((status[1] == 0xAA) || (status[1] == 0x55))
905 ro = TRUE;
906 break;
907
908 default:
909 ro = readOnlySHAEE;
910 break;
911 }
912
913 return ro;
914 }
915
916 /**
917 * Query to see if current memory bank non-volatile. Memory is
918 * non-volatile if it retains its contents even when removed from
919 * the 1-Wire network.
920 *
921 * bank to tell what memory bank of the ibutton to use.
922 * SNum the serial number for the part.
923 *
924 * @return 'true' if current memory bank non volatile.
925 */
isNonVolatileSHAEE(SMALLINT bank,uchar * SNum)926 SMALLINT isNonVolatileSHAEE(SMALLINT bank, uchar *SNum)
927 {
928 return nonVolatileSHAEE;
929 }
930
931 /**
932 * Query to see if current memory bank pages need the adapter to
933 * have a 'ProgramPulse' in order to write to the memory.
934 *
935 * bank to tell what memory bank of the ibutton to use.
936 * SNum the serial number for the part.
937 *
938 * @return 'true' if writing to the current memory bank pages
939 * requires a 'ProgramPulse'.
940 */
needsProgramPulseSHAEE(SMALLINT bank,uchar * SNum)941 SMALLINT needsProgramPulseSHAEE(SMALLINT bank, uchar *SNum)
942 {
943 return needProgramPulseSHAEE;
944 }
945
946 /**
947 * Query to see if current memory bank pages need the adapter to
948 * have a 'PowerDelivery' feature in order to write to the memory.
949 *
950 * bank to tell what memory bank of the ibutton to use.
951 * SNum the serial number for the part.
952 *
953 * @return 'true' if writing to the current memory bank pages
954 * requires 'PowerDelivery'.
955 */
needsPowerDeliverySHAEE(SMALLINT bank,uchar * SNum)956 SMALLINT needsPowerDeliverySHAEE(SMALLINT bank, uchar *SNum)
957 {
958 return needPowerDeliverySHAEE;
959 }
960
961 /**
962 * Checks to see if this memory bank's pages deliver extra
963 * information outside of the normal data space, when read. Examples
964 * of this may be a redirection byte, counter, tamper protection
965 * bytes, or SHA-1 result. If this method returns true then the
966 * methods with an 'extraInfo' parameter can be used.
967 *
968 * bank to tell what memory bank of the ibutton to use.
969 * SNum the serial number for the part.
970 *
971 * @return true if reading the this memory bank's
972 * pages provides extra information
973 */
hasExtraInfoSHAEE(SMALLINT bank,uchar * SNum)974 SMALLINT hasExtraInfoSHAEE(SMALLINT bank, uchar *SNum)
975 {
976 SMALLINT extra = ExtraInfoSHAEE;
977
978 if(bank == 3)
979 extra = FALSE;
980
981 return extra;
982 }
983
984 /**
985 * Query to get the length in bytes of extra information that
986 * is read when read a page in the current memory bank. See
987 * 'hasExtraInfoSHAEE()'.
988 *
989 * bank to tell what memory bank of the ibutton to use.
990 * SNum the serial number for the part.
991 *
992 * @return number of bytes in Extra Information read when reading
993 * pages in the current memory bank.
994 */
getExtraInfoLengthSHAEE(SMALLINT bank,uchar * SNum)995 SMALLINT getExtraInfoLengthSHAEE(SMALLINT bank, uchar *SNum)
996 {
997 SMALLINT len = extraInfoLengthSHAEE;
998
999 if(bank == 3)
1000 len = 0;
1001
1002 return len;
1003 }
1004
1005 /**
1006 * Query to get a string description of what is contained in
1007 * the Extra Informationed return when reading pages in the current
1008 * memory bank. See 'hasExtraInfoSHAEE()'.
1009 *
1010 * bank to tell what memory bank of the ibutton to use.
1011 * SNum the serial number for the part.
1012 *
1013 * @return string describing extra information.
1014 */
getExtraInfoDescSHAEE(SMALLINT bank,uchar * SNum)1015 char *getExtraInfoDescSHAEE(SMALLINT bank, uchar *SNum)
1016 {
1017 if(bank == 3)
1018 return "";
1019
1020 return extraInfoDescSHAEE;
1021 }
1022
1023 /**
1024 * Query to see if current memory bank pages can be read with
1025 * the contents being verified by a device generated CRC.
1026 * This is used to see if the 'ReadPageCRCSHAEE()' can be used.
1027 *
1028 * bank to tell what memory bank of the ibutton to use.
1029 * SNum the serial number for the part.
1030 *
1031 * @return 'true' if current memory bank can be read with self
1032 * generated CRC.
1033 */
hasPageAutoCRCSHAEE(SMALLINT bank,uchar * SNum)1034 SMALLINT hasPageAutoCRCSHAEE(SMALLINT bank, uchar *SNum)
1035 {
1036 SMALLINT autoCRC = pageAutoCRCSHAEE;
1037
1038 if(bank == 3)
1039 autoCRC = FALSE;
1040
1041 return autoCRC;
1042 }
1043
1044 /**
1045 * Query to get Maximum data page length in bytes for a packet
1046 * read or written in the current memory bank. See the 'ReadPagePacket()'
1047 * and 'WritePagePacket()' methods. This method is only usefull
1048 * if the current memory bank is general purpose memory.
1049 *
1050 * @return max packet page length in bytes in current memory bank
1051 */
getMaxPacketDataLengthSHAEE(SMALLINT bank,uchar * SNum)1052 SMALLINT getMaxPacketDataLengthSHAEE(SMALLINT bank, uchar *SNum)
1053 {
1054 return PAGE_LENGTH_SHAEE - 3;
1055 }
1056
1057 /**
1058 * Query to see if current memory bank pages can be redirected
1059 * to another pages. This is mostly used in Write-Once memory
1060 * to provide a means to update.
1061 *
1062 * bank to tell what memory bank of the ibutton to use.
1063 * SNum the serial number for the part.
1064 *
1065 * @return 'true' if current memory bank pages can be redirected
1066 * to a new page.
1067 */
canRedirectPageSHAEE(SMALLINT bank,uchar * SNum)1068 SMALLINT canRedirectPageSHAEE(SMALLINT bank, uchar *SNum)
1069 {
1070 return FALSE;
1071 }
1072
1073 /**
1074 * Query to see if current memory bank pages can be locked. A
1075 * locked page would prevent any changes to the memory.
1076 *
1077 * bank to tell what memory bank of the ibutton to use.
1078 * SNum the serial number for the part.
1079 *
1080 * @return 'true' if current memory bank pages can be redirected
1081 * to a new page.
1082 */
canLockPageSHAEE(SMALLINT bank,uchar * SNum)1083 SMALLINT canLockPageSHAEE(SMALLINT bank, uchar *SNum)
1084 {
1085 return FALSE;
1086 }
1087
1088 /**
1089 * Query to see if current memory bank pages can be locked from
1090 * being redirected. This would prevent a Write-Once memory from
1091 * being updated.
1092 *
1093 * bank to tell what memory bank of the ibutton to use.
1094 * SNum the serial number for the part.
1095 *
1096 * @return 'true' if current memory bank pages can be locked from
1097 * being redirected to a new page.
1098 */
canLockRedirectPageSHAEE(SMALLINT bank,uchar * SNum)1099 SMALLINT canLockRedirectPageSHAEE(SMALLINT bank, uchar *SNum)
1100 {
1101 return FALSE;
1102 }
1103
1104
1105 // ------------------------
1106 // Extras
1107 // ------------------------
1108
1109 /**
1110 * Write to the Scratch Pad, which is a max of 8 bytes.
1111 *
1112 * portnum the port number of the port being used for the
1113 * 1-Wire Network.
1114 * addr the address to write the data to
1115 * out_buf byte array to write into scratch pad
1116 * len length of the write data
1117 *
1118 * @return - returns 'TRUE' if scratch pad was written correctly
1119 * and 'FALSE' if not.
1120 */
writeSpad(int portnum,int addr,uchar * out_buf,int len)1121 SMALLINT writeSpad(int portnum, int addr, uchar *out_buf, int len)
1122 {
1123 uchar send_block[64];
1124 ushort lastcrc16;
1125 int i, cnt;
1126
1127 cnt = 0;
1128
1129 // access the device
1130 if(owAccess(portnum))
1131 {
1132 send_block[cnt++] = WRITE_SCRATCHPAD_SHAEE;
1133 send_block[cnt++] = addr & 0xFF;
1134 send_block[cnt++] = ((addr & 0xFFFF) >> 8) & 0xFF;
1135
1136 for(i=0;i<len;i++)
1137 send_block[cnt++] = out_buf[i];
1138
1139 send_block[cnt++] = 0xFF;
1140 send_block[cnt++] = 0xFF;
1141
1142
1143 if(!owBlock(portnum,FALSE,send_block,cnt))
1144 {
1145 OWERROR(OWERROR_BLOCK_FAILED);
1146 return FALSE;
1147 }
1148
1149 // verify the CRC is correct
1150 setcrc16(portnum,0);
1151 for(i=0;i<cnt;i++)
1152 lastcrc16 = docrc16(portnum,send_block[i]);
1153
1154 if(lastcrc16 != 0x0000B001)
1155 {
1156 OWERROR(OWERROR_CRC_FAILED);
1157 return FALSE;
1158 }
1159 }
1160 else
1161 {
1162 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1163 return FALSE;
1164 }
1165
1166 return TRUE;
1167 }
1168
1169 /**
1170 * Copy what is in the Sratch Pad, which is a max of 8 bytes to a certain
1171 * address in memory.
1172 *
1173 * portnum the port number of the port being used for the
1174 * 1-Wire Network.
1175 * addr the address to copy the data to
1176 * SNum the serial number for the part.
1177 * extra_buf byte array to write the calculated MAC
1178 * memory byte array for memory of the page to be copied to
1179 *
1180 * @return - returns 'TRUE' if the scratch pad was copied correctly
1181 * and 'FALSE' if not.
1182 */
copySpad(int portnum,int addr,uchar * SNum,uchar * extra_buf,uchar * memory)1183 SMALLINT copySpad(int portnum, int addr, uchar *SNum, uchar *extra_buf, uchar *memory)
1184 {
1185 short send_cnt=0;
1186 ushort tmpadd;
1187 uchar send_block[80];
1188 int i;
1189 uchar scratch[8],es,test;
1190 unsigned MT[64];
1191 long A,B,C,D,E;
1192 long Temp;
1193
1194 for(i=0;i<4;i++)
1195 MT[i] = local_secret[i];
1196
1197 for(i=4;i<32;i++)
1198 MT[i] = memory[i-4];
1199
1200 if(readSpad(portnum, &tmpadd, &es, scratch))
1201 for(i=32;i<40;i++)
1202 MT[i] = scratch[i-32];
1203 else
1204 return FALSE;
1205
1206 MT[40] = (addr & 0xf0) >> 5;
1207
1208 for(i=41;i<48;i++)
1209 MT[i] = SNum[i-41];
1210
1211 for(i=48;i<52;i++)
1212 MT[i] = local_secret[i-44];
1213
1214 for(i=52;i<55;i++)
1215 MT[i] = 0xff;
1216
1217 MT[55] = 0x80;
1218
1219 for(i=56;i<62;i++)
1220 MT[i] = 0x00;
1221
1222 MT[62] = 0x01;
1223 MT[63] = 0xB8;
1224
1225 ComputeSHA(MT,&A,&B,&C,&D,&E);
1226
1227 // access the device
1228 if(owAccess(portnum))
1229 {
1230 // Copy command
1231 send_block[send_cnt++] = 0x55;
1232
1233 // address 1
1234 send_block[send_cnt++] = (uchar)(tmpadd & 0xFF);
1235 // address 2
1236 send_block[send_cnt++] = (uchar)((tmpadd >> 8) & 0xFF);
1237
1238 // ending address with data status
1239 send_block[send_cnt++] = es;
1240
1241 if(owBlock(portnum,FALSE,send_block,send_cnt))
1242 {
1243 send_cnt = 0;
1244
1245 // sending MAC
1246 Temp = E;
1247 for(i=0;i<4;i++)
1248 {
1249 send_block[send_cnt++] = (uchar) (Temp & 0x000000FF);
1250 extra_buf[i] = send_block[send_cnt-1];
1251 Temp >>= 8;
1252 }
1253
1254 Temp = D;
1255 for(i=0;i<4;i++)
1256 {
1257 send_block[send_cnt++] = (uchar) (Temp & 0x000000FF);
1258 extra_buf[i] = send_block[send_cnt-1];
1259 Temp >>= 8;
1260 }
1261
1262 Temp = C;
1263 for(i=0;i<4;i++)
1264 {
1265 send_block[send_cnt++] = (uchar) (Temp & 0x000000FF);
1266 extra_buf[i] = send_block[send_cnt-1];
1267 Temp >>= 8;
1268 }
1269
1270 Temp = B;
1271 for(i=0;i<4;i++)
1272 {
1273 send_block[send_cnt++] = (uchar) (Temp & 0x000000FF);
1274 extra_buf[i] = send_block[send_cnt-1];
1275 Temp >>= 8;
1276 }
1277
1278 Temp = A;
1279 for(i=0;i<4;i++)
1280 {
1281 send_block[send_cnt++] = (uchar) (Temp & 0x000000FF);
1282 extra_buf[i] = send_block[send_cnt-1];
1283 Temp >>= 8;
1284 }
1285
1286 msDelay(2);
1287
1288 if(owBlock(portnum,FALSE,send_block,send_cnt))
1289 {
1290 msDelay(10);
1291
1292 test = owReadByte(portnum);
1293
1294 if((test == 0xAA) || (test == 0x55))
1295 return TRUE;
1296 else
1297 {
1298 if(test == 0xFF)
1299 {
1300 OWERROR(OWERROR_WRITE_PROTECTED);
1301 return FALSE;
1302 }
1303 else if(test == 0x00)
1304 {
1305 OWERROR(OWERROR_NONMATCHING_MAC);
1306 return FALSE;
1307 }
1308 }
1309 }
1310
1311 OWERROR(OWERROR_BLOCK_FAILED);
1312 return FALSE;
1313
1314 }
1315 else
1316 {
1317 OWERROR(OWERROR_BLOCK_FAILED);
1318 return FALSE;
1319 }
1320
1321 }
1322 else
1323 {
1324 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1325 return FALSE;
1326 }
1327
1328
1329 return FALSE;
1330 }
1331
1332 /**
1333 * Read from the Scratch Pad, which is a max of 8 bytes.
1334 *
1335 * portnum number 0 to MAX_PORTNUM-1. This number is provided to
1336 * indicate the symbolic port number.
1337 * addr the address to read the data
1338 * es offset byte read from scratchpad
1339 * data data buffer read from scratchpad
1340 *
1341 * @return - returns 'TRUE' if the scratch pad was read correctly
1342 * and 'FALSE' if not
1343 */
readSpad(int portnum,ushort * addr,uchar * es,uchar * data)1344 SMALLINT readSpad(int portnum, ushort *addr, uchar *es, uchar *data)
1345 {
1346 short send_cnt=0;
1347 uchar send_block[50];
1348 int i;
1349 ushort lastcrc16;
1350
1351 // access the device
1352 if(owAccess(portnum))
1353 {
1354 // read scratchpad command
1355 send_block[send_cnt++] = 0xAA;
1356 // now add the read bytes for data bytes and crc16
1357 for(i=0; i<13; i++)
1358 send_block[send_cnt++] = 0xFF;
1359
1360 // now send the block
1361 if (owBlock(portnum,FALSE,send_block,send_cnt))
1362 {
1363 // copy data to return buffers
1364 *addr = (send_block[2] << 8) | send_block[1];
1365 *es = send_block[3];
1366
1367 // calculate CRC16 of result
1368 setcrc16(portnum,0);
1369 for (i = 0; i < send_cnt ; i++)
1370 lastcrc16 = docrc16(portnum,send_block[i]);
1371
1372 // verify CRC16 is correct
1373 if (lastcrc16 == 0xB001)
1374 {
1375 for (i = 0; i < 8; i++)
1376 data[i] = send_block[4 + i];
1377 // success
1378 return TRUE;
1379 }
1380 else
1381 {
1382 OWERROR(OWERROR_CRC_FAILED);
1383 return FALSE;
1384 }
1385 }
1386 else
1387 {
1388 OWERROR(OWERROR_BLOCK_FAILED);
1389 return FALSE;
1390 }
1391
1392 }
1393 else
1394 {
1395 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1396 return FALSE;
1397 }
1398
1399
1400 return FALSE;
1401 }
1402
1403 /**
1404 * Reads authenticated page.
1405 *
1406 * portnum number 0 to MAX_PORTNUM-1. This number is provided to
1407 * indicate the symbolic port number.
1408 * addr address of the data to be read along with Physical address
1409 * SNum the serial number for the part.
1410 * data the data read from the address
1411 * extra the MAC calculated for this function
1412 *
1413 * @return - returns 'TRUE' if the page was read and had the correct MAC
1414 * and 'FALSE' if not.
1415 */
ReadAuthPage(SMALLINT bank,int portnum,int addr,uchar * SNum,uchar * data,uchar * extra)1416 SMALLINT ReadAuthPage(SMALLINT bank, int portnum, int addr, uchar *SNum,
1417 uchar *data, uchar *extra)
1418 {
1419 short send_cnt=0;
1420 uchar send_block[80];
1421 int i;
1422 //jpe long A,B,C,D,E;
1423 //jpe long Temp;
1424 //jpe unsigned MT[64];
1425 //jpe uchar memory[32],scratch[8],es;
1426 //jpe ushort tmpadd;
1427 ushort lastcrc16;
1428
1429 if(!writeSpad(portnum,addr,&challenge[0],8))
1430 return FALSE;
1431
1432 /*jpe for(i=0;i<4;i++)
1433 MT[i] = local_secret[i];
1434
1435 if(!readSHAEE(bank,portnum,SNum,((addr/32)*32),FALSE,memory,32))
1436 return FALSE;
1437
1438 for(i=4;i<36;i++)
1439 MT[i] = memory[i-4];
1440
1441 for(i=36;i<40;i++)
1442 MT[i] = 0xFF;
1443
1444 if(!readSpad(portnum, &tmpadd, &es, scratch))
1445 return FALSE;
1446
1447 MT[40] = (0x40 | (uchar)(((tmpadd << 3) & 0x08) |
1448 (uchar)((tmpadd >> 5) & 0x07)));
1449
1450 for(i=41;i<48;i++)
1451 MT[i] = SNum[i-41];
1452
1453 for(i=48;i<52;i++)
1454 MT[i] = local_secret[i-44];
1455
1456 for(i=52;i<55;i++)
1457 MT[i] = scratch[i-48];
1458
1459 MT[55] = 0x80;
1460
1461 for(i=56;i<62;i++)
1462 MT[i] = 0x00;
1463
1464 MT[62] = 0x01;
1465 MT[63] = 0xB8;
1466
1467 ComputeSHA(MT,&A,&B,&C,&D,&E);
1468 jpe*/
1469 // access the device
1470 if(owAccess(portnum))
1471 {
1472 setcrc16(portnum,0);
1473
1474 // Read Authenticated Command
1475 send_block[send_cnt] = 0xA5;
1476 docrc16(portnum,send_block[send_cnt++]);
1477
1478 // address 1
1479 //jpe send_block[send_cnt] = (uchar)(tmpadd & 0xFF);
1480 send_block[send_cnt] = (uchar)(addr & 0xFF);
1481 docrc16(portnum,send_block[send_cnt++]);
1482 // address 2
1483 //jpe send_block[send_cnt] = (uchar)((tmpadd >> 8) & 0xFF);
1484 send_block[send_cnt] = (uchar)((addr >> 8) & 0xFF);
1485 docrc16(portnum,send_block[send_cnt++]);
1486
1487 // data + FF byte
1488 for (i = 0; i < 35; i++)
1489 send_block[send_cnt++] = 0xFF;
1490
1491 // now send the block
1492 if (owBlock(portnum,FALSE,send_block,send_cnt))
1493 {
1494 // calculate CRC16 of result
1495 for (i = 3; i < send_cnt; i++)
1496 lastcrc16 = docrc16(portnum,send_block[i]);
1497
1498 // verify CRC16 is correct
1499 if (lastcrc16 != 0xB001)
1500 {
1501 OWERROR(OWERROR_CRC_FAILED);
1502 return FALSE;
1503 }
1504
1505 for(i=3;i<35;i++)
1506 data[i-3] = send_block[i];
1507
1508 send_cnt = 0;
1509 for(i=0;i<22;i++)
1510 send_block[send_cnt++] = 0xFF;
1511
1512 // Delay for MAC
1513 msDelay(2);
1514
1515 if(owBlock(portnum,FALSE,send_block,send_cnt))
1516 {
1517 // calculate CRC16 of result
1518 setcrc16(portnum,0);
1519 for (i = 0; i < send_cnt ; i++)
1520 lastcrc16 = docrc16(portnum,send_block[i]);
1521
1522 // verify CRC16 is correct
1523 if (lastcrc16 != 0xB001)
1524 {
1525 OWERROR(OWERROR_CRC_FAILED);
1526 return FALSE;
1527 }
1528
1529 /*jpe send_cnt = 0;
1530 Temp = E;
1531 for(i=0;i<4;i++)
1532 {
1533 if(send_block[send_cnt++] != (uchar) (Temp & 0x000000FF))
1534 {
1535 OWERROR(OWERROR_NONMATCHING_MAC);
1536 return FALSE;
1537 }
1538 Temp >>= 8;
1539 }
1540
1541 Temp = D;
1542 for(i=0;i<4;i++)
1543 {
1544 if(send_block[send_cnt++] != (uchar) (Temp & 0x000000FF))
1545 {
1546 OWERROR(OWERROR_NONMATCHING_MAC);
1547 return FALSE;
1548 }
1549 Temp >>= 8;
1550 }
1551
1552 Temp = C;
1553 for(i=0;i<4;i++)
1554 {
1555 if(send_block[send_cnt++] != (uchar) (Temp & 0x000000FF))
1556 {
1557 OWERROR(OWERROR_NONMATCHING_MAC);
1558 return FALSE;
1559 }
1560 Temp >>= 8;
1561 }
1562
1563 Temp = B;
1564 for(i=0;i<4;i++)
1565 {
1566 if(send_block[send_cnt++] != (uchar) (Temp & 0x000000FF))
1567 {
1568 OWERROR(OWERROR_NONMATCHING_MAC);
1569 return FALSE;
1570 }
1571 Temp >>= 8;
1572 }
1573
1574 Temp = A;
1575 for(i=0;i<4;i++)
1576 {
1577 if(send_block[send_cnt++] != (uchar) (Temp & 0x000000FF))
1578 {
1579 OWERROR(OWERROR_NONMATCHING_MAC);
1580 return FALSE;
1581 }
1582 Temp >>= 8;
1583 }
1584 jpe*/
1585 for(i=0;i<20;i++)
1586 extra[i] = send_block[i];
1587
1588 return TRUE;
1589 }
1590 else
1591 {
1592 OWERROR(OWERROR_BLOCK_FAILED);
1593 return FALSE;
1594 }
1595
1596 }
1597 else
1598 {
1599 OWERROR(OWERROR_BLOCK_FAILED);
1600 return FALSE;
1601 }
1602
1603 }
1604 else
1605 {
1606 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1607 return FALSE;
1608 }
1609
1610
1611 return FALSE;
1612 }
1613
1614 /**
1615 * Loads data into memory without a copy scratchpad
1616 *
1617 * portnum number 0 to MAX_PORTNUM-1. This number is provided to
1618 * indicate the symbolic port number.
1619 * addr address of the data to be read along with Physical address
1620 * SNum the serial number for the part.
1621 * secret the load first secret data
1622 * data_len the length of the secret.
1623 *
1624 * @return - returns 'TRUE' if load first secret worked
1625 * and 'FALSE' if not.
1626 */
loadFirstSecret(int portnum,int addr,uchar * SNum,uchar * secret,int data_len)1627 SMALLINT loadFirstSecret(int portnum, int addr, uchar *SNum, uchar *secret, int data_len)
1628 {
1629 ushort tempadd;
1630 uchar es,data[8],test;
1631 uchar send_block[32];
1632 int send_cnt=0;
1633 uchar mem[32];
1634 int i;
1635
1636 if(readSHAEE(3,portnum,SNum,0,FALSE,mem,16))
1637 {
1638 if((mem[8] == 0xAA) || (mem[8] == 0x55))
1639 {
1640 OWERROR(OWERROR_WRITE_PROTECT_SECRET);
1641 return FALSE;
1642 }
1643
1644 if(((addr < 32)) &&
1645 (((mem[9] == 0xAA) || (mem[9] == 0x55)) ||
1646 ((mem[13] == 0xAA) || (mem[13] == 0x55))))
1647 {
1648 OWERROR(OWERROR_WRITE_PROTECT);
1649 return FALSE;
1650 }
1651
1652 if(((addr < 128)) &&
1653 ((mem[9] == 0xAA) || (mem[9] == 0x55)))
1654 {
1655 OWERROR(OWERROR_WRITE_PROTECT);
1656 return FALSE;
1657 }
1658 }
1659
1660
1661 if(writeSpad(portnum,addr,secret,data_len) &&
1662 readSpad(portnum,&tempadd,&es,data))
1663 {
1664
1665 // access the device
1666 if(owAccess(portnum))
1667 {
1668 // write scratchpad command
1669 send_block[send_cnt++] = 0x5A;
1670 // address 1
1671 send_block[send_cnt++] = (uchar)(tempadd & 0xFF);
1672 // address 2
1673 send_block[send_cnt++] = (uchar)((tempadd >> 8) & 0xFF);
1674 // ending address with data status
1675 send_block[send_cnt++] = es;
1676
1677 if(owBlock(portnum,FALSE,send_block,send_cnt))
1678 {
1679 // 10ms delay for writing first secret
1680 msDelay(10);
1681
1682 test = owReadByte(portnum);
1683
1684 if((test == 0xAA) || (test == 0x55))
1685 {
1686 if(addr == 128)
1687 {
1688 for(i=0;i<8;i++)
1689 local_secret[i] = secret[i];
1690 }
1691
1692 return TRUE;
1693 }
1694 else
1695 {
1696 OWERROR(OWERROR_LOAD_FIRST_SECRET);
1697 return FALSE;
1698 }
1699 }
1700 else
1701 {
1702 OWERROR(OWERROR_BLOCK_FAILED);
1703 return FALSE;
1704 }
1705 }
1706 else
1707 {
1708 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1709 return FALSE;
1710 }
1711
1712 }
1713
1714 return FALSE;
1715 }
1716
1717 /**
1718 * Calculate the next secret using the current one.
1719 *
1720 * portnum number 0 to MAX_PORTNUM-1. This number is provided to
1721 * indicate the symbolic port number.
1722 * addr address of the data to be read along with Physical address
1723 * SNum the serial number for the part.
1724 * secret the load first secret data
1725 *
1726 * @return - returns 'TRUE' if the next secret was calculated correctly
1727 * and 'FALSE' if not.
1728 */
computeNextSecret(int portnum,int addr,uchar * SNum,uchar * secret)1729 SMALLINT computeNextSecret(int portnum, int addr, uchar *SNum, uchar *secret)
1730 {
1731 int i;
1732 unsigned MT[64];
1733 long A,B,C,D,E;
1734 long Temp;
1735 uchar memory[32],scratch[8],es;
1736 ushort tmpadd;
1737 uchar send_block[32];
1738 int send_cnt=0;
1739 SMALLINT bank;
1740
1741 for(i=0;i<8;i++)
1742 scratch[i] = 0x00;
1743
1744 if(!writeSpad(portnum,addr,scratch,8))
1745 return FALSE;
1746
1747 for(i=0;i<4;i++)
1748 MT[i] = local_secret[i];
1749
1750 if(addr < 32)
1751 bank = 0;
1752 else if((addr > 31) && (addr < 64))
1753 bank = 1;
1754 else if((addr > 63) && (addr < 128))
1755 bank = 2;
1756
1757 if(readSHAEE(bank,portnum,SNum,(addr/((ushort)32))*32,FALSE,memory,32))
1758 for(i=4;i<36;i++)
1759 MT[i] = memory[i-4];
1760 else
1761 return FALSE;
1762
1763 for(i=36;i<40;i++)
1764 MT[i] = 0xFF;
1765
1766 if(readSpad(portnum, &tmpadd, &es, scratch))
1767 {
1768 MT[40] = scratch[0] & 0x3F;
1769
1770 for(i=41;i<48;i++)
1771 MT[i] = scratch[i-40];
1772 for(i=48;i<52;i++)
1773 MT[i] = local_secret[i-44];
1774 }
1775 else
1776 return FALSE;
1777
1778 for(i=52;i<55;i++)
1779 MT[i] = 0xFF;
1780
1781 MT[55] = 0x80;
1782
1783 for(i=56;i<62;i++)
1784 MT[i] = 0x00;
1785
1786 MT[62] = 0x01;
1787 MT[63] = 0xB8;
1788
1789 ComputeSHA(MT,&A,&B,&C,&D,&E);
1790
1791 Temp = E;
1792 for(i=0;i<4;i++)
1793 {
1794 secret[i] = (uchar) (Temp & 0x000000FF);
1795 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1796 // printf("%02X",secret[i]);
1797 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1798 Temp >>= 8;
1799 }
1800 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1801 // printf("\n");
1802 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1803
1804 Temp = D;
1805 for(i=0;i<4;i++)
1806 {
1807 secret[i+4] = (uchar) (Temp & 0x000000FF);
1808 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1809 // printf("%02X",secret[i+4]);
1810 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1811 Temp >>= 8;
1812 }
1813 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1814 // printf("\n");
1815 //\\//\\//\\//\\// DEBUG: printing out what the next secret is.
1816
1817 // access the device
1818 if(owAccess(portnum))
1819 {
1820 // Next Secret command
1821 send_block[send_cnt++] = 0x33;
1822
1823 // address 1
1824 send_block[send_cnt++] = (uchar)(addr & 0xFF);
1825 // address 2
1826 send_block[send_cnt++] = (uchar)((addr >> 8) & 0xFF);
1827
1828
1829 if(owBlock(portnum,FALSE,send_block,send_cnt))
1830 {
1831 msDelay(12);
1832
1833 if(readSpad(portnum, &tmpadd, &es, scratch))
1834 {
1835 for(i=0;i<8;i++)
1836 if(scratch[i] != 0xAA)
1837 {
1838 OWERROR(OWERROR_COMPUTE_NEXT_SECRET);
1839 return FALSE;
1840 }
1841
1842 for(i=0;i<8;i++)
1843 local_secret[i] = secret[i];
1844
1845 return TRUE;
1846 }
1847 }
1848 else
1849 {
1850 OWERROR(OWERROR_BLOCK_FAILED);
1851 return FALSE;
1852 }
1853
1854 }
1855 else
1856 {
1857 OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1858 return FALSE;
1859 }
1860
1861 return FALSE;
1862
1863 }
1864
1865 /**
1866 * This function set the bus master secret, which is used in
1867 * calculating the MAC that is sent to the part for different
1868 * operations.
1869 *
1870 * new_secret is the new bus master secret to be set.
1871 */
setBusMasterSecret(uchar * new_secret)1872 void setBusMasterSecret(uchar *new_secret)
1873 {
1874 int i;
1875
1876 for(i=0;i<8;i++)
1877 local_secret[i] = new_secret[i];
1878 }
1879
1880 /**
1881 * This function returns what the current bus master secret is.
1882 *
1883 * return_secret is used to copy what the current bus master
1884 * secret is.
1885 */
returnBusMasterSecret(uchar * return_secret)1886 void returnBusMasterSecret(uchar *return_secret)
1887 {
1888 int i;
1889
1890 for(i=0;i<8;i++)
1891 return_secret[i] = local_secret[i];
1892 }
1893
1894 /**
1895 * This function set the challenge, which resides in the
1896 * scratch pad for doing a read authenticate page command.
1897 *
1898 * new_challenge this is what the new challenge is going
1899 * to be set to.
1900 */
setChallenge(uchar * new_challenge)1901 void setChallenge(uchar *new_challenge)
1902 {
1903 int i;
1904
1905 for(i=0;i<8;i++)
1906 challenge[i] = new_challenge[i];
1907 }
1908
1909 //----------------------------------------------------------------------
1910 // Compute the 160-bit MAC
1911 //
1912 // 'MT' - input data
1913 // 'A' - part of the 160 bits
1914 // 'B' - part of the 160 bits
1915 // 'C' - part of the 160 bits
1916 // 'D' - part of the 160 bits
1917 // 'E' - part of the 160 bits
1918 //
1919 //
ComputeSHA(unsigned int * MT,long * A,long * B,long * C,long * D,long * E)1920 void ComputeSHA(unsigned int *MT,long *A,long *B, long *C, long *D,long *E)
1921 {
1922 unsigned long MTword[80];
1923 int i;
1924 long ShftTmp;
1925 long Temp;
1926
1927 for(i=0;i<16;i++)
1928 MTword[i] = (MT[i*4] << 24) | (MT[i*4+1] << 16) |
1929 (MT[i*4+2] << 8) | MT[i*4+3];
1930
1931 for(i=16;i<80;i++)
1932 {
1933 ShftTmp = MTword[i-3] ^ MTword[i-8] ^ MTword[i-14] ^ MTword[i-16];
1934 MTword[i] = ((ShftTmp << 1) & 0xfffffffe) |
1935 ((ShftTmp >> 31) & 0x00000001);
1936 }
1937
1938 *A=0x67452301;
1939 *B=0xefcdab89;
1940 *C=0x98badcfe;
1941 *D=0x10325476;
1942 *E=0xc3d2e1f0;
1943
1944 for(i=0;i<80;i++)
1945 {
1946 ShftTmp = ((*A << 5) & 0xffffffe0) | ((*A >> 27) & 0x0000001f);
1947 Temp = NLF(*B,*C,*D,i) + *E + KTN(i) + MTword[i] + ShftTmp;
1948 *E = *D;
1949 *D = *C;
1950 *C = ((*B << 30) & 0xc0000000) | ((*B >> 2) & 0x3fffffff);
1951 *B = *A;
1952 *A = Temp;
1953 }
1954 }
1955
1956 // calculation used for the MAC
KTN(int n)1957 long KTN (int n)
1958 {
1959 if(n<20)
1960 return 0x5a827999;
1961 else if (n<40)
1962 return 0x6ed9eba1;
1963 else if (n<60)
1964 return 0x8f1bbcdc;
1965 else
1966 return 0xca62c1d6;
1967 }
1968
1969 // calculation used for the MAC
NLF(long B,long C,long D,int n)1970 long NLF (long B, long C, long D, int n)
1971 {
1972 if(n<20)
1973 return ((B&C)|((~B)&D));
1974 else if(n<40)
1975 return (B^C^D);
1976 else if(n<60)
1977 return ((B&C)|(B&D)|(C&D));
1978 else
1979 return (B^C^D);
1980 }