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