Update decrypt for 4.4
Change-Id: I8d5d7b6a49890e4707d70de8b429563de0d2ad99
This commit is contained in:
@@ -354,6 +354,8 @@ endif
|
||||
ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
|
||||
include $(commands_recovery_local_path)/crypto/jb/Android.mk
|
||||
include $(commands_recovery_local_path)/crypto/fs_mgr/Android.mk
|
||||
include $(commands_recovery_local_path)/crypto/logwrapper/Android.mk
|
||||
include $(commands_recovery_local_path)/crypto/scrypt/Android.mk
|
||||
endif
|
||||
ifeq ($(HAVE_SELINUX), true)
|
||||
include $(commands_recovery_local_path)/minzip/Android.mk
|
||||
|
||||
+15
-13
@@ -1,34 +1,36 @@
|
||||
# Copyright 2011 The Android Open Source Project
|
||||
ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= fs_mgr.c
|
||||
LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
|
||||
LOCAL_MODULE:= libfs_mgrtwrp
|
||||
LOCAL_SHARED_LIBRARIES := libext4_utils
|
||||
LOCAL_STATIC_LIBRARIES := liblogwraptwrp libmincrypttwrp
|
||||
LOCAL_C_INCLUDES += system/extras/ext4_utils bootable/recovery/libmincrypt/includes
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
|
||||
#include $(CLEAR_VARS)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
#LOCAL_SRC_FILES:= fs_mgr_main.c
|
||||
LOCAL_SRC_FILES:= fs_mgr_main.c
|
||||
|
||||
#LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
|
||||
#LOCAL_MODULE:= fs_mgr
|
||||
LOCAL_MODULE:= fs_mgrtwrp
|
||||
|
||||
#LOCAL_MODULE_TAGS := optional
|
||||
#LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
#LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
|
||||
#LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
|
||||
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
|
||||
|
||||
#LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc
|
||||
LOCAL_STATIC_LIBRARIES := libfs_mgrtwrp liblogwraptwrp libcutils liblog libc libmincrypttwrp libext4_utils_static
|
||||
|
||||
#include $(BUILD_EXECUTABLE)
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
endif
|
||||
|
||||
+444
-107
@@ -14,11 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* TO DO:
|
||||
* 1. Re-direct fsck output to the kernel log?
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -32,17 +27,37 @@
|
||||
#include <sys/wait.h>
|
||||
#include <libgen.h>
|
||||
#include <time.h>
|
||||
//#include <sys/swap.h>
|
||||
/* XXX These need to be obtained from kernel headers. See b/9336527 */
|
||||
#define SWAP_FLAG_PREFER 0x8000
|
||||
#define SWAP_FLAG_PRIO_MASK 0x7fff
|
||||
#define SWAP_FLAG_PRIO_SHIFT 0
|
||||
#define SWAP_FLAG_DISCARD 0x10000
|
||||
|
||||
#include <linux/loop.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <cutils/partition_utils.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <logwrap/logwrap.h>
|
||||
|
||||
#include "mincrypt/rsa.h"
|
||||
#include "mincrypt/sha.h"
|
||||
#include "mincrypt/sha256.h"
|
||||
|
||||
#include "fs_mgr_priv.h"
|
||||
#include "fs_mgr_priv_verity.h"
|
||||
|
||||
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
|
||||
#define KEY_IN_FOOTER "footer"
|
||||
|
||||
#define E2FSCK_BIN "/system/bin/e2fsck"
|
||||
#define MKSWAP_BIN "/system/bin/mkswap"
|
||||
|
||||
#define FSCK_LOG_FILE "/dev/fscklogs/log"
|
||||
|
||||
#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
struct flag_list {
|
||||
const char *name;
|
||||
@@ -58,6 +73,12 @@ static struct flag_list mount_flags[] = {
|
||||
{ "ro", MS_RDONLY },
|
||||
{ "rw", 0 },
|
||||
{ "remount", MS_REMOUNT },
|
||||
{ "bind", MS_BIND },
|
||||
{ "rec", MS_REC },
|
||||
{ "unbindable", MS_UNBINDABLE },
|
||||
{ "private", MS_PRIVATE },
|
||||
{ "slave", MS_SLAVE },
|
||||
{ "shared", MS_SHARED },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
@@ -66,10 +87,27 @@ static struct flag_list fs_mgr_flags[] = {
|
||||
{ "wait", MF_WAIT },
|
||||
{ "check", MF_CHECK },
|
||||
{ "encryptable=",MF_CRYPT },
|
||||
{ "nonremovable",MF_NONREMOVABLE },
|
||||
{ "voldmanaged=",MF_VOLDMANAGED},
|
||||
{ "length=", MF_LENGTH },
|
||||
{ "recoveryonly",MF_RECOVERYONLY },
|
||||
{ "swapprio=", MF_SWAPPRIO },
|
||||
{ "zramsize=", MF_ZRAMSIZE },
|
||||
{ "verify", MF_VERIFY },
|
||||
{ "noemulatedsd", MF_NOEMULATEDSD },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
struct fs_mgr_flag_values {
|
||||
char *key_loc;
|
||||
long long part_length;
|
||||
char *label;
|
||||
int partnum;
|
||||
int swap_prio;
|
||||
unsigned int zram_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* gettime() - returns the time in seconds of the system's monotonic clock or
|
||||
* zero on error.
|
||||
@@ -100,7 +138,8 @@ static int wait_for_file(const char *filename, int timeout)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
|
||||
static int parse_flags(char *flags, struct flag_list *fl,
|
||||
struct fs_mgr_flag_values *flag_vals,
|
||||
char *fs_options, int fs_options_len)
|
||||
{
|
||||
int f = 0;
|
||||
@@ -108,11 +147,14 @@ static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
|
||||
char *p;
|
||||
char *savep;
|
||||
|
||||
/* initialize key_loc to null, if we find an MF_CRYPT flag,
|
||||
* then we'll set key_loc to the proper value */
|
||||
if (key_loc) {
|
||||
*key_loc = NULL;
|
||||
/* initialize flag values. If we find a relevant flag, we'll
|
||||
* update the value */
|
||||
if (flag_vals) {
|
||||
memset(flag_vals, 0, sizeof(*flag_vals));
|
||||
flag_vals->partnum = -1;
|
||||
flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
|
||||
}
|
||||
|
||||
/* initialize fs_options to the null string */
|
||||
if (fs_options && (fs_options_len > 0)) {
|
||||
fs_options[0] = '\0';
|
||||
@@ -126,11 +168,45 @@ static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
|
||||
for (i = 0; fl[i].name; i++) {
|
||||
if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
|
||||
f |= fl[i].flag;
|
||||
if ((fl[i].flag == MF_CRYPT) && key_loc) {
|
||||
if ((fl[i].flag == MF_CRYPT) && flag_vals) {
|
||||
/* The encryptable flag is followed by an = and the
|
||||
* location of the keys. Get it and return it.
|
||||
*/
|
||||
*key_loc = strdup(strchr(p, '=') + 1);
|
||||
flag_vals->key_loc = strdup(strchr(p, '=') + 1);
|
||||
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
|
||||
/* The length flag is followed by an = and the
|
||||
* size of the partition. Get it and return it.
|
||||
*/
|
||||
flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
|
||||
/* The voldmanaged flag is followed by an = and the
|
||||
* label, a colon and the partition number or the
|
||||
* word "auto", e.g.
|
||||
* voldmanaged=sdcard:3
|
||||
* Get and return them.
|
||||
*/
|
||||
char *label_start;
|
||||
char *label_end;
|
||||
char *part_start;
|
||||
|
||||
label_start = strchr(p, '=') + 1;
|
||||
label_end = strchr(p, ':');
|
||||
if (label_end) {
|
||||
flag_vals->label = strndup(label_start,
|
||||
(int) (label_end - label_start));
|
||||
part_start = strchr(p, ':') + 1;
|
||||
if (!strcmp(part_start, "auto")) {
|
||||
flag_vals->partnum = -1;
|
||||
} else {
|
||||
flag_vals->partnum = strtol(part_start, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
ERROR("Warning: voldmanaged= flag malformed\n");
|
||||
}
|
||||
} else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
|
||||
flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
} else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
|
||||
flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -167,7 +243,7 @@ out:
|
||||
* then return an empty buffer. This effectively ignores lines that are too long.
|
||||
* On EOF, return null.
|
||||
*/
|
||||
static char *fs_mgr_getline(char *buf, int size, FILE *file)
|
||||
static char *fs_getline(char *buf, int size, FILE *file)
|
||||
{
|
||||
int cnt = 0;
|
||||
int eof = 0;
|
||||
@@ -221,7 +297,7 @@ static char *fs_mgr_getline(char *buf, int size, FILE *file)
|
||||
}
|
||||
}
|
||||
|
||||
static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
||||
{
|
||||
FILE *fstab_file;
|
||||
int cnt, entries;
|
||||
@@ -229,8 +305,9 @@ static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
char line[256];
|
||||
const char *delim = " \t";
|
||||
char *save_ptr, *p;
|
||||
struct fstab_rec *fstab;
|
||||
char *key_loc;
|
||||
struct fstab *fstab;
|
||||
struct fstab_rec *recs;
|
||||
struct fs_mgr_flag_values flag_vals;
|
||||
#define FS_OPTIONS_LEN 1024
|
||||
char tmp_fs_options[FS_OPTIONS_LEN];
|
||||
|
||||
@@ -241,7 +318,7 @@ static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
}
|
||||
|
||||
entries = 0;
|
||||
while (fs_mgr_getline(line, sizeof(line), fstab_file)) {
|
||||
while (fs_getline(line, sizeof(line), fstab_file)) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
len = strlen(line);
|
||||
if (line[len - 1] == '\n') {
|
||||
@@ -263,12 +340,16 @@ static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fstab = calloc(entries + 1, sizeof(struct fstab_rec));
|
||||
/* Allocate and init the fstab structure */
|
||||
fstab = calloc(1, sizeof(struct fstab));
|
||||
fstab->num_entries = entries;
|
||||
fstab->fstab_filename = strdup(fstab_path);
|
||||
fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
|
||||
|
||||
fseek(fstab_file, 0, SEEK_SET);
|
||||
|
||||
cnt = 0;
|
||||
while (fs_mgr_getline(line, sizeof(line), fstab_file)) {
|
||||
while (fs_getline(line, sizeof(line), fstab_file)) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
len = strlen(line);
|
||||
if (line[len - 1] == '\n') {
|
||||
@@ -297,41 +378,47 @@ static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
ERROR("Error parsing mount source\n");
|
||||
return 0;
|
||||
}
|
||||
fstab[cnt].blk_dev = strdup(p);
|
||||
fstab->recs[cnt].blk_device = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mnt_point\n");
|
||||
ERROR("Error parsing mount_point\n");
|
||||
return 0;
|
||||
}
|
||||
fstab[cnt].mnt_point = strdup(p);
|
||||
fstab->recs[cnt].mount_point = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_type\n");
|
||||
return 0;
|
||||
}
|
||||
fstab[cnt].type = strdup(p);
|
||||
fstab->recs[cnt].fs_type = strdup(p);
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing mount_flags\n");
|
||||
return 0;
|
||||
}
|
||||
tmp_fs_options[0] = '\0';
|
||||
fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN);
|
||||
fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
|
||||
tmp_fs_options, FS_OPTIONS_LEN);
|
||||
|
||||
/* fs_options are optional */
|
||||
if (tmp_fs_options[0]) {
|
||||
fstab[cnt].fs_options = strdup(tmp_fs_options);
|
||||
fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
|
||||
} else {
|
||||
fstab[cnt].fs_options = NULL;
|
||||
fstab->recs[cnt].fs_options = NULL;
|
||||
}
|
||||
|
||||
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||
ERROR("Error parsing fs_mgr_options\n");
|
||||
return 0;
|
||||
}
|
||||
fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0);
|
||||
fstab[cnt].key_loc = key_loc;
|
||||
|
||||
fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
|
||||
&flag_vals, NULL, 0);
|
||||
fstab->recs[cnt].key_loc = flag_vals.key_loc;
|
||||
fstab->recs[cnt].length = flag_vals.part_length;
|
||||
fstab->recs[cnt].label = flag_vals.label;
|
||||
fstab->recs[cnt].partnum = flag_vals.partnum;
|
||||
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
|
||||
fstab->recs[cnt].zram_size = flag_vals.zram_size;
|
||||
cnt++;
|
||||
}
|
||||
fclose(fstab_file);
|
||||
@@ -339,46 +426,76 @@ static struct fstab_rec *read_fstab(char *fstab_path)
|
||||
return fstab;
|
||||
}
|
||||
|
||||
static void free_fstab(struct fstab_rec *fstab)
|
||||
void fs_mgr_free_fstab(struct fstab *fstab)
|
||||
{
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
while (fstab[i].blk_dev) {
|
||||
if (!fstab) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Free the pointers return by strdup(3) */
|
||||
free(fstab[i].blk_dev);
|
||||
free(fstab[i].mnt_point);
|
||||
free(fstab[i].type);
|
||||
free(fstab[i].fs_options);
|
||||
free(fstab[i].key_loc);
|
||||
|
||||
free(fstab->recs[i].blk_device);
|
||||
free(fstab->recs[i].mount_point);
|
||||
free(fstab->recs[i].fs_type);
|
||||
free(fstab->recs[i].fs_options);
|
||||
free(fstab->recs[i].key_loc);
|
||||
free(fstab->recs[i].label);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Free the actual fstab array created by calloc(3) */
|
||||
/* Free the fstab_recs array created by calloc(3) */
|
||||
free(fstab->recs);
|
||||
|
||||
/* Free the fstab filename */
|
||||
free(fstab->fstab_filename);
|
||||
|
||||
/* Free fstab */
|
||||
free(fstab);
|
||||
}
|
||||
|
||||
static void check_fs(char *blk_dev, char *type)
|
||||
static void check_fs(char *blk_device, char *fs_type, char *target)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
int ret;
|
||||
long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
|
||||
char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
|
||||
char *e2fsck_argv[] = {
|
||||
E2FSCK_BIN,
|
||||
"-y",
|
||||
blk_device
|
||||
};
|
||||
|
||||
/* Check for the types of filesystems we know how to check */
|
||||
if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) {
|
||||
INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev);
|
||||
pid = fork();
|
||||
if (pid > 0) {
|
||||
/* Parent, wait for the child to return */
|
||||
waitpid(pid, &status, 0);
|
||||
} else if (pid == 0) {
|
||||
/* child, run checker */
|
||||
execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL);
|
||||
if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
|
||||
/*
|
||||
* First try to mount and unmount the filesystem. We do this because
|
||||
* the kernel is more efficient than e2fsck in running the journal and
|
||||
* processing orphaned inodes, and on at least one device with a
|
||||
* performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
|
||||
* to do what the kernel does in about a second.
|
||||
*
|
||||
* After mounting and unmounting the filesystem, run e2fsck, and if an
|
||||
* error is recorded in the filesystem superblock, e2fsck will do a full
|
||||
* check. Otherwise, it does nothing. If the kernel cannot mount the
|
||||
* filesytsem due to an error, e2fsck is still run to do a full check
|
||||
* fix the filesystem.
|
||||
*/
|
||||
ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
|
||||
if (!ret) {
|
||||
umount(target);
|
||||
}
|
||||
|
||||
/* Only gets here on error */
|
||||
ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN);
|
||||
} else {
|
||||
INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
|
||||
|
||||
ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
|
||||
&status, true, LOG_KLOG | LOG_FILE,
|
||||
true, FSCK_LOG_FILE);
|
||||
|
||||
if (ret < 0) {
|
||||
/* No need to check for error in fork, we can't really handle it now */
|
||||
ERROR("Fork failed trying to run %s\n", E2FSCK_BIN);
|
||||
ERROR("Failed trying to run %s\n", E2FSCK_BIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,6 +513,43 @@ static void remove_trailing_slashes(char *n)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the given block device as read-only, using the BLKROSET ioctl.
|
||||
* Return 0 on success, and -1 on error.
|
||||
*/
|
||||
static void fs_set_blk_ro(const char *blockdev)
|
||||
{
|
||||
int fd;
|
||||
int ON = 1;
|
||||
|
||||
fd = open(blockdev, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
// should never happen
|
||||
return;
|
||||
}
|
||||
|
||||
ioctl(fd, BLKROSET, &ON);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* __mount(): wrapper around the mount() system call which also
|
||||
* sets the underlying block device to read-only if the mount is read-only.
|
||||
* See "man 2 mount" for return values.
|
||||
*/
|
||||
static int __mount(const char *source, const char *target,
|
||||
const char *filesystemtype, unsigned long mountflags,
|
||||
const void *data)
|
||||
{
|
||||
int ret = mount(source, target, filesystemtype, mountflags, data);
|
||||
|
||||
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
|
||||
fs_set_blk_ro(source);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fs_match(char *in1, char *in2)
|
||||
{
|
||||
char *n1;
|
||||
@@ -416,49 +570,71 @@ static int fs_match(char *in1, char *in2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fs_mgr_mount_all(char *fstab_file)
|
||||
int fs_mgr_mount_all(struct fstab *fstab)
|
||||
{
|
||||
int i = 0;
|
||||
int encrypted = 0;
|
||||
int ret = -1;
|
||||
int mret;
|
||||
struct fstab_rec *fstab = 0;
|
||||
|
||||
if (!(fstab = read_fstab(fstab_file))) {
|
||||
if (!fstab) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; fstab[i].blk_dev; i++) {
|
||||
if (fstab[i].fs_mgr_flags & MF_WAIT) {
|
||||
wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Don't mount entries that are managed by vold */
|
||||
if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fstab[i].fs_mgr_flags & MF_CHECK) {
|
||||
check_fs(fstab[i].blk_dev, fstab[i].type);
|
||||
/* Skip swap and raw partition entries such as boot, recovery, etc */
|
||||
if (!strcmp(fstab->recs[i].fs_type, "swap") ||
|
||||
!strcmp(fstab->recs[i].fs_type, "emmc") ||
|
||||
!strcmp(fstab->recs[i].fs_type, "mtd")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type,
|
||||
fstab[i].flags, fstab[i].fs_options);
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
|
||||
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
|
||||
check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
|
||||
fstab->recs[i].mount_point);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) {
|
||||
if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
|
||||
ERROR("Could not set up verified partition, skipping!");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
|
||||
fstab->recs[i].fs_type, fstab->recs[i].flags,
|
||||
fstab->recs[i].fs_options);
|
||||
|
||||
if (!mret) {
|
||||
/* Success! Go get the next one */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* mount(2) returned an error, check if it's encrypted and deal with it */
|
||||
if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) {
|
||||
if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) &&
|
||||
!partition_wiped(fstab->recs[i].blk_device)) {
|
||||
/* Need to mount a tmpfs at this mountpoint for now, and set
|
||||
* properties that vold will query later for decrypting
|
||||
*/
|
||||
if (mount("tmpfs", fstab[i].mnt_point, "tmpfs",
|
||||
if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs",
|
||||
MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
|
||||
ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n",
|
||||
fstab[i].mnt_point);
|
||||
fstab->recs[i].mount_point);
|
||||
goto out;
|
||||
}
|
||||
encrypted = 1;
|
||||
} else {
|
||||
ERROR("Cannot mount filesystem on %s at %s\n",
|
||||
fstab[i].blk_dev, fstab[i].mnt_point);
|
||||
fstab->recs[i].blk_device, fstab->recs[i].mount_point);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -470,49 +646,65 @@ int fs_mgr_mount_all(char *fstab_file)
|
||||
}
|
||||
|
||||
out:
|
||||
free_fstab(fstab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the
|
||||
/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
|
||||
* tmp mount we do to check the user password
|
||||
*/
|
||||
int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point)
|
||||
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
|
||||
char *tmp_mount_point)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
struct fstab_rec *fstab = 0;
|
||||
char *m;
|
||||
|
||||
if (!(fstab = read_fstab(fstab_file))) {
|
||||
if (!fstab) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; fstab[i].blk_dev; i++) {
|
||||
if (!fs_match(fstab[i].mnt_point, n_name)) {
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
if (!fs_match(fstab->recs[i].mount_point, n_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found our match */
|
||||
/* First check the filesystem if requested */
|
||||
if (fstab[i].fs_mgr_flags & MF_WAIT) {
|
||||
wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
|
||||
/* If this swap or a raw partition, report an error */
|
||||
if (!strcmp(fstab->recs[i].fs_type, "swap") ||
|
||||
!strcmp(fstab->recs[i].fs_type, "emmc") ||
|
||||
!strcmp(fstab->recs[i].fs_type, "mtd")) {
|
||||
ERROR("Cannot mount filesystem of type %s on %s\n",
|
||||
fstab->recs[i].fs_type, n_blk_device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((fstab[i].fs_mgr_flags & MF_CHECK) && strcmp("ext4", fstab[i].type) != 0) {
|
||||
check_fs(fstab[i].blk_dev, fstab[i].type);
|
||||
/* First check the filesystem if requested */
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
|
||||
wait_for_file(n_blk_device, WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
|
||||
check_fs(n_blk_device, fstab->recs[i].fs_type,
|
||||
fstab->recs[i].mount_point);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) {
|
||||
if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
|
||||
ERROR("Could not set up verified partition, skipping!");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now mount it where requested */
|
||||
if (tmp_mnt_point) {
|
||||
m = tmp_mnt_point;
|
||||
if (tmp_mount_point) {
|
||||
m = tmp_mount_point;
|
||||
} else {
|
||||
m = fstab[i].mnt_point;
|
||||
m = fstab->recs[i].mount_point;
|
||||
}
|
||||
if (mount(n_blk_dev, m, fstab[i].type,
|
||||
fstab[i].flags, fstab[i].fs_options)) {
|
||||
if (__mount(n_blk_device, m, fstab->recs[i].fs_type,
|
||||
fstab->recs[i].flags, fstab->recs[i].fs_options)) {
|
||||
ERROR("Cannot mount filesystem on %s at %s\n",
|
||||
n_blk_dev, m);
|
||||
n_blk_device, m);
|
||||
goto out;
|
||||
} else {
|
||||
ret = 0;
|
||||
@@ -521,10 +713,9 @@ int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_m
|
||||
}
|
||||
|
||||
/* We didn't find a match, say so and return an error */
|
||||
ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point);
|
||||
ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
|
||||
|
||||
out:
|
||||
free_fstab(fstab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -547,65 +738,211 @@ int fs_mgr_do_tmpfs_mount(char *n_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fs_mgr_unmount_all(char *fstab_file)
|
||||
int fs_mgr_unmount_all(struct fstab *fstab)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
struct fstab_rec *fstab = 0;
|
||||
|
||||
if (!(fstab = read_fstab(fstab_file))) {
|
||||
if (!fstab) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fstab[i].blk_dev) {
|
||||
if (umount(fstab[i].mnt_point)) {
|
||||
ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point);
|
||||
while (fstab->recs[i].blk_device) {
|
||||
if (umount(fstab->recs[i].mount_point)) {
|
||||
ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point);
|
||||
ret = -1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
free_fstab(fstab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This must be called after mount_all, because the mkswap command needs to be
|
||||
* available.
|
||||
*/
|
||||
int fs_mgr_swapon_all(struct fstab *fstab)
|
||||
{
|
||||
int i = 0;
|
||||
int flags = 0;
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
int status;
|
||||
char *mkswap_argv[2] = {
|
||||
MKSWAP_BIN,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (!fstab) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Skip non-swap entries */
|
||||
if (strcmp(fstab->recs[i].fs_type, "swap")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fstab->recs[i].zram_size > 0) {
|
||||
/* A zram_size was specified, so we need to configure the
|
||||
* device. There is no point in having multiple zram devices
|
||||
* on a system (all the memory comes from the same pool) so
|
||||
* we can assume the device number is 0.
|
||||
*/
|
||||
FILE *zram_fp;
|
||||
|
||||
zram_fp = fopen(ZRAM_CONF_DEV, "r+");
|
||||
if (zram_fp == NULL) {
|
||||
ERROR("Unable to open zram conf device " ZRAM_CONF_DEV);
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size);
|
||||
fclose(zram_fp);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
|
||||
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
/* Initialize the swap area */
|
||||
mkswap_argv[1] = fstab->recs[i].blk_device;
|
||||
err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
|
||||
&status, true, LOG_KLOG, false, NULL);
|
||||
if (err) {
|
||||
ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If -1, then no priority was specified in fstab, so don't set
|
||||
* SWAP_FLAG_PREFER or encode the priority */
|
||||
if (fstab->recs[i].swap_prio >= 0) {
|
||||
flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
|
||||
SWAP_FLAG_PRIO_MASK;
|
||||
flags |= SWAP_FLAG_PREFER;
|
||||
} else {
|
||||
flags = 0;
|
||||
}
|
||||
// requires sys/swap.h which is not available in older trees
|
||||
// this entire function does not appear to be used for decrypt
|
||||
err = -1; //swapon(fstab->recs[i].blk_device, flags);
|
||||
if (err) {
|
||||
ERROR("swapon failed for %s\n", fstab->recs[i].blk_device);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* key_loc must be at least PROPERTY_VALUE_MAX bytes long
|
||||
*
|
||||
* real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long
|
||||
* real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
|
||||
*/
|
||||
int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size)
|
||||
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
|
||||
{
|
||||
int i = 0;
|
||||
struct fstab_rec *fstab = 0;
|
||||
|
||||
if (!(fstab = read_fstab(fstab_file))) {
|
||||
if (!fstab) {
|
||||
return -1;
|
||||
}
|
||||
/* Initialize return values to null strings */
|
||||
if (key_loc) {
|
||||
*key_loc = '\0';
|
||||
}
|
||||
if (real_blk_dev) {
|
||||
*real_blk_dev = '\0';
|
||||
if (real_blk_device) {
|
||||
*real_blk_device = '\0';
|
||||
}
|
||||
|
||||
/* Look for the encryptable partition to find the data */
|
||||
for (i = 0; fstab[i].blk_dev; i++) {
|
||||
if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) {
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
/* Don't deal with vold managed enryptable partitions here */
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
|
||||
continue;
|
||||
}
|
||||
if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found a match */
|
||||
if (key_loc) {
|
||||
strlcpy(key_loc, fstab[i].key_loc, size);
|
||||
strlcpy(key_loc, fstab->recs[i].key_loc, size);
|
||||
}
|
||||
if (real_blk_dev) {
|
||||
strlcpy(real_blk_dev, fstab[i].blk_dev, size);
|
||||
if (real_blk_device) {
|
||||
strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
free_fstab(fstab);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add an entry to the fstab, and return 0 on success or -1 on error */
|
||||
int fs_mgr_add_entry(struct fstab *fstab,
|
||||
const char *mount_point, const char *fs_type,
|
||||
const char *blk_device, long long length)
|
||||
{
|
||||
struct fstab_rec *new_fstab_recs;
|
||||
int n = fstab->num_entries;
|
||||
|
||||
new_fstab_recs = (struct fstab_rec *)
|
||||
realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
|
||||
|
||||
if (!new_fstab_recs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A new entry was added, so initialize it */
|
||||
memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
|
||||
new_fstab_recs[n].mount_point = strdup(mount_point);
|
||||
new_fstab_recs[n].fs_type = strdup(fs_type);
|
||||
new_fstab_recs[n].blk_device = strdup(blk_device);
|
||||
new_fstab_recs[n].length = 0;
|
||||
|
||||
/* Update the fstab struct */
|
||||
fstab->recs = new_fstab_recs;
|
||||
fstab->num_entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fstab) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < fstab->num_entries; i++) {
|
||||
int len = strlen(fstab->recs[i].mount_point);
|
||||
if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
|
||||
(path[len] == '\0' || path[len] == '/')) {
|
||||
return &fstab->recs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_VOLDMANAGED;
|
||||
}
|
||||
|
||||
int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NONREMOVABLE;
|
||||
}
|
||||
|
||||
int fs_mgr_is_encryptable(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_CRYPT;
|
||||
}
|
||||
|
||||
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
|
||||
{
|
||||
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ int main(int argc, char *argv[])
|
||||
int n_flag=0;
|
||||
char *n_name;
|
||||
char *n_blk_dev;
|
||||
char *fstab;
|
||||
char *fstab_file;
|
||||
struct fstab *fstab;
|
||||
|
||||
klog_init();
|
||||
klog_set_level(6);
|
||||
@@ -90,7 +91,9 @@ int main(int argc, char *argv[])
|
||||
parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev);
|
||||
|
||||
/* The name of the fstab file is last, after the option */
|
||||
fstab = argv[argc - 1];
|
||||
fstab_file = argv[argc - 1];
|
||||
|
||||
fstab = fs_mgr_read_fstab(fstab_file);
|
||||
|
||||
if (a_flag) {
|
||||
return fs_mgr_mount_all(fstab);
|
||||
@@ -103,6 +106,8 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fs_mgr_free_fstab(fstab);
|
||||
|
||||
/* Should not get here */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+21
-16
@@ -25,17 +25,7 @@
|
||||
|
||||
#define CRYPTO_TMPFS_OPTIONS "size=128m,mode=0771,uid=1000,gid=1000"
|
||||
|
||||
struct fstab_rec {
|
||||
char *blk_dev;
|
||||
char *mnt_point;
|
||||
char *type;
|
||||
unsigned long flags;
|
||||
char *fs_options;
|
||||
int fs_mgr_flags;
|
||||
char *key_loc;
|
||||
};
|
||||
|
||||
#define WAIT_TIMEOUT 5
|
||||
#define WAIT_TIMEOUT 20
|
||||
|
||||
/* fstab has the following format:
|
||||
*
|
||||
@@ -59,8 +49,8 @@ struct fstab_rec {
|
||||
* run an fscheck program on the <source> before mounting the filesystem.
|
||||
* If check is specifed on a read-only filesystem, it is ignored.
|
||||
* Also, "encryptable" means that filesystem can be encrypted.
|
||||
* The "encryptable" flag _MUST_ be followed by a : and a string which
|
||||
* is the location of the encryption keys. I can either be a path
|
||||
* The "encryptable" flag _MUST_ be followed by a = and a string which
|
||||
* is the location of the encryption keys. It can either be a path
|
||||
* to a file or partition which contains the keys, or the word "footer"
|
||||
* which means the keys are in the last 16 Kbytes of the partition
|
||||
* containing the filesystem.
|
||||
@@ -72,9 +62,24 @@ struct fstab_rec {
|
||||
*
|
||||
*/
|
||||
|
||||
#define MF_WAIT 0x1
|
||||
#define MF_CHECK 0x2
|
||||
#define MF_CRYPT 0x4
|
||||
#define MF_WAIT 0x1
|
||||
#define MF_CHECK 0x2
|
||||
#define MF_CRYPT 0x4
|
||||
#define MF_NONREMOVABLE 0x8
|
||||
#define MF_VOLDMANAGED 0x10
|
||||
#define MF_LENGTH 0x20
|
||||
#define MF_RECOVERYONLY 0x40
|
||||
#define MF_SWAPPRIO 0x80
|
||||
#define MF_ZRAMSIZE 0x100
|
||||
#define MF_VERIFY 0x200
|
||||
/*
|
||||
* There is no emulated sdcard daemon running on /data/media on this device,
|
||||
* so treat the physical SD card as the only external storage device,
|
||||
* a la the Nexus One.
|
||||
*/
|
||||
#define MF_NOEMULATEDSD 0x400
|
||||
|
||||
#define DM_BUF_SIZE 4096
|
||||
|
||||
#endif /* __CORE_FS_MGR_PRIV_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
int fs_mgr_setup_verity(struct fstab_rec *fstab);
|
||||
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <libgen.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <logwrap/logwrap.h>
|
||||
|
||||
#include "mincrypt/rsa.h"
|
||||
#include "mincrypt/sha.h"
|
||||
#include "mincrypt/sha256.h"
|
||||
|
||||
#include "ext4_utils.h"
|
||||
#include "ext4.h"
|
||||
|
||||
#include "fs_mgr_priv.h"
|
||||
#include "fs_mgr_priv_verity.h"
|
||||
|
||||
#define VERITY_METADATA_SIZE 32768
|
||||
#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
|
||||
#define VERITY_TABLE_RSA_KEY "/verity_key"
|
||||
|
||||
extern struct fs_info info;
|
||||
|
||||
static RSAPublicKey *load_key(char *path)
|
||||
{
|
||||
FILE *f;
|
||||
RSAPublicKey *key;
|
||||
|
||||
key = malloc(sizeof(RSAPublicKey));
|
||||
if (!key) {
|
||||
ERROR("Can't malloc key\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = fopen(path, "r");
|
||||
if (!f) {
|
||||
ERROR("Can't open '%s'\n", path);
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!fread(key, sizeof(*key), 1, f)) {
|
||||
ERROR("Could not read key!");
|
||||
fclose(f);
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (key->len != RSANUMWORDS) {
|
||||
ERROR("Invalid key length %d\n", key->len);
|
||||
fclose(f);
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return key;
|
||||
}
|
||||
|
||||
static int verify_table(char *signature, char *table, int table_length)
|
||||
{
|
||||
int fd;
|
||||
RSAPublicKey *key;
|
||||
uint8_t hash_buf[SHA_DIGEST_SIZE];
|
||||
int retval = -1;
|
||||
|
||||
// Hash the table
|
||||
SHA_hash((uint8_t*)table, table_length, hash_buf);
|
||||
|
||||
// Now get the public key from the keyfile
|
||||
key = load_key(VERITY_TABLE_RSA_KEY);
|
||||
if (!key) {
|
||||
ERROR("Couldn't load verity keys");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// verify the result
|
||||
if (!RSA_verify(key,
|
||||
(uint8_t*) signature,
|
||||
RSANUMBYTES,
|
||||
(uint8_t*) hash_buf,
|
||||
SHA_DIGEST_SIZE)) {
|
||||
ERROR("Couldn't verify table.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
free(key);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int get_target_device_size(char *blk_device, uint64_t *device_size)
|
||||
{
|
||||
int data_device;
|
||||
struct ext4_super_block sb;
|
||||
|
||||
data_device = open(blk_device, O_RDONLY);
|
||||
if (data_device < 0) {
|
||||
ERROR("Error opening block device (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek64(data_device, 1024, SEEK_SET) < 0) {
|
||||
ERROR("Error seeking to superblock");
|
||||
close(data_device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
|
||||
ERROR("Error reading superblock");
|
||||
close(data_device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ext4_parse_sb(&sb);
|
||||
*device_size = info.len;
|
||||
|
||||
close(data_device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_verity_metadata(char *block_device, char **signature, char **table)
|
||||
{
|
||||
unsigned magic_number;
|
||||
unsigned table_length;
|
||||
uint64_t device_length;
|
||||
int protocol_version;
|
||||
FILE *device;
|
||||
int retval = -1;
|
||||
|
||||
device = fopen(block_device, "r");
|
||||
if (!device) {
|
||||
ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
// find the start of the verity metadata
|
||||
if (get_target_device_size(block_device, &device_length) < 0) {
|
||||
ERROR("Could not get target device size.\n");
|
||||
goto out;
|
||||
}
|
||||
if (fseek(device, device_length, SEEK_SET) < 0) {
|
||||
ERROR("Could not seek to start of verity metadata block.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check the magic number
|
||||
if (!fread(&magic_number, sizeof(int), 1, device)) {
|
||||
ERROR("Couldn't read magic number!\n");
|
||||
goto out;
|
||||
}
|
||||
if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
|
||||
ERROR("Couldn't find verity metadata at offset %llu!\n", device_length);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// check the protocol version
|
||||
if (!fread(&protocol_version, sizeof(int), 1, device)) {
|
||||
ERROR("Couldn't read verity metadata protocol version!\n");
|
||||
goto out;
|
||||
}
|
||||
if (protocol_version != 0) {
|
||||
ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// get the signature
|
||||
*signature = (char*) malloc(RSANUMBYTES * sizeof(char));
|
||||
if (!*signature) {
|
||||
ERROR("Couldn't allocate memory for signature!\n");
|
||||
goto out;
|
||||
}
|
||||
if (!fread(*signature, RSANUMBYTES, 1, device)) {
|
||||
ERROR("Couldn't read signature from verity metadata!\n");
|
||||
free(*signature);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// get the size of the table
|
||||
if (!fread(&table_length, sizeof(int), 1, device)) {
|
||||
ERROR("Couldn't get the size of the verity table from metadata!\n");
|
||||
free(*signature);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// get the table + null terminator
|
||||
table_length += 1;
|
||||
*table = malloc(table_length);
|
||||
if(!*table) {
|
||||
ERROR("Couldn't allocate memory for verity table!\n");
|
||||
goto out;
|
||||
}
|
||||
if (!fgets(*table, table_length, device)) {
|
||||
ERROR("Couldn't read the verity table from metadata!\n");
|
||||
free(*table);
|
||||
free(*signature);
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
if (device)
|
||||
fclose(device);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags)
|
||||
{
|
||||
memset(io, 0, DM_BUF_SIZE);
|
||||
io->data_size = DM_BUF_SIZE;
|
||||
io->data_start = sizeof(struct dm_ioctl);
|
||||
io->version[0] = 4;
|
||||
io->version[1] = 0;
|
||||
io->version[2] = 0;
|
||||
io->flags = flags | DM_READONLY_FLAG;
|
||||
if (name) {
|
||||
strlcpy(io->name, name, sizeof(io->name));
|
||||
}
|
||||
}
|
||||
|
||||
static int create_verity_device(struct dm_ioctl *io, char *name, int fd)
|
||||
{
|
||||
verity_ioctl_init(io, name, 1);
|
||||
if (ioctl(fd, DM_DEV_CREATE, io)) {
|
||||
ERROR("Error creating device mapping (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name)
|
||||
{
|
||||
verity_ioctl_init(io, name, 0);
|
||||
if (ioctl(fd, DM_DEV_STATUS, io)) {
|
||||
ERROR("Error fetching verity device number (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
|
||||
if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) {
|
||||
ERROR("Error getting verity block device name (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table)
|
||||
{
|
||||
char *verity_params;
|
||||
char *buffer = (char*) io;
|
||||
uint64_t device_size = 0;
|
||||
|
||||
if (get_target_device_size(blockdev, &device_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
|
||||
|
||||
struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
|
||||
|
||||
// set tgt arguments here
|
||||
io->target_count = 1;
|
||||
tgt->status=0;
|
||||
tgt->sector_start=0;
|
||||
tgt->length=device_size/512;
|
||||
strcpy(tgt->target_type, "verity");
|
||||
|
||||
// build the verity params here
|
||||
verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
|
||||
if (sprintf(verity_params, "%s", table) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set next target boundary
|
||||
verity_params += strlen(verity_params) + 1;
|
||||
verity_params = (char*) (((unsigned long)verity_params + 7) & ~8);
|
||||
tgt->next = verity_params - buffer;
|
||||
|
||||
// send the ioctl to load the verity table
|
||||
if (ioctl(fd, DM_TABLE_LOAD, io)) {
|
||||
ERROR("Error loading verity table (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resume_verity_table(struct dm_ioctl *io, char *name, int fd)
|
||||
{
|
||||
verity_ioctl_init(io, name, 0);
|
||||
if (ioctl(fd, DM_DEV_SUSPEND, io)) {
|
||||
ERROR("Error activating verity device (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_access(char *device) {
|
||||
int tries = 25;
|
||||
while (tries--) {
|
||||
if (!access(device, F_OK) || errno != ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
usleep(40 * 1000);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fs_mgr_setup_verity(struct fstab_rec *fstab) {
|
||||
|
||||
int retval = -1;
|
||||
|
||||
char *verity_blk_name;
|
||||
char *verity_table;
|
||||
char *verity_table_signature;
|
||||
|
||||
char buffer[DM_BUF_SIZE];
|
||||
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
|
||||
char *mount_point = basename(fstab->mount_point);
|
||||
|
||||
// set the dm_ioctl flags
|
||||
io->flags |= 1;
|
||||
io->target_count = 1;
|
||||
|
||||
// get the device mapper fd
|
||||
int fd;
|
||||
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
|
||||
ERROR("Error opening device mapper (%s)", strerror(errno));
|
||||
return retval;
|
||||
}
|
||||
|
||||
// create the device
|
||||
if (create_verity_device(io, mount_point, fd) < 0) {
|
||||
ERROR("Couldn't create verity device!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// get the name of the device file
|
||||
if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
|
||||
ERROR("Couldn't get verity device number!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// read the verity block at the end of the block device
|
||||
if (read_verity_metadata(fstab->blk_device,
|
||||
&verity_table_signature,
|
||||
&verity_table) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// verify the signature on the table
|
||||
if (verify_table(verity_table_signature,
|
||||
verity_table,
|
||||
strlen(verity_table)) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// load the verity mapping table
|
||||
if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// activate the device
|
||||
if (resume_verity_table(io, mount_point, fd) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// assign the new verity block device as the block device
|
||||
free(fstab->blk_device);
|
||||
fstab->blk_device = verity_blk_name;
|
||||
|
||||
// make sure we've set everything up properly
|
||||
if (test_access(fstab->blk_device) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
@@ -17,11 +17,56 @@
|
||||
#ifndef __CORE_FS_MGR_H
|
||||
#define __CORE_FS_MGR_H
|
||||
|
||||
int fs_mgr_mount_all(char *fstab_file);
|
||||
int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point);
|
||||
#include <stdint.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct fstab {
|
||||
int num_entries;
|
||||
struct fstab_rec *recs;
|
||||
char *fstab_filename;
|
||||
};
|
||||
|
||||
struct fstab_rec {
|
||||
char *blk_device;
|
||||
char *mount_point;
|
||||
char *fs_type;
|
||||
unsigned long flags;
|
||||
char *fs_options;
|
||||
int fs_mgr_flags;
|
||||
char *key_loc;
|
||||
char *verity_loc;
|
||||
long long length;
|
||||
char *label;
|
||||
int partnum;
|
||||
int swap_prio;
|
||||
unsigned int zram_size;
|
||||
};
|
||||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
|
||||
void fs_mgr_free_fstab(struct fstab *fstab);
|
||||
int fs_mgr_mount_all(struct fstab *fstab);
|
||||
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
|
||||
char *tmp_mount_point);
|
||||
int fs_mgr_do_tmpfs_mount(char *n_name);
|
||||
int fs_mgr_unmount_all(char *fstab_file);
|
||||
int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size);
|
||||
int fs_mgr_unmount_all(struct fstab *fstab);
|
||||
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
|
||||
char *real_blk_device, int size);
|
||||
int fs_mgr_add_entry(struct fstab *fstab,
|
||||
const char *mount_point, const char *fs_type,
|
||||
const char *blk_device, long long length);
|
||||
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
|
||||
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
|
||||
int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
|
||||
int fs_mgr_is_encryptable(struct fstab_rec *fstab);
|
||||
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
|
||||
int fs_mgr_swapon_all(struct fstab *fstab);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_FS_MGR_H */
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ LOCAL_MODULE_TAGS := eng
|
||||
LOCAL_MODULES_TAGS = optional
|
||||
LOCAL_CFLAGS =
|
||||
LOCAL_SRC_FILES = cryptfs.c
|
||||
LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include
|
||||
LOCAL_SHARED_LIBRARIES += libc liblog libcutils libcrypto
|
||||
LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp
|
||||
LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include bootable/recovery/crypto/scrypt/lib/crypto
|
||||
LOCAL_SHARED_LIBRARIES += libc liblog libcutils libcrypto libext4_utils
|
||||
LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp libscrypttwrp_static liblogwraptwrp libmincrypttwrp
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
+892
-328
File diff suppressed because it is too large
Load Diff
+78
-11
@@ -15,22 +15,31 @@
|
||||
*/
|
||||
|
||||
/* This structure starts 16,384 bytes before the end of a hardware
|
||||
* partition that is encrypted.
|
||||
* Immediately following this structure is the encrypted key.
|
||||
* The keysize field tells how long the key is, in bytes.
|
||||
* Then there is 32 bytes of padding,
|
||||
* Finally there is the salt used with the user password.
|
||||
* The salt is fixed at 16 bytes long.
|
||||
* partition that is encrypted, or in a separate partition. It's location
|
||||
* is specified by a property set in init.<device>.rc.
|
||||
* The structure allocates 48 bytes for a key, but the real key size is
|
||||
* specified in the struct. Currently, the code is hardcoded to use 128
|
||||
* bit keys.
|
||||
* The fields after salt are only valid in rev 1.1 and later stuctures.
|
||||
* Obviously, the filesystem does not include the last 16 kbytes
|
||||
* of the partition.
|
||||
* of the partition if the crypt_mnt_ftr lives at the end of the
|
||||
* partition.
|
||||
*/
|
||||
|
||||
#include <cutils/properties.h>
|
||||
|
||||
/* The current cryptfs version */
|
||||
#define CURRENT_MAJOR_VERSION 1
|
||||
#define CURRENT_MINOR_VERSION 2
|
||||
|
||||
#define CRYPT_FOOTER_OFFSET 0x4000
|
||||
#define CRYPT_FOOTER_TO_PERSIST_OFFSET 0x1000
|
||||
#define CRYPT_PERSIST_DATA_SIZE 0x1000
|
||||
|
||||
#define MAX_CRYPTO_TYPE_NAME_LEN 64
|
||||
|
||||
#define MAX_KEY_LEN 48
|
||||
#define SALT_LEN 16
|
||||
#define KEY_TO_SALT_PADDING 32
|
||||
|
||||
/* definitions of flags in the structure below */
|
||||
#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
|
||||
@@ -38,9 +47,18 @@
|
||||
* clear when done before rebooting */
|
||||
|
||||
#define CRYPT_MNT_MAGIC 0xD0B5B1C4
|
||||
#define PERSIST_DATA_MAGIC 0xE950CD44
|
||||
|
||||
#define SCRYPT_PROP "ro.crypto.scrypt_params"
|
||||
#define SCRYPT_DEFAULTS { 15, 3, 1 }
|
||||
|
||||
/* Key Derivation Function algorithms */
|
||||
#define KDF_PBKDF2 1
|
||||
#define KDF_SCRYPT 2
|
||||
|
||||
#define __le32 unsigned int
|
||||
#define __le16 unsigned short int
|
||||
#define __le16 unsigned short int
|
||||
#define __le8 unsigned char
|
||||
|
||||
struct crypt_mnt_ftr {
|
||||
__le32 magic; /* See above */
|
||||
@@ -56,6 +74,48 @@ struct crypt_mnt_ftr {
|
||||
unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
|
||||
needed to decrypt this
|
||||
partition, null terminated */
|
||||
__le32 spare2; /* ignored */
|
||||
unsigned char master_key[MAX_KEY_LEN]; /* The encrypted key for decrypting the filesystem */
|
||||
unsigned char salt[SALT_LEN]; /* The salt used for this encryption */
|
||||
__le64 persist_data_offset[2]; /* Absolute offset to both copies of crypt_persist_data
|
||||
* on device with that info, either the footer of the
|
||||
* real_blkdevice or the metadata partition. */
|
||||
|
||||
__le32 persist_data_size; /* The number of bytes allocated to each copy of the
|
||||
* persistent data table*/
|
||||
|
||||
__le8 kdf_type; /* The key derivation function used. */
|
||||
|
||||
/* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */
|
||||
__le8 N_factor; /* (1 << N) */
|
||||
__le8 r_factor; /* (1 << r) */
|
||||
__le8 p_factor; /* (1 << p) */
|
||||
};
|
||||
|
||||
/* Persistant data that should be available before decryption.
|
||||
* Things like airplane mode, locale and timezone are kept
|
||||
* here and can be retrieved by the CryptKeeper UI to properly
|
||||
* configure the phone before asking for the password
|
||||
* This is only valid if the major and minor version above
|
||||
* is set to 1.1 or higher.
|
||||
*
|
||||
* This is a 4K structure. There are 2 copies, and the code alternates
|
||||
* writing one and then clearing the previous one. The reading
|
||||
* code reads the first valid copy it finds, based on the magic number.
|
||||
* The absolute offset to the first of the two copies is kept in rev 1.1
|
||||
* and higher crypt_mnt_ftr structures.
|
||||
*/
|
||||
struct crypt_persist_entry {
|
||||
char key[PROPERTY_KEY_MAX];
|
||||
char val[PROPERTY_VALUE_MAX];
|
||||
};
|
||||
|
||||
/* Should be exactly 4K in size */
|
||||
struct crypt_persist_data {
|
||||
__le32 persist_magic;
|
||||
__le32 persist_valid_entries;
|
||||
__le32 persist_spare[30];
|
||||
struct crypt_persist_entry persist_entry[0];
|
||||
};
|
||||
|
||||
struct volume_info {
|
||||
@@ -67,12 +127,17 @@ struct volume_info {
|
||||
char crypto_blkdev[256];
|
||||
char label[256];
|
||||
};
|
||||
#define VOL_NONREMOVABLE 0x1
|
||||
#define VOL_ENCRYPTABLE 0x2
|
||||
#define VOL_NONREMOVABLE 0x1
|
||||
#define VOL_ENCRYPTABLE 0x2
|
||||
#define VOL_PRIMARY 0x4
|
||||
#define VOL_PROVIDES_ASEC 0x8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*kdf_func)(char *passwd, unsigned char *salt, unsigned char *ikey, void *params);
|
||||
|
||||
int cryptfs_crypto_complete(void);
|
||||
int cryptfs_check_passwd(char *pw);
|
||||
int cryptfs_verify_passwd(char *newpw);
|
||||
@@ -83,6 +148,8 @@ extern "C" {
|
||||
char *crypto_dev_path, unsigned int max_pathlen,
|
||||
int *new_major, int *new_minor);
|
||||
int cryptfs_revert_volume(const char *label);
|
||||
int cryptfs_getfield(char *fieldname, char *value, int len);
|
||||
int cryptfs_setfield(char *fieldname, char *value);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# ========================================================
|
||||
# Static library
|
||||
# ========================================================
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := liblogwraptwrp
|
||||
LOCAL_SRC_FILES := logwrap.c
|
||||
LOCAL_SHARED_LIBRARIES := libcutils liblog
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# ========================================================
|
||||
# Shared library
|
||||
# ========================================================
|
||||
#include $(CLEAR_VARS)
|
||||
#LOCAL_MODULE := liblogwrap
|
||||
#LOCAL_SHARED_LIBRARIES := libcutils liblog
|
||||
#LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap
|
||||
#LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
#LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
#include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
# ========================================================
|
||||
# Executable
|
||||
# ========================================================
|
||||
#include $(CLEAR_VARS)
|
||||
#LOCAL_SRC_FILES:= logwrapper.c
|
||||
#LOCAL_MODULE := logwrapper
|
||||
#LOCAL_STATIC_LIBRARIES := liblog liblogwrap libcutils
|
||||
#include $(BUILD_EXECUTABLE)
|
||||
@@ -0,0 +1,190 @@
|
||||
|
||||
Copyright (c) 2005-2008, 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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/* system/core/include/logwrap/logwrap.h
|
||||
*
|
||||
* Copyright 2013, 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.
|
||||
*/
|
||||
|
||||
#ifndef __LIBS_LOGWRAP_H
|
||||
#define __LIBS_LOGWRAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Run a command while logging its stdout and stderr
|
||||
*
|
||||
* WARNING: while this function is running it will clear all SIGCHLD handlers
|
||||
* if you rely on SIGCHLD in the caller there is a chance zombies will be
|
||||
* created if you're not calling waitpid after calling this. This function will
|
||||
* log a warning when it clears SIGCHLD for processes other than the child it
|
||||
* created.
|
||||
*
|
||||
* Arguments:
|
||||
* argc: the number of elements in argv
|
||||
* argv: an array of strings containing the command to be executed and its
|
||||
* arguments as separate strings. argv does not need to be
|
||||
* NULL-terminated
|
||||
* status: the equivalent child status as populated by wait(status). This
|
||||
* value is only valid when logwrap successfully completes. If NULL
|
||||
* the return value of the child will be the function's return value.
|
||||
* ignore_int_quit: set to true if you want to completely ignore SIGINT and
|
||||
* SIGQUIT while logwrap is running. This may force the end-user to
|
||||
* send a signal twice to signal the caller (once for the child, and
|
||||
* once for the caller)
|
||||
* log_target: Specify where to log the output of the child, either LOG_NONE,
|
||||
* LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel
|
||||
* log), or LOG_FILE (and you need to specify a pathname in the
|
||||
* file_path argument, otherwise pass NULL). These are bit fields,
|
||||
* and can be OR'ed together to log to multiple places.
|
||||
* abbreviated: If true, capture up to the first 100 lines and last 4K of
|
||||
* output from the child. The abbreviated output is not dumped to
|
||||
* the specified log until the child has exited.
|
||||
* file_path: if log_target has the LOG_FILE bit set, then this parameter
|
||||
* must be set to the pathname of the file to log to.
|
||||
*
|
||||
* Return value:
|
||||
* 0 when logwrap successfully run the child process and captured its status
|
||||
* -1 when an internal error occurred
|
||||
* -ECHILD if status is NULL and the child didn't exit properly
|
||||
* the return value of the child if it exited properly and status is NULL
|
||||
*
|
||||
*/
|
||||
|
||||
/* Values for the log_target parameter android_fork_execvp_ext() */
|
||||
#define LOG_NONE 0
|
||||
#define LOG_ALOG 1
|
||||
#define LOG_KLOG 2
|
||||
#define LOG_FILE 4
|
||||
|
||||
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
|
||||
int log_target, bool abbreviated, char *file_path);
|
||||
|
||||
/* Similar to above, except abbreviated logging is not available, and if logwrap
|
||||
* is true, logging is to the Android system log, and if false, there is no
|
||||
* logging.
|
||||
*/
|
||||
static inline int android_fork_execvp(int argc, char* argv[], int *status,
|
||||
bool ignore_int_quit, bool logwrap)
|
||||
{
|
||||
return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
|
||||
(logwrap ? LOG_ALOG : LOG_NONE), false, NULL);
|
||||
}
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __LIBS_LOGWRAP_H */
|
||||
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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 <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <poll.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <logwrap/logwrap.h>
|
||||
#include "private/android_filesystem_config.h"
|
||||
#include "cutils/log.h"
|
||||
#include <cutils/klog.h>
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define ERROR(fmt, args...) \
|
||||
do { \
|
||||
fprintf(stderr, fmt, ## args); \
|
||||
ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \
|
||||
} while(0)
|
||||
|
||||
#define FATAL_CHILD(fmt, args...) \
|
||||
do { \
|
||||
ERROR(fmt, ## args); \
|
||||
_exit(-1); \
|
||||
} while(0)
|
||||
|
||||
#define MAX_KLOG_TAG 16
|
||||
|
||||
/* This is a simple buffer that holds up to the first beginning_buf->buf_size
|
||||
* bytes of output from a command.
|
||||
*/
|
||||
#define BEGINNING_BUF_SIZE 0x1000
|
||||
struct beginning_buf {
|
||||
char *buf;
|
||||
size_t alloc_len;
|
||||
/* buf_size is the usable space, which is one less than the allocated size */
|
||||
size_t buf_size;
|
||||
size_t used_len;
|
||||
};
|
||||
|
||||
/* This is a circular buf that holds up to the last ending_buf->buf_size bytes
|
||||
* of output from a command after the first beginning_buf->buf_size bytes
|
||||
* (which are held in beginning_buf above).
|
||||
*/
|
||||
#define ENDING_BUF_SIZE 0x1000
|
||||
struct ending_buf {
|
||||
char *buf;
|
||||
ssize_t alloc_len;
|
||||
/* buf_size is the usable space, which is one less than the allocated size */
|
||||
ssize_t buf_size;
|
||||
ssize_t used_len;
|
||||
/* read and write offsets into the circular buffer */
|
||||
int read;
|
||||
int write;
|
||||
};
|
||||
|
||||
/* A structure to hold all the abbreviated buf data */
|
||||
struct abbr_buf {
|
||||
struct beginning_buf b_buf;
|
||||
struct ending_buf e_buf;
|
||||
int beginning_buf_full;
|
||||
};
|
||||
|
||||
/* Collect all the various bits of info needed for logging in one place. */
|
||||
struct log_info {
|
||||
int log_target;
|
||||
char klog_fmt[MAX_KLOG_TAG * 2];
|
||||
char *btag;
|
||||
bool abbreviated;
|
||||
FILE *fp;
|
||||
struct abbr_buf a_buf;
|
||||
};
|
||||
|
||||
/* Forware declaration */
|
||||
static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen);
|
||||
|
||||
/* Return 0 on success, and 1 when full */
|
||||
static int add_line_to_linear_buf(struct beginning_buf *b_buf,
|
||||
char *line, ssize_t line_len)
|
||||
{
|
||||
size_t new_len;
|
||||
char *new_buf;
|
||||
int full = 0;
|
||||
|
||||
if ((line_len + b_buf->used_len) > b_buf->buf_size) {
|
||||
full = 1;
|
||||
} else {
|
||||
/* Add to the end of the buf */
|
||||
memcpy(b_buf->buf + b_buf->used_len, line, line_len);
|
||||
b_buf->used_len += line_len;
|
||||
}
|
||||
|
||||
return full;
|
||||
}
|
||||
|
||||
static void add_line_to_circular_buf(struct ending_buf *e_buf,
|
||||
char *line, ssize_t line_len)
|
||||
{
|
||||
ssize_t free_len;
|
||||
ssize_t needed_space;
|
||||
char *new_buf;
|
||||
int cnt;
|
||||
|
||||
if (e_buf->buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (line_len > e_buf->buf_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
free_len = e_buf->buf_size - e_buf->used_len;
|
||||
|
||||
if (line_len > free_len) {
|
||||
/* remove oldest entries at read, and move read to make
|
||||
* room for the new string */
|
||||
needed_space = line_len - free_len;
|
||||
e_buf->read = (e_buf->read + needed_space) % e_buf->buf_size;
|
||||
e_buf->used_len -= needed_space;
|
||||
}
|
||||
|
||||
/* Copy the line into the circular buffer, dealing with possible
|
||||
* wraparound.
|
||||
*/
|
||||
cnt = MIN(line_len, e_buf->buf_size - e_buf->write);
|
||||
memcpy(e_buf->buf + e_buf->write, line, cnt);
|
||||
if (cnt < line_len) {
|
||||
memcpy(e_buf->buf, line + cnt, line_len - cnt);
|
||||
}
|
||||
e_buf->used_len += line_len;
|
||||
e_buf->write = (e_buf->write + line_len) % e_buf->buf_size;
|
||||
}
|
||||
|
||||
/* Log directly to the specified log */
|
||||
static void do_log_line(struct log_info *log_info, char *line) {
|
||||
if (log_info->log_target & LOG_KLOG) {
|
||||
klog_write(6, log_info->klog_fmt, line);
|
||||
}
|
||||
if (log_info->log_target & LOG_ALOG) {
|
||||
ALOG(LOG_INFO, log_info->btag, "%s", line);
|
||||
}
|
||||
if (log_info->log_target & LOG_FILE) {
|
||||
fprintf(log_info->fp, "%s\n", line);
|
||||
}
|
||||
}
|
||||
|
||||
/* Log to either the abbreviated buf, or directly to the specified log
|
||||
* via do_log_line() above.
|
||||
*/
|
||||
static void log_line(struct log_info *log_info, char *line, int len) {
|
||||
if (log_info->abbreviated) {
|
||||
add_line_to_abbr_buf(&log_info->a_buf, line, len);
|
||||
} else {
|
||||
do_log_line(log_info, line);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The kernel will take a maximum of 1024 bytes in any single write to
|
||||
* the kernel logging device file, so find and print each line one at
|
||||
* a time. The allocated size for buf should be at least 1 byte larger
|
||||
* than buf_size (the usable size of the buffer) to make sure there is
|
||||
* room to temporarily stuff a null byte to terminate a line for logging.
|
||||
*/
|
||||
static void print_buf_lines(struct log_info *log_info, char *buf, int buf_size)
|
||||
{
|
||||
char *line_start;
|
||||
char c;
|
||||
int line_len;
|
||||
int i;
|
||||
|
||||
line_start = buf;
|
||||
for (i = 0; i < buf_size; i++) {
|
||||
if (*(buf + i) == '\n') {
|
||||
/* Found a line ending, print the line and compute new line_start */
|
||||
/* Save the next char and replace with \0 */
|
||||
c = *(buf + i + 1);
|
||||
*(buf + i + 1) = '\0';
|
||||
do_log_line(log_info, line_start);
|
||||
/* Restore the saved char */
|
||||
*(buf + i + 1) = c;
|
||||
line_start = buf + i + 1;
|
||||
} else if (*(buf + i) == '\0') {
|
||||
/* The end of the buffer, print the last bit */
|
||||
do_log_line(log_info, line_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If the buffer was completely full, and didn't end with a newline, just
|
||||
* ignore the partial last line.
|
||||
*/
|
||||
}
|
||||
|
||||
static void init_abbr_buf(struct abbr_buf *a_buf) {
|
||||
char *new_buf;
|
||||
|
||||
memset(a_buf, 0, sizeof(struct abbr_buf));
|
||||
new_buf = malloc(BEGINNING_BUF_SIZE);
|
||||
if (new_buf) {
|
||||
a_buf->b_buf.buf = new_buf;
|
||||
a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE;
|
||||
a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1;
|
||||
}
|
||||
new_buf = malloc(ENDING_BUF_SIZE);
|
||||
if (new_buf) {
|
||||
a_buf->e_buf.buf = new_buf;
|
||||
a_buf->e_buf.alloc_len = ENDING_BUF_SIZE;
|
||||
a_buf->e_buf.buf_size = ENDING_BUF_SIZE - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_abbr_buf(struct abbr_buf *a_buf) {
|
||||
free(a_buf->b_buf.buf);
|
||||
free(a_buf->e_buf.buf);
|
||||
}
|
||||
|
||||
static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen) {
|
||||
if (!a_buf->beginning_buf_full) {
|
||||
a_buf->beginning_buf_full =
|
||||
add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
|
||||
}
|
||||
if (a_buf->beginning_buf_full) {
|
||||
add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_abbr_buf(struct log_info *log_info) {
|
||||
struct abbr_buf *a_buf = &log_info->a_buf;
|
||||
|
||||
/* Add the abbreviated output to the kernel log */
|
||||
if (a_buf->b_buf.alloc_len) {
|
||||
print_buf_lines(log_info, a_buf->b_buf.buf, a_buf->b_buf.used_len);
|
||||
}
|
||||
|
||||
/* Print an ellipsis to indicate that the buffer has wrapped or
|
||||
* is full, and some data was not logged.
|
||||
*/
|
||||
if (a_buf->e_buf.used_len == a_buf->e_buf.buf_size) {
|
||||
do_log_line(log_info, "...\n");
|
||||
}
|
||||
|
||||
if (a_buf->e_buf.used_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Simplest way to print the circular buffer is allocate a second buf
|
||||
* of the same size, and memcpy it so it's a simple linear buffer,
|
||||
* and then cal print_buf_lines on it */
|
||||
if (a_buf->e_buf.read < a_buf->e_buf.write) {
|
||||
/* no wrap around, just print it */
|
||||
print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read,
|
||||
a_buf->e_buf.used_len);
|
||||
} else {
|
||||
/* The circular buffer will always have at least 1 byte unused,
|
||||
* so by allocating alloc_len here we will have at least
|
||||
* 1 byte of space available as required by print_buf_lines().
|
||||
*/
|
||||
char * nbuf = malloc(a_buf->e_buf.alloc_len);
|
||||
if (!nbuf) {
|
||||
return;
|
||||
}
|
||||
int first_chunk_len = a_buf->e_buf.buf_size - a_buf->e_buf.read;
|
||||
memcpy(nbuf, a_buf->e_buf.buf + a_buf->e_buf.read, first_chunk_len);
|
||||
/* copy second chunk */
|
||||
memcpy(nbuf + first_chunk_len, a_buf->e_buf.buf, a_buf->e_buf.write);
|
||||
print_buf_lines(log_info, nbuf, first_chunk_len + a_buf->e_buf.write);
|
||||
free(nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static int parent(const char *tag, int parent_read, pid_t pid,
|
||||
int *chld_sts, int log_target, bool abbreviated, char *file_path) {
|
||||
int status = 0;
|
||||
char buffer[4096];
|
||||
struct pollfd poll_fds[] = {
|
||||
[0] = {
|
||||
.fd = parent_read,
|
||||
.events = POLLIN,
|
||||
},
|
||||
};
|
||||
int rc = 0;
|
||||
int fd;
|
||||
|
||||
struct log_info log_info;
|
||||
|
||||
int a = 0; // start index of unprocessed data
|
||||
int b = 0; // end index of unprocessed data
|
||||
int sz;
|
||||
bool found_child = false;
|
||||
char tmpbuf[256];
|
||||
|
||||
log_info.btag = basename(tag);
|
||||
if (!log_info.btag) {
|
||||
log_info.btag = (char*) tag;
|
||||
}
|
||||
|
||||
if (abbreviated && (log_target == LOG_NONE)) {
|
||||
abbreviated = 0;
|
||||
}
|
||||
if (abbreviated) {
|
||||
init_abbr_buf(&log_info.a_buf);
|
||||
}
|
||||
|
||||
if (log_target & LOG_KLOG) {
|
||||
snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
|
||||
"<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
|
||||
}
|
||||
|
||||
if ((log_target & LOG_FILE) && !file_path) {
|
||||
/* No file_path specified, clear the LOG_FILE bit */
|
||||
log_target &= ~LOG_FILE;
|
||||
}
|
||||
|
||||
if (log_target & LOG_FILE) {
|
||||
fd = open(file_path, O_WRONLY | O_CREAT, 0664);
|
||||
if (fd < 0) {
|
||||
ERROR("Cannot log to file %s\n", file_path);
|
||||
log_target &= ~LOG_FILE;
|
||||
} else {
|
||||
lseek(fd, 0, SEEK_END);
|
||||
log_info.fp = fdopen(fd, "a");
|
||||
}
|
||||
}
|
||||
|
||||
log_info.log_target = log_target;
|
||||
log_info.abbreviated = abbreviated;
|
||||
|
||||
while (!found_child) {
|
||||
if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
|
||||
ERROR("poll failed\n");
|
||||
rc = -1;
|
||||
goto err_poll;
|
||||
}
|
||||
|
||||
if (poll_fds[0].revents & POLLIN) {
|
||||
sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b);
|
||||
|
||||
sz += b;
|
||||
// Log one line at a time
|
||||
for (b = 0; b < sz; b++) {
|
||||
if (buffer[b] == '\r') {
|
||||
if (abbreviated) {
|
||||
/* The abbreviated logging code uses newline as
|
||||
* the line separator. Lucikly, the pty layer
|
||||
* helpfully cooks the output of the command
|
||||
* being run and inserts a CR before NL. So
|
||||
* I just change it to NL here when doing
|
||||
* abbreviated logging.
|
||||
*/
|
||||
buffer[b] = '\n';
|
||||
} else {
|
||||
buffer[b] = '\0';
|
||||
}
|
||||
} else if (buffer[b] == '\n') {
|
||||
buffer[b] = '\0';
|
||||
log_line(&log_info, &buffer[a], b - a);
|
||||
a = b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (a == 0 && b == sizeof(buffer) - 1) {
|
||||
// buffer is full, flush
|
||||
buffer[b] = '\0';
|
||||
log_line(&log_info, &buffer[a], b - a);
|
||||
b = 0;
|
||||
} else if (a != b) {
|
||||
// Keep left-overs
|
||||
b -= a;
|
||||
memmove(buffer, &buffer[a], b);
|
||||
a = 0;
|
||||
} else {
|
||||
a = 0;
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (poll_fds[0].revents & POLLHUP) {
|
||||
int ret;
|
||||
|
||||
ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret < 0) {
|
||||
rc = errno;
|
||||
ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
|
||||
goto err_waitpid;
|
||||
}
|
||||
if (ret > 0) {
|
||||
found_child = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chld_sts != NULL) {
|
||||
*chld_sts = status;
|
||||
} else {
|
||||
if (WIFEXITED(status))
|
||||
rc = WEXITSTATUS(status);
|
||||
else
|
||||
rc = -ECHILD;
|
||||
}
|
||||
|
||||
// Flush remaining data
|
||||
if (a != b) {
|
||||
buffer[b] = '\0';
|
||||
log_line(&log_info, &buffer[a], b - a);
|
||||
}
|
||||
|
||||
/* All the output has been processed, time to dump the abbreviated output */
|
||||
if (abbreviated) {
|
||||
print_abbr_buf(&log_info);
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status)) {
|
||||
snprintf(tmpbuf, sizeof(tmpbuf),
|
||||
"%s terminated by exit(%d)\n", log_info.btag, WEXITSTATUS(status));
|
||||
do_log_line(&log_info, tmpbuf);
|
||||
}
|
||||
} else {
|
||||
if (WIFSIGNALED(status)) {
|
||||
snprintf(tmpbuf, sizeof(tmpbuf),
|
||||
"%s terminated by signal %d\n", log_info.btag, WTERMSIG(status));
|
||||
do_log_line(&log_info, tmpbuf);
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
snprintf(tmpbuf, sizeof(tmpbuf),
|
||||
"%s stopped by signal %d\n", log_info.btag, WSTOPSIG(status));
|
||||
do_log_line(&log_info, tmpbuf);
|
||||
}
|
||||
}
|
||||
|
||||
err_waitpid:
|
||||
err_poll:
|
||||
if (log_target & LOG_FILE) {
|
||||
fclose(log_info.fp); /* Also closes underlying fd */
|
||||
}
|
||||
if (abbreviated) {
|
||||
free_abbr_buf(&log_info.a_buf);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void child(int argc, char* argv[]) {
|
||||
// create null terminated argv_child array
|
||||
char* argv_child[argc + 1];
|
||||
memcpy(argv_child, argv, argc * sizeof(char *));
|
||||
argv_child[argc] = NULL;
|
||||
|
||||
if (execvp(argv_child[0], argv_child)) {
|
||||
FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
|
||||
int log_target, bool abbreviated, char *file_path) {
|
||||
pid_t pid;
|
||||
int parent_ptty;
|
||||
int child_ptty;
|
||||
char *child_devname = NULL;
|
||||
struct sigaction intact;
|
||||
struct sigaction quitact;
|
||||
sigset_t blockset;
|
||||
sigset_t oldset;
|
||||
int rc = 0;
|
||||
|
||||
rc = pthread_mutex_lock(&fd_mutex);
|
||||
if (rc) {
|
||||
ERROR("failed to lock signal_fd mutex\n");
|
||||
goto err_lock;
|
||||
}
|
||||
|
||||
/* Use ptty instead of socketpair so that STDOUT is not buffered */
|
||||
parent_ptty = open("/dev/ptmx", O_RDWR);
|
||||
if (parent_ptty < 0) {
|
||||
ERROR("Cannot create parent ptty\n");
|
||||
rc = -1;
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
|
||||
((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
|
||||
ERROR("Problem with /dev/ptmx\n");
|
||||
rc = -1;
|
||||
goto err_ptty;
|
||||
}
|
||||
|
||||
child_ptty = open(child_devname, O_RDWR);
|
||||
if (child_ptty < 0) {
|
||||
ERROR("Cannot open child_ptty\n");
|
||||
rc = -1;
|
||||
goto err_child_ptty;
|
||||
}
|
||||
|
||||
sigemptyset(&blockset);
|
||||
sigaddset(&blockset, SIGINT);
|
||||
sigaddset(&blockset, SIGQUIT);
|
||||
pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
close(child_ptty);
|
||||
ERROR("Failed to fork\n");
|
||||
rc = -1;
|
||||
goto err_fork;
|
||||
} else if (pid == 0) {
|
||||
pthread_mutex_unlock(&fd_mutex);
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
close(parent_ptty);
|
||||
|
||||
// redirect stdout and stderr
|
||||
dup2(child_ptty, 1);
|
||||
dup2(child_ptty, 2);
|
||||
close(child_ptty);
|
||||
|
||||
child(argc, argv);
|
||||
} else {
|
||||
close(child_ptty);
|
||||
if (ignore_int_quit) {
|
||||
struct sigaction ignact;
|
||||
|
||||
memset(&ignact, 0, sizeof(ignact));
|
||||
ignact.sa_handler = SIG_IGN;
|
||||
sigaction(SIGINT, &ignact, &intact);
|
||||
sigaction(SIGQUIT, &ignact, &quitact);
|
||||
}
|
||||
|
||||
rc = parent(argv[0], parent_ptty, pid, status, log_target,
|
||||
abbreviated, file_path);
|
||||
}
|
||||
|
||||
if (ignore_int_quit) {
|
||||
sigaction(SIGINT, &intact, NULL);
|
||||
sigaction(SIGQUIT, &quitact, NULL);
|
||||
}
|
||||
err_fork:
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
err_child_ptty:
|
||||
err_ptty:
|
||||
close(parent_ptty);
|
||||
err_open:
|
||||
pthread_mutex_unlock(&fd_mutex);
|
||||
err_lock:
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <logwrap/logwrap.h>
|
||||
#include <cutils/klog.h>
|
||||
|
||||
#include "cutils/log.h"
|
||||
|
||||
void fatal(const char *msg) {
|
||||
fprintf(stderr, "%s", msg);
|
||||
ALOG(LOG_ERROR, "logwrapper", "%s", msg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void usage() {
|
||||
fatal(
|
||||
"Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n"
|
||||
"\n"
|
||||
"Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
|
||||
"the Android logging system. Tag is set to BINARY, priority is\n"
|
||||
"always LOG_INFO.\n"
|
||||
"\n"
|
||||
"-a: Causes logwrapper to do abbreviated logging.\n"
|
||||
" This logs up to the first 4K and last 4K of the command\n"
|
||||
" being run, and logs the output when the command exits\n"
|
||||
"-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
|
||||
" fault address is set to the status of wait()\n"
|
||||
"-k: Causes logwrapper to log to the kernel log instead of\n"
|
||||
" the Android system log\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int seg_fault_on_exit = 0;
|
||||
int log_target = LOG_ALOG;
|
||||
bool abbreviated = false;
|
||||
int ch;
|
||||
int status = 0xAAAA;
|
||||
int rc;
|
||||
|
||||
while ((ch = getopt(argc, argv, "adk")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
abbreviated = true;
|
||||
break;
|
||||
case 'd':
|
||||
seg_fault_on_exit = 1;
|
||||
break;
|
||||
case 'k':
|
||||
log_target = LOG_KLOG;
|
||||
klog_set_level(6);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
|
||||
log_target, abbreviated, NULL);
|
||||
if (!rc) {
|
||||
if (WIFEXITED(status))
|
||||
rc = WEXITSTATUS(status);
|
||||
else
|
||||
rc = -ECHILD;
|
||||
}
|
||||
|
||||
if (seg_fault_on_exit) {
|
||||
*(int *)status = 0; // causes SIGSEGV with fault_address = status
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# Enable to be able to use ALOG* with #include "cutils/log.h"
|
||||
#log_c_includes += system/core/include
|
||||
#log_shared_libraries := liblog
|
||||
|
||||
# These makefiles are here instead of being Android.mk files in the
|
||||
# respective crypto, ssl, and apps directories so
|
||||
# that import_openssl.sh import won't remove them.
|
||||
include $(LOCAL_PATH)/build-config.mk
|
||||
include $(LOCAL_PATH)/Scrypt.mk
|
||||
|
||||
include $(call all-named-subdir-makefiles,tests)
|
||||
@@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
/*
|
||||
* version 20110505
|
||||
* D. J. Bernstein
|
||||
* Public domain.
|
||||
*
|
||||
* Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
|
||||
*/
|
||||
@@ -0,0 +1,105 @@
|
||||
# Auto-generated - DO NOT EDIT!
|
||||
# To regenerate, edit scrypt.config, then run:
|
||||
# ./import_scrypt.sh import /path/to/scrypt-1.1.6.tar.gz
|
||||
#
|
||||
# Before including this file, the local Android.mk must define the following
|
||||
# variables:
|
||||
#
|
||||
# local_c_flags
|
||||
# local_c_includes
|
||||
# local_additional_dependencies
|
||||
#
|
||||
# This script will define the following variables:
|
||||
#
|
||||
# target_c_flags
|
||||
# target_c_includes
|
||||
# target_src_files
|
||||
#
|
||||
# host_c_flags
|
||||
# host_c_includes
|
||||
# host_src_files
|
||||
#
|
||||
|
||||
# Ensure these are empty.
|
||||
unknown_arch_c_flags :=
|
||||
unknown_arch_src_files :=
|
||||
unknown_arch_exclude_files :=
|
||||
|
||||
|
||||
common_c_flags :=
|
||||
|
||||
common_src_files := \
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
|
||||
common_c_includes := \
|
||||
lib/crypto \
|
||||
lib/util \
|
||||
|
||||
arm_c_flags :=
|
||||
|
||||
arm_src_files :=
|
||||
|
||||
arm_exclude_files :=
|
||||
|
||||
arm_neon_c_flags :=
|
||||
|
||||
arm_neon_src_files := \
|
||||
lib/crypto/crypto_scrypt-neon.c \
|
||||
|
||||
arm_neon_exclude_files := \
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
|
||||
x86_c_flags :=
|
||||
|
||||
x86_src_files := \
|
||||
lib/crypto/crypto_scrypt-sse.c \
|
||||
|
||||
x86_exclude_files := \
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
|
||||
x86_64_c_flags :=
|
||||
|
||||
x86_64_src_files := \
|
||||
lib/crypto/crypto_scrypt-sse.c \
|
||||
|
||||
x86_64_exclude_files := \
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
|
||||
mips_c_flags :=
|
||||
|
||||
mips_src_files :=
|
||||
|
||||
mips_exclude_files :=
|
||||
|
||||
target_arch := $(TARGET_ARCH)
|
||||
ifeq ($(target_arch)-$(TARGET_HAS_BIGENDIAN),mips-true)
|
||||
target_arch := unknown_arch
|
||||
endif
|
||||
|
||||
target_c_flags := $(common_c_flags) $($(target_arch)_c_flags) $(local_c_flags)
|
||||
target_c_includes := $(addprefix bootable/recovery/crypto/scrypt/,$(common_c_includes)) $(local_c_includes)
|
||||
target_src_files := $(common_src_files) $($(target_arch)_src_files)
|
||||
target_src_files := $(filter-out $($(target_arch)_exclude_files), $(target_src_files))
|
||||
|
||||
# Hacks for ARM NEON support
|
||||
ifeq ($(target_arch),arm)
|
||||
ifeq ($(ARCH_ARM_HAVE_NEON),true)
|
||||
target_c_flags += $(arm_neon_c_flags)
|
||||
target_src_files += $(arm_neon_src_files)
|
||||
target_src_files := $(filter-out $(arm_neon_exclude_files), $(target_src_files))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
|
||||
host_arch := x86
|
||||
else
|
||||
host_arch := unknown_arch
|
||||
endif
|
||||
|
||||
host_c_flags := $(common_c_flags) $($(host_arch)_c_flags) $(local_c_flags)
|
||||
host_c_includes := $(addprefix bootable/recovery/crypto/scrypt/,$(common_c_includes)) $(local_c_includes)
|
||||
host_src_files := $(common_src_files) $($(host_arch)_src_files)
|
||||
host_src_files := $(filter-out $($(host_arch)_exclude_files), $(host_src_files))
|
||||
|
||||
local_additional_dependencies += $(LOCAL_PATH)/Scrypt-config.mk
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
local_c_flags := -DUSE_OPENSSL_PBKDF2
|
||||
|
||||
local_c_includes := $(log_c_includes) external/openssl/include
|
||||
|
||||
local_additional_dependencies := $(LOCAL_PATH)/android-config.mk $(LOCAL_PATH)/Scrypt.mk
|
||||
|
||||
include $(LOCAL_PATH)/Scrypt-config.mk
|
||||
|
||||
#######################################
|
||||
# target static library
|
||||
include $(CLEAR_VARS)
|
||||
include $(LOCAL_PATH)/android-config.mk
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := $(log_shared_libraries)
|
||||
|
||||
# If we're building an unbundled build, don't try to use clang since it's not
|
||||
# in the NDK yet. This can be removed when a clang version that is fast enough
|
||||
# in the NDK.
|
||||
ifeq (,$(TARGET_BUILD_APPS))
|
||||
LOCAL_CLANG := true
|
||||
else
|
||||
LOCAL_SDK_VERSION := 9
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES += $(target_src_files)
|
||||
LOCAL_CFLAGS += $(target_c_flags)
|
||||
LOCAL_C_INCLUDES += $(target_c_includes)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE:= libscrypttwrp_static
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(local_additional_dependencies)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################
|
||||
# host static library
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
include $(LOCAL_PATH)/android-config.mk
|
||||
LOCAL_SHARED_LIBRARIES := $(log_shared_libraries)
|
||||
LOCAL_SRC_FILES += $(host_src_files)
|
||||
LOCAL_CFLAGS += $(host_c_flags)
|
||||
LOCAL_C_INCLUDES += $(host_c_includes)
|
||||
LOCAL_LDLIBS += -ldl
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE:= libscrypttwrp_static
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(local_additional_dependencies)
|
||||
include $(BUILD_HOST_STATIC_LIBRARY)
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# These flags represent the build-time configuration of scrypt for Android
|
||||
#
|
||||
# The value of $(scrypt_cflags) was pruned from the Makefile generated
|
||||
# by running ./configure from import_scrypt.sh.
|
||||
#
|
||||
# This script performs minor but required patching for the Android build.
|
||||
#
|
||||
|
||||
LOCAL_CFLAGS += $(scrypt_cflags)
|
||||
|
||||
# Add in flags to let config.h be read properly
|
||||
LOCAL_CFLAGS += "-DHAVE_CONFIG_H"
|
||||
|
||||
# Add clang here when it works on host
|
||||
# LOCAL_CLANG := true
|
||||
@@ -0,0 +1,6 @@
|
||||
# Auto-generated - DO NOT EDIT!
|
||||
# To regenerate, edit scrypt.config, then run:
|
||||
# ./import_scrypt.sh import /path/to/scrypt-1.1.6.tar.gz
|
||||
#
|
||||
scrypt_cflags := \
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `be64enc', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_BE64ENC 0
|
||||
|
||||
/* Define to 1 if you have the <err.h> header file. */
|
||||
#define HAVE_ERR_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
#define HAVE_LIBRT 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `posix_memalign' function. */
|
||||
#define HAVE_POSIX_MEMALIGN 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct sysinfo'. */
|
||||
#define HAVE_STRUCT_SYSINFO 1
|
||||
|
||||
/* Define to 1 if `mem_unit' is member of `struct sysinfo'. */
|
||||
#define HAVE_STRUCT_SYSINFO_MEM_UNIT 1
|
||||
|
||||
/* Define to 1 if `totalram' is member of `struct sysinfo'. */
|
||||
#define HAVE_STRUCT_SYSINFO_TOTALRAM 1
|
||||
|
||||
/* Define to 1 if the OS has a hw.usermem sysctl */
|
||||
/* #undef HAVE_SYSCTL_HW_USERMEM */
|
||||
|
||||
/* Define to 1 if you have the `sysinfo' function. */
|
||||
#define HAVE_SYSINFO 1
|
||||
|
||||
/* Define to 1 if you have the <sys/endian.h> header file. */
|
||||
/* #undef HAVE_SYS_ENDIAN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sysinfo.h> header file. */
|
||||
#define HAVE_SYS_SYSINFO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "scrypt"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "scrypt"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "scrypt 1.1.6"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "scrypt"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.1.6"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.1.6"
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
Executable
+493
@@ -0,0 +1,493 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2009 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.
|
||||
#
|
||||
|
||||
#
|
||||
# This script imports new versions of scrypt (http://www.tarsnap.com/scrypt/) into the
|
||||
# Android source tree. To run, (1) fetch the appropriate tarball from the scrypt repository,
|
||||
# (2) check the gpg/pgp signature, and then (3) run:
|
||||
# ./import_scrypt.sh import scrypt-*.tar.gz
|
||||
#
|
||||
# IMPORTANT: See README.android for additional details.
|
||||
|
||||
# turn on exit on error as well as a warning when it happens
|
||||
set -e
|
||||
set -x
|
||||
trap "echo WARNING: Exiting on non-zero subprocess exit code" ERR;
|
||||
|
||||
# Ensure consistent sorting order / tool output.
|
||||
export LANG=C
|
||||
export LC_ALL=C
|
||||
|
||||
export DIRNAME=$(dirname $0)
|
||||
|
||||
function die() {
|
||||
declare -r message=$1
|
||||
|
||||
echo $message
|
||||
exit 1
|
||||
}
|
||||
|
||||
function usage() {
|
||||
declare -r message=$1
|
||||
|
||||
if [ ! "$message" = "" ]; then
|
||||
echo $message
|
||||
fi
|
||||
echo "Usage:"
|
||||
echo " ./import_scrypt.sh import </path/to/scrypt-*.tar.gz>"
|
||||
echo " ./import_scrypt.sh regenerate <patch/*.patch>"
|
||||
echo " ./import_scrypt.sh generate <patch/*.patch> </path/to/scrypt-*.tar.gz>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function main() {
|
||||
if [ ! -d patches ]; then
|
||||
die "scrypt patch directory patches/ not found"
|
||||
fi
|
||||
|
||||
if [ ! -f scrypt.version ]; then
|
||||
die "scrypt.version not found"
|
||||
fi
|
||||
|
||||
source $DIRNAME/scrypt.version
|
||||
if [ "$SCRYPT_VERSION" == "" ]; then
|
||||
die "Invalid scrypt.version; see README.android for more information"
|
||||
fi
|
||||
|
||||
SCRYPT_DIR=scrypt-$SCRYPT_VERSION
|
||||
SCRYPT_DIR_ORIG=$SCRYPT_DIR.orig
|
||||
|
||||
if [ ! -f scrypt.config ]; then
|
||||
die "scrypt.config not found"
|
||||
fi
|
||||
|
||||
source $DIRNAME/scrypt.config
|
||||
if [ "$CONFIGURE_ARGS" == "" -o "$UNNEEDED_SOURCES" == "" -o "$NEEDED_SOURCES" == "" ]; then
|
||||
die "Invalid scrypt.config; see README.android for more information"
|
||||
fi
|
||||
|
||||
declare -r command=$1
|
||||
shift || usage "No command specified. Try import, regenerate, or generate."
|
||||
if [ "$command" = "import" ]; then
|
||||
declare -r tar=$1
|
||||
shift || usage "No tar file specified."
|
||||
import $tar
|
||||
elif [ "$command" = "regenerate" ]; then
|
||||
declare -r patch=$1
|
||||
shift || usage "No patch file specified."
|
||||
[ -d $SCRYPT_DIR ] || usage "$SCRYPT_DIR not found, did you mean to use generate?"
|
||||
[ -d $SCRYPT_DIR_ORIG_ORIG ] || usage "$SCRYPT_DIR_ORIG not found, did you mean to use generate?"
|
||||
regenerate $patch
|
||||
elif [ "$command" = "generate" ]; then
|
||||
declare -r patch=$1
|
||||
shift || usage "No patch file specified."
|
||||
declare -r tar=$1
|
||||
shift || usage "No tar file specified."
|
||||
generate $patch $tar
|
||||
else
|
||||
usage "Unknown command specified $command. Try import, regenerate, or generate."
|
||||
fi
|
||||
}
|
||||
|
||||
# Compute the name of an assembly source file generated by one of the
|
||||
# gen_asm_xxxx() functions below. The logic is the following:
|
||||
# - if "$2" is not empty, output it directly
|
||||
# - otherwise, change the file extension of $1 from .pl to .S and output
|
||||
# it.
|
||||
# Usage: default_asm_file "$1" "$2"
|
||||
# or default_asm_file "$@"
|
||||
#
|
||||
# $1: generator path (perl script)
|
||||
# $2: optional output file name.
|
||||
function default_asm_file () {
|
||||
if [ "$2" ]; then
|
||||
echo "$2"
|
||||
else
|
||||
echo "${1%%.pl}.S"
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate an ARM assembly file.
|
||||
# $1: generator (perl script)
|
||||
# $2: [optional] output file name
|
||||
function gen_asm_arm () {
|
||||
local OUT
|
||||
OUT=$(default_asm_file "$@")
|
||||
perl "$1" > "$OUT"
|
||||
}
|
||||
|
||||
function gen_asm_mips () {
|
||||
local OUT
|
||||
OUT=$(default_asm_file "$@")
|
||||
# The perl scripts expect to run the target compiler as $CC to determine
|
||||
# the endianess of the target. Setting CC to true is a hack that forces the scripts
|
||||
# to generate little endian output
|
||||
CC=true perl "$1" o32 > "$OUT"
|
||||
}
|
||||
|
||||
function gen_asm_x86 () {
|
||||
local OUT
|
||||
OUT=$(default_asm_file "$@")
|
||||
perl "$1" elf -fPIC > "$OUT"
|
||||
}
|
||||
|
||||
function gen_asm_x86_64 () {
|
||||
local OUT
|
||||
OUT=$(default_asm_file "$@")
|
||||
perl "$1" elf "$OUT" > "$OUT"
|
||||
}
|
||||
|
||||
|
||||
# Filter all items in a list that match a given pattern.
|
||||
# $1: space-separated list
|
||||
# $2: egrep pattern.
|
||||
# Out: items in $1 that match $2
|
||||
function filter_by_egrep() {
|
||||
declare -r pattern=$1
|
||||
shift
|
||||
echo "$@" | tr ' ' '\n' | grep -e "$pattern" | tr '\n' ' '
|
||||
}
|
||||
|
||||
# Sort and remove duplicates in a space-separated list
|
||||
# $1: space-separated list
|
||||
# Out: new space-separated list
|
||||
function uniq_sort () {
|
||||
echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' '
|
||||
}
|
||||
|
||||
function print_autogenerated_header() {
|
||||
echo "# Auto-generated - DO NOT EDIT!"
|
||||
echo "# To regenerate, edit scrypt.config, then run:"
|
||||
echo "# ./import_scrypt.sh import /path/to/scrypt-$SCRYPT_VERSION.tar.gz"
|
||||
echo "#"
|
||||
}
|
||||
|
||||
function generate_build_config_mk() {
|
||||
./configure $CONFIGURE_ARGS
|
||||
#rm -f apps/CA.pl.bak crypto/scryptconf.h.bak
|
||||
|
||||
declare -r tmpfile=$(mktemp)
|
||||
(grep -e -D Makefile | grep -v CONFIGURE_ARGS= | grep -v OPTIONS=) > $tmpfile
|
||||
|
||||
declare -r cflags=$(filter_by_egrep "^-D" $(grep -e "^CFLAG=" $tmpfile))
|
||||
declare -r depflags=$(filter_by_egrep "^-D" $(grep -e "^DEPFLAG=" $tmpfile))
|
||||
rm -f $tmpfile
|
||||
|
||||
echo "Generating $(basename $1)"
|
||||
(
|
||||
print_autogenerated_header
|
||||
|
||||
echo "scrypt_cflags := \\"
|
||||
for cflag in $cflags $depflags; do
|
||||
echo " $cflag \\"
|
||||
done
|
||||
echo ""
|
||||
) > $1
|
||||
}
|
||||
|
||||
# Return the value of a computed variable name.
|
||||
# E.g.:
|
||||
# FOO=foo
|
||||
# BAR=bar
|
||||
# echo $(var_value FOO_$BAR) -> prints the value of ${FOO_bar}
|
||||
# $1: Variable name
|
||||
# Out: variable value
|
||||
var_value() {
|
||||
# Note: don't use 'echo' here, because it's sensitive to values
|
||||
# that begin with an underscore (e.g. "-n")
|
||||
eval printf \"%s\\n\" \$$1
|
||||
}
|
||||
|
||||
# Same as var_value, but returns sorted output without duplicates.
|
||||
# $1: Variable name
|
||||
# Out: variable value (if space-separated list, sorted with no duplicates)
|
||||
var_sorted_value() {
|
||||
uniq_sort $(var_value $1)
|
||||
}
|
||||
|
||||
# Print the definition of a given variable in a GNU Make build file.
|
||||
# $1: Variable name (e.g. common_src_files)
|
||||
# $2+: Variable value (e.g. list of sources)
|
||||
print_vardef_in_mk() {
|
||||
declare -r varname=$1
|
||||
shift
|
||||
if [ -z "$1" ]; then
|
||||
echo "$varname :="
|
||||
else
|
||||
echo "$varname := \\"
|
||||
for src; do
|
||||
echo " $src \\"
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Same as print_vardef_in_mk, but print a CFLAGS definition from
|
||||
# a list of compiler defines.
|
||||
# $1: Variable name (e.g. common_c_flags)
|
||||
# $2: List of defines (e.g. SCRYPT_NO_DONKEYS ...)
|
||||
print_defines_in_mk() {
|
||||
declare -r varname=$1
|
||||
shift
|
||||
if [ -z "$1" ]; then
|
||||
echo "$varname :="
|
||||
else
|
||||
echo "$varname := \\"
|
||||
for def; do
|
||||
echo " -D$def \\"
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Generate a configuration file like Scrypt-config.mk
|
||||
# This uses variable definitions from scrypt.config to build a config
|
||||
# file that can compute the list of target- and host-specific sources /
|
||||
# compiler flags for a given component.
|
||||
#
|
||||
# $1: Target file name. (e.g. Scrypt-config.mk)
|
||||
function generate_config_mk() {
|
||||
declare -r output="$1"
|
||||
declare -r all_archs="arm arm_neon x86 x86_64 mips"
|
||||
|
||||
echo "Generating $(basename $output)"
|
||||
(
|
||||
print_autogenerated_header
|
||||
echo \
|
||||
"# Before including this file, the local Android.mk must define the following
|
||||
# variables:
|
||||
#
|
||||
# local_c_flags
|
||||
# local_c_includes
|
||||
# local_additional_dependencies
|
||||
#
|
||||
# This script will define the following variables:
|
||||
#
|
||||
# target_c_flags
|
||||
# target_c_includes
|
||||
# target_src_files
|
||||
#
|
||||
# host_c_flags
|
||||
# host_c_includes
|
||||
# host_src_files
|
||||
#
|
||||
|
||||
# Ensure these are empty.
|
||||
unknown_arch_c_flags :=
|
||||
unknown_arch_src_files :=
|
||||
unknown_arch_exclude_files :=
|
||||
|
||||
"
|
||||
common_defines=$(var_sorted_value SCRYPT_DEFINES)
|
||||
print_defines_in_mk common_c_flags $common_defines
|
||||
|
||||
common_sources=$(var_sorted_value SCRYPT_SOURCES)
|
||||
print_vardef_in_mk common_src_files $common_sources
|
||||
|
||||
common_includes=$(var_sorted_value SCRYPT_INCLUDES)
|
||||
print_vardef_in_mk common_c_includes $common_includes
|
||||
|
||||
for arch in $all_archs; do
|
||||
arch_defines=$(var_sorted_value SCRYPT_DEFINES_${arch})
|
||||
print_defines_in_mk ${arch}_c_flags $arch_defines
|
||||
|
||||
arch_sources=$(var_sorted_value SCRYPT_SOURCES_${arch})
|
||||
print_vardef_in_mk ${arch}_src_files $arch_sources
|
||||
|
||||
arch_exclude_sources=$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch})
|
||||
print_vardef_in_mk ${arch}_exclude_files $arch_exclude_sources
|
||||
|
||||
done
|
||||
|
||||
echo "\
|
||||
target_arch := \$(TARGET_ARCH)
|
||||
ifeq (\$(target_arch)-\$(TARGET_HAS_BIGENDIAN),mips-true)
|
||||
target_arch := unknown_arch
|
||||
endif
|
||||
|
||||
target_c_flags := \$(common_c_flags) \$(\$(target_arch)_c_flags) \$(local_c_flags)
|
||||
target_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes)
|
||||
target_src_files := \$(common_src_files) \$(\$(target_arch)_src_files)
|
||||
target_src_files := \$(filter-out \$(\$(target_arch)_exclude_files), \$(target_src_files))
|
||||
|
||||
# Hacks for ARM NEON support
|
||||
ifeq (\$(target_arch),arm)
|
||||
ifeq (\$(ARCH_ARM_HAVE_NEON),true)
|
||||
target_c_flags += \$(arm_neon_c_flags)
|
||||
target_src_files += \$(arm_neon_src_files)
|
||||
target_src_files := \$(filter-out \$(arm_neon_exclude_files), \$(target_src_files))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (\$(HOST_OS)-\$(HOST_ARCH),linux-x86)
|
||||
host_arch := x86
|
||||
else
|
||||
host_arch := unknown_arch
|
||||
endif
|
||||
|
||||
host_c_flags := \$(common_c_flags) \$(\$(host_arch)_c_flags) \$(local_c_flags)
|
||||
host_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes)
|
||||
host_src_files := \$(common_src_files) \$(\$(host_arch)_src_files)
|
||||
host_src_files := \$(filter-out \$(\$(host_arch)_exclude_files), \$(host_src_files))
|
||||
|
||||
local_additional_dependencies += \$(LOCAL_PATH)/$(basename $output)
|
||||
"
|
||||
|
||||
) > "$output"
|
||||
}
|
||||
|
||||
function import() {
|
||||
declare -r SCRYPT_SOURCE=$1
|
||||
|
||||
untar $SCRYPT_SOURCE readonly
|
||||
applypatches $SCRYPT_DIR
|
||||
|
||||
cd $SCRYPT_DIR
|
||||
|
||||
generate_build_config_mk ../build-config.mk
|
||||
|
||||
touch ../MODULE_LICENSE_BSD_LIKE
|
||||
|
||||
cd ..
|
||||
|
||||
generate_config_mk Scrypt-config.mk
|
||||
|
||||
# Prune unnecessary sources
|
||||
prune
|
||||
|
||||
NEEDED_SOURCES="$NEEDED_SOURCES"
|
||||
for i in $NEEDED_SOURCES; do
|
||||
echo "Updating $i"
|
||||
rm -r $i
|
||||
mv $SCRYPT_DIR/$i .
|
||||
done
|
||||
|
||||
cleantar
|
||||
}
|
||||
|
||||
function regenerate() {
|
||||
declare -r patch=$1
|
||||
|
||||
generatepatch $patch
|
||||
}
|
||||
|
||||
function generate() {
|
||||
declare -r patch=$1
|
||||
declare -r SCRYPT_SOURCE=$2
|
||||
|
||||
untar $SCRYPT_SOURCE
|
||||
applypatches $SCRYPT_DIR_ORIG $patch
|
||||
prune
|
||||
|
||||
for i in $NEEDED_SOURCES; do
|
||||
echo "Restoring $i"
|
||||
rm -r $SCRYPT_DIR/$i
|
||||
cp -rf $i $SCRYPT_DIR/$i
|
||||
done
|
||||
|
||||
generatepatch $patch
|
||||
cleantar
|
||||
}
|
||||
|
||||
# Find all files in a sub-directory that are encoded in ISO-8859
|
||||
# $1: Directory.
|
||||
# Out: list of files in $1 that are encoded as ISO-8859.
|
||||
function find_iso8859_files() {
|
||||
find $1 -type f -print0 | xargs -0 file | fgrep "ISO-8859" | cut -d: -f1
|
||||
}
|
||||
|
||||
# Convert all ISO-8859 files in a given subdirectory to UTF-8
|
||||
# $1: Directory name
|
||||
function convert_iso8859_to_utf8() {
|
||||
declare -r iso_files=$(find_iso8859_files "$1")
|
||||
for iso_file in $iso_files; do
|
||||
iconv --from-code iso-8859-1 --to-code utf-8 $iso_file > $iso_file.tmp
|
||||
rm -f $iso_file
|
||||
mv $iso_file.tmp $iso_file
|
||||
done
|
||||
}
|
||||
|
||||
function untar() {
|
||||
declare -r SCRYPT_SOURCE=$1
|
||||
declare -r readonly=$2
|
||||
|
||||
# Remove old source
|
||||
cleantar
|
||||
|
||||
# Process new source
|
||||
tar -zxf $SCRYPT_SOURCE
|
||||
convert_iso8859_to_utf8 $SCRYPT_DIR
|
||||
cp -rfP $SCRYPT_DIR $SCRYPT_DIR_ORIG
|
||||
if [ ! -z $readonly ]; then
|
||||
find $SCRYPT_DIR_ORIG -type f -print0 | xargs -0 chmod a-w
|
||||
fi
|
||||
}
|
||||
|
||||
function prune() {
|
||||
echo "Removing $UNNEEDED_SOURCES"
|
||||
(cd $SCRYPT_DIR_ORIG && rm -rf $UNNEEDED_SOURCES)
|
||||
(cd $SCRYPT_DIR && rm -r $UNNEEDED_SOURCES)
|
||||
}
|
||||
|
||||
function cleantar() {
|
||||
rm -rf $SCRYPT_DIR_ORIG
|
||||
rm -rf $SCRYPT_DIR
|
||||
}
|
||||
|
||||
function applypatches () {
|
||||
declare -r dir=$1
|
||||
declare -r skip_patch=$2
|
||||
|
||||
cd $dir
|
||||
|
||||
# Apply appropriate patches
|
||||
for i in $SCRYPT_PATCHES; do
|
||||
if [ ! "$skip_patch" = "patches/$i" ]; then
|
||||
echo "Applying patch $i"
|
||||
patch -p1 --merge < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i"
|
||||
else
|
||||
echo "Skiping patch $i"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# Cleanup patch output
|
||||
find . \( -type f -o -type l \) -name "*.orig" -print0 | xargs -0 rm -f
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
function generatepatch() {
|
||||
declare -r patch=$1
|
||||
|
||||
# Cleanup stray files before generating patch
|
||||
find $SCRYPT_DIR -type f -name "*.orig" -print0 | xargs -0 rm -f
|
||||
find $SCRYPT_DIR -type f -name "*~" -print0 | xargs -0 rm -f
|
||||
|
||||
declare -r variable_name=SCRYPT_PATCHES_`basename $patch .patch | sed s/-/_/`_SOURCES
|
||||
# http://tldp.org/LDP/abs/html/ivr.html
|
||||
eval declare -r sources=\$$variable_name
|
||||
rm -f $patch
|
||||
touch $patch
|
||||
for i in $sources; do
|
||||
LC_ALL=C TZ=UTC0 diff -aup $SCRYPT_DIR_ORIG/$i $SCRYPT_DIR/$i >> $patch && die "ERROR: No diff for patch $path in file $i"
|
||||
done
|
||||
echo "Generated patch $patch"
|
||||
echo "NOTE To make sure there are not unwanted changes from conflicting patches, be sure to review the generated patch."
|
||||
}
|
||||
|
||||
main $@
|
||||
@@ -0,0 +1,6 @@
|
||||
The source code under this directory is taken from the client for the
|
||||
Tarsnap online backup system (and released under the 2-clause BSD license
|
||||
with permission of the author); keeping this code in sync with the Tarsnap
|
||||
code is highly desirable and explains why there is some functionality
|
||||
included here which is not actually used by the scrypt file encryption
|
||||
utility.
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* version 20110505
|
||||
* D. J. Bernstein
|
||||
* Public domain.
|
||||
*
|
||||
* Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
|
||||
*/
|
||||
|
||||
#define ROUNDS 8
|
||||
static void
|
||||
salsa20_8_intrinsic(void * input)
|
||||
{
|
||||
int i;
|
||||
|
||||
const uint32x4_t abab = {-1,0,-1,0};
|
||||
|
||||
/*
|
||||
* This is modified since we only have one argument. Usually you'd rearrange
|
||||
* the constant, key, and input bytes, but we just have one linear array to
|
||||
* rearrange which is a bit easier.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Change the input to be diagonals as if it's a 4x4 matrix of 32-bit values.
|
||||
*/
|
||||
uint32x4_t x0x5x10x15;
|
||||
uint32x4_t x12x1x6x11;
|
||||
uint32x4_t x8x13x2x7;
|
||||
uint32x4_t x4x9x14x3;
|
||||
|
||||
uint32x4_t x0x1x10x11;
|
||||
uint32x4_t x12x13x6x7;
|
||||
uint32x4_t x8x9x2x3;
|
||||
uint32x4_t x4x5x14x15;
|
||||
|
||||
uint32x4_t x0x1x2x3;
|
||||
uint32x4_t x4x5x6x7;
|
||||
uint32x4_t x8x9x10x11;
|
||||
uint32x4_t x12x13x14x15;
|
||||
|
||||
x0x1x2x3 = vld1q_u8((uint8_t *) input);
|
||||
x4x5x6x7 = vld1q_u8(16 + (uint8_t *) input);
|
||||
x8x9x10x11 = vld1q_u8(32 + (uint8_t *) input);
|
||||
x12x13x14x15 = vld1q_u8(48 + (uint8_t *) input);
|
||||
|
||||
x0x1x10x11 = vcombine_u32(vget_low_u32(x0x1x2x3), vget_high_u32(x8x9x10x11));
|
||||
x4x5x14x15 = vcombine_u32(vget_low_u32(x4x5x6x7), vget_high_u32(x12x13x14x15));
|
||||
x8x9x2x3 = vcombine_u32(vget_low_u32(x8x9x10x11), vget_high_u32(x0x1x2x3));
|
||||
x12x13x6x7 = vcombine_u32(vget_low_u32(x12x13x14x15), vget_high_u32(x4x5x6x7));
|
||||
|
||||
x0x5x10x15 = vbslq_u32(abab,x0x1x10x11,x4x5x14x15);
|
||||
x8x13x2x7 = vbslq_u32(abab,x8x9x2x3,x12x13x6x7);
|
||||
x4x9x14x3 = vbslq_u32(abab,x4x5x14x15,x8x9x2x3);
|
||||
x12x1x6x11 = vbslq_u32(abab,x12x13x6x7,x0x1x10x11);
|
||||
|
||||
uint32x4_t start0 = x0x5x10x15;
|
||||
uint32x4_t start1 = x12x1x6x11;
|
||||
uint32x4_t start3 = x4x9x14x3;
|
||||
uint32x4_t start2 = x8x13x2x7;
|
||||
|
||||
/* From here on this should be the same as the SUPERCOP version. */
|
||||
|
||||
uint32x4_t diag0 = start0;
|
||||
uint32x4_t diag1 = start1;
|
||||
uint32x4_t diag2 = start2;
|
||||
uint32x4_t diag3 = start3;
|
||||
|
||||
uint32x4_t a0;
|
||||
uint32x4_t a1;
|
||||
uint32x4_t a2;
|
||||
uint32x4_t a3;
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
a0 = diag1 + diag0;
|
||||
diag3 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
|
||||
a1 = diag0 + diag3;
|
||||
diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
|
||||
a2 = diag3 + diag2;
|
||||
diag1 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
|
||||
a3 = diag2 + diag1;
|
||||
diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
|
||||
|
||||
diag3 = vextq_u32(diag3,diag3,3);
|
||||
diag2 = vextq_u32(diag2,diag2,2);
|
||||
diag1 = vextq_u32(diag1,diag1,1);
|
||||
|
||||
a0 = diag3 + diag0;
|
||||
diag1 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
|
||||
a1 = diag0 + diag1;
|
||||
diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
|
||||
a2 = diag1 + diag2;
|
||||
diag3 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
|
||||
a3 = diag2 + diag3;
|
||||
diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
|
||||
|
||||
diag1 = vextq_u32(diag1,diag1,3);
|
||||
diag2 = vextq_u32(diag2,diag2,2);
|
||||
diag3 = vextq_u32(diag3,diag3,1);
|
||||
}
|
||||
|
||||
x0x5x10x15 = diag0 + start0;
|
||||
x12x1x6x11 = diag1 + start1;
|
||||
x8x13x2x7 = diag2 + start2;
|
||||
x4x9x14x3 = diag3 + start3;
|
||||
|
||||
x0x1x10x11 = vbslq_u32(abab,x0x5x10x15,x12x1x6x11);
|
||||
x12x13x6x7 = vbslq_u32(abab,x12x1x6x11,x8x13x2x7);
|
||||
x8x9x2x3 = vbslq_u32(abab,x8x13x2x7,x4x9x14x3);
|
||||
x4x5x14x15 = vbslq_u32(abab,x4x9x14x3,x0x5x10x15);
|
||||
|
||||
x0x1x2x3 = vcombine_u32(vget_low_u32(x0x1x10x11),vget_high_u32(x8x9x2x3));
|
||||
x4x5x6x7 = vcombine_u32(vget_low_u32(x4x5x14x15),vget_high_u32(x12x13x6x7));
|
||||
x8x9x10x11 = vcombine_u32(vget_low_u32(x8x9x2x3),vget_high_u32(x0x1x10x11));
|
||||
x12x13x14x15 = vcombine_u32(vget_low_u32(x12x13x6x7),vget_high_u32(x4x5x14x15));
|
||||
|
||||
vst1q_u8((uint8_t *) input,(uint8x16_t) x0x1x2x3);
|
||||
vst1q_u8(16 + (uint8_t *) input,(uint8x16_t) x4x5x6x7);
|
||||
vst1q_u8(32 + (uint8_t *) input,(uint8x16_t) x8x9x10x11);
|
||||
vst1q_u8(48 + (uint8_t *) input,(uint8x16_t) x12x13x14x15);
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
#include <openssl/evp.h>
|
||||
#else
|
||||
#include "sha256.h"
|
||||
#endif
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
#include "crypto_scrypt-neon-salsa208.h"
|
||||
|
||||
static void blkcpy(void *, void *, size_t);
|
||||
static void blkxor(void *, void *, size_t);
|
||||
void crypto_core_salsa208_armneon2(void *);
|
||||
static void blockmix_salsa8(uint8x16_t *, uint8x16_t *, uint8x16_t *, size_t);
|
||||
static uint64_t integerify(void *, size_t);
|
||||
static void smix(uint8_t *, size_t, uint64_t, void *, void *);
|
||||
|
||||
static void
|
||||
blkcpy(void * dest, void * src, size_t len)
|
||||
{
|
||||
uint8x16_t * D = dest;
|
||||
uint8x16_t * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = S[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(void * dest, void * src, size_t len)
|
||||
{
|
||||
uint8x16_t * D = dest;
|
||||
uint8x16_t * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = veorq_u8(D[i], S[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(B, Y, r):
|
||||
* Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
* length; the temporary space Y must also be the same size.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(uint8x16_t * Bin, uint8x16_t * Bout, uint8x16_t * X, size_t r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &Bin[8 * r - 4], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8], 64);
|
||||
salsa20_8_intrinsic((void *) X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[i * 4], X, 64);
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8 + 4], 64);
|
||||
salsa20_8_intrinsic((void *) X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[(r + i) * 4], X, 64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(void * B, size_t r)
|
||||
{
|
||||
uint8_t * X = (void*)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
|
||||
return (le64dec(X));
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the
|
||||
* temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
* XY must be 256r bytes in length. The value N must be a power of 2.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
|
||||
{
|
||||
uint8x16_t * X = XY;
|
||||
uint8x16_t * Y = (void *)((uintptr_t)(XY) + 128 * r);
|
||||
uint8x16_t * Z = (void *)((uintptr_t)(XY) + 256 * r);
|
||||
uint32_t * X32 = (void *)X;
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
blkcpy(X, B, 128 * r);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
|
||||
Y, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(Y, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
blkcpy(B, X, 128 * r);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
void * B0, * V0, * XY0;
|
||||
uint8_t * B;
|
||||
uint32_t * V;
|
||||
uint32_t * XY;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N == 0)) {
|
||||
errno = EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
#ifdef HAVE_POSIX_MEMALIGN
|
||||
if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
|
||||
goto err0;
|
||||
B = (uint8_t *)(B0);
|
||||
if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(XY0);
|
||||
#ifndef MAP_ANON
|
||||
if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
#else
|
||||
if ((B0 = malloc(128 * r * p + 63)) == NULL)
|
||||
goto err0;
|
||||
B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
|
||||
if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
|
||||
#ifndef MAP_ANON
|
||||
if ((V0 = malloc(128 * r * N + 63)) == NULL)
|
||||
goto err2;
|
||||
V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MAP_ANON
|
||||
if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
#else
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
#endif
|
||||
-1, 0)) == MAP_FAILED)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
#endif
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[i * 128 * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
#endif
|
||||
|
||||
/* Free memory. */
|
||||
#ifdef MAP_ANON
|
||||
if (munmap(V0, 128 * r * N))
|
||||
goto err2;
|
||||
#else
|
||||
free(V0);
|
||||
#endif
|
||||
free(XY0);
|
||||
free(B0);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err2:
|
||||
free(XY0);
|
||||
err1:
|
||||
free(B0);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
#include <openssl/evp.h>
|
||||
#else
|
||||
#include "sha256.h"
|
||||
#endif
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
static void blkcpy(uint8_t *, uint8_t *, size_t);
|
||||
static void blkxor(uint8_t *, uint8_t *, size_t);
|
||||
static void salsa20_8(uint8_t[64]);
|
||||
static void blockmix_salsa8(uint8_t *, uint8_t *, size_t);
|
||||
static uint64_t integerify(uint8_t *, size_t);
|
||||
static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *);
|
||||
|
||||
static void
|
||||
blkcpy(uint8_t * dest, uint8_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(uint8_t * dest, uint8_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dest[i] ^= src[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(uint8_t B[64])
|
||||
{
|
||||
uint32_t B32[16];
|
||||
uint32_t x[16];
|
||||
size_t i;
|
||||
|
||||
/* Convert little-endian values in. */
|
||||
for (i = 0; i < 16; i++)
|
||||
B32[i] = le32dec(&B[i * 4]);
|
||||
|
||||
/* Compute x = doubleround^4(B32). */
|
||||
for (i = 0; i < 16; i++)
|
||||
x[i] = B32[i];
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns. */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows. */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
|
||||
/* Compute B32 = B32 + x. */
|
||||
for (i = 0; i < 16; i++)
|
||||
B32[i] += x[i];
|
||||
|
||||
/* Convert little-endian values out. */
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[4 * i], B32[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(B, Y, r):
|
||||
* Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
* length; the temporary space Y must also be the same size.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r)
|
||||
{
|
||||
uint8_t X[64];
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &B[(2 * r - 1) * 64], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &B[i * 64], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
blkcpy(&Y[i * 64], X, 64);
|
||||
}
|
||||
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64);
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(uint8_t * B, size_t r)
|
||||
{
|
||||
uint8_t * X = &B[(2 * r - 1) * 64];
|
||||
|
||||
return (le64dec(X));
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the
|
||||
* temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
* XY must be 256r bytes in length. The value N must be a power of 2.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY)
|
||||
{
|
||||
uint8_t * X = XY;
|
||||
uint8_t * Y = &XY[128 * r];
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
|
||||
/* 1: X <-- B */
|
||||
blkcpy(X, B, 128 * r);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[i * (128 * r)], X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, &V[j * (128 * r)], 128 * r);
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
blkcpy(B, X, 128 * r);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
uint8_t * B;
|
||||
uint8_t * V;
|
||||
uint8_t * XY;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N == 0)) {
|
||||
errno = EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
if ((B = malloc(128 * r * p)) == NULL)
|
||||
goto err0;
|
||||
if ((XY = malloc(256 * r)) == NULL)
|
||||
goto err1;
|
||||
if ((V = malloc(128 * r * N)) == NULL)
|
||||
goto err2;
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
#endif
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[i * 128 * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
#endif
|
||||
|
||||
/* Free memory. */
|
||||
free(V);
|
||||
free(XY);
|
||||
free(B);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err2:
|
||||
free(XY);
|
||||
err1:
|
||||
free(B);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
#include <openssl/evp.h>
|
||||
#else
|
||||
#include "sha256.h"
|
||||
#endif
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
static void blkcpy(void *, void *, size_t);
|
||||
static void blkxor(void *, void *, size_t);
|
||||
static void salsa20_8(__m128i *);
|
||||
static void blockmix_salsa8(__m128i *, __m128i *, __m128i *, size_t);
|
||||
static uint64_t integerify(void *, size_t);
|
||||
static void smix(uint8_t *, size_t, uint64_t, void *, void *);
|
||||
|
||||
static void
|
||||
blkcpy(void * dest, void * src, size_t len)
|
||||
{
|
||||
__m128i * D = dest;
|
||||
__m128i * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = S[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(void * dest, void * src, size_t len)
|
||||
{
|
||||
__m128i * D = dest;
|
||||
__m128i * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = _mm_xor_si128(D[i], S[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(__m128i B[4])
|
||||
{
|
||||
__m128i X0, X1, X2, X3;
|
||||
__m128i T;
|
||||
size_t i;
|
||||
|
||||
X0 = B[0];
|
||||
X1 = B[1];
|
||||
X2 = B[2];
|
||||
X3 = B[3];
|
||||
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
/* Operate on "columns". */
|
||||
T = _mm_add_epi32(X0, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X1, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X3, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x93);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x39);
|
||||
|
||||
/* Operate on "rows". */
|
||||
T = _mm_add_epi32(X0, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X3, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X1, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x39);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x93);
|
||||
}
|
||||
|
||||
B[0] = _mm_add_epi32(B[0], X0);
|
||||
B[1] = _mm_add_epi32(B[1], X1);
|
||||
B[2] = _mm_add_epi32(B[2], X2);
|
||||
B[3] = _mm_add_epi32(B[3], X3);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(Bin, Bout, X, r):
|
||||
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
|
||||
* bytes in length; the output Bout must also be the same size. The
|
||||
* temporary space X must be 64 bytes.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(__m128i * Bin, __m128i * Bout, __m128i * X, size_t r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &Bin[8 * r - 4], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[i * 4], X, 64);
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8 + 4], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[(r + i) * 4], X, 64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(void * B, size_t r)
|
||||
{
|
||||
uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
|
||||
return (((uint64_t)(X[13]) << 32) + X[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
|
||||
{
|
||||
__m128i * X = XY;
|
||||
__m128i * Y = (void *)((uintptr_t)(XY) + 128 * r);
|
||||
__m128i * Z = (void *)((uintptr_t)(XY) + 256 * r);
|
||||
uint32_t * X32 = (void *)X;
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
X32[k * 16 + i] =
|
||||
le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
|
||||
Y, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(Y, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
le32enc(&B[(k * 16 + (i * 5 % 16)) * 4],
|
||||
X32[k * 16 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
void * B0, * V0, * XY0;
|
||||
uint8_t * B;
|
||||
uint32_t * V;
|
||||
uint32_t * XY;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N == 0)) {
|
||||
errno = EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > (SIZE_MAX - 64) / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
#ifdef HAVE_POSIX_MEMALIGN
|
||||
if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
|
||||
goto err0;
|
||||
B = (uint8_t *)(B0);
|
||||
if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(XY0);
|
||||
#ifndef MAP_ANON
|
||||
if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
#else
|
||||
if ((B0 = malloc(128 * r * p + 63)) == NULL)
|
||||
goto err0;
|
||||
B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
|
||||
if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
|
||||
#ifndef MAP_ANON
|
||||
if ((V0 = malloc(128 * r * N + 63)) == NULL)
|
||||
goto err2;
|
||||
V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MAP_ANON
|
||||
if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
#else
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
#endif
|
||||
-1, 0)) == MAP_FAILED)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
#endif
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[i * 128 * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
#ifdef USE_OPENSSL_PBKDF2
|
||||
PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
#endif
|
||||
|
||||
/* Free memory. */
|
||||
#ifdef MAP_ANON
|
||||
if (munmap(V0, 128 * r * N))
|
||||
goto err2;
|
||||
#else
|
||||
free(V0);
|
||||
#endif
|
||||
free(XY0);
|
||||
free(B0);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err2:
|
||||
free(XY0);
|
||||
err1:
|
||||
free(B0);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _CRYPTO_SCRYPT_H_
|
||||
#define _CRYPTO_SCRYPT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
|
||||
uint32_t, uint32_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_CRYPTO_SCRYPT_H_ */
|
||||
@@ -0,0 +1,140 @@
|
||||
/*-
|
||||
* Copyright 2007-2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _SYSENDIAN_H_
|
||||
#define _SYSENDIAN_H_
|
||||
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
|
||||
#if !HAVE_DECL_BE64ENC
|
||||
#undef HAVE_SYS_ENDIAN_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
be64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
|
||||
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
|
||||
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
|
||||
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[7] = x & 0xff;
|
||||
p[6] = (x >> 8) & 0xff;
|
||||
p[5] = (x >> 16) & 0xff;
|
||||
p[4] = (x >> 24) & 0xff;
|
||||
p[3] = (x >> 32) & 0xff;
|
||||
p[2] = (x >> 40) & 0xff;
|
||||
p[1] = (x >> 48) & 0xff;
|
||||
p[0] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
le32dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le32enc(void *pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
le64dec(const void *pp)
|
||||
{
|
||||
const uint8_t *p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
|
||||
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
|
||||
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
|
||||
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le64enc(void *pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
p[4] = (x >> 32) & 0xff;
|
||||
p[5] = (x >> 40) & 0xff;
|
||||
p[6] = (x >> 48) & 0xff;
|
||||
p[7] = (x >> 56) & 0xff;
|
||||
}
|
||||
#endif /* !HAVE_SYS_ENDIAN_H */
|
||||
|
||||
#endif /* !_SYSENDIAN_H_ */
|
||||
@@ -0,0 +1,11 @@
|
||||
bionic.patch:
|
||||
|
||||
Allows scrypt to compile against bionic.
|
||||
|
||||
use_openssl_pbkdf2.patch:
|
||||
|
||||
Uses the PBKDF2 function from OpenSSL (it uses accelerated SHA256)
|
||||
|
||||
arm-neon.patch:
|
||||
|
||||
Adds NEON acceleration for the Salsa20/8 mixing function.
|
||||
@@ -0,0 +1,437 @@
|
||||
diff --git a/lib/crypto/crypto_scrypt-neon-salsa208.h b/lib/crypto/crypto_scrypt-neon-salsa208.h
|
||||
new file mode 100644
|
||||
index 0000000..a3b1019
|
||||
--- /dev/null
|
||||
+++ b/lib/crypto/crypto_scrypt-neon-salsa208.h
|
||||
@@ -0,0 +1,120 @@
|
||||
+/*
|
||||
+ * version 20110505
|
||||
+ * D. J. Bernstein
|
||||
+ * Public domain.
|
||||
+ *
|
||||
+ * Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
|
||||
+ */
|
||||
+
|
||||
+#define ROUNDS 8
|
||||
+static void
|
||||
+salsa20_8_intrinsic(void * input)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ const uint32x4_t abab = {-1,0,-1,0};
|
||||
+
|
||||
+ /*
|
||||
+ * This is modified since we only have one argument. Usually you'd rearrange
|
||||
+ * the constant, key, and input bytes, but we just have one linear array to
|
||||
+ * rearrange which is a bit easier.
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ * Change the input to be diagonals as if it's a 4x4 matrix of 32-bit values.
|
||||
+ */
|
||||
+ uint32x4_t x0x5x10x15;
|
||||
+ uint32x4_t x12x1x6x11;
|
||||
+ uint32x4_t x8x13x2x7;
|
||||
+ uint32x4_t x4x9x14x3;
|
||||
+
|
||||
+ uint32x4_t x0x1x10x11;
|
||||
+ uint32x4_t x12x13x6x7;
|
||||
+ uint32x4_t x8x9x2x3;
|
||||
+ uint32x4_t x4x5x14x15;
|
||||
+
|
||||
+ uint32x4_t x0x1x2x3;
|
||||
+ uint32x4_t x4x5x6x7;
|
||||
+ uint32x4_t x8x9x10x11;
|
||||
+ uint32x4_t x12x13x14x15;
|
||||
+
|
||||
+ x0x1x2x3 = vld1q_u8((uint8_t *) input);
|
||||
+ x4x5x6x7 = vld1q_u8(16 + (uint8_t *) input);
|
||||
+ x8x9x10x11 = vld1q_u8(32 + (uint8_t *) input);
|
||||
+ x12x13x14x15 = vld1q_u8(48 + (uint8_t *) input);
|
||||
+
|
||||
+ x0x1x10x11 = vcombine_u32(vget_low_u32(x0x1x2x3), vget_high_u32(x8x9x10x11));
|
||||
+ x4x5x14x15 = vcombine_u32(vget_low_u32(x4x5x6x7), vget_high_u32(x12x13x14x15));
|
||||
+ x8x9x2x3 = vcombine_u32(vget_low_u32(x8x9x10x11), vget_high_u32(x0x1x2x3));
|
||||
+ x12x13x6x7 = vcombine_u32(vget_low_u32(x12x13x14x15), vget_high_u32(x4x5x6x7));
|
||||
+
|
||||
+ x0x5x10x15 = vbslq_u32(abab,x0x1x10x11,x4x5x14x15);
|
||||
+ x8x13x2x7 = vbslq_u32(abab,x8x9x2x3,x12x13x6x7);
|
||||
+ x4x9x14x3 = vbslq_u32(abab,x4x5x14x15,x8x9x2x3);
|
||||
+ x12x1x6x11 = vbslq_u32(abab,x12x13x6x7,x0x1x10x11);
|
||||
+
|
||||
+ uint32x4_t start0 = x0x5x10x15;
|
||||
+ uint32x4_t start1 = x12x1x6x11;
|
||||
+ uint32x4_t start3 = x4x9x14x3;
|
||||
+ uint32x4_t start2 = x8x13x2x7;
|
||||
+
|
||||
+ /* From here on this should be the same as the SUPERCOP version. */
|
||||
+
|
||||
+ uint32x4_t diag0 = start0;
|
||||
+ uint32x4_t diag1 = start1;
|
||||
+ uint32x4_t diag2 = start2;
|
||||
+ uint32x4_t diag3 = start3;
|
||||
+
|
||||
+ uint32x4_t a0;
|
||||
+ uint32x4_t a1;
|
||||
+ uint32x4_t a2;
|
||||
+ uint32x4_t a3;
|
||||
+
|
||||
+ for (i = ROUNDS;i > 0;i -= 2) {
|
||||
+ a0 = diag1 + diag0;
|
||||
+ diag3 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
|
||||
+ a1 = diag0 + diag3;
|
||||
+ diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
|
||||
+ a2 = diag3 + diag2;
|
||||
+ diag1 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
|
||||
+ a3 = diag2 + diag1;
|
||||
+ diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
|
||||
+
|
||||
+ diag3 = vextq_u32(diag3,diag3,3);
|
||||
+ diag2 = vextq_u32(diag2,diag2,2);
|
||||
+ diag1 = vextq_u32(diag1,diag1,1);
|
||||
+
|
||||
+ a0 = diag3 + diag0;
|
||||
+ diag1 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
|
||||
+ a1 = diag0 + diag1;
|
||||
+ diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
|
||||
+ a2 = diag1 + diag2;
|
||||
+ diag3 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
|
||||
+ a3 = diag2 + diag3;
|
||||
+ diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
|
||||
+
|
||||
+ diag1 = vextq_u32(diag1,diag1,3);
|
||||
+ diag2 = vextq_u32(diag2,diag2,2);
|
||||
+ diag3 = vextq_u32(diag3,diag3,1);
|
||||
+ }
|
||||
+
|
||||
+ x0x5x10x15 = diag0 + start0;
|
||||
+ x12x1x6x11 = diag1 + start1;
|
||||
+ x8x13x2x7 = diag2 + start2;
|
||||
+ x4x9x14x3 = diag3 + start3;
|
||||
+
|
||||
+ x0x1x10x11 = vbslq_u32(abab,x0x5x10x15,x12x1x6x11);
|
||||
+ x12x13x6x7 = vbslq_u32(abab,x12x1x6x11,x8x13x2x7);
|
||||
+ x8x9x2x3 = vbslq_u32(abab,x8x13x2x7,x4x9x14x3);
|
||||
+ x4x5x14x15 = vbslq_u32(abab,x4x9x14x3,x0x5x10x15);
|
||||
+
|
||||
+ x0x1x2x3 = vcombine_u32(vget_low_u32(x0x1x10x11),vget_high_u32(x8x9x2x3));
|
||||
+ x4x5x6x7 = vcombine_u32(vget_low_u32(x4x5x14x15),vget_high_u32(x12x13x6x7));
|
||||
+ x8x9x10x11 = vcombine_u32(vget_low_u32(x8x9x2x3),vget_high_u32(x0x1x10x11));
|
||||
+ x12x13x14x15 = vcombine_u32(vget_low_u32(x12x13x6x7),vget_high_u32(x4x5x14x15));
|
||||
+
|
||||
+ vst1q_u8((uint8_t *) input,(uint8x16_t) x0x1x2x3);
|
||||
+ vst1q_u8(16 + (uint8_t *) input,(uint8x16_t) x4x5x6x7);
|
||||
+ vst1q_u8(32 + (uint8_t *) input,(uint8x16_t) x8x9x10x11);
|
||||
+ vst1q_u8(48 + (uint8_t *) input,(uint8x16_t) x12x13x14x15);
|
||||
+}
|
||||
diff --git a/lib/crypto/crypto_scrypt-neon.c b/lib/crypto/crypto_scrypt-neon.c
|
||||
new file mode 100644
|
||||
index 0000000..a3bf052
|
||||
--- /dev/null
|
||||
+++ b/lib/crypto/crypto_scrypt-neon.c
|
||||
@@ -0,0 +1,305 @@
|
||||
+/*-
|
||||
+ * Copyright 2009 Colin Percival
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. 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.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 file was originally written by Colin Percival as part of the Tarsnap
|
||||
+ * online backup system.
|
||||
+ */
|
||||
+#include "scrypt_platform.h"
|
||||
+
|
||||
+#include <machine/cpu-features.h>
|
||||
+#include <arm_neon.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdint.h>
|
||||
+#include <limits.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+#include <openssl/evp.h>
|
||||
+#else
|
||||
+#include "sha256.h"
|
||||
+#endif
|
||||
+#include "sysendian.h"
|
||||
+
|
||||
+#include "crypto_scrypt.h"
|
||||
+
|
||||
+#include "crypto_scrypt-neon-salsa208.h"
|
||||
+
|
||||
+static void blkcpy(void *, void *, size_t);
|
||||
+static void blkxor(void *, void *, size_t);
|
||||
+void crypto_core_salsa208_armneon2(void *);
|
||||
+static void blockmix_salsa8(uint8x16_t *, uint8x16_t *, uint8x16_t *, size_t);
|
||||
+static uint64_t integerify(void *, size_t);
|
||||
+static void smix(uint8_t *, size_t, uint64_t, void *, void *);
|
||||
+
|
||||
+static void
|
||||
+blkcpy(void * dest, void * src, size_t len)
|
||||
+{
|
||||
+ uint8x16_t * D = dest;
|
||||
+ uint8x16_t * S = src;
|
||||
+ size_t L = len / 16;
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < L; i++)
|
||||
+ D[i] = S[i];
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+blkxor(void * dest, void * src, size_t len)
|
||||
+{
|
||||
+ uint8x16_t * D = dest;
|
||||
+ uint8x16_t * S = src;
|
||||
+ size_t L = len / 16;
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < L; i++)
|
||||
+ D[i] = veorq_u8(D[i], S[i]);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * blockmix_salsa8(B, Y, r):
|
||||
+ * Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
+ * length; the temporary space Y must also be the same size.
|
||||
+ */
|
||||
+static void
|
||||
+blockmix_salsa8(uint8x16_t * Bin, uint8x16_t * Bout, uint8x16_t * X, size_t r)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ /* 1: X <-- B_{2r - 1} */
|
||||
+ blkcpy(X, &Bin[8 * r - 4], 64);
|
||||
+
|
||||
+ /* 2: for i = 0 to 2r - 1 do */
|
||||
+ for (i = 0; i < r; i++) {
|
||||
+ /* 3: X <-- H(X \xor B_i) */
|
||||
+ blkxor(X, &Bin[i * 8], 64);
|
||||
+ salsa20_8_intrinsic((void *) X);
|
||||
+
|
||||
+ /* 4: Y_i <-- X */
|
||||
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
+ blkcpy(&Bout[i * 4], X, 64);
|
||||
+
|
||||
+ /* 3: X <-- H(X \xor B_i) */
|
||||
+ blkxor(X, &Bin[i * 8 + 4], 64);
|
||||
+ salsa20_8_intrinsic((void *) X);
|
||||
+
|
||||
+ /* 4: Y_i <-- X */
|
||||
+ /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
+ blkcpy(&Bout[(r + i) * 4], X, 64);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * integerify(B, r):
|
||||
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
+ */
|
||||
+static uint64_t
|
||||
+integerify(void * B, size_t r)
|
||||
+{
|
||||
+ uint8_t * X = (void*)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
+
|
||||
+ return (le64dec(X));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * smix(B, r, N, V, XY):
|
||||
+ * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the
|
||||
+ * temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
+ * XY must be 256r bytes in length. The value N must be a power of 2.
|
||||
+ */
|
||||
+static void
|
||||
+smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
|
||||
+{
|
||||
+ uint8x16_t * X = XY;
|
||||
+ uint8x16_t * Y = (void *)((uintptr_t)(XY) + 128 * r);
|
||||
+ uint8x16_t * Z = (void *)((uintptr_t)(XY) + 256 * r);
|
||||
+ uint32_t * X32 = (void *)X;
|
||||
+ uint64_t i, j;
|
||||
+ size_t k;
|
||||
+
|
||||
+ /* 1: X <-- B */
|
||||
+ blkcpy(X, B, 128 * r);
|
||||
+
|
||||
+ /* 2: for i = 0 to N - 1 do */
|
||||
+ for (i = 0; i < N; i += 2) {
|
||||
+ /* 3: V_i <-- X */
|
||||
+ blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
|
||||
+
|
||||
+ /* 4: X <-- H(X) */
|
||||
+ blockmix_salsa8(X, Y, Z, r);
|
||||
+
|
||||
+ /* 3: V_i <-- X */
|
||||
+ blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
|
||||
+ Y, 128 * r);
|
||||
+
|
||||
+ /* 4: X <-- H(X) */
|
||||
+ blockmix_salsa8(Y, X, Z, r);
|
||||
+ }
|
||||
+
|
||||
+ /* 6: for i = 0 to N - 1 do */
|
||||
+ for (i = 0; i < N; i += 2) {
|
||||
+ /* 7: j <-- Integerify(X) mod N */
|
||||
+ j = integerify(X, r) & (N - 1);
|
||||
+
|
||||
+ /* 8: X <-- H(X \xor V_j) */
|
||||
+ blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
+ blockmix_salsa8(X, Y, Z, r);
|
||||
+
|
||||
+ /* 7: j <-- Integerify(X) mod N */
|
||||
+ j = integerify(Y, r) & (N - 1);
|
||||
+
|
||||
+ /* 8: X <-- H(X \xor V_j) */
|
||||
+ blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
+ blockmix_salsa8(Y, X, Z, r);
|
||||
+ }
|
||||
+
|
||||
+ /* 10: B' <-- X */
|
||||
+ blkcpy(B, X, 128 * r);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
+ * p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
+ * must be a power of 2.
|
||||
+ *
|
||||
+ * Return 0 on success; or -1 on error.
|
||||
+ */
|
||||
+int
|
||||
+crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
+ const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||
+ uint8_t * buf, size_t buflen)
|
||||
+{
|
||||
+ void * B0, * V0, * XY0;
|
||||
+ uint8_t * B;
|
||||
+ uint32_t * V;
|
||||
+ uint32_t * XY;
|
||||
+ uint32_t i;
|
||||
+
|
||||
+ /* Sanity-check parameters. */
|
||||
+#if SIZE_MAX > UINT32_MAX
|
||||
+ if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
+ errno = EFBIG;
|
||||
+ goto err0;
|
||||
+ }
|
||||
+#endif
|
||||
+ if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
+ errno = EFBIG;
|
||||
+ goto err0;
|
||||
+ }
|
||||
+ if (((N & (N - 1)) != 0) || (N == 0)) {
|
||||
+ errno = EINVAL;
|
||||
+ goto err0;
|
||||
+ }
|
||||
+ if ((r > SIZE_MAX / 128 / p) ||
|
||||
+#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
+ (r > SIZE_MAX / 256) ||
|
||||
+#endif
|
||||
+ (N > SIZE_MAX / 128 / r)) {
|
||||
+ errno = ENOMEM;
|
||||
+ goto err0;
|
||||
+ }
|
||||
+
|
||||
+ /* Allocate memory. */
|
||||
+#ifdef HAVE_POSIX_MEMALIGN
|
||||
+ if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
|
||||
+ goto err0;
|
||||
+ B = (uint8_t *)(B0);
|
||||
+ if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
|
||||
+ goto err1;
|
||||
+ XY = (uint32_t *)(XY0);
|
||||
+#ifndef MAP_ANON
|
||||
+ if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
|
||||
+ goto err2;
|
||||
+ V = (uint32_t *)(V0);
|
||||
+#endif
|
||||
+#else
|
||||
+ if ((B0 = malloc(128 * r * p + 63)) == NULL)
|
||||
+ goto err0;
|
||||
+ B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
|
||||
+ if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
|
||||
+ goto err1;
|
||||
+ XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
|
||||
+#ifndef MAP_ANON
|
||||
+ if ((V0 = malloc(128 * r * N + 63)) == NULL)
|
||||
+ goto err2;
|
||||
+ V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
|
||||
+#endif
|
||||
+#endif
|
||||
+#ifdef MAP_ANON
|
||||
+ if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
|
||||
+#ifdef MAP_NOCORE
|
||||
+ MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
+#else
|
||||
+ MAP_ANON | MAP_PRIVATE,
|
||||
+#endif
|
||||
+ -1, 0)) == MAP_FAILED)
|
||||
+ goto err2;
|
||||
+ V = (uint32_t *)(V0);
|
||||
+#endif
|
||||
+
|
||||
+ /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
+#else
|
||||
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
+#endif
|
||||
+
|
||||
+ /* 2: for i = 0 to p - 1 do */
|
||||
+ for (i = 0; i < p; i++) {
|
||||
+ /* 3: B_i <-- MF(B_i, N) */
|
||||
+ smix(&B[i * 128 * r], r, N, V, XY);
|
||||
+ }
|
||||
+
|
||||
+ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
+#else
|
||||
+ PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
+#endif
|
||||
+
|
||||
+ /* Free memory. */
|
||||
+#ifdef MAP_ANON
|
||||
+ if (munmap(V0, 128 * r * N))
|
||||
+ goto err2;
|
||||
+#else
|
||||
+ free(V0);
|
||||
+#endif
|
||||
+ free(XY0);
|
||||
+ free(B0);
|
||||
+
|
||||
+ /* Success! */
|
||||
+ return (0);
|
||||
+
|
||||
+err2:
|
||||
+ free(XY0);
|
||||
+err1:
|
||||
+ free(B0);
|
||||
+err0:
|
||||
+ /* Failure! */
|
||||
+ return (-1);
|
||||
+}
|
||||
@@ -0,0 +1,80 @@
|
||||
diff --git a/lib/crypto/crypto_scrypt-ref.c b/lib/crypto/crypto_scrypt-ref.c
|
||||
index 79a6f8f..60ef2aa 100644
|
||||
--- a/lib/crypto/crypto_scrypt-ref.c
|
||||
+++ b/lib/crypto/crypto_scrypt-ref.c
|
||||
@@ -34,7 +34,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+#include <openssl/evp.h>
|
||||
+#else
|
||||
#include "sha256.h"
|
||||
+#endif
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
@@ -256,7 +260,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
goto err2;
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
+#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
+#endif
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
@@ -265,7 +273,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
+#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
+#endif
|
||||
|
||||
/* Free memory. */
|
||||
free(V);
|
||||
diff --git a/lib/crypto/crypto_scrypt-sse.c b/lib/crypto/crypto_scrypt-sse.c
|
||||
index 875175e..dd18f29 100644
|
||||
--- a/lib/crypto/crypto_scrypt-sse.c
|
||||
+++ b/lib/crypto/crypto_scrypt-sse.c
|
||||
@@ -37,7 +37,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+#include <openssl/evp.h>
|
||||
+#else
|
||||
#include "sha256.h"
|
||||
+#endif
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
@@ -332,7 +336,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
#endif
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
|
||||
+#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
+#endif
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
@@ -341,7 +349,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
+#ifdef USE_OPENSSL_PBKDF2
|
||||
+ PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
|
||||
+#else
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
+#endif
|
||||
|
||||
/* Free memory. */
|
||||
#ifdef MAP_ANON
|
||||
@@ -0,0 +1,94 @@
|
||||
CONFIGURE_ARGS="\
|
||||
\
|
||||
"
|
||||
|
||||
# unneeded directories
|
||||
UNNEEDED_SOURCES="\
|
||||
lib/scryptenc \
|
||||
"
|
||||
|
||||
# unneeded files
|
||||
UNNEEDED_SOURCES+="\
|
||||
config.h.in \
|
||||
configure \
|
||||
FORMAT \
|
||||
main.c \
|
||||
Makefile.in \
|
||||
scrypt.1 \
|
||||
lib/crypto/crypto_aesctr.c \
|
||||
lib/crypto/crypto_aesctr.h \
|
||||
lib/crypto/crypto_scrypt-nosse.c \
|
||||
lib/crypto/sha256.c \
|
||||
lib/crypto/sha256.h \
|
||||
lib/util/memlimit.c \
|
||||
lib/util/memlimit.h \
|
||||
lib/util/readpass.c \
|
||||
lib/util/readpass.h \
|
||||
lib/util/warn.c \
|
||||
lib/util/warn.h \
|
||||
"
|
||||
|
||||
NEEDED_SOURCES="\
|
||||
config.h \
|
||||
lib \
|
||||
scrypt_platform.h \
|
||||
"
|
||||
|
||||
SCRYPT_INCLUDES="\
|
||||
lib/crypto \
|
||||
lib/util \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES="\
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_arm="\
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_EXCLUDES_arm="\
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_arm_neon="\
|
||||
lib/crypto/crypto_scrypt-neon.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_EXCLUDES_arm_neon="\
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_mips="\
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_EXCLUDES_mips="\
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_x86="\
|
||||
lib/crypto/crypto_scrypt-sse.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_EXCLUDES_x86="\
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_x86_64="\
|
||||
lib/crypto/crypto_scrypt-sse.c \
|
||||
"
|
||||
|
||||
SCRYPT_SOURCES_EXCLUDES_x86_64="\
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
"
|
||||
|
||||
SCRYPT_PATCHES="\
|
||||
use_openssl_pbkdf2.patch \
|
||||
arm-neon.patch \
|
||||
"
|
||||
|
||||
SCRYPT_PATCHES_use_openssl_pbkdf2_SOURCES="\
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
"
|
||||
|
||||
SCRYPT_PATCHES_bionic_SOURCES="\
|
||||
lib/crypto/crypto_scrypt-neon.c \
|
||||
lib/crypto/crypto_scrypt-neon-salsa208.h \
|
||||
"
|
||||
@@ -0,0 +1 @@
|
||||
SCRYPT_VERSION=1.1.6
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _SCRYPT_PLATFORM_H_
|
||||
#define _SCRYPT_PLATFORM_H_
|
||||
|
||||
#if defined(CONFIG_H_FILE)
|
||||
#include CONFIG_H_FILE
|
||||
#elif defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#else
|
||||
#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
|
||||
#endif
|
||||
|
||||
#endif /* !_SCRYPT_PLATFORM_H_ */
|
||||
@@ -0,0 +1,25 @@
|
||||
# Build the scrypt unit tests
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
scrypt_test.cpp
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
external/gtest/include \
|
||||
external/scrypt/lib/crypto
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcrypto
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libscrypt_static \
|
||||
libgtest \
|
||||
libgtest_main
|
||||
|
||||
LOCAL_MODULE := scrypt_test
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "scrypt_test"
|
||||
#include <utils/Log.h>
|
||||
#include <utils/UniquePtr.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
extern "C" {
|
||||
#include <crypto_scrypt.h>
|
||||
}
|
||||
|
||||
namespace android {
|
||||
|
||||
typedef struct scrypt_test_setting_t {
|
||||
const char *pw, *salt;
|
||||
uint32_t Nfactor, rfactor, pfactor;
|
||||
} scrypt_test_setting;
|
||||
|
||||
static const scrypt_test_setting post_settings[] = {
|
||||
{"", "", 16, 1, 1},
|
||||
{"password", "NaCl", 1024, 8, 16},
|
||||
{"pleaseletmein", "SodiumChloride", 16384, 8, 1},
|
||||
{0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const uint8_t post_vectors[][64] = {
|
||||
{0x77,0xd6,0x57,0x62,0x38,0x65,0x7b,0x20,0x3b,0x19,0xca,0x42,0xc1,0x8a,0x04,0x97,
|
||||
0xf1,0x6b,0x48,0x44,0xe3,0x07,0x4a,0xe8,0xdf,0xdf,0xfa,0x3f,0xed,0xe2,0x14,0x42,
|
||||
0xfc,0xd0,0x06,0x9d,0xed,0x09,0x48,0xf8,0x32,0x6a,0x75,0x3a,0x0f,0xc8,0x1f,0x17,
|
||||
0xe8,0xd3,0xe0,0xfb,0x2e,0x0d,0x36,0x28,0xcf,0x35,0xe2,0x0c,0x38,0xd1,0x89,0x06},
|
||||
{0xfd,0xba,0xbe,0x1c,0x9d,0x34,0x72,0x00,0x78,0x56,0xe7,0x19,0x0d,0x01,0xe9,0xfe,
|
||||
0x7c,0x6a,0xd7,0xcb,0xc8,0x23,0x78,0x30,0xe7,0x73,0x76,0x63,0x4b,0x37,0x31,0x62,
|
||||
0x2e,0xaf,0x30,0xd9,0x2e,0x22,0xa3,0x88,0x6f,0xf1,0x09,0x27,0x9d,0x98,0x30,0xda,
|
||||
0xc7,0x27,0xaf,0xb9,0x4a,0x83,0xee,0x6d,0x83,0x60,0xcb,0xdf,0xa2,0xcc,0x06,0x40},
|
||||
{0x70,0x23,0xbd,0xcb,0x3a,0xfd,0x73,0x48,0x46,0x1c,0x06,0xcd,0x81,0xfd,0x38,0xeb,
|
||||
0xfd,0xa8,0xfb,0xba,0x90,0x4f,0x8e,0x3e,0xa9,0xb5,0x43,0xf6,0x54,0x5d,0xa1,0xf2,
|
||||
0xd5,0x43,0x29,0x55,0x61,0x3f,0x0f,0xcf,0x62,0xd4,0x97,0x05,0x24,0x2a,0x9a,0xf9,
|
||||
0xe6,0x1e,0x85,0xdc,0x0d,0x65,0x1e,0x40,0xdf,0xcf,0x01,0x7b,0x45,0x57,0x58,0x87},
|
||||
};
|
||||
|
||||
class ScryptTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(ScryptTest, TestVectors) {
|
||||
int i;
|
||||
|
||||
for (i = 0; post_settings[i].pw != NULL; i++) {
|
||||
uint8_t output[64];
|
||||
|
||||
scrypt_test_setting_t s = post_settings[i];
|
||||
ASSERT_EQ(0,
|
||||
crypto_scrypt((const uint8_t*) s.pw, strlen(s.pw), (const uint8_t*) s.salt,
|
||||
strlen(s.salt), s.Nfactor, s.rfactor, s.pfactor, output, sizeof(output)))
|
||||
<< "scrypt call should succeed for " << i << "; error=" << strerror(errno);
|
||||
ASSERT_EQ(0, memcmp(post_vectors[i], output, sizeof(output)))
|
||||
<< "Should match expected output";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user