xref: /openbmc/google-misc/subprojects/libcr51sign/src/libcr51sign_support.c (revision 5acaca2f8f6eb816a814f0f90d746a6a33d8d926)
1 /*
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/libcr51sign_support.h>
17 #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
24 extern "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
226