Compare commits

...

54 Commits
v15.3 ... v16.3

Author SHA1 Message Date
topjohnwu
7d7686da33 Update Magisk Manager 2018-03-28 15:23:55 +08:00
topjohnwu
65e455ef0b Update Android gradle plugin 2018-03-28 02:43:03 +08:00
topjohnwu
ac05e2f2e2 Fix tail size calculation
Close #381
2018-03-27 00:45:18 +08:00
topjohnwu
787f7b3035 Remove backwards compatibility symlinks
These links cause magiskhide unable to work ideally and add complications. I think I gave enough time for migration
2018-03-27 00:35:59 +08:00
topjohnwu
31bd642b80 Update to busybox 1.28.2 2018-03-26 22:12:04 +08:00
topjohnwu
f0bac6b154 Resetprop small refactor 2018-03-26 21:21:48 +08:00
topjohnwu
cc7e74ca11 Cleanup build.gradle 2018-03-26 03:53:06 +08:00
topjohnwu
e8a44646b8 Update Magisk Manager 2018-03-18 12:34:07 +08:00
topjohnwu
ae97d011ae Change MagiskHide state if logd is disabled 2018-03-18 12:17:10 +08:00
imswebra
1b7657a374 tips.md Grammar Fix 2018-03-18 12:16:57 +08:00
topjohnwu
5665e04014 Force using system binaries 2018-03-17 21:42:42 +08:00
topjohnwu
bb70385a42 Update Magisk Manager 2018-03-11 08:37:13 +08:00
topjohnwu
9855877b03 Update rules for Android P 2018-03-11 08:36:20 +08:00
topjohnwu
76c9188fae Android P renamed nonplat_properties 2018-03-11 02:53:57 +08:00
topjohnwu
e4e5269836 Android P have no make_ext4fs, use mke2fs as fallback 2018-03-11 02:52:24 +08:00
topjohnwu
9e737df534 Update high compression mode detection logic 2018-03-10 15:55:55 +08:00
Shaka Huang
0b3192c4d5 Check dtb even if kernel is not available
By the flow of unpacking boot image of Chrome OS there will be no kernel file but an dtb image. In that case the dtb image won’t be added when repacking boot image.

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-03-03 20:57:55 +08:00
Shaka Huang
968e6237bd Fix error parsing MTK boot.img
Should be copy & paste error:

1. boot->r_fmt should be re-checked instead of boot->k_fmt once MTK header was found in ramdisk.

2. ramdisk_size should be restored instead of kernel_size when uncompressed ramdisk was found.

3. Correct header of ramdisk

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-03-03 20:57:37 +08:00
worstperson
d780b5a0e4 Add support for the Nook Tablet, Acclaim
Also changed occurences of NOOK with NOOKHD
2018-03-03 20:55:44 +08:00
worstperson
3e48427eaf Add support for the new NOOK_MAGIC
The new cmdline value that's been in use since Marshmallow
2018-03-03 20:55:44 +08:00
worstperson
31360c34ed Set NOOK_PRE_HEADER_SZ from 0xFFFFF to 0x100000
All applicable Nook HD/HD+ roms are using this offset
2018-03-03 20:55:44 +08:00
topjohnwu
e9624e2304 Update submodules 2018-02-22 02:49:54 +08:00
topjohnwu
9c6e64f47d Workaround compiler optimization bug 2018-02-21 14:44:24 +08:00
topjohnwu
0afa601551 Fix F2FS manager crashing 2018-02-20 05:15:06 +08:00
topjohnwu
a94fa81195 Support non skip_initramfs device with slot suffix 2018-02-14 00:57:52 +08:00
topjohnwu
6119c24720 Bump Magisk Manager version 2018-02-13 08:04:47 +08:00
topjohnwu
7da205f4c8 Round sizes to nearest integer 2018-02-12 04:56:50 +08:00
topjohnwu
754fafcfe9 Check logd before logging 2018-02-12 02:48:15 +08:00
topjohnwu
bd7766b17e Prevent small memory leak 2018-02-11 21:55:57 +08:00
Andrew Gunnerson
70b7d73453 utils/cpio.c: Fix off-by-one error in cpio_vec_insert
Previously, if `cpio_vec_insert()` needed to replace a file and the file
already exists as the first entry, then a duplicate entry would get
created.

This fixes the bug I reported at:
https://forum.xda-developers.com/showpost.php?p=75449768&postcount=22647

Signed-off-by: Andrew Gunnerson <andrewgunnerson@gmail.com>
2018-02-11 18:50:42 +08:00
Andrew Gunnerson
5ad4702a5b utils/file.c: NULL terminate all files read into memory
Some functions, like `patch_init_rc()`, treat buffers read into memory
as a string instead of a byte buffer. Since the buffers weren't
NULL-terminated, this resulted in out-of-bounds reads and caused crashes
in certain conditions.

THis commit updates fd_full_read() to always NULL-terminate the buffers
so that they can be treated as strings when working with text files.

Signed-off-by: Andrew Gunnerson <andrewgunnerson@gmail.com>
2018-02-11 18:50:42 +08:00
topjohnwu
40b6fe03c2 Tweak enum 2018-02-11 18:50:42 +08:00
topjohnwu
49ecba2476 Obfuscate filenames to prevent detection
Because why not
2018-02-11 04:04:47 +08:00
topjohnwu
ebd509d92d Obfuscate socket name to prevent detection
Because why not
2018-02-11 03:59:54 +08:00
topjohnwu
7193374a7e Better Windows support 2018-02-10 19:54:58 +08:00
topjohnwu
6728445542 Support separate ramdisk images 2018-02-10 03:34:13 +08:00
topjohnwu
10ed299c78 Detect recovery on FBE devices with no DE access 2018-02-10 03:31:00 +08:00
topjohnwu
32b124913e Change busybox config 2018-02-06 05:52:25 +08:00
topjohnwu
599ae95251 Support moving files across filesystems 2018-02-02 04:47:16 +08:00
topjohnwu
d1be34c34a Support sepolicy_debug 2018-02-02 04:17:13 +08:00
topjohnwu
bc2cac90fe Hardlink files recursively 2018-02-02 03:22:38 +08:00
topjohnwu
28350e3ad9 Support Nook Green Loader 2018-01-30 05:56:59 +08:00
topjohnwu
f48e6c93b8 Support Tegra blobs 2018-01-30 05:20:18 +08:00
topjohnwu
7cfc24d68f Add DHTB header support 2018-01-29 22:16:02 +08:00
topjohnwu
a58d3ea04d Use libmincrypt 2018-01-29 15:34:05 +08:00
topjohnwu
dfee9954e0 Small refactor of magiskboot 2018-01-29 03:12:35 +08:00
topjohnwu
eed86c760f Add support to PXA devices
Close #340
2018-01-29 02:44:30 +08:00
topjohnwu
c471bb6f67 Update external sources 2018-01-29 02:41:39 +08:00
topjohnwu
518c2b0f95 Update README 2018-01-28 04:44:46 +08:00
topjohnwu
328fc44194 Rename module core to native 2018-01-27 09:11:28 +08:00
topjohnwu
b6f735a8f6 Rename module 2018-01-27 08:34:40 +08:00
topjohnwu
deae08fc4b Port zipadjust to Java 2018-01-27 08:25:34 +08:00
topjohnwu
c61135ee7b Embed testkeys into jar 2018-01-27 00:19:35 +08:00
topjohnwu
97cf15007f Update crypto 2018-01-23 05:06:34 +08:00
116 changed files with 4686 additions and 1878 deletions

32
.gitmodules vendored
View File

@@ -1,27 +1,27 @@
[submodule "jni/selinux"]
path = core/jni/external/selinux
[submodule "selinux"]
path = native/jni/external/selinux
url = https://github.com/topjohnwu/selinux.git
[submodule "jni/su"]
path = core/jni/su
[submodule "su"]
path = native/jni/su
url = https://github.com/topjohnwu/MagiskSU.git
[submodule "jni/magiskpolicy"]
path = core/jni/magiskpolicy
[submodule "magiskpolicy"]
path = native/jni/magiskpolicy
url = https://github.com/topjohnwu/magiskpolicy.git
[submodule "MagiskManager"]
path = app
url = https://github.com/topjohnwu/MagiskManager.git
[submodule "jni/busybox"]
path = core/jni/external/busybox
[submodule "busybox"]
path = native/jni/external/busybox
url = https://github.com/topjohnwu/ndk-busybox.git
[submodule "jni/external/dtc"]
path = core/jni/external/dtc
[submodule "dtc"]
path = native/jni/external/dtc
url = https://github.com/dgibson/dtc
[submodule "jni/external/lz4"]
path = core/jni/external/lz4
[submodule "lz4"]
path = native/jni/external/lz4
url = https://github.com/lz4/lz4.git
[submodule "jni/external/bzip2"]
path = core/jni/external/bzip2
[submodule "bzip2"]
path = native/jni/external/bzip2
url = https://github.com/nemequ/bzip2.git
[submodule "jni/external/xz"]
path = core/jni/external/xz
[submodule "xz"]
path = native/jni/external/xz
url = https://github.com/xz-mirror/xz.git

View File

