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