blob: cfdb5b9d5bc89a9782e5943ad5830f23fa77635e [file] [log] [blame]
Shashank Mittalcd98d472011-08-02 14:29:24 -07001/*
Amir Samuelova3382942014-03-13 13:48:57 +02002 * Copyright (c) 2011,2013-2014 The Linux Foundation. All rights reserved.
Shashank Mittalcd98d472011-08-02 14:29:24 -07003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in
11 * the documentation and/or other materials provided with the
12 * distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
21 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
24 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27#include <x509.h>
vijay kumar4f4405f2014-08-08 11:49:53 +053028#include <err.h>
Shashank Mittalcd98d472011-08-02 14:29:24 -070029#include <certificate.h>
30#include <crypto_hash.h>
vijay kumar4f4405f2014-08-08 11:49:53 +053031#include <string.h>
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -080032#include <openssl/err.h>
Shashank Mittalcd98d472011-08-02 14:29:24 -070033#include "image_verify.h"
Amir Samuelov67ae1d32013-03-24 16:27:52 +020034#include "scm.h"
Shashank Mittalcd98d472011-08-02 14:29:24 -070035
vijay kumar4f4405f2014-08-08 11:49:53 +053036
Shashank Mittalcd98d472011-08-02 14:29:24 -070037/*
38 * Returns -1 if decryption failed otherwise size of plain_text in bytes
39 */
Shashank Mittal64d04852014-08-28 15:02:46 -070040int image_decrypt_signature_rsa(unsigned char *signature_ptr,
41 unsigned char *plain_text, RSA *rsa_key)
42{
43 int ret = -1;
44
45 if (rsa_key == NULL) {
46 dprintf(CRITICAL, "ERROR: Boot Invalid, RSA_KEY is NULL!\n");
47 return ret;
48 }
49
50 ret = RSA_public_decrypt(SIGNATURE_SIZE, signature_ptr, plain_text,
51 rsa_key, RSA_PKCS1_PADDING);
52 dprintf(SPEW, "DEBUG openssl: Return of RSA_public_decrypt = %d\n",
53 ret);
54
55 return ret;
56}
57
58/*
59 * Returns -1 if decryption failed otherwise size of plain_text in bytes
60 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080061static int
62image_decrypt_signature(unsigned char *signature_ptr, unsigned char *plain_text)
63{
Shashank Mittalcd98d472011-08-02 14:29:24 -070064 /*
65 * Extract Public Key and Decrypt Signature
66 */
67 int ret = -1;
68 X509 *x509_certificate = NULL;
vijay kumar4f4405f2014-08-08 11:49:53 +053069 const unsigned char *cert_ptr = (const unsigned char *)certBuffer;
Shashank Mittalcd98d472011-08-02 14:29:24 -070070 unsigned int cert_size = sizeof(certBuffer);
71 EVP_PKEY *pub_key = NULL;
Ajay Dudanib01e5062011-12-03 23:23:42 -080072 RSA *rsa_key = NULL;
Shashank Mittalcd98d472011-08-02 14:29:24 -070073
74 /*
75 * Get Pubkey and Convert the internal EVP_PKEY to RSA internal struct
76 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080077 if ((x509_certificate = d2i_X509(NULL, &cert_ptr, cert_size)) == NULL) {
Shashank Mittalcd98d472011-08-02 14:29:24 -070078 dprintf(CRITICAL,
79 "ERROR: Image Invalid, X509_Certificate is NULL!\n");
80 goto cleanup;
81 }
82 pub_key = X509_get_pubkey(x509_certificate);
Lijuan Gao0e2caf22014-07-15 18:36:18 +080083 if (pub_key == NULL) {
84 dprintf(CRITICAL, "ERROR: Boot Invalid, PUB_KEY is NULL!\n");
85 goto cleanup;
86 }
87
Shashank Mittalcd98d472011-08-02 14:29:24 -070088 rsa_key = EVP_PKEY_get1_RSA(pub_key);
Ajay Dudanib01e5062011-12-03 23:23:42 -080089 if (rsa_key == NULL) {
90 dprintf(CRITICAL, "ERROR: Boot Invalid, RSA_KEY is NULL!\n");
Shashank Mittalcd98d472011-08-02 14:29:24 -070091 goto cleanup;
92 }
93
Shashank Mittal64d04852014-08-28 15:02:46 -070094 ret = image_decrypt_signature_rsa(signature_ptr, plain_text, rsa_key);
Ajay Dudanib01e5062011-12-03 23:23:42 -080095 dprintf(SPEW, "DEBUG openssl: Return of RSA_public_decrypt = %d\n",
96 ret);
Shashank Mittalcd98d472011-08-02 14:29:24 -070097
Ajay Dudanib01e5062011-12-03 23:23:42 -080098 cleanup:
Shashank Mittalcd98d472011-08-02 14:29:24 -070099 if (rsa_key != NULL)
100 RSA_free(rsa_key);
101 if (x509_certificate != NULL)
102 X509_free(x509_certificate);
103 if (pub_key != NULL)
104 EVP_PKEY_free(pub_key);
105 return ret;
106}
107
Shashank Mittal64d04852014-08-28 15:02:46 -0700108/* Calculates digest of an image and save it in digest buffer */
109void image_find_digest(unsigned char *image_ptr, unsigned int image_size,
110 unsigned hash_type, unsigned char *digest)
111{
112 /*
113 * Calculate hash of image and save calculated hash on TZ.
114 */
115 hash_find(image_ptr, image_size, (unsigned char *)digest, hash_type);
116#ifdef TZ_SAVE_KERNEL_HASH
117 if (hash_type == CRYPTO_AUTH_ALG_SHA256) {
118 save_kernel_hash_cmd(digest);
119 dprintf(INFO, "Image hash saved.\n");
120 } else
121 dprintf(INFO, "image_verify: hash is not SHA-256.\n");
122#endif
123}
124
Shashank Mittalcd98d472011-08-02 14:29:24 -0700125/*
126 * Returns 1 when image is signed and authorized.
127 * Returns 0 when image is unauthorized.
128 * Expects a pointer to the start of image and pointer to start of sig
129 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800130int
131image_verify(unsigned char *image_ptr,
132 unsigned char *signature_ptr,
133 unsigned int image_size, unsigned hash_type)
134{
Shashank Mittalcd98d472011-08-02 14:29:24 -0700135
136 int ret = -1;
137 int auth = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800138 unsigned char *plain_text = NULL;
Shashank Mittalcd98d472011-08-02 14:29:24 -0700139 unsigned int digest[8];
vijay kumar4f4405f2014-08-08 11:49:53 +0530140 int hash_size;
Shashank Mittalcd98d472011-08-02 14:29:24 -0700141
Ajay Dudanib01e5062011-12-03 23:23:42 -0800142 plain_text = (unsigned char *)calloc(sizeof(char), SIGNATURE_SIZE);
143 if (plain_text == NULL) {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700144 dprintf(CRITICAL, "ERROR: Calloc failed during verification\n");
145 goto cleanup;
146 }
147
Amir Samuelova3382942014-03-13 13:48:57 +0200148 /*
149 * Calculate hash of image and save calculated hash on TZ.
150 */
151 hash_size =
152 (hash_type == CRYPTO_AUTH_ALG_SHA256) ? SHA256_SIZE : SHA1_SIZE;
Shashank Mittal64d04852014-08-28 15:02:46 -0700153 image_find_digest(image_ptr, image_size, hash_type,
154 (unsigned char *)&digest);
Amir Samuelova3382942014-03-13 13:48:57 +0200155
156 /*
157 * Decrypt the pre-calculated expected image hash.
Sundarajan Srinivasanf3908592014-04-21 14:14:30 -0700158 * Return value, ret should be equal to hash_size. Otherwise it means a failure. With this check
159 * we avoid a potential vulnerability due to trailing data placed at the end of digest.
Amir Samuelova3382942014-03-13 13:48:57 +0200160 */
Shashank Mittalcd98d472011-08-02 14:29:24 -0700161 ret = image_decrypt_signature(signature_ptr, plain_text);
Sundarajan Srinivasanf3908592014-04-21 14:14:30 -0700162 if (ret != hash_size) {
163 dprintf(CRITICAL, "ERROR: Image Invalid! signature check failed! ret %d\n", ret);
Shashank Mittalcd98d472011-08-02 14:29:24 -0700164 goto cleanup;
165 }
166
167 /*
Amir Samuelova3382942014-03-13 13:48:57 +0200168 * Compare the expected hash with the calculated hash.
Shashank Mittalcd98d472011-08-02 14:29:24 -0700169 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800170 if (memcmp(plain_text, digest, hash_size) != 0) {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700171 dprintf(CRITICAL,
172 "ERROR: Image Invalid! Please use another image!\n");
173 ret = -1;
174 goto cleanup;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800175 } else {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700176 /* Authorized image */
177 auth = 1;
178 }
179
180 /* Cleanup after complete usage of openssl - cached data and objects */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800181 cleanup:
Shashank Mittalcd98d472011-08-02 14:29:24 -0700182 if (plain_text != NULL)
183 free(plain_text);
184 EVP_cleanup();
185 CRYPTO_cleanup_all_ex_data();
186 ERR_remove_thread_state(NULL);
187 return auth;
188}