Merge pull request #475 from th-otto/PR-2
[appimagekit/gsi.git] / digest.c
blob3b0783d7320bc65b8400f7e6573cde4b4d9ee71c
1 /*
2 cc -o digest getsection.c digest.c -lssl -lcrypto
3 */
5 #include <stdio.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <openssl/sha.h>
9 #include <stdlib.h>
10 #include <sys/stat.h>
11 #include <linux/limits.h>
13 #include "getsection.h"
15 typedef unsigned char byte;
17 char segment_name[] = ".sha256_sig";
19 int sha256_file(char *path, char outputBuffer[65], int skip_offset, int skip_length)
21 FILE *file = fopen(path, "rb");
22 if(!file) return(1);
23 byte hash[SHA256_DIGEST_LENGTH];
24 SHA256_CTX sha256;
25 SHA256_Init(&sha256);
26 const int bufSize = 1024*1024;
27 byte *buffer = malloc(bufSize);
28 int bytesRead = 0;
29 if(!buffer) {
30 fclose(file);
31 return ENOMEM;
34 int totalBytesRead = 0;
35 if(skip_offset <= bufSize){
36 bytesRead = fread(buffer, 1, skip_offset, file);
37 totalBytesRead += bytesRead;
38 // printf("totalBytesRead: %i\n", totalBytesRead);
39 // printf("bytesRead: %i\n", bytesRead);
40 SHA256_Update(&sha256, buffer, bytesRead);
41 } else {
42 int stillToRead = skip_offset-bytesRead;
43 // printf("Initial stillToRead: %i\n", stillToRead);
44 int readThisTime;
46 if(stillToRead>bufSize){
47 readThisTime = bufSize;
48 } else {
49 readThisTime = stillToRead;
51 while((bytesRead = fread(buffer, 1, readThisTime, file)))
53 totalBytesRead += bytesRead;
54 // printf("totalBytesRead: %i\n", totalBytesRead);
55 // printf("readThisTime: %i\n", readThisTime);
56 // printf("bytesRead: %i\n", bytesRead);
57 SHA256_Update(&sha256, buffer, bytesRead);
58 stillToRead = skip_offset-totalBytesRead;
59 // printf("stillToRead: %i\n", stillToRead);
61 if(stillToRead>bufSize){
62 readThisTime = bufSize;
63 } else {
64 readThisTime = stillToRead;
69 fseek(file, skip_offset+skip_length, SEEK_SET);
71 /* Instead of the skipped area, calculate the sha256 of the same amount if 0x00s */
72 int i = 0;
73 for(i = 0; i < skip_length; i++) {
74 SHA256_Update(&sha256, "\0", 1);
75 totalBytesRead += 1;
78 while((bytesRead = fread(buffer, 1, bufSize, file)))
80 totalBytesRead += bytesRead;
81 // printf("totalBytesRead: %i\n", totalBytesRead);
82 // printf("bytesRead: %i\n", bytesRead);
83 SHA256_Update(&sha256, buffer, bytesRead);
85 SHA256_Final(hash, &sha256);
87 // fprintf(stderr, "totalBytesRead: %i\n", totalBytesRead);
89 for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
91 sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
93 outputBuffer[64] = 0;
95 fclose(file);
96 free(buffer);
98 return 0;
101 int main(int argc,char **argv)
103 int res = 0;
105 if(argc < 2){
106 fprintf(stderr, "Usage: %s file offset length\n", argv[0]);
107 fprintf(stderr, "If no offset and length are provided, the ELF section '%s' is skipped\n\n", segment_name);
108 fprintf(stderr, "Calculate a sha256 of a file except a skipped area from offset to offset+length bytes\n");
109 fprintf(stderr, "which is replaced with 0x00 during checksum calculation.\n");
110 fprintf(stderr, "This is useful when a signature is placed in the skipped area.\n");
111 exit(1);
114 unsigned long skip_offset = 0;
115 unsigned long skip_length = 0;
116 char *filename = argv[1];
118 struct stat st;
119 if (stat(filename, &st) < 0) {
120 fprintf(stderr, "not existing file: %s\n", filename);
121 exit(1);
124 if(argc < 4){
125 get_elf_section_offset_and_lenghth(filename, ".sha256_sig", &skip_offset, &skip_length);
126 if(skip_length > 0)
127 fprintf(stderr, "Skipping ELF section %s with offset %lu, length %lu\n", segment_name, skip_offset, skip_length);
128 } else if(argc == 4) {
129 skip_offset = atoi(argv[2]);
130 skip_length = atoi(argv[3]);
131 } else {
132 exit(1);
135 int size = st.st_size;
136 if(size < skip_offset+skip_length){
137 fprintf(stderr, "offset+length cannot be less than the file size\n");
138 exit(1);
141 static char buffer[65];
142 res = sha256_file(filename, buffer, skip_offset, skip_length);
143 printf("%s\n", buffer);
144 return res;