platform/msm_shared: Add support for verified boot.

Add support to verify boot image before booting up.

Change-Id: Id6c7f6f712d6a267eaebf9814e2ea3ea1910da71
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
new file mode 100644
index 0000000..6ebcb0c
--- /dev/null
+++ b/platform/msm_shared/boot_verifier.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2014 The Linux Foundation. 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.
+ *
+ * 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 <crypto_hash.h>
+#include <boot_verifier.h>
+#include <image_verify.h>
+#include <mmc.h>
+#include <oem_keystore.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <partition_parser.h>
+#include <rsa.h>
+#include <string.h>
+
+static KEYSTORE *oem_keystore;
+static KEYSTORE *user_keystore;
+static uint32_t dev_boot_state = RED;
+BUF_DMA_ALIGN(keystore_buf, 4096);
+char KEYSTORE_PTN_NAME[] = "keystore";
+
+static char *VERIFIED_FLASH_ALLOWED_PTN[] = {
+	"aboot",
+	"boot",
+	"recovery",
+	"system",
+	NULL };
+
+ASN1_SEQUENCE(AUTH_ATTR) ={
+	ASN1_SIMPLE(AUTH_ATTR, target, ASN1_PRINTABLESTRING),
+	ASN1_SIMPLE(AUTH_ATTR, len, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(AUTH_ATTR)
+IMPLEMENT_ASN1_FUNCTIONS(AUTH_ATTR)
+
+	ASN1_SEQUENCE(VERIFIED_BOOT_SIG) = {
+		ASN1_SIMPLE(VERIFIED_BOOT_SIG, version, ASN1_INTEGER),
+		ASN1_SIMPLE(VERIFIED_BOOT_SIG, algor, X509_ALGOR),
+		ASN1_SIMPLE(VERIFIED_BOOT_SIG, auth_attr, AUTH_ATTR),
+		ASN1_SIMPLE(VERIFIED_BOOT_SIG, sig, ASN1_OCTET_STRING)
+	} ASN1_SEQUENCE_END(VERIFIED_BOOT_SIG)
+IMPLEMENT_ASN1_FUNCTIONS(VERIFIED_BOOT_SIG)
+
+	ASN1_SEQUENCE(KEY) = {
+		ASN1_SIMPLE(KEY, algorithm_id, X509_ALGOR),
+		ASN1_SIMPLE(KEY, key_material, RSAPublicKey)
+	}ASN1_SEQUENCE_END(KEY)
+IMPLEMENT_ASN1_FUNCTIONS(KEY);
+
+ASN1_SEQUENCE(KEYBAG) = {
+	ASN1_SIMPLE(KEYBAG, mykey, KEY)
+}ASN1_SEQUENCE_END(KEYBAG)
+IMPLEMENT_ASN1_FUNCTIONS(KEYBAG)
+
+	ASN1_SEQUENCE(KEYSTORE_INNER) = {
+		ASN1_SIMPLE(KEYSTORE_INNER, version, ASN1_INTEGER),
+		ASN1_SIMPLE(KEYSTORE_INNER, mykeybag, KEYBAG)
+	} ASN1_SEQUENCE_END(KEYSTORE_INNER)
+IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE_INNER)
+
+	ASN1_SEQUENCE(KEYSTORE) = {
+		ASN1_SIMPLE(KEYSTORE, version, ASN1_INTEGER),
+		ASN1_SIMPLE(KEYSTORE, mykeybag, KEYBAG),
+		ASN1_SIMPLE(KEYSTORE, sig, VERIFIED_BOOT_SIG)
+	} ASN1_SEQUENCE_END(KEYSTORE)
+IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE)
+
+static uint32_t read_der_message_length(unsigned char* input)
+{
+	uint32_t len = 0;
+	int pos = 0;
+	uint8_t len_bytes = 1;
+
+	/* Check if input starts with Sequence id (0X30) */
+	if(input[pos] != 0x30)
+		return len;
+	pos++;
+
+	/* A length of 0xAABBCCDD in DER encoded messages would be sequence of
+	   following octets 0xAA, 0xBB, 0XCC, 0XDD.
+
+	   To read length - read each octet and shift left by 1 octect before
+	   reading next octet.
+	*/
+	/* check if short or long length form */
+	if(input[pos] & 0x80)
+	{
+		len_bytes = (input[pos] & ~(0x80));
+		pos++;
+	}
+	while(len_bytes)
+	{
+		/* Shift len by 1 octet */
+		len = len << 8;
+
+		/* Read next octet */
+		len = len | input[pos];
+		pos++; len_bytes--;
+	}
+
+	/* Add number of octets representing sequence id and length  */
+	len += pos;
+
+	return len;
+}
+
+static int verify_digest(unsigned char* input, unsigned char *digest, int hash_size)
+{
+	int ret = -1;
+	uint32_t len = read_der_message_length(input);
+	X509_SIG *sig = d2i_X509_SIG(NULL, &input, len);
+	if(sig == NULL)
+	{
+		dprintf(CRITICAL, "boot_verifier: Reading digest failed\n");
+		return ret;
+	}
+
+	if(sig->digest->length != SHA256_SIZE)
+	{
+		dprintf(CRITICAL, "boot_verifier: Digest length error.\n");
+		goto verify_digest_error;
+	}
+
+	if(memcmp(sig->digest->data, digest, hash_size) == 0)
+		ret = 0;
+
+verify_digest_error:
+	if(sig != NULL)
+		X509_SIG_free(sig);
+
+	return ret;
+}
+
+static int add_attribute_to_img(unsigned char *ptr, AUTH_ATTR *input)
+{
+	return i2d_AUTH_ATTR(input, &ptr);
+}
+
+static bool boot_verify_compare_sha256(unsigned char *image_ptr,
+		unsigned int image_size, unsigned char *signature_ptr, RSA *rsa)
+{
+	int ret = -1;
+	bool auth = false;
+	unsigned char *plain_text = NULL;
+	unsigned int digest[8];
+
+	plain_text = (unsigned char *)calloc(sizeof(char), SIGNATURE_SIZE);
+	if (plain_text == NULL) {
+		dprintf(CRITICAL, "boot_verifier: Calloc failed during verification\n");
+		goto cleanup;
+	}
+
+	/* Calculate SHA256sum */
+	image_find_digest(image_ptr, image_size, CRYPTO_AUTH_ALG_SHA256,
+			(unsigned char *)&digest);
+
+	/* Find digest from the image */
+	ret = image_decrypt_signature_rsa(signature_ptr, plain_text, rsa);
+
+	dprintf(SPEW, "boot_verifier: Return of RSA_public_decrypt = %d\n",
+			ret);
+
+	ret = verify_digest(plain_text, (unsigned char*)digest, SHA256_SIZE);
+	if(ret == 0)
+	{
+		auth = true;
+	}
+
+cleanup:
+	if (plain_text != NULL)
+		free(plain_text);
+	EVP_cleanup();
+	CRYPTO_cleanup_all_ex_data();
+	ERR_remove_thread_state(NULL);
+	return auth;
+
+}
+
+static bool verify_image_with_sig(unsigned char* img_addr, uint32_t img_size,
+		char *pname, VERIFIED_BOOT_SIG *sig, KEYSTORE *ks)
+{
+	bool ret = false;
+	uint32_t len;
+	int shift_bytes;
+	RSA *rsa = NULL;
+	bool keystore_verification = false;
+
+	if(!strcmp(pname, "keystore"))
+		keystore_verification = true;
+
+	/* Verify target name */
+	if(strncmp((char*)(sig->auth_attr->target->data), pname,
+				sig->auth_attr->target->length) ||
+				(strlen(pname) != sig->auth_attr->target->length))
+	{
+		dprintf(CRITICAL,
+				"boot_verifier: verification failure due to target name mismatch\n");
+		goto verify_image_with_sig_error;
+	}
+
+	/* Read image size from signature */
+	/* A len = 0xAABBCC (represented by 3 octets) would be stored in
+	   len->data as 0X00CCBBAA and len->length as 3(octets).
+
+	   To read len we need to left shift data to number of missing octets and
+	   then change it to host long
+	 */
+	len = *((uint32_t*)sig->auth_attr->len->data);
+	shift_bytes = sizeof(uint32_t) - sig->auth_attr->len->length;
+	if(shift_bytes > 0) {
+		len = len << (shift_bytes*8);
+	}
+	len = ntohl(len);
+
+	/* Verify image size*/
+	if(len != img_size)
+	{
+		dprintf(CRITICAL,
+				"boot_verifier: image length is different. (%d vs %d)\n",
+				len, img_size);
+		goto verify_image_with_sig_error;
+	}
+
+	/* append attribute to image */
+	if(!keystore_verification)
+		img_size += add_attribute_to_img((unsigned char*)(img_addr + img_size),
+				sig->auth_attr);
+
+	/* compare SHA256SUM of image with value in signature */
+	if(ks != NULL)
+		rsa = ks->mykeybag->mykey->key_material;
+
+	ret = boot_verify_compare_sha256(img_addr, img_size,
+			(unsigned char*)sig->sig->data, rsa);
+
+	if(!ret)
+	{
+		dprintf(CRITICAL,
+				"boot_verifier: Image verification failed.\n");
+	}
+
+verify_image_with_sig_error:
+	return ret;
+}
+
+static int encode_inner_keystore(unsigned char *ptr, KEYSTORE *ks)
+{
+	int ret = 0;
+	KEYSTORE_INNER  *ks_inner = KEYSTORE_INNER_new();
+	if (ks_inner == NULL)
+		return ret;
+	ASN1_INTEGER *tmp_version = ks_inner->version;
+	KEYBAG *tmp_mykeybag = ks_inner->mykeybag;
+
+	ks_inner->version = ks->version;
+	ks_inner->mykeybag = ks->mykeybag;
+	ret = i2d_KEYSTORE_INNER(ks_inner, &ptr);
+
+	ks_inner->version = tmp_version;
+	ks_inner->mykeybag = tmp_mykeybag;
+
+	if(ks_inner != NULL)
+		KEYSTORE_INNER_free(ks_inner);
+	return ret;
+}
+
+static bool verify_keystore(unsigned char * ks_addr, KEYSTORE *ks)
+{
+	bool ret = false;
+	unsigned char * ptr = ks_addr;
+	uint32_t inner_len = encode_inner_keystore(ptr, ks);
+	ret = verify_image_with_sig(ks_addr, inner_len, "keystore", ks->sig,
+			oem_keystore);
+	return ret;
+}
+
+static void read_oem_keystore()
+{
+	if(oem_keystore != NULL)
+		return;
+
+	unsigned char *input = OEM_KEYSTORE;
+	uint32_t len = read_der_message_length(input);
+	KEYSTORE *ks = d2i_KEYSTORE(NULL, &input, len);
+	if(ks != NULL)
+	{
+		oem_keystore = ks;
+		user_keystore = ks;
+	}
+}
+
+static int read_user_keystore_ptn()
+{
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+
+	index = partition_get_index(KEYSTORE_PTN_NAME);
+	ptn = partition_get_offset(index);
+	if(ptn == 0) {
+		dprintf(CRITICAL, "boot_verifier: No keystore partition found\n");
+		return -1;
+	}
+
+	if (mmc_read(ptn, (unsigned int *) keystore_buf, mmc_page_size())) {
+		dprintf(CRITICAL, "boot_verifier: Cannot read user keystore\n");
+		return -1;
+	}
+	return 0;
+}
+
+static void read_user_keystore(unsigned char *user_addr)
+{
+	unsigned char *input = user_addr;
+	uint32_t len = read_der_message_length(input);
+	KEYSTORE *ks = d2i_KEYSTORE(NULL, &input, len);
+	if(ks != NULL)
+	{
+		if(verify_keystore(user_addr, ks) == false)
+		{
+			dprintf(CRITICAL, "boot_verifier: Keystore verification failed!\n");
+			boot_verify_send_event(KEYSTORE_VERIFICATION_FAIL);
+		}
+		else
+			dprintf(CRITICAL, "boot_verifier: Keystore verification success!\n");
+		user_keystore = ks;
+	}
+	else
+	{
+		user_keystore = oem_keystore;
+	}
+}
+
+uint32_t boot_verify_keystore_init()
+{
+	/* Read OEM Keystore */
+	read_oem_keystore();
+
+	/* Read User Keystore */
+	if(!read_user_keystore_ptn())
+		read_user_keystore((unsigned char *)keystore_buf);
+	return dev_boot_state;
+}
+
+bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname)
+{
+	bool ret = false;
+	VERIFIED_BOOT_SIG *sig = NULL;
+	unsigned char* sig_addr = (unsigned char*)(img_addr + img_size);
+	uint32_t sig_len = read_der_message_length(sig_addr);
+
+	if(dev_boot_state == ORANGE)
+	{
+		dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
+		dprintf(INFO, "boot_verifier: Skipping boot verification.\n");
+		return false;
+	}
+
+	if(!sig_len)
+	{
+		dprintf(CRITICAL, "boot_verifier: Error while reading singature length.\n");
+		goto verify_image_error;
+	}
+
+	if((sig = d2i_VERIFIED_BOOT_SIG(NULL, &sig_addr, sig_len)) == NULL)
+	{
+		dprintf(CRITICAL,
+				"boot_verifier: verification failure due to target name mismatch\n");
+		goto verify_image_error;
+	}
+
+	ret = verify_image_with_sig(img_addr, img_size, pname, sig, user_keystore);
+
+verify_image_error:
+	if(sig != NULL)
+		VERIFIED_BOOT_SIG_free(sig);
+	if(!ret)
+		boot_verify_send_event(BOOT_VERIFICATION_FAIL);
+	return ret;
+}
+
+void boot_verify_send_event(uint32_t event)
+{
+	switch(event)
+	{
+		case BOOT_INIT:
+			dev_boot_state = GREEN;
+			break;
+		case KEYSTORE_VERIFICATION_FAIL:
+			if(dev_boot_state == GREEN)
+				dev_boot_state = YELLOW;
+			break;
+		case BOOT_VERIFICATION_FAIL:
+			if(dev_boot_state == GREEN || dev_boot_state == YELLOW)
+				dev_boot_state = RED;
+			break;
+		case DEV_UNLOCK:
+			dev_boot_state = ORANGE;
+			break;
+		case USER_DENIES:
+			if(dev_boot_state == YELLOW || dev_boot_state == ORANGE)
+				dev_boot_state = RED;
+			break;
+	}
+}
+
+uint32_t boot_verify_get_state()
+{
+	return dev_boot_state;
+}
+
+void boot_verify_print_state()
+{
+	switch(dev_boot_state)
+	{
+		case GREEN:
+			dprintf(INFO, "boot_verifier: Device is in GREEN boot state.\n");
+			break;
+		case ORANGE:
+			dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
+			break;
+		case YELLOW:
+			dprintf(INFO, "boot_verifier: Device is in YELLOW boot state.\n");
+			break;
+		case RED:
+			dprintf(INFO, "boot_verifier: Device is in RED boot state.\n");
+			break;
+	}
+}
+
+bool boot_verify_validate_keystore(unsigned char * user_addr)
+{
+	bool ret = false;
+	unsigned char *input = user_addr;
+	uint32_t len = read_der_message_length(input);
+	KEYSTORE *ks = d2i_KEYSTORE(NULL, &input, len);
+	if(ks != NULL)
+	{
+		ret = true;
+	}
+	return ret;
+}
+
+static bool check_list(char**list, char* entry)
+{
+	int i = 0;
+	if(list == NULL || entry == NULL)
+		return false;
+
+	while(*list != NULL)
+	{
+		if(!strcmp(entry, *list))
+			return true;
+
+		list++;
+	}
+
+	return false;
+}
+
+bool boot_verify_flash_allowed(char * entry)
+{
+	return check_list(VERIFIED_FLASH_ALLOWED_PTN, entry);
+}
diff --git a/platform/msm_shared/image_verify.c b/platform/msm_shared/image_verify.c
index 284f8e5..bc2017d 100644
--- a/platform/msm_shared/image_verify.c
+++ b/platform/msm_shared/image_verify.c
@@ -33,6 +33,27 @@
 /*
  * Returns -1 if decryption failed otherwise size of plain_text in bytes
  */
