-/* Copyright (C) 2014 Jason Self <j@jxself.org>
-
-This file is part of skeinsum.
-
-skeinsum is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-skeinsum is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with skeinsum. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
-#include <getopt.h>
-#include <malloc.h>
-#include <math.h>
-#include <glob.h>
-#include <sys/stat.h>
-#include "SHA3api_ref.h"
-
-#define hashbitlen 256
-#define MaxNmberFiles 10
-#define skeinVersion "1.3"
-
-
-char invalidOption = 0;
-
-enum
-{
- QUIET_OPTION = 11,
- STATUS_OPTION,
- TAG_OPTION,
- HELP_OPTION,
- VERSION_OPTION
-};
-
-static struct option const long_options[] =
-{
- { "binary", no_argument, NULL, 'b' },
- { "check", no_argument, NULL, 'c' },
- { "quiet", no_argument, NULL, QUIET_OPTION },
- { "status", no_argument, NULL, STATUS_OPTION },
- { "text", no_argument, NULL, 't' },
- { "warn", no_argument, NULL, 'w' },
- { "tag", no_argument, NULL, TAG_OPTION },
- { "help", no_argument, NULL, HELP_OPTION },
- { "version", no_argument, NULL, VERSION_OPTION },
- { NULL, 0, NULL, 0 }
-};
-
-void printHexMsg(unsigned char *ptr, int size, char result[])
-{
- int i = 0;
- int j = 0;
- char High, Low;
- for (i = 0 ; i < size ; i ++)
- {
- High = ptr[i]>>4;
- Low = ptr[i]&0x0F;
-
- if (High >= 0xA && High <= 0xF)
- High += 0x37;
- else if(High >= 0x0 && High <= 0x9)
- High += 0x30;
-
- if (Low >= 0xA && Low <= 0xF)
- Low += 0x37;
- else if(Low >= 0x0 && Low <= 0x9)
- Low += 0x30;
-
- result[j++] = High;
- result[j++] = Low;
- }
- result[i] = 0;
-}
-
-int HashTextMode(char file_name[], char MsgDigest[])
-{
- FILE *fp_in = fopen(file_name,"r");
- struct stat st;
- stat(file_name, &st);
- long size_fp_in = st.st_size;
-
- if(fp_in == NULL)
- {
- printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
- printf(" %s FAILED open or read\n",file_name);
- return -1 ;
- }
-
- char *hello;
- hello = (char*) malloc (size_fp_in);
- fgets(hello,size_fp_in,fp_in);
-
- unsigned char output[hashbitlen/4];
- Hash(hashbitlen,(unsigned char*) hello,size_fp_in,output);
-
- printHexMsg(output,hashbitlen/4,MsgDigest);
-
- fclose(fp_in);
- return 1;
-}
-
-int HashBinaryMode(char file_name[],char MsgDigest[])
-{
- FILE *fp_in = fopen(file_name,"rb");
- struct stat st;
- stat(file_name, &st);
- long size_fp_in = st.st_size;
-
- if(fp_in == NULL)
- {
- printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
- printf(" %s FAILED open or read\n",file_name);
- return -1 ;
- }
-
- unsigned char *hello;
- hello = (unsigned char*) malloc (size_fp_in);
- fread(hello,size_fp_in,1,fp_in);
-
- unsigned char output[hashbitlen/4];
- Hash(hashbitlen,hello,size_fp_in,output);
-
- printHexMsg(output,hashbitlen/4,MsgDigest);
-
- fclose(fp_in);
- return 1;
-}
-
-int HashStringMode(char Msg[],char MsgDigest[])
-{
- unsigned char output[hashbitlen/4];
- Hash(hashbitlen,(unsigned char*) Msg,sizeof(Msg),output);
- printHexMsg(output,hashbitlen/4,MsgDigest);
- return 1;
-}
-
-/*
- * return 1 : is File
- * return 2 : is Directory
- * return -1 : Something else.
- */
-int isFile(char argument[])
-{
- struct stat s;
- if( stat(argument,&s) == 0 )
- {
- if( s.st_mode & S_IFDIR )
- {
- return 2;
- }
- else if( s.st_mode & S_IFREG )
- {
- return 1;
- }
- }
- else
- return -1;
- return 0;
-}
-
-int isProper(char MsgDigest[])
-{
- if ((strlen(MsgDigest) - hashbitlen/4) != 0)
- return 0;
- int index = 0;
- char c = 0;
- for(index = 0; index < strlen(MsgDigest);index++)
- {
- c = MsgDigest[index];
- if(!(( c >= '0' && c <= '9' ) || ( c >= 'A' && c <= 'F')))
- return 0;
- }
-
- return 1;
-}
-
-
-int decomposeHashLine(char hash[], char MsgDigest_tmp[], char file_tmp[])
-{
- char c = 0;
- int i = 0 , j =0;
- int isTagFile = 0;
- char alg[20];
- char tmp[1000];
- while(((c = hash[i])!=' ')&&((c = hash[i])!='_'))
- {
- tmp[i] = hash[i];
- i++;
- }
- tmp[i] = 0;
-
- sprintf(alg,"skein%d",hashbitlen);
- if(!strcmp(alg,tmp))
- {
- isTagFile = 1;
- }
-
- if(isTagFile == 0)
- {
- strcpy(MsgDigest_tmp,tmp);
- i++;
- while((c = hash[i])!= '\n')
- {
- file_tmp[j] = hash[i];
- i++;
- j++;
- }
- file_tmp[j] = 0;
- }
- else if((hash[i]=='_')&&(hash[i+1]=='v'))
- {
- i = i + 2;
- j = 0;
- char version[5];
- while((c = hash[i])!=' ')
- {
- version[j] = hash[i];
- i++;
- j++;
- }
- version[i] = 0;
- float vers = 0, skeinVers = 0;
- sscanf(version,"%f",&vers);
- sscanf(skeinVersion,"%f",&skeinVers);
-
- j = 0;
- i = i + 2;
- while((c = hash[i])!=')')
- {
- file_tmp[j] = hash[i];
- i++;
- j++;
- }
- file_tmp[j] = 0;
-
- i = i + 4;
- j = 0;
- while((c = hash[i])!='\n')
- {
- MsgDigest_tmp[j] = hash[i];
- i++;
- j++;
- }
- MsgDigest_tmp[j] = 0;
-
- if(skeinVers < vers)
- {//version newer than mine
- return (-1);
- }
- else if (skeinVers > vers)
- {//going to use older version than mine
- return (0) ;
- }
- else
- { //versions match
- return (1);
- }
- }
- return 1;
-
-}
-
-
-
-int main(int argc, char** argv)
-{
- char MsgDigest[hashbitlen/2];
- char **list_files = (char**) malloc(MaxNmberFiles* sizeof(char*));
- int number_files = 0;
- int binary = -1,
- check = -1,
- quiet = -1,
- warn = -1,
- status = -1,
- help = -1,
- version = -1,
- tag = -1,
- hashString = -1,
- badParam = -1;
-
- int errorFound = 0;
- int opt = 0;
-/*****************************************************************************************
- ************************************* GETTING DATA ***********************************
- *****************************************************************************************/
- while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
- {
- switch (opt)
- {
- case 'b' :
- {
- binary = 1;
- break;
- }
- case 't' :
- {
- binary = 0;
- break;
- }
- case 'c' :
- {
- check = 1;
- break;
- }
- case QUIET_OPTION :
- {
- quiet = 1;
- break;
- }
- case 'w' :
- {
- warn = 1;
- break;
- }
- case STATUS_OPTION :
- {
- status = 1;
- break;
- }
- case HELP_OPTION :
- {
- help = 1;
- break;
- }
- case VERSION_OPTION :
- {
- version = 1;
- break;
- }
- case TAG_OPTION :
- {
- tag = 1;
- break;
- }
- case 0 :
- {
- hashString = 1;
- break;
- }
- default :
- {
- badParam = 1;
- break;
- }
- }
- }
-
- if(badParam == 1)
- {
- printf("Try `skein%dsum --help' for more information.\n",hashbitlen);
- exit(1);
- }
-
- for (; optind < argc; ++optind)
- {
- switch (opt)
- {
- case -1:
- {// no options found, test if there is a file and hash it
- if(isFile(argv[optind]) == 1)
- {
- char *file_name = malloc(sizeof(argv[optind]));
- file_name = argv[optind];
- list_files[number_files] = (char*) malloc (sizeof(file_name));
- list_files[number_files] = file_name;
- number_files ++;
- }
- else if (isFile(argv[optind]) == 2)
- {
- printf("skein%dsum: %s Is a directory\n",hashbitlen,argv[optind]);
- errorFound = 1;
- }
- else
- {
- printf("skein%dsum: %s: No such file or directory\n",hashbitlen,argv[optind]);
- errorFound = 1;
- }
- break;
- }
- }
- }
-/*****************************************************************************************
- ************************************* PROCESSING DATA ***********************************
- *****************************************************************************************/
- if(argc > 1 && version == 1)
- {
- printf("skein256sum 1.0\n");
- printf("License GPLv3+: GNU GPL version 3 or later\n");
- printf("<http://gnu.org/licenses/gpl.html>\n");
- printf("This is free software: you are free to change and redistribute it.\n");
- printf("There is NO WARRANTY, to the extent permitted by law.\n");
- exit(1);
- }
- if(argc > 1 && help == 1)
- {
-
- printf("Usage: skein%dsum [OPTION]... [FILE]...\n",hashbitlen);
- printf("Print or check skein (%d-bit) checksums.\n",hashbitlen);
- printf("With no FILE, or when FILE is -, read standard input.\n");
- printf("\n");
- printf("-b, --binary read in binary mode\n");
- printf("-c, --check read skein sums from the FILEs and check them\n");
- printf("--tag create a BSD-style checksum\n");
- printf("-t, --text read in text mode (default)\n");
- printf("\n");
- printf("The following three options are useful only when verifying checksums:\n");
- printf("--quiet don't print OK for each successfully verified file\n");
- printf("--status don't output anything, status code shows success\n");
- printf("-w, --warn warn about improperly formatted checksum lines\n");
- printf("\n");
- printf("--strict with --check, exit non-zero for any invalid input\n");
- printf("--help display this help and exit\n");
- printf("--version output version information and exit\n");
- printf("\n");
- printf("The sums are computed as described in version 1.3 of the Skein\n");
- printf("specification. When checking, the input should be a former output of\n");
- printf("this program. The default mode is to print a line with checksum, a\n");
- printf("character indicating input mode ('*' for binary, space for text), and\n");
- printf("name for each FILE.\n");
- exit(1);
- }
-
- if(argc > 1 && binary == 1)
- {
- if (check == 1 || quiet == 1 || warn == 1 || status == 1)
- {
- printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
- printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
- exit(0);
- }
- if(number_files > 0)
- {
- int index_files = 0;
- while(index_files < number_files)
- {
- if(hashString == 1)
- {
- printf("skein%dsum: %s: No such file or directory\n",hashbitlen,list_files[index_files]);
- index_files++;
- continue;
- }
- if(HashBinaryMode(list_files[index_files],MsgDigest)!=-1)
- {
- if(tag == 1)
- {
- printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
- }
- else
- {
- printf("%s ",MsgDigest);
- printf("*%s\n",list_files[index_files]);
- }
- }
- index_files++;
- }
- }
- else if(errorFound != 1)
- { // read stdin for strings
- char stri[100];
- char longstring[1000];
- longstring[0] = 0;
- while((fgets(stri,100,stdin))!=NULL)
- {
- strcat(longstring,stri);
- }
- HashStringMode(longstring,MsgDigest);
- if(tag == 1)
- {
- printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
- }
- else
- {
- printf("%s *-\n",MsgDigest);
- }
- }
- }
-
- else if (argc > 1 && binary == 0) // Text Mode
- {
- if (check == 1 || quiet == 1 || warn == 1 || status == 1)
- {
- printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
- printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
- exit(0);
- }
- if(number_files > 0)
- {
- int index_files = 0;
- while(index_files < number_files)
- {
- if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
- {
- if(tag == 1)
- {
- printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
- }
- else
- {
- printf("%s ",MsgDigest);
- printf("%s\n",list_files[index_files]);
- }
- }
- index_files++;
- }
- }
- else if(errorFound != 1)
- { // read stdin for strings
- char stri[100];
- char longstring[1000];
- longstring[0] = 0;
- while((fgets(stri,100,stdin))!=NULL)
- {
- strcat(longstring,stri);
- }
- HashStringMode(longstring,MsgDigest);
- if(tag == 1)
- {
- printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
- }
- else
- {
- printf("%s -\n",MsgDigest);
- }
- }
- }
-
- else if (argc > 1 && binary == -1)
- {
- if(check == -1)
- {// hashing stdin entries
- if(quiet == 1 || status == 1 || warn == 1)
- {
- if(quiet == 1)
- printf("skein%dsum: the --quiet option is meaningful only when verifying checksums\n",hashbitlen);
- if(status ==1)
- printf("skein%dsum: the --status option is meaningful only when verifying checksums\n",hashbitlen);
- if(warn == 1)
- printf("skein%dsum: the --warn option is meaningful only when verifying checksums\n",hashbitlen);
-
- printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
- exit(1);
- }
- if(number_files > 0)
- {// hashing files
- int index_files = 0;
- while(index_files < number_files)
- {
- if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
- {
- if(tag == 1)
- {
- printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
- }
- else
- {
- printf("%s ",MsgDigest);
- printf("%s\n",list_files[index_files]);
- }
- }
- index_files++;
- }
- }
- else if(errorFound != 1)
- { // hasing strings read from stdin
- char stri[100];
- char longstring[1000];
- longstring[0] = 0;
- while((fgets(stri,100,stdin))!=NULL)
- {
- strcat(longstring,stri);
- }
- HashStringMode(longstring,MsgDigest);
- if(tag == 1)
- {
- printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
- }
- else
- {
- printf("%s -\n",MsgDigest);
- }
- }
- }
- else if(check == 1)
- {
- if(tag == 1)
- {
- printf("skein%dsum: the --tag option is meaningless when verifying checksums\n",hashbitlen);
- printf("Try 'skein%dsum --help' for more information\n",hashbitlen);
- exit(1);
- }
- int index_files = 0;
- while(index_files < number_files)
- {
- FILE *fp;
- char hash[500], file_name[100], file_tmp[100], MsgDigest_tmp[hashbitlen/2];
- int NoMatch = 0, NotProper = 0, Computed = 0;
- strcpy(file_name,list_files[index_files]);
- //show everything
- int line = 0;
- fp = fopen(file_name,"r");
- if(fp!=NULL)
- {
- while(fgets(hash,500,fp)!=NULL)
- {
- line ++;
- Computed++;
- unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
- if(hashVersion == -1)
- {
- printf("skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
- printf("You should update your algorithm\n");
- continue;
- }
- else if( hashVersion == 0)
- {
- printf("skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
- printf("You should use the older algorithm\n");
- continue;
- }
- else
- {
- if(!isProper(MsgDigest_tmp))
- {
- if(status != 1 && warn == 1)
- {
- printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
- }
- NotProper ++;
- NoMatch ++;
- continue;
- }
- if(file_tmp[0] == '*')
- {
- int index_file_tmp = 0;
- for( ; file_tmp[index_file_tmp+1]!=0 ; index_file_tmp++)
- {
- file_tmp[index_file_tmp] = file_tmp[index_file_tmp + 1];
- }
- file_tmp[index_file_tmp] = 0;
- HashBinaryMode(file_tmp,MsgDigest);
- }
- else
- {
- HashTextMode(file_tmp,MsgDigest);
- }
-
- if(!strcmp(MsgDigest,MsgDigest_tmp))
- {
- if(quiet != 1)
- {
- printf("%s: OK\n",file_tmp);
- }
- }
- else
- {
- printf("%s: FAILED\n",file_tmp);
- NoMatch ++;
- }
- }
- }
- if(NoMatch)
- {
- printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
- hashbitlen,NoMatch,Computed);
- }
- if(NotProper)
- {
- printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
- }
- }
- else
- {
- printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
- }
- index_files++;
-
- }
-
- if(number_files == 0)
- {
- char longstring[1000];
- char file_name[30];
- char MsgDigest_tmp[hashbitlen/2];
- int Computed = 0, NotProper = 0, NoMatch = 0 , line = 0;
- while((fgets(longstring,1000,stdin))!=NULL)
- {
- Computed++;
- line ++;
- decomposeHashLine(longstring,MsgDigest_tmp,file_name);
- if(!isProper(MsgDigest_tmp))
- {
- if(status != 1 && warn == 1)
- {
- printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_name,line,hashbitlen);
- }
- NotProper ++;
- NoMatch ++;
- continue;
- }
- if(file_name[0] == '*')
- {
- int index_file_tmp = 0;
- for( ; file_name[index_file_tmp+1]!=0 ; index_file_tmp++)
- {
- file_name[index_file_tmp] = file_name[index_file_tmp + 1];
- }
- file_name[index_file_tmp] = 0;
- HashBinaryMode(file_name,MsgDigest);
- }
- else
- {
- HashTextMode(file_name,MsgDigest);
- }
-
- if(!strcmp(MsgDigest,MsgDigest_tmp))
- {
- if(quiet != 1)
- {
- printf("%s: OK\n",file_name);
- }
- }
- else
- {
- printf("%s: FAILED\n",file_name);
- NoMatch ++;
- }
- }
- if(NoMatch)
- {
- printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
- hashbitlen,NoMatch,Computed);
- }
- if(NotProper)
- {
- printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
- }
-
- }
-
-
- }
- }
-
- if ((errorFound != 1) && (argc == 1 || (hashString == 1 && number_files == 0)))
- {
- char stri[100];
- char longstring[1000];
- longstring[0] = 0;
- while((fgets(stri,100,stdin))!=NULL)
- {
- strcat(longstring,stri);
- }
- HashStringMode(longstring,MsgDigest);
- printf("%s -\n",MsgDigest);
- }
-
- return 1;
-}
+const int hashbitlen = 256;