blob: 6dddf23c6f9ea13e48567a910002e77026c0ca73 [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 */
William A. Kennington III5acaca22021-10-28 16:32:33 -070016#include <libcr51sign/libcr51sign_support.h>
William A. Kennington IIIdeb55012021-10-28 17:12:23 -070017#include <openssl/err.h>
Nan Zhou7a337042021-07-26 21:05:21 -070018#include <openssl/evp.h>
19#include <openssl/pem.h>
20#include <openssl/rsa.h>
21#include <stdio.h>
22#include <string.h>
23
24#ifdef __cplusplus
25extern "C"
26{
27#endif
28
William A. Kennington IIIdeb55012021-10-28 17:12:23 -070029#ifndef USER_PRINT
30#define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
31#endif
32
Nan Zhou7a337042021-07-26 21:05:21 -070033 // @func hash_init get ready to compute a hash
34 //
35 // @param[in] ctx - context struct
36 // @param[in] hash_type - type of hash function to use
37 //
38 // @return nonzero on error, zero on success
39
40 int hash_init(const void* ctx, enum hash_type type)
41 {
42 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
43 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
44 hash_context->hash_type = type;
45 if (type == HASH_SHA2_256) // SHA256_Init returns 1
46 SHA256_Init(&hash_context->sha256_ctx);
47 else if (type == HASH_SHA2_512)
48 SHA512_Init(&hash_context->sha512_ctx);
49 else
50 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
51
52 return LIBCR51SIGN_SUCCESS;
53 }
54
55 // @func hash_update add data to the hash
56 //
57 // @param[in] ctx - context struct
58 // @param[in] buf - data to add to hash
59 // @param[in] count - number of bytes of data to add
60 //
61 // @return nonzero on error, zero on success
62
63 int hash_update(void* ctx, const uint8_t* data, size_t size)
64 {
65 if (size == 0)
66 return LIBCR51SIGN_SUCCESS;
67 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
68 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
69
70 if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
71 SHA256_Update(&hash_context->sha256_ctx, data, size);
72 else if (hash_context->hash_type == HASH_SHA2_512)
73 SHA512_Update(&hash_context->sha512_ctx, data, size);
74 else
75 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
76
77 return LIBCR51SIGN_SUCCESS;
78 }
79
80 // @func hash_final finish hash calculation
81 //
82 // @param[in] ctx - context struct
83 // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
84 //
85 // @return nonzero on error, zero on success
86
87 int hash_final(void* ctx, uint8_t* hash)
88 {
89 int rv;
90 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
91 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
92
93 if (hash_context->hash_type == HASH_SHA2_256)
94 rv = SHA256_Final(hash, &hash_context->sha256_ctx);
95 else if (hash_context->hash_type == HASH_SHA2_512)
96 rv = SHA512_Final(hash, &hash_context->sha512_ctx);
97 else
98 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
99
100 if (rv)
101 return LIBCR51SIGN_SUCCESS;
102 else
103 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
104 }
105
106 // @func verify check that the signature is valid for given hashed data
107 //
108 // @param[in] ctx - context struct
109 // @param[in] scheme - type of signature, hash, etc.
110 // @param[in] sig - signature blob
111 // @param[in] sig_len - length of signature in bytes
112 // @param[in] data - pre-hashed data to verify
113 // @param[in] data_len - length of hashed data in bytes
114 //
115 // verify_signature expects RSA public key file path in ctx->key_ring
116 // @return nonzero on error, zero on success
117
118 int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
119 const uint8_t* sig, size_t sig_len,
120 const uint8_t* data, size_t data_len)
121 {
122 // By default returns error.
123 int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
124
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800125 CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700126 for (size_t i = 0; i < sig_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700127 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700128 CPRINTS(ctx, "%x", sig[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700129 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800130 CPRINTS(ctx, "\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700131
132 struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
133 FILE* fp = fopen(lctx->keyring, "r");
134 RSA *rsa = NULL, *pub_rsa = NULL;
135 EVP_PKEY* pkey = NULL;
136 BIO* bio = BIO_new(BIO_s_mem());
137 if (!fp)
138 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800139 CPRINTS(ctx, "fopen failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700140 goto clean_up;
141 }
142
143 pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
144 if (!pkey)
145 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800146 CPRINTS(ctx, "Read public key failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700147 goto clean_up;
148 }
149
150 rsa = EVP_PKEY_get1_RSA(pkey);
151 if (!rsa)
152 {
153 goto clean_up;
154 }
155 pub_rsa = RSAPublicKey_dup(rsa);
156 if (!RSA_print(bio, pub_rsa, 2))
157 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800158 CPRINTS(ctx, "RSA print failed\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700159 }
160 if (!pub_rsa)
161 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800162 CPRINTS(ctx, "no pub RSA\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700163 goto clean_up;
164 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800165 CPRINTS(ctx, "public RSA\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700166 char buffer[1024];
167 while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
168 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700169 CPRINTS(ctx, " %s", buffer);
Nan Zhou7a337042021-07-26 21:05:21 -0700170 }
171 enum hash_type hash_type;
172 rv = get_hash_type_from_signature(sig_scheme, &hash_type);
173 if (rv != LIBCR51SIGN_SUCCESS)
174 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800175 CPRINTS(ctx, "Invalid hash_type!\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700176 goto clean_up;
177 }
178 int hash_nid = -1;
179 if (hash_type == HASH_SHA2_256)
180 {
181 hash_nid = NID_sha256;
182 }
183 else if (hash_type == HASH_SHA2_512)
184 {
185 hash_nid = NID_sha512;
186 }
187 else
188 {
189 rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
190 goto clean_up;
191 }
192
193 int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
194 // OpenSSL RSA_verify returns 1 on success and 0 on failure
195 if (!ret)
196 {
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800197 CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700198 ERR_error_string(ERR_get_error(), NULL));
Nan Zhou7a337042021-07-26 21:05:21 -0700199 rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
200 goto clean_up;
201 }
202 rv = LIBCR51SIGN_SUCCESS;
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800203 CPRINTS(ctx, "sig: ");
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700204 for (size_t i = 0; i < sig_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700205 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700206 CPRINTS(ctx, "%x", sig[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700207 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800208 CPRINTS(ctx, "\n");
Nan Zhou7a337042021-07-26 21:05:21 -0700209
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800210 CPRINTS(ctx, "data: ");
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700211 for (size_t i = 0; i < data_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700212 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700213 CPRINTS(ctx, "%x", data[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700214 }
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800215 CPRINTS(ctx, "\n");
216
Nan Zhou7a337042021-07-26 21:05:21 -0700217 const unsigned rsa_size = RSA_size(pub_rsa);
William A. Kennington IIIaf46bea2021-12-18 14:35:45 -0800218 CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
Nan Zhou7a337042021-07-26 21:05:21 -0700219
220 clean_up:
221 if (fp)
222 {
223 fclose(fp);
224 }
225 EVP_PKEY_free(pkey);
226 RSA_free(rsa);
227 RSA_free(pub_rsa);
228 BIO_free(bio);
229 return rv;
230 }
231
232#ifdef __cplusplus
233} // extern "C"
234#endif