@@ -6,17 +6,15 @@
### Environment Requirements
1. A 64-bit machine: `cmake` for Android is only available in 64-bit
2. Python 3.5+: run `build.py` script
3. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
4. Latest Android SDK: `ANDROID_HOME` environment variable should point to the Android SDK folder
5. Android NDK: Install NDK along with SDK (`$ANDROID_HOME/ndk-bundle`), or specify custom path `ANDROID_NDK`
6. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
7. (Unix only) C compiler: Build `zipadjust`. Windows users can use the pre-built `zipadjust.exe`
1. Python 3.5+: run `build.py` script
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
3. Latest Android SDK: `ANDROID_HOME` environment variable should point to the Android SDK folder
4. Android NDK: Install NDK along with SDK (`$ANDROID_HOME/ndk-bundle`), or specify custom path `ANDROID_NDK`
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
### Instructions and Notes
1. Magisk can be built with the latest NDK (r16 as of writing), however binaries released officially will be built with NDK r10e due to ELF incompatibilities with the binaries built from the newer NDKs.
2. The easiest way to setup the environment is by importing this folder as an Android Studio project. The IDE will download required components and construct the environment for you. You still have to set the `ANDROID_HOME` environment variable to point to the SDK path.
2. The easiest way to setup the environment is by importing the folder as an Android Studio project. The IDE will download required components and construct the environment for you. You still have to set the `ANDROID_HOME` environment variable to point to the SDK path.
3. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
4. Build everything with `build.py`, don't directly call `gradlew` or `ndk-build`, since most requires special setup / dependencies.
5. By default, `build.py` will build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (through the flag `--release`), you will need to place a Java Keystore file at `release_signature.jks` to sign Magisk Manager's APK. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
@@ -46,7 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* Copyright 2016-2018, John Wu (@topjohnwu)
* All contributors and translators on Github
**MagiskSU** (`core/jni/su`)
**MagiskSU** (`native/jni/su`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
@@ -54,23 +52,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* Copyright 2010, Adam Shanks (@ChainsDD)
* Copyright 2008, Zinx Verituse (@zinxv)
**MagiskPolicy** (`core/jni/magiskpolicy`)
**MagiskPolicy** (`native/jni/magiskpolicy`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
* Copyright 2015, Joshua Brindle (@joshua_brindle)
**MagiskHide** (`core/jni/magiskhide`)
**MagiskHide** (`native/jni/magiskhide`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2016, Pierre-Hugues Husson (phh@phh.me)
**resetprop** (`core/jni/resetprop`)
**resetprop** (`native/jni/resetprop`)
* Copyright 2016-2018 John Wu (@topjohnwu)
* Copyright 2016 nkk71 (nkk71x@gmail.com)
**External Dependencies** (`core/jni/external`)
**External Dependencies** (`native/jni/external`)
* Makefile for busybox, generated by [ndk-busybox-kitchen](https://github.com/topjohnwu/ndk-busybox-kitchen)
* Each dependencies has its own license/copyright information in each subdirectory.

2
app

Submodule app updated: 759e905c3c...e79d764148

View File

@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.1.0'
// NOTE: Do not place your application dependencies here; they belong
@@ -19,9 +19,16 @@ allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
ext {
compileSdkVersion = 27
buildToolsVersion = "27.0.3"
supportLibVersion = "27.1.0"
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@@ -26,13 +26,6 @@ try:
except FileNotFoundError:
error('Please install Java and make sure \'java\' is available in PATH')
# If not Windows, we need gcc to compile
if os.name != 'nt':
try:
subprocess.run(['gcc', '-v'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except FileNotFoundError:
error('Please install C compiler and make sure \'gcc\' is available in PATH')
import argparse
import multiprocessing
import zipfile
@@ -89,13 +82,13 @@ def build_binary(args):
header('* Building Magisk binaries')
# Force update logging.h timestamp to trigger recompilation
os.utime(os.path.join('core', 'jni', 'include', 'logging.h'))
os.utime(os.path.join('native', 'jni', 'include', 'logging.h'))
debug_flag = '' if args.release else '-DMAGISK_DEBUG'
cflag = 'MAGISK_FLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\"'.format(args.versionString, args.versionCode, debug_flag)
# Prebuild
proc = subprocess.run('{} -C core PRECOMPILE=true {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
proc = subprocess.run('{} -C native PRECOMPILE=true {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
if proc.returncode != 0:
error('Build Magisk binary failed!')
@@ -104,7 +97,7 @@ def build_binary(args):
mkdir_p(os.path.join('out', arch))
with open(os.path.join('out', arch, 'dump.h'), 'w') as dump:
dump.write('#include "stdlib.h"\n')
mv(os.path.join('core', 'libs', arch, 'magisk'), os.path.join('out', arch, 'magisk'))
mv(os.path.join('native', 'libs', arch, 'magisk'), os.path.join('out', arch, 'magisk'))
with open(os.path.join('out', arch, 'magisk'), 'rb') as bin:
dump.write('const uint8_t magisk_dump[] = "')
dump.write(''.join("\\x{:02X}".format(c) for c in lzma.compress(bin.read(), preset=9)))
@@ -112,7 +105,7 @@ def build_binary(args):
print('')
proc = subprocess.run('{} -C core {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
proc = subprocess.run('{} -C native {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
if proc.returncode != 0:
error('Build Magisk binary failed!')
@@ -120,18 +113,14 @@ def build_binary(args):
for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']:
for binary in ['magiskinit', 'magiskboot', 'b64xz', 'busybox']:
try:
mv(os.path.join('core', 'libs', arch, binary), os.path.join('out', arch, binary))
mv(os.path.join('native', 'libs', arch, binary), os.path.join('out', arch, binary))
except:
pass
def build_apk(args):
header('* Building Magisk Manager')
for key in ['public.certificate.x509.pem', 'private.key.pk8']:
source = os.path.join('ziptools', key)
target = os.path.join('app', 'src', 'main', 'assets', key)
cp(source, target)
mkdir(os.path.join('app', 'src', 'main', 'assets'))
for script in ['magisk_uninstaller.sh', 'util_functions.sh']:
source = os.path.join('scripts', script)
target = os.path.join('app', 'src', 'main', 'assets', script)
@@ -331,51 +320,22 @@ def zip_uninstaller(args):
sign_adjust_zip(unsigned, output)
def sign_adjust_zip(unsigned, output):
signer_name = 'zipsigner-1.1.jar'
jarsigner = os.path.join('crypto', 'build', 'libs', signer_name)
signer_name = 'zipsigner-2.1.jar'
jarsigner = os.path.join('utils', 'build', 'libs', signer_name)
if os.name != 'nt' and not os.path.exists(os.path.join('ziptools', 'zipadjust')):
header('* Building zipadjust')
# Compile zipadjust
proc = subprocess.run('gcc -o ziptools/zipadjust ziptools/zipadjust_src/*.c -lz', shell=True)
if proc.returncode != 0:
error('Build zipadjust failed!')
if not os.path.exists(jarsigner):
header('* Building ' + signer_name)
proc = subprocess.run('{} crypto:shadowJar'.format(os.path.join('.', 'gradlew')), shell=True)
proc = subprocess.run('{} utils:shadowJar'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build {} failed!'.format(signer_name))
header('* Signing / Adjusting Zip')
publicKey = os.path.join('ziptools', 'public.certificate.x509.pem')
privateKey = os.path.join('ziptools', 'private.key.pk8')
header('* Signing Zip')
signed = tempfile.mkstemp()[1]
# Unsigned->signed
proc = subprocess.run(['java', '-jar', jarsigner,
publicKey, privateKey, unsigned, signed])
proc = subprocess.run(['java', '-jar', jarsigner, unsigned, output])
if proc.returncode != 0:
error('First sign flashable zip failed!')
adjusted = tempfile.mkstemp()[1]
# Adjust zip
proc = subprocess.run([os.path.join('ziptools', 'zipadjust'), signed, adjusted])
if proc.returncode != 0:
error('Adjust flashable zip failed!')
# Adjusted -> output
proc = subprocess.run(['java', '-jar', jarsigner,
"-m", publicKey, privateKey, adjusted, output])
if proc.returncode != 0:
error('Second sign flashable zip failed!')
# Cleanup
rm(unsigned)
rm(signed)
rm(adjusted)
error('Signing zip failed!')
def cleanup(args):
if len(args.target) == 0:
@@ -383,14 +343,14 @@ def cleanup(args):
if 'binary' in args.target:
header('* Cleaning binaries')
subprocess.run(ndk_build + ' -C core PRECOMPILE=true clean', shell=True)
subprocess.run(ndk_build + ' -C core clean', shell=True)
subprocess.run(ndk_build + ' -C native PRECOMPILE=true clean', shell=True)
subprocess.run(ndk_build + ' -C native clean', shell=True)
for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']:
shutil.rmtree(os.path.join('out', arch), ignore_errors=True)
if 'java' in args.target:
header('* Cleaning java')
subprocess.run('{} app:clean snet:clean crypto:clean'.format(os.path.join('.', 'gradlew')), shell=True)
subprocess.run('{} app:clean snet:clean utils:clean'.format(os.path.join('.', 'gradlew')), shell=True)
for f in os.listdir('out'):
if '.apk' in f:
rm(os.path.join('out', f))

View File

@@ -1,152 +0,0 @@
/* socket.c - All socket related operations
*/
#include <fcntl.h>
#include "daemon.h"
#include "logging.h"
#include "utils.h"
#include "magisk.h"
/* Setup the address and return socket fd */
int setup_socket(struct sockaddr_un *sun) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_LOCAL;
memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, sizeof(REQUESTOR_DAEMON_PATH) - 1);
return fd;
}
/*
* Receive a file descriptor from a Unix socket.
* Contributed by @mkasick
*
* Returns the file descriptor on success, or -1 if a file
* descriptor was not actually included in the message
*
* On error the function terminates by calling exit(-1)
*/
int recv_fd(int sockfd) {
// Need to receive data from the message, otherwise don't care about it.
char iovbuf;
struct iovec iov = {
.iov_base = &iovbuf,
.iov_len = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
.msg_controllen = sizeof(cmsgbuf),
};
xrecvmsg(sockfd, &msg, MSG_WAITALL);
// Was a control message actually sent?
switch (msg.msg_controllen) {
case 0:
// No, so the file descriptor was closed and won't be used.
return -1;
case sizeof(cmsgbuf):
// Yes, grab the file descriptor from it.
break;
default:
goto error;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL ||
cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
error:
LOGE("unable to read fd");
exit(-1);
}
return *(int *)CMSG_DATA(cmsg);
}
/*
* Send a file descriptor through a Unix socket.
* Contributed by @mkasick
*
* On error the function terminates by calling exit(-1)
*
* fd may be -1, in which case the dummy data is sent,
* but no control message with the FD is sent.
*/
void send_fd(int sockfd, int fd) {
// Need to send some data in the message, this will do.
struct iovec iov = {
.iov_base = "",
.iov_len = 1,
};
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
if (fd != -1) {
// Is the file descriptor actually open?
if (fcntl(fd, F_GETFD) == -1) {
if (errno != EBADF) {
PLOGE("unable to send fd");
}
// It's closed, don't send a control message or sendmsg will EBADF.
} else {
// It's open, send the file descriptor in a control message.
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
}
}
xsendmsg(sockfd, &msg, 0);
}
int read_int(int fd) {
int val;
xxread(fd, &val, sizeof(int));
return val;
}
void write_int(int fd, int val) {
if (fd < 0) return;
xwrite(fd, &val, sizeof(int));
}
char* read_string(int fd) {
int len = read_int(fd);
if (len > PATH_MAX || len < 0) {
LOGE("invalid string length %d", len);
exit(1);
}
char* val = xmalloc(sizeof(char) * (len + 1));
xxread(fd, val, len);
val[len] = '\0';
return val;
}
void write_string(int fd, const char* val) {
if (fd < 0) return;
int len = strlen(val);
write_int(fd, len);
xwrite(fd, val, len);
}

Submodule core/jni/external/dtc deleted from 22a65c5331

Submodule core/jni/external/lz4 deleted from c10863b98e

View File

@@ -1,295 +0,0 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include <stdio.h>
#include <string.h>
/* for uint32_t */
#include <stdint.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(
uint32_t state[5],
const unsigned char buffer[64]
)
{
uint32_t a, b, c, d, e;
typedef union
{
unsigned char c[64];
uint32_t l[16];
} CHAR64LONG16;
#ifdef SHA1HANDSOFF
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
memcpy(block, buffer, 64);
#else
/* The following had better never be used because it causes the
* pointer-to-const buffer to be cast into a pointer to non-const.
* And the result is written through. I threw a "const" in, hoping
* this will cause a diagnostic.
*/
CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a, b, c, d, e, 0);
R0(e, a, b, c, d, 1);
R0(d, e, a, b, c, 2);
R0(c, d, e, a, b, 3);
R0(b, c, d, e, a, 4);
R0(a, b, c, d, e, 5);
R0(e, a, b, c, d, 6);
R0(d, e, a, b, c, 7);
R0(c, d, e, a, b, 8);
R0(b, c, d, e, a, 9);
R0(a, b, c, d, e, 10);
R0(e, a, b, c, d, 11);
R0(d, e, a, b, c, 12);
R0(c, d, e, a, b, 13);
R0(b, c, d, e, a, 14);
R0(a, b, c, d, e, 15);
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
memset(block, '\0', sizeof(block));
#endif
}
/* SHA1Init - Initialize new context */
void SHA1Init(
SHA1_CTX * context
)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(
SHA1_CTX * context,
const unsigned char *data,
uint32_t len
)
{
uint32_t i;
uint32_t j;
j = context->count[0];
if ((context->count[0] += len << 3) < j)
context->count[1]++;
context->count[1] += (len >> 29);
j = (j >> 3) & 63;
if ((j + len) > 63)
{
memcpy(&context->buffer[j], data, (i = 64 - j));
SHA1Transform(context->state, context->buffer);
for (; i + 63 < len; i += 64)
{
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else
i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(
unsigned char digest[20],
SHA1_CTX * context
)
{
unsigned i;
unsigned char finalcount[8];
unsigned char c;
#if 0 /* untested "improvement" by DHR */
/* Convert context->count to a sequence of bytes
* in finalcount. Second element first, but
* big-endian order within element.
* But we do it all backwards.
*/
unsigned char *fcp = &finalcount[8];
for (i = 0; i < 2; i++)
{
uint32_t t = context->count[i];
int j;
for (j = 0; j < 4; t >>= 8, j++)
*--fcp = (unsigned char) t}
#else
for (i = 0; i < 8; i++)
{
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
}
#endif
c = 0200;
SHA1Update(context, &c, 1);
while ((context->count[0] & 504) != 448)
{
c = 0000;
SHA1Update(context, &c, 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++)
{
digest[i] = (unsigned char)
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
/* Wipe variables */
memset(context, '\0', sizeof(*context));
memset(&finalcount, '\0', sizeof(finalcount));
}
void SHA1(
char *hash_out,
const char *str,
int len)
{
SHA1_CTX ctx;
unsigned int ii;
SHA1Init(&ctx);
for (ii=0; ii<len; ii+=1)
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
SHA1Final((unsigned char *)hash_out, &ctx);
hash_out[20] = '\0';
}

View File

@@ -1,308 +0,0 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "bootimg.h"
#include "magiskboot.h"
#include "utils.h"
#include "logging.h"
#define INSUF_BLOCK_RET 2
#define CHROMEOS_RET 3
#define ELF32_RET 4
#define ELF64_RET 5
static void dump(void *buf, size_t size, const char *filename) {
int fd = creat(filename, 0644);
xwrite(fd, buf, size);
close(fd);
}
static size_t restore(const char *filename, int fd) {
int ifd = xopen(filename, O_RDONLY);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
xsendfile(fd, ifd, NULL, size);
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
static void print_hdr(const boot_img_hdr *hdr) {
fprintf(stderr, "KERNEL [%d] @ 0x%08x\n", hdr->kernel_size, hdr->kernel_addr);
fprintf(stderr, "RAMDISK [%d] @ 0x%08x\n", hdr->ramdisk_size, hdr->ramdisk_addr);
fprintf(stderr, "SECOND [%d] @ 0x%08x\n", hdr->second_size, hdr->second_addr);
fprintf(stderr, "EXTRA [%d] @ 0x%08x\n", hdr->extra_size, hdr->tags_addr);
fprintf(stderr, "PAGESIZE [%d]\n", hdr->page_size);
if (hdr->os_version != 0) {
int a,b,c,y,m = 0;
int os_version, os_patch_level;
os_version = hdr->os_version >> 11;
os_patch_level = hdr->os_version & 0x7ff;
a = (os_version >> 14) & 0x7f;
b = (os_version >> 7) & 0x7f;
c = os_version & 0x7f;
fprintf(stderr, "OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (os_patch_level >> 4) + 2000;
m = os_patch_level & 0xf;
fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m);
}
fprintf(stderr, "NAME [%s]\n", hdr->name);
fprintf(stderr, "CMDLINE [%s]\n", hdr->cmdline);
}
int parse_img(const char *image, boot_img *boot) {
memset(boot, 0, sizeof(*boot));
int is_blk = mmap_ro(image, &boot->map_addr, &boot->map_size);
// Parse image
fprintf(stderr, "Parsing boot image: [%s]\n", image);
for (void *head = boot->map_addr; head < boot->map_addr + boot->map_size; head += 256) {
size_t pos = 0;
switch (check_type(head)) {
case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing
boot->flags |= CHROMEOS_FLAG;
continue;
case ELF32:
exit(ELF32_RET);
case ELF64:
exit(ELF64_RET);
case AOSP:
// Read the header
memcpy(&boot->hdr, head + pos, sizeof(boot->hdr));
pos += boot->hdr.page_size;
print_hdr(&boot->hdr);
boot->kernel = head + pos;
pos += boot->hdr.kernel_size;
mem_align(&pos, boot->hdr.page_size);
boot->ramdisk = head + pos;
pos += boot->hdr.ramdisk_size;
mem_align(&pos, boot->hdr.page_size);
if (boot->hdr.second_size) {
boot->second = head + pos;
pos += boot->hdr.second_size;
mem_align(&pos, boot->hdr.page_size);
}
if (boot->hdr.extra_size) {
boot->extra = head + pos;
pos += boot->hdr.extra_size;
mem_align(&pos, boot->hdr.page_size);
}
if (pos < boot->map_size) {
boot->tail = head + pos;
boot->tail_size = boot->map_size - pos;
}
// Search for dtb in kernel
for (uint32_t i = 0; i < boot->hdr.kernel_size; ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i;
boot->dt_size = boot->hdr.kernel_size - i;
boot->hdr.kernel_size = i;
fprintf(stderr, "DTB [%u]\n", boot->dt_size);
}
}
boot->ramdisk_type = check_type(boot->ramdisk);
boot->kernel_type = check_type(boot->kernel);
// Check MTK
if (boot->kernel_type == MTK) {
fprintf(stderr, "MTK_KERNEL_HDR [512]\n");
boot->flags |= MTK_KERNEL;
memcpy(&boot->mtk_kernel_hdr, boot->kernel, sizeof(mtk_hdr));
boot->kernel += 512;
boot->hdr.kernel_size -= 512;
boot->kernel_type = check_type(boot->kernel);
}
if (boot->ramdisk_type == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR [512]\n");
boot->flags |= MTK_RAMDISK;
memcpy(&boot->mtk_ramdisk_hdr, boot->ramdisk, sizeof(mtk_hdr));
boot->ramdisk += 512;
boot->hdr.ramdisk_size -= 512;
boot->ramdisk_type = check_type(boot->ramdisk);
}
char fmt[16];
get_type_name(boot->kernel_type, fmt);
fprintf(stderr, "KERNEL_FMT [%s]\n", fmt);
get_type_name(boot->ramdisk_type, fmt);
fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt);
return boot->flags & CHROMEOS_FLAG ? CHROMEOS_RET :
((is_blk && boot->tail_size < 500 * 1024) ? INSUF_BLOCK_RET : 0);
default:
continue;
}
}
LOGE("No boot image magic found!\n");
}
void unpack(const char* image) {
boot_img boot;
int ret = parse_img(image, &boot);
int fd;
// Dump kernel
if (COMPRESSED(boot.kernel_type)) {
fd = creat(KERNEL_FILE, 0644);
decomp(boot.kernel_type, fd, boot.kernel, boot.hdr.kernel_size);
close(fd);
} else {
dump(boot.kernel, boot.hdr.kernel_size, KERNEL_FILE);
}
if (boot.dt_size) {
// Dump dtb
dump(boot.dtb, boot.dt_size, DTB_FILE);
}
// Dump ramdisk
if (COMPRESSED(boot.ramdisk_type)) {
fd = creat(RAMDISK_FILE, 0644);
decomp(boot.ramdisk_type, fd, boot.ramdisk, boot.hdr.ramdisk_size);
close(fd);
} else {
dump(boot.ramdisk, boot.hdr.ramdisk_size, RAMDISK_FILE ".raw");
LOGE("Unknown ramdisk format! Dumped to %s\n", RAMDISK_FILE ".raw");
}
if (boot.hdr.second_size) {
// Dump second
dump(boot.second, boot.hdr.second_size, SECOND_FILE);
}
if (boot.hdr.extra_size) {
// Dump extra
dump(boot.extra, boot.hdr.extra_size, EXTRA_FILE);
}
munmap(boot.map_addr, boot.map_size);
exit(ret);
}
void repack(const char* orig_image, const char* out_image) {
boot_img boot;
// There are possible two MTK headers
size_t mtk_kernel_off, mtk_ramdisk_off;
// Parse original image
parse_img(orig_image, &boot);
fprintf(stderr, "Repack to boot image: [%s]\n", out_image);
// Create new image
int fd = creat(out_image, 0644);
// Skip a page for header
write_zero(fd, boot.hdr.page_size);
if (boot.flags & MTK_KERNEL) {
// Record position and skip MTK header
mtk_kernel_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, 512);
}
if (COMPRESSED(boot.kernel_type)) {
size_t raw_size;
void *kernel_raw;
mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size);
boot.hdr.kernel_size = comp(boot.kernel_type, fd, kernel_raw, raw_size);
munmap(kernel_raw, raw_size);
} else {
boot.hdr.kernel_size = restore(KERNEL_FILE, fd);
}
// Restore dtb
if (boot.dt_size && access(DTB_FILE, R_OK) == 0) {
boot.hdr.kernel_size += restore(DTB_FILE, fd);
}
file_align(fd, boot.hdr.page_size, 1);
if (boot.flags & MTK_RAMDISK) {
// Record position and skip MTK header
mtk_ramdisk_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, 512);
}
if (access(RAMDISK_FILE, R_OK) == 0) {
// If we found raw cpio, compress to original format
size_t cpio_size;
void *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
boot.hdr.ramdisk_size = comp(boot.ramdisk_type, fd, cpio, cpio_size);
munmap(cpio, cpio_size);
} else {
// Find compressed ramdisk
char name[PATH_MAX];
int found = 0;
for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
if (access(name, R_OK) == 0) {
found = 1;
break;
}
}
if (!found)
LOGE("No ramdisk exists!\n");
boot.hdr.ramdisk_size = restore(name, fd);
}
file_align(fd, boot.hdr.page_size, 1);
// Restore second
if (boot.hdr.second_size && access(SECOND_FILE, R_OK) == 0) {
boot.hdr.second_size = restore(SECOND_FILE, fd);
file_align(fd, boot.hdr.page_size, 1);
}
// Restore extra
if (boot.hdr.extra_size && access(EXTRA_FILE, R_OK) == 0) {
boot.hdr.extra_size = restore(EXTRA_FILE, fd);
file_align(fd, boot.hdr.page_size, 1);
}
// Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (boot.tail_size >= 16) {
if (memcmp(boot.tail, "SEANDROIDENFORCE", 16) == 0 ||
memcmp(boot.tail, LG_BUMP_MAGIC, 16) == 0 ) {
restore_buf(fd, boot.tail, 16);
}
}
// Write MTK headers back
if (boot.flags & MTK_KERNEL) {
lseek(fd, mtk_kernel_off, SEEK_SET);
boot.mtk_kernel_hdr.size = boot.hdr.kernel_size;
boot.hdr.kernel_size += 512;
restore_buf(fd, &boot.mtk_kernel_hdr, sizeof(mtk_hdr));
}
if (boot.flags & MTK_RAMDISK) {
lseek(fd, mtk_ramdisk_off, SEEK_SET);
boot.mtk_ramdisk_hdr.size = boot.hdr.ramdisk_size;
boot.hdr.ramdisk_size += 512;
restore_buf(fd, &boot.mtk_ramdisk_hdr, sizeof(mtk_hdr));
}
// Main header
lseek(fd, 0, SEEK_SET);
restore_buf(fd, &boot.hdr, sizeof(boot.hdr));
// Print new image info
print_hdr(&boot.hdr);
munmap(boot.map_addr, boot.map_size);
close(fd);
}

View File

@@ -1,127 +0,0 @@
/* tools/mkbootimg/bootimg.h
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdint.h>
#include "types.h"
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t extra_size; /* extra blob size in bytes */
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
* os_version = ver << 11 | lvl */
uint32_t os_version;
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
** | extra blobs | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
** p = (extra_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
typedef struct mtk_hdr {
uint8_t magic[4]; /* MTK magic */
uint32_t size; /* Size of the content */
uint8_t name[32]; /* The type of the header */
} mtk_hdr;
// Flags
#define MTK_KERNEL 0x1
#define MTK_RAMDISK 0x2
#define CHROMEOS_FLAG 0x4
typedef struct boot_img {
size_t map_size;
uint32_t dt_size;
size_t tail_size;
uint8_t flags;
file_t kernel_type, ramdisk_type;
boot_img_hdr hdr;
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
void *map_addr;
void *kernel;
void *dtb;
void *ramdisk;
void *second;
void *extra;
void *tail;
} boot_img;
#endif

View File

@@ -1,42 +0,0 @@
package com.topjohnwu.crypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Security;
public class ZipSigner {
public static void main(String[] args) {
boolean minSign = false;
int argStart = 0;
if (args.length < 4) {
System.err.println("Usage: zipsigner [-m] publickey.x509[.pem] privatekey.pk8 input.jar output.jar");
System.exit(2);
}
if (args[0].equals("-m")) {
minSign = true;
argStart = 1;
}
SignAPK.sBouncyCastleProvider = new BouncyCastleProvider();
Security.insertProviderAt(SignAPK.sBouncyCastleProvider, 1);
File pubKey = new File(args[argStart]);
File privKey = new File(args[argStart + 1]);
File input = new File(args[argStart + 2]);
File output = new File(args[argStart + 3]);
try (InputStream pub = new FileInputStream(pubKey);
InputStream priv = new FileInputStream(privKey);
JarMap jar = new JarMap(input, false)) {
SignAPK.signZip(pub, priv, jar, output, minSign);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

View File

@@ -1,7 +1,7 @@
# Tips and Tricks
## OTA Installation Tips
Magisk do modifications systemless-ly, which means applying official OTAs is much simpler. Here I provide a few tutorials for several different kind of devices to apply OTAs and preserve Magisk after the installation if possible.
Magisk does modifications systemless-ly, which means applying official OTAs is much simpler. Here I provide a few tutorials for several different kind of devices to apply OTAs and preserve Magisk after the installation if possible.
**This tutorial is only for Magisk v14.1+**
@@ -50,4 +50,4 @@ If you decide to start by installing Magisk without touching your recovery parti
How to remove a file systemless-ly? To actually make the file **disappear** is complicated (possible, not worth the effort). **Replacing it with a dummy file should be good enough**! Create an empty file with the same name and place it in the same path within a module, it shall replace your target file with a dummy file.
## Remove Folders
Same as mentioned above, actually making the folder to **disappear** is not worth the effort. **Replacing it with an empty folder should be good enough**! A handy trick for module developers using [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) is to add the folder you want to remove into the `REPLACE` list within `config.sh`. If your module doesn't provide a correspond folder, it will create an empty folder, and automatically add `.replace` into the empty folder so the dummy folder will properly replace the one in `/system`.
Same as mentioned above, actually making the folder to **disappear** is not worth the effort. **Replacing it with an empty folder should be good enough**! A handy trick for module developers using [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) is to add the folder you want to remove into the `REPLACE` list within `config.sh`. If your module doesn't provide a correspond folder, it will create an empty folder, and automatically add `.replace` into the empty folder so the dummy folder will properly replace the one in `/system`.

View File

@@ -1,6 +1,6 @@
#Mon Dec 04 11:24:34 CST 2017
#Tue Mar 27 21:17:43 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View File

@@ -1,7 +1,8 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
externalNativeBuild {
ndkBuild {

View File

@@ -31,7 +31,7 @@ LOCAL_SHARED_LIBRARIES := libsqlite libselinux
LOCAL_C_INCLUDES := \
jni/include \
jni/external/include \
$(EXT_PATH)/include \
$(LIBSELINUX)
LOCAL_SRC_FILES := \
@@ -87,22 +87,21 @@ include $(BUILD_EXECUTABLE)
# magiskboot
include $(CLEAR_VARS)
LOCAL_MODULE := magiskboot
LOCAL_STATIC_LIBRARIES := liblzma liblz4 libbz2 libfdt
LOCAL_STATIC_LIBRARIES := libmincrypt liblzma liblz4 libbz2 libfdt
LOCAL_C_INCLUDES := \
jni/include \
jni/external/include \
$(EXT_PATH)/include \
$(LIBLZMA) \
$(LIBLZ4) \
$(LIBBZ2) \
$(LIBFDT)
LOCAL_SRC_FILES := \
external/sha1/sha1.c \
magiskboot/main.c \
magiskboot/bootimg.c \
magiskboot/hexpatch.c \
magiskboot/compress.c \
magiskboot/types.c \
magiskboot/format.c \
magiskboot/dtb.c \
magiskboot/ramdisk.c \
$(UTIL_SRC)

View File

@@ -2,3 +2,4 @@ APP_ABI := x86 x86_64 armeabi-v7a arm64-v8a
APP_PLATFORM := android-21
APP_CFLAGS := $(MAGISK_FLAGS) -std=gnu99
APP_CPPFLAGS := -std=c++11
APP_SHORT_COMMANDS := true

View File

@@ -51,7 +51,7 @@ struct node_entry {
static void concat_path(struct node_entry *node) {
if (node->parent)
concat_path(node->parent);
int len = strlen(buf);
size_t len = strlen(buf);
buf[len] = '/';
strcpy(buf + len + 1, node->name);
}

View File

@@ -25,7 +25,7 @@ int is_daemon_init = 0, seperate_vendor = 0;
static void *request_handler(void *args) {
int client = *((int *) args);
free(args);
client_request req = read_int(client);
int req = read_int(client);
struct ucred credential;
get_client_cred(client, &credential);
@@ -127,6 +127,7 @@ void daemon_init() {
rm_rf("/data/magisk");
unlink("/data/magisk.img");
unlink("/data/magisk_debug.log");
xmkdir("/data/adb", 0700);
chmod("/data/adb", 0700);
LOGI("* Creating /sbin overlay");
@@ -134,6 +135,7 @@ void daemon_init() {
struct dirent *entry;
int root, sbin;
char buf[PATH_MAX], buf2[PATH_MAX];
char magisk_name[10], init_name[10];
// Setup links under /sbin
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
@@ -141,13 +143,8 @@ void daemon_init() {
chmod("/root", 0755);
root = xopen("/root", O_RDONLY | O_CLOEXEC);
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
dir = xfdopendir(sbin);
while((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
linkat(sbin, entry->d_name, root, entry->d_name, 0);
if (strcmp(entry->d_name, "magisk") == 0)
unlinkat(sbin, entry->d_name, 0);
}
link_dir(sbin, root);
unlink("/sbin/magisk");
close(sbin);
xmount("tmpfs", "/sbin", "tmpfs", 0, NULL);
@@ -160,20 +157,27 @@ void daemon_init() {
snprintf(buf2, PATH_MAX, "/sbin/%s", entry->d_name);
xsymlink(buf, buf2);
}
gen_rand_str(magisk_name, sizeof(magisk_name));
snprintf(buf, PATH_MAX, "/root/%s", magisk_name);
unlink("/sbin/magisk");
rename("/root/magisk", buf);
xsymlink(buf, "/sbin/magisk");
for (int i = 0; applet[i]; ++i) {
snprintf(buf2, PATH_MAX, "/sbin/%s", applet[i]);
xsymlink("/root/magisk", buf2);
xsymlink(buf, buf2);
}
gen_rand_str(init_name, sizeof(init_name));
snprintf(buf, PATH_MAX, "/root/%s", init_name);
unlink("/sbin/magiskinit");
rename("/root/magiskinit", buf);
for (int i = 0; init_applet[i]; ++i) {
snprintf(buf2, PATH_MAX, "/sbin/%s", init_applet[i]);
xsymlink("/root/magiskinit", buf2);
xsymlink(buf, buf2);
}
close(root);
// Backward compatibility
xsymlink(DATABIN, "/data/magisk");
xsymlink(MAINIMG, "/data/magisk.img");
xsymlink(MOUNTPOINT, "/magisk");
close(root);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
@@ -198,7 +202,7 @@ void daemon_init() {
xmkdirs(MIRRDIR "/system", 0755);
xmount(buf, MIRRDIR "/system", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s -> %s\n", buf, MIRRDIR "/system");
LOGI("mount: %s <- %s\n", MIRRDIR "/system", buf);
#else
LOGI("mount: %s\n", MIRRDIR "/system");
#endif
@@ -208,7 +212,7 @@ void daemon_init() {
xmkdirs(MIRRDIR "/vendor", 0755);
xmount(buf, MIRRDIR "/vendor", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s -> %s\n", buf, MIRRDIR "/vendor");
LOGI("mount: %s <- %s\n", MIRRDIR "/vendor", buf);
#else
LOGI("mount: %s\n", MIRRDIR "/vendor");
#endif
@@ -219,7 +223,7 @@ void daemon_init() {
if (!seperate_vendor) {
xsymlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor");
#ifdef MAGISK_DEBUG
LOGI("link: %s -> %s\n", MIRRDIR "/system/vendor", MIRRDIR "/vendor");
LOGI("link: %s <- %s\n", MIRRDIR "/vendor", MIRRDIR "/system/vendor");
#else
LOGI("link: %s\n", MIRRDIR "/vendor");
#endif
@@ -257,6 +261,9 @@ void start_daemon() {
exit(1);
xlisten(fd, 10);
// Start the log monitor
monitor_logs();
if ((is_daemon_init = (access(MAGISKTMP, F_OK) == 0))) {
// Restart stuffs if the daemon is restarted
exec_command_sync("logcat", "-b", "all", "-c", NULL);
@@ -266,9 +273,6 @@ void start_daemon() {
daemon_init();
}
// Start the log monitor
monitor_logs();
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Change process name

View File

@@ -12,8 +12,10 @@
#include "magisk.h"
#include "utils.h"
#include "resetprop.h"
extern int is_daemon_init;
int logd = 0;
static int am_proc_start_filter(const char *log) {
return strstr(log, "am_proc_start") != NULL;
@@ -44,9 +46,20 @@ struct log_listener log_events[] = {
};
#ifdef MAGISK_DEBUG
static int debug_log_pid, debug_log_fd;
static int debug_log_pid = -1, debug_log_fd = -1;
#endif
static void check_logd() {
char *prop = getprop("init.svc.logd");
if (prop != NULL) {
free(prop);
logd = 1;
} else {
LOGD("log_monitor: logd not started, disable logging");
logd = 0;
}
}
static void *logger_thread(void *args) {
int log_fd = -1, log_pid;
char line[4096];
@@ -54,6 +67,15 @@ static void *logger_thread(void *args) {
LOGD("log_monitor: logger start");
while (1) {
if (!logd) {
// Disable all services
for (int i = 0; i < (sizeof(log_events) / sizeof(struct log_listener)); ++i) {
close(log_events[i].fd);
log_events[i].fd = -1;
}
return NULL;
}
// Start logcat
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-b", "main", "-v", "threadtime", "-s", "am_proc_start", "-s", "Magisk", NULL);
while (fdgets(line, sizeof(line), log_fd)) {
@@ -75,6 +97,8 @@ static void *logger_thread(void *args) {
// Clear buffer before restart
exec_command_sync("logcat", "-b", "events", "-b", "main", "-c", NULL);
check_logd();
}
// Should never be here, but well...
@@ -139,40 +163,49 @@ static void *debug_magisk_log_thread(void *args) {
void monitor_logs() {
pthread_t thread;
// Start log file dumper before monitor
xpthread_create(&thread, NULL, magisk_log_thread, NULL);
pthread_detach(thread);
check_logd();
// Start logcat monitor
xpthread_create(&thread, NULL, logger_thread, NULL);
pthread_detach(thread);
if (logd) {
// Start log file dumper before monitor
xpthread_create(&thread, NULL, magisk_log_thread, NULL);
pthread_detach(thread);
// Start logcat monitor
xpthread_create(&thread, NULL, logger_thread, NULL);
pthread_detach(thread);
}
}
void start_debug_full_log() {
#ifdef MAGISK_DEBUG
// Log everything initially
debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "threadtime", NULL);
close(debug_log_fd);
if (logd) {
// Log everything initially
debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "threadtime", NULL);
close(debug_log_fd);
}
#endif
}
void stop_debug_full_log() {
#ifdef MAGISK_DEBUG
// Stop recording the boot logcat after every boot task is done
kill(debug_log_pid, SIGTERM);
waitpid(debug_log_pid, NULL, 0);
// Start debug thread
start_debug_log();
if (debug_log_pid > 0) {
kill(debug_log_pid, SIGTERM);
waitpid(debug_log_pid, NULL, 0);
// Start debug thread
start_debug_log();
}
#endif
}
void start_debug_log() {
#ifdef MAGISK_DEBUG
pthread_t thread;
// Start debug thread
xpthread_create(&thread, NULL, debug_magisk_log_thread, NULL);
pthread_detach(thread);
if (logd) {
pthread_t thread;
// Start debug thread
xpthread_create(&thread, NULL, debug_magisk_log_thread, NULL);
pthread_detach(thread);
}
#endif
}

View File

@@ -55,10 +55,11 @@
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
static int keepverity = 0, keepencrypt = 0;
static char RAND_SOCKET_NAME[sizeof(SOCKET_NAME)];
static int SOCKET_OFF = -1;
struct cmdline {
int skip_initramfs;
char skip_initramfs;
char slot[3];
};
@@ -72,8 +73,7 @@ struct device {
static void parse_cmdline(struct cmdline *cmd) {
// cleanup
cmd->skip_initramfs = 0;
cmd->slot[0] = '\0';
memset(cmd, 0, sizeof(&cmd));
char cmdline[4096];
mkdir("/proc", 0555);
@@ -87,11 +87,13 @@ static void parse_cmdline(struct cmdline *cmd) {
sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot);
} else if (strncmp(tok, "androidboot.slot", 16) == 0) {
cmd->slot[0] = '_';
sscanf(tok, "androidboot.slot=%s", cmd->slot + 1);
sscanf(tok, "androidboot.slot=%c", cmd->slot + 1);
} else if (strcmp(tok, "skip_initramfs") == 0) {
cmd->skip_initramfs = 1;
}
}
VLOG("cmdline: skip_initramfs[%d] slot[%s]\n", cmd->skip_initramfs, cmd->slot);
}
static void parse_device(struct device *dev, char *uevent) {
@@ -146,24 +148,7 @@ static int setup_block(struct device *dev, const char *partname) {
return 0;
}
static void fstab_patch_cb(int dirfd, struct dirent *entry) {
if (entry->d_type == DT_REG && strstr(entry->d_name, "fstab")) {
void *buf;
size_t _size;
uint32_t size;
full_read_at(dirfd, entry->d_name, &buf, &_size);
size = _size; /* Type conversion */
if (!keepverity)
patch_verity(&buf, &size, 1);
if (!keepencrypt)
patch_encryption(&buf, &size);
int fstab = xopenat(dirfd, entry->d_name, O_WRONLY | O_CLOEXEC);
write(fstab, buf, size);
close(fstab);
}
}
static void patch_ramdisk(int root) {
static void patch_ramdisk() {
void *addr;
size_t size;
mmap_rw("/init", &addr, &size);
@@ -181,30 +166,11 @@ static void patch_ramdisk(int root) {
write(fd, addr, size);
close(fd);
free(addr);
/* Disabled for now */
// char *key, *value;
// full_read("/.backup/.magisk", &addr, &size);
// for (char *tok = strtok(addr, "\n"); tok; tok = strtok(NULL, "\n")) {
// key = tok;
// value = strchr(tok, '=') + 1;
// value[-1] = '\0';
// if (strcmp(key, "KEEPVERITY") == 0)
// keepverity = strcmp(value, "true") == 0;
// else if (strcmp(key, "KEEPFORCEENCRYPT") == 0)
// keepencrypt = strcmp(value, "true") == 0;
// }
// excl_list = (char *[]) { "system_root", "system", "vendor", NULL };
// in_order_walk(root, fstab_patch_cb);
// if (!keepverity)
// unlink("/verity_key");
}
static int strend(const char *s1, const char *s2) {
int l1 = strlen(s1);
int l2 = strlen(s2);
size_t l1 = strlen(s1);
size_t l2 = strlen(s2);
return strcmp(s1 + l1 - l2, s2);
}
@@ -318,6 +284,12 @@ static int patch_sepolicy() {
sepol_magisk_rules();
dump_policydb("/sepolicy");
// Remove the stupid debug sepolicy and use our own
if (access("/sepolicy_debug", F_OK) == 0) {
unlink("/sepolicy_debug");
link("/sepolicy", "/sepolicy_debug");
}
return 0;
}
@@ -327,7 +299,7 @@ static int unxz(const void *buf, size_t size, int fd) {
lzma_stream strm = LZMA_STREAM_INIT;
if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK)
return 1;
lzma_ret ret = 0;
lzma_ret ret;
void *out = malloc(BUFSIZE);
strm.next_in = buf;
strm.avail_in = size;
@@ -361,6 +333,23 @@ static int dump_magiskrc(const char *path, mode_t mode) {
return 0;
}
static void patch_socket_name(const char *path) {
void *buf;
size_t size;
mmap_rw(path, &buf, &size);
if (SOCKET_OFF < 0) {
for (int i = 0; i < size; ++i) {
if (memcmp(buf + i, socket_name, sizeof(SOCKET_NAME)) == 0) {
SOCKET_OFF = i;
break;
}
}
}
gen_rand_str(RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
memcpy(buf + SOCKET_OFF, RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
munmap(buf, size);
}
static void magisk_init_daemon() {
setsid();
@@ -375,7 +364,8 @@ static void magisk_init_daemon() {
dup3(null, STDIN_FILENO, O_CLOEXEC);
dup3(null, STDOUT_FILENO, O_CLOEXEC);
dup3(null, STDERR_FILENO, O_CLOEXEC);
close(null);
if (null > STDERR_FILENO)
close(null);
// Transit our context to su (mimic setcon)
int fd, crap;
@@ -392,6 +382,7 @@ static void magisk_init_daemon() {
while (1) {
struct sockaddr_un sun;
fd = setup_socket(&sun);
memcpy(sun.sun_path + 1, RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
while (connect(fd, (struct sockaddr*) &sun, sizeof(sun)))
usleep(10000); /* Wait 10 ms after each try */
@@ -438,109 +429,114 @@ int main(int argc, char *argv[]) {
dump_magiskrc("/overlay/init.magisk.rc", 0750);
mkdir("/overlay/sbin", 0755);
dump_magisk("/overlay/sbin/magisk", 0755);
patch_socket_name("/overlay/sbin/magisk");
mkdir("/overlay/root", 0755);
link("/init", "/overlay/root/magiskinit");
struct cmdline cmd;
parse_cmdline(&cmd);
VLOG("cmdline: skip_initramfs=[%d] slot_suffix=[%s]\n", cmd.skip_initramfs, cmd.slot);
/* ***********
* Initialize
* ***********/
int root = open("/", O_RDONLY | O_CLOEXEC);
if (cmd.skip_initramfs) {
// Exclude overlay folder
excl_list = (char *[]) { "overlay", ".backup", NULL };
// Clear rootfs
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
} else if (access("/ramdisk.cpio.xz", R_OK) == 0) {
// High compression mode
void *addr;
size_t size;
mmap_ro("/ramdisk.cpio.xz", &addr, &size);
int fd = creat("/ramdisk.cpio", 0);
unxz(addr, size, fd);
munmap(addr, size);
close(fd);
struct vector v;
vec_init(&v);
parse_cpio(&v, "/ramdisk.cpio");
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
chdir("/");
cpio_extract_all(&v);
cpio_vec_destroy(&v);
} else {
// Revert original init binary
unlink("/init");
link("/.backup/init", "/init");
}
/* ************
* Early Mount
* ************/
// If skip_initramfs or using split policies, we need early mount
if (cmd.skip_initramfs || access("/sepolicy", R_OK) != 0) {
char partname[32];
struct device dev;
// Mount sysfs
mkdir("/sys", 0755);
xmount("sysfs", "/sys", "sysfs", 0, NULL);
char partname[32];
// Mount system
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
struct device dev;
setup_block(&dev, partname);
if (cmd.skip_initramfs) {
mkdir("/system_root", 0755);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
mkdir("/system_root", 0755);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
// Clone rootfs except /system
excl_list = (char *[]) { "system", NULL };
clone_dir(system_root, root);
close(system_root);
// Exclude system folder
excl_list = (char *[]) { "system", NULL };
clone_dir(system_root, root);
mkdir("/system", 0755);
xmount("/system_root/system", "/system", NULL, MS_BIND, NULL);
mkdir("/system", 0755);
xmount("/system_root/system", "/system", NULL, MS_BIND, NULL);
} else {
xmount(dev.path, "/system", "ext4", MS_RDONLY, NULL);
}
// Mount vendor
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
// We need to mount independent vendor partition
if (setup_block(&dev, partname) == 0)
xmount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
close(system_root);
} else {
if (access("/ramdisk.cpio.xz", R_OK) == 0) {
// High compression mode
void *addr;
size_t size;
mmap_ro("/ramdisk.cpio.xz", &addr, &size);
int fd = creat("/ramdisk.cpio", 0);
unxz(addr, size, fd);
munmap(addr, size);
close(fd);
struct vector v;
vec_init(&v);
parse_cpio(&v, "/ramdisk.cpio");
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
chdir("/");
cpio_extract_all(&v);
cpio_vec_destroy(&v);
} else {
// Revert original init binary
unlink("/init");
link("/.backup/init", "/init");
}
}
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
/* *************
* Patch rootfs
* *************/
// Only patch rootfs if not intended to run in recovery
if (access("/etc/recovery.fstab", F_OK) != 0) {
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
mv_dir(overlay, root);
close(overlay);
rmdir("/overlay");
patch_ramdisk(root);
if (patch_sepolicy()) {
/* Non skip_initramfs devices using separate sepolicy
* Mount /system and try to load again */
xmount("sysfs", "/sys", "sysfs", 0, NULL);
struct device dev;
setup_block(&dev, "system");
xmount(dev.path, "/system", "ext4", MS_RDONLY, NULL);
// We need to mount independent vendor partition
if (setup_block(&dev, "vendor") == 0)
xmount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
patch_ramdisk();
patch_sepolicy();
patch_sepolicy();
umount("/system");
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
if (fork_dont_care() == 0) {
strcpy(argv[0], "magiskinit");
close(overlay);
close(root);
magisk_init_daemon();
}
}
// Clean up
close(overlay);
close(root);
if (!cmd.skip_initramfs)
umount("/system");
umount("/vendor");
rmdir("/overlay");
// Finally, give control back!
execv("/init", argv);

155
native/jni/core/socket.c Normal file
View File

@@ -0,0 +1,155 @@
/* socket.c - All socket related operations
*/
#include <fcntl.h>
#include "daemon.h"
#include "logging.h"
#include "utils.h"
#include "magisk.h"
char socket_name[] = SOCKET_NAME;
/* Setup the address and return socket fd */
int setup_socket(struct sockaddr_un *sun) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_LOCAL;
sun->sun_path[0] = '\0';
memcpy(sun->sun_path + 1, socket_name, sizeof(SOCKET_NAME));
return fd;
}
/*
* Receive a file descriptor from a Unix socket.
* Contributed by @mkasick
*
* Returns the file descriptor on success, or -1 if a file
* descriptor was not actually included in the message
*
* On error the function terminates by calling exit(-1)
*/
int recv_fd(int sockfd) {
// Need to receive data from the message, otherwise don't care about it.
char iovbuf;
struct iovec iov = {
.iov_base = &iovbuf,
.iov_len = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
.msg_controllen = sizeof(cmsgbuf),
};
xrecvmsg(sockfd, &msg, MSG_WAITALL);
// Was a control message actually sent?
switch (msg.msg_controllen) {
case 0:
// No, so the file descriptor was closed and won't be used.
return -1;
case sizeof(cmsgbuf):
// Yes, grab the file descriptor from it.
break;
default:
goto error;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL ||
cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
error:
LOGE("unable to read fd");
exit(-1);
}
return *(int *)CMSG_DATA(cmsg);
}
/*
* Send a file descriptor through a Unix socket.
* Contributed by @mkasick
*
* On error the function terminates by calling exit(-1)
*
* fd may be -1, in which case the dummy data is sent,
* but no control message with the FD is sent.
*/
void send_fd(int sockfd, int fd) {
// Need to send some data in the message, this will do.
struct iovec iov = {
.iov_base = "",
.iov_len = 1,
};
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
if (fd != -1) {
// Is the file descriptor actually open?
if (fcntl(fd, F_GETFD) == -1) {
if (errno != EBADF) {
PLOGE("unable to send fd");
}
// It's closed, don't send a control message or sendmsg will EBADF.
} else {
// It's open, send the file descriptor in a control message.
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
}
}
xsendmsg(sockfd, &msg, 0);
}
int read_int(int fd) {
int val;
xxread(fd, &val, sizeof(int));
return val;
}
void write_int(int fd, int val) {
if (fd < 0) return;
xwrite(fd, &val, sizeof(int));
}
char* read_string(int fd) {
int len = read_int(fd);
if (len > PATH_MAX || len < 0) {
LOGE("invalid string length %d", len);
exit(1);
}
char* val = xmalloc(sizeof(char) * (len + 1));
xxread(fd, val, len);
val[len] = '\0';
return val;
}
void write_string(int fd, const char* val) {
if (fd < 0) return;
int len = strlen(val);
write_int(fd, len);
xwrite(fd, val, len);
}

View File

@@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir)
# libsqlite.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libsqlite
LOCAL_C_INCLUDES := jni/external/include
LOCAL_C_INCLUDES := $(EXT_PATH)/include
LOCAL_SRC_FILES := stubs/sqlite3_stub.c
include $(BUILD_SHARED_LIBRARY)
@@ -14,6 +14,20 @@ LOCAL_C_INCLUDES := $(LIBSELINUX)
LOCAL_SRC_FILES := stubs/selinux_stub.c
include $(BUILD_SHARED_LIBRARY)
# libmincrypt.a
include $(CLEAR_VARS)
LOCAL_MODULE:= libmincrypt
LOCAL_C_INCLUDES := $(EXT_PATH)/include
LOCAL_SRC_FILES := \
mincrypt/dsa_sig.c \
mincrypt/p256.c \
mincrypt/p256_ec.c \
mincrypt/p256_ecdsa.c \
mincrypt/rsa.c \
mincrypt/sha.c \
mincrypt/sha256.c
include $(BUILD_STATIC_LIBRARY)
# libfdt.a
include $(CLEAR_VARS)
LOCAL_MODULE:= libfdt

1
native/jni/external/busybox vendored Submodule

1
native/jni/external/dtc vendored Submodule

Submodule native/jni/external/dtc added at e54388015a

View File

@@ -0,0 +1,43 @@
/*
* 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.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
#include "mincrypt/p256.h"
#ifdef __cplusplus
extern "C" {
#endif
// Returns 0 if input sig is not a valid ASN.1 sequence
int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ */

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2007 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 SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_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 // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_

View File

@@ -0,0 +1,162 @@
/*
* 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.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
// Collection of routines manipulating 256 bit unsigned integers.
// Just enough to implement ecdsa-p256 and related algorithms.
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define P256_BITSPERDIGIT 32
#define P256_NDIGITS 8
#define P256_NBYTES 32
typedef int p256_err;
typedef uint32_t p256_digit;
typedef int32_t p256_sdigit;
typedef uint64_t p256_ddigit;
typedef int64_t p256_sddigit;
// Defining p256_int as struct to leverage struct assigment.
typedef struct {
p256_digit a[P256_NDIGITS];
} p256_int;
extern const p256_int SECP256r1_n; // Curve order
extern const p256_int SECP256r1_p; // Curve prime
extern const p256_int SECP256r1_b; // Curve param
// Initialize a p256_int to zero.
void p256_init(p256_int* a);
// Clear a p256_int to zero.
void p256_clear(p256_int* a);
// Return bit. Index 0 is least significant.
int p256_get_bit(const p256_int* a, int index);
// b := a % MOD
void p256_mod(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// c := a * (top_b | b) % MOD
void p256_modmul(
const p256_int* MOD,
const p256_int* a,
const p256_digit top_b,
const p256_int* b,
p256_int* c);
// b := 1 / a % MOD
// MOD best be SECP256r1_n
void p256_modinv(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// b := 1 / a % MOD
// MOD best be SECP256r1_n
// Faster than p256_modinv()
void p256_modinv_vartime(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// b := a << (n % P256_BITSPERDIGIT)
// Returns the bits shifted out of most significant digit.
p256_digit p256_shl(const p256_int* a, int n, p256_int* b);
// b := a >> (n % P256_BITSPERDIGIT)
void p256_shr(const p256_int* a, int n, p256_int* b);
int p256_is_zero(const p256_int* a);
int p256_is_odd(const p256_int* a);
int p256_is_even(const p256_int* a);
// Returns -1, 0 or 1.
int p256_cmp(const p256_int* a, const p256_int *b);
// c: = a - b
// Returns -1 on borrow.
int p256_sub(const p256_int* a, const p256_int* b, p256_int* c);
// c := a + b
// Returns 1 on carry.
int p256_add(const p256_int* a, const p256_int* b, p256_int* c);
// c := a + (single digit)b
// Returns carry 1 on carry.
int p256_add_d(const p256_int* a, p256_digit b, p256_int* c);
// ec routines.
// {out_x,out_y} := nG
void p256_base_point_mul(const p256_int *n,
p256_int *out_x,
p256_int *out_y);
// {out_x,out_y} := n{in_x,in_y}
void p256_point_mul(const p256_int *n,
const p256_int *in_x,
const p256_int *in_y,
p256_int *out_x,
p256_int *out_y);
// {out_x,out_y} := n1G + n2{in_x,in_y}
void p256_points_mul_vartime(
const p256_int *n1, const p256_int *n2,
const p256_int *in_x, const p256_int *in_y,
p256_int *out_x, p256_int *out_y);
// Return whether point {x,y} is on curve.
int p256_is_valid_point(const p256_int* x, const p256_int* y);
// Outputs big-endian binary form. No leading zero skips.
void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
// Reads from big-endian binary form,
// thus pre-pad with leading zeros if short.
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
#define P256_DIGITS(x) ((x)->a)
#define P256_DIGIT(x,y) ((x)->a[y])
#define P256_ZERO {{0}}
#define P256_ONE {{1}}
#ifdef __cplusplus
}
#endif
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_

View File

@@ -0,0 +1,53 @@
/*
* 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.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
// Using current directory as relative include path here since
// this code typically gets lifted into a variety of build systems
// and directory structures.
#include "p256.h"
#ifdef __cplusplus
extern "C" {
#endif
// Returns 0 if {r,s} is not a signature on message for
// public key {key_x,key_y}.
//
// Note: message is a p256_int.
// Convert from a binary string using p256_from_bin().
int p256_ecdsa_verify(const p256_int* key_x,
const p256_int* key_y,
const p256_int* message,
const p256_int* r, const p256_int* s);
#ifdef __cplusplus
}
#endif
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_

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 SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_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 // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005 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 SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_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 // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2011 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 SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_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 // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_

1
native/jni/external/lz4 vendored Submodule

Submodule native/jni/external/lz4 added at dfed9fa1d7

126
native/jni/external/mincrypt/dsa_sig.c vendored Normal file
View File

@@ -0,0 +1,126 @@
/*
* 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.
*/
#include <string.h>
#include "mincrypt/dsa_sig.h"
#include "mincrypt/p256.h"
/**
* Trims off the leading zero bytes and copy it to a buffer aligning it to the end.
*/
static inline int trim_to_p256_bytes(unsigned char dst[P256_NBYTES], unsigned char *src,
int src_len) {
int dst_offset;
while (*src == '\0' && src_len > 0) {
src++;
src_len--;
}
if (src_len > P256_NBYTES || src_len < 1) {
return 0;
}
dst_offset = P256_NBYTES - src_len;
memset(dst, 0, dst_offset);
memcpy(dst + dst_offset, src, src_len);
return 1;
}
/**
* Unpacks the ASN.1 DSA signature sequence.
*/
int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int) {
/*
* Structure is:
* 0x30 0xNN SEQUENCE + s_length
* 0x02 0xNN INTEGER + r_length
* 0xAA 0xBB .. r_length bytes of "r" (offset 4)
* 0x02 0xNN INTEGER + s_length
* 0xMM 0xNN .. s_length bytes of "s" (offset 6 + r_len)
*/
int seq_len;
unsigned char r_bytes[P256_NBYTES];
unsigned char s_bytes[P256_NBYTES];
int r_len;
int s_len;
memset(r_bytes, 0, sizeof(r_bytes));
memset(s_bytes, 0, sizeof(s_bytes));
/*
* Must have at least:
* 2 bytes sequence header and length
* 2 bytes R integer header and length
* 1 byte of R
* 2 bytes S integer header and length
* 1 byte of S
*
* 8 bytes total
*/
if (sig_len < 8 || sig[0] != 0x30 || sig[2] != 0x02) {
return 0;
}
seq_len = sig[1];
if ((seq_len <= 0) || (seq_len + 2 != sig_len)) {
return 0;
}
r_len = sig[3];
/*
* Must have at least:
* 2 bytes for R header and length
* 2 bytes S integer header and length
* 1 byte of S
*/
if ((r_len < 1) || (r_len > seq_len - 5) || (sig[4 + r_len] != 0x02)) {
return 0;
}
s_len = sig[5 + r_len];
/**
* Must have:
* 2 bytes for R header and length
* r_len bytes for R
* 2 bytes S integer header and length
*/
if ((s_len < 1) || (s_len != seq_len - 4 - r_len)) {
return 0;
}
/*
* ASN.1 encoded integers are zero-padded for positive integers. Make sure we have
* a correctly-sized buffer and that the resulting integer isn't too large.
*/
if (!trim_to_p256_bytes(r_bytes, &sig[4], r_len)
|| !trim_to_p256_bytes(s_bytes, &sig[6 + r_len], s_len)) {
return 0;
}
p256_from_bin(r_bytes, r_int);
p256_from_bin(s_bytes, s_int);
return 1;
}

373
native/jni/external/mincrypt/p256.c vendored Normal file
View File

@@ -0,0 +1,373 @@
/*
* 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.
*/
// This is an implementation of the P256 elliptic curve group. It's written to
// be portable 32-bit, although it's still constant-time.
//
// WARNING: Implementing these functions in a constant-time manner is far from
// obvious. Be careful when touching this code.
//
// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "mincrypt/p256.h"
const p256_int SECP256r1_n = // curve order
{{0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0, -1}};
const p256_int SECP256r1_p = // curve field size
{{-1, -1, -1, 0, 0, 0, 1, -1 }};
const p256_int SECP256r1_b = // curve b
{{0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0,
0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8}};
void p256_init(p256_int* a) {
memset(a, 0, sizeof(*a));
}
void p256_clear(p256_int* a) { p256_init(a); }
int p256_get_bit(const p256_int* scalar, int bit) {
return (P256_DIGIT(scalar, bit / P256_BITSPERDIGIT)
>> (bit & (P256_BITSPERDIGIT - 1))) & 1;
}
int p256_is_zero(const p256_int* a) {
int i, result = 0;
for (i = 0; i < P256_NDIGITS; ++i) result |= P256_DIGIT(a, i);
return !result;
}
// top, c[] += a[] * b
// Returns new top
static p256_digit mulAdd(const p256_int* a,
p256_digit b,
p256_digit top,
p256_digit* c) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += (p256_ddigit)P256_DIGIT(a, i) * b;
*c++ = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)carry;
}
// top, c[] -= top_a, a[]
static p256_digit subTop(p256_digit top_a,
const p256_digit* a,
p256_digit top_c,
p256_digit* c) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= *a++;
*c++ = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
borrow += top_c;
borrow -= top_a;
top_c = (p256_digit)borrow;
assert((borrow >> P256_BITSPERDIGIT) == 0);
return top_c;
}
// top, c[] -= MOD[] & mask (0 or -1)
// returns new top.
static p256_digit subM(const p256_int* MOD,
p256_digit top,
p256_digit* c,
p256_digit mask) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)borrow;
}
// top, c[] += MOD[] & mask (0 or -1)
// returns new top.
static p256_digit addM(const p256_int* MOD,
p256_digit top,
p256_digit* c,
p256_digit mask) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)carry;
}
// c = a * b mod MOD. c can be a and/or b.
void p256_modmul(const p256_int* MOD,
const p256_int* a,
const p256_digit top_b,
const p256_int* b,
p256_int* c) {
p256_digit tmp[P256_NDIGITS * 2 + 1] = { 0 };
p256_digit top = 0;
int i;
// Multiply/add into tmp.
for (i = 0; i < P256_NDIGITS; ++i) {
if (i) tmp[i + P256_NDIGITS - 1] = top;
top = mulAdd(a, P256_DIGIT(b, i), 0, tmp + i);
}
// Multiply/add top digit
tmp[i + P256_NDIGITS - 1] = top;
top = mulAdd(a, top_b, 0, tmp + i);
// Reduce tmp, digit by digit.
for (; i >= 0; --i) {
p256_digit reducer[P256_NDIGITS] = { 0 };
p256_digit top_reducer;
// top can be any value at this point.
// Guestimate reducer as top * MOD, since msw of MOD is -1.
top_reducer = mulAdd(MOD, top, 0, reducer);
// Subtract reducer from top | tmp.
top = subTop(top_reducer, reducer, top, tmp + i);
// top is now either 0 or 1. Make it 0, fixed-timing.
assert(top <= 1);
top = subM(MOD, top, tmp + i, ~(top - 1));
assert(top == 0);
// We have now reduced the top digit off tmp. Fetch new top digit.
top = tmp[i + P256_NDIGITS - 1];
}
// tmp might still be larger than MOD, yet same bit length.
// Make sure it is less, fixed-timing.
addM(MOD, 0, tmp, subM(MOD, 0, tmp, -1));
memcpy(c, tmp, P256_NBYTES);
}
int p256_is_odd(const p256_int* a) { return P256_DIGIT(a, 0) & 1; }
int p256_is_even(const p256_int* a) { return !(P256_DIGIT(a, 0) & 1); }
p256_digit p256_shl(const p256_int* a, int n, p256_int* b) {
int i;
p256_digit top = P256_DIGIT(a, P256_NDIGITS - 1);
n %= P256_BITSPERDIGIT;
for (i = P256_NDIGITS - 1; i > 0; --i) {
p256_digit accu = (P256_DIGIT(a, i) << n);
accu |= (P256_DIGIT(a, i - 1) >> (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) << n);
top = (p256_digit)((((p256_ddigit)top) << n) >> P256_BITSPERDIGIT);
return top;
}
void p256_shr(const p256_int* a, int n, p256_int* b) {
int i;
n %= P256_BITSPERDIGIT;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> n);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> n);
}
static void p256_shr1(const p256_int* a, int highbit, p256_int* b) {
int i;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> 1);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - 1));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> 1) |
(highbit << (P256_BITSPERDIGIT - 1));
}
// Return -1, 0, 1 for a < b, a == b or a > b respectively.
int p256_cmp(const p256_int* a, const p256_int* b) {
int i;
p256_sddigit borrow = 0;
p256_digit notzero = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i);
// Track whether any result digit is ever not zero.
// Relies on !!(non-zero) evaluating to 1, e.g., !!(-1) evaluating to 1.
notzero |= !!((p256_digit)borrow);
borrow >>= P256_BITSPERDIGIT;
}
return (int)borrow | notzero;
}
// c = a - b. Returns borrow: 0 or -1.
int p256_sub(const p256_int* a, const p256_int* b, p256_int* c) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i);
if (c) P256_DIGIT(c, i) = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
return (int)borrow;
}
// c = a + b. Returns carry: 0 or 1.
int p256_add(const p256_int* a, const p256_int* b, p256_int* c) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit)P256_DIGIT(a, i) + P256_DIGIT(b, i);
if (c) P256_DIGIT(c, i) = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return (int)carry;
}
// b = a + d. Returns carry, 0 or 1.
int p256_add_d(const p256_int* a, p256_digit d, p256_int* b) {
int i;
p256_ddigit carry = d;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit)P256_DIGIT(a, i);
if (b) P256_DIGIT(b, i) = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return (int)carry;
}
// b = 1/a mod MOD, binary euclid.
void p256_modinv_vartime(const p256_int* MOD,
const p256_int* a,
p256_int* b) {
p256_int R = P256_ZERO;
p256_int S = P256_ONE;
p256_int U = *MOD;
p256_int V = *a;
for (;;) {
if (p256_is_even(&U)) {
p256_shr1(&U, 0, &U);
if (p256_is_even(&R)) {
p256_shr1(&R, 0, &R);
} else {
// R = (R+MOD)/2
p256_shr1(&R, p256_add(&R, MOD, &R), &R);
}
} else if (p256_is_even(&V)) {
p256_shr1(&V, 0, &V);
if (p256_is_even(&S)) {
p256_shr1(&S, 0, &S);
} else {
// S = (S+MOD)/2
p256_shr1(&S, p256_add(&S, MOD, &S) , &S);
}
} else { // U,V both odd.
if (!p256_sub(&V, &U, NULL)) {
p256_sub(&V, &U, &V);
if (p256_sub(&S, &R, &S)) p256_add(&S, MOD, &S);
if (p256_is_zero(&V)) break; // done.
} else {
p256_sub(&U, &V, &U);
if (p256_sub(&R, &S, &R)) p256_add(&R, MOD, &R);
}
}
}
p256_mod(MOD, &R, b);
}
void p256_mod(const p256_int* MOD,
const p256_int* in,
p256_int* out) {
if (out != in) *out = *in;
addM(MOD, 0, P256_DIGITS(out), subM(MOD, 0, P256_DIGITS(out), -1));
}
// Verify y^2 == x^3 - 3x + b mod p
// and 0 < x < p and 0 < y < p
int p256_is_valid_point(const p256_int* x, const p256_int* y) {
p256_int y2, x3;
if (p256_cmp(&SECP256r1_p, x) <= 0 ||
p256_cmp(&SECP256r1_p, y) <= 0 ||
p256_is_zero(x) ||
p256_is_zero(y)) return 0;
p256_modmul(&SECP256r1_p, y, 0, y, &y2); // y^2
p256_modmul(&SECP256r1_p, x, 0, x, &x3); // x^2
p256_modmul(&SECP256r1_p, x, 0, &x3, &x3); // x^3
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - x
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 2x
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 3x
if (p256_add(&x3, &SECP256r1_b, &x3)) // x^3 - 3x + b
p256_sub(&x3, &SECP256r1_p, &x3);
return p256_cmp(&y2, &x3) == 0;
}
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
int i;
const uint8_t* p = &src[0];
for (i = P256_NDIGITS - 1; i >= 0; --i) {
P256_DIGIT(dst, i) =
(p[0] << 24) |
(p[1] << 16) |
(p[2] << 8) |
p[3];
p += 4;
}
}

1279
native/jni/external/mincrypt/p256_ec.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
* 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.
*/
#include <string.h>
#include "mincrypt/p256_ecdsa.h"
#include "mincrypt/p256.h"
int p256_ecdsa_verify(const p256_int* key_x, const p256_int* key_y,
const p256_int* message,
const p256_int* r, const p256_int* s) {
p256_int u, v;
// Check public key.
if (!p256_is_valid_point(key_x, key_y)) return 0;
// Check r and s are != 0 % n.
p256_mod(&SECP256r1_n, r, &u);
p256_mod(&SECP256r1_n, s, &v);
if (p256_is_zero(&u) || p256_is_zero(&v)) return 0;
p256_modinv_vartime(&SECP256r1_n, s, &v);
p256_modmul(&SECP256r1_n, message, 0, &v, &u); // message / s % n
p256_modmul(&SECP256r1_n, r, 0, &v, &v); // r / s % n
p256_points_mul_vartime(&u, &v,
key_x, key_y,
&u, &v);
p256_mod(&SECP256r1_n, &u, &u); // (x coord % p) % n
return p256_cmp(r, &u) == 0;
}

308
native/jni/external/mincrypt/rsa.c vendored Normal file
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
native/jni/external/mincrypt/sha.c vendored Normal file
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
native/jni/external/mincrypt/sha256.c vendored Normal file
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;
}

View File

@@ -11,32 +11,32 @@
extern int is_daemon_init, seperate_vendor;
// Commands require connecting to daemon
typedef enum {
enum {
DO_NOTHING = 0,
LAUNCH_MAGISKHIDE,
STOP_MAGISKHIDE,
ADD_HIDELIST,
RM_HIDELIST,
LS_HIDELIST,
SUPERUSER,
CHECK_VERSION,
CHECK_VERSION_CODE,
POST_FS,
POST_FS_DATA,
LATE_START,
TEST
} client_request;
LAUNCH_MAGISKHIDE,
STOP_MAGISKHIDE,
ADD_HIDELIST,
RM_HIDELIST,
LS_HIDELIST
};
// Return codes for daemon
typedef enum {
enum {
DAEMON_ERROR = -1,
DAEMON_SUCCESS = 0,
ROOT_REQUIRED,
LOGD_DISABLED,
HIDE_IS_ENABLED,
HIDE_NOT_ENABLED,
HIDE_ITEM_EXIST,
HIDE_ITEM_NOT_EXIST,
} daemon_response;
};
// daemon.c

View File

@@ -58,6 +58,7 @@ struct log_listener {
};
extern struct log_listener log_events[];
extern int logd;
void monitor_logs();
void start_debug_full_log();

View File

@@ -7,7 +7,7 @@
#include "logging.h"
#define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK"
#define REQUESTOR_DAEMON_PATH "\0MAGISK"
#define SOCKET_NAME "d30138f2310a9fb9c54a3e0c21f58591"
#ifndef ARG_MAX
#define ARG_MAX 4096
@@ -55,6 +55,7 @@ extern char *argv0; /* For changing process name */
#define init_applet ((char *[]) { "magiskpolicy", "supolicy", NULL })
extern int (*applet_main[]) (int, char *[]), (*init_applet_main[]) (int, char *[]);
extern char socket_name[]; /* Workaround compiler bug pre NDK r13 */
int create_links(const char *bin, const char *path);

View File

@@ -90,9 +90,13 @@ void get_client_cred(int fd, struct ucred *cred);
int switch_mnt_ns(int pid);
int fork_dont_care();
void wait_till_exists(const char *target);
void gen_rand_str(char *buf, int len);
// file.c
#define align(p, a) (((p) + (a) - 1) / (a) * (a))
#define align_off(p, a) (align(p, a) - (p))
extern char **excl_list;
struct file_attr {
@@ -108,6 +112,7 @@ void frm_rf(int dirfd);
void mv_f(const char *source, const char *destination);
void mv_dir(int src, int dest);
void cp_afc(const char *source, const char *destination);
void link_dir(int src, int dest);
void clone_dir(int src, int dest);
int getattr(const char *path, struct file_attr *a);
int getattrat(int dirfd, const char *pathname, struct file_attr *a);
@@ -125,8 +130,6 @@ void full_read(const char *filename, void **buf, size_t *size);
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size);
void stream_full_read(int fd, void **buf, size_t *size);
void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align, int out);
// img.c

View File

@@ -0,0 +1,431 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "bootimg.h"
#include "magiskboot.h"
#include "utils.h"
#include "logging.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
#define INSUF_BLOCK_RET 2
#define CHROMEOS_RET 3
#define ELF32_RET 4
#define ELF64_RET 5
// Macros to determine header on-the-go
#define lheader(b, e, o) \
((b)->flags & PXA_FLAG) ? \
(((struct pxa_boot_img_hdr*) (b)->hdr)->e o) : \
(((struct boot_img_hdr*) (b)->hdr)->e o)
#define header(b, e) (lheader(b, e,))
static void dump(void *buf, size_t size, const char *filename) {
if (size == 0)
return;
int fd = creat(filename, 0644);
xwrite(fd, buf, size);
close(fd);
}
static size_t restore(const char *filename, int fd) {
int ifd = xopen(filename, O_RDONLY);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
xsendfile(fd, ifd, NULL, size);
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
static void print_hdr(const boot_img *boot) {
fprintf(stderr, "KERNEL [%u]\n", header(boot, kernel_size));
fprintf(stderr, "RAMDISK [%u]\n", header(boot, ramdisk_size));
fprintf(stderr, "SECOND [%u]\n", header(boot, second_size));
fprintf(stderr, "EXTRA [%u]\n", header(boot, extra_size));
fprintf(stderr, "PAGESIZE [%u]\n", header(boot, page_size));
if (!(boot->flags & PXA_FLAG)) {
uint32_t os_version = ((boot_img_hdr*) boot->hdr)->os_version;
if (os_version) {
int a,b,c,y,m = 0;
int version, patch_level;
version = os_version >> 11;
patch_level = os_version & 0x7ff;
a = (version >> 14) & 0x7f;
b = (version >> 7) & 0x7f;
c = version & 0x7f;
fprintf(stderr, "OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (patch_level >> 4) + 2000;
m = patch_level & 0xf;
fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m);
}
}
fprintf(stderr, "NAME [%s]\n", header(boot, name));
fprintf(stderr, "CMDLINE [%s]\n", header(boot, cmdline));
fprintf(stderr, "CHECKSUM [");
for (int i = 0; i < ((boot->flags & SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE); ++i)
fprintf(stderr, "%02x", header(boot, id)[i]);
fprintf(stderr, "]\n");
}
static void clean_boot(boot_img *boot) {
munmap(boot->map_addr, boot->map_size);
free(boot->hdr);
free(boot->k_hdr);
free(boot->r_hdr);
free(boot->b_hdr);
memset(boot, 0, sizeof(*boot));
}
#define pos_align() pos = align(pos, header(boot, page_size))
int parse_img(const char *image, boot_img *boot) {
memset(boot, 0, sizeof(*boot));
int is_blk = mmap_ro(image, &boot->map_addr, &boot->map_size);
// Parse image
fprintf(stderr, "Parsing boot image: [%s]\n", image);
for (void *head = boot->map_addr; head < boot->map_addr + boot->map_size; ++head) {
size_t pos = 0;
switch (check_fmt(head, boot->map_size)) {
case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing
boot->flags |= CHROMEOS_FLAG;
continue;
case DHTB:
boot->flags |= DHTB_FLAG;
boot->flags |= SEANDROID_FLAG;
fprintf(stderr, "DHTB_HDR\n");
continue;
case ELF32:
exit(ELF32_RET);
case ELF64:
exit(ELF64_RET);
case BLOB:
boot->flags |= BLOB_FLAG;
fprintf(stderr, "TEGRA_BLOB\n");
boot->b_hdr = malloc(sizeof(blob_hdr));
memcpy(boot->b_hdr, head, sizeof(blob_hdr));
continue;
case AOSP:
// Read the header
if (((boot_img_hdr*) head)->page_size >= 0x02000000) {
boot->flags |= PXA_FLAG;
fprintf(stderr, "PXA_BOOT_HDR\n");
boot->hdr = malloc(sizeof(pxa_boot_img_hdr));
memcpy(boot->hdr, head, sizeof(pxa_boot_img_hdr));
} else if (memcmp(((boot_img_hdr*) head)->cmdline, NOOKHD_MAGIC, 12) == 0
|| memcmp(((boot_img_hdr*) head)->cmdline, NOOKHD_NEW_MAGIC, 26) == 0) {
boot->flags |= NOOKHD_FLAG;
fprintf(stderr, "NOOKHD_GREEN_LOADER\n");
head += NOOKHD_PRE_HEADER_SZ - 1;
continue;
} else if (memcmp(((boot_img_hdr*) head)->name, ACCLAIM_MAGIC, 10) == 0) {
boot->flags |= ACCLAIM_FLAG;
fprintf(stderr, "ACCLAIM_BAUWKSBOOT\n");
head += ACCLAIM_PRE_HEADER_SZ - 1;
continue;
} else {
boot->hdr = malloc(sizeof(boot_img_hdr));
memcpy(boot->hdr, head, sizeof(boot_img_hdr));
}
pos += header(boot, page_size);
for (int i = SHA_DIGEST_SIZE; i < SHA256_DIGEST_SIZE; ++i) {
if (header(boot, id)[i]) {
boot->flags |= SHA256_FLAG;
break;
}
}
print_hdr(boot);
boot->kernel = head + pos;
pos += header(boot, kernel_size);
pos_align();
boot->ramdisk = head + pos;
pos += header(boot, ramdisk_size);
pos_align();
boot->second = head + pos;
pos += header(boot, second_size);
pos_align();
boot->extra = head + pos;
pos += header(boot, extra_size);
pos_align();
if (pos < boot->map_size) {
boot->tail = head + pos;
boot->tail_size = boot->map_size - (boot->tail - boot->map_addr);
}
// Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (boot->tail_size >= 16 && memcmp(boot->tail, SEANDROID_MAGIC, 16) == 0) {
boot->flags |= SEANDROID_FLAG;
} else if (boot->tail_size >= 16 && memcmp(boot->tail, LG_BUMP_MAGIC, 16) == 0) {
boot->flags |= LG_BUMP_FLAG;
}
// Search for dtb in kernel
for (uint32_t i = 0; i < header(boot, kernel_size); ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i;
boot->dt_size = header(boot, kernel_size) - i;
lheader(boot, kernel_size, = i);
fprintf(stderr, "DTB [%u]\n", boot->dt_size);
break;
}
}
boot->k_fmt = check_fmt(boot->kernel, header(boot, kernel_size));
boot->r_fmt = check_fmt(boot->ramdisk, header(boot, ramdisk_size));
// Check MTK
if (boot->k_fmt == MTK) {
fprintf(stderr, "MTK_KERNEL_HDR\n");
boot->flags |= MTK_KERNEL;
boot->k_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->k_hdr, boot->kernel, sizeof(mtk_hdr));
fprintf(stderr, "KERNEL [%u]\n", boot->k_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->k_hdr->name);
boot->kernel += 512;
lheader(boot, kernel_size, -= 512);
boot->k_fmt = check_fmt(boot->kernel, header(boot, kernel_size));
}
if (boot->r_fmt == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR\n");
boot->flags |= MTK_RAMDISK;
boot->r_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->r_hdr, boot->ramdisk, sizeof(mtk_hdr));
fprintf(stderr, "RAMDISK [%u]\n", boot->r_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->r_hdr->name);
boot->ramdisk += 512;
lheader(boot, ramdisk_size, -= 512);
boot->r_fmt = check_fmt(boot->ramdisk, header(boot, ramdisk_size));
}
char fmt[16];
get_fmt_name(boot->k_fmt, fmt);
fprintf(stderr, "KERNEL_FMT [%s]\n", fmt);
get_fmt_name(boot->r_fmt, fmt);
fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt);
return boot->flags & CHROMEOS_FLAG ? CHROMEOS_RET :
((is_blk && boot->tail_size < 500 * 1024) ? INSUF_BLOCK_RET : 0);
default:
continue;
}
}
LOGE("No boot image magic found!\n");
}
int unpack(const char *image) {
boot_img boot;
int ret = parse_img(image, &boot);
int fd;
// Dump kernel
if (COMPRESSED(boot.k_fmt)) {
fd = creat(KERNEL_FILE, 0644);
decomp(boot.k_fmt, fd, boot.kernel, header(&boot, kernel_size));
close(fd);
} else {
dump(boot.kernel, header(&boot, kernel_size), KERNEL_FILE);
}
// Dump dtb
dump(boot.dtb, boot.dt_size, DTB_FILE);
// Dump ramdisk
if (COMPRESSED(boot.r_fmt)) {
fd = creat(RAMDISK_FILE, 0644);
decomp(boot.r_fmt, fd, boot.ramdisk, header(&boot, ramdisk_size));
close(fd);
} else {
dump(boot.ramdisk, header(&boot, ramdisk_size), RAMDISK_FILE);
}
// Dump second
dump(boot.second, header(&boot, second_size), SECOND_FILE);
// Dump extra
dump(boot.extra, header(&boot, extra_size), EXTRA_FILE);
clean_boot(&boot);
return ret;
}
#define file_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR) - header_off, header(&boot, page_size)))
void repack(const char* orig_image, const char* out_image) {
boot_img boot;
off_t header_off, kernel_off, ramdisk_off, second_off, extra_off;
// Parse original image
parse_img(orig_image, &boot);
// Reset all sizes
lheader(&boot, kernel_size, = 0);
lheader(&boot, ramdisk_size, = 0);
lheader(&boot, second_size, = 0);
lheader(&boot, extra_size, = 0);
boot.dt_size = 0;
fprintf(stderr, "Repack to boot image: [%s]\n", out_image);
// Create new image
int fd = creat(out_image, 0644);
if (boot.flags & DHTB_FLAG) {
// Skip DHTB header
write_zero(fd, 512);
} else if (boot.flags & BLOB_FLAG) {
// Skip blob header
write_zero(fd, sizeof(blob_hdr));
} else if (boot.flags & NOOKHD_FLAG) {
restore_buf(fd, boot.map_addr, NOOKHD_PRE_HEADER_SZ);
} else if (boot.flags & ACCLAIM_FLAG) {
restore_buf(fd, boot.map_addr, ACCLAIM_PRE_HEADER_SZ);
}
// Skip a page for header
header_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, header(&boot, page_size));
// kernel
kernel_off = lseek(fd, 0, SEEK_CUR);
if (boot.flags & MTK_KERNEL) {
// Skip MTK header
write_zero(fd, 512);
}
if (access(KERNEL_FILE, R_OK) == 0) {
if (COMPRESSED(boot.k_fmt)) {
size_t raw_size;
void *kernel_raw;
mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size);
lheader(&boot, kernel_size, = comp(boot.k_fmt, fd, kernel_raw, raw_size));
munmap(kernel_raw, raw_size);
} else {
lheader(&boot, kernel_size, = restore(KERNEL_FILE, fd));
}
}
// dtb
if (access(DTB_FILE, R_OK) == 0) {
lheader(&boot, kernel_size, += restore(DTB_FILE, fd));
}
file_align();
// ramdisk
ramdisk_off = lseek(fd, 0, SEEK_CUR);
if (boot.flags & MTK_RAMDISK) {
// Skip MTK header
write_zero(fd, 512);
}
if (access(RAMDISK_FILE, R_OK) == 0) {
if (COMPRESSED(boot.r_fmt)) {
size_t cpio_size;
void *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
lheader(&boot, ramdisk_size, = comp(boot.r_fmt, fd, cpio, cpio_size));
munmap(cpio, cpio_size);
} else {
lheader(&boot, ramdisk_size, = restore(RAMDISK_FILE, fd));
}
file_align();
}
// second
second_off = lseek(fd, 0, SEEK_CUR);
if (access(SECOND_FILE, R_OK) == 0) {
lheader(&boot, second_size, = restore(SECOND_FILE, fd));
file_align();
}
// extra
extra_off = lseek(fd, 0, SEEK_CUR);
if (access(EXTRA_FILE, R_OK) == 0) {
lheader(&boot, extra_size, = restore(EXTRA_FILE, fd));
file_align();
}
// Append tail info
if (boot.flags & SEANDROID_FLAG) {
restore_buf(fd, SEANDROID_MAGIC "\xFF\xFF\xFF\xFF", 20);
}
if (boot.flags & LG_BUMP_FLAG) {
restore_buf(fd, LG_BUMP_MAGIC, 16);
}
close(fd);
// Map output image as rw
munmap(boot.map_addr, boot.map_size);
mmap_rw(out_image, &boot.map_addr, &boot.map_size);
// MTK headers
if (boot.flags & MTK_KERNEL) {
boot.k_hdr->size = header(&boot, kernel_size);
lheader(&boot, kernel_size, += 512);
memcpy(boot.map_addr + kernel_off, boot.k_hdr, sizeof(mtk_hdr));
}
if (boot.flags & MTK_RAMDISK) {
boot.r_hdr->size = header(&boot, ramdisk_size);
lheader(&boot, ramdisk_size, += 512);
memcpy(boot.map_addr + ramdisk_off, boot.r_hdr, sizeof(mtk_hdr));
}
// Update checksum
HASH_CTX ctx;
(boot.flags & SHA256_FLAG) ? SHA256_init(&ctx) : SHA_init(&ctx);
uint32_t size = header(&boot, kernel_size);
HASH_update(&ctx, boot.map_addr + kernel_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, ramdisk_size);
HASH_update(&ctx, boot.map_addr + ramdisk_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, second_size);
HASH_update(&ctx, boot.map_addr + second_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, extra_size);
if (size) {
HASH_update(&ctx, boot.map_addr + extra_off, size);
HASH_update(&ctx, &size, sizeof(size));
}
memset(header(&boot, id), 0, 32);
memcpy(header(&boot, id), HASH_final(&ctx),
(boot.flags & SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE);
// Print new image info
print_hdr(&boot);
// Main header
memcpy(boot.map_addr + header_off, boot.hdr,
(boot.flags & PXA_FLAG) ? sizeof(pxa_boot_img_hdr) : sizeof(boot_img_hdr));
if (boot.flags & DHTB_FLAG) {
// DHTB header
dhtb_hdr *hdr = boot.map_addr;
memcpy(hdr, DHTB_MAGIC, 8);
hdr->size = boot.map_size - 512;
SHA256_hash(boot.map_addr + 512, hdr->size, hdr->checksum);
} else if (boot.flags & BLOB_FLAG) {
// Blob headers
boot.b_hdr->size = boot.map_size - sizeof(blob_hdr);
memcpy(boot.map_addr, boot.b_hdr, sizeof(blob_hdr));
}
clean_boot(&boot);
}

View File

@@ -0,0 +1,169 @@
#include <stdint.h>
#include "format.h"
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t extra_size; /* extra blob size in bytes */
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
* os_version = ver << 11 | lvl */
uint32_t os_version;
char name[16]; /* asciiz product name */
char cmdline[512];
char id[32]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) boot_img_hdr ;
typedef struct pxa_boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t extra_size; /* extra blob size in bytes */
uint32_t unknown; /* unknown value */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
char name[24]; /* asciiz product name */
char cmdline[512];
char id[32]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) pxa_boot_img_hdr;
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
** | extra blob | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
** p = (extra_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
typedef struct mtk_hdr {
uint32_t magic; /* MTK magic */
uint32_t size; /* Size of the content */
char name[32]; /* The type of the header */
} __attribute__((packed)) mtk_hdr;
typedef struct dhtb_hdr {
char magic[8]; /* DHTB magic */
char checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
} __attribute__((packed)) dhtb_hdr;
typedef struct blob_hdr {
char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */
uint32_t datalen; /* 0x00000000 */
uint32_t signature; /* 0x00000000 */
char magic[16]; /* "MSM-RADIO-UPDATE" */
uint32_t hdr_version; /* 0x00010000 */
uint32_t hdr_size; /* Size of header */
uint32_t part_offset; /* Same as size */
uint32_t num_parts; /* Number of partitions */
uint32_t unknown[7]; /* All 0x00000000 */
char name[4]; /* Name of partition */
uint32_t offset; /* offset in blob where this partition starts */
uint32_t size; /* Size of data */
uint32_t version; /* 0x00000001 */
} __attribute__((packed)) blob_hdr;
// Flags
#define MTK_KERNEL 0x0001
#define MTK_RAMDISK 0x0002
#define CHROMEOS_FLAG 0x0004
#define PXA_FLAG 0x0008
#define DHTB_FLAG 0x0010
#define SEANDROID_FLAG 0x0020
#define LG_BUMP_FLAG 0x0040
#define SHA256_FLAG 0x0080
#define BLOB_FLAG 0x0100
#define NOOKHD_FLAG 0x0200
#define ACCLAIM_FLAG 0x0400
typedef struct boot_img {
// Memory map of the whole image
void *map_addr;
size_t map_size;
// Headers
void *hdr; /* Either boot_img_hdr or pxa_boot_img_hdr */
mtk_hdr *k_hdr; /* MTK kernel header */
mtk_hdr *r_hdr; /* MTK ramdisk header */
blob_hdr *b_hdr; /* Tegra blob header */
// Flags to indicate the state of current boot image
uint16_t flags;
// The format of kernel and ramdisk
format_t k_fmt;
format_t r_fmt;
// Pointer to dtb that is appended after kernel
void *dtb;
uint32_t dt_size;
// Pointer to end of image
void *tail;
size_t tail_size;
// Pointers to blocks defined in header
void *kernel;
void *ramdisk;
void *second;
void *extra;
} boot_img;
#endif

View File

@@ -343,7 +343,7 @@ done:
return total;
}
long long decomp(file_t type, int to, const void *from, size_t size) {
long long decomp(format_t type, int to, const void *from, size_t size) {
switch (type) {
case GZIP:
return gzip(0, to, from, size);
@@ -363,7 +363,7 @@ long long decomp(file_t type, int to, const void *from, size_t size) {
}
}
long long comp(file_t type, int to, const void *from, size_t size) {
long long comp(format_t type, int to, const void *from, size_t size) {
switch (type) {
case GZIP:
return gzip(1, to, from, size);
@@ -395,7 +395,7 @@ void decomp_file(char *from, const char *to) {
stream_full_read(STDIN_FILENO, &file, &size);
else
mmap_ro(from, &file, &size);
file_t type = check_type(file);
format_t type = check_fmt(file, size);
char *ext;
ext = strrchr(from, '.');
if (to == NULL)
@@ -453,7 +453,7 @@ void decomp_file(char *from, const char *to) {
}
void comp_file(const char *method, const char *from, const char *to) {
file_t type;
format_t type;
char *ext, dest[PATH_MAX];
if (strcmp(method, "gzip") == 0) {
type = GZIP;

View File

@@ -1,44 +1,50 @@
#include <string.h>
#include "bootimg.h"
#include "types.h"
#include "format.h"
file_t check_type(const void *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, 8) == 0) {
#define MATCH(s) (len >= (sizeof(s) - 1) && memcmp(buf, s, sizeof(s) - 1) == 0)
format_t check_fmt(const void *buf, size_t len) {
if (MATCH(CHROMEOS_MAGIC)) {
return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
} else if (MATCH(BOOT_MAGIC)) {
return AOSP;
} else if (memcmp(buf, ELF32_MAGIC, 5) == 0) {
} else if (MATCH(ELF32_MAGIC)) {
return ELF32;
} else if (memcmp(buf, ELF64_MAGIC, 5) == 0) {
} else if (MATCH(ELF64_MAGIC)) {
return ELF64;
} else if (memcmp(buf, GZIP_MAGIC, 4) == 0) {
} else if (MATCH(GZIP_MAGIC)) {
return GZIP;
} else if (memcmp(buf, LZOP_MAGIC, 9) == 0) {
} else if (MATCH(LZOP_MAGIC)) {
return LZOP;
} else if (memcmp(buf, XZ_MAGIC, 6) == 0) {
} else if (MATCH(XZ_MAGIC)) {
return XZ;
} else if (memcmp(buf, "\x5d\x00\x00", 3) == 0
} else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0
&& (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) {
return LZMA;
} else if (memcmp(buf, BZIP_MAGIC, 3) == 0) {
} else if (MATCH(BZIP_MAGIC)) {
return BZIP2;
} else if (memcmp(buf, LZ4_MAGIC, 4) == 0) {
} else if (MATCH(LZ4_MAGIC)) {
return LZ4;
} else if (memcmp(buf, LZ4_LEG_MAGIC, 4) == 0) {
} else if (MATCH(LZ4_LEG_MAGIC)) {
return LZ4_LEGACY;
} else if (memcmp(buf, MTK_MAGIC, 4) == 0) {
} else if (MATCH(MTK_MAGIC)) {
return MTK;
} else if (memcmp(buf, DTB_MAGIC, 4) == 0) {
} else if (MATCH(DTB_MAGIC)) {
return DTB;
} else if (MATCH(DHTB_MAGIC)) {
return DHTB;
} else if (MATCH(TEGRABLOB_MAGIC)) {
return BLOB;
} else {
return UNKNOWN;
}
}
void get_type_name(file_t type, char *name) {
void get_fmt_name(format_t fmt, char *name) {
char *s;
switch (type) {
switch (fmt) {
case CHROMEOS:
s = "chromeos";
break;

View File

@@ -1,25 +1,28 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#ifndef _FORMAT_H_
#define _FORMAT_H_
typedef enum {
UNKNOWN,
CHROMEOS,
AOSP,
ELF32,
ELF64,
GZIP,
LZOP,
XZ,
LZMA,
BZIP2,
LZ4,
LZ4_LEGACY,
MTK,
DTB
} file_t;
UNKNOWN,
CHROMEOS,
AOSP,
ELF32,
ELF64,
GZIP,
LZOP,
XZ,
LZMA,
BZIP2,
LZ4,
LZ4_LEGACY,
MTK,
DTB,
DHTB,
BLOB
} format_t;
#define COMPRESSED(type) (type >= GZIP && type <= LZ4_LEGACY)
#define COMPRESSED(fmt) (fmt >= GZIP && fmt <= LZ4_LEGACY)
#define BOOT_MAGIC "ANDROID!"
#define CHROMEOS_MAGIC "CHROMEOS"
#define ELF32_MAGIC "\x7f""ELF\x01"
#define ELF64_MAGIC "\x7f""ELF\x02"
@@ -32,11 +35,19 @@ typedef enum {
#define MTK_MAGIC "\x88\x16\x88\x58"
#define DTB_MAGIC "\xd0\x0d\xfe\xed"
#define LG_BUMP_MAGIC "\x41\xa9\xe4\x67\x74\x4d\x1d\x1b\xa4\x29\xf2\xec\xea\x65\x52\x79"
#define DHTB_MAGIC "\x44\x48\x54\x42\x01\x00\x00\x00"
#define SEANDROID_MAGIC "SEANDROIDENFORCE"
#define TEGRABLOB_MAGIC "-SIGNED-BY-SIGNBLOB-"
#define NOOKHD_MAGIC "Green Loader"
#define NOOKHD_NEW_MAGIC "eMMC boot.img+secondloader"
#define NOOKHD_PRE_HEADER_SZ 1048576
#define ACCLAIM_MAGIC "BauwksBoot"
#define ACCLAIM_PRE_HEADER_SZ 262144
#define SUP_LIST ((char *[]) { "gzip", "xz", "lzma", "bzip2", "lz4", "lz4_legacy", NULL })
#define SUP_EXT_LIST ((char *[]) { "gz", "xz", "lzma", "bz2", "lz4", "lz4", NULL })
file_t check_type(const void *buf);
void get_type_name(file_t type, char *name);
format_t check_fmt(const void *buf, size_t len);
void get_fmt_name(format_t fmt, char *name);
#endif

View File

@@ -14,7 +14,7 @@
#define NEW_BOOT "new-boot.img"
// Main entries
void unpack(const char *image);
int unpack(const char *image);
void repack(const char* orig_image, const char* out_image);
void hexpatch(const char *image, const char *from, const char *to);
int parse_img(const char *image, boot_img *boot);
@@ -29,7 +29,7 @@ size_t lzma(int mode, int fd, const void *buf, size_t size);
size_t lz4(int mode, int fd, const void *buf, size_t size);
size_t bzip2(int mode, int fd, const void *buf, size_t size);
size_t lz4_legacy(int mode, int fd, const void *buf, size_t size);
long long comp(file_t type, int to, const void *from, size_t size);
long long decomp(file_t type, int to, const void *from, size_t size);
long long comp(format_t type, int to, const void *from, size_t size);
long long decomp(format_t type, int to, const void *from, size_t size);
#endif

View File

@@ -6,7 +6,7 @@
#include "magiskboot.h"
#include "utils.h"
#include "sha1.h"
#include "mincrypt/sha.h"
/********************
Patch Boot Image
@@ -126,19 +126,20 @@ int main(int argc, char *argv[]) {
unlink(name);
}
} else if (argc > 2 && strcmp(argv[1], "--sha1") == 0) {
char sha1[21], *buf;
uint8_t sha1[SHA_DIGEST_SIZE];
void *buf;
size_t size;
mmap_ro(argv[2], (void **) &buf, &size);
SHA1(sha1, buf, size);
for (int i = 0; i < 20; ++i)
mmap_ro(argv[2], &buf, &size);
SHA_hash(buf, size, sha1);
for (int i = 0; i < SHA_DIGEST_SIZE; ++i)
printf("%02x", sha1[i]);
printf("\n");
munmap(buf, size);
} else if (argc > 2 && strcmp(argv[1], "--parse") == 0) {
boot_img boot;
exit(parse_img(argv[2], &boot));
return parse_img(argv[2], &boot);
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]);
return unpack(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
repack(argv[2], argc > 3 ? argv[3] : NEW_BOOT);
} else if (argc > 2 && strcmp(argv[1], "--decompress") == 0) {
@@ -157,7 +158,8 @@ int main(int argc, char *argv[]) {
char *cmd = argv[1] + 5;
if (*cmd == '\0') usage(argv[0]);
else ++cmd;
if (dtb_commands(cmd, argc - 2, argv + 2)) usage(argv[0]);
if (dtb_commands(cmd, argc - 2, argv + 2))
usage(argv[0]);
} else {
usage(argv[0]);
}

View File

@@ -34,18 +34,22 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
#define STOCK_BOOT 0x0
#define MAGISK_PATCH 0x1
#define OTHER_PATCH 0x2
#define HIGH_COMPRESS 0x2
#define OTHER_PATCH 0x3
static int cpio_test(struct vector *v) {
const char *OTHER_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", "boot/sbin/launch_daemonsu.sh", NULL };
const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", "overlay/init.magisk.rc", NULL };
for (int i = 0; OTHER_LIST[i]; ++i)
if (cpio_find(v, OTHER_LIST[i]) > 0)
if (cpio_find(v, OTHER_LIST[i]) >= 0)
return OTHER_PATCH;
if (cpio_find(v, "ramdisk.cpio.xz") >= 0)
return HIGH_COMPRESS;
for (int i = 0; MAGISK_LIST[i]; ++i)
if (cpio_find(v, MAGISK_LIST[i]) > 0)
if (cpio_find(v, MAGISK_LIST[i]) >= 0)
return MAGISK_PATCH;
return STOCK_BOOT;

View File

@@ -113,7 +113,7 @@ int rm_list(char *proc) {
return HIDE_NOT_ENABLED;
}
daemon_response ret = DAEMON_ERROR;
int ret = DAEMON_ERROR;
char *line;
int do_rm = 0;
struct vector *new_list = xmalloc(sizeof(*new_list));

View File

@@ -49,6 +49,17 @@ void launch_magiskhide(int client) {
return;
}
if (!logd) {
if (client > 0) {
write_int(client, LOGD_DISABLED);
close(client);
}
setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props
deleteprop2(MAGISKHIDE_PROP, 0);
return;
}
hideEnabled = 1;
LOGI("* Starting MagiskHide\n");
@@ -110,7 +121,7 @@ int magiskhide_main(int argc, char *argv[]) {
if (argc < 2) {
usage(argv[0]);
}
client_request req = DO_NOTHING;
int req = DO_NOTHING;
if (strcmp(argv[1], "--enable") == 0) {
req = LAUNCH_MAGISKHIDE;
} else if (strcmp(argv[1], "--disable") == 0) {
@@ -129,16 +140,16 @@ int magiskhide_main(int argc, char *argv[]) {
if (req == ADD_HIDELIST || req == RM_HIDELIST) {
write_string(fd, argv[2]);
}
daemon_response code = read_int(fd);
int code = read_int(fd);
switch (code) {
case DAEMON_ERROR:
fprintf(stderr, "Error occured in daemon...\n");
return code;
case DAEMON_SUCCESS:
break;
case ROOT_REQUIRED:
fprintf(stderr, "Root is required for this operation\n");
return code;
case LOGD_DISABLED:
fprintf(stderr, "Logd is not running, cannot run logcat\n");
return (code);
case HIDE_NOT_ENABLED:
fprintf(stderr, "Magisk hide is not enabled yet\n");
return code;
@@ -151,6 +162,10 @@ int magiskhide_main(int argc, char *argv[]) {
case HIDE_ITEM_NOT_EXIST:
fprintf(stderr, "Process [%s] does not exist in hide list\n", argv[2]);
return code;
case DAEMON_ERROR:
default:
fprintf(stderr, "Error occured in daemon...\n");
return code;
}
if (req == LS_HIDELIST) {

View File

@@ -4,7 +4,6 @@
#include <pthread.h>
#define TERM_THREAD SIGUSR1
#define HIDE_DONE SIGUSR2
// Kill process
void kill_proc(int pid);

View File

@@ -20,7 +20,7 @@
#include "magiskhide.h"
static char init_ns[32], zygote_ns[2][32], cache_block[256];
static int hide_queue = 0, zygote_num, has_cache = 1, pipefd[2] = { -1, -1 };
static int zygote_num, has_cache = 1, pipefd[2] = { -1, -1 };
// Workaround for the lack of pthread_cancel
static void term_thread(int sig) {
@@ -38,17 +38,6 @@ static void term_thread(int sig) {
pthread_exit(NULL);
}
static void hide_done(int sig) {
--hide_queue;
if (hide_queue == 0) {
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xsymlink(DATABIN, "/data/magisk");
xsymlink(MAINIMG, "/data/magisk.img");
xsymlink(MOUNTPOINT, "/magisk");
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
}
}
static int read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
@@ -140,9 +129,6 @@ exit:
kill(pid, SIGCONT);
// Free up memory
vec_destroy(&mount_list);
// Wait a while and link it back
sleep(10);
kill(ppid, HIDE_DONE);
_exit(0);
}
@@ -151,7 +137,6 @@ void proc_monitor() {
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, TERM_THREAD);
sigaddset(&block_set, HIDE_DONE);
pthread_sigmask(SIG_UNBLOCK, &block_set, NULL);
// Register the cancel signal
@@ -159,8 +144,6 @@ void proc_monitor() {
memset(&act, 0, sizeof(act));
act.sa_handler = term_thread;
sigaction(TERM_THREAD, &act, NULL);
act.sa_handler = hide_done;
sigaction(HIDE_DONE, &act, NULL);
cache_block[0] = '\0';
@@ -241,14 +224,6 @@ void proc_monitor() {
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, pid, ns);
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
unlink("/magisk");
unlink("/data/magisk");
unlink("/data/magisk.img");
unlink(MAGISKRC);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
++hide_queue;
/*
* The setns system call do not support multithread processes
* We have to fork a new process, setns, then do the unmounts

View File

@@ -2,52 +2,6 @@
*
* Copyright 2016 nkk71 <nkk71x@gmail.com>
* Copyright 2016 topjohnwu <topjohnwu@gmail.com>
*
* Info:
*
* all changes are in
*
* bionic/libc/bionic/system_properties.cpp
*
* Functions that need to be patched/added in system_properties.cpp
*
* int __system_properties_init2()
* on android 7, first tear down the everything then let it initialize again:
* if (initialized) {
* //list_foreach(contexts, [](context_node* l) { l->reset_access(); });
* //return 0;
* free_and_unmap_contexts();
* initialized = false;
* }
*
*
* static prop_area* map_prop_area(const char* filename, bool is_legacy)
* we dont want this read only so change: 'O_RDONLY' to 'O_RDWR'
*
* static prop_area* map_fd_ro(const int fd)
* we dont want this read only so change: 'PROT_READ' to 'PROT_READ | PROT_WRITE'
*
*
* Copy the code of prop_info *prop_area::find_property, and modify to delete props
* const prop_info *prop_area::find_property_and_del(prop_bt *const trie, const char *name)
* {
* ...
* ... Do not alloc a new prop_bt here, remove all code involve alloc_if_needed
* ...
*
* if (prop_offset != 0) {
* atomic_store_explicit(&current->prop, 0, memory_order_release); // Add this line to nullify the prop entry
* return to_prop_info(&current->prop);
* } else {
*
* ....
* }
*
*
* by patching just those functions directly, all other functions should be ok
* as is.
*
*
*/
#include <stdio.h>

View File

@@ -153,7 +153,7 @@ class prop_area {
}
const prop_info* find(const char* name);
bool del(const char *name); // resetprop add
bool del(const char *name); /* resetprop add */
bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
@@ -184,7 +184,7 @@ class prop_area {
const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
const char* value, uint32_t valuelen, bool alloc_if_needed);
bool find_property_and_del(prop_bt *const trie, const char *name); // resetprop add
bool find_property_and_del(prop_bt *const trie, const char *name); /* resetprop add */
bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
void* cookie);
@@ -283,7 +283,8 @@ static prop_area* map_prop_area_rw(const char* filename, const char* context,
return pa;
}
static prop_area* map_fd_ro(const int fd) {
// resetprop: map the memory as rw
static prop_area* map_fd_rw(const int fd) {
struct stat fd_stat;
if (fstat(fd, &fd_stat) < 0) {
return nullptr;
@@ -298,7 +299,7 @@ static prop_area* map_fd_ro(const int fd) {
pa_size = fd_stat.st_size;
pa_data_size = pa_size - sizeof(prop_area);
void* const map_result = mmap(nullptr, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // resetprop: add PROT_WRITE
void* const map_result = mmap(nullptr, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); /* resetprop: add PROT_WRITE */
if (map_result == MAP_FAILED) {
return nullptr;
}
@@ -313,10 +314,10 @@ static prop_area* map_fd_ro(const int fd) {
}
static prop_area* map_prop_area(const char* filename) {
int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDWR); // resetprop: O_RDONLY -> O_RDWR
int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDWR); /* resetprop: O_RDONLY -> O_RDWR */
if (fd == -1) return nullptr;
prop_area* map_result = map_fd_ro(fd);
prop_area* map_result = map_fd_rw(fd);
close(fd);
return map_result;
@@ -530,7 +531,7 @@ bool prop_area::find_property_and_del(prop_bt* const trie, const char* name) {
uint_least32_t prop_offset = atomic_load_explicit(&current->prop, memory_order_relaxed);
if (prop_offset != 0) {
atomic_store_explicit(&current->prop, 0, memory_order_release); // resetprop: nullify the offset to delete the prop
atomic_store_explicit(&current->prop, 0, memory_order_release);
return true;
} else {
return false;
@@ -1116,16 +1117,16 @@ static bool initialize_properties() {
if (!initialize_properties_from_file("/system/etc/selinux/plat_property_contexts")) {
return false;
}
if (!initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts")) {
return false;
}
// Don't check for failure here, so we always have a sane list of properties.
// E.g. In case of recovery, the vendor partition will not have mounted and we
// still need the system / platform properties to function.
initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts") ||
initialize_properties_from_file("/vendor/etc/selinux/vendor_property_contexts");
} else {
if (!initialize_properties_from_file("/plat_property_contexts")) {
return false;
}
if (!initialize_properties_from_file("/nonplat_property_contexts")) {
return false;
}
initialize_properties_from_file("/nonplat_property_contexts");
}
return true;

View File

@@ -46,7 +46,7 @@ int cpio_cmp(const void *a, const void *b) {
void cpio_vec_insert(struct vector *v, cpio_entry *n) {
int i = cpio_find(v, n->filename);
if (i > 0) {
if (i >= 0) {
// Replace, then all is done
cpio_free(vec_entry(v)[i]);
vec_entry(v)[i] = n;
@@ -56,6 +56,7 @@ void cpio_vec_insert(struct vector *v, cpio_entry *n) {
}
// Parse cpio file to a vector of cpio_entry
#define parse_align() lseek(fd, align(lseek(fd, 0, SEEK_CUR), 4), SEEK_SET)
void parse_cpio(struct vector *v, const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd < 0) return;
@@ -79,7 +80,7 @@ void parse_cpio(struct vector *v, const char *filename) {
// f->check = x8u(header.check);
f->filename = xmalloc(namesize);
xxread(fd, f->filename, namesize);
file_align(fd, 4, 0);
parse_align();
if (strcmp(f->filename, ".") == 0 || strcmp(f->filename, "..") == 0) {
cpio_free(f);
continue;
@@ -91,13 +92,14 @@ void parse_cpio(struct vector *v, const char *filename) {
if (f->filesize) {
f->data = xmalloc(f->filesize);
xxread(fd, f->data, f->filesize);
file_align(fd, 4, 0);
parse_align();
}
vec_push_back(v, f);
}
close(fd);
}
#define dump_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), 4))
void dump_cpio(struct vector *v, const char *filename) {
fprintf(stderr, "Dump cpio: [%s]\n", filename);
unsigned inode = 300000;
@@ -124,17 +126,17 @@ void dump_cpio(struct vector *v, const char *filename) {
);
xwrite(fd, header, 110);
xwrite(fd, e->filename, strlen(e->filename) + 1);
file_align(fd, 4, 1);
dump_align();
if (e->filesize) {
xwrite(fd, e->data, e->filesize);
file_align(fd, 4, 1);
dump_align();
}
}
// Write trailer
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", inode++, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0);
xwrite(fd, header, 110);
xwrite(fd, "TRAILER!!!\0", 11);
file_align(fd, 4, 1);
dump_align();
close(fd);
}

View File

@@ -228,6 +228,33 @@ void clone_dir(int src, int dest) {
}
}
void link_dir(int src, int dest) {
struct dirent *entry;
DIR *dir;
int newsrc, newdest;
struct file_attr a;
dir = xfdopendir(src);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
if (is_excl(entry->d_name))
continue;
if (entry->d_type == DT_DIR) {
getattrat(src, entry->d_name, &a);
xmkdirat(dest, entry->d_name, a.st.st_mode & 0777);
setattrat(dest, entry->d_name, &a);
newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
link_dir(newsrc, newdest);
close(newsrc);
close(newdest);
} else {
linkat(src, entry->d_name, dest, entry->d_name, 0);
}
}
}
int getattr(const char *path, struct file_attr *a) {
if (xlstat(path, &a->st) == -1)
return -1;
@@ -374,8 +401,9 @@ int mmap_rw(const char *filename, void **buf, size_t *size) {
void fd_full_read(int fd, void **buf, size_t *size) {
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmalloc(*size);
*buf = xmalloc(*size + 1);
xxread(fd, *buf, *size);
((char *) *buf)[*size] = '\0';
}
void full_read(const char *filename, void **buf, size_t *size) {
@@ -424,24 +452,3 @@ void write_zero(int fd, size_t size) {
ftruncate(fd, pos + size);
lseek(fd, pos + size, SEEK_SET);
}
void mem_align(size_t *pos, size_t align) {
size_t mask = align - 1;
if (*pos & mask) {
*pos += align - (*pos & mask);
}
}
void file_align(int fd, size_t align, int out) {
size_t pos = lseek(fd, 0, SEEK_CUR);
size_t mask = align - 1;
size_t off;
if (pos & mask) {
off = align - (pos & mask);
if (out) {
write_zero(fd, off);
} else {
lseek(fd, pos + off, SEEK_SET);
}
}
}

View File

@@ -3,9 +3,11 @@
#include <unistd.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <sys/sendfile.h>
#include <linux/loop.h>
#include "magisk.h"
@@ -15,7 +17,7 @@ static int e2fsck(const char *img) {
// Check and repair ext4 image
char buffer[128];
int pid, fd = -1;
pid = exec_command(1, &fd, NULL, "e2fsck", "-yf", img, NULL);
pid = exec_command(1, &fd, NULL, "/system/bin/e2fsck", "-yf", img, NULL);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd))
@@ -56,11 +58,13 @@ int create_img(const char *img, int size) {
LOGI("Create %s with size %dM\n", img, size);
int ret;
char buffer[16];
snprintf(buffer, sizeof(buffer), "%dM", size);
ret = exec_command_sync("make_ext4fs", "-l", buffer, img, NULL);
if (ret < 0)
return 1;
char size_str[16];
snprintf(size_str, sizeof(size_str), "%dM", size);
ret = exec_command_sync("/system/bin/make_ext4fs", "-b", "4096", "-l", size_str, img, NULL);
if (ret < 0) {
// On Android P there is no make_ext4fs, use mke2fs
ret = exec_command_sync("/system/bin/mke2fs", "-b", "4096", "-t", "ext4", img, size_str, NULL);
}
return ret;
}
@@ -69,7 +73,7 @@ int get_img_size(const char *img, int *used, int *total) {
return 1;
char buffer[PATH_MAX];
int pid, fd = -1, status = 1;
pid = exec_command(1, &fd, NULL, "e2fsck", "-n", img, NULL);
pid = exec_command(1, &fd, NULL, "/system/bin/e2fsck", "-n", img, NULL);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd)) {
@@ -84,8 +88,8 @@ int get_img_size(const char *img, int *used, int *total) {
}
if (status) continue;
sscanf(tok, "%d/%d", used, total);
*used = *used / 256 + 1;
*total /= 256;
*used = (*used + 255) / 256;
*total = (*total + 128) / 256;
break;
}
}
@@ -101,7 +105,7 @@ int resize_img(const char *img, int size) {
char buffer[128];
int pid, fd = -1, used, total;
snprintf(buffer, sizeof(buffer), "%dM", size);
pid = exec_command(1, &fd, NULL, "resize2fs", img, buffer, NULL);
pid = exec_command(1, &fd, NULL, "/system/bin/resize2fs", img, buffer, NULL);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd))
@@ -167,7 +171,15 @@ int merge_img(const char *source, const char *target) {
return 0;
LOGI("* Merging %s -> %s\n", source, target);
if (access(target, F_OK) == -1) {
xrename(source, target);
if (rename(source, target) < 0) {
// Copy and remove
int tgt = creat(target, 0644);
int src = xopen(source, O_RDONLY | O_CLOEXEC);
sendfile(tgt, src, 0, INT_MAX);
close(tgt);
close(src);
unlink(source);
}
return 0;
}

View File

@@ -17,6 +17,7 @@
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/inotify.h>
#include <sys/sysmacros.h>
#include "logging.h"
#include "utils.h"
@@ -50,7 +51,7 @@ int check_data() {
struct vector v;
vec_init(&v);
file_to_vector("/proc/mounts", &v);
char *line, *crypto;
char *line;
int mnt = 0;
vec_for_each(&v, line) {
if (strstr(line, " /data ")) {
@@ -60,9 +61,28 @@ int check_data() {
}
}
vec_deep_destroy(&v);
// /data is mounted and not tmpfs and data is unencrypted or vold is started
return mnt && (((crypto = getprop("ro.crypto.state")) && strcmp(crypto, "unencrypted") == 0)
|| getprop("init.svc.vold"));
int data = 0;
if (mnt) {
char *crypto = getprop("ro.crypto.state");
if (crypto != NULL) {
if (strcmp(crypto, "unencrypted") == 0) {
// Unencrypted, we can directly access data
data = 1;
} else {
// Encrypted, check whether vold is started
char *vold = getprop("init.svc.vold");
if (vold != NULL) {
free(vold);
data = 1;
}
}
free(crypto);
} else {
// ro.crypto.state is not set, assume it's unencrypted
data = 1;
}
}
return data;
}
/* All the string should be freed manually!! */
@@ -260,7 +280,7 @@ static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), co
}
execvpe(argv0, (char **) vec_entry(&args), envp);
PLOGE("execvpe");
PLOGE("execvpe %s", argv0);
return -1;
}
@@ -341,3 +361,21 @@ void wait_till_exists(const char *target) {
}
close(fd);
}
void gen_rand_str(char *buf, int len) {
const char base[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.";
int urandom;
if (access("/dev/urandom", R_OK) == 0) {
urandom = xopen("/dev/urandom", O_RDONLY | O_CLOEXEC);
} else {
mknod("/urandom", S_IFCHR | 0666, makedev(1, 9));
urandom = xopen("/urandom", O_RDONLY | O_CLOEXEC);
unlink("/urandom");
}
xxread(urandom, buf, len - 1);
close(urandom);
for (int i = 0; i < len - 1; ++i) {
buf[i] = base[buf[i] % (sizeof(base) - 1)];
}
buf[len - 1] = '\0';
}

View File

@@ -53,8 +53,6 @@ if [ -z $SOURCEDMODE ]; then
cd "`dirname_wrap "${BASH_SOURCE:-$0}"`"
# Load utility functions
. ./util_functions.sh
# Detect current status
mount_partitions
fi
BOOTIMAGE="$1"
@@ -68,7 +66,7 @@ BOOTIMAGE="$1"
if [ -z $KEEPFORCEENCRYPT ]; then
if [ "`getprop ro.crypto.state`" = "encrypted" ]; then
KEEPFORCEENCRYPT=true
ui_print "- Encrypted data detected"
ui_print "- Encrypted data detected, keep forceencrypt"
else
KEEPFORCEENCRYPT=false
fi
@@ -93,9 +91,7 @@ case $? in
abort "! Unable to unpack boot image"
;;
2 )
ui_print "! Insufficient boot partition size detected"
HIGHCOMP=true
ui_print "- Enable high compression mode"
;;
3 )
ui_print "- ChromeOS boot image detected"
@@ -116,6 +112,7 @@ esac
# Test patch status and do restore, after this section, ramdisk.cpio.orig is guaranteed to exist
ui_print "- Checking ramdisk status"
MAGISK_PATCHED=false
./magiskboot --cpio ramdisk.cpio test
case $? in
0 ) # Stock boot
@@ -127,18 +124,32 @@ case $? in
cp -af ramdisk.cpio ramdisk.cpio.orig
;;
1 ) # Magisk patched
ui_print "- Magisk patched image detected"
# Find SHA1 of stock boot image
[ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null`
./magiskboot --cpio ramdisk.cpio restore
cp -af ramdisk.cpio ramdisk.cpio.orig
MAGISK_PATCHED=true
HIGHCOMP=false
;;
2 ) # Other patched
2 ) # High compression mode
MAGISK_PATCHED=true
HIGHCOMP=true
;;
3 ) # Other patched
ui_print "! Boot image patched by other programs"
abort "! Please restore stock boot image"
;;
esac
if $MAGISK_PATCHED; then
ui_print "- Magisk patched image detected"
# Find SHA1 of stock boot image
[ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null`
./magiskboot --cpio ramdisk.cpio restore
cp -af ramdisk.cpio ramdisk.cpio.orig
fi
if $HIGHCOMP; then
ui_print "! Insufficient boot partition size detected"
ui_print "- Enable high compression mode"
fi
##########################################################################################
# Ramdisk patches
##########################################################################################
@@ -159,15 +170,17 @@ if ! $KEEPVERITY && [ -f dtb ]; then
./magiskboot --dtb-patch dtb && ui_print "- Patching fstab in dtb to remove dm-verity"
fi
# Remove Samsung RKP in stock kernel
./magiskboot --hexpatch kernel \
49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
if [ -f kernel ]; then
# Remove Samsung RKP in stock kernel
./magiskboot --hexpatch kernel \
49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
# skip_initramfs -> want_initramfs
./magiskboot --hexpatch kernel \
736B69705F696E697472616D6673 \
77616E745F696E697472616D6673
# skip_initramfs -> want_initramfs
./magiskboot --hexpatch kernel \
736B69705F696E697472616D6673 \
77616E745F696E697472616D6673
fi
##########################################################################################
# Repack and flash

View File

@@ -53,33 +53,44 @@ getvar KEEPVERITY
getvar KEEPFORCEENCRYPT
getvar BOOTIMAGE
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found boot/ramdisk image: $BOOTIMAGE"
if [ ! -z $DTBOIMAGE ]; then
ui_print "- Found dtbo image: $DTBOIMAGE"
# Disable dtbo patch by default
[ -z $KEEPVERITY ] && KEEPVERITY=true
fi
# Detect version and architecture
api_level_arch_detect
[ $API -lt 21 ] && abort "! Magisk is only for Lollipop 5.0+ (SDK 21+)"
# Check if system root is installed and remove
remove_system_su
ui_print "- Device platform: $ARCH"
BINDIR=$INSTALLER/$ARCH
chmod -R 755 $CHROMEDIR $BINDIR
# Check if system root is installed and remove
remove_system_su
##########################################################################################
# Environment
##########################################################################################
ui_print "- Constructing environment"
if is_mounted /data; then
MAGISKBIN=/data/adb/magisk
mkdir -p /data/adb 2>/dev/null
chmod 700 /data/adb 2>/dev/null
# Check if we can actually access the data (DE storage)
DATA=false
if grep ' /data ' /proc/mounts | grep -vq 'tmpfs'; then
[ ! -d /data/adb ] && mkdir /data/adb
touch /data/adb/.write_test && rm /data/adb/.write_test && DATA=true
fi
# Some legacy migration
if $DATA; then
MAGISKBIN=/data/adb/magisk
run_migrations
[ -L /data/magisk.img ] || mv /data/magisk.img /data/adb/magisk.img 2>/dev/null
else
MAGISKBIN=/cache/data_bin
fi
@@ -104,18 +115,8 @@ $BOOTMODE || recovery_actions
# Boot patching
##########################################################################################
[ -z $BOOTIMAGE ] && find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found boot image: $BOOTIMAGE"
if [ ! -z $DTBOIMAGE ]; then
ui_print "- Found dtbo image: $DTBOIMAGE"
# Disable dtbo patch by default
[ -z $KEEPVERITY ] && KEEPVERITY=true
fi
eval $BOOTSIGNER -verify < $BOOTIMAGE && BOOTSIGNED=true
$BOOTSIGNED && ui_print "- Signed boot image detected"
$BOOTSIGNED && ui_print "- Boot image is signed with AVB 1.0"
SOURCEDMODE=true
cd $MAGISKBIN
@@ -128,14 +129,14 @@ rm -f new-boot.img
if [ -f stock_boot* ]; then
rm -f /data/stock_boot* 2>/dev/null
is_mounted /data && mv stock_boot* /data
$DATA && mv stock_boot* /data
fi
$KEEPVERITY || patch_dtbo_image
if [ -f stock_dtbo* ]; then
rm -f /data/stock_dtbo* 2>/dev/null
is_mounted /data && mv stock_dtbo* /data
$DATA && mv stock_dtbo* /data
fi
cd /

View File

@@ -73,7 +73,7 @@ case $? in
ui_print "- Stock boot image detected"
abort "! Magisk is not installed!"
;;
1 ) # Magisk patched
1|2 ) # Magisk patched
ui_print "- Magisk patched image detected"
# Find SHA1 of stock boot image
[ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null`
@@ -89,7 +89,7 @@ case $? in
flash_boot_image new-boot.img "$BOOTIMAGE"
fi
;;
2 ) # Other patched
3 ) # Other patched
ui_print "! Boot image patched by other programs"
abort "! Cannot uninstall"
;;
@@ -103,4 +103,4 @@ rm -rf /cache/*magisk* /cache/unblock /data/*magisk* /data/cache/*magisk* /data
/data/user*/*/magisk.db /data/user*/*/com.topjohnwu.magisk /data/user*/*/.tmp.magisk.config \
/data/adb/*magisk* 2>/dev/null
$BOOTMODE && reboot
$BOOTMODE && /system/bin/reboot

View File

@@ -94,21 +94,12 @@ grep_prop() {
getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$$VARNAME)
[ ! -z $VALUE ] && return
local VALUE=
for DIR in /.backup /dev /data /cache /system; do
VALUE=`grep_prop $VARNAME $DIR/.magisk`
[ ! -z $VALUE ] && break;
done
eval $VARNAME=\$VALUE
}
resolve_link() {
RESOLVED="$1"
while RESOLVE=`readlink $RESOLVED`; do
RESOLVED=$RESOLVE
done
echo $RESOLVED
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
}
find_boot_image() {
@@ -116,22 +107,22 @@ find_boot_image() {
if [ ! -z $SLOT ]; then
BOOTIMAGE=`find /dev/block -iname boot$SLOT | head -n 1` 2>/dev/null
fi
if [ -z "$BOOTIMAGE" ]; then
if [ -z $BOOTIMAGE ]; then
# The slot info is incorrect...
SLOT=
for BLOCK in boot_a kern-a android_boot kernel boot lnx bootimg; do
for BLOCK in ramdisk boot_a kern-a android_boot kernel boot lnx bootimg; do
BOOTIMAGE=`find /dev/block -iname $BLOCK | head -n 1` 2>/dev/null
[ ! -z $BOOTIMAGE ] && break
done
fi
# Recovery fallback
if [ -z "$BOOTIMAGE" ]; then
if [ -z $BOOTIMAGE ]; then
for FSTAB in /etc/*fstab*; do
BOOTIMAGE=`grep -v '#' $FSTAB | grep -E '/boot[^a-zA-Z]' | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
[ ! -z $BOOTIMAGE ] && break
done
fi
[ ! -z "$BOOTIMAGE" ] && BOOTIMAGE=`resolve_link $BOOTIMAGE`
[ ! -z $BOOTIMAGE ] && BOOTIMAGE=`readlink -f $BOOTIMAGE`
}
run_migrations() {
@@ -158,6 +149,7 @@ run_migrations() {
fi
# Remove old dbs
rm -f /data/user*/*/magisk.db
[ -L /data/magisk.img ] || mv /data/magisk.img /data/adb/magisk.img 2>/dev/null
}
flash_boot_image() {
@@ -167,7 +159,12 @@ flash_boot_image() {
*.gz) COMMAND="gzip -d < '$1'";;
*) COMMAND="cat '$1'";;
esac
$BOOTSIGNED && SIGNCOM="$BOOTSIGNER -sign" || SIGNCOM="cat -"
if $BOOTSIGNED; then
SIGNCOM="$BOOTSIGNER -sign"
ui_print "- Sign boot image with test keys"
else
SIGNCOM="cat -"
fi
case "$2" in
/dev/block/*)
ui_print "- Flashing new boot image"
@@ -182,7 +179,7 @@ flash_boot_image() {
find_dtbo_image() {
DTBOIMAGE=`find /dev/block -iname dtbo$SLOT | head -n 1` 2>/dev/null
[ ! -z $DTBOIMAGE ] && DTBOIMAGE=`resolve_link $DTBOIMAGE`
[ ! -z $DTBOIMAGE ] && DTBOIMAGE=`readlink -f $DTBOIMAGE`
}
patch_dtbo_image() {
@@ -232,7 +229,7 @@ sign_chromeos() {
}
is_mounted() {
TARGET="`resolve_link $1`"
TARGET="`readlink -f $1`"
cat /proc/mounts | grep " $TARGET " >/dev/null
return $?
}
@@ -321,9 +318,9 @@ abort() {
}
set_perm() {
chown $2:$3 $1 || exit 1
chmod $4 $1 || exit 1
[ -z $5 ] && chcon 'u:object_r:system_file:s0' $1 || chcon $5 $1
chown $2:$3 $1 || return 1
chmod $4 $1 || return 1
[ -z $5 ] && chcon 'u:object_r:system_file:s0' $1 || chcon $5 $1 || return 1
}
set_perm_recursive() {

View File

@@ -1 +1 @@
include ':app', ':core', ':crypto', ':snet'
include ':app', ':native', ':utils', ':snet'

Some files were not shown because too many files have changed in this diff Show More