forked from chwdt/vanmoof-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcrc32.c
More file actions
188 lines (145 loc) · 5.39 KB
/
Copy pathcrc32.c
File metadata and controls
188 lines (145 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <zlib.h>
#include "mmap.h"
#include "endian.h"
#include "ware.h"
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s <binfile>\n", progname);
exit(1);
}
static const uint32_t crc_poly = 0x4c11db7;
static const uint32_t initial_crc = 0xffffffff;
static uint32_t crc32_calculate(uint32_t crc, const void *data, size_t length)
{
const uint32_t *p = data;
size_t i, b;
for (i = 0; i < length; i += sizeof(uint32_t)) {
crc ^= *p++;
for (b = 0; b < 32; b++) {
if (crc & (1 << 31))
crc = (crc << 1) ^ crc_poly;
else
crc <<= 1;
}
}
return crc;
}
static uint32_t ware_crc(uint32_t crc, const vanmoof_ware_t *ware, const void *data, size_t length)
{
vanmoof_ware_t tmp;
memcpy(&tmp, ware, sizeof(tmp));
tmp.crc = 0xffffffff;
tmp.length = 0xffffffff;
crc = crc32_calculate(crc, &tmp, sizeof(tmp));
crc = crc32_calculate(crc, data + sizeof(tmp), length - sizeof(tmp));
return crc;
}
int main(int argc, char** argv)
{
progname = strrchr(argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
if (argc < 2)
usage();
char *filename = argv[1];
int fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0) {
fprintf(stderr, "%s: open(%s): %s\n", progname, filename, strerror(errno));
exit(1);
}
struct stat st;
if (fstat(fd, &st) < 0) {
fprintf(stderr, "%s: stat(%s): %s\n", progname, filename, strerror(errno));
exit(1);
}
void *data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (data == (void *)-1) {
fprintf(stderr, "%s: mmap(%s): %s\n", progname, filename, strerror(errno));
exit(1);
}
close(fd);
vanmoof_ware_t ware;
memcpy(&ware, data, sizeof(ware));
ble_ware_t ble_ware;
memcpy(&ble_ware, data, sizeof(ble_ware));
if (le32toh(ware.magic) == WARE_MAGIC) {
printf("%s: vanmoof ware magic OK\n", filename);
printf("%s: vanmoof ware version %08x\n", filename, le32toh(ware.version));
printf("%s: vanmoof ware CRC 0x%08x\n", filename, le32toh(ware.crc));
printf("%s: vanmoof ware length 0x%08x\n", filename, le32toh(ware.length));
printf("%s: vanmoof ware date %s\n", filename, ware.date);
printf("%s: vanmoof ware time %s\n", filename, ware.time);
uint32_t length = le32toh(ware.length);
if (length > st.st_size) {
printf("%s: vanmoof ware length 0x%08x extends beyond file size 0x%08zx\n",
filename, length, st.st_size);
exit(1);
}
uint32_t crc = ware_crc(initial_crc, &ware, data, length);
printf("%s: CRC 0x%08x %s\n", filename, crc, crc == le32toh(ware.crc) ? "OK" : "FAIL");
if (crc != le32toh(ware.crc))
exit(1);
} else if (memcmp(ble_ware.magic, BLE_WARE_MAGIC, sizeof(ble_ware.magic)) == 0) {
printf("%s: BLE ware magic OK\n", filename);
printf("%s: BLE ware version %08x\n", filename, le32toh(ble_ware.soft_ver));
printf("%s: BLE ware CRC 0x%08x\n", filename, le32toh(ble_ware.crc));
printf("%s: BLE ware length 0x%08x\n", filename, le32toh(ble_ware.len));
uint32_t length = le32toh(ble_ware.len);
if (length > st.st_size) {
printf("%s: BLE ware length 0x%08x extends beyond file size 0x%08zx\n",
filename, length, st.st_size);
exit(1);
}
uint32_t crc = crc32(0, data + 12, length - 12);
printf("%s: CRC 0x%08x %s\n", filename, crc, crc == le32toh(ble_ware.crc) ? "OK" : "FAIL");
if (crc != le32toh(ble_ware.crc))
exit(1);
printf("%s: BLE ware entry 0x%08x\n", filename, le32toh(ble_ware.prg_entry));
printf("%s: BLE ware hdr len 0x%08x\n", filename, le32toh(ble_ware.hdr_len));
ble_ware_seg_t seg;
size_t offset = le32toh(ble_ware.hdr_len);
while (offset < st.st_size) {
memcpy(&seg, data + offset, sizeof(ble_ware_seg_t));
printf("%s: BLE ware seg type 0x%02x\n", filename, seg.seg_type);
printf("%s: BLE ware seg len 0x%08x\n", filename, le32toh(seg.seg_len));
if (seg.seg_type == BLE_SEG_TYPE_SECURITY) {
ble_ware_signature_seg_t sig;
memcpy(&sig, data + offset + sizeof(ble_ware_seg_t),
le32toh(seg.seg_len) - sizeof(ble_ware_seg_t));
printf("%s: BLE ware signature ver 0x%02x\n", filename, sig.sig_ver);
printf("%s: BLE ware signature timestamp 0x%08x\n", filename, le32toh(sig.timestamp));
printf("%s: BLE ware signature signer %02x %02x %02x %02x %02x %02x %02x %02x\n",
filename, sig.ecdsa_signer[0], sig.ecdsa_signer[1], sig.ecdsa_signer[2],
sig.ecdsa_signer[3], sig.ecdsa_signer[4], sig.ecdsa_signer[5],
sig.ecdsa_signer[6], sig.ecdsa_signer[7]);
printf("%s: BLE ware signature %02x %02x %02x %02x ...\n",
filename, sig.ecdsa_signature[0], sig.ecdsa_signature[1],
sig.ecdsa_signature[2], sig.ecdsa_signature[3]);
}
offset += le32toh(seg.seg_len);
}
} else {
printf("%s: vanmoof ware magic not found, assume boot-loader binary\n", filename);
uint32_t expected_crc = le32toh(*(uint32_t *)(data + st.st_size - sizeof(uint32_t)));
uint8_t *version = (uint8_t *)(data + st.st_size - 2 * sizeof(uint32_t));
printf("%s: version %c%c%c\n", filename, version[3], version[2], version[1]);
printf("%s: expected CRC 0x%08x\n", filename, expected_crc);
uint32_t crc = crc32_calculate(initial_crc, data, st.st_size - sizeof(uint32_t));
printf("%s: CRC 0x%08x %s\n", filename, crc, crc == expected_crc ? "OK" : "FAIL");
if (crc != expected_crc)
exit(1);
}
return 0;
}