summaryrefslogtreecommitdiff
path: root/recovery/check/security.cpp (plain)
blob: 8c48cdf17b844964a0b97d97ce2bef176aa78f29
1#include <ctype.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <limits.h>
5#include <sys/stat.h>
6#include <sys/wait.h>
7#include <unistd.h>
8#include <sys/types.h>
9#include <sys/mount.h>
10#include <string.h>
11
12#include <ziparchive/zip_archive.h>
13#include <android-base/logging.h>
14
15#include "common.h"
16#include "cutils/properties.h"
17#include "security.h"
18
19T_KernelVersion kernel_ver = KernelV_3_10;
20/**
21 * --- judge platform whether match with zip image or not
22 *
23 * @platformEncryptStatus: 0: platform unencrypted, 1: platform encrypted
24 * @imageEncryptStatus: 0: image unencrypted, 1: image encrypted
25 * @imageName: image name
26 * @imageBuffer: image data address
27 * @imageSize: image data size
28 *
29 * return value:
30 * <0: failed
31 * =0: not match
32 * >0: match
33 */
34static int IsPlatformMachWithZipArchiveImage(
35 const int platformEncryptStatus,
36 const int imageEncryptStatus,
37 const char *imageName,
38 const unsigned char *imageBuffer,
39 const int imageSize)
40{
41 int fd = -1, ret = -1;
42 ssize_t result = -1;
43
44 if (strcmp(imageName, BOOT_IMG) &&
45 strcmp(imageName, RECOVERY_IMG) &&
46 strcmp(imageName, BOOTLOADER_IMG)) {
47 printf("can't support %s at present\n",
48 imageName);
49 return -1;
50 }
51
52 if (imageBuffer == NULL) {
53 printf("havn't malloc space for %s\n",
54 imageName);
55 return -1;
56 }
57
58 if (imageSize <= 0) {
59 printf("%s size is %d\n",
60 imageName, imageSize);
61 return -1;
62 }
63
64 switch (platformEncryptStatus) {
65 case 0: {
66 if (!imageEncryptStatus) {
67 ret = 1;
68 } else {
69 ret = 0;
70 }
71 break;
72 }
73
74 case 1: {
75 if (!imageEncryptStatus) {
76 ret = 0;
77 } else {
78 fd = open(DEFEND_KEY, O_RDWR);
79 if (fd <= 0) {
80 printf("open %s failed (%s)\n",
81 DEFEND_KEY, strerror(errno));
82 return -1;
83 }
84 result = write(fd, imageBuffer, imageSize);// check rsa
85 printf("write %s datas to %s. [imgsize:%d, result:%d, %s]\n",
86 imageName, DEFEND_KEY, imageSize, result,
87 (result == 1) ? "match" :
88 (result == -2) ? "not match" : "failed or not support");
89 if (result == 1) {
90 ret = 1;
91 } else if(result == -2) {
92 ret = 0;
93 } else { // failed or not support
94 ret = -1;
95 }
96 close(fd);
97 fd = -1;
98 }
99 break;
100 }
101 }
102
103 return ret;
104}
105
106/**
107 * --- check bootloader.img whether encrypt or not
108 *
109 * @imageName: bootloader.img
110 * @imageBuffer: bootloader.img data address
111 *
112 * return value:
113 * <0: failed
114 * =0: unencrypted
115 * >0: encrypted
116 */
117static int IsBootloaderImageEncrypted(
118 const char *imageName,
119 const unsigned char *imageBuffer)
120{
121 int step0=1;
122 int step1=1;
123 int index=0;
124 unsigned char result= 0;
125 const unsigned char *pstart = NULL;
126 const unsigned char *pImageAddr = imageBuffer;
127 const unsigned char *pEncryptedBootloaderInfoBufAddr = NULL;
128
129 // Don't modify. unencrypt bootloader info, for kernel version 3.10
130 const int bootloaderEncryptInfoOffset = 0x1b0;
131 const unsigned char unencryptedBootloaderInfoBuf[] =
132 { 0x4D, 0x33, 0x48, 0x48, 0x52, 0x45, 0x56, 0x30 };
133
134 // Don't modify. unencrypt bootloader info, for kernel version 3.14
135 const int newbootloaderEncryptInfoOffset = 0x10;
136 const int newbootloaderEncryptInfoOffset1 = 0x70;
137 const unsigned char newunencryptedBootloaderInfoBuf[] = { 0x40, 0x41, 0x4D, 0x4C};
138
139 if (strcmp(imageName, BOOTLOADER_IMG)) {
140 printf("this image must be %s,but it is %s\n",
141 BOOTLOADER_IMG, imageName);
142 return -1;
143 }
144
145 if (imageBuffer == NULL) {
146 printf("havn't malloc space for %s\n",
147 imageName);
148 return -1;
149 }
150
151 if (kernel_ver == KernelV_3_10) {
152 //check image whether encrypted for kernel 3.10
153 pEncryptedBootloaderInfoBufAddr = pImageAddr + bootloaderEncryptInfoOffset;
154 if (!memcmp(unencryptedBootloaderInfoBuf, pEncryptedBootloaderInfoBufAddr,
155 ARRAY_SIZE(unencryptedBootloaderInfoBuf))) {
156 return 0; // unencrypted
157 } else {
158 return 1;
159 }
160 }
161
162 //check image whether encrypted for kernel 3.14
163 pEncryptedBootloaderInfoBufAddr = pImageAddr + newbootloaderEncryptInfoOffset;
164 if (!memcmp(newunencryptedBootloaderInfoBuf, pEncryptedBootloaderInfoBufAddr,
165 ARRAY_SIZE(newunencryptedBootloaderInfoBuf))) {
166 step0 = 0;
167 }
168
169 pstart = pImageAddr + newbootloaderEncryptInfoOffset1;
170 for (index=0;index<16;index++) {
171 result ^= pstart[index];
172 }
173
174 if (result == 0) {
175 step1 = 0;
176 }
177
178 if ((step0 == 1) && (step0 == 1)) {
179 return 1; // encrypted
180 }
181
182 return 0;//unencrypted
183}
184
185/* return value:
186 * <0: failed
187 * =0: not match
188 * >0: match
189 */
190int DtbImgEncrypted(
191 const char *imageName,
192 const unsigned char *imageBuffer,
193 const int imageSize,
194 const char *flag,
195 unsigned char *encryptedbuf)
196{
197 int len = 0;
198 ssize_t result = -1;
199 ssize_t readlen = -1;
200 int fd = -1, ret = -1;
201
202 if ((imageBuffer == NULL) || (imageName == NULL)) {
203 printf("imageBuffer is null!\n");
204 return -1;
205 }
206
207 if (access(DECRYPT_DTB, F_OK) ||access(DEFEND_KEY, F_OK)) {
208 printf("doesn't support dtb secure check\n");
209 return 2; // kernel doesn't support
210 }
211
212 fd = open(DECRYPT_DTB, O_RDWR);
213 if (fd <= 0) {
214 printf("open %s failed!\n", DECRYPT_DTB);
215 return -1;
216 }
217
218 len = write(fd, flag, 1);
219 if (len != 1) {
220 printf("write %s failed!\n", DECRYPT_DTB);
221 close(fd);
222 fd = -1;
223 return -1;
224 }
225
226 close(fd);
227 fd = -1;
228
229 fd = open(DEFEND_KEY, O_RDWR);
230 if (fd <= 0) {
231 printf("open %s failed (%s)\n",DEFEND_KEY, strerror(errno));
232 return -1;
233 }
234
235 result = write(fd, imageBuffer, imageSize);// check rsa
236 printf("write %s datas to %s. [imgsize:%d, result:%d, %s]\n",
237 imageName, DEFEND_KEY, imageSize, result,
238 (result == 1) ? "match" :
239 (result == -2) ? "not match" : "failed or not support");
240
241 if (!strcmp(flag, "1")) {
242 printf("dtb.img need to encrypted!\n");
243 readlen = read(fd, encryptedbuf, imageSize);
244 if (readlen < 0) {
245 printf("read %s error!\n", DEFEND_KEY);
246 close(fd);
247 return -1;
248 }
249
250 }
251
252 if (result == 1) {
253 ret = 1;
254 } else if(result == -2) {
255 ret = 0;
256 } else { // failed or not support
257 ret = -1;
258 }
259
260 close(fd);
261 fd = -1;
262
263 return ret;
264}
265
266/**
267 * --- check zip archive image whether encrypt or not
268 * image is bootloader.img/boot.img/recovery.img
269 *
270 * @imageName: image name
271 * @imageBuffer: image data address
272 * @imageSize: image data size
273 *
274 * return value:
275 * <0: failed
276 * =0: unencrypted
277 * >0: encrypted
278 */
279static int IsZipArchiveImageEncrypted(
280 const char *imageName,
281 const unsigned char *imageBuffer,
282 const int imageSize)
283{
284 int ret = -1;
285 const unsigned char *pImageAddr = imageBuffer;
286
287 if (strcmp(imageName, BOOT_IMG) &&
288 strcmp(imageName, RECOVERY_IMG) &&
289 strcmp(imageName, BOOTLOADER_IMG)) {
290 printf("can't support %s at present\n",
291 imageName);
292 return -1;
293 }
294
295 if (imageBuffer == NULL) {
296 printf("havn't malloc space for %s\n",
297 imageName);
298 return -1;
299 }
300
301 if (imageSize <= 0) {
302 printf("%s size is %d\n",
303 imageName, imageSize);
304 return -1;
305 }
306
307 if (!strcmp(imageName, BOOTLOADER_IMG)) {
308 return IsBootloaderImageEncrypted(imageName, imageBuffer);
309 }
310
311 if (kernel_ver == KernelV_3_10) {
312 //check image whether encrypted for kernel 3.10
313 const pT_SecureBootImgHdr encryptSecureBootImgHdr =
314 (const pT_SecureBootImgHdr)pImageAddr;
315 const pT_EncryptBootImgInfo encryptBootImgInfo =
316 &encryptSecureBootImgHdr->encryptBootImgInfo;
317
318 secureDbg("magic:%s, version:0x%04x, totalLenAfterEncrypted:0x%0x\n",
319 encryptBootImgInfo->magic, encryptBootImgInfo->version,
320 encryptBootImgInfo->totalLenAfterEncrypted);
321
322 ret = memcmp(encryptBootImgInfo->magic, SECUREBOOT_MAGIC,
323 strlen(SECUREBOOT_MAGIC));
324 if (!ret && encryptBootImgInfo->version != 0x0) {
325 return 1; // encrypted
326 }
327
328 return 0;
329 }
330
331 //check image whether encrypted for kernel 3.14
332 const AmlSecureBootImgHeader encryptSecureBootImgHeader =
333 (const AmlSecureBootImgHeader)pImageAddr;
334 const p_AmlEncryptBootImgInfo encryptBootImgHeader =
335 &encryptSecureBootImgHeader->encrypteImgInfo;
336
337 secureDbg("magic:%s, version:0x%04x\n",
338 encryptBootImgHeader->magic, encryptBootImgHeader->version);
339
340 ret = memcmp(encryptBootImgHeader->magic, SECUREBOOT_MAGIC,
341 strlen(SECUREBOOT_MAGIC));
342 if (!ret && encryptBootImgHeader->version != 0x0) {
343 return 1; // encrypted
344 }
345
346 return 0; // unencrypted
347 }
348
349/**
350 * --- check platform whether encrypt or not
351 *
352 * return value:
353 * <0: failed
354 * =0: unencrypted
355 * >0: encrypted
356 */
357int IsPlatformEncrypted(void)
358{
359 int fd = -1, ret = -1;
360 ssize_t count = 0;
361 char rBuf[128] = {0};
362 char platform[PROPERTY_VALUE_MAX+1] = {0};
363
364 if (!(access(SECURE_CHECK, F_OK) || (access(SECURE_CHECK_BAK, F_OK))) \
365 || access(DEFEND_KEY, F_OK)) {
366 printf("kernel doesn't support secure check\n");
367 return 2; // kernel doesn't support
368 }
369
370 fd = open(SECURE_CHECK, O_RDONLY);
371 if (fd <= 0) {
372 fd = open(SECURE_CHECK_BAK, O_RDONLY);
373 if (fd <= 0) {
374 printf("open %s failed (%s)\n",
375 SECURE_CHECK, strerror(errno));
376 return -1;
377 }
378 kernel_ver = KernelV_3_14;
379 }
380
381 property_get("ro.build.product", platform, "unknow");
382 count = read(fd, rBuf, sizeof(rBuf) - 1);
383 if (count <= 0) {
384 printf("read %s failed (count:%d)\n",
385 SECURE_CHECK, count);
386 close(fd);
387 return -1;
388 }
389 rBuf[count] = '\0';
390
391 if (!strcmp(rBuf, s_pStatus[UNENCRYPT])) {
392 printf("check platform(%s): unencrypted\n", platform);
393 ret = 0;
394 } else if (!strcmp(rBuf, s_pStatus[ENCRYPT])) {
395 printf("check platform(%s): encrypted\n", platform);
396 ret = 1;
397 } else if (!strcmp(rBuf, s_pStatus[FAIL])) {
398 printf("check platform(%s): failed\n", platform);
399 } else {
400 printf("check platform(%s): %s\n", platform, rBuf);
401 }
402
403 if (fd > 0) {
404 close(fd);
405 fd = -1;
406 }
407
408 return ret;
409}
410
411/**
412 * --- get upgrade package image data
413 *
414 * @zipArchive: zip archive object
415 * @imageName: upgrade package image's name
416 * @imageSize: upgrade package image's size
417 *
418 * return value:
419 * <0: failed
420 * =0: can't find image
421 * >0: get image data successful
422 */
423static unsigned char *s_pImageBuffer = NULL;
424static int GetZipArchiveImage(
425 const ZipArchiveHandle za,
426 const char *imageName,
427 int *imageSize)
428{
429 ZipString zip_path(imageName);
430 ZipEntry entry;
431 if (FindEntry(za, zip_path, &entry) != 0) {
432 printf("no %s in package!\n", imageName);
433 return 0;
434 }
435
436 *imageSize = entry.uncompressed_length;
437 if (*imageSize <= 0) {
438 printf("can't get package entry uncomp len(%d) (%s)\n",
439 *imageSize, strerror(errno));
440 return -1;
441 }
442
443 if (s_pImageBuffer != NULL) {
444 free(s_pImageBuffer);
445 s_pImageBuffer = NULL;
446 }
447
448 s_pImageBuffer = (unsigned char *)calloc(*imageSize, sizeof(unsigned char));
449 if (!s_pImageBuffer) {
450 printf("can't malloc %d size space (%s)\n",
451 *imageSize, strerror(errno));
452 return -1;
453 }
454
455 int32_t ret = ExtractToMemory(za, &entry, s_pImageBuffer, entry.uncompressed_length);
456 if (ret != 0) {
457 printf("can't extract package entry to image buffer\n");
458 goto FREE_IMAGE_MEM;
459 }
460
461 return 1;
462
463
464FREE_IMAGE_MEM:
465 if (s_pImageBuffer != NULL) {
466 free(s_pImageBuffer);
467 s_pImageBuffer = NULL;
468 }
469
470 return -1;
471}
472
473/**
474 * --- check platform and upgrade package whether
475 * encrypted,if all encrypted,rsa whether all the same
476 *
477 * @ziparchive: Archive of Zip Package
478 *
479 * return value:
480 * =-1: failed; not allow upgrade
481 * = 0: check not match; not allow upgrade
482 * = 1: check match; allow upgrade
483 * = 2: kernel not support secure check; allow upgrade
484 */
485int RecoverySecureCheck(const ZipArchiveHandle zipArchive)
486{
487 int i = 0, ret = -1, err = -1;
488 int ret_dtb = 0;
489 int imageSize = 0;
490 int platformEncryptStatus = 0, imageEncryptStatus = 0;
491 const char *pImageName[] = {
492 BOOTLOADER_IMG,
493 BOOT_IMG,
494 RECOVERY_IMG };
495
496 platformEncryptStatus = IsPlatformEncrypted();
497 if (platformEncryptStatus == 2) {
498 return 2;// kernel doesn't support
499 }
500
501 if (platformEncryptStatus < 0) {
502 return -1;
503 }
504
505 if (platformEncryptStatus >0 ) {
506 ret = GetZipArchiveImage(zipArchive, DTB_IMG, &imageSize);
507 if (ret > 0) {
508 ret_dtb = DtbImgEncrypted(DTB_IMG, s_pImageBuffer, imageSize, "0", NULL);
509 if (ret_dtb == 2) {
510 printf("dtb secure check not support!\n");
511 } else if (ret_dtb > 0){
512 printf("dtb secure check success!\n");
513
514 } else {
515 printf("dtb secure check error!\n");
516 ret = -1;
517 goto ERR1;
518 }
519 } else if (ret == 0) {
520 printf("check %s: not find,skiping...\n", DTB_IMG);
521 } else {
522 printf("get %s datas failed\n", DTB_IMG);
523 goto ERR1;
524 }
525 }
526
527 for (i = 0; i < ARRAY_SIZE(pImageName); i++) {
528 ret = GetZipArchiveImage(zipArchive, pImageName[i], &imageSize);
529 if (ret < 0) {
530 printf("get %s datas failed\n", pImageName[i]);
531 goto ERR1;
532 } else if (ret == 0) {
533 printf("check %s: not find,skiping...\n", pImageName[i]);
534 continue;
535 } else if (ret > 0) {
536 secureDbg("get %s datas(size:0x%0x, addr:0x%x) successful\n",
537 pImageName[i], imageSize, (int)s_pImageBuffer);
538 imageEncryptStatus = IsZipArchiveImageEncrypted(pImageName[i], s_pImageBuffer, imageSize);
539
540 printf("check %s: %s\n",
541 pImageName[i], (imageEncryptStatus < 0) ? "failed" :
542 !imageEncryptStatus ? "unencrypted" : "encrypted");
543 if (imageEncryptStatus < 0) {
544 ret = -1;
545 goto ERR1;
546 }
547
548 ret = IsPlatformMachWithZipArchiveImage(
549 platformEncryptStatus, imageEncryptStatus, pImageName[i],
550 s_pImageBuffer, imageSize);
551 if (ret < 0) {
552 printf("%s match platform failed\n", pImageName[i]);
553 goto ERR1;
554 } else if (ret == 0) { // if one of image doesn't match with platform,exit
555 printf("%s doesn't match platform\n", pImageName[i]);
556 goto ERR1;
557 } else {
558 secureDbg("%s match platform\n", pImageName[i]);
559 }
560
561 if (s_pImageBuffer != NULL) {
562 free(s_pImageBuffer);
563 s_pImageBuffer = NULL;
564 }
565 }
566 }
567
568 return 1;
569
570
571ERR1:
572 if (s_pImageBuffer != NULL) {
573 free(s_pImageBuffer);
574 s_pImageBuffer = NULL;
575 }
576
577 return ret;
578}
579