+int image_decrypt_signature_rsa(unsigned char *signature_ptr,
+		unsigned char *plain_text, RSA *rsa_key)
+{
+	int ret = -1;
+
+	if (rsa_key == NULL) {
+		dprintf(CRITICAL, "ERROR: Boot Invalid, RSA_KEY is NULL!\n");
+		return ret;
+	}
+
+	ret = RSA_public_decrypt(SIGNATURE_SIZE, signature_ptr, plain_text,
+				 rsa_key, RSA_PKCS1_PADDING);
+	dprintf(SPEW, "DEBUG openssl: Return of RSA_public_decrypt = %d\n",
+		ret);
+
+	return ret;
+}
+
+/*
+ * Returns -1 if decryption failed otherwise size of plain_text in bytes
+ */
 static int
 image_decrypt_signature(unsigned char *signature_ptr, unsigned char *plain_text)
 {
@@ -66,8 +87,7 @@
 		goto cleanup;
 	}
 
-	ret = RSA_public_decrypt(SIGNATURE_SIZE, signature_ptr, plain_text,
-				 rsa_key, RSA_PKCS1_PADDING);
+	ret = image_decrypt_signature_rsa(signature_ptr, plain_text, rsa_key);
 	dprintf(SPEW, "DEBUG openssl: Return of RSA_public_decrypt = %d\n",
 		ret);
 
