Merge pull request #865 from AppImage/fix_appimagetool_names_architecture_wrongly
[appimagekit.git] / src / validate.c
blobf4cfd23e3a411f59204267f1d9c4f0982eae0468
1 #include <glib.h>
2 #include <glib/gprintf.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <openssl/sha.h>
7 #include <stdlib.h>
8 #include <sys/stat.h>
9 #include <linux/limits.h>
10 #include <unistd.h>
11 #include <libgen.h>
12 #include <fcntl.h>
13 #include <sys/mman.h>
15 #include "appimage/appimage.h"
16 #include "appimage/appimage_shared.h"
17 #include "light_elf.h"
19 typedef unsigned char byte;
21 char segment_name[] = ".sha256_sig";
23 int sha256_file(char *path, char outputBuffer[65], int skip_offset, int skip_length)
25 FILE *file = fopen(path, "rb");
26 if(!file) return(1);
27 byte hash[SHA256_DIGEST_LENGTH];
28 SHA256_CTX sha256;
29 SHA256_Init(&sha256);
30 const int bufSize = 1024*1024;
31 byte *buffer = malloc(bufSize);
32 int bytesRead = 0;
33 if(!buffer) {
34 fclose(file);
35 return ENOMEM;
38 int totalBytesRead = 0;
39 if(skip_offset <= bufSize){
40 bytesRead = fread(buffer, 1, skip_offset, file);
41 totalBytesRead += bytesRead;
42 // printf("totalBytesRead: %i\n", totalBytesRead);
43 // printf("bytesRead: %i\n", bytesRead);
44 SHA256_Update(&sha256, buffer, bytesRead);
45 } else {
46 int stillToRead = skip_offset-bytesRead;
47 // printf("Initial stillToRead: %i\n", stillToRead);
48 int readThisTime;
50 if(stillToRead>bufSize){
51 readThisTime = bufSize;
52 } else {
53 readThisTime = stillToRead;
55 while((bytesRead = fread(buffer, 1, readThisTime, file)))
57 totalBytesRead += bytesRead;
58 // printf("totalBytesRead: %i\n", totalBytesRead);
59 // printf("readThisTime: %i\n", readThisTime);
60 // printf("bytesRead: %i\n", bytesRead);
61 SHA256_Update(&sha256, buffer, bytesRead);
62 stillToRead = skip_offset-totalBytesRead;
63 // printf("stillToRead: %i\n", stillToRead);
65 if(stillToRead>bufSize){
66 readThisTime = bufSize;
67 } else {
68 readThisTime = stillToRead;
73 fseek(file, skip_offset+skip_length, SEEK_SET);
75 /* Instead of the skipped area, calculate the sha256 of the same amount if 0x00s */
76 int i = 0;
77 for(i = 0; i < skip_length; i++) {
78 SHA256_Update(&sha256, "\0", 1);
79 totalBytesRead += 1;
82 while((bytesRead = fread(buffer, 1, bufSize, file)))
84 totalBytesRead += bytesRead;
85 // printf("totalBytesRead: %i\n", totalBytesRead);
86 // printf("bytesRead: %i\n", bytesRead);
87 SHA256_Update(&sha256, buffer, bytesRead);
89 SHA256_Final(hash, &sha256);
91 // fprintf(stderr, "totalBytesRead: %i\n", totalBytesRead);
93 for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
95 sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
97 outputBuffer[64] = 0;
99 fclose(file);
101 return 0;
104 int main(int argc,char **argv) {
105 if(argc < 2){
106 fprintf(stderr, "Usage: %s Signed.AppImage\n", argv[0]);
107 exit(1);
110 char *filename = argv[1];
112 unsigned long skip_offset = 0;
113 unsigned long skip_length = 0;
115 if (!appimage_get_elf_section_offset_and_length(filename, ".sha256_sig", &skip_offset, &skip_length)) {
116 fprintf(stderr, "Failed to read .sha256_sig section");
117 exit(1);
120 if(skip_length > 0) {
121 fprintf(stderr, "Skipping ELF section %s with offset %lu, length %lu\n", segment_name, skip_offset, skip_length);
122 } else {
123 fprintf(stderr, "ELF section %s not found, is the file signed?\n", segment_name);
124 exit(1);
127 char *digestfile;
128 digestfile = g_strconcat("/tmp/", basename(g_strconcat(filename, ".digest", NULL)), NULL);
129 char *signaturefile;
130 signaturefile = g_strconcat("/tmp/", basename(g_strconcat(filename, ".sig", NULL)), NULL);
132 uint8_t *data = malloc(skip_length);
133 unsigned long k;
134 FILE* fd = fopen(filename, "r");
135 fseek(fd, skip_offset, SEEK_SET);
136 fread(data, skip_length, sizeof(uint8_t), fd);
137 fclose(fd);
138 FILE *fpdst2 = fopen(signaturefile, "w");
139 if (fpdst2 == NULL) {
140 fprintf(stderr, "Not able to open the signature file for writing, aborting");
141 exit(1);
143 for (k = 0; k < skip_length; k++) {
144 fprintf(fpdst2, "%c", data[k]);
146 fclose(fpdst2);
147 free(data);
149 struct stat st;
150 stat(filename, &st);
151 int size = st.st_size;
152 if(size < skip_offset+skip_length){
153 fprintf(stderr, "offset+length cannot be less than the file size\n");
154 exit(1);
157 static char buffer[65];
158 sha256_file(filename, buffer, skip_offset, skip_length);
159 printf("%s\n", buffer);
162 FILE *f = fopen(digestfile, "w");
163 if (f == NULL){
164 printf("Error opening digestfile\n");
165 exit(1);
167 fprintf(f, "%s", buffer);
168 fclose(f);
169 if (! g_file_test(digestfile, G_FILE_TEST_IS_REGULAR)) {
170 printf("Error writing digestfile\n");
171 exit(1);
174 char command[1024];
175 gchar *gpg2_path = g_find_program_in_path ("gpg2");
176 sprintf (command, "%s --verify %s %s", gpg2_path, signaturefile, digestfile);
177 fprintf (stderr, "%s\n", command);
178 FILE *fp = popen(command, "r");
179 if (fp == NULL)
180 fprintf(stderr, "gpg2 command did not succeed");
181 int exitcode = WEXITSTATUS(pclose(fp));
182 unlink(digestfile);
183 unlink(signaturefile);
184 return exitcode;