Fix merge conflicts and update for 4.4 kitkat

Make a copy of libmincrypt in TWRP source so we do not have to
ifdef verifier.cpp for various versions of mincrypt.

Remove reboot tool from toolbox (it was removed from 4.4 and did
not compile properly on some devices in older trees)
This commit is contained in:
Dees Troy
2013-11-02 20:25:14 +00:00
37 changed files with 1706 additions and 258 deletions
+6 -5
View File
@@ -306,13 +306,13 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libaosprecovery
LOCAL_MODULE_TAGS := eng
LOCAL_MODULES_TAGS = optional
LOCAL_CFLAGS =
ifneq ($(wildcard system/core/libmincrypt/rsa_e_3.c),)
LOCAL_CFLAGS += -DHAS_EXPONENT
ifeq ($(TARGET_BOARD_PLATFORM),rk30xx)
LOCAL_CFLAGS += -DRK3066
endif
LOCAL_C_INCLUDES := bootable/recovery/libmincrypt/includes
LOCAL_SRC_FILES = adb_install.cpp bootloader.cpp verifier.cpp mtdutils/mtdutils.c
LOCAL_SHARED_LIBRARIES += libc liblog libcutils libmtdutils
LOCAL_STATIC_LIBRARIES += libmincrypt
LOCAL_STATIC_LIBRARIES += libmincrypttwrp
include $(BUILD_SHARED_LIBRARY)
@@ -343,7 +343,8 @@ include $(commands_recovery_local_path)/injecttwrp/Android.mk \
$(commands_recovery_local_path)/libblkid/Android.mk \
$(commands_recovery_local_path)/minuitwrp/Android.mk \
$(commands_recovery_local_path)/openaes/Android.mk \
$(commands_recovery_local_path)/toolbox/Android.mk
$(commands_recovery_local_path)/toolbox/Android.mk \
$(commands_recovery_local_path)/libmincrypt/Android.mk
ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true)
include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk
+1 -1
View File
@@ -101,7 +101,7 @@ int LoadFileContents(const char* filename, FileContents* file,
}
}
SHA(file->data, file->size, file->sha1);
SHA_hash(file->data, file->size, file->sha1);
return 0;
}
+2 -2
View File
@@ -287,13 +287,13 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
long l_int = strtol(left, &end, 10);
if (left[0] == '\0' || *end != '\0') {
fprintf(stderr, "[%s] is not an int\n", left);
printf("[%s] is not an int\n", left);
goto done;
}
long r_int = strtol(right, &end, 10);
if (right[0] == '\0' || *end != '\0') {
fprintf(stderr, "[%s] is not an int\n", right);
printf("[%s] is not an int\n", right);
goto done;
}
+5 -5
View File
@@ -34,8 +34,8 @@ int expect(const char* expr_str, const char* expected, int* errors) {
int error_count = 0;
error = yyparse(&e, &error_count);
if (error > 0 || error_count > 0) {
fprintf(stderr, "error parsing \"%s\" (%d errors)\n",
expr_str, error_count);
printf("error parsing \"%s\" (%d errors)\n",
expr_str, error_count);
++*errors;
return 0;
}
@@ -49,7 +49,7 @@ int expect(const char* expr_str, const char* expected, int* errors) {
free(state.errmsg);
free(state.script);
if (result == NULL && expected != NULL) {
fprintf(stderr, "error evaluating \"%s\"\n", expr_str);
printf("error evaluating \"%s\"\n", expr_str);
++*errors;
return 0;
}
@@ -59,8 +59,8 @@ int expect(const char* expr_str, const char* expected, int* errors) {
}
if (strcmp(result, expected) != 0) {
fprintf(stderr, "evaluating \"%s\": expected \"%s\", got \"%s\"\n",
expr_str, expected, result);
printf("evaluating \"%s\": expected \"%s\", got \"%s\"\n",
expr_str, expected, result);
++*errors;
free(result);
return 0;
+8
View File
@@ -2,6 +2,7 @@ import /init.recovery.${ro.hardware}.rc
on early-init
start ueventd
start healthd
on init
export PATH /sbin
@@ -37,13 +38,20 @@ on boot
class_start default
on property:sys.powerctl=*
powerctl ${sys.powerctl}
service ueventd /sbin/ueventd
critical
service healthd /sbin/healthd -n
critical
service recovery /sbin/recovery
service adbd /sbin/adbd recovery
disabled
socket adbd stream 660 system system
# Always start adbd on userdebug and eng builds
on property:ro.debuggable=1
+12 -6
View File
@@ -154,6 +154,7 @@ try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
} else {
ui->Print("\n");
}
fflush(stdout);
} else if (strcmp(command, "wipe_cache") == 0) {
*wipe_cache = 1;
} else if (strcmp(command, "clear_display") == 0) {
@@ -179,7 +180,9 @@ really_install_package(const char *path, int* wipe_cache)
{
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
ui->Print("Finding update package...\n");
ui->SetProgressType(RecoveryUI::INDETERMINATE);
// Give verification half the progress bar...
ui->SetProgressType(RecoveryUI::DETERMINATE);
ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
LOGI("Update location: %s\n", path);
if (ensure_path_mounted(path) != 0) {
@@ -190,17 +193,14 @@ really_install_package(const char *path, int* wipe_cache)
ui->Print("Opening update package...\n");
int numKeys;
RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
if (loadedKeys == NULL) {
LOGE("Failed to load keys\n");
return INSTALL_CORRUPT;
}
LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
// Give verification half the progress bar...
ui->Print("Verifying update package...\n");
ui->SetProgressType(RecoveryUI::DETERMINATE);
ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
int err;
err = verify_file(path, loadedKeys, numKeys);
@@ -236,7 +236,13 @@ install_package(const char* path, int* wipe_cache, const char* install_file)
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
}
int result = really_install_package(path, wipe_cache);
int result;
if (setup_install_mounts() != 0) {
LOGE("failed to set up expected mounts for install; aborting\n");
result = INSTALL_ERROR;
} else {
result = really_install_package(path, wipe_cache);
}
if (install_log) {
fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
fputc('\n', install_log);
+16
View File
@@ -0,0 +1,16 @@
# Copyright 2008 The Android Open Source Project
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypttwrp
LOCAL_C_INCLUDES := bootable/recovery/libmincrypt/includes
LOCAL_SRC_FILES := rsa.c sha.c sha256.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libmincrypttwrp
LOCAL_SRC_FILES := rsa.c sha.c sha256.c
include $(BUILD_HOST_STATIC_LIBRARY)
+23
View File
@@ -0,0 +1,23 @@
Copyright 2008, The Android Open Source Project
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Google Inc. nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,40 @@
// Copyright 2007 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
#define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct HASH_CTX; // forward decl
typedef struct HASH_VTAB {
void (* const init)(struct HASH_CTX*);
void (* const update)(struct HASH_CTX*, const void*, int);
const uint8_t* (* const final)(struct HASH_CTX*);
const uint8_t* (* const hash)(const void*, int, uint8_t*);
int size;
} HASH_VTAB;
typedef struct HASH_CTX {
const HASH_VTAB * f;
uint64_t count;
uint8_t buf[64];
uint32_t state[8]; // upto SHA2
} HASH_CTX;
#define HASH_init(ctx) (ctx)->f->init(ctx)
#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
#define HASH_final(ctx) (ctx)->f->final(ctx)
#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
#define HASH_size(ctx) (ctx)->f->size
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SECURITY_UTIL_LITE_HASH_INTERNAL_H__
+58
View File
@@ -0,0 +1,58 @@
/* rsa.h
**
** Copyright 2008, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EMBEDDED_RSA_H_
#define _EMBEDDED_RSA_H_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RSANUMBYTES 256 /* 2048 bit key length */
#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))
typedef struct RSAPublicKey {
int len; /* Length of n[] in number of uint32_t */
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
uint32_t n[RSANUMWORDS]; /* modulus as little endian array */
uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
int exponent; /* 3 or 65537 */
} RSAPublicKey;
int RSA_verify(const RSAPublicKey *key,
const uint8_t* signature,
const int len,
const uint8_t* hash,
const int hash_len);
#ifdef __cplusplus
}
#endif
#endif
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2005 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef SECURITY_UTIL_LITE_SHA1_H__
#define SECURITY_UTIL_LITE_SHA1_H__
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef HASH_CTX SHA_CTX;
void SHA_init(SHA_CTX* ctx);
void SHA_update(SHA_CTX* ctx, const void* data, int len);
const uint8_t* SHA_final(SHA_CTX* ctx);
// Convenience method. Returns digest address.
// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
#define SHA_DIGEST_SIZE 20
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SECURITY_UTIL_LITE_SHA1_H__
+29
View File
@@ -0,0 +1,29 @@
// Copyright 2011 Google Inc. All Rights Reserved.
// Author: mschilder@google.com (Marius Schilder)
#ifndef SECURITY_UTIL_LITE_SHA256_H__
#define SECURITY_UTIL_LITE_SHA256_H__
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef HASH_CTX SHA256_CTX;
void SHA256_init(SHA256_CTX* ctx);
void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
const uint8_t* SHA256_final(SHA256_CTX* ctx);
// Convenience method. Returns digest address.
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
#define SHA256_DIGEST_SIZE 32
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SECURITY_UTIL_LITE_SHA256_H__
+308
View File
@@ -0,0 +1,308 @@
/* rsa.c
**
** Copyright 2012, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
// a[] -= mod
static void subM(const RSAPublicKey* key,
uint32_t* a) {
int64_t A = 0;
int i;
for (i = 0; i < key->len; ++i) {
A += (uint64_t)a[i] - key->n[i];
a[i] = (uint32_t)A;
A >>= 32;
}
}
// return a[] >= mod
static int geM(const RSAPublicKey* key,
const uint32_t* a) {
int i;
for (i = key->len; i;) {
--i;
if (a[i] < key->n[i]) return 0;
if (a[i] > key->n[i]) return 1;
}
return 1; // equal
}
// montgomery c[] += a * b[] / R % mod
static void montMulAdd(const RSAPublicKey* key,
uint32_t* c,
const uint32_t a,
const uint32_t* b) {
uint64_t A = (uint64_t)a * b[0] + c[0];
uint32_t d0 = (uint32_t)A * key->n0inv;
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
int i;
for (i = 1; i < key->len; ++i) {
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
c[i - 1] = (uint32_t)B;
}
A = (A >> 32) + (B >> 32);
c[i - 1] = (uint32_t)A;
if (A >> 32) {
subM(key, c);
}
}
// montgomery c[] = a[] * b[] / R % mod
static void montMul(const RSAPublicKey* key,
uint32_t* c,
const uint32_t* a,
const uint32_t* b) {
int i;
for (i = 0; i < key->len; ++i) {
c[i] = 0;
}
for (i = 0; i < key->len; ++i) {
montMulAdd(key, c, a[i], b);
}
}
// In-place public exponentiation.
// Input and output big-endian byte array in inout.
static void modpow(const RSAPublicKey* key,
uint8_t* inout) {
uint32_t a[RSANUMWORDS];
uint32_t aR[RSANUMWORDS];
uint32_t aaR[RSANUMWORDS];
uint32_t* aaa = 0;
int i;
// Convert from big endian byte array to little endian word array.
for (i = 0; i < key->len; ++i) {
uint32_t tmp =
(inout[((key->len - 1 - i) * 4) + 0] << 24) |
(inout[((key->len - 1 - i) * 4) + 1] << 16) |
(inout[((key->len - 1 - i) * 4) + 2] << 8) |
(inout[((key->len - 1 - i) * 4) + 3] << 0);
a[i] = tmp;
}
if (key->exponent == 65537) {
aaa = aaR; // Re-use location.
montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
for (i = 0; i < 16; i += 2) {
montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
}
montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
} else if (key->exponent == 3) {
aaa = aR; // Re-use location.
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
}
// Make sure aaa < mod; aaa is at most 1x mod too large.
if (geM(key, aaa)) {
subM(key, aaa);
}
// Convert to bigendian byte array
for (i = key->len - 1; i >= 0; --i) {
uint32_t tmp = aaa[i];
*inout++ = tmp >> 24;
*inout++ = tmp >> 16;
*inout++ = tmp >> 8;
*inout++ = tmp >> 0;
}
}
// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
// other flavor which omits the optional parameter entirely). This code does not
// accept signatures without the optional parameter.
/*
static const uint8_t sha_padding[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00, 0x04, 0x14,
// 20 bytes of hash go here.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
*/
// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
0x7c, 0xfb, 0xf1, 0x67
};
/*
static const uint8_t sha256_padding[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
// 32 bytes of hash go here.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
*/
// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
};
// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
// Both e=3 and e=65537 are supported. hash_len may be
// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
// values are supported.
//
// Returns 1 on successful verification, 0 on failure.
int RSA_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *hash,
const int hash_len) {
uint8_t buf[RSANUMBYTES];
int i;
const uint8_t* padding_hash;
if (key->len != RSANUMWORDS) {
return 0; // Wrong key passed in.
}
if (len != sizeof(buf)) {
return 0; // Wrong input length.
}
if (hash_len != SHA_DIGEST_SIZE &&
hash_len != SHA256_DIGEST_SIZE) {
return 0; // Unsupported hash.
}
if (key->exponent != 3 && key->exponent != 65537) {
return 0; // Unsupported exponent.
}
for (i = 0; i < len; ++i) { // Copy input to local workspace.
buf[i] = signature[i];
}
modpow(key, buf); // In-place exponentiation.
// Xor sha portion, so it all becomes 00 iff equal.
for (i = len - hash_len; i < len; ++i) {
buf[i] ^= *hash++;
}
// Hash resulting buf, in-place.
switch (hash_len) {
case SHA_DIGEST_SIZE:
padding_hash = kExpectedPadShaRsa2048;
SHA_hash(buf, len, buf);
break;
case SHA256_DIGEST_SIZE:
padding_hash = kExpectedPadSha256Rsa2048;
SHA256_hash(buf, len, buf);
break;
default:
return 0;
}
// Compare against expected hash value.
for (i = 0; i < hash_len; ++i) {
if (buf[i] != padding_hash[i]) {
return 0;
}
}
return 1; // All checked out OK.
}
+155
View File
@@ -0,0 +1,155 @@
/* sha.c
**
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
static void SHA1_Transform(SHA_CTX* ctx) {
uint32_t W[80];
uint32_t A, B, C, D, E;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for(; t < 80; t++) {
W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
for(t = 0; t < 80; t++) {
uint32_t tmp = rol(5,A) + E + W[t];
if (t < 20)
tmp += (D^(B&(C^D))) + 0x5A827999;
else if ( t < 40)
tmp += (B^C^D) + 0x6ED9EBA1;
else if ( t < 60)
tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
else
tmp += (B^C^D) + 0xCA62C1D6;
E = D;
D = C;
C = rol(30,B);
B = A;
A = tmp;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
static const HASH_VTAB SHA_VTAB = {
SHA_init,
SHA_update,
SHA_final,
SHA_hash,
SHA_DIGEST_SIZE
};
void SHA_init(SHA_CTX* ctx) {
ctx->f = &SHA_VTAB;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
void SHA_update(SHA_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == 64) {
SHA1_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA_final(SHA_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count & 63) != 56) {
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA_update(ctx, &tmp, 1);
}
for (i = 0; i < 5; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
/* Convenience function */
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
SHA_CTX ctx;
SHA_init(&ctx);
SHA_update(&ctx, data, len);
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
return digest;
}
+184
View File
@@ -0,0 +1,184 @@
/* sha256.c
**
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha256.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
#define shr(value, bits) ((value) >> (bits))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
static void SHA256_Transform(SHA256_CTX* ctx) {
uint32_t W[64];
uint32_t A, B, C, D, E, F, G, H;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for(; t < 64; t++) {
uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
W[t] = W[t-16] + s0 + W[t-7] + s1;
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
for(t = 0; t < 64; t++) {
uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
uint32_t t2 = s0 + maj;
uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
uint32_t ch = (E & F) ^ ((~E) & G);
uint32_t t1 = H + s1 + ch + K[t] + W[t];
H = G;
G = F;
F = E;
E = D + t1;
D = C;
C = B;
B = A;
A = t1 + t2;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
static const HASH_VTAB SHA256_VTAB = {
SHA256_init,
SHA256_update,
SHA256_final,
SHA256_hash,
SHA256_DIGEST_SIZE
};
void SHA256_init(SHA256_CTX* ctx) {
ctx->f = &SHA256_VTAB;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
ctx->count = 0;
}
void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == 64) {
SHA256_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA256_final(SHA256_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA256_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count & 63) != 56) {
SHA256_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA256_update(ctx, &tmp, 1);
}
for (i = 0; i < 8; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
/* Convenience function */
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
SHA256_CTX ctx;
SHA256_init(&ctx);
SHA256_update(&ctx, data, len);
memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
return digest;
}
+2 -2
View File
@@ -390,8 +390,8 @@ int gr_init(void)
get_memory_surface(&gr_mem_surface);
fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",
gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);
printf("framebuffer: fd %d (%d x %d)\n",
gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);
/* start with 0 as front (displayed) and 1 as back (drawing) */
gr_active_fb = 0;
+14 -13
View File
@@ -286,7 +286,7 @@ static int read_block(const MtdPartition *partition, int fd, char *data)
{
struct mtd_ecc_stats before, after;
if (ioctl(fd, ECCGETSTATS, &before)) {
fprintf(stderr, "mtd: ECCGETSTATS error (%s)\n", strerror(errno));
printf("mtd: ECCGETSTATS error (%s)\n", strerror(errno));
return -1;
}
@@ -297,13 +297,13 @@ static int read_block(const MtdPartition *partition, int fd, char *data)
while (pos + size <= (int) partition->size) {
if (lseek64(fd, pos, SEEK_SET) != pos || read(fd, data, size) != size) {
fprintf(stderr, "mtd: read error at 0x%08llx (%s)\n",
printf("mtd: read error at 0x%08llx (%s)\n",
pos, strerror(errno));
} else if (ioctl(fd, ECCGETSTATS, &after)) {
fprintf(stderr, "mtd: ECCGETSTATS error (%s)\n", strerror(errno));
printf("mtd: ECCGETSTATS error (%s)\n", strerror(errno));
return -1;
} else if (after.failed != before.failed) {
fprintf(stderr, "mtd: ECC errors (%d soft, %d hard) at 0x%08llx\n",
printf("mtd: ECC errors (%d soft, %d hard) at 0x%08llx\n",
after.corrected - before.corrected,
after.failed - before.failed, pos);
// copy the comparison baseline for the next read.
@@ -435,43 +435,44 @@ static int write_block(MtdWriteContext *ctx, const char *data)
}
#else
if (ioctl(fd, MEMERASE, &erase_info) < 0) {
fprintf(stderr, "mtd: erase failure at 0x%08lx (%s)\n",
printf("mtd: erase failure at 0x%08lx (%s)\n",
pos, strerror(errno));
continue;
}
#endif
if (lseek(fd, pos, SEEK_SET) != pos ||
write(fd, data, size) != size) {
fprintf(stderr, "mtd: write error at 0x%08lx (%s)\n",
printf("mtd: write error at 0x%08lx (%s)\n",
pos, strerror(errno));
}
char verify[size];
if (lseek(fd, pos, SEEK_SET) != pos ||
read(fd, verify, size) != size) {
fprintf(stderr, "mtd: re-read error at 0x%08lx (%s)\n",
printf("mtd: re-read error at 0x%08lx (%s)\n",
pos, strerror(errno));
continue;
}
if (memcmp(data, verify, size) != 0) {
fprintf(stderr, "mtd: verification error at 0x%08lx (%s)\n",
printf("mtd: verification error at 0x%08lx (%s)\n",
pos, strerror(errno));
continue;
}
if (retry > 0) {
fprintf(stderr, "mtd: wrote block after %d retries\n", retry);
printf("mtd: wrote block after %d retries\n", retry);
}
fprintf(stderr, "mtd: successfully wrote block at %llx\n", pos);
printf("mtd: successfully wrote block at %lx\n", pos);
return 0; // Success!
}
// Try to erase it once more as we give up on this block
add_bad_block_offset(ctx, pos);
fprintf(stderr, "mtd: skipping write block at 0x%08lx\n", pos);
printf("mtd: skipping write block at 0x%08lx\n", pos);
#ifdef RK3066
rk30_zero_out(fd, pos, size);
#else
ioctl(fd, MEMERASE, &erase_info);
#endif
pos += partition->erase_size;
@@ -535,7 +536,7 @@ off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks)
while (blocks-- > 0) {
loff_t bpos = pos;
if (ioctl(ctx->fd, MEMGETBADBLOCK, &bpos) > 0) {
fprintf(stderr, "mtd: not erasing bad block at 0x%08lx\n", pos);
printf("mtd: not erasing bad block at 0x%08lx\n", pos);
pos += ctx->partition->erase_size;
continue; // Don't try to erase known factory-bad blocks.
}
@@ -549,7 +550,7 @@ off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks)
}
#else
if (ioctl(ctx->fd, MEMERASE, &erase_info) < 0) {
fprintf(stderr, "mtd: erase failure at 0x%08lx\n", pos);
printf("mtd: erase failure at 0x%08lx\n", pos);
}
#endif
pos += ctx->partition->erase_size;
+101 -26
View File
@@ -77,6 +77,7 @@ static const struct option OPTIONS[] = {
#define LAST_LOG_FILE "/cache/recovery/last_log"
static const char *CACHE_LOG_DIR = "/cache/recovery";
static const char *COMMAND_FILE = "/cache/recovery/command";
static const char *INTENT_FILE = "/cache/recovery/intent";
static const char *LOG_FILE = "/cache/recovery/log";
@@ -90,6 +91,7 @@ static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
RecoveryUI* ui = NULL;
char* locale = NULL;
char recovery_version[PROPERTY_VALUE_MAX+1];
/*
* The recovery tool communicates with the main system through /cache files.
@@ -299,6 +301,19 @@ rotate_last_logs(int max) {
}
}
static void
copy_logs() {
// Copy logs to cache so the system can find out what happened.
copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
chmod(LOG_FILE, 0600);
chown(LOG_FILE, 1000, 1000); // system user
chmod(LAST_LOG_FILE, 0640);
chmod(LAST_INSTALL_FILE, 0644);
sync();
}
// clear the recovery command and prepare to boot a (hopefully working) system,
// copy our log file to cache as well (for the system to read), and
// record any intent we were asked to communicate back to the system.
@@ -328,14 +343,7 @@ finish_recovery(const char *send_intent) {
check_and_fclose(fp, LOCALE_FILE);
}
// Copy logs to cache so the system can find out what happened.
copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
chmod(LOG_FILE, 0600);
chown(LOG_FILE, 1000, 1000); // system user
chmod(LAST_LOG_FILE, 0640);
chmod(LAST_INSTALL_FILE, 0644);
copy_logs();
// Reset to normal system boot so recovery won't cycle indefinitely.
struct bootloader_message boot;
@@ -352,22 +360,95 @@ finish_recovery(const char *send_intent) {
sync(); // For good measure.
}
typedef struct _saved_log_file {
char* name;
struct stat st;
unsigned char* data;
struct _saved_log_file* next;
} saved_log_file;
static int
erase_volume(const char *volume) {
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
ui->SetBackground(RecoveryUI::ERASING);
ui->SetProgressType(RecoveryUI::INDETERMINATE);
saved_log_file* head = NULL;
if (is_cache) {
// If we're reformatting /cache, we load any
// "/cache/recovery/last*" files into memory, so we can restore
// them after the reformat.
ensure_path_mounted(volume);
DIR* d;
struct dirent* de;
d = opendir(CACHE_LOG_DIR);
if (d) {
char path[PATH_MAX];
strcpy(path, CACHE_LOG_DIR);
strcat(path, "/");
int path_len = strlen(path);
while ((de = readdir(d)) != NULL) {
if (strncmp(de->d_name, "last", 4) == 0) {
saved_log_file* p = (saved_log_file*) malloc(sizeof(saved_log_file));
strcpy(path+path_len, de->d_name);
p->name = strdup(path);
if (stat(path, &(p->st)) == 0) {
// truncate files to 512kb
if (p->st.st_size > (1 << 19)) {
p->st.st_size = 1 << 19;
}
p->data = (unsigned char*) malloc(p->st.st_size);
FILE* f = fopen(path, "rb");
fread(p->data, 1, p->st.st_size, f);
fclose(f);
p->next = head;
head = p;
} else {
free(p);
}
}
}
closedir(d);
} else {
if (errno != ENOENT) {
printf("opendir failed: %s\n", strerror(errno));
}
}
}
ui->Print("Formatting %s...\n", volume);
ensure_path_unmounted(volume);
int result = format_volume(volume);
if (is_cache) {
while (head) {
FILE* f = fopen_path(head->name, "wb");
if (f) {
fwrite(head->data, 1, head->st.st_size, f);
fclose(f);
chmod(head->name, head->st.st_mode);
chown(head->name, head->st.st_uid, head->st.st_gid);
}
free(head->name);
free(head->data);
saved_log_file* temp = head->next;
free(head);
head = temp;
}
if (strcmp(volume, "/cache") == 0) {
// Any part of the log we'd copied to cache is now gone.
// Reset the pointer so we copy from the beginning of the temp
// log.
tmplog_offset = 0;
copy_logs();
}
return format_volume(volume);
return result;
}
static char*
@@ -462,21 +543,17 @@ copy_sideloaded_package(const char* original_path) {
static const char**
prepend_title(const char* const* headers) {
const char* title[] = { "Android system recovery <"
EXPAND(RECOVERY_API_VERSION) "e>",
"",
NULL };
// count the number of lines in our title, plus the
// caller-provided headers.
int count = 0;
int count = 3; // our title has 3 lines
const char* const* p;
for (p = title; *p; ++p, ++count);
for (p = headers; *p; ++p, ++count);
const char** new_headers = (const char**)malloc((count+1) * sizeof(char*));
const char** h = new_headers;
for (p = title; *p; ++p, ++h) *h = *p;
*(h++) = "Android system recovery <" EXPAND(RECOVERY_API_VERSION) "e>";
*(h++) = recovery_version;
*(h++) = "";
for (p = headers; *p; ++p, ++h) *h = *p;
*h = NULL;
@@ -750,10 +827,6 @@ prompt_and_wait(Device* device, int status) {
break;
case Device::APPLY_EXT:
// Some packages expect /cache to be mounted (eg,
// standard incremental packages expect to use /cache
// as scratch space).
ensure_path_mounted(CACHE_ROOT);
status = update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache, device);
if (status == INSTALL_SUCCESS && wipe_cache) {
ui->Print("\n-- Wiping cache (at package request)...\n");
@@ -799,12 +872,12 @@ prompt_and_wait(Device* device, int status) {
break;
case Device::APPLY_ADB_SIDELOAD:
ensure_path_mounted(CACHE_ROOT);
status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE);
if (status >= 0) {
if (status != INSTALL_SUCCESS) {
ui->SetBackground(RecoveryUI::ERROR);
ui->Print("Installation aborted.\n");
copy_logs();
} else if (!ui->IsTextVisible()) {
return; // reboot if logs aren't visible
} else {
@@ -910,8 +983,8 @@ main(int argc, char **argv) {
load_volume_table();
ensure_path_mounted(LAST_LOG_FILE);
rotate_last_logs(5);
rotate_last_logs(10);
get_args(&argc, &argv);
int previous_runs = 0;
@@ -959,8 +1032,7 @@ main(int argc, char **argv) {
sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
if (!sehandle) {
fprintf(stderr, "Warning: No file_contexts\n");
ui->Print("Warning: No file_contexts\n");
ui->Print("Warning: No file_contexts\n");
}
//device->StartRecovery();
@@ -988,6 +1060,7 @@ main(int argc, char **argv) {
printf("\n");
property_list(print_property, NULL);
property_get("ro.build.display.id", recovery_version, "");
printf("\n");
// Check for and run startup script if script exists
@@ -1110,6 +1183,7 @@ main(int argc, char **argv) {
}
if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
copy_logs();
ui->SetBackground(RecoveryUI::ERROR);
}
if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
@@ -1138,5 +1212,6 @@ main(int argc, char **argv) {
#else
reboot(RB_AUTOBOOT);
#endif
property_set(ANDROID_RB_PROPERTY, "reboot,");
return EXIT_SUCCESS;
}
+19
View File
@@ -217,3 +217,22 @@ int format_volume(const char* volume) {
LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
return -1;
}
int setup_install_mounts() {
if (fstab == NULL) {
LOGE("can't set up install mounts: no fstab loaded\n");
return -1;
}
for (int i = 0; i < fstab->num_entries; ++i) {
Volume* v = fstab->recs + i;
if (strcmp(v->mount_point, "/tmp") == 0 ||
strcmp(v->mount_point, "/cache") == 0) {
if (ensure_path_mounted(v->mount_point) != 0) return -1;
} else {
if (ensure_path_unmounted(v->mount_point) != 0) return -1;
}
}
return 0;
}
+4
View File
@@ -42,6 +42,10 @@ int ensure_path_unmounted(const char* path);
// it is mounted.
int format_volume(const char* volume);
// Ensure that all and only the volumes that packages expect to find
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
int setup_install_mounts();
#ifdef __cplusplus
}
#endif
+40 -11
View File
@@ -202,9 +202,29 @@ void ScreenRecoveryUI::draw_progress_locked()
}
}
#define C_HEADER 247,0,6
#define C_MENU 0,106,157
#define C_LOG 249,194,0
void ScreenRecoveryUI::SetColor(UIElement e) {
switch (e) {
case HEADER:
gr_color(247, 0, 6, 255);
break;
case MENU:
case MENU_SEL_BG:
gr_color(0, 106, 157, 255);
break;
case MENU_SEL_FG:
gr_color(255, 255, 255, 255);
break;
case LOG:
gr_color(249, 194, 0, 255);
break;
case TEXT_FILL:
gr_color(0, 0, 0, 160);
break;
default:
gr_color(255, 255, 255, 255);
break;
}
}
// Redraw everything on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
@@ -214,37 +234,38 @@ void ScreenRecoveryUI::draw_screen_locked()
draw_progress_locked();
if (show_text) {
gr_color(0, 0, 0, 160);
SetColor(TEXT_FILL);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
int y = 0;
int i = 0;
if (show_menu) {
gr_color(C_HEADER, 255);
SetColor(HEADER);
for (; i < menu_top + menu_items; ++i) {
if (i == menu_top) gr_color(C_MENU, 255);
if (i == menu_top) SetColor(MENU);
if (i == menu_top + menu_sel) {
// draw the highlight bar
SetColor(MENU_SEL_BG);
gr_fill(0, y-2, gr_fb_width(), y+char_height+2);
// white text of selected item
gr_color(255, 255, 255, 255);
SetColor(MENU_SEL_FG);
if (menu[i][0]) gr_text(4, y, menu[i], 1);
gr_color(C_MENU, 255);
SetColor(MENU);
} else {
if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top);
}
y += char_height+4;
}
gr_color(C_MENU, 255);
SetColor(MENU);
y += 4;
gr_fill(0, y, gr_fb_width(), y+2);
y += 4;
++i;
}
gr_color(C_LOG, 255);
SetColor(LOG);
// display from the bottom up, until we hit the top of the
// screen, the bottom of the menu, or we've displayed the
@@ -452,10 +473,11 @@ void ScreenRecoveryUI::SetProgressType(ProgressType type)
pthread_mutex_lock(&updateMutex);
if (progressBarType != type) {
progressBarType = type;
update_progress_locked();
}
progressScopeStart = 0;
progressScopeSize = 0;
progress = 0;
update_progress_locked();
pthread_mutex_unlock(&updateMutex);
}
@@ -599,3 +621,10 @@ void ScreenRecoveryUI::ShowText(bool visible)
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
void ScreenRecoveryUI::Redraw()
{
pthread_mutex_lock(&updateMutex);
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
+8 -1
View File
@@ -53,6 +53,14 @@ class ScreenRecoveryUI : public RecoveryUI {
int SelectMenu(int sel);
void EndMenu();
void Redraw();
enum UIElement { HEADER, MENU, MENU_SEL_BG, MENU_SEL_FG, LOG, TEXT_FILL };
virtual void SetColor(UIElement e);
protected:
int install_overlay_offset_x, install_overlay_offset_y;
private:
Icon currentIcon;
int installingFrame;
@@ -94,7 +102,6 @@ class ScreenRecoveryUI : public RecoveryUI {
int animation_fps;
int indeterminate_frames;
int installing_frames;
int install_overlay_offset_x, install_overlay_offset_y;
int overlay_offset_x, overlay_offset_y;
void draw_install_overlay_locked(int frame);
Binary file not shown.
BIN
View File
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIJAKhkCO1dDYMaMA0GCSqGSIb3DQEBCwUAMG8xCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBW
aWV3MQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMT
B1Rlc3QxMjMwHhcNMTMwNDEwMTcyMzUyWhcNMTMwNTEwMTcyMzUyWjBvMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQD
EwdUZXN0MTIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu8WwMN9x
4Mz7YgkG2qy9g8/kl5ZoYrUM0ApHhaITAcL7RXLZaNipCf0w/YjYTQgj+75MK30x
TsnPeWNOEwA62gkHrZyyWfxBRO6kBYuIuI4roGDBJOmKQ1OEaDeIRKu7q5V8v3Cs
0wQDAQWTbhpxBZr9UYFgJUg8XWBfPrGJLVwsoiy4xrMhoTlNZKHfwOMMqVtSHkZX
qydYrcIzyjh+TO0e/xSNQ8MMRRbtqWgCHN6Rzhog3IHZu0RaPoukariopjXM/s0V
gTm3rHDHCOpna2pNblyiFlvbkoCs769mtNmx/yrDShO30jg/xaG8RypKDvTChzOT
oWW/XQ5VEXjbHwIDAQABo4HUMIHRMB0GA1UdDgQWBBRlT2dEZJY1tmUM8mZ0xnhS
GdD9TTCBoQYDVR0jBIGZMIGWgBRlT2dEZJY1tmUM8mZ0xnhSGdD9TaFzpHEwbzEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50
YWluIFZpZXcxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEQMA4G
A1UEAxMHVGVzdDEyM4IJAKhkCO1dDYMaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
AQELBQADggEBAKWWQ9S0V9wWjrMJe8exj1gklwD1Ysi0vi+h2tfixahelrpsNkWi
EFjoUSHEkW9ThLmtui646uAlwSiWtSn1XkGGmIJ3s+gmAFUcMc0CaK0dgoq/M9zn
fQ0Vkzc1tK4MLsf+CbPDywPycb6+T3dBkerbWn9GUpjGl1ANWlciXZZ3657m61sL
HhwUOBxbZZ6sYP4ed2SVCf45GgMyJ0VoUg5yI2JzPAgOkGfeEIPVXE1M94edJY4G
8eHYvXovJZwXvKFI+ZyS0KBPx8cpfw89RB9qmkxqNBIm8qWb3qBiuBEIPj+NF/7w
sC/Fv8NNXkVquy0xa0qdyJBABzWE18zGcXs=
-----END CERTIFICATE-----
BIN
View File
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEqDCCA5CgAwIBAgIJAJNurL4H8gHfMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
Fw0wODAyMjkwMTMzNDZaFw0zNTA3MTcwMTMzNDZaMIGUMQswCQYDVQQGEwJVUzET
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
hvcNAQEBBQADggENADCCAQgCggEBANaTGQTexgskse3HYuDZ2CU+Ps1s6x3i/waM
qOi8qM1r03hupwqnbOYOuw+ZNVn/2T53qUPn6D1LZLjk/qLT5lbx4meoG7+yMLV4
wgRDvkxyGLhG9SEVhvA4oU6Jwr44f46+z4/Kw9oe4zDJ6pPQp8PcSvNQIg1QCAcy
4ICXF+5qBTNZ5qaU7Cyz8oSgpGbIepTYOzEJOmc3Li9kEsBubULxWBjf/gOBzAzU
RNps3cO4JFgZSAGzJWQTT7/emMkod0jb9WdqVA2BVMi7yge54kdVMxHEa5r3b97s
zI5p58ii0I54JiCUP5lyfTwE/nKZHZnfm644oLIXf6MdW2r+6R8CAQOjgfwwgfkw
HQYDVR0OBBYEFEhZAFY9JyxGrhGGBaR0GawJyowRMIHJBgNVHSMEgcEwgb6AFEhZ
AFY9JyxGrhGGBaR0GawJyowRoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAJNurL4H8gHfMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHqvlozrUMRBBVEY0NqrrwFbinZa
J6cVosK0TyIUFf/azgMJWr+kLfcHCHJsIGnlw27drgQAvilFLAhLwn62oX6snb4Y
LCBOsVMR9FXYJLZW2+TcIkCRLXWG/oiVHQGo/rWuWkJgU134NDEFJCJGjDbiLCpe
+ZTWHdcwauTJ9pUbo8EvHRkU3cYfGmLaLfgn9gP+pWA7LFQNvXwBnDa6sppCccEX
31I828XzgXpJ4O+mDL1/dBd+ek8ZPUP0IgdyZm5MTYPhvVqGCHzzTy3sIeJFymwr
sBbmg2OAUNLEMO6nwmocSdN2ClirfxqCzJOLSDE4QyS9BAH6EhY6UFcOaE0=
-----END CERTIFICATE-----
+27
View File
@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEqDCCA5CgAwIBAgIJAJNurL4H8gHfMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
Fw0xMzA0MTAxODA1MzZaFw0xMzA1MTAxODA1MzZaMIGUMQswCQYDVQQGEwJVUzET
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
hvcNAQEBBQADggENADCCAQgCggEBANaTGQTexgskse3HYuDZ2CU+Ps1s6x3i/waM
qOi8qM1r03hupwqnbOYOuw+ZNVn/2T53qUPn6D1LZLjk/qLT5lbx4meoG7+yMLV4
wgRDvkxyGLhG9SEVhvA4oU6Jwr44f46+z4/Kw9oe4zDJ6pPQp8PcSvNQIg1QCAcy
4ICXF+5qBTNZ5qaU7Cyz8oSgpGbIepTYOzEJOmc3Li9kEsBubULxWBjf/gOBzAzU
RNps3cO4JFgZSAGzJWQTT7/emMkod0jb9WdqVA2BVMi7yge54kdVMxHEa5r3b97s
zI5p58ii0I54JiCUP5lyfTwE/nKZHZnfm644oLIXf6MdW2r+6R8CAQOjgfwwgfkw
HQYDVR0OBBYEFEhZAFY9JyxGrhGGBaR0GawJyowRMIHJBgNVHSMEgcEwgb6AFEhZ
AFY9JyxGrhGGBaR0GawJyowRoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAJNurL4H8gHfMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKRVj9hOaozH1W8Wb4CNj7sCWixh
UMMZJXkxUtvUVHZGefp6MdtYiD/ZM7YRwZphm9aNhkykbHJdZ3lPzeL2csCa+sDQ
8sIzGu0/aD6p4zgIKQZmz0mZHqPGbHoLWOmA9EexRCFZ7vO/kO56ZbyhfFz2DI3S
Yez65CabErOFhNX6WukSPbV3zfsHRDD5JUStb/ko6t99HXsvIO0Ax9poj60PpCC1
SiFzHZUY9mOnUfJFs+3NWCwKtP9nho3mZ3pJ1i+SeF6JiqbE3KHl4CDBeVGcu3CK
fiUZ8e8iXVN471Cgc5GD6Ud1pS7ifNZJsKhbETQ63KmvHCLRPi4NmP67uDE=
-----END CERTIFICATE-----
+11 -7
View File
@@ -21,18 +21,22 @@ ifeq ($(TWHAVE_SELINUX), true)
endif
LOCAL_SRC_FILES := \
dynarray.c \
toolbox.c \
$(patsubst %,%.c,$(TOOLS))
TOOLS += reboot
ifeq ($(BOARD_USES_BOOTMENU),true)
LOCAL_SRC_FILES += ../../../external/bootmenu/libreboot/reboot.c
else
LOCAL_SRC_FILES += reboot.c
ifneq ($(wildcard system/core/toolbox/dynarray.c),)
LOCAL_SRC_FILES += dynarray.c
endif
# reboot.c was removed in 4.4 kitkat
#TOOLS += reboot
#ifeq ($(BOARD_USES_BOOTMENU),true)
# LOCAL_SRC_FILES += ../../../external/bootmenu/libreboot/reboot.c
#else
# LOCAL_SRC_FILES += reboot.c
#endif
LOCAL_C_INCLUDES := bionic/libc/bionic
LOCAL_SHARED_LIBRARIES := \
+33 -8
View File
@@ -48,7 +48,8 @@ static RecoveryUI* self = NULL;
RecoveryUI::RecoveryUI() :
key_queue_len(0),
key_last_down(-1),
key_down_time(0) {
key_long_press(false),
key_down_count(0) {
pthread_mutex_init(&key_queue_mutex, NULL);
pthread_cond_init(&key_queue_cond, NULL);
self = this;
@@ -114,19 +115,22 @@ void RecoveryUI::process_key(int key_code, int updown) {
bool register_key = false;
bool long_press = false;
const long long_threshold = CLOCKS_PER_SEC * 750 / 1000;
pthread_mutex_lock(&key_queue_mutex);
key_pressed[key_code] = updown;
if (updown) {
++key_down_count;
key_last_down = key_code;
key_down_time = clock();
key_long_press = false;
pthread_t th;
key_timer_t* info = new key_timer_t;
info->ui = this;
info->key_code = key_code;
info->count = key_down_count;
pthread_create(&th, NULL, &RecoveryUI::time_key_helper, info);
pthread_detach(th);
} else {
if (key_last_down == key_code) {
long duration = clock() - key_down_time;
if (duration > long_threshold) {
long_press = true;
}
long_press = key_long_press;
register_key = true;
}
key_last_down = -1;
@@ -156,6 +160,24 @@ void RecoveryUI::process_key(int key_code, int updown) {
}
}
void* RecoveryUI::time_key_helper(void* cookie) {
key_timer_t* info = (key_timer_t*) cookie;
info->ui->time_key(info->key_code, info->count);
delete info;
return NULL;
}
void RecoveryUI::time_key(int key_code, int count) {
usleep(750000); // 750 ms == "long"
bool long_press = false;
pthread_mutex_lock(&key_queue_mutex);
if (key_last_down == key_code && key_down_count == count) {
long_press = key_long_press = true;
}
pthread_mutex_unlock(&key_queue_mutex);
if (long_press) KeyLongPress(key_code);
}
void RecoveryUI::EnqueueKey(int key_code) {
pthread_mutex_lock(&key_queue_mutex);
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
@@ -246,3 +268,6 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) {
void RecoveryUI::NextCheckKeyIsLong(bool is_long_press) {
}
void RecoveryUI::KeyLongPress(int key) {
}
+20 -1
View File
@@ -80,8 +80,17 @@ class RecoveryUI {
enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE };
virtual KeyAction CheckKey(int key);
// Called immediately before each call to CheckKey(), tell you if
// the key was long-pressed.
virtual void NextCheckKeyIsLong(bool is_long_press);
// Called when a key is held down long enough to have been a
// long-press (but before the key is released). This means that
// if the key is eventually registered (released without any other
// keys being pressed in the meantime), NextCheckKeyIsLong() will
// be called with "true".
virtual void KeyLongPress(int key);
// --- menu display ---
// Display some header text followed by a menu of items, which appears
@@ -108,15 +117,25 @@ private:
int key_queue[256], key_queue_len;
char key_pressed[KEY_MAX + 1]; // under key_queue_mutex
int key_last_down; // under key_queue_mutex
clock_t key_down_time; // under key_queue_mutex
bool key_long_press; // under key_queue_mutex
int key_down_count; // under key_queue_mutex
int rel_sum;
typedef struct {
RecoveryUI* ui;
int key_code;
int count;
} key_timer_t;
pthread_t input_t;
static void* input_thread(void* cookie);
static int input_callback(int fd, short revents, void* data);
void process_key(int key_code, int updown);
bool usb_connected();
static void* time_key_helper(void* cookie);
void time_key(int key_code, int count);
};
#endif // RECOVERY_UI_H
+310 -31
View File
@@ -27,6 +27,12 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <selinux/selinux.h>
#include <ftw.h>
#include <sys/capability.h>
#include <sys/xattr.h>
#include <linux/xattr.h>
#include <inttypes.h>
#include "cutils/misc.h"
#include "cutils/properties.h"
@@ -98,13 +104,13 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
const MtdPartition* mtd;
mtd = mtd_find_partition_by_name(location);
if (mtd == NULL) {
fprintf(stderr, "%s: no mtd partition named \"%s\"",
printf("%s: no mtd partition named \"%s\"",
name, location);
result = strdup("");
goto done;
}
if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) {
fprintf(stderr, "mtd mount of %s failed: %s\n",
printf("mtd mount of %s failed: %s\n",
location, strerror(errno));
result = strdup("");
goto done;
@@ -113,7 +119,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
} else {
if (mount(location, mount_point, fs_type,
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) {
fprintf(stderr, "%s: failed to mount %s at %s: %s\n",
printf("%s: failed to mount %s at %s: %s\n",
name, location, mount_point, strerror(errno));
result = strdup("");
} else {
@@ -176,7 +182,7 @@ Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
scan_mounted_volumes();
const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point);
if (vol == NULL) {
fprintf(stderr, "unmount of %s failed; no such volume\n", mount_point);
printf("unmount of %s failed; no such volume\n", mount_point);
result = strdup("");
} else {
unmount_mounted_volume(vol);
@@ -234,25 +240,25 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
mtd_scan_partitions();
const MtdPartition* mtd = mtd_find_partition_by_name(location);
if (mtd == NULL) {
fprintf(stderr, "%s: no mtd partition named \"%s\"",
printf("%s: no mtd partition named \"%s\"",
name, location);
result = strdup("");
goto done;
}
MtdWriteContext* ctx = mtd_write_partition(mtd);
if (ctx == NULL) {
fprintf(stderr, "%s: can't write \"%s\"", name, location);
printf("%s: can't write \"%s\"", name, location);
result = strdup("");
goto done;
}
if (mtd_erase_blocks(ctx, -1) == -1) {
mtd_write_close(ctx);
fprintf(stderr, "%s: failed to erase \"%s\"", name, location);
printf("%s: failed to erase \"%s\"", name, location);
result = strdup("");
goto done;
}
if (mtd_write_close(ctx) != 0) {
fprintf(stderr, "%s: failed to close \"%s\"", name, location);
printf("%s: failed to close \"%s\"", name, location);
result = strdup("");
goto done;
}
@@ -261,7 +267,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
} else if (strcmp(fs_type, "ext4") == 0) {
int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle);
if (status != 0) {
fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
printf("%s: make_ext4fs failed (%d) on %s",
name, status, location);
result = strdup("");
goto done;
@@ -269,7 +275,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
result = location;
#endif
} else {
fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"",
printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"",
name, fs_type, partition_type);
}
@@ -395,13 +401,13 @@ Value* PackageExtractFileFn(const char* name, State* state,
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path);
if (entry == NULL) {
fprintf(stderr, "%s: no %s in package\n", name, zip_path);
printf("%s: no %s in package\n", name, zip_path);
goto done2;
}
FILE* f = fopen(dest_path, "wb");
if (f == NULL) {
fprintf(stderr, "%s: can't open %s for write: %s\n",
printf("%s: can't open %s for write: %s\n",
name, dest_path, strerror(errno));
goto done2;
}
@@ -427,14 +433,14 @@ Value* PackageExtractFileFn(const char* name, State* state,
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path);
if (entry == NULL) {
fprintf(stderr, "%s: no %s in package\n", name, zip_path);
printf("%s: no %s in package\n", name, zip_path);
goto done1;
}
v->size = mzGetZipEntryUncompLen(entry);
v->data = malloc(v->size);
if (v->data == NULL) {
fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n",
printf("%s: failed to allocate %ld bytes for %s\n",
name, (long)v->size, zip_path);
goto done1;
}
@@ -461,13 +467,13 @@ static int make_parents(char* name) {
*p = '\0';
if (make_parents(name) < 0) return -1;
int result = mkdir(name, 0700);
if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name);
if (result == 0) printf("symlink(): created [%s]\n", name);
*p = '/';
if (result == 0 || errno == EEXIST) {
// successfully created or already existed; we're done
return 0;
} else {
fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno));
printf("failed to mkdir %s: %s\n", name, strerror(errno));
return -1;
}
}
@@ -495,18 +501,18 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
for (i = 0; i < argc-1; ++i) {
if (unlink(srcs[i]) < 0) {
if (errno != ENOENT) {
fprintf(stderr, "%s: failed to remove %s: %s\n",
printf("%s: failed to remove %s: %s\n",
name, srcs[i], strerror(errno));
++bad;
}
}
if (make_parents(srcs[i])) {
fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n",
printf("%s: failed to symlink %s to %s: making parents failed\n",
name, srcs[i], target);
++bad;
}
if (symlink(target, srcs[i]) < 0) {
fprintf(stderr, "%s: failed to symlink %s to %s: %s\n",
printf("%s: failed to symlink %s to %s: %s\n",
name, srcs[i], target, strerror(errno));
++bad;
}
@@ -575,12 +581,12 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) {
for (i = 3; i < argc; ++i) {
if (chown(args[i], uid, gid) < 0) {
fprintf(stderr, "%s: chown of %s to %d %d failed: %s\n",
printf("%s: chown of %s to %d %d failed: %s\n",
name, args[i], uid, gid, strerror(errno));
++bad;
}
if (chmod(args[i], mode) < 0) {
fprintf(stderr, "%s: chmod of %s to %o failed: %s\n",
printf("%s: chmod of %s to %o failed: %s\n",
name, args[i], mode, strerror(errno));
++bad;
}
@@ -601,6 +607,264 @@ done:
return StringValue(result);
}
struct perm_parsed_args {
bool has_uid;
uid_t uid;
bool has_gid;
gid_t gid;
bool has_mode;
mode_t mode;
bool has_fmode;
mode_t fmode;
bool has_dmode;
mode_t dmode;
bool has_selabel;
char* selabel;
bool has_capabilities;
uint64_t capabilities;
};
static struct perm_parsed_args ParsePermArgs(int argc, char** args) {
int i;
struct perm_parsed_args parsed;
int bad = 0;
static int max_warnings = 20;
memset(&parsed, 0, sizeof(parsed));
for (i = 1; i < argc; i += 2) {
if (strcmp("uid", args[i]) == 0) {
int64_t uid;
if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) {
parsed.uid = uid;
parsed.has_uid = true;
} else {
printf("ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("gid", args[i]) == 0) {
int64_t gid;
if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) {
parsed.gid = gid;
parsed.has_gid = true;
} else {
printf("ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("mode", args[i]) == 0) {
int32_t mode;
if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
parsed.mode = mode;
parsed.has_mode = true;
} else {
printf("ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("dmode", args[i]) == 0) {
int32_t mode;
if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
parsed.dmode = mode;
parsed.has_dmode = true;
} else {
printf("ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("fmode", args[i]) == 0) {
int32_t mode;
if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
parsed.fmode = mode;
parsed.has_fmode = true;
} else {
printf("ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("capabilities", args[i]) == 0) {
int64_t capabilities;
if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) {
parsed.capabilities = capabilities;
parsed.has_capabilities = true;
} else {
printf("ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (strcmp("selabel", args[i]) == 0) {
if (args[i+1][0] != '\0') {
parsed.selabel = args[i+1];
parsed.has_selabel = true;
} else {
printf("ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]);
bad++;
}
continue;
}
if (max_warnings != 0) {
printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]);
max_warnings--;
if (max_warnings == 0) {
printf("ParsedPermArgs: suppressing further warnings\n");
}
}
}
return parsed;
}
static int ApplyParsedPerms(
const char* filename,
const struct stat *statptr,
struct perm_parsed_args parsed)
{
int bad = 0;
/* ignore symlinks */
if (S_ISLNK(statptr->st_mode)) {
return 0;
}
if (parsed.has_uid) {
if (chown(filename, parsed.uid, -1) < 0) {
printf("ApplyParsedPerms: chown of %s to %d failed: %s\n",
filename, parsed.uid, strerror(errno));
bad++;
}
}
if (parsed.has_gid) {
if (chown(filename, -1, parsed.gid) < 0) {
printf("ApplyParsedPerms: chgrp of %s to %d failed: %s\n",
filename, parsed.gid, strerror(errno));
bad++;
}
}
if (parsed.has_mode) {
if (chmod(filename, parsed.mode) < 0) {
printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
filename, parsed.mode, strerror(errno));
bad++;
}
}
if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) {
if (chmod(filename, parsed.dmode) < 0) {
printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
filename, parsed.dmode, strerror(errno));
bad++;
}
}
if (parsed.has_fmode && S_ISREG(statptr->st_mode)) {
if (chmod(filename, parsed.fmode) < 0) {
printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
filename, parsed.fmode, strerror(errno));
bad++;
}
}
if (parsed.has_selabel) {
// TODO: Don't silently ignore ENOTSUP
if (lsetfilecon(filename, parsed.selabel) && (errno != ENOTSUP)) {
printf("ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n",
filename, parsed.selabel, strerror(errno));
bad++;
}
}
if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) {
if (parsed.capabilities == 0) {
if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) {
// Report failure unless it's ENODATA (attribute not set)
printf("ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n",
filename, parsed.capabilities, strerror(errno));
bad++;
}
} else {
struct vfs_cap_data cap_data;
memset(&cap_data, 0, sizeof(cap_data));
cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff);
cap_data.data[0].inheritable = 0;
cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32);
cap_data.data[1].inheritable = 0;
if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
printf("ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n",
filename, parsed.capabilities, strerror(errno));
bad++;
}
}
}
return bad;
}
// nftw doesn't allow us to pass along context, so we need to use
// global variables. *sigh*
static struct perm_parsed_args recursive_parsed_args;
static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr,
int fileflags, struct FTW *pfwt) {
return ApplyParsedPerms(filename, statptr, recursive_parsed_args);
}
static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) {
int i;
int bad = 0;
static int nwarnings = 0;
struct stat sb;
Value* result = NULL;
bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
if ((argc % 2) != 1) {
return ErrorAbort(state, "%s() expects an odd number of arguments, got %d",
name, argc);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) return NULL;
if (lstat(args[0], &sb) == -1) {
result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno));
goto done;
}
struct perm_parsed_args parsed = ParsePermArgs(argc, args);
if (recursive) {
recursive_parsed_args = parsed;
bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS);
memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args));
} else {
bad += ApplyParsedPerms(args[0], &sb, parsed);
}
done:
for (i = 0; i < argc; ++i) {
free(args[i]);
}
free(args);
if (result != NULL) {
return result;
}
if (bad > 0) {
return ErrorAbort(state, "%s: some changes failed", name);
}
return StringValue(strdup(""));
}
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
@@ -721,7 +985,7 @@ static bool write_raw_image_cb(const unsigned char* data,
int data_len, void* ctx) {
int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len);
if (r == data_len) return true;
fprintf(stderr, "%s\n", strerror(errno));
printf("%s\n", strerror(errno));
return false;
}
@@ -937,23 +1201,23 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
memcpy(args2, args, sizeof(char*) * argc);
args2[argc] = NULL;
fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc);
printf("about to run program [%s] with %d args\n", args2[0], argc);
pid_t child = fork();
if (child == 0) {
execv(args2[0], args2);
fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno));
printf("run_program: execv failed: %s\n", strerror(errno));
_exit(1);
}
int status;
waitpid(child, &status, 0);
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
fprintf(stderr, "run_program: child exited with status %d\n",
printf("run_program: child exited with status %d\n",
WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "run_program: child terminated by signal %d\n",
printf("run_program: child terminated by signal %d\n",
WTERMSIG(status));
}
@@ -1002,11 +1266,11 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (args[0]->size < 0) {
fprintf(stderr, "%s(): no file contents received", name);
printf("%s(): no file contents received", name);
return StringValue(strdup(""));
}
uint8_t digest[SHA_DIGEST_SIZE];
SHA(args[0]->data, args[0]->size, digest);
SHA_hash(args[0]->data, args[0]->size, digest);
FreeValue(args[0]);
if (argc == 1) {
@@ -1017,12 +1281,12 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE);
for (i = 1; i < argc; ++i) {
if (args[i]->type != VAL_STRING) {
fprintf(stderr, "%s(): arg %d is not a string; skipping",
printf("%s(): arg %d is not a string; skipping",
name, i);
} else if (ParseSha1(args[i]->data, arg_digest) != 0) {
// Warn about bad args and skip them.
fprintf(stderr, "%s(): error parsing \"%s\" as sha-1; skipping",
name, args[i]->data);
printf("%s(): error parsing \"%s\" as sha-1; skipping",
name, args[i]->data);
} else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) {
break;
}
@@ -1082,9 +1346,24 @@ void RegisterInstallFunctions() {
RegisterFunction("package_extract_dir", PackageExtractDirFn);
RegisterFunction("package_extract_file", PackageExtractFileFn);
RegisterFunction("symlink", SymlinkFn);
// Maybe, at some future point, we can delete these functions? They have been
// replaced by perm_set and perm_set_recursive.
RegisterFunction("set_perm", SetPermFn);
RegisterFunction("set_perm_recursive", SetPermFn);
// Usage:
// set_metadata("filename", "key1", "value1", "key2", "value2", ...)
// Example:
// set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
RegisterFunction("set_metadata", SetMetadataFn);
// Usage:
// set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
// Example:
// set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
RegisterFunction("set_metadata_recursive", SetMetadataFn);
RegisterFunction("getprop", GetPropFn);
RegisterFunction("file_getprop", FileGetPropFn);
RegisterFunction("write_raw_image", WriteRawImageFn);
+12 -12
View File
@@ -39,13 +39,14 @@ struct selabel_handle *sehandle;
int main(int argc, char** argv) {
// Various things log information to stdout or stderr more or less
// at random. The log file makes more sense if buffering is
// turned off so things appear in the right order.
// at random (though we've tried to standardize on stdout). The
// log file makes more sense if buffering is turned off so things
// appear in the right order.
setbuf(stdout, NULL);
setbuf(stderr, NULL);
if (argc != 4) {
fprintf(stderr, "unexpected number of arguments (%d)\n", argc);
printf("unexpected number of arguments (%d)\n", argc);
return 1;
}
@@ -53,7 +54,7 @@ int main(int argc, char** argv) {
if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||
version[1] != '\0') {
// We support version 1, 2, or 3.
fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "
printf("wrong updater binary API; expected 1, 2, or 3; "
"got %s\n",
argv[1]);
return 2;
@@ -72,20 +73,20 @@ int main(int argc, char** argv) {
int err;
err = mzOpenZipArchive(package_data, &za);
if (err != 0) {
fprintf(stderr, "failed to open package %s: %s\n",
printf("failed to open package %s: %s\n",
package_data, strerror(err));
return 3;
}
const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);
if (script_entry == NULL) {
fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data);
printf("failed to find %s in %s\n", SCRIPT_NAME, package_data);
return 4;
}
char* script = malloc(script_entry->uncompLen+1);
if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {
fprintf(stderr, "failed to read script from package\n");
printf("failed to read script from package\n");
return 5;
}
script[script_entry->uncompLen] = '\0';
@@ -121,7 +122,7 @@ int main(int argc, char** argv) {
yy_scan_string(script);
int error = yyparse(&root, &error_count);
if (error != 0 || error_count > 0) {
fprintf(stderr, "%d parse errors\n", error_count);
printf("%d parse errors\n", error_count);
return 6;
}
@@ -140,7 +141,6 @@ int main(int argc, char** argv) {
}
if (!sehandle) {
fprintf(stderr, "Warning: No file_contexts\n");
fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
}
@@ -159,10 +159,10 @@ int main(int argc, char** argv) {
char* result = Evaluate(&state, root);
if (result == NULL) {
if (state.errmsg == NULL) {
fprintf(stderr, "script aborted (no error message)\n");
printf("script aborted (no error message)\n");
fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
} else {
fprintf(stderr, "script aborted: %s\n", state.errmsg);
printf("script aborted: %s\n", state.errmsg);
char* line = strtok(state.errmsg, "\n");
while (line) {
fprintf(cmd_pipe, "ui_print %s\n", line);
@@ -173,7 +173,7 @@ int main(int argc, char** argv) {
free(state.errmsg);
return 7;
} else {
fprintf(stderr, "script result was [%s]\n", result);
fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result);
free(result);
}
+68 -39
View File
@@ -20,6 +20,7 @@
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
#include <string.h>
#include <stdio.h>
@@ -38,23 +39,13 @@
int verify_file(const char* path) {
//ui->SetProgress(0.0);
int numKeys;
RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
if (loadedKeys == NULL) {
int numKeys;
Certificate* pKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
if (pKeys == NULL) {
LOGE("Failed to load keys\n");
return VERIFY_FAILURE;
return INSTALL_CORRUPT;
}
/*
LOGI("%d key(s) loaded from %s\n\n RSA Key:\n\n", numKeys, PUBLIC_KEYS_FILE);
int rsa_size = sizeof(RSAPublicKey);
unsigned char* ptr = (unsigned char*) loadedKeys;
unsigned int valuedees;
for (int dees2 = 0; dees2 < rsa_size; dees2++) {
valuedees = *ptr;
printf("%02x ", valuedees);
ptr++;
}
printf("\n\n");*/
LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
FILE* f = fopen(path, "rb");
if (f == NULL) {
@@ -87,6 +78,7 @@ int verify_file(const char* path) {
}
if (footer[2] != 0xff || footer[3] != 0xff) {
LOGE("footer is wrong\n");
fclose(f);
return VERIFY_FAILURE;
}
@@ -158,8 +150,19 @@ int verify_file(const char* path) {
#define BUFFER_SIZE 4096
SHA_CTX ctx;
SHA_init(&ctx);
bool need_sha1 = false;
bool need_sha256 = false;
for (i = 0; i < numKeys; ++i) {
switch (pKeys[i].hash_len) {
case SHA_DIGEST_SIZE: need_sha1 = true; break;
case SHA256_DIGEST_SIZE: need_sha256 = true; break;
}
}
SHA_CTX sha1_ctx;
SHA256_CTX sha256_ctx;
SHA_init(&sha1_ctx);
SHA256_init(&sha256_ctx);
unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE);
if (buffer == NULL) {
LOGE("failed to alloc memory for sha1 buffer\n");
@@ -178,7 +181,8 @@ int verify_file(const char* path) {
fclose(f);
return VERIFY_FAILURE;
}
SHA_update(&ctx, buffer, size);
if (need_sha1) SHA_update(&sha1_ctx, buffer, size);
if (need_sha256) SHA256_update(&sha256_ctx, buffer, size);
so_far += size;
double f = so_far / (double)signed_len;
if (f > frac + 0.02 || size == so_far) {
@@ -189,20 +193,28 @@ int verify_file(const char* path) {
fclose(f);
free(buffer);
const uint8_t* sha1 = SHA_final(&ctx);
const uint8_t* sha1 = SHA_final(&sha1_ctx);
const uint8_t* sha256 = SHA256_final(&sha256_ctx);
for (i = 0; i < numKeys; ++i) {
const uint8_t* hash;
switch (pKeys[i].hash_len) {
case SHA_DIGEST_SIZE: hash = sha1; break;
case SHA256_DIGEST_SIZE: hash = sha256; break;
default: continue;
}
// The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that
// the signing tool appends after the signature itself.
int dees = RSA_verify(loadedKeys+i, eocd + eocd_size - 6 - RSANUMBYTES,
RSANUMBYTES, sha1);
if (dees) {
if (RSA_verify(pKeys[i].public_key, eocd + eocd_size - 6 - RSANUMBYTES,
RSANUMBYTES, hash, pKeys[i].hash_len)) {
LOGI("whole-file signature verified against key %d\n", i);
free(eocd);
return VERIFY_SUCCESS;
} else {
LOGI("failed to verify against key %d\n", i);
}
LOGI("i: %i, eocd_size: %i, RSANUMBYTES: %i, returned %i\n", i, eocd_size, RSANUMBYTES, dees);
LOGI("i: %i, eocd_size: %i, RSANUMBYTES: %i\n", i, eocd_size, RSANUMBYTES);
}
free(eocd);
LOGE("failed to verify whole-file signature\n");
@@ -228,10 +240,19 @@ int verify_file(const char* path) {
// The file may contain multiple keys in this format, separated by
// commas. The last key must not be followed by a comma.
//
// A Certificate is a pair of an RSAPublicKey and a particular hash
// (we support SHA-1 and SHA-256; we store the hash length to signify
// which is being used). The hash used is implied by the version number.
//
// 1: 2048-bit RSA key with e=3 and SHA-1 hash
// 2: 2048-bit RSA key with e=65537 and SHA-1 hash
// 3: 2048-bit RSA key with e=3 and SHA-256 hash
// 4: 2048-bit RSA key with e=65537 and SHA-256 hash
//
// Returns NULL if the file failed to parse, or if it contain zero keys.
RSAPublicKey*
Certificate*
load_keys(const char* filename, int* numKeys) {
RSAPublicKey* out = NULL;
Certificate* out = NULL;
*numKeys = 0;
FILE* f = fopen(filename, "r");
@@ -245,29 +266,39 @@ load_keys(const char* filename, int* numKeys) {
bool done = false;
while (!done) {
++*numKeys;
out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
RSAPublicKey* key = out + (*numKeys - 1);
out = (Certificate*)realloc(out, *numKeys * sizeof(Certificate));
Certificate* cert = out + (*numKeys - 1);
cert->public_key = (RSAPublicKey*)malloc(sizeof(RSAPublicKey));
#ifdef HAS_EXPONENT
char start_char;
if (fscanf(f, " %c", &start_char) != 1) goto exit;
if (start_char == '{') {
// a version 1 key has no version specifier.
key->exponent = 3;
cert->public_key->exponent = 3;
cert->hash_len = SHA_DIGEST_SIZE;
} else if (start_char == 'v') {
int version;
if (fscanf(f, "%d {", &version) != 1) goto exit;
if (version == 2) {
key->exponent = 65537;
} else {
goto exit;
switch (version) {
case 2:
cert->public_key->exponent = 65537;
cert->hash_len = SHA_DIGEST_SIZE;
break;
case 3:
cert->public_key->exponent = 3;
cert->hash_len = SHA256_DIGEST_SIZE;
break;
case 4:
cert->public_key->exponent = 65537;
cert->hash_len = SHA256_DIGEST_SIZE;
break;
default:
goto exit;
}
}
RSAPublicKey* key = cert->public_key;
if (fscanf(f, " %i , 0x%x , { %u",
#else
if (fscanf(f, " { %i , 0x%x , { %u",
#endif
&(key->len), &(key->n0inv), &(key->n[0])) != 3) {
goto exit;
}
@@ -298,9 +329,7 @@ load_keys(const char* filename, int* numKeys) {
LOGE("unexpected character between keys\n");
goto exit;
}
#ifdef HAS_EXPONENT
LOGI("read key e=%d\n", key->exponent);
#endif
LOGI("read key e=%d hash=%d\n", key->exponent, cert->hash_len);
}
}
+6 -1
View File
@@ -25,12 +25,17 @@ enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
typedef struct Certificate {
int hash_len; // SHA_DIGEST_SIZE (SHA-1) or SHA256_DIGEST_SIZE (SHA-256)
RSAPublicKey* public_key;
} Certificate;
/* Look in the file for a signature footer, and verify that it
* matches one of the given keys. Return one of the constants below.
*/
int verify_file(const char* path);
RSAPublicKey* load_keys(const char* filename, int* numKeys);
Certificate* load_keys(const char* filename, int* numKeys);
#define VERIFY_SUCCESS 0
#define VERIFY_FAILURE 1
+80 -71
View File
@@ -21,80 +21,82 @@
#include "common.h"
#include "verifier.h"
#include "ui.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
// This is build/target/product/security/testkey.x509.pem after being
// dumped out by dumpkey.jar.
RSAPublicKey test_key =
{ 64, 0xc926ad21,
{ 1795090719, 2141396315, 950055447, -1713398866,
-26044131, 1920809988, 546586521, -795969498,
1776797858, -554906482, 1805317999, 1429410244,
129622599, 1422441418, 1783893377, 1222374759,
-1731647369, 323993566, 28517732, 609753416,
1826472888, 215237850, -33324596, -245884705,
-1066504894, 774857746, 154822455, -1797768399,
-1536767878, -1275951968, -1500189652, 87251430,
-1760039318, 120774784, 571297800, -599067824,
-1815042109, -483341846, -893134306, -1900097649,
-1027721089, 950095497, 555058928, 414729973,
1136544882, -1250377212, 465547824, -236820568,
-1563171242, 1689838846, -404210357, 1048029507,
895090649, 247140249, 178744550, -747082073,
-1129788053, 109881576, -350362881, 1044303212,
-522594267, -1309816990, -557446364, -695002876},
{ -857949815, -510492167, -1494742324, -1208744608,
251333580, 2131931323, 512774938, 325948880,
-1637480859, 2102694287, -474399070, 792812816,
1026422502, 2053275343, -1494078096, -1181380486,
165549746, -21447327, -229719404, 1902789247,
772932719, -353118870, -642223187, 216871947,
-1130566647, 1942378755, -298201445, 1055777370,
964047799, 629391717, -2062222979, -384408304,
191868569, -1536083459, -612150544, -1297252564,
-1592438046, -724266841, -518093464, -370899750,
-739277751, -1536141862, 1323144535, 61311905,
1997411085, 376844204, 213777604, -217643712,
9135381, 1625809335, -1490225159, -1342673351,
1117190829, -57654514, 1825108855, -1281819325,
1111251351, -1726129724, 1684324211, -1773988491,
367251975, 810756730, -1941182952, 1175080310 },
{ 0x6afee91fu, 0x7fa31d5bu, 0x38a0b217u, 0x99df9baeu,
0xfe72991du, 0x727d3c04u, 0x20943f99u, 0xd08e7826u,
0x69e7c8a2u, 0xdeeccc8eu, 0x6b9af76fu, 0x553311c4u,
0x07b9e247u, 0x54c8bbcau, 0x6a540d81u, 0x48dbf567u,
0x98c92877u, 0x134fbfdeu, 0x01b32564u, 0x24581948u,
0x6cddc3b8u, 0x0cd444dau, 0xfe0381ccu, 0xf15818dfu,
0xc06e6d42u, 0x2e2f6412u, 0x093a6737u, 0x94d83b31u,
0xa466c87au, 0xb3f284a0u, 0xa694ec2cu, 0x053359e6u,
0x9717ee6au, 0x0732e080u, 0x220d5008u, 0xdc4af350u,
0x93d0a7c3u, 0xe330c9eau, 0xcac3da1eu, 0x8ebecf8fu,
0xc2be387fu, 0x38a14e89u, 0x211586f0u, 0x18b846f5u,
0x43be4c72u, 0xb578c204u, 0x1bbfb230u, 0xf1e267a8u,
0xa2d3e656u, 0x64b8e4feu, 0xe7e83d4bu, 0x3e77a943u,
0x3559ffd9u, 0x0ebb0f99u, 0x0aa76ce6u, 0xd3786ea7u,
0xbca8cd6bu, 0x068ca8e8u, 0xeb1de2ffu, 0x3e3ecd6cu,
0xe0d9d825u, 0xb1edc762u, 0xdec60b24u, 0xd6931904u},
{ 0xccdcb989u, 0xe19281f9u, 0xa6e80accu, 0xb7f40560u,
0x0efb0bccu, 0x7f12b0bbu, 0x1e90531au, 0x136d95d0u,
0x9e660665u, 0x7d54918fu, 0xe3b93ea2u, 0x2f415d10u,
0x3d2df6e6u, 0x7a627ecfu, 0xa6f22d70u, 0xb995907au,
0x09de16b2u, 0xfeb8bd61u, 0xf24ec294u, 0x716a427fu,
0x2e12046fu, 0xeaf3d56au, 0xd9b873adu, 0x0ced340bu,
0xbc9cec09u, 0x73c65903u, 0xee39ce9bu, 0x3eede25au,
0x397633b7u, 0x2583c165u, 0x8514f97du, 0xe9166510u,
0x0b6fae99u, 0xa47139fdu, 0xdb8352f0u, 0xb2ad7f2cu,
0xa11552e2u, 0xd4d490a7u, 0xe11e8568u, 0xe9e484dau,
0xd3ef8449u, 0xa47055dau, 0x4edd9557u, 0x03a78ba1u,
0x770e130du, 0x16762facu, 0x0cbdfcc4u, 0xf3070540u,
0x008b6515u, 0x60e7e1b7u, 0xa72cf7f9u, 0xaff86e39u,
0x4296faadu, 0xfc90430eu, 0x6cc8f377u, 0xb398fd43u,
0x423c5997u, 0x991d59c4u, 0x6464bf73u, 0x96431575u,
0x15e3d207u, 0x30532a7au, 0x8c4be618u, 0x460a4d76u },
3
};
RSAPublicKey test_f4_key =
{ 64, 0xc9bd1f21,
{ 293133087u, 3210546773u, 865313125u, 250921607u,
3158780490u, 943703457u, 1242806226u, 2986289859u,
2942743769u, 2457906415u, 2719374299u, 1783459420u,
149579627u, 3081531591u, 3440738617u, 2788543742u,
2758457512u, 1146764939u, 3699497403u, 2446203424u,
1744968926u, 1159130537u, 2370028300u, 3978231572u,
3392699980u, 1487782451u, 1180150567u, 2841334302u,
3753960204u, 961373345u, 3333628321u, 748825784u,
2978557276u, 1566596926u, 1613056060u, 2600292737u,
1847226629u, 50398611u, 1890374404u, 2878700735u,
2286201787u, 1401186359u, 619285059u, 731930817u,
2340993166u, 1156490245u, 2992241729u, 151498140u,
318782170u, 3480838990u, 2100383433u, 4223552555u,
3628927011u, 4247846280u, 1759029513u, 4215632601u,
2719154626u, 3490334597u, 1751299340u, 3487864726u,
3668753795u, 4217506054u, 3748782284u, 3150295088u },
{ 1772626313u, 445326068u, 3477676155u, 1758201194u,
2986784722u, 491035581u, 3922936562u, 702212696u,
2979856666u, 3324974564u, 2488428922u, 3056318590u,
1626954946u, 664714029u, 398585816u, 3964097931u,
3356701905u, 2298377729u, 2040082097u, 3025491477u,
539143308u, 3348777868u, 2995302452u, 3602465520u,
212480763u, 2691021393u, 1307177300u, 704008044u,
2031136606u, 1054106474u, 3838318865u, 2441343869u,
1477566916u, 700949900u, 2534790355u, 3353533667u,
336163563u, 4106790558u, 2701448228u, 1571536379u,
1103842411u, 3623110423u, 1635278839u, 1577828979u,
910322800u, 715583630u, 138128831u, 1017877531u,
2289162787u, 447994798u, 1897243165u, 4121561445u,
4150719842u, 2131821093u, 2262395396u, 3305771534u,
980753571u, 3256525190u, 3128121808u, 1072869975u,
3507939515u, 4229109952u, 118381341u, 2209831334u },
{ 0x1178db1fu, 0xbf5d0e55u, 0x3393a165u, 0x0ef4c287u,
0xbc472a4au, 0x383fc5a1u, 0x4a13b7d2u, 0xb1ff2ac3u,
0xaf66b4d9u, 0x9280acefu, 0xa2165bdbu, 0x6a4d6e5cu,
0x08ea676bu, 0xb7ac70c7u, 0xcd158139u, 0xa635ccfeu,
0xa46ab8a8u, 0x445a3e8bu, 0xdc81d9bbu, 0x91ce1a20u,
0x68021cdeu, 0x4516eda9u, 0x8d43c30cu, 0xed1eff14u,
0xca387e4cu, 0x58adc233u, 0x4657ab27u, 0xa95b521eu,
0xdfc0e30cu, 0x394d64a1u, 0xc6b321a1u, 0x2ca22cb8u,
0xb1892d5cu, 0x5d605f3eu, 0x6025483cu, 0x9afd5181u,
0x6e1a7105u, 0x03010593u, 0x70acd304u, 0xab957cbfu,
0x8844abbbu, 0x53846837u, 0x24e98a43u, 0x2ba060c1u,
0x8b88b88eu, 0x44eea405u, 0xb259fc41u, 0x0907ad9cu,
0x13003adau, 0xcf79634eu, 0x7d314ec9u, 0xfbbe4c2bu,
0xd84d0823u, 0xfd30fd88u, 0x68d8a909u, 0xfb4572d9u,
0xa21301c2u, 0xd00a4785u, 0x6862b50cu, 0xcfe49796u,
0xdaacbd83u, 0xfb620906u, 0xdf71e0ccu, 0xbbc5b030u },
{ 0x69a82189u, 0x1a8b22f4u, 0xcf49207bu, 0x68cc056au,
0xb206b7d2u, 0x1d449bbdu, 0xe9d342f2u, 0x29daea58u,
0xb19d011au, 0xc62f15e4u, 0x9452697au, 0xb62bb87eu,
0x60f95cc2u, 0x279ebb2du, 0x17c1efd8u, 0xec47558bu,
0xc81334d1u, 0x88fe7601u, 0x79992eb1u, 0xb4555615u,
0x2022ac8cu, 0xc79a4b8cu, 0xb288b034u, 0xd6b942f0u,
0x0caa32fbu, 0xa065ba51u, 0x4de9f154u, 0x29f64f6cu,
0x7910af5eu, 0x3ed4636au, 0xe4c81911u, 0x9183f37du,
0x5811e1c4u, 0x29c7a58cu, 0x9715d4d3u, 0xc7e2dce3u,
0x140972ebu, 0xf4c8a69eu, 0xa104d424u, 0x5dabbdfbu,
0x41cb4c6bu, 0xd7f44717u, 0x61785ff7u, 0x5e0bc273u,
0x36426c70u, 0x2aa6f08eu, 0x083badbfu, 0x3cab941bu,
0x8871da23u, 0x1ab3dbaeu, 0x7115a21du, 0xf5aa0965u,
0xf766f562u, 0x7f110225u, 0x86d96a04u, 0xc50a120eu,
0x3a751ca3u, 0xc21aa186u, 0xba7359d0u, 0x3ff2b257u,
0xd116e8bbu, 0xfc1318c0u, 0x070e5b1du, 0x83b759a6u },
65537
};
@@ -136,30 +138,37 @@ ui_print(const char* format, ...) {
int main(int argc, char **argv) {
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: %s [-f4 | -file <keys>] <package>\n", argv[0]);
fprintf(stderr, "Usage: %s [-sha256] [-f4 | -file <keys>] <package>\n", argv[0]);
return 2;
}
RSAPublicKey* key = &test_key;
Certificate default_cert;
Certificate* cert = &default_cert;
cert->public_key = &test_key;
cert->hash_len = SHA_DIGEST_SIZE;
int num_keys = 1;
++argv;
if (strcmp(argv[0], "-sha256") == 0) {
++argv;
cert->hash_len = SHA256_DIGEST_SIZE;
}
if (strcmp(argv[0], "-f4") == 0) {
++argv;
key = &test_f4_key;
cert->public_key = &test_f4_key;
} else if (strcmp(argv[0], "-file") == 0) {
++argv;
key = load_keys(argv[0], &num_keys);
cert = load_keys(argv[0], &num_keys);
++argv;
}
ui = new FakeUI();
int result = verify_file(*argv, key, num_keys);
int result = verify_file(*argv, cert, num_keys);
if (result == VERIFY_SUCCESS) {
printf("SUCCESS\n");
printf("VERIFIED\n");
return 0;
} else if (result == VERIFY_FAILURE) {
printf("FAILURE\n");
printf("NOT VERIFIED\n");
return 1;
} else {
printf("bad return value\n");
+22 -16
View File
@@ -64,33 +64,39 @@ $ADB push $ANDROID_PRODUCT_OUT/system/bin/verifier_test \
expect_succeed() {
testname "$1 (should succeed)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test $WORK_DIR/package.zip || fail
shift
run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip || fail
}
expect_fail() {
testname "$1 (should fail)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test $WORK_DIR/package.zip && fail
}
expect_succeed_f4() {
testname "$1 (should succeed)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test -f4 $WORK_DIR/package.zip || fail
}
expect_fail_f4() {
testname "$1 (should fail)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test -f4 $WORK_DIR/package.zip && fail
shift
run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip && fail
}
# not signed at all
expect_fail unsigned.zip
# signed in the pre-donut way
expect_fail jarsigned.zip
# success cases
expect_succeed otasigned.zip
expect_fail_f4 otasigned.zip
expect_succeed_f4 otasigned_f4.zip
expect_succeed otasigned_f4.zip -f4
expect_succeed otasigned_sha256.zip -sha256
expect_succeed otasigned_f4_sha256.zip -sha256 -f4
# verified against different key
expect_fail otasigned.zip -f4
expect_fail otasigned_f4.zip
# verified against right key but wrong hash algorithm
expect_fail otasigned.zip -sha256
expect_fail otasigned_f4.zip -sha256 -f4
expect_fail otasigned_sha256.zip
expect_fail otasigned_f4_sha256.zip -f4
# various other cases
expect_fail random.zip
expect_fail fake-eocd.zip
expect_fail alter-metadata.zip