blob: 4e9c517d5bbe07fbd9a247f53fc5430aef5029cb [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 IIIdeb55012021-10-28 17:12:23 -0700125 CPRINTS(ctx, "\n sig_len %zu sig: ", sig_len);
126 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 }
130
131 struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
132 FILE* fp = fopen(lctx->keyring, "r");
133 RSA *rsa = NULL, *pub_rsa = NULL;
134 EVP_PKEY* pkey = NULL;
135 BIO* bio = BIO_new(BIO_s_mem());
136 if (!fp)
137 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700138 CPRINTS(ctx, "\n fopen failed: ");
Nan Zhou7a337042021-07-26 21:05:21 -0700139 goto clean_up;
140 }
141
142 pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
143 if (!pkey)
144 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700145 CPRINTS(ctx, "\n Read public key failed: ");
Nan Zhou7a337042021-07-26 21:05:21 -0700146 goto clean_up;
147 }
148
149 rsa = EVP_PKEY_get1_RSA(pkey);
150 if (!rsa)
151 {
152 goto clean_up;
153 }
154 pub_rsa = RSAPublicKey_dup(rsa);
155 if (!RSA_print(bio, pub_rsa, 2))
156 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700157 CPRINTS(ctx, "\n RSA print failed ");
Nan Zhou7a337042021-07-26 21:05:21 -0700158 }
159 if (!pub_rsa)
160 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700161 CPRINTS(ctx, "\n no pub rsa: ");
Nan Zhou7a337042021-07-26 21:05:21 -0700162 goto clean_up;
163 }
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700164 CPRINTS(ctx, "\n public rsa \n");
Nan Zhou7a337042021-07-26 21:05:21 -0700165 char buffer[1024];
166 while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
167 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700168 CPRINTS(ctx, " %s", buffer);
Nan Zhou7a337042021-07-26 21:05:21 -0700169 }
170 enum hash_type hash_type;
171 rv = get_hash_type_from_signature(sig_scheme, &hash_type);
172 if (rv != LIBCR51SIGN_SUCCESS)
173 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700174 CPRINTS(ctx, "\n Invalid hash_type! \n");
Nan Zhou7a337042021-07-26 21:05:21 -0700175 goto clean_up;
176 }
177 int hash_nid = -1;
178 if (hash_type == HASH_SHA2_256)
179 {
180 hash_nid = NID_sha256;
181 }
182 else if (hash_type == HASH_SHA2_512)
183 {
184 hash_nid = NID_sha512;
185 }
186 else
187 {
188 rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
189 goto clean_up;
190 }
191
192 int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
193 // OpenSSL RSA_verify returns 1 on success and 0 on failure
194 if (!ret)
195 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700196 CPRINTS(ctx, "\n OPENSSL_ERROR: %s \n",
197 ERR_error_string(ERR_get_error(), NULL));
Nan Zhou7a337042021-07-26 21:05:21 -0700198 rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
199 goto clean_up;
200 }
201 rv = LIBCR51SIGN_SUCCESS;
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700202 CPRINTS(ctx, "\n sig: ");
203 for (size_t i = 0; i < sig_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700204 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700205 CPRINTS(ctx, "%x", sig[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700206 }
207
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700208 CPRINTS(ctx, "\n data: ");
209 for (size_t i = 0; i < data_len; i++)
Nan Zhou7a337042021-07-26 21:05:21 -0700210 {
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700211 CPRINTS(ctx, "%x", data[i]);
Nan Zhou7a337042021-07-26 21:05:21 -0700212 }
213 const unsigned rsa_size = RSA_size(pub_rsa);
William A. Kennington IIIdeb55012021-10-28 17:12:23 -0700214 CPRINTS(ctx, "\n rsa size %d sig_len %d", rsa_size, (uint32_t)sig_len);
Nan Zhou7a337042021-07-26 21:05:21 -0700215
216 clean_up:
217 if (fp)
218 {
219 fclose(fp);
220 }
221 EVP_PKEY_free(pkey);
222 RSA_free(rsa);
223 RSA_free(pub_rsa);
224 BIO_free(bio);
225 return rv;
226 }
227
228#ifdef __cplusplus
229} // extern "C"
230#endif