blob: 81f05c53c96e54d6976f23a23a0a02c41d7448ce [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>
Nan Zhou7a337042021-07-26 21:05:21 -070017#include <openssl/evp.h>
18#include <openssl/pem.h>
19#include <openssl/rsa.h>
20#include <stdio.h>
21#include <string.h>
22
23#ifdef __cplusplus
24extern "C"
25{
26#endif
27
28 // @func hash_init get ready to compute a hash
29 //
30 // @param[in] ctx - context struct
31 // @param[in] hash_type - type of hash function to use
32 //
33 // @return nonzero on error, zero on success
34
35 int hash_init(const void* ctx, enum hash_type type)
36 {
37 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
38 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
39 hash_context->hash_type = type;
40 if (type == HASH_SHA2_256) // SHA256_Init returns 1
41 SHA256_Init(&hash_context->sha256_ctx);
42 else if (type == HASH_SHA2_512)
43 SHA512_Init(&hash_context->sha512_ctx);
44 else
45 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
46
47 return LIBCR51SIGN_SUCCESS;
48 }
49
50 // @func hash_update add data to the hash
51 //
52 // @param[in] ctx - context struct
53 // @param[in] buf - data to add to hash
54 // @param[in] count - number of bytes of data to add
55 //
56 // @return nonzero on error, zero on success
57
58 int hash_update(void* ctx, const uint8_t* data, size_t size)
59 {
60 if (size == 0)
61 return LIBCR51SIGN_SUCCESS;
62 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
63 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
64
65 if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
66 SHA256_Update(&hash_context->sha256_ctx, data, size);
67 else if (hash_context->hash_type == HASH_SHA2_512)
68 SHA512_Update(&hash_context->sha512_ctx, data, size);
69 else
70 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
71
72 return LIBCR51SIGN_SUCCESS;
73 }
74
75 // @func hash_final finish hash calculation
76 //
77 // @param[in] ctx - context struct
78 // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
79 //
80 // @return nonzero on error, zero on success
81
82 int hash_final(void* ctx, uint8_t* hash)
83 {
84 int rv;
85 struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
86 struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
87
88 if (hash_context->hash_type == HASH_SHA2_256)
89 rv = SHA256_Final(hash, &hash_context->sha256_ctx);
90 else if (hash_context->hash_type == HASH_SHA2_512)
91 rv = SHA512_Final(hash, &hash_context->sha512_ctx);
92 else
93 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
94
95 if (rv)
96 return LIBCR51SIGN_SUCCESS;
97 else
98 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
99 }
100
101 // @func verify check that the signature is valid for given hashed data
102 //
103 // @param[in] ctx - context struct
104 // @param[in] scheme - type of signature, hash, etc.
105 // @param[in] sig - signature blob
106 // @param[in] sig_len - length of signature in bytes
107 // @param[in] data - pre-hashed data to verify
108 // @param[in] data_len - length of hashed data in bytes
109 //
110 // verify_signature expects RSA public key file path in ctx->key_ring
111 // @return nonzero on error, zero on success
112
113 int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
114 const uint8_t* sig, size_t sig_len,
115 const uint8_t* data, size_t data_len)
116 {
117 // By default returns error.
118 int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
119
120 printf("\n sig_len %zu sig: ", sig_len);
121 for (int i = 0; i < sig_len; i++)
122 {
123 printf("%x", sig[i]);
124 }
125
126 struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
127 FILE* fp = fopen(lctx->keyring, "r");
128 RSA *rsa = NULL, *pub_rsa = NULL;
129 EVP_PKEY* pkey = NULL;
130 BIO* bio = BIO_new(BIO_s_mem());
131 if (!fp)
132 {
133 printf("\n fopen failed: ");
134 goto clean_up;
135 }
136
137 pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
138 if (!pkey)
139 {
140 printf("\n Read public key failed: ");
141 goto clean_up;
142 }
143
144 rsa = EVP_PKEY_get1_RSA(pkey);
145 if (!rsa)
146 {
147 goto clean_up;
148 }
149 pub_rsa = RSAPublicKey_dup(rsa);
150 if (!RSA_print(bio, pub_rsa, 2))
151 {
152 printf("\n RSA print failed ");
153 }
154 if (!pub_rsa)
155 {
156 printf("\n no pub rsa: ");
157 goto clean_up;
158 }
159 printf("\n public rsa \n");
160 char buffer[1024];
161 while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
162 {
163 printf(" %s", buffer);
164 }
165 enum hash_type hash_type;
166 rv = get_hash_type_from_signature(sig_scheme, &hash_type);
167 if (rv != LIBCR51SIGN_SUCCESS)
168 {
169 printf("\n Invalid hash_type! \n");
170 goto clean_up;
171 }
172 int hash_nid = -1;
173 if (hash_type == HASH_SHA2_256)
174 {
175 hash_nid = NID_sha256;
176 }
177 else if (hash_type == HASH_SHA2_512)
178 {
179 hash_nid = NID_sha512;
180 }
181 else
182 {
183 rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
184 goto clean_up;
185 }
186
187 int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
188 // OpenSSL RSA_verify returns 1 on success and 0 on failure
189 if (!ret)
190 {
191 printf("\n OPENSSL_ERROR: %s \n",
192 ERR_error_string(ERR_get_error(), NULL));
193 rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
194 goto clean_up;
195 }
196 rv = LIBCR51SIGN_SUCCESS;
197 printf("\n sig: ");
198 for (int i = 0; i < sig_len; i++)
199 {
200 printf("%x", sig[i]);
201 }
202
203 printf("\n data: ");
204 for (int i = 0; i < data_len; i++)
205 {
206 printf("%x", data[i]);
207 }
208 const unsigned rsa_size = RSA_size(pub_rsa);
209 printf("\n rsa size %d sig_len %d", rsa_size, (uint32_t)sig_len);
210
211 clean_up:
212 if (fp)
213 {
214 fclose(fp);
215 }
216 EVP_PKEY_free(pkey);
217 RSA_free(rsa);
218 RSA_free(pub_rsa);
219 BIO_free(bio);
220 return rv;
221 }
222
223#ifdef __cplusplus
224} // extern "C"
225#endif