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