aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Zongker2014-01-13 16:16:58 -0600
committerDoug Zongker2014-01-16 15:29:28 -0600
commit99916f0496cfe37891d40f21a9a0e387620a8a60 (patch)
tree6b457a65cfdf482fec027386fcd7d197586c67b2 /verifier.cpp
parent0708239c003a1537c9cbf98dea5a490955d667aa (diff)
downloadplatform-bootable-recovery-99916f0496cfe37891d40f21a9a0e387620a8a60.tar.gz
platform-bootable-recovery-99916f0496cfe37891d40f21a9a0e387620a8a60.tar.xz
platform-bootable-recovery-99916f0496cfe37891d40f21a9a0e387620a8a60.zip
do verification and extraction on memory, not files
Changes minzip and recovery's file signature verification to work on memory regions, rather than files. For packages which are regular files, install.cpp now mmap()s them into memory and then passes the mapped memory to the verifier and to the minzip library. Support for files which are raw block maps (which will be used when we have packages written to encrypted data partitions) is present but largely untested so far. Bug: 12188746 Change-Id: I12cc3e809834745a489dd9d4ceb558cbccdc3f71
Diffstat (limited to 'verifier.cpp')
-rw-r--r--verifier.cpp70
1 files changed, 15 insertions, 55 deletions
diff --git a/verifier.cpp b/verifier.cpp
index 0930fbd1..55d58ee2 100644
--- a/verifier.cpp
+++ b/verifier.cpp
@@ -111,15 +111,10 @@ static bool read_pkcs7(uint8_t* pkcs7_der, size_t pkcs7_der_len, uint8_t** sig_d
111// Return VERIFY_SUCCESS, VERIFY_FAILURE (if any error is encountered 111// Return VERIFY_SUCCESS, VERIFY_FAILURE (if any error is encountered
112// or no key matches the signature). 112// or no key matches the signature).
113 113
114int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys) { 114int verify_file(unsigned char* addr, size_t length,
115 const Certificate* pKeys, unsigned int numKeys) {
115 ui->SetProgress(0.0); 116 ui->SetProgress(0.0);
116 117
117 FILE* f = fopen(path, "rb");
118 if (f == NULL) {
119 LOGE("failed to open %s (%s)\n", path, strerror(errno));
120 return VERIFY_FAILURE;
121 }
122
123 // An archive with a whole-file signature will end in six bytes: 118 // An archive with a whole-file signature will end in six bytes:
124 // 119 //
125 // (2-byte signature start) $ff $ff (2-byte comment size) 120 // (2-byte signature start) $ff $ff (2-byte comment size)
@@ -131,22 +126,15 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
131 126
132#define FOOTER_SIZE 6 127#define FOOTER_SIZE 6
133 128
134 if (fseek(f, -FOOTER_SIZE, SEEK_END) != 0) { 129 if (length < FOOTER_SIZE) {
135 LOGE("failed to seek in %s (%s)\n", path, strerror(errno)); 130 LOGE("not big enough to contain footer\n");
136 fclose(f);
137 return VERIFY_FAILURE; 131 return VERIFY_FAILURE;
138 } 132 }
139 133
140 unsigned char footer[FOOTER_SIZE]; 134 unsigned char* footer = addr + length - FOOTER_SIZE;
141 if (fread(footer, 1, FOOTER_SIZE, f) != FOOTER_SIZE) {
142 LOGE("failed to read footer from %s (%s)\n", path, strerror(errno));
143 fclose(f);
144 return VERIFY_FAILURE;
145 }
146 135
147 if (footer[2] != 0xff || footer[3] != 0xff) { 136 if (footer[2] != 0xff || footer[3] != 0xff) {
148 LOGE("footer is wrong\n"); 137 LOGE("footer is wrong\n");
149 fclose(f);
150 return VERIFY_FAILURE; 138 return VERIFY_FAILURE;
151 } 139 }
152 140
@@ -157,7 +145,6 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
157 145
158 if (signature_start <= FOOTER_SIZE) { 146 if (signature_start <= FOOTER_SIZE) {
159 LOGE("Signature start is in the footer"); 147 LOGE("Signature start is in the footer");
160 fclose(f);
161 return VERIFY_FAILURE; 148 return VERIFY_FAILURE;
162 } 149 }
163 150
@@ -167,9 +154,8 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
167 // comment length. 154 // comment length.
168 size_t eocd_size = comment_size + EOCD_HEADER_SIZE; 155 size_t eocd_size = comment_size + EOCD_HEADER_SIZE;
169 156
170 if (fseek(f, -eocd_size, SEEK_END) != 0) { 157 if (length < eocd_size) {
171 LOGE("failed to seek in %s (%s)\n", path, strerror(errno)); 158 LOGE("not big enough to contain EOCD\n");
172 fclose(f);
173 return VERIFY_FAILURE; 159 return VERIFY_FAILURE;
174 } 160 }
175 161
@@ -177,26 +163,15 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
177 // This is everything except the signature data and length, which 163 // This is everything except the signature data and length, which
178 // includes all of the EOCD except for the comment length field (2 164 // includes all of the EOCD except for the comment length field (2
179 // bytes) and the comment data. 165 // bytes) and the comment data.
180 size_t signed_len = ftell(f) + EOCD_HEADER_SIZE - 2; 166 size_t signed_len = length - eocd_size + EOCD_HEADER_SIZE - 2;
181 167
182 unsigned char* eocd = (unsigned char*)malloc(eocd_size); 168 unsigned char* eocd = addr + length - eocd_size;
183 if (eocd == NULL) {
184 LOGE("malloc for EOCD record failed\n");
185 fclose(f);
186 return VERIFY_FAILURE;
187 }
188 if (fread(eocd, 1, eocd_size, f) != eocd_size) {
189 LOGE("failed to read eocd from %s (%s)\n", path, strerror(errno));
190 fclose(f);
191 return VERIFY_FAILURE;
192 }
193 169
194 // If this is really is the EOCD record, it will begin with the 170 // If this is really is the EOCD record, it will begin with the
195 // magic number $50 $4b $05 $06. 171 // magic number $50 $4b $05 $06.
196 if (eocd[0] != 0x50 || eocd[1] != 0x4b || 172 if (eocd[0] != 0x50 || eocd[1] != 0x4b ||
197 eocd[2] != 0x05 || eocd[3] != 0x06) { 173 eocd[2] != 0x05 || eocd[3] != 0x06) {
198 LOGE("signature length doesn't match EOCD marker\n"); 174 LOGE("signature length doesn't match EOCD marker\n");
199 fclose(f);
200 return VERIFY_FAILURE; 175 return VERIFY_FAILURE;
201 } 176 }
202 177
@@ -209,7 +184,6 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
209 // which could be exploitable. Fail verification if 184 // which could be exploitable. Fail verification if
210 // this sequence occurs anywhere after the real one. 185 // this sequence occurs anywhere after the real one.
211 LOGE("EOCD marker occurs after start of EOCD\n"); 186 LOGE("EOCD marker occurs after start of EOCD\n");
212 fclose(f);
213 return VERIFY_FAILURE; 187 return VERIFY_FAILURE;
214 } 188 }
215 } 189 }
@@ -229,35 +203,23 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
229 SHA256_CTX sha256_ctx; 203 SHA256_CTX sha256_ctx;
230 SHA_init(&sha1_ctx); 204 SHA_init(&sha1_ctx);
231 SHA256_init(&sha256_ctx); 205 SHA256_init(&sha256_ctx);
232 unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE);
233 if (buffer == NULL) {
234 LOGE("failed to alloc memory for sha1 buffer\n");
235 fclose(f);
236 return VERIFY_FAILURE;
237 }
238 206
239 double frac = -1.0; 207 double frac = -1.0;
240 size_t so_far = 0; 208 size_t so_far = 0;
241 fseek(f, 0, SEEK_SET);
242 while (so_far < signed_len) { 209 while (so_far < signed_len) {
243 size_t size = BUFFER_SIZE; 210 size_t size = signed_len - so_far;
244 if (signed_len - so_far < size) size = signed_len - so_far; 211 if (size > BUFFER_SIZE) size = BUFFER_SIZE;
245 if (fread(buffer, 1, size, f) != size) { 212
246 LOGE("failed to read data from %s (%s)\n", path, strerror(errno)); 213 if (need_sha1) SHA_update(&sha1_ctx, addr + so_far, size);
247 fclose(f); 214 if (need_sha256) SHA256_update(&sha256_ctx, addr + so_far, size);
248 return VERIFY_FAILURE;
249 }
250 if (need_sha1) SHA_update(&sha1_ctx, buffer, size);
251 if (need_sha256) SHA256_update(&sha256_ctx, buffer, size);
252 so_far += size; 215 so_far += size;
216
253 double f = so_far / (double)signed_len; 217 double f = so_far / (double)signed_len;
254 if (f > frac + 0.02 || size == so_far) { 218 if (f > frac + 0.02 || size == so_far) {
255 ui->SetProgress(f); 219 ui->SetProgress(f);
256 frac = f; 220 frac = f;
257 } 221 }
258 } 222 }
259 fclose(f);
260 free(buffer);
261 223
262 const uint8_t* sha1 = SHA_final(&sha1_ctx); 224 const uint8_t* sha1 = SHA_final(&sha1_ctx);
263 const uint8_t* sha256 = SHA256_final(&sha256_ctx); 225 const uint8_t* sha256 = SHA256_final(&sha256_ctx);
@@ -269,10 +231,8 @@ int verify_file(const char* path, const Certificate* pKeys, unsigned int numKeys
269 if (!read_pkcs7(eocd + eocd_size - signature_start, signature_size, &sig_der, 231 if (!read_pkcs7(eocd + eocd_size - signature_start, signature_size, &sig_der,
270 &sig_der_length)) { 232 &sig_der_length)) {
271 LOGE("Could not find signature DER block\n"); 233 LOGE("Could not find signature DER block\n");
272 free(eocd);
273 return VERIFY_FAILURE; 234 return VERIFY_FAILURE;
274 } 235 }
275 free(eocd);
276 236
277 /* 237 /*
278 * Check to make sure at least one of the keys matches the signature. Since 238 * Check to make sure at least one of the keys matches the signature. Since