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 }