@@ -81,6 +101,23 @@
 	return ret;
 }
 
+/* Calculates digest of an image and save it in digest buffer */
+void image_find_digest(unsigned char *image_ptr, unsigned int image_size,
+		unsigned hash_type, unsigned char *digest)
+{
+	/*
+	 * Calculate hash of image and save calculated hash on TZ.
+	 */
+	hash_find(image_ptr, image_size, (unsigned char *)digest, hash_type);
+#ifdef TZ_SAVE_KERNEL_HASH
+	if (hash_type == CRYPTO_AUTH_ALG_SHA256) {
+		save_kernel_hash_cmd(digest);
+		dprintf(INFO, "Image hash saved.\n");
+	} else
+		dprintf(INFO, "image_verify: hash is not SHA-256.\n");
+#endif
+}
+
 /*
  * Returns 1 when image is signed and authorized.
  * Returns 0 when image is unauthorized.
@@ -109,14 +146,8 @@
 	 */
 	hash_size =
 	    (hash_type == CRYPTO_AUTH_ALG_SHA256) ? SHA256_SIZE : SHA1_SIZE;
-	hash_find(image_ptr, image_size, (unsigned char *)&digest, hash_type);
-#ifdef TZ_SAVE_KERNEL_HASH
-	if (hash_type == CRYPTO_AUTH_ALG_SHA256) {
-		save_kernel_hash_cmd(digest);
-		dprintf(INFO, "Image hash saved.\n");
-	} else
-		dprintf(INFO, "image_verify: hash is not SHA-256.\n");
-#endif
+	image_find_digest(image_ptr, image_size, hash_type,
+			(unsigned char *)&digest);
 
 	/*
 	 * Decrypt the pre-calculated expected image hash.
diff --git a/platform/msm_shared/include/boot_verifier.h b/platform/msm_shared/include/boot_verifier.h
new file mode 100644
index 0000000..616f23c
--- /dev/null
+++ b/platform/msm_shared/include/boot_verifier.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014 The Linux Foundation. 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.
+ *
+ * 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.
+ */
+#ifndef __BOOT_VERIFIER_H
+#define __BOOT_VERIFIER_H
+
+#include <asn1.h>
+#include <rsa.h>
+
+/**
+ *    AndroidVerifiedBootSignature DEFINITIONS ::=
+ *    BEGIN
+ *        FormatVersion ::= INTEGER
+ *        AlgorithmIdentifier ::=  SEQUENCE {
+ *            algorithm OBJECT IDENTIFIER,
+ *            parameters ANY DEFINED BY algorithm OPTIONAL
+ *        }
+ *        AuthenticatedAttributes ::= SEQUENCE {
+ *            target CHARACTER STRING,
+ *            length INTEGER
+ *        }
+ *        Signature ::= OCTET STRING
+ *     END
+ */
+
+typedef struct auth_attr_st
+{
+	ASN1_PRINTABLESTRING *target;
+	ASN1_INTEGER *len;
+}AUTH_ATTR;
+
+DECLARE_STACK_OF(AUTH_ATTR)
+DECLARE_ASN1_SET_OF(AUTH_ATTR)
+DECLARE_ASN1_FUNCTIONS(AUTH_ATTR)
+
+typedef struct verif_boot_sig_st
+{
+	ASN1_INTEGER *version;
+	X509_ALGOR *algor;
+	AUTH_ATTR *auth_attr;
+	ASN1_OCTET_STRING *sig;
+}VERIFIED_BOOT_SIG;
+
+DECLARE_STACK_OF(VERIFIED_BOOT_SIG)
+DECLARE_ASN1_SET_OF(VERIFIED_BOOT_SIG)
+DECLARE_ASN1_FUNCTIONS(VERIFIED_BOOT_SIG)
+
+/**
+ * AndroidVerifiedBootKeystore DEFINITIONS ::=
+ * BEGIN
+ *     FormatVersion ::= INTEGER
+ *     KeyBag ::= SEQUENCE {
+ *         Key  ::= SEQUENCE {
+ *             AlgorithmIdentifier  ::=  SEQUENCE {
+ *                 algorithm OBJECT IDENTIFIER,
+ *                 parameters ANY DEFINED BY algorithm OPTIONAL
+ *             }
+ *             KeyMaterial ::= RSAPublicKey
+ *         }
+ *     }
+ *     Signature ::= AndroidVerifiedBootSignature
+ * END
+ */
+
+typedef struct key_st
+{
+	X509_ALGOR *algorithm_id;
+	RSA *key_material;
+}KEY;
+
+DECLARE_STACK_OF(KEY)
+DECLARE_ASN1_SET_OF(KEY)
+DECLARE_ASN1_FUNCTIONS(KEY)
+
+typedef struct keybag_st
+{
+	KEY *mykey;
+}KEYBAG;
+
+DECLARE_STACK_OF(KEYBAG)
+DECLARE_ASN1_SET_OF(KEYBAG)
+DECLARE_ASN1_FUNCTIONS(KEYBAG)
+
+typedef struct keystore_inner_st
+{
+	ASN1_INTEGER *version;
+	KEYBAG *mykeybag;
+}KEYSTORE_INNER;
+
+DECLARE_STACK_OF(KEYSTORE_INNER)
+DECLARE_ASN1_SET_OF(KEYSTORE_INNER)
+DECLARE_ASN1_FUNCTIONS(KEYSTORE_INNER)
+
+typedef struct keystore_st
+{
+	ASN1_INTEGER *version;
+	KEYBAG *mykeybag;
+	VERIFIED_BOOT_SIG *sig;
+}KEYSTORE;
+
+DECLARE_STACK_OF(KEYSTORE)
+DECLARE_ASN1_SET_OF(KEYSTORE)
+DECLARE_ASN1_FUNCTIONS(KEYSTORE)
+
+enum boot_state
+{
+	GREEN,
+	ORANGE,
+	YELLOW,
+	RED,
+};
+
+enum boot_verfiy_event
+{
+	BOOT_INIT,
+	DEV_UNLOCK,
+	KEYSTORE_VERIFICATION_FAIL,
+	BOOT_VERIFICATION_FAIL,
+	USER_DENIES,
+};
+
+extern char KEYSTORE_PTN_NAME[];
+/* Function to initialize keystore */
+uint32_t boot_verify_keystore_init();
+/* Function to verify boot/recovery image */
+bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname);
+/* Function to send event to boot state machine */
+void boot_verify_send_event(uint32_t event);
+/* Read current boot state */
+uint32_t boot_verify_get_state();
+/* Print current boot state */
+void boot_verify_print_state();
+/* Function to validate keystore */
+bool boot_verify_validate_keystore(unsigned char * user_addr);
+/* Function to check if partition is allowed to flash in verified mode */
+bool boot_verify_flash_allowed(char * entry);
+#endif
diff --git a/platform/msm_shared/include/image_verify.h b/platform/msm_shared/include/image_verify.h
index 709aa93..0819421 100644
--- a/platform/msm_shared/include/image_verify.h
+++ b/platform/msm_shared/include/image_verify.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011,2014 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,8 @@
 #ifndef __IMAGE_VERIFY_H
 #define __IMAGE_VERIFY_H
 
