//---------------------------------------------------------------------------
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Dallas Semiconductor
// shall not be used except as stated in the Dallas Semiconductor
// Branding Policy.
//---------------------------------------------------------------------------
//
//  AHAapp.c - This utility debits money from a roving SHA iButton
//               (DS1963S) using a coprocessor SHA iButton.
//
//  Version:   2.00
//  History:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "ownet.h"
#include "ibsha33.h"

// mode constants
enum { MD_FIND_ROVING=0, MD_READ_AUTH, MD_MONEY_VERF, MD_MONEY_CHANGE,
       MD_MONEY_WRITE, MD_READ_BACK_AUTH, MD_VERIFY_GONE };

// local function prototypes
int ParseData(char *,int,uchar *,int);

// globals
int time_stamp;
// verbose output mode
int VERBOSE=0;

//----------------------------------------------------------------------
//  This is the Main routine for shaapp
//
// Note: This algorithm used is the SHA-1 algorithm as specified in the
// datasheet for the DS1961S, where the last step of the official
// FIPS-180 SHA routine is omitted (which only involves the addition of
// constant values).
//
int main(int argc, char **argv)
{
   char msg[200];
   int portnum = 0;
   uchar data[8];
   ushort i;
   uchar sn[8],secret[8], memory[32];
   int rslt,n=13,done=FALSE,skip;
   int reads=0;
   uchar indata[32];
   int address;
   ushort addr;
   uchar es;
   char hexstr[32];

   // check for required port name
   if (argc != 2)
   {
      sprintf(msg,"1-Wire Net name required on command line!\n"
                  " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" "
                  "(Linux DS2480),\"1\" (Win32 TMEX)\n");
      printf("%s",msg);
      return 0;
   }

   for(i=0; i<8; i++)
   {
      secret[i] = 0xFF;
      data[i] = 0xFF;
   }

   if((portnum = owAcquireEx(argv[1])) < 0)
      ExitProg("Did not Acquire port.\n",1);
   else
   {
      rslt = owFirst(portnum, TRUE, FALSE);
      owSerialNum(portnum,sn,TRUE);

      while(rslt && ((sn[0] != 0xB3) && (sn[0] != 0x33)))
      {
         rslt = owNext(portnum,TRUE,FALSE);
         owSerialNum(portnum,sn,TRUE);
      }

      for(i=0;i<8;i++)
         printf("%02X ",sn[i]);
      printf("\n");

      if((sn[0] == 0xB3) || (sn[0] == 0x33))
      {
         if(ReadMem(portnum,128,indata))
         {
            if(((indata[8] != 0xAA) && (indata[8] != 0x55)) &&
               ((indata[11] != 0xAA) && (indata[11] != 0x55)))
            {
               // Clear all memory to 0xFFh
               for(i=0;i<16;i++)
               {
                  if(!LoadFirSecret(portnum,(ushort) (i*8),data,8))
                     printf("MEMORY ADDRESS %d DIDN'T WRITE\n",i*8);
               }

               printf("Current Bus Master Secret Is:\n");
               for(i=0;i<8;i++)
                  printf("%02X ",secret[i]);
               printf("\n");
            }
            else if((indata[9] != 0xAA) || (indata[9] != 0x55))
            {
               printf("Please Enter the Current Secret\n");
               printf("AA AA AA AA AA AA AA AA  <- Example\n");
               scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                      &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

               if(!ParseData(hexstr,strlen(hexstr),data,16))
                  printf("DIDN'T PARSE\n");
               else
               {
                  printf("The secret read was:\n");
                  for(i=0;i<8;i++)
                  {
                     secret[i] = data[i];
                     printf("%02X ",secret[i]);
                     data[i] = 0xFF;
                  }
                  printf("\n");
               }

               printf("\n");

               if((indata[13] == 0xAA) || (indata[13] == 0x55))
                  skip = 4;
               else
                  skip = 0;

               for(i=skip;i<16;i++)
               {
                  ReadMem(portnum,(ushort)(((i*8)/((ushort)32))*32),memory);

                  if(WriteScratchSHAEE(portnum,(ushort) (i*8),&data[0],8))
                     CopyScratchSHAEE(portnum,(ushort) (i*8),secret,sn,memory);
               }
            }
            else
            {
               printf("Please Enter the Current Secret\n");
               printf("AA AA AA AA AA AA AA AA  <- Example\n");
               scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                      &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);
               if(!ParseData(hexstr,strlen(hexstr),secret,16))
                  printf("DIDN'T PARSE\n");
               else
               {
                  printf("The secret that was read:\n");
                  for(i=0;i<8;i++)
                  {
                     printf("%02X ",secret[i]);
                  }
                  printf("\n");
               }
            }
         }

         do
         {
            printf("PICK AN OPERATION:\n\n");
            printf("(1)  Read memory\n");                   // Reads memory page data

            printf("(2)  Write scratchpad\n");              // Write to scratch pad

            printf("(3)  Read scratchpad\n");               // Read scratch pad data

            printf("(4)  Copy scratchpad\n");               // Copy scratch pad to address

            printf("(5)  Load First Secret with Address\n");// Load first secret data

            printf("(6)  Compute Next Secret\n");           // Compute next secret and
                                                            // changes Bus Master secret

            printf("(7)  Read Auth page\n");                // Read authenticate page

            printf("(8)  Change/Load Secret Only\n");       // Changes/Loads Secret and
                                                            // Bus Master Secret

            printf("(9)  Change Bus Master Secret\n");       // Only changes Bus Master S.

            printf("(10) Write Protect Secret\n");          // Write protect secret

            printf("(11) Write Protect pages 0 to 3\n");    // Write protect pages 0 to 3

            printf("(12) EPROM mode control for page 1\n"); // EPROM mode for page 1

            printf("(13) Write Protect page 0 only\n");     // Write protect page 0.

            printf("(14) Print Current Bus Master Secret.\n");

            printf("(15) QUIT\n");

            scanf("%d",&n);
            if(n == 15)
            {
               n = 0;        //used to finish off the loop
               done = TRUE;
               break;
            }

            switch(n)
            {
               case 1:  // Read Memory
                  printf("\nEnter memory address to read as integer\n");
                  scanf("%d",&reads);
                  if(ReadMem(portnum,(ushort)reads,indata))
                  {
                     printf("\n");

                     for(i=0;i<8;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=8;i<16;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=16;i<24;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=24;i<32;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     printf("Read Complete\n\n\n");
                  }
                  else
                     printf("READ DIDN'T WORK\n\n\n");
                  break;

               case 2:  // Write Scratchpad
                  printf("\nEnter the 8 bytes of data to be written.\n");
                  printf("AA AA AA AA AA AA AA AA  <- Example\n");
                  scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                        &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

                  printf("\nNow enter the address as an integer.\n");
                  scanf("%d",&address);

                  if(!ParseData(hexstr,strlen(hexstr),data,16))
                  {
                     printf("DIDN'T PARSE\n");
                     break;
                  }

                  ReadMem(portnum,(ushort)((address/((ushort)32))*32),memory);

                  if(WriteScratchSHAEE(portnum,(ushort)address,data,8))
                     printf("Write complete\n\n\n");
                  else
                     printf("WRITE DIDN'T WORK\n\n\n");
                  break;

               case 3:  // Read Scratchpad
                  printf("\n");
                  if(ReadScratchSHAEE(portnum,&addr,&es,data))
                  {
                     printf("Address is:   %d\n",addr);
                     printf("E/S Data is:  %02X\n",es);
                     printf("Scratch pad data is:\n");
                     for(i=0;i<8;i++)
                        printf("%02X ",data[i]);
                     printf("\n\n\n");
                  }
                  else
                     printf("READ DIDN'T WORK\n\n\n");
                  break;

               case 4:  // Copy Scratchpad
                  printf("\nEnter address to copy to as an integer.\n");
                  scanf("%d",&address);
                  if(CopyScratchSHAEE(portnum,(ushort)address,secret,sn,memory))
                     printf("Copy Scratch Pad Complete\n\n\n");
                  else
                     printf("COPY DIDN'T WORK\n\n\n");
                  break;

               case 5:  // Load First Secret
                  printf("\nEnter the 8 bytes of data to be written.\n");
                  printf("AA AA AA AA AA AA AA AA  <- Example\n");
                  scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                        &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

                  printf("\nEnter the address where you want "
                         "to load the secret as an integer.\n");
                  scanf("%d",&address);

                  if(!ParseData(hexstr,strlen(hexstr),data,16))
                  {
                     printf("DIDN'T PARSE\n");
                     break;
                  }

                  if(LoadFirSecret(portnum,(ushort)address,data,8))
                  {
                     if(address == 128)
                     {
                        for(i=0;i<8;i++)
                           secret[i] = data[i];
                     }

                     printf("Load Complete\n\n\n");
                  }
                  else
                     printf("LOAD DIDN'T WORK\n\n\n");
                  break;

               case 6:  // Compute Next Secret
                  printf("\nEnter the address for the page of data to use in computation\n");
                  scanf("%d",&address);
                  if(NextSecret(portnum,(ushort)address,secret))
                  {
                     for(i=0;i<8;i++)
                        printf("%02X ",secret[i]);
                     printf("\n");

                     printf("Next secret is complete\n\n\n");
                  }
                  else
                     printf("NEXT SECRET DIDN'T WORK\n\n\n");
                  break;

               case 7:  // Read Authenticate SHA Page
                  printf("\nEnter the 8 bytes of challenge to use.\n");
                  printf("AA AA AA AA AA AA AA AA  <- Example\n");
                  scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                        &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

                  printf("\nEnter address of page to read authenticate\n");
                  scanf("%d",&address);

                  if(!ParseData(hexstr,strlen(hexstr),data,16))
                  {
                     printf("DIDN'T PARSE\n");
                     break;
                  }


                  if(ReadAuthPageSHAEE(portnum,(ushort)address,secret,sn,indata,data))
                  {
                     printf("\n");

                     for(i=0;i<8;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=8;i<16;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=16;i<24;i++)
                        printf("%02X ",indata[i]);
                     printf("\n");

                     for(i=24;i<32;i++)
                        printf("%02X ",indata[i]);
                     printf("\n\n");

                     printf("Read Authenticate Complete\n\n\n");
                  }
                  else
                     printf("READ DIDN'T WORK\n\n\n");
                  break;

               case 8:  // Change/Load new secret
                  printf("\nEnter 8 byte secret you wish to load/change\n");
                  printf("AA AA AA AA AA AA AA AA  <- Example\n");
                  scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                        &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

                  if(!ParseData(hexstr,strlen(hexstr),data,16))
                  {
                     printf("DIDN'T PARSE\n");
                     break;
                  }

                  if(LoadFirSecret(portnum,128,data,8))
                  {
                     for(i=0;i<8;i++)
                        secret[i] = data[i];

                     printf("Secret Loaded\n\n\n");
                  }
                  else
                     printf("SECRET NOT LOADED\n\n\n");
                  break;

               case 9:  // Change Bus Master Secret
                  printf("\nEnter 8 byte secret you wish to load for Bus Master\n");
                  printf("AA AA AA AA AA AA AA AA  <- Example\n");
                  scanf("%s %s %s %s %s %s %s %s",&hexstr[0],&hexstr[2],&hexstr[4],
                        &hexstr[6],&hexstr[8],&hexstr[10],&hexstr[12],&hexstr[14]);

                  if(!ParseData(hexstr,strlen(hexstr),data,16))
                  {
                     printf("DIDN'T PARSE\n");
                     break;
                  }
                  else
                  {
                     for(i=0;i<8;i++)
                        secret[i] = data[i];

                     printf("Bus Master Secret Changed.\n");
                  }

                  break;

               case 10:  // Lock Secret
                  printf("\n");
                  data[0] = 0xAA;
                  for(i=1;i<8;i++)
                     data[i] = 0x00;

                  ReadMem(portnum,128,memory);

                  if(WriteScratchSHAEE(portnum,136,data,8) &&
                     CopyScratchSHAEE(portnum,136,secret,sn,memory))
                     printf("Secret Locked\n\n\n");
                  else
                     printf("SECRET NOT LOCKED\n\n\n");
                  break;

               case 11:  // Write-protect pages 0 to 3
                  printf("\n");
                  data[0] = 0x00;
                  data[1] = 0xAA;
                  for(i=2;i<8;i++)
                     data[i] = 0x00;

                  ReadMem(portnum,128,memory);

                  if(WriteScratchSHAEE(portnum,136,data,8) &&
                     CopyScratchSHAEE(portnum,136,secret,sn,memory))
                     printf("Pages 0 to 3 write protected\n\n\n");
                  else
                     printf("PAGES NOT WRITE PROTECTED\n\n\n");
                  break;

               case 12:  // Set page 1 to EPROM mode
                  printf("\n");
                  for(i=0;i<4;i++)
                     data[i] = 0x00;

                  data[4] = 0xAA;

                  for(i=5;i<8;i++)
                     data[i] = 0x00;

                  ReadMem(portnum,128,memory);

                  if(WriteScratchSHAEE(portnum,136,data,8) &&
                     CopyScratchSHAEE(portnum,136,secret,sn,memory))
                     printf("EPROM mode control activated for page 1.\n\n\n");
                  else
                     printf("EPROM PROGRAMMING DIDN'T WORK\n\n\n");
                  break;

               case 13:  // Write protect page 0
                  printf("\n");
                  for(i=0;i<5;i++)
                     data[i] = 0x00;

                  data[5] = 0xAA;

                  for(i=6;i<8;i++)
                     data[i] = 0x00;

                  ReadMem(portnum,128,memory);

                  if(WriteScratchSHAEE(portnum,136,data,8) &&
                     CopyScratchSHAEE(portnum,136,secret,sn,memory))
                     printf("Page 0 Write-protected\n\n\n");
                  else
                     printf("NOT WRITE-PROTECTED\n\n\n");
                  break;

               case 14:  // Print Current Bus Master Secret
                  printf("\nThe Current Bus Master Secret is:\n");
                  for(i=0;i<8;i++)
                     printf("%02X ",secret[i]);
                  printf("\n\n\n");
                  break;

               default:
                  break;
            }

         }while(!done);

      }
      else
         printf("DS2432 not found on One Wire Network\n");

      owRelease(portnum);
   }

   return 1;
}


