• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  *
4  * This software may be distributed under the terms of the BSD license.
5  * See README for more details.
6  */
7 
8 #include "wpa_evp_key.h"
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <crypto/evp.h>
13 #include <crypto/x509.h>
14 #include <openssl/asn1.h>
15 #include <openssl/crypto.h>
16 #include <openssl/engine.h>
17 #include <openssl/ossl_typ.h>
18 #include <openssl/rsa.h>
19 #include <openssl/x509.h>
20 
21 #include "cert_manager_api.h"
22 #include "common.h"
23 
24 static char g_key_uri[MAX_LEN_URI];
25 
cm_sign(const struct CmBlob * keyUri,const struct CmBlob * message,struct CmBlob * signature,struct CmSignatureSpec * spec)26 static int cm_sign(const struct CmBlob *keyUri, const struct CmBlob *message, struct CmBlob *signature,
27     struct CmSignatureSpec *spec)
28 {
29     int32_t ret;
30     uint64_t handleValue = 0;
31     struct CmBlob handle = { sizeof(uint64_t), (uint8_t *)&handleValue };
32 
33     ret = CmInit(keyUri, spec, &handle);
34     if (ret != CM_SUCCESS) {
35         wpa_printf(MSG_DEBUG, "sign CmInit failed");
36         return 0;
37     }
38 
39     ret = CmUpdate(&handle, message);
40     if (ret != CM_SUCCESS) {
41         wpa_printf(MSG_DEBUG, "sign CmUpdate failed");
42         return 0;
43     }
44 
45     struct CmBlob inDataFinish = { 0, NULL };
46     ret = CmFinish(&handle, &inDataFinish, signature);
47     if (ret != CM_SUCCESS) {
48         wpa_printf(MSG_DEBUG, "sign CmFinish failed");
49         return 0;
50     }
51 
52     ret = CmAbort(&handle);
53     if (ret != CM_SUCCESS) {
54         wpa_printf(MSG_DEBUG, "sign CmAbort failed");
55     }
56     return 1;
57 }
58 
rsa_sign(int type,const unsigned char * m,unsigned int m_length,unsigned char * sigret,unsigned int * siglen,const RSA * rsa)59 int rsa_sign(int type, const unsigned char *m, unsigned int m_length,
60     unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
61 {
62     int ret;
63     struct CmBlob keyUri = { sizeof(g_key_uri), (uint8_t *)g_key_uri };
64     struct CmBlob message = { m_length, (uint8_t *)m };
65     uint8_t signData[DEFAULT_SIGNATURE_LEN] = { 0 };
66     struct CmBlob signature = { DEFAULT_SIGNATURE_LEN, (uint8_t *)signData };
67     struct CmSignatureSpec spec = { CM_KEY_PURPOSE_SIGN, CM_PADDING_PKCS1_V1_5, CM_DIGEST_NONE };
68 
69     wpa_printf(MSG_DEBUG, "%s type:%d m:%d m_len:%u", __func__, type, m == NULL, m_length);
70     ret = cm_sign(&keyUri, &message, &signature, &spec);
71     if (ret && signature.size > 0) {
72         *siglen = signature.size;
73         os_memcpy(sigret, signature.data, signature.size);
74         wpa_printf(MSG_INFO, "%s sign len:%u", __func__, signature.size);
75         return 1;
76     }
77     return 0;
78 }
79 
rsa_priv_enc(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)80 int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
81 {
82     int ret;
83     struct CmBlob keyUri = { sizeof(g_key_uri), (uint8_t *)g_key_uri };
84     struct CmBlob message = { flen, (uint8_t *)from };
85     uint8_t signData[DEFAULT_SIGNATURE_LEN] = { 0 };
86     struct CmBlob signature = { DEFAULT_SIGNATURE_LEN, (uint8_t *)signData };
87     if (padding != 3) { // openssl: RSA_NO_PADDING 3
88         wpa_printf(MSG_ERROR, "%s unsupport padding: %d", __func__, padding);
89         return -1;
90     }
91     struct CmSignatureSpec spec = { CM_KEY_PURPOSE_SIGN, CM_PADDING_NONE, CM_DIGEST_NONE };
92 
93     ret = cm_sign(&keyUri, &message, &signature, &spec);
94     if (ret && signature.size > 0) {
95         os_memcpy(to, signature.data, signature.size);
96         wpa_printf(MSG_INFO, "%s sign len:%u", __func__, signature.size);
97         return signature.size;
98     }
99     return -1;
100 }
101 
ec_sign(int type,const unsigned char * dgst,int dlen,unsigned char * sig,unsigned int * siglen,const BIGNUM * kinv,const BIGNUM * r,EC_KEY * eckey)102 int ec_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
103     unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
104 {
105     int ret;
106     struct CmBlob keyUri = { sizeof(g_key_uri), (uint8_t *)g_key_uri };
107     struct CmBlob message = { dlen, (uint8_t *)dgst };
108     uint8_t signData[DEFAULT_SIGNATURE_LEN] = { 0 };
109     struct CmBlob signature = { DEFAULT_SIGNATURE_LEN, (uint8_t *)signData };
110     struct CmSignatureSpec spec = { CM_KEY_PURPOSE_SIGN, CM_PADDING_NONE, CM_DIGEST_NONE };
111 
112     ret = cm_sign(&keyUri, &message, &signature, &spec);
113     if (ret && signature.size > 0) {
114         *siglen = signature.size;
115         os_memcpy(sig, signature.data, signature.size);
116         wpa_printf(MSG_INFO, "%s sign len:%u", __func__, signature.size);
117         return 1;
118     }
119     return 0;
120 }
121 
wrap_rsa(const char * key_id,const RSA * public_rsa)122 static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa)
123 {
124     RSA *rsa = RSA_new();
125     if (rsa == NULL) {
126         wpa_printf(MSG_ERROR, "%s rsa new fail", __func__);
127         return NULL;
128     }
129     RSA_METHOD *rsa_method = RSA_meth_new("", 0);
130     if (rsa_method == NULL) {
131         wpa_printf(MSG_ERROR, "%s rsa_method new fail", __func__);
132         RSA_free(rsa);
133         return NULL;
134     }
135     if (!RSA_meth_set_sign(rsa_method, rsa_sign) ||
136         !RSA_meth_set_priv_enc(rsa_method, rsa_priv_enc) ||
137         !RSA_set_method(rsa, rsa_method)) {
138         wpa_printf(MSG_ERROR, "%s rsa_method or rsa set fail", __func__);
139         RSA_free(rsa);
140         RSA_meth_free(rsa_method);
141         return NULL;
142     }
143     if (!RSA_set0_key(rsa, (BIGNUM *)RSA_get0_n(public_rsa), (BIGNUM *)RSA_get0_e(public_rsa), NULL)) {
144         wpa_printf(MSG_ERROR, "%s RSA_set0_key() failed", __func__);
145         RSA_free(rsa);
146         RSA_meth_free(rsa_method);
147         return NULL;
148     }
149     EVP_PKEY *result = EVP_PKEY_new();
150     if (result != NULL && !EVP_PKEY_assign_RSA(result, rsa)) {
151         wpa_printf(MSG_ERROR, "%s assign rsa fail", __func__);
152         RSA_free(rsa);
153         RSA_meth_free(rsa_method);
154         EVP_PKEY_free(result);
155         return NULL;
156     }
157     os_memset(g_key_uri, 0, sizeof(g_key_uri));
158     if (strlen(key_id) < sizeof(g_key_uri))
159         os_memcpy(g_key_uri, key_id, strlen(key_id));
160     return result;
161 }
162 
wrap_ec(const char * key_id,EC_KEY * public_ec)163 static EVP_PKEY *wrap_ec(const char *key_id, EC_KEY *public_ec)
164 {
165     EC_KEY_METHOD *ec_method = EC_KEY_METHOD_new(ec_method);
166     if (ec_method == NULL) {
167         wpa_printf(MSG_ERROR, "%s ec_method new fail", __func__);
168         return NULL;
169     }
170     EC_KEY_METHOD_set_sign(ec_method, ec_sign, NULL, NULL);
171     EC_KEY_set_method(public_ec, ec_method);
172 
173     EVP_PKEY *result = EVP_PKEY_new();
174     if (result != NULL && !EVP_PKEY_assign_EC_KEY(result, public_ec)) {
175         wpa_printf(MSG_ERROR, "%s assign ec fail", __func__);
176         EC_KEY_METHOD_free(ec_method);
177         EVP_PKEY_free(result);
178         return NULL;
179     }
180 
181     os_memset(g_key_uri, 0, sizeof(g_key_uri));
182     if (strlen(key_id) < sizeof(g_key_uri))
183         os_memcpy(g_key_uri, key_id, strlen(key_id));
184     return result;
185 }
186 
get_pubkey(const char * key_id)187 static EVP_PKEY* get_pubkey(const char *key_id)
188 {
189     struct Credential certificate = { 0 };
190     certificate.credData.data = (uint8_t *)malloc(MAX_LEN_CERTIFICATE_CHAIN);
191     if (certificate.credData.data == NULL) {
192         wpa_printf(MSG_ERROR, "%s malloc certificate.credData.data fail", __func__);
193         return NULL;
194     }
195 
196     BIO* bio = BIO_from_cm(key_id, certificate);
197     if (bio == NULL) {
198         wpa_printf(MSG_ERROR, "%s bio is null", __func__);
199         if (certificate.credData.data != NULL) {
200             free(certificate.credData.data);
201         }
202         return NULL;
203     }
204 
205     X509 *decoded_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
206 
207     if (certificate.credData.data != NULL) {
208         free(certificate.credData.data);
209     }
210 
211     if (decoded_cert == NULL) {
212         wpa_printf(MSG_ERROR, "%s decoded cert is null", __func__);
213         return NULL;
214     }
215     return X509_get_pubkey(decoded_cert);
216 }
217 
GET_EVP_PKEY(const char * key_id)218 EVP_PKEY *GET_EVP_PKEY(const char *key_id)
219 {
220     int key_type;
221     EVP_PKEY *wrap_key = NULL;
222     EVP_PKEY *pub_key = NULL;
223 
224     if (key_id == NULL) {
225         wpa_printf(MSG_ERROR, "key id is NULL");
226         return NULL;
227     }
228     pub_key = get_pubkey(key_id);
229     if (pub_key == NULL) {
230         wpa_printf(MSG_ERROR, "pub key is NULL");
231         return NULL;
232     }
233 
234     key_type = EVP_PKEY_type(pub_key->type);
235 
236     if (key_type == EVP_PKEY_RSA) {
237         const RSA *public_rsa = EVP_PKEY_get0_RSA(pub_key);
238         if (public_rsa == NULL ) {
239             wpa_printf(MSG_ERROR, "public_rsa is NULL");
240             EVP_PKEY_free(pub_key);
241             return NULL;
242         }
243         wrap_key = wrap_rsa(key_id, public_rsa);
244         EVP_PKEY_free(pub_key);
245         return wrap_key;
246     } else if (key_type == EVP_PKEY_EC) {
247         EC_KEY *ec_key = (EC_KEY *)EVP_PKEY_get0_EC_KEY(pub_key);
248         if (ec_key == NULL) {
249             wpa_printf(MSG_ERROR, "ec_key is NULL");
250             EVP_PKEY_free(pub_key);
251             return NULL;
252         }
253         wrap_key = wrap_ec(key_id, ec_key);
254         EVP_PKEY_free(pub_key);
255         return wrap_key;
256     }
257     wpa_printf(MSG_ERROR, "unsupported key type:%d", key_type);
258     EVP_PKEY_free(pub_key);
259     return NULL;
260 }
261 
BIO_from_cm(const char * key_id,struct Credential certificate)262 BIO *BIO_from_cm(const char *key_id, struct Credential certificate)
263 {
264     BIO *bio = NULL;
265     uint32_t store = CM_PRI_CREDENTIAL_STORE;
266     if (os_strncmp(key_id, "oh:t=sk", 7) == 0) {
267         store = CM_SYS_CREDENTIAL_STORE;
268     }
269     struct CmBlob keyUri;
270 
271     if (key_id == NULL) {
272         wpa_printf(MSG_ERROR, "key id is NULL");
273         return NULL;
274     }
275     keyUri.size = strlen(key_id) + 1;
276     keyUri.data = (uint8_t *)key_id;
277 
278     certificate.credData.size = MAX_LEN_CERTIFICATE_CHAIN;
279     int ret = CmGetAppCert(&keyUri, store, &certificate);
280     if (ret != 0) {
281         wpa_printf(MSG_ERROR, "%s key:%s, size:%u, ret:%d", __func__,
282             key_id, certificate.credData.size, ret);
283         return bio;
284     }
285 
286     wpa_printf(MSG_DEBUG, "%s key:%s, size:%u", __func__,
287             key_id, certificate.credData.size);
288 
289     if (certificate.credData.size > 0)
290         bio = BIO_new_mem_buf(certificate.credData.data, certificate.credData.size);
291 
292     return bio;
293 }
294