+#include <x509.h>
+
 #define SHA1_SIZE      16
 #define SHA256_SIZE    32
 /* For keys of length 2048 bits */
@@ -37,4 +39,12 @@
 int image_verify(unsigned char *image_ptr,
 		 unsigned char *signature_ptr,
 		 unsigned int image_size, unsigned hash_type);
+
+/* Decrypt signature with RSA public key */
+int image_decrypt_signature_rsa(unsigned char *signature_ptr,
+		unsigned char *plain_text, RSA *rsa_key);
+
+/* Find hash of image */
+void image_find_digest(unsigned char *image_ptr, unsigned int image_size,
+		unsigned hash_type, unsigned char *digest);
 #endif
diff --git a/platform/msm_shared/include/oem_keystore.h b/platform/msm_shared/include/oem_keystore.h
new file mode 100644
index 0000000..47b3a4f
--- /dev/null
+++ b/platform/msm_shared/include/oem_keystore.h
@@ -0,0 +1,83 @@
+/* Copyright (c) 2014, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ *
+ */
+#ifndef _OEM_KEYSTORE_H
+#define _OEM_KEYSTORE_H
+const unsigned char OEM_KEYSTORE[] = {
+  0x30, 0x82, 0x02, 0x4c, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x1d, 0x30,
+  0x82, 0x01, 0x19, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x0b, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01,
+  0x00, 0xc8, 0x82, 0x09, 0x43, 0x84, 0x33, 0x91, 0xfa, 0xca, 0xa1, 0x43,
+  0xc1, 0x92, 0xa9, 0x26, 0x0c, 0xe2, 0x15, 0xab, 0x71, 0xfa, 0x85, 0x97,
+  0x5f, 0xf0, 0xcd, 0x66, 0xeb, 0x7f, 0x0b, 0xc1, 0x01, 0x8e, 0x8e, 0x1b,
+  0xfa, 0xaa, 0x82, 0x21, 0xd3, 0x1d, 0x3b, 0x0a, 0x91, 0x0e, 0xcd, 0x85,
+  0xa0, 0x4d, 0xd7, 0xed, 0x27, 0x72, 0xa6, 0xb1, 0x26, 0x8e, 0xe9, 0x5f,
+  0x57, 0x77, 0x3d, 0x93, 0x79, 0x38, 0xde, 0xac, 0xa1, 0xc9, 0xd1, 0xcc,
+  0x42, 0x04, 0x53, 0x88, 0x64, 0xac, 0xaa, 0xab, 0xfc, 0xb7, 0xf0, 0x32,
+  0x2d, 0xb0, 0xf4, 0xe1, 0x35, 0x58, 0xdf, 0x5e, 0x8a, 0x47, 0x28, 0x2b,
+  0xa9, 0xda, 0x54, 0xd3, 0xbc, 0x0a, 0x12, 0x5f, 0x76, 0x5e, 0x16, 0xab,
+  0xf5, 0x9d, 0x11, 0x8f, 0x36, 0x99, 0x3a, 0x1c, 0x76, 0x95, 0x31, 0xa9,
+  0x92, 0x86, 0x81, 0xcc, 0x56, 0x56, 0x52, 0xe2, 0x70, 0xf4, 0xb3, 0x99,
+  0xe7, 0x2e, 0xdd, 0x9d, 0x33, 0xad, 0x22, 0x8a, 0x10, 0x17, 0x53, 0xf2,
+  0x6a, 0x85, 0x80, 0xad, 0x14, 0xd3, 0xa2, 0xd3, 0xe2, 0x37, 0x8a, 0x4c,
+  0xdd, 0xa2, 0xdb, 0x46, 0x32, 0xa9, 0x23, 0x46, 0x1a, 0xd5, 0x86, 0xec,
+  0x39, 0x98, 0x06, 0xd0, 0x4f, 0xe8, 0x6f, 0x02, 0x90, 0x05, 0x76, 0x3b,
+  0x8b, 0xfc, 0x86, 0x8d, 0xa1, 0x3d, 0x58, 0x80, 0xc7, 0x9e, 0x53, 0xd0,
+  0xa2, 0xb8, 0xbb, 0xc7, 0x13, 0x35, 0xcd, 0x6f, 0xc2, 0x07, 0xad, 0xa2,
+  0xe1, 0x82, 0x12, 0xf1, 0xbc, 0x4f, 0x19, 0x00, 0x0f, 0x9d, 0x9f, 0x9d,
+  0x01, 0x43, 0x24, 0xac, 0xe6, 0x30, 0x11, 0x38, 0xae, 0xa6, 0xb7, 0x47,
+  0xb3, 0x71, 0x8b, 0x79, 0x46, 0xd4, 0x3b, 0x7d, 0xf0, 0x6c, 0x84, 0xa2,
+  0x58, 0xb4, 0xe3, 0x86, 0x8f, 0xb8, 0xfc, 0xf9, 0xcb, 0x1c, 0x30, 0x17,
+  0x1e, 0x34, 0xc3, 0x98, 0xa3, 0x02, 0x01, 0x03, 0x30, 0x82, 0x01, 0x24,
+  0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x0b, 0x30, 0x0e, 0x13, 0x08, 0x6b, 0x65, 0x79, 0x73,
+  0x74, 0x6f, 0x72, 0x65, 0x02, 0x02, 0x01, 0x28, 0x04, 0x82, 0x01, 0x00,
+  0x96, 0x5e, 0x50, 0x0f, 0x17, 0x97, 0xed, 0x8b, 0xfe, 0x92, 0x21, 0x79,
+  0xc9, 0x55, 0x1b, 0x20, 0xb6, 0xb6, 0x8a, 0xac, 0xbc, 0xb0, 0x77, 0x8c,
+  0x46, 0xf5, 0x73, 0xc3, 0x6e, 0xf8, 0xac, 0x67, 0x48, 0x7f, 0xb0, 0x5b,
+  0xc0, 0x37, 0x4b, 0xea, 0x77, 0xcb, 0x9b, 0x8e, 0x37, 0x4a, 0x76, 0x3c,
+  0xef, 0x18, 0x42, 0x17, 0x5f, 0xa0, 0x50, 0x38, 0xdd, 0xc3, 0x19, 0xd3,
+  0x72, 0x65, 0xa5, 0x81, 0x51, 0x9e, 0x6a, 0xc6, 0x98, 0xfc, 0xba, 0x82,
+  0x8a, 0x3b, 0xc7, 0x78, 0xbc, 0x0c, 0x75, 0x70, 0x25, 0x42, 0x0c, 0xd1,
+  0xba, 0xbb, 0x8d, 0x5c, 0x34, 0xd7, 0x90, 0x08, 0xf8, 0x0a, 0x31, 0x86,
+  0xc6, 0x0a, 0x47, 0xd4, 0x69, 0x62, 0xf0, 0x03, 0x89, 0x56, 0xca, 0x42,
+  0x75, 0xf3, 0x30, 0x24, 0x6c, 0xda, 0xb0, 0x4f, 0xf4, 0xdc, 0x0c, 0xd0,
+  0x20, 0xf8, 0xb9, 0x0f, 0x16, 0x84, 0xc7, 0xca, 0xc5, 0x7b, 0x66, 0x46,
+  0x76, 0x38, 0x11, 0x2d, 0x30, 0x88, 0xc3, 0x93, 0x14, 0x91, 0xad, 0x80,
+  0x94, 0xc9, 0xab, 0x75, 0x80, 0x07, 0xde, 0xed, 0x7e, 0xfe, 0x18, 0x5c,
+  0x16, 0xfa, 0x92, 0x45, 0xf4, 0x2b, 0x59, 0xcf, 0x2b, 0xf0, 0x7b, 0x2d,
+  0xfe, 0xf4, 0x07, 0x34, 0xb4, 0xad, 0x7d, 0x1f, 0x34, 0xc1, 0x48, 0x09,
+  0xf5, 0xf8, 0x26, 0xd9, 0x3b, 0x32, 0x25, 0xb1, 0x8f, 0x48, 0x08, 0xcf,
+  0x21, 0x14, 0x16, 0x15, 0x7e, 0x58, 0x89, 0x8b, 0x2a, 0x97, 0x89, 0xa7,
+  0x3a, 0x45, 0x13, 0x3b, 0x49, 0x86, 0xfb, 0xa2, 0x2d, 0x50, 0x92, 0x44,
+  0x57, 0x89, 0x6a, 0xcc, 0xe5, 0x1c, 0xae, 0xc1, 0x84, 0xf9, 0x3b, 0x38,
+  0x0b, 0x48, 0xb3, 0x24, 0x99, 0x46, 0x4e, 0xf8, 0xe5, 0x9f, 0x01, 0xd1,
+  0xf7, 0x62, 0x1f, 0xb8, 0xb5, 0x19, 0x30, 0x7f, 0x9f, 0x2d, 0x67, 0x3c,
+  0xc6, 0x0a, 0x5c, 0x3c
+};
+#endif
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index f5f6dce..9d935b3 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -34,6 +34,11 @@
 	$(LOCAL_DIR)/mmc.o
 endif
 
+ifeq ($(ENABLE_VERIFIED_BOOT),1)
+OBJS += \
+	$(LOCAL_DIR)/boot_verifier.o
+endif
+
 ifeq ($(PLATFORM),msm8x60)
 	OBJS += $(LOCAL_DIR)/mipi_dsi.o \
 			$(LOCAL_DIR)/i2c_qup.o \