blob: ce5103db4383b2715c3bf7a30e3f400ee2810496 [file] [log] [blame]
Nan Zhou7a337042021-07-26 21:05:21 -07001/*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Willy Tuadb8ffe2023-07-17 13:44:22 -070016
17#include <libcr51sign/libcr51sign.h>
William A. Kennington III5acaca22021-10-28 16:32:33 -070018#include <libcr51sign/libcr51sign_support.h>
William A. Kennington IIIdeb55012021-10-28 17:12:23 -070019#include <openssl/err.h>
Nan Zhou7a337042021-07-26 21:05:21 -070020#include <openssl/evp.h>
21#include <openssl/pem.h>
22#include <openssl/rsa.h>
23#include <stdio.h>
Nan Zhou7a337042021-07-26 21:05:21 -070024
25#ifdef __cplusplus
26extern "C"
27{
28#endif
29
William A. Kennington IIIdeb55012021-10-28 17:12:23 -070030#ifndef USER_PRINT
31#define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
32#endif
33
Nan Zhou7a337042021-07-26 21:05:21 -070034 // @func hash_init get ready to compute a hash
35 //
36 // @param[in] ctx - context struct
37 // @param[in] hash_type - type of hash function to use
38 //
39 // @return nonzero on error, zero on success
40
41 int hash_init(const void* ctx, enum hash_type type)
42 {
43 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
44 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
45 hash_context->hash_type = type;
46 if (type == HASH_SHA2_256) // SHA256_Init returns 1
47 SHA256_Init(&hash_context->sha256_ctx);
48 else if (type == HASH_SHA2_512)
49 SHA512_Init(&hash_context->sha512_ctx);
50 else
51 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
52
53 return LIBCR51SIGN_SUCCESS;
54 }
55
56 // @func hash_update add data to the hash
57 //
58 // @param[in] ctx - context struct
59 // @param[in] buf - data to add to hash
60 // @param[in] count - number of bytes of data to add
61 //
62 // @return nonzero on error, zero on success
63
64 int hash_update(void* ctx, const uint8_t* data, size_t size)
65 {
66 if (size == 0)
67 return LIBCR51SIGN_SUCCESS;
68 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
69 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
70
71 if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
72 SHA256_Update(&hash_context->sha256_ctx, data, size);
73 else if (hash_context->hash_type == HASH_SHA2_512)
74 SHA512_Update(&hash_context->sha512_ctx, data, size);
75 else
76 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
77
78 return LIBCR51SIGN_SUCCESS;
79 }
80
81 // @func hash_final finish hash calculation
82 //
83 // @param[in] ctx - context struct
84 // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
85 //
86 // @return nonzero on error, zero on success
87
88 int hash_final(void* ctx, uint8_t* hash)
89 {
90 int rv;
91 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
92 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
93
94 if (hash_context->hash_type == HASH_SHA2_256)
95 rv = SHA256_Final(hash, &hash_context->sha256_ctx);
96 else if (hash_context->hash_type == HASH_SHA2_512)
97 rv = SHA512_Final(hash, &hash_context->sha512_ctx);
98 else
99 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
100
101 if (rv)
102 return LIBCR51SIGN_SUCCESS;
103 else
104 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
105 }
106
107 // @func verify check that the signature is valid for given hashed data
108 //
109 // @param[in] ctx - context struct
110 // @param[in] scheme - type of signature, hash, etc.
111 // @param[in] sig - signature blob
112 // @param[in] sig_len - length of signature in bytes
113 // @param[in] data - pre-hashed data to verify
114 // @param[in] data_len - length of hashed data in bytes
115 //
116 // verify_signature expects RSA public key file path in ctx->key_ring
117 // @return nonzero on error, zero on success
118
119 int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
120 const uint8_t* sig, size_t sig_len,
121 const uint8_t* data, size_t data_len)
122 {
123 // By default returns error.
124 int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
125
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800126 CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700127 for (size_t i = 0; i < sig_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700128 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700129 CPRINTS(ctx, "%x", sig[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700130 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800131 CPRINTS(ctx, "\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700132
133 struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
134 FILE* fp = fopen(lctx->keyring, "r");
135 RSA *rsa = NULL, *pub_rsa = NULL;
136 EVP_PKEY* pkey = NULL;
137 BIO* bio = BIO_new(BIO_s_mem());
138 if (!fp)
139 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800140 CPRINTS(ctx, "fopen failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700141 goto clean_up;
142 }
143
144 pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
145 if (!pkey)
146 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800147 CPRINTS(ctx, "Read public key failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700148 goto clean_up;
149 }
150
151 rsa = EVP_PKEY_get1_RSA(pkey);
152 if (!rsa)
153 {
154 goto clean_up;
155 }
156 pub_rsa = RSAPublicKey_dup(rsa);
157 if (!RSA_print(bio, pub_rsa, 2))
158 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800159 CPRINTS(ctx, "RSA print failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700160 }
161 if (!pub_rsa)
162 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800163 CPRINTS(ctx, "no pub RSA\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700164 goto clean_up;
165 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800166 CPRINTS(ctx, "public RSA\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700167 char buffer[1024];
168 while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
169 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700170 CPRINTS(ctx, " %s", buffer);
Nan Zhou7a337042021-07-26 21:05:21 -0700171 }
172 enum hash_type hash_type;
173 rv = get_hash_type_from_signature(sig_scheme, &hash_type);
174 if (rv != LIBCR51SIGN_SUCCESS)
175 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800176 CPRINTS(ctx, "Invalid hash_type!\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700177 goto clean_up;
178 }
179 int hash_nid = -1;
180 if (hash_type == HASH_SHA2_256)
181 {
182 hash_nid = NID_sha256;
183 }
184 else if (hash_type == HASH_SHA2_512)
185 {
186 hash_nid = NID_sha512;
187 }
188 else
189 {
190 rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
191 goto clean_up;
192 }
193
194 int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
195 // OpenSSL RSA_verify returns 1 on success and 0 on failure
196 if (!ret)
197 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800198 CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700199 ERR_error_string(ERR_get_error(), NULL));
Nan Zhou7a337042021-07-26 21:05:21 -0700200 rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
201 goto clean_up;
202 }
203 rv = LIBCR51SIGN_SUCCESS;
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800204 CPRINTS(ctx, "sig: ");
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700205 for (size_t i = 0; i < sig_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700206 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700207 CPRINTS(ctx, "%x", sig[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700208 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800209 CPRINTS(ctx, "\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700210
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800211 CPRINTS(ctx, "data: ");
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700212 for (size_t i = 0; i < data_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700213 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700214 CPRINTS(ctx, "%x", data[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700215 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800216 CPRINTS(ctx, "\n");
217
Nan Zhou7a337042021-07-26 21:05:21 -0700218 const unsigned rsa_size = RSA_size(pub_rsa);
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800219 CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
Nan Zhou7a337042021-07-26 21:05:21 -0700220
221 clean_up:
222 if (fp)
223 {
224 fclose(fp);
225 }
226 EVP_PKEY_free(pkey);
227 RSA_free(rsa);
228 RSA_free(pub_rsa);
229 BIO_free(bio);
230 return rv;
231 }
232
233#ifdef __cplusplus
234} // extern "C"
235#endif