//----------------------------------------------------------------------
// Parse the raw file data in to an array of uchar's.  The data must
// be hex characters possible seperated by white space
//     12 34 456789ABCD EF
//     FE DC BA 98 7654 32 10
// would be converted to an array of 16 uchars.
// return the array length.  If an invalid hex pair is found then the
// return will be 0.
//
// inbuf    the input buffer that is to be parsed
// insize   the size of the input buffer
// outbuf   the parsed data from the input buffer
// maxsize  the max size that is to be parsed.
//
// return the length of that data that was parsed
//
int ParseData(char *inbuf, int insize, uchar *outbuf, int maxsize)
{
   int ps, outlen=0, gotmnib=0;
   uchar mnib = 0;

   // loop until end of data
   for (ps = 0; ps < insize; ps++)
   {
      // check for white space
      if (isspace(inbuf[ps]))
         continue;
      // not white space, make sure hex
      else if (isxdigit(inbuf[ps]))
      {
         // check if have first nibble yet
         if (gotmnib)
         {
            // this is the second nibble
            outbuf[outlen++] = (mnib << 4) | ToHex(inbuf[ps]);
            gotmnib = 0;
         }
         else
         {
            // this is the first nibble
            mnib = ToHex(inbuf[ps]);
            gotmnib = 1;
         }
      }
      else
         return 0;

      // if getting to the max return what we have
      if ((outlen + 1) >= maxsize)
         return outlen;
   }

   return outlen;
}

