blob: 068f1887ce1eef8014756fffe54df21bb1f92be7 [file] [log] [blame]
Shashank Mittalcd98d472011-08-02 14:29:24 -07001/*
Duy Truongf3ac7b32013-02-13 01:07:28 -08002 * Copyright (c) 2011, 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>
28#include <certificate.h>
29#include <crypto_hash.h>
30#include "image_verify.h"
31
32/*
33 * Returns -1 if decryption failed otherwise size of plain_text in bytes
34 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080035static int
36image_decrypt_signature(unsigned char *signature_ptr, unsigned char *plain_text)
37{
Shashank Mittalcd98d472011-08-02 14:29:24 -070038 /*
39 * Extract Public Key and Decrypt Signature
40 */
41 int ret = -1;
42 X509 *x509_certificate = NULL;
43 unsigned char *cert_ptr = certBuffer;
44 unsigned int cert_size = sizeof(certBuffer);
45 EVP_PKEY *pub_key = NULL;
Ajay Dudanib01e5062011-12-03 23:23:42 -080046 RSA *rsa_key = NULL;
Shashank Mittalcd98d472011-08-02 14:29:24 -070047
48 /*
49 * Get Pubkey and Convert the internal EVP_PKEY to RSA internal struct
50 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080051 if ((x509_certificate = d2i_X509(NULL, &cert_ptr, cert_size)) == NULL) {
Shashank Mittalcd98d472011-08-02 14:29:24 -070052 dprintf(CRITICAL,
53 "ERROR: Image Invalid, X509_Certificate is NULL!\n");
54 goto cleanup;
55 }
56 pub_key = X509_get_pubkey(x509_certificate);
57 rsa_key = EVP_PKEY_get1_RSA(pub_key);
Ajay Dudanib01e5062011-12-03 23:23:42 -080058 if (rsa_key == NULL) {
59 dprintf(CRITICAL, "ERROR: Boot Invalid, RSA_KEY is NULL!\n");
Shashank Mittalcd98d472011-08-02 14:29:24 -070060 goto cleanup;
61 }
62
63 ret = RSA_public_decrypt(SIGNATURE_SIZE, signature_ptr, plain_text,
Ajay Dudanib01e5062011-12-03 23:23:42 -080064 rsa_key, RSA_PKCS1_PADDING);
65 dprintf(SPEW, "DEBUG openssl: Return of RSA_public_decrypt = %d\n",
66 ret);
Shashank Mittalcd98d472011-08-02 14:29:24 -070067
Ajay Dudanib01e5062011-12-03 23:23:42 -080068 cleanup:
Shashank Mittalcd98d472011-08-02 14:29:24 -070069 if (rsa_key != NULL)
70 RSA_free(rsa_key);
71 if (x509_certificate != NULL)
72 X509_free(x509_certificate);
73 if (pub_key != NULL)
74 EVP_PKEY_free(pub_key);
75 return ret;
76}
77
78/*
79 * Returns 1 when image is signed and authorized.
80 * Returns 0 when image is unauthorized.
81 * Expects a pointer to the start of image and pointer to start of sig
82 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080083int
84image_verify(unsigned char *image_ptr,
85 unsigned char *signature_ptr,
86 unsigned int image_size, unsigned hash_type)
87{
Shashank Mittalcd98d472011-08-02 14:29:24 -070088
89 int ret = -1;
90 int auth = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -080091 unsigned char *plain_text = NULL;
Shashank Mittalcd98d472011-08-02 14:29:24 -070092 unsigned int digest[8];
93 unsigned int hash_size;
94
Ajay Dudanib01e5062011-12-03 23:23:42 -080095 plain_text = (unsigned char *)calloc(sizeof(char), SIGNATURE_SIZE);
96 if (plain_text == NULL) {
Shashank Mittalcd98d472011-08-02 14:29:24 -070097 dprintf(CRITICAL, "ERROR: Calloc failed during verification\n");
98 goto cleanup;
99 }
100
101 ret = image_decrypt_signature(signature_ptr, plain_text);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800102 if (ret == -1) {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700103 dprintf(CRITICAL, "ERROR: Image Invalid! Decryption failed!\n");
104 goto cleanup;
105 }
106
107 /*
108 * Calculate hash of image for comparison
109 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800110 hash_size =
111 (hash_type == CRYPTO_AUTH_ALG_SHA256) ? SHA256_SIZE : SHA1_SIZE;
112 hash_find(image_ptr, image_size, (unsigned char *)&digest, hash_type);
113 if (memcmp(plain_text, digest, hash_size) != 0) {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700114 dprintf(CRITICAL,
115 "ERROR: Image Invalid! Please use another image!\n");
116 ret = -1;
117 goto cleanup;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800118 } else {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700119 /* Authorized image */
120 auth = 1;
121 }
122
123 /* Cleanup after complete usage of openssl - cached data and objects */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 cleanup:
Shashank Mittalcd98d472011-08-02 14:29:24 -0700125 if (plain_text != NULL)
126 free(plain_text);
127 EVP_cleanup();
128 CRYPTO_cleanup_all_ex_data();
129 ERR_remove_thread_state(NULL);
130 return auth;
131}