diff options
Diffstat (limited to 'fastbootd/other')
-rw-r--r-- | fastbootd/other/gptedit.c | 303 | ||||
-rw-r--r-- | fastbootd/other/partitions.sample.cfg | 60 | ||||
-rw-r--r-- | fastbootd/other/sign/src/SignImg.java | 181 | ||||
-rw-r--r-- | fastbootd/other/vendor_trigger.c | 96 |
4 files changed, 640 insertions, 0 deletions
diff --git a/fastbootd/other/gptedit.c b/fastbootd/other/gptedit.c new file mode 100644 index 0000000..d423529 --- /dev/null +++ b/fastbootd/other/gptedit.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2009-2013, Google Inc. + * All rights reserved. + * + * 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 THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + */ + +#include <getopt.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <cutils/klog.h> + +#include "commands/partitions.h" +#include "debug.h" + +unsigned int debug_level = DEBUG; +//TODO: add tool to generate config file + +void usage() { + fprintf(stderr, + "usage: test_gpt [ <option> ] <file>\n" + "\n" + "options:\n" + " -p print partitions\n" + " -c print config file\n" + " -a adds new partition\n" + " -d deletes partition (-o needed)\n" + "\n" + " -n name@startlba,endlba new partition detail\n" + " -o old partition name\n" + " -t type guid\n" + " -g partition guid\n" + " -l gpt_location specyfies gpt secto\n" + ); + +} + +void printGPT(struct GPT_entry_table *table); +void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid); +void deleteGPT(struct GPT_entry_table *table, const char *name); +void configPrintGPT(struct GPT_entry_table *table); + +int main(int argc, char *argv[]) { + int print_cmd = 0; + int config_cmd = 0; + int add_cmd = 0; + int del_cmd = 0; + int sync_cmd = 0; + int c; + const char *new_partition = NULL; + const char *old_partition = NULL; + const char *type_guid = NULL; + const char *partition_guid = NULL; + unsigned gpt_location = 1; + + klog_init(); + klog_set_level(6); + + const struct option longopts[] = { + {"print", no_argument, 0, 'p'}, + {"config-print", no_argument, 0, 'c'}, + {"add", no_argument, 0, 'a'}, + {"del", no_argument, 0, 'd'}, + {"new", required_argument, 0, 'n'}, + {"old", required_argument, 0, 'o'}, + {"type", required_argument, 0, 't'}, + {"sync", required_argument, 0, 's'}, + {"guid", required_argument, 0, 'g'}, + {"location", required_argument, 0, 'l'}, + {0, 0, 0, 0} + }; + + while (1) { + c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL); + /* Alphabetical cases */ + if (c < 0) + break; + switch (c) { + case 'p': + print_cmd = 1; + break; + case 'c': + config_cmd = 1; + break; + case 'a': + add_cmd = 1; + break; + case 'd': + del_cmd = 1; + break; + case 'n': + new_partition = optarg; + break; + case 'o': + old_partition = optarg; + break; + case 't': + type_guid = optarg; + case 'g': + partition_guid = optarg; + break; + case 's': + sync_cmd = 1; + break; + case 'l': + gpt_location = strtoul(optarg, NULL, 10); + fprintf(stderr, "Got offset as %d", gpt_location); + break; + case '?': + return 1; + default: + abort(); + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + usage(); + return 1; + } + + const char *path = argv[0]; + struct GPT_entry_table *table = GPT_get_device(path, gpt_location); + if (table == NULL) { + fprintf(stderr, "unable to get GPT table from %s\n", path); + return 1; + } + + if (add_cmd) + addGPT(table, new_partition, partition_guid, type_guid); + if (del_cmd) + deleteGPT(table, old_partition); + if (print_cmd) + printGPT(table); + if (config_cmd) + configPrintGPT(table); + if (sync_cmd) + GPT_sync(table); + + GPT_release_device(table); + + return 0; +} + +void printGPT(struct GPT_entry_table *table) { + struct GPT_entry_raw *entry = table->entries; + unsigned n, m; + char name[GPT_NAMELEN + 1]; + + printf("ptn start block end block name\n"); + printf("---- ------------- -------------\n"); + + for (n = 0; n < table->header->entries_count; n++, entry++) { + if (entry->type_guid[0] == 0) + continue; + for (m = 0; m < GPT_NAMELEN; m++) { + name[m] = entry->name[m] & 127; + } + name[m] = 0; + printf("#%03d %13"PRId64" %13"PRId64" %s\n", + n + 1, entry->first_lba, entry->last_lba, name); + } +} + +void configPrintGPT(struct GPT_entry_table *table) { + struct GPT_entry_raw *entry = table->entries; + unsigned n, m; + char name[GPT_NAMELEN + 1]; + char temp_guid[17]; + temp_guid[16] = 0; + + printf("header_lba %"PRId64"\n", table->header->current_lba); + printf("backup_lba %"PRId64"\n", table->header->backup_lba); + printf("first_lba %"PRId64"\n", table->header->first_usable_lba); + printf("last_lba %"PRId64"\n", table->header->last_usable_lba); + printf("entries_lba %"PRId64"\n", table->header->entries_lba); + snprintf(temp_guid, 17, "%s", table->header->disk_guid); + printf("guid \"%s\"", temp_guid); + + printf("\npartitions {\n"); + + for (n = 0; n < table->header->entries_count; n++, entry++) { + uint64_t size = entry->last_lba - entry->first_lba + 1; + + if (entry->type_guid[0] == 0) + continue; + for (m = 0; m < GPT_NAMELEN; m++) { + name[m] = entry->name[m] & 127; + } + name[m] = 0; + + printf(" %s {\n", name); + snprintf(temp_guid, 17, "%s", entry->partition_guid); + printf(" guid \"%s\"\n", temp_guid); + printf(" first_lba %"PRId64"\n", entry->first_lba); + printf(" partition_size %"PRId64"\n", size); + if (entry->flags & GPT_FLAG_SYSTEM) + printf(" system\n"); + if (entry->flags & GPT_FLAG_BOOTABLE) + printf(" bootable\n"); + if (entry->flags & GPT_FLAG_READONLY) + printf(" readonly\n"); + if (entry->flags & GPT_FLAG_DOAUTOMOUNT) + printf(" automount\n"); + printf(" }\n\n"); + } + printf("}\n"); +} + +void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) { + char *c, *c2; + char *arg = malloc(strlen(str)); + char *name = arg; + unsigned start, end; + strcpy(arg, str); + if (guid == NULL || tguid == NULL) { + fprintf(stderr, "Type guid and partion guid needed"); + free(arg); + return; + } + + c = strchr(arg, '@'); + + if (c == NULL) { + fprintf(stderr, "Wrong entry format"); + free(arg); + return; + } + + *c++ = '\0'; + + c2 = strchr(c, ','); + + if (c2 == NULL) { + fprintf(stderr, "Wrong entry format"); + free(arg); + return; + } + + start = strtoul(c, NULL, 10); + *c2++ = '\0'; + end = strtoul(c2, NULL, 10); + + struct GPT_entry_raw data; + strncpy((char *)data.partition_guid, guid, 15); + data.partition_guid[15] = '\0'; + strncpy((char *)data.type_guid, tguid, 15); + data.type_guid[15] = '\0'; + GPT_to_UTF16(data.name, name, GPT_NAMELEN); + data.first_lba = start; + data.last_lba = end; + + fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid); + GPT_add_entry(table, &data); + free(arg); +} + +void deleteGPT(struct GPT_entry_table *table, const char *name) { + struct GPT_entry_raw *entry; + + if (name == NULL) { + fprintf(stderr, "Need partition name"); + return; + } + + entry = GPT_get_pointer_by_name(table, name); + + if (!entry) { + fprintf(stderr, "Unable to find partition: %s", name); + return; + } + GPT_delete_entry(table, entry); +} + diff --git a/fastbootd/other/partitions.sample.cfg b/fastbootd/other/partitions.sample.cfg new file mode 100644 index 0000000..49562cf --- /dev/null +++ b/fastbootd/other/partitions.sample.cfg @@ -0,0 +1,60 @@ + +header_lba 1 +backup_lba 101 +first_lba 43 +last_lba 100 +entries_lba 2 + +partitions { + #You can generate this as output from gptedit -c + SOS { + first_lba 28672 + partition_size 16384 + } + + DTB { + first_lba 45056 + partition_size 8192 + } + + LNX { + first_lba 53248 + partition_size 16384 + } + + APP { + first_lba 69632 + partition_size 1048576 + } + + CAC { + first_lba 1118208 + partition_size 1572864 + } + + MSC { + first_lba 2691072 + partition_size 4096 + } + + USP { + first_lba 2695168 + partition_size 65536 + } + + MDA { + first_lba 2760704 + partition_size 4096 + } + + FCT { + first_lba 2764800 + partition_size 32768 + } + + UDA { + first_lba 2797568 + partition_size 27975680 + } +} + diff --git a/fastbootd/other/sign/src/SignImg.java b/fastbootd/other/sign/src/SignImg.java new file mode 100644 index 0000000..338d427 --- /dev/null +++ b/fastbootd/other/sign/src/SignImg.java @@ -0,0 +1,181 @@ +package signtool; + +import java.io.*; +import java.util.Properties; +import java.util.ArrayList; + +import javax.mail.internet.*; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.activation.MailcapCommandMap; +import javax.activation.CommandMap; + +import java.security.PrivateKey; +import java.security.Security; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.cert.X509Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedGenerator; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.bouncycastle.cms.CMSSignedGenerator; +import org.bouncycastle.cms.CMSProcessable; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSTypedData; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.util.Store; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.ASN1Object; + + +public class SignImg { + + /* It reads private key in pkcs#8 formate + * Conversion: + * openssl pkcs8 -topk8 -nocrypt -outform DER < inkey.pem > outkey.pk8 + */ + private static PrivateKey getPrivateKey(String path) throws IOException, FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException { + File file = new File(path); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int)file.length()]; + fis.read(data); + fis.close(); + + PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(data); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = kf.generatePrivate(kspec); + + return privateKey; + } + + private static MimeBodyPart getContent(String path) throws IOException, FileNotFoundException, MessagingException { + MimeBodyPart body = new MimeBodyPart(); + + File file = new File(path); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int)file.length()]; + fis.read(data); + fis.close(); + + body.setContent(data, "application/octet-stream"); + + return body; + } + + private static CMSProcessableByteArray getCMSContent(String path) throws IOException, FileNotFoundException, MessagingException { + File file = new File(path); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int)file.length()]; + fis.read(data); + fis.close(); + CMSProcessableByteArray cms = new CMSProcessableByteArray(data); + + return cms; + } + + private static X509Certificate readCert(String path) throws IOException, FileNotFoundException, CertificateException { + File file = new File(path); + FileInputStream is = new FileInputStream(file); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate cert = cf.generateCertificate(is); + is.close(); + + return (X509Certificate) cert; + } + + private static void save(MimeBodyPart content, String path) throws IOException, FileNotFoundException, MessagingException { + File file = new File(path); + FileOutputStream os = new FileOutputStream(file); + + content.writeTo(os); + + os.close(); + } + + private static Store certToStore(X509Certificate certificate) throws CertificateEncodingException { + ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); + certList.add(certificate); + return new JcaCertStore(certList); + } + + public static void setDefaultMailcap() + { + MailcapCommandMap _mailcap = + (MailcapCommandMap)CommandMap.getDefaultCommandMap(); + + _mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature"); + _mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime"); + _mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature"); + _mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime"); + _mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed"); + + CommandMap.setDefaultCommandMap(_mailcap); + } + + public static void main(String[] args) { + try { + if (args.length < 4) { + System.out.println("Usage: signimg data private_key certificate output"); + return; + } + System.out.println("Signing the image"); + setDefaultMailcap(); + + Security.addProvider(new BouncyCastleProvider()); + + PrivateKey key = getPrivateKey(args[1]); + System.out.println("File read sucessfully"); + + CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); + + CMSTypedData body = getCMSContent(args[0]); + System.out.println("Content read sucessfully"); + + X509Certificate cert = (X509Certificate) readCert(args[2]); + System.out.println("Certificate read sucessfully"); + + ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(key); + + Store certs = certToStore(cert); + + generator.addCertificates(certs); + generator.addSignerInfoGenerator( + new JcaSignerInfoGeneratorBuilder( + new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()) + .build(sha256Signer, cert)); + + CMSSignedData signed = generator.generate(body, true); + System.out.println("Signed"); + + Properties props = System.getProperties(); + Session session = Session.getDefaultInstance(props, null); + + File file = new File(args[3]); + FileOutputStream os = new FileOutputStream(file); + + ASN1InputStream asn1 = new ASN1InputStream(signed.getEncoded()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DEROutputStream dOut = new DEROutputStream(os); + dOut.writeObject(ASN1Object.fromByteArray(signed.getEncoded())); + + } + catch (Exception ex) { + System.out.println("Exception during programm execution: " + ex.getMessage()); + } + } +} diff --git a/fastbootd/other/vendor_trigger.c b/fastbootd/other/vendor_trigger.c new file mode 100644 index 0000000..101959b --- /dev/null +++ b/fastbootd/other/vendor_trigger.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009-2013, Google Inc. + * All rights reserved. + * + * 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 THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + */ + +#include <stdlib.h> + +#include "vendor_trigger.h" +#include "debug.h" + +unsigned int debug_level = DEBUG; + +static const int version = 1; + +int check_version(const int fastboot_version, int *libversion) { + *libversion = version; + return !(fastboot_version == version); +} + +int gpt_layout(struct GPT_content *table) { + D(DEBUG, "message from libvendor"); + return 0; +} + +int oem_cmd(const char *arg, const char **response) { + D(DEBUG, "message from libvendor, oem catched request %s", arg); + return 0; +} + +static int close_triggers(struct vendor_trigger_t *dev) +{ + if (dev) + free(dev); + + return 0; +} + +static int open_triggers(const struct hw_module_t *module, char const *name, + struct hw_device_t **device) { + struct vendor_trigger_t *dev = malloc(sizeof(struct vendor_trigger_t)); + klog_init(); + klog_set_level(6); + + memset(dev, 0, sizeof(*dev)); + dev->common.module = (struct hw_module_t *) module; + dev->common.close = (int (*)(struct hw_device_t *)) close_triggers; + + dev->gpt_layout = gpt_layout; + dev->oem_cmd = oem_cmd; + + *device = (struct hw_device_t *) dev; + + return 0; +} + + +static struct hw_module_methods_t trigger_module_methods = { + .open = open_triggers, +}; + +struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = TRIGGER_MODULE_ID, + .name = "vendor trigger library for fastbootd", + .author = "Google, Inc.", + .methods = &trigger_module_methods, +}; + |