openssl/lk: Enable signed boot img check
This uses openssl to check the boot image prior
to jumping to kernel to see if it is a signed
kernel image.
Change-Id: I92927fd9317a0f701dab395cc6d39929c64340c1
diff --git a/platform/msm_shared/image_verify.c b/platform/msm_shared/image_verify.c
new file mode 100644
index 0000000..0458c76
--- /dev/null
+++ b/platform/msm_shared/image_verify.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 <x509.h>
+#include <certificate.h>
+#include <crypto_hash.h>
+#include "image_verify.h"
+
+/*
+ * 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){
+ /*
+ * Extract Public Key and Decrypt Signature
+ */
+ int ret = -1;
+ X509 *x509_certificate = NULL;
+ unsigned char *cert_ptr = certBuffer;
+ unsigned int cert_size = sizeof(certBuffer);
+ EVP_PKEY *pub_key = NULL;
+ RSA* rsa_key = NULL;
+
+ /*
+ * Get Pubkey and Convert the internal EVP_PKEY to RSA internal struct
+ */
+ if ((x509_certificate = d2i_X509(NULL, &cert_ptr, cert_size)) == NULL){
+ dprintf(CRITICAL,
+ "ERROR: Image Invalid, X509_Certificate is NULL!\n");
+ goto cleanup;
+ }
+ pub_key = X509_get_pubkey(x509_certificate);
+ rsa_key = EVP_PKEY_get1_RSA(pub_key);
+ if (rsa_key == NULL){
+ dprintf(CRITICAL,
+ "ERROR: Boot Invalid, RSA_KEY is NULL!\n");
+ goto cleanup;
+ }
+
+ 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);
+
+cleanup:
+ if (rsa_key != NULL)
+ RSA_free(rsa_key);
+ if (x509_certificate != NULL)
+ X509_free(x509_certificate);
+ if (pub_key != NULL)
+ EVP_PKEY_free(pub_key);
+ return ret;
+}
+
+/*
+ * Returns 1 when image is signed and authorized.
+ * Returns 0 when image is unauthorized.
+ * Expects a pointer to the start of image and pointer to start of sig
+ */
+int image_verify(unsigned char * image_ptr,
+ unsigned char * signature_ptr,
+ unsigned int image_size,
+ unsigned hash_type){
+
+ int ret = -1;
+ int auth = 0;
+ unsigned char * plain_text = NULL;
+ unsigned int digest[8];
+ unsigned int hash_size;
+
+ plain_text = (unsigned char*) calloc(sizeof(char), SIGNATURE_SIZE);
+ if (plain_text == NULL){
+ dprintf(CRITICAL, "ERROR: Calloc failed during verification\n");
+ goto cleanup;
+ }
+
+ ret = image_decrypt_signature(signature_ptr, plain_text);
+ if (ret == -1){
+ dprintf(CRITICAL, "ERROR: Image Invalid! Decryption failed!\n");
+ goto cleanup;
+ }
+
+ /*
+ * Calculate hash of image for comparison
+ */
+ hash_size = (hash_type == CRYPTO_AUTH_ALG_SHA256) ?
+ SHA256_SIZE : SHA1_SIZE;
+ hash_find(image_ptr, image_size,
+ (unsigned char*)&digest, hash_type);
+ if(memcmp(plain_text, digest, hash_size) != 0)
+ {
+ dprintf(CRITICAL,
+ "ERROR: Image Invalid! Please use another image!\n");
+ ret = -1;
+ goto cleanup;
+ }
+ else
+ {
+ /* Authorized image */
+ auth = 1;
+ }
+
+ /* Cleanup after complete usage of openssl - cached data and objects */
+cleanup:
+ if (plain_text != NULL)
+ free(plain_text);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ ERR_remove_thread_state(NULL);
+ return auth;
+}