Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial source files from Google's AOSP

  • Loading branch information...
commit 3e2b55b4528d3d9077ca20ab4ae1838c67671c21 1 parent ef4c9ed
Pete Batard authored
View
2  README.md
@@ -2,3 +2,5 @@ bootimg-tools
=============
Android boot.img creation and extraction tools (also MinGW compatible)
+Based on the original Android bootimg tools from:
+ https://android.googlesource.com/platform/system/core
View
352 cpio/mkbootfs.c
@@ -0,0 +1,352 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include <private/android_filesystem_config.h>
+
+/* NOTES
+**
+** - see buffer-format.txt from the linux kernel docs for
+** an explanation of this file format
+** - dotfiles are ignored
+** - directories named 'root' are ignored
+** - device notes, pipes, etc are not supported (error)
+*/
+
+void die(const char *why, ...)
+{
+ va_list ap;
+
+ va_start(ap, why);
+ fprintf(stderr,"error: ");
+ vfprintf(stderr, why, ap);
+ fprintf(stderr,"\n");
+ va_end(ap);
+ exit(1);
+}
+
+struct fs_config_entry {
+ char* name;
+ int uid, gid, mode;
+};
+
+static struct fs_config_entry* canned_config = NULL;
+
+/* Each line in the canned file should be a path plus three ints (uid,
+ * gid, mode). */
+#ifdef PATH_MAX
+#define CANNED_LINE_LENGTH (PATH_MAX+100)
+#else
+#define CANNED_LINE_LENGTH (1024)
+#endif
+
+static int verbose = 0;
+static int total_size = 0;
+
+static void fix_stat(const char *path, struct stat *s)
+{
+ uint64_t capabilities;
+ if (canned_config) {
+ // Use the list of file uid/gid/modes loaded from the file
+ // given with -f.
+
+ struct fs_config_entry* empty_path_config = NULL;
+ struct fs_config_entry* p;
+ for (p = canned_config; p->name; ++p) {
+ if (!p->name[0]) {
+ empty_path_config = p;
+ }
+ if (strcmp(p->name, path) == 0) {
+ s->st_uid = p->uid;
+ s->st_gid = p->gid;
+ s->st_mode = p->mode | (s->st_mode & ~07777);
+ return;
+ }
+ }
+ s->st_uid = empty_path_config->uid;
+ s->st_gid = empty_path_config->gid;
+ s->st_mode = empty_path_config->mode | (s->st_mode & ~07777);
+ } else {
+ // Use the compiled-in fs_config() function.
+
+ fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode, &capabilities);
+ }
+}
+
+static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
+{
+ // Nothing is special about this value, just picked something in the
+ // approximate range that was being used already, and avoiding small
+ // values which may be special.
+ static unsigned next_inode = 300000;
+
+ while(total_size & 3) {
+ total_size++;
+ putchar(0);
+ }
+
+ fix_stat(out, s);
+// fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode);
+
+ printf("%06x%08x%08x%08x%08x%08x%08x"
+ "%08x%08x%08x%08x%08x%08x%08x%s%c",
+ 0x070701,
+ next_inode++, // s.st_ino,
+ s->st_mode,
+ 0, // s.st_uid,
+ 0, // s.st_gid,
+ 1, // s.st_nlink,
+ 0, // s.st_mtime,
+ datasize,
+ 0, // volmajor
+ 0, // volminor
+ 0, // devmajor
+ 0, // devminor,
+ olen + 1,
+ 0,
+ out,
+ 0
+ );
+
+ total_size += 6 + 8*13 + olen + 1;
+
+ if(strlen(out) != (unsigned int)olen) die("ACK!");
+
+ while(total_size & 3) {
+ total_size++;
+ putchar(0);
+ }
+
+ if(datasize) {
+ fwrite(data, datasize, 1, stdout);
+ total_size += datasize;
+ }
+}
+
+static void _eject_trailer()
+{
+ struct stat s;
+ memset(&s, 0, sizeof(s));
+ _eject(&s, "TRAILER!!!", 10, 0, 0);
+
+ while(total_size & 0xff) {
+ total_size++;
+ putchar(0);
+ }
+}
+
+static void _archive(char *in, char *out, int ilen, int olen);
+
+static int compare(const void* a, const void* b) {
+ return strcmp(*(const char**)a, *(const char**)b);
+}
+
+static void _archive_dir(char *in, char *out, int ilen, int olen)
+{
+ int i, t;
+ DIR *d;
+ struct dirent *de;
+
+ if(verbose) {
+ fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
+ in, out, ilen, olen);
+ }
+
+ d = opendir(in);
+ if(d == 0) die("cannot open directory '%s'", in);
+
+ int size = 32;
+ int entries = 0;
+ char** names = malloc(size * sizeof(char*));
+ if (names == NULL) {
+ fprintf(stderr, "failed to allocate dir names array (size %d)\n", size);
+ exit(1);
+ }
+
+ while((de = readdir(d)) != 0){
+ /* xxx: feature? maybe some dotfiles are okay */
+ if(de->d_name[0] == '.') continue;
+
+ /* xxx: hack. use a real exclude list */
+ if(!strcmp(de->d_name, "root")) continue;
+
+ if (entries >= size) {
+ size *= 2;
+ names = realloc(names, size * sizeof(char*));
+ if (names == NULL) {
+ fprintf(stderr, "failed to reallocate dir names array (size %d)\n",
+ size);
+ exit(1);
+ }
+ }
+ names[entries] = strdup(de->d_name);
+ if (names[entries] == NULL) {
+ fprintf(stderr, "failed to strdup name \"%s\"\n",
+ de->d_name);
+ exit(1);
+ }
+ ++entries;
+ }
+
+ qsort(names, entries, sizeof(char*), compare);
+
+ for (i = 0; i < entries; ++i) {
+ t = strlen(names[i]);
+ in[ilen] = '/';
+ memcpy(in + ilen + 1, names[i], t + 1);
+
+ if(olen > 0) {
+ out[olen] = '/';
+ memcpy(out + olen + 1, names[i], t + 1);
+ _archive(in, out, ilen + t + 1, olen + t + 1);
+ } else {
+ memcpy(out, names[i], t + 1);
+ _archive(in, out, ilen + t + 1, t);
+ }
+
+ in[ilen] = 0;
+ out[olen] = 0;
+
+ free(names[i]);
+ }
+ free(names);
+}
+
+static void _archive(char *in, char *out, int ilen, int olen)
+{
+ struct stat s;
+
+ if(verbose) {
+ fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
+ in, out, ilen, olen);
+ }
+
+ if(lstat(in, &s)) die("could not stat '%s'\n", in);
+
+ if(S_ISREG(s.st_mode)){
+ char *tmp;
+ int fd;
+
+ fd = open(in, O_RDONLY);
+ if(fd < 0) die("cannot open '%s' for read", in);
+
+ tmp = (char*) malloc(s.st_size);
+ if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
+
+ if(read(fd, tmp, s.st_size) != s.st_size) {
+ die("cannot read %d bytes", s.st_size);
+ }
+
+ _eject(&s, out, olen, tmp, s.st_size);
+
+ free(tmp);
+ close(fd);
+ } else if(S_ISDIR(s.st_mode)) {
+ _eject(&s, out, olen, 0, 0);
+ _archive_dir(in, out, ilen, olen);
+ } else if(S_ISLNK(s.st_mode)) {
+ char buf[1024];
+ int size;
+ size = readlink(in, buf, 1024);
+ if(size < 0) die("cannot read symlink '%s'", in);
+ _eject(&s, out, olen, buf, size);
+ } else {
+ die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
+ }
+}
+
+void archive(const char *start, const char *prefix)
+{
+ char in[8192];
+ char out[8192];
+
+ strcpy(in, start);
+ strcpy(out, prefix);
+
+ _archive_dir(in, out, strlen(in), strlen(out));
+}
+
+static void read_canned_config(char* filename)
+{
+ int allocated = 8;
+ int used = 0;
+
+ canned_config =
+ (struct fs_config_entry*)malloc(allocated * sizeof(struct fs_config_entry));
+
+ char line[CANNED_LINE_LENGTH];
+ FILE* f = fopen(filename, "r");
+ if (f == NULL) die("failed to open canned file");
+
+ while (fgets(line, CANNED_LINE_LENGTH, f) != NULL) {
+ if (!line[0]) break;
+ if (used >= allocated) {
+ allocated *= 2;
+ canned_config = (struct fs_config_entry*)realloc(
+ canned_config, allocated * sizeof(struct fs_config_entry));
+ }
+
+ struct fs_config_entry* cc = canned_config + used;
+
+ if (isspace(line[0])) {
+ cc->name = strdup("");
+ cc->uid = atoi(strtok(line, " \n"));
+ } else {
+ cc->name = strdup(strtok(line, " \n"));
+ cc->uid = atoi(strtok(NULL, " \n"));
+ }
+ cc->gid = atoi(strtok(NULL, " \n"));
+ cc->mode = strtol(strtok(NULL, " \n"), NULL, 8);
+ ++used;
+ }
+ if (used >= allocated) {
+ ++allocated;
+ canned_config = (struct fs_config_entry*)realloc(
+ canned_config, allocated * sizeof(struct fs_config_entry));
+ }
+ canned_config[used].name = NULL;
+
+ fclose(f);
+}
+
+
+int main(int argc, char *argv[])
+{
+ argc--;
+ argv++;
+
+ if (argc > 1 && strcmp(argv[0], "-f") == 0) {
+ read_canned_config(argv[1]);
+ argc -= 2;
+ argv += 2;
+ }
+
+ if(argc == 0) die("no directories to process?!");
+
+ while(argc-- > 0){
+ char *x = strchr(*argv, '=');
+ if(x != 0) {
+ *x++ = 0;
+ } else {
+ x = "";
+ }
+
+ archive(*argv, x);
+
+ argv++;
+ }
+
+ _eject_trailer();
+
+ return 0;
+}
View
40 include/mincrypt/hash-internal.h
@@ -0,0 +1,40 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
+
+#ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
+#define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+struct HASH_CTX; // forward decl
+
+typedef struct HASH_VTAB {
+ void (* const init)(struct HASH_CTX*);
+ void (* const update)(struct HASH_CTX*, const void*, int);
+ const uint8_t* (* const final)(struct HASH_CTX*);
+ const uint8_t* (* const hash)(const void*, int, uint8_t*);
+ int size;
+} HASH_VTAB;
+
+typedef struct HASH_CTX {
+ const HASH_VTAB * f;
+ uint64_t count;
+ uint8_t buf[64];
+ uint32_t state[8]; // upto SHA2
+} HASH_CTX;
+
+#define HASH_init(ctx) (ctx)->f->init(ctx)
+#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
+#define HASH_final(ctx) (ctx)->f->final(ctx)
+#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
+#define HASH_size(ctx) (ctx)->f->size
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // SECURITY_UTIL_LITE_HASH_INTERNAL_H__
View
58 include/mincrypt/rsa.h
@@ -0,0 +1,58 @@
+/* rsa.h
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _EMBEDDED_RSA_H_
+#define _EMBEDDED_RSA_H_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RSANUMBYTES 256 /* 2048 bit key length */
+#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))
+
+typedef struct RSAPublicKey {
+ int len; /* Length of n[] in number of uint32_t */
+ uint32_t n0inv; /* -1 / n[0] mod 2^32 */
+ uint32_t n[RSANUMWORDS]; /* modulus as little endian array */
+ uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
+ int exponent; /* 3 or 65537 */
+} RSAPublicKey;
+
+int RSA_verify(const RSAPublicKey *key,
+ const uint8_t* signature,
+ const int len,
+ const uint8_t* hash,
+ const int hash_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
30 include/mincrypt/sha.h
@@ -0,0 +1,30 @@
+// Copyright 2005 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
+
+#ifndef SECURITY_UTIL_LITE_SHA1_H__
+#define SECURITY_UTIL_LITE_SHA1_H__
+
+#include <stdint.h>
+#include "hash-internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX SHA_CTX;
+
+void SHA_init(SHA_CTX* ctx);
+void SHA_update(SHA_CTX* ctx, const void* data, int len);
+const uint8_t* SHA_final(SHA_CTX* ctx);
+
+// Convenience method. Returns digest address.
+// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
+
+#define SHA_DIGEST_SIZE 20
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // SECURITY_UTIL_LITE_SHA1_H__
View
29 include/mincrypt/sha256.h
@@ -0,0 +1,29 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
+
+#ifndef SECURITY_UTIL_LITE_SHA256_H__
+#define SECURITY_UTIL_LITE_SHA256_H__
+
+#include <stdint.h>
+#include "hash-internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX SHA256_CTX;
+
+void SHA256_init(SHA256_CTX* ctx);
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
+const uint8_t* SHA256_final(SHA256_CTX* ctx);
+
+// Convenience method. Returns digest address.
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
+
+#define SHA256_DIGEST_SIZE 32
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // SECURITY_UTIL_LITE_SHA256_H__
View
117 include/private/android_filesystem_capability.h
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/*
+ * Taken from linux/capability.h, with minor modifications
+ */
+
+#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
+#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H
+
+#include <stdint.h>
+
+#define __user
+#define __u32 uint32_t
+#define __le32 uint32_t
+
+#define _LINUX_CAPABILITY_VERSION_1 0x19980330
+#define _LINUX_CAPABILITY_U32S_1 1
+#define _LINUX_CAPABILITY_VERSION_2 0x20071026
+#define _LINUX_CAPABILITY_U32S_2 2
+#define _LINUX_CAPABILITY_VERSION_3 0x20080522
+#define _LINUX_CAPABILITY_U32S_3 2
+
+typedef struct __user_cap_header_struct {
+ __u32 version;
+ int pid;
+} __user *cap_user_header_t;
+
+typedef struct __user_cap_data_struct {
+ __u32 effective;
+ __u32 permitted;
+ __u32 inheritable;
+} __user *cap_user_data_t;
+
+#define VFS_CAP_REVISION_MASK 0xFF000000
+#define VFS_CAP_REVISION_SHIFT 24
+#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
+#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
+#define VFS_CAP_REVISION_1 0x01000000
+#define VFS_CAP_U32_1 1
+#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+#define VFS_CAP_REVISION_2 0x02000000
+#define VFS_CAP_U32_2 2
+#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
+#define VFS_CAP_U32 VFS_CAP_U32_2
+#define VFS_CAP_REVISION VFS_CAP_REVISION_2
+
+struct vfs_cap_data {
+ __le32 magic_etc;
+ struct {
+ __le32 permitted;
+ __le32 inheritable;
+ } data[VFS_CAP_U32];
+};
+
+#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
+#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
+#define CAP_CHOWN 0
+#define CAP_DAC_OVERRIDE 1
+#define CAP_DAC_READ_SEARCH 2
+#define CAP_FOWNER 3
+#define CAP_FSETID 4
+#define CAP_KILL 5
+#define CAP_SETGID 6
+#define CAP_SETUID 7
+#define CAP_SETPCAP 8
+#define CAP_LINUX_IMMUTABLE 9
+#define CAP_NET_BIND_SERVICE 10
+#define CAP_NET_BROADCAST 11
+#define CAP_NET_ADMIN 12
+#define CAP_NET_RAW 13
+#define CAP_IPC_LOCK 14
+#define CAP_IPC_OWNER 15
+#define CAP_SYS_MODULE 16
+#define CAP_SYS_RAWIO 17
+#define CAP_SYS_CHROOT 18
+#define CAP_SYS_PTRACE 19
+#define CAP_SYS_PACCT 20
+#define CAP_SYS_ADMIN 21
+#define CAP_SYS_BOOT 22
+#define CAP_SYS_NICE 23
+#define CAP_SYS_RESOURCE 24
+#define CAP_SYS_TIME 25
+#define CAP_SYS_TTY_CONFIG 26
+#define CAP_MKNOD 27
+#define CAP_LEASE 28
+#define CAP_AUDIT_WRITE 29
+#define CAP_AUDIT_CONTROL 30
+#define CAP_SETFCAP 31
+#define CAP_MAC_OVERRIDE 32
+#define CAP_MAC_ADMIN 33
+#define CAP_SYSLOG 34
+#define CAP_WAKE_ALARM 35
+#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
+#define CAP_TO_INDEX(x) ((x) >> 5)
+#define CAP_TO_MASK(x) (1 << ((x) & 31))
+
+#undef __user
+#undef __u32
+#undef __le32
+
+#endif
View
286 include/private/android_filesystem_config.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (mkbootfs and mkyaffs2image) and
+** by the device side of adb.
+*/
+
+#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
+#define _ANDROID_FILESYSTEM_CONFIG_H_
+
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+#ifdef HAVE_ANDROID_OS
+#include <linux/capability.h>
+#else
+#include "android_filesystem_capability.h"
+#endif
+
+/* This is the master Users and Groups config for the platform.
+** DO NOT EVER RENUMBER.
+*/
+
+#define AID_ROOT 0 /* traditional unix root user */
+
+#define AID_SYSTEM 1000 /* system server */
+
+#define AID_RADIO 1001 /* telephony subsystem, RIL */
+#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
+#define AID_GRAPHICS 1003 /* graphics devices */
+#define AID_INPUT 1004 /* input devices */
+#define AID_AUDIO 1005 /* audio devices */
+#define AID_CAMERA 1006 /* camera devices */
+#define AID_LOG 1007 /* log devices */
+#define AID_COMPASS 1008 /* compass device */
+#define AID_MOUNT 1009 /* mountd socket */
+#define AID_WIFI 1010 /* wifi subsystem */
+#define AID_ADB 1011 /* android debug bridge (adbd) */
+#define AID_INSTALL 1012 /* group for installing packages */
+#define AID_MEDIA 1013 /* mediaserver process */
+#define AID_DHCP 1014 /* dhcp client */
+#define AID_SDCARD_RW 1015 /* external storage write access */
+#define AID_VPN 1016 /* vpn system */
+#define AID_KEYSTORE 1017 /* keystore subsystem */
+#define AID_USB 1018 /* USB devices */
+#define AID_DRM 1019 /* DRM server */
+#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */
+#define AID_GPS 1021 /* GPS daemon */
+#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
+#define AID_MEDIA_RW 1023 /* internal media storage write access */
+#define AID_MTP 1024 /* MTP USB driver access */
+#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */
+#define AID_DRMRPC 1026 /* group for drm rpc */
+#define AID_NFC 1027 /* nfc subsystem */
+#define AID_SDCARD_R 1028 /* external storage read access */
+#define AID_CLAT 1029 /* clat part of nat464 */
+#define AID_LOOP_RADIO 1030 /* loop radio devices */
+#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */
+
+#define AID_SHELL 2000 /* adb and debug shell user */
+#define AID_CACHE 2001 /* cache access */
+#define AID_DIAG 2002 /* access to diagnostic resources */
+
+/* The 3000 series are intended for use as supplemental group id's only.
+ * They indicate special Android capabilities that the kernel is aware of. */
+#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
+#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
+#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
+#define AID_NET_RAW 3004 /* can create raw INET sockets */
+#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
+#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
+#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
+#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */
+
+#define AID_MISC 9998 /* access to misc storage */
+#define AID_NOBODY 9999
+
+#define AID_APP 10000 /* first app user */
+
+#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
+
+#define AID_USER 100000 /* offset for uid ranges for each user */
+
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
+#define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */
+
+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
+struct android_id_info {
+ const char *name;
+ unsigned aid;
+};
+
+static const struct android_id_info android_ids[] = {
+ { "root", AID_ROOT, },
+ { "system", AID_SYSTEM, },
+ { "radio", AID_RADIO, },
+ { "bluetooth", AID_BLUETOOTH, },
+ { "graphics", AID_GRAPHICS, },
+ { "input", AID_INPUT, },
+ { "audio", AID_AUDIO, },
+ { "camera", AID_CAMERA, },
+ { "log", AID_LOG, },
+ { "compass", AID_COMPASS, },
+ { "mount", AID_MOUNT, },
+ { "wifi", AID_WIFI, },
+ { "dhcp", AID_DHCP, },
+ { "adb", AID_ADB, },
+ { "install", AID_INSTALL, },
+ { "media", AID_MEDIA, },
+ { "drm", AID_DRM, },
+ { "mdnsr", AID_MDNSR, },
+ { "nfc", AID_NFC, },
+ { "drmrpc", AID_DRMRPC, },
+ { "shell", AID_SHELL, },
+ { "cache", AID_CACHE, },
+ { "diag", AID_DIAG, },
+ { "net_bt_admin", AID_NET_BT_ADMIN, },
+ { "net_bt", AID_NET_BT, },
+ { "net_bt_stack", AID_NET_BT_STACK, },
+ { "sdcard_r", AID_SDCARD_R, },
+ { "sdcard_rw", AID_SDCARD_RW, },
+ { "media_rw", AID_MEDIA_RW, },
+ { "vpn", AID_VPN, },
+ { "keystore", AID_KEYSTORE, },
+ { "usb", AID_USB, },
+ { "mtp", AID_MTP, },
+ { "gps", AID_GPS, },
+ { "inet", AID_INET, },
+ { "net_raw", AID_NET_RAW, },
+ { "net_admin", AID_NET_ADMIN, },
+ { "net_bw_stats", AID_NET_BW_STATS, },
+ { "net_bw_acct", AID_NET_BW_ACCT, },
+ { "loop_radio", AID_LOOP_RADIO, },
+ { "misc", AID_MISC, },
+ { "nobody", AID_NOBODY, },
+ { "clat", AID_CLAT, },
+ { "mediadrm", AID_MEDIA_DRM, },
+};
+
+#define android_id_count \
+ (sizeof(android_ids) / sizeof(android_ids[0]))
+
+struct fs_path_config {
+ unsigned mode;
+ unsigned uid;
+ unsigned gid;
+ uint64_t capabilities;
+ const char *prefix;
+};
+
+/* Rules for directories.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root.
+*/
+
+static const struct fs_path_config android_dirs[] = {
+ { 00770, AID_SYSTEM, AID_CACHE, 0, "cache" },
+ { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
+ { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
+ { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/dalvik-cache" },
+ { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
+ { 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" },
+ { 00771, AID_SHELL, AID_SHELL, 0, "data/local" },
+ { 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" },
+ { 00770, AID_DHCP, AID_DHCP, 0, "data/misc/dhcp" },
+ { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
+ { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
+ { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "sbin" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/bin" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
+ { 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
+ { 00755, AID_ROOT, AID_ROOT, 0, 0 },
+};
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_files[] = {
+ { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" },
+ { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" },
+ { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.trout.rc" },
+ { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" },
+ { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.testmenu" },
+ { 00550, AID_DHCP, AID_SHELL, 0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
+ { 00444, AID_RADIO, AID_AUDIO, 0, "system/etc/AudioPara4.csv" },
+ { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
+ { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
+ { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" },
+ { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
+ { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
+ { 00644, AID_APP, AID_APP, 0, "data/data/*" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "system/bin/ping" },
+
+ /* the following file is INTENTIONALLY set-gid and not set-uid.
+ * Do not change. */
+ { 02750, AID_ROOT, AID_INET, 0, "system/bin/netcfg" },
+
+ /* the following five files are INTENTIONALLY set-uid, but they
+ * are NOT included on user builds. */
+ { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/su" },
+ { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" },
+ { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" },
+ { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" },
+ { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/tcpdump" },
+ { 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" },
+
+ /* the following file has enhanced capabilities and IS included in user builds. */
+ { 00750, AID_ROOT, AID_SHELL, (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" },
+
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "sbin/*" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "init*" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "charger*" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" },
+ { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
+ { 00644, AID_ROOT, AID_ROOT, 0, 0 },
+};
+
+static inline void fs_config(const char *path, int dir,
+ unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
+{
+ const struct fs_path_config *pc;
+ int plen;
+
+ if (path[0] == '/') {
+ path++;
+ }
+
+ pc = dir ? android_dirs : android_files;
+ plen = strlen(path);
+ for(; pc->prefix; pc++){
+ int len = strlen(pc->prefix);
+ if (dir) {
+ if(plen < len) continue;
+ if(!strncmp(pc->prefix, path, len)) break;
+ continue;
+ }
+ /* If name ends in * then allow partial matches. */
+ if (pc->prefix[len -1] == '*') {
+ if(!strncmp(pc->prefix, path, len - 1)) break;
+ } else if (plen == len){
+ if(!strncmp(pc->prefix, path, len)) break;
+ }
+ }
+ *uid = pc->uid;
+ *gid = pc->gid;
+ *mode = (*mode & (~07777)) | pc->mode;
+ *capabilities = pc->capabilities;
+
+#if 0
+ fprintf(stderr,"< '%s' '%s' %d %d %o >\n",
+ path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode);
+#endif
+}
+#endif
+#endif
View
23 libmincrypt/NOTICE
@@ -0,0 +1,23 @@
+ Copyright 2008, The Android Open Source Project
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Google Inc. nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
308 libmincrypt/rsa.c
@@ -0,0 +1,308 @@
+/* rsa.c
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
+
+// a[] -= mod
+static void subM(const RSAPublicKey* key,
+ uint32_t* a) {
+ int64_t A = 0;
+ int i;
+ for (i = 0; i < key->len; ++i) {
+ A += (uint64_t)a[i] - key->n[i];
+ a[i] = (uint32_t)A;
+ A >>= 32;
+ }
+}
+
+// return a[] >= mod
+static int geM(const RSAPublicKey* key,
+ const uint32_t* a) {
+ int i;
+ for (i = key->len; i;) {
+ --i;
+ if (a[i] < key->n[i]) return 0;
+ if (a[i] > key->n[i]) return 1;
+ }
+ return 1; // equal
+}
+
+// montgomery c[] += a * b[] / R % mod
+static void montMulAdd(const RSAPublicKey* key,
+ uint32_t* c,
+ const uint32_t a,
+ const uint32_t* b) {
+ uint64_t A = (uint64_t)a * b[0] + c[0];
+ uint32_t d0 = (uint32_t)A * key->n0inv;
+ uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+ int i;
+
+ for (i = 1; i < key->len; ++i) {
+ A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+ B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+ c[i - 1] = (uint32_t)B;
+ }
+
+ A = (A >> 32) + (B >> 32);
+
+ c[i - 1] = (uint32_t)A;
+
+ if (A >> 32) {
+ subM(key, c);
+ }
+}
+
+// montgomery c[] = a[] * b[] / R % mod
+static void montMul(const RSAPublicKey* key,
+ uint32_t* c,
+ const uint32_t* a,
+ const uint32_t* b) {
+ int i;
+ for (i = 0; i < key->len; ++i) {
+ c[i] = 0;
+ }
+ for (i = 0; i < key->len; ++i) {
+ montMulAdd(key, c, a[i], b);
+ }
+}
+
+// In-place public exponentiation.
+// Input and output big-endian byte array in inout.
+static void modpow(const RSAPublicKey* key,
+ uint8_t* inout) {
+ uint32_t a[RSANUMWORDS];
+ uint32_t aR[RSANUMWORDS];
+ uint32_t aaR[RSANUMWORDS];
+ uint32_t* aaa = 0;
+ int i;
+
+ // Convert from big endian byte array to little endian word array.
+ for (i = 0; i < key->len; ++i) {
+ uint32_t tmp =
+ (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+ (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+ (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+ (inout[((key->len - 1 - i) * 4) + 3] << 0);
+ a[i] = tmp;
+ }
+
+ if (key->exponent == 65537) {
+ aaa = aaR; // Re-use location.
+ montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
+ for (i = 0; i < 16; i += 2) {
+ montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
+ montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
+ }
+ montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
+ } else if (key->exponent == 3) {
+ aaa = aR; // Re-use location.
+ montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
+ montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
+ montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
+ }
+
+ // Make sure aaa < mod; aaa is at most 1x mod too large.
+ if (geM(key, aaa)) {
+ subM(key, aaa);
+ }
+
+ // Convert to bigendian byte array
+ for (i = key->len - 1; i >= 0; --i) {
+ uint32_t tmp = aaa[i];
+ *inout++ = tmp >> 24;
+ *inout++ = tmp >> 16;
+ *inout++ = tmp >> 8;
+ *inout++ = tmp >> 0;
+ }
+}
+
+// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
+// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
+// other flavor which omits the optional parameter entirely). This code does not
+// accept signatures without the optional parameter.
+
+/*
+static const uint8_t sha_padding[RSANUMBYTES] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+ 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00, 0x04, 0x14,
+
+ // 20 bytes of hash go here.
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+*/
+
+// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
+ 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
+ 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
+ 0x7c, 0xfb, 0xf1, 0x67
+};
+
+/*
+static const uint8_t sha256_padding[RSANUMBYTES] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
+ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
+
+ // 32 bytes of hash go here.
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+*/
+
+// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
+ 0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
+ 0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
+ 0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
+ 0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
+};
+
+// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
+// Both e=3 and e=65537 are supported. hash_len may be
+// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
+// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
+// values are supported.
+//
+// Returns 1 on successful verification, 0 on failure.
+int RSA_verify(const RSAPublicKey *key,
+ const uint8_t *signature,
+ const int len,
+ const uint8_t *hash,
+ const int hash_len) {
+ uint8_t buf[RSANUMBYTES];
+ int i;
+ const uint8_t* padding_hash;
+
+ if (key->len != RSANUMWORDS) {
+ return 0; // Wrong key passed in.
+ }
+
+ if (len != sizeof(buf)) {
+ return 0; // Wrong input length.
+ }
+
+ if (hash_len != SHA_DIGEST_SIZE &&
+ hash_len != SHA256_DIGEST_SIZE) {
+ return 0; // Unsupported hash.
+ }
+
+ if (key->exponent != 3 && key->exponent != 65537) {
+ return 0; // Unsupported exponent.
+ }
+
+ for (i = 0; i < len; ++i) { // Copy input to local workspace.
+ buf[i] = signature[i];
+ }
+
+ modpow(key, buf); // In-place exponentiation.
+
+ // Xor sha portion, so it all becomes 00 iff equal.
+ for (i = len - hash_len; i < len; ++i) {
+ buf[i] ^= *hash++;
+ }
+
+ // Hash resulting buf, in-place.
+ switch (hash_len) {
+ case SHA_DIGEST_SIZE:
+ padding_hash = kExpectedPadShaRsa2048;
+ SHA_hash(buf, len, buf);
+ break;
+ case SHA256_DIGEST_SIZE:
+ padding_hash = kExpectedPadSha256Rsa2048;
+ SHA256_hash(buf, len, buf);
+ break;
+ default:
+ return 0;
+ }
+
+ // Compare against expected hash value.
+ for (i = 0; i < hash_len; ++i) {
+ if (buf[i] != padding_hash[i]) {
+ return 0;
+ }
+ }
+
+ return 1; // All checked out OK.
+}
View
155 libmincrypt/sha.c
@@ -0,0 +1,155 @@
+/* sha.c
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Optimized for minimal code size.
+
+#include "mincrypt/sha.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static void SHA1_Transform(SHA_CTX* ctx) {
+ uint32_t W[80];
+ uint32_t A, B, C, D, E;
+ uint8_t* p = ctx->buf;
+ int t;
+
+ for(t = 0; t < 16; ++t) {
+ uint32_t tmp = *p++ << 24;
+ tmp |= *p++ << 16;
+ tmp |= *p++ << 8;
+ tmp |= *p++;
+ W[t] = tmp;
+ }
+
+ for(; t < 80; t++) {
+ W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+ for(t = 0; t < 80; t++) {
+ uint32_t tmp = rol(5,A) + E + W[t];
+
+ if (t < 20)
+ tmp += (D^(B&(C^D))) + 0x5A827999;
+ else if ( t < 40)
+ tmp += (B^C^D) + 0x6ED9EBA1;
+ else if ( t < 60)
+ tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
+ else
+ tmp += (B^C^D) + 0xCA62C1D6;
+
+ E = D;
+ D = C;
+ C = rol(30,B);
+ B = A;
+ A = tmp;
+ }
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+static const HASH_VTAB SHA_VTAB = {
+ SHA_init,
+ SHA_update,
+ SHA_final,
+ SHA_hash,
+ SHA_DIGEST_SIZE
+};
+
+void SHA_init(SHA_CTX* ctx) {
+ ctx->f = &SHA_VTAB;
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+ ctx->count = 0;
+}
+
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+ int i = (int) (ctx->count & 63);
+ const uint8_t* p = (const uint8_t*)data;
+
+ ctx->count += len;
+
+ while (len--) {
+ ctx->buf[i++] = *p++;
+ if (i == 64) {
+ SHA1_Transform(ctx);
+ i = 0;
+ }
+ }
+}
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
+ uint8_t *p = ctx->buf;
+ uint64_t cnt = ctx->count * 8;
+ int i;
+
+ SHA_update(ctx, (uint8_t*)"\x80", 1);
+ while ((ctx->count & 63) != 56) {
+ SHA_update(ctx, (uint8_t*)"\0", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
+ SHA_update(ctx, &tmp, 1);
+ }
+
+ for (i = 0; i < 5; i++) {
+ uint32_t tmp = ctx->state[i];
+ *p++ = tmp >> 24;
+ *p++ = tmp >> 16;
+ *p++ = tmp >> 8;
+ *p++ = tmp >> 0;
+ }
+
+ return ctx->buf;
+}
+
+/* Convenience function */
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
+ SHA_CTX ctx;
+ SHA_init(&ctx);
+ SHA_update(&ctx, data, len);
+ memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
+ return digest;
+}
View
184 libmincrypt/sha256.c
@@ -0,0 +1,184 @@
+/* sha256.c
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Optimized for minimal code size.
+
+#include "mincrypt/sha256.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+#define shr(value, bits) ((value) >> (bits))
+
+static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
+
+static void SHA256_Transform(SHA256_CTX* ctx) {
+ uint32_t W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+ uint8_t* p = ctx->buf;
+ int t;
+
+ for(t = 0; t < 16; ++t) {
+ uint32_t tmp = *p++ << 24;
+ tmp |= *p++ << 16;
+ tmp |= *p++ << 8;
+ tmp |= *p++;
+ W[t] = tmp;
+ }
+
+ for(; t < 64; t++) {
+ uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
+ uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
+ W[t] = W[t-16] + s0 + W[t-7] + s1;
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ for(t = 0; t < 64; t++) {
+ uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
+ uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
+ uint32_t t2 = s0 + maj;
+ uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
+ uint32_t ch = (E & F) ^ ((~E) & G);
+ uint32_t t1 = H + s1 + ch + K[t] + W[t];
+
+ H = G;
+ G = F;
+ F = E;
+ E = D + t1;
+ D = C;
+ C = B;
+ B = A;
+ A = t1 + t2;
+ }
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+static const HASH_VTAB SHA256_VTAB = {
+ SHA256_init,
+ SHA256_update,
+ SHA256_final,
+ SHA256_hash,
+ SHA256_DIGEST_SIZE
+};
+
+void SHA256_init(SHA256_CTX* ctx) {
+ ctx->f = &SHA256_VTAB;
+ ctx->state[0] = 0x6a09e667;
+ ctx->state[1] = 0xbb67ae85;
+ ctx->state[2] = 0x3c6ef372;
+ ctx->state[3] = 0xa54ff53a;
+ ctx->state[4] = 0x510e527f;
+ ctx->state[5] = 0x9b05688c;
+ ctx->state[6] = 0x1f83d9ab;
+ ctx->state[7] = 0x5be0cd19;
+ ctx->count = 0;
+}
+
+
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
+ int i = (int) (ctx->count & 63);
+ const uint8_t* p = (const uint8_t*)data;
+
+ ctx->count += len;
+
+ while (len--) {
+ ctx->buf[i++] = *p++;
+ if (i == 64) {
+ SHA256_Transform(ctx);
+ i = 0;
+ }
+ }
+}
+
+
+const uint8_t* SHA256_final(SHA256_CTX* ctx) {
+ uint8_t *p = ctx->buf;
+ uint64_t cnt = ctx->count * 8;
+ int i;
+
+ SHA256_update(ctx, (uint8_t*)"\x80", 1);
+ while ((ctx->count & 63) != 56) {
+ SHA256_update(ctx, (uint8_t*)"\0", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
+ SHA256_update(ctx, &tmp, 1);
+ }
+
+ for (i = 0; i < 8; i++) {
+ uint32_t tmp = ctx->state[i];
+ *p++ = tmp >> 24;
+ *p++ = tmp >> 16;
+ *p++ = tmp >> 8;
+ *p++ = tmp >> 0;
+ }
+
+ return ctx->buf;
+}
+
+/* Convenience function */
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
+ SHA256_CTX ctx;
+ SHA256_init(&ctx);
+ SHA256_update(&ctx, data, len);
+ memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
+ return digest;
+}
View
102 mkbootimg/bootimg.h
@@ -0,0 +1,102 @@
+/* tools/mkbootimg/bootimg.h
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef _BOOT_IMAGE_H_
+#define _BOOT_IMAGE_H_
+
+typedef struct boot_img_hdr boot_img_hdr;
+
+#define BOOT_MAGIC "ANDROID!"
+#define BOOT_MAGIC_SIZE 8
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+#define BOOT_EXTRA_ARGS_SIZE 1024
+
+struct boot_img_hdr
+{
+ unsigned char magic[BOOT_MAGIC_SIZE];
+
+ unsigned kernel_size; /* size in bytes */
+ unsigned kernel_addr; /* physical load addr */
+
+ unsigned ramdisk_size; /* size in bytes */
+ unsigned ramdisk_addr; /* physical load addr */
+
+ unsigned second_size; /* size in bytes */
+ unsigned second_addr; /* physical load addr */
+
+ unsigned tags_addr; /* physical addr for kernel tags */
+ unsigned page_size; /* flash page size we assume */
+ unsigned unused[2]; /* future expansion: should be 0 */
+
+ unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
+
+ unsigned char cmdline[BOOT_ARGS_SIZE];
+
+ unsigned id[8]; /* timestamp / checksum / sha1 / etc */
+
+ /* Supplemental command line data; kept here to maintain
+ * binary compatibility with older versions of mkbootimg */
+ unsigned char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
+};
+
+/*
+** +-----------------+
+** | boot header | 1 page
+** +-----------------+
+** | kernel | n pages
+** +-----------------+
+** | ramdisk | m pages
+** +-----------------+
+** | second stage | o pages
+** +-----------------+
+**
+** n = (kernel_size + page_size - 1) / page_size
+** m = (ramdisk_size + page_size - 1) / page_size
+** o = (second_size + page_size - 1) / page_size
+**
+** 0. all entities are page_size aligned in flash
+** 1. kernel and ramdisk are required (size != 0)
+** 2. second is optional (second_size == 0 -> no second)
+** 3. load each element (kernel, ramdisk, second) at
+** the specified physical address (kernel_addr, etc)
+** 4. prepare tags at tag_addr. kernel_args[] is
+** appended to the kernel commandline in the tags.
+** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+** 6. if second_size != 0: jump to second_addr
+** else: jump to kernel_addr
+*/
+
+#if 0
+typedef struct ptentry ptentry;
+
+struct ptentry {
+ char name[16]; /* asciiz partition name */
+ unsigned start; /* starting block number */
+ unsigned length; /* length in blocks */
+ unsigned flags; /* set to zero */
+};
+
+/* MSM Partition Table ATAG
+**
+** length: 2 + 7 * n
+** atag: 0x4d534d70
+** <ptentry> x n
+*/
+#endif
+
+#endif
View
277 mkbootimg/mkbootimg.c
@@ -0,0 +1,277 @@
+/* tools/mkbootimg/mkbootimg.c
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "mincrypt/sha.h"
+#include "bootimg.h"
+
+static void *load_file(const char *fn, unsigned *_sz)
+{
+ char *data;
+ int sz;
+ int fd;
+
+ data = 0;
+ fd = open(fn, O_RDONLY);
+ if(fd < 0) return 0;
+
+ sz = lseek(fd, 0, SEEK_END);
+ if(sz < 0) goto oops;
+
+ if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
+
+ data = (char*) malloc(sz);
+ if(data == 0) goto oops;
+
+ if(read(fd, data, sz) != sz) goto oops;
+ close(fd);
+
+ if(_sz) *_sz = sz;
+ return data;
+
+oops:
+ close(fd);
+ if(data != 0) free(data);
+ return 0;
+}
+
+int usage(void)
+{
+ fprintf(stderr,"usage: mkbootimg\n"
+ " --kernel <filename>\n"
+ " --ramdisk <filename>\n"
+ " [ --second <2ndbootloader-filename> ]\n"
+ " [ --cmdline <kernel-commandline> ]\n"
+ " [ --board <boardname> ]\n"
+ " [ --base <address> ]\n"
+ " [ --pagesize <pagesize> ]\n"
+ " -o|--output <filename>\n"
+ );
+ return 1;
+}
+
+
+
+static unsigned char padding[16384] = { 0, };
+
+int write_padding(int fd, unsigned pagesize, unsigned itemsize)
+{
+ unsigned pagemask = pagesize - 1;
+ unsigned count;
+
+ if((itemsize & pagemask) == 0) {
+ return 0;
+ }
+
+ count = pagesize - (itemsize & pagemask);
+
+ if(write(fd, padding, count) != count) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ boot_img_hdr hdr;
+
+ char *kernel_fn = 0;
+ void *kernel_data = 0;
+ char *ramdisk_fn = 0;
+ void *ramdisk_data = 0;
+ char *second_fn = 0;
+ void *second_data = 0;
+ char *cmdline = "";
+ char *bootimg = 0;
+ char *board = "";
+ unsigned pagesize = 2048;
+ int fd;
+ SHA_CTX ctx;
+ uint8_t* sha;
+ unsigned base = 0x10000000;
+ unsigned kernel_offset = 0x00008000;
+ unsigned ramdisk_offset = 0x01000000;
+ unsigned second_offset = 0x00f00000;
+ unsigned tags_offset = 0x00000100;
+ size_t cmdlen;
+
+ argc--;
+ argv++;
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ while(argc > 0){
+ char *arg = argv[0];
+ char *val = argv[1];
+ if(argc < 2) {
+ return usage();
+ }
+ argc -= 2;
+ argv += 2;
+ if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
+ bootimg = val;
+ } else if(!strcmp(arg, "--kernel")) {
+ kernel_fn = val;
+ } else if(!strcmp(arg, "--ramdisk")) {
+ ramdisk_fn = val;
+ } else if(!strcmp(arg, "--second")) {
+ second_fn = val;
+ } else if(!strcmp(arg, "--cmdline")) {
+ cmdline = val;
+ } else if(!strcmp(arg, "--base")) {
+ base = strtoul(val, 0, 16);
+ } else if(!strcmp(arg, "--kernel_offset")) {
+ kernel_offset = strtoul(val, 0, 16);
+ } else if(!strcmp(arg, "--ramdisk_offset")) {
+ ramdisk_offset = strtoul(val, 0, 16);
+ } else if(!strcmp(arg, "--second_offset")) {
+ second_offset = strtoul(val, 0, 16);
+ } else if(!strcmp(arg, "--tags_offset")) {
+ tags_offset = strtoul(val, 0, 16);
+ } else if(!strcmp(arg, "--board")) {
+ board = val;
+ } else if(!strcmp(arg,"--pagesize")) {
+ pagesize = strtoul(val, 0, 10);
+ if ((pagesize != 2048) && (pagesize != 4096)
+ && (pagesize != 8192) && (pagesize != 16384)) {
+ fprintf(stderr,"error: unsupported page size %d\n", pagesize);
+ return -1;
+ }
+ } else {
+ return usage();
+ }
+ }
+ hdr.page_size = pagesize;
+
+ hdr.kernel_addr = base + kernel_offset;
+ hdr.ramdisk_addr = base + ramdisk_offset;
+ hdr.second_addr = base + second_offset;
+ hdr.tags_addr = base + tags_offset;
+
+ if(bootimg == 0) {
+ fprintf(stderr,"error: no output filename specified\n");
+ return usage();
+ }
+
+ if(kernel_fn == 0) {
+ fprintf(stderr,"error: no kernel image specified\n");
+ return usage();
+ }
+
+ if(ramdisk_fn == 0) {
+ fprintf(stderr,"error: no ramdisk image specified\n");
+ return usage();
+ }
+
+ if(strlen(board) >= BOOT_NAME_SIZE) {
+ fprintf(stderr,"error: board name too large\n");
+ return usage();
+ }
+
+ strcpy(hdr.name, board);
+
+ memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
+
+ cmdlen = strlen(cmdline);
+ if(cmdlen > (BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE - 2)) {
+ fprintf(stderr,"error: kernel commandline too large\n");
+ return 1;
+ }
+ /* Even if we need to use the supplemental field, ensure we
+ * are still NULL-terminated */
+ strncpy((char *)hdr.cmdline, cmdline, BOOT_ARGS_SIZE - 1);
+ hdr.cmdline[BOOT_ARGS_SIZE - 1] = '\0';
+ if (cmdlen >= (BOOT_ARGS_SIZE - 1)) {
+ cmdline += (BOOT_ARGS_SIZE - 1);
+ strncpy((char *)hdr.extra_cmdline, cmdline, BOOT_EXTRA_ARGS_SIZE);
+ }
+
+ kernel_data = load_file(kernel_fn, &hdr.kernel_size);
+ if(kernel_data == 0) {
+ fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
+ return 1;
+ }
+
+ if(!strcmp(ramdisk_fn,"NONE")) {
+ ramdisk_data = 0;
+ hdr.ramdisk_size = 0;
+ } else {
+ ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
+ if(ramdisk_data == 0) {
+ fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
+ return 1;
+ }
+ }
+
+ if(second_fn) {
+ second_data = load_file(second_fn, &hdr.second_size);
+ if(second_data == 0) {
+ fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
+ return 1;
+ }
+ }
+
+ /* put a hash of the contents in the header so boot images can be
+ * differentiated based on their first 2k.
+ */
+ SHA_init(&ctx);
+ SHA_update(&ctx, kernel_data, hdr.kernel_size);
+ SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
+ SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
+ SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
+ SHA_update(&ctx, second_data, hdr.second_size);
+ SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
+ sha = SHA_final(&ctx);
+ memcpy(hdr.id, sha,
+ SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
+
+ fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if(fd < 0) {
+ fprintf(stderr,"error: could not create '%s'\n", bootimg);
+ return 1;
+ }
+
+ if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
+ if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
+
+ if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
+ if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
+
+ if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
+ if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
+
+ if(second_data) {
+ if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
+ if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
+ }
+
+ return 0;
+
+fail:
+ unlink(bootimg);
+ close(fd);
+ fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
+ strerror(errno));
+ return 1;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.