1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <string.h>
13 #include <tee_log.h>
14 #include <rsa/rsa_local.h>
15 #include <openssl/ossl_typ.h>
16 #include <openssl/x509.h>
17 #include <openssl/rsa.h>
18 #include <securec.h>
19 #include "crypto_wrapper.h"
20 #include "crypto_inner_interface.h"
21
22 static uint8_t g_rsa_key_oid[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
23 static uint8_t g_ecc_key_oid[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1 };
24
x509_crl_validate(uint8_t * cert,uint32_t cert_len,uint8_t * parent_key,uint32_t parent_key_len)25 int x509_crl_validate(uint8_t *cert, uint32_t cert_len, uint8_t *parent_key, uint32_t parent_key_len)
26 {
27 X509_CRL *cert_x509 = NULL;
28 EVP_PKEY *pkey = NULL;
29 int ret = -1;
30
31 if (cert == NULL || parent_key == NULL)
32 return -1;
33
34 cert_x509 = d2i_X509_CRL(NULL, (const uint8_t **)(&cert), (long)cert_len);
35 if (cert_x509 == NULL) {
36 tloge("d2i cert failed");
37 goto error;
38 }
39
40 pkey = d2i_PUBKEY(&pkey, (const unsigned char **)(&parent_key), parent_key_len);
41 if (pkey == NULL) {
42 tloge("d2i pubkey failed");
43 goto error;
44 }
45
46 ret = X509_CRL_verify(cert_x509, pkey);
47 error:
48 X509_CRL_free(cert_x509);
49 EVP_PKEY_free(pkey);
50
51 return ret;
52 }
x509_cert_validate(uint8_t * cert,uint32_t cert_len,uint8_t * parent_key,uint32_t parent_key_len)53 int x509_cert_validate(uint8_t *cert, uint32_t cert_len, uint8_t *parent_key, uint32_t parent_key_len)
54 {
55 X509 *cert_x509 = NULL;
56 EVP_PKEY *pkey = NULL;
57 int ret = -1;
58
59 if (cert == NULL || parent_key == NULL)
60 return -1;
61
62 cert_x509 = d2i_X509(NULL, (const unsigned char **)(&cert), (long)cert_len);
63 if (cert_x509 == NULL) {
64 tloge("d2i cert failed");
65 goto error;
66 }
67
68 pkey = d2i_PUBKEY(&pkey, (const unsigned char **)(&parent_key), (long)parent_key_len);
69 if (pkey == NULL) {
70 tloge("d2i pubkey failed");
71 goto error;
72 }
73
74 ret = X509_verify(cert_x509, pkey);
75
76 error:
77 X509_free(cert_x509);
78 EVP_PKEY_free(pkey);
79
80 return ret;
81 }
82
get_keytype_from_sp(const uint8_t * in,uint32_t inlen)83 int get_keytype_from_sp(const uint8_t *in, uint32_t inlen)
84 {
85 int tag = 0;
86 int class;
87 long tmplen = (long)inlen;
88 const uint8_t *end = in + inlen;
89
90 if (in == NULL)
91 return -1;
92
93 (void)ASN1_get_object(&in, &tmplen, &tag, &class, end - in);
94 if (tag != V_ASN1_SEQUENCE) {
95 tloge("tag1 invalid type");
96 return -1;
97 }
98
99 tag = 0;
100 end = in + tmplen;
101 (void)ASN1_get_object(&in, &tmplen, &tag, &class, end - in);
102 if (tag != V_ASN1_SEQUENCE) {
103 tloge("tag2 invalid type");
104 return -1;
105 }
106
107 tag = 0;
108 end = in + tmplen;
109 (void)ASN1_get_object(&in, &tmplen, &tag, &class, end - in);
110 if (tag != V_ASN1_OBJECT) {
111 tloge("tag1 invalid type");
112 return -1;
113 }
114
115 if ((tmplen == (long)sizeof(g_rsa_key_oid)) && (memcmp(in, g_rsa_key_oid, tmplen) == 0))
116 return RSA_ALG;
117 if ((tmplen == (long)sizeof(g_ecc_key_oid)) && (memcmp(in, g_ecc_key_oid, tmplen) == 0))
118 return ECC_ALG;
119
120 /* It is not RSA nor ECC key */
121 return -1;
122 }
123
ecc_nid_boringssl2tom(uint32_t nid)124 static int ecc_nid_boringssl2tom(uint32_t nid)
125 {
126 uint32_t index = 0;
127 crypto_u2u nid_tom_to_boring[] = {
128 { NID_X9_62_prime192v1, NIST_P192 }, { NID_secp224r1, NIST_P224 }, { NID_X9_62_prime256v1, NIST_P256 },
129 { NID_secp384r1, NIST_P384 }, { NID_secp521r1, NIST_P521 },
130 };
131 for (; index < sizeof(nid_tom_to_boring) / sizeof(crypto_u2u); index++) {
132 if (nid == nid_tom_to_boring[index].src)
133 return nid_tom_to_boring[index].dest;
134 }
135 tloge("invalid nid 0x%x\n", nid);
136 return -1;
137 }
138
get_rsa_pub_from_cert(rsa_pub_key_t * rsa_pub,const uint8_t * in,uint32_t inlen)139 static int get_rsa_pub_from_cert(rsa_pub_key_t *rsa_pub, const uint8_t *in, uint32_t inlen)
140 {
141 RSA *rsa = NULL;
142 uint32_t n_len, e_len;
143 rsa = d2i_RSA_PUBKEY(NULL, &in, inlen);
144 if (rsa == NULL) {
145 tloge("d2i rsa pubkey failed");
146 return -1;
147 }
148
149 bool check = (rsa->e == NULL || rsa->n == NULL);
150 if (check) {
151 tloge("n or e is NULL");
152 RSA_free(rsa);
153 return -1;
154 }
155
156 n_len = (uint32_t)BN_num_bytes(rsa->n);
157 e_len = (uint32_t)BN_num_bytes(rsa->e);
158 if (n_len > sizeof(rsa_pub->n) || e_len > sizeof(rsa_pub->e)) {
159 tloge("pub key buffer too small");
160 RSA_free(rsa);
161 return -1;
162 }
163
164 rsa_pub->n_len = (uint32_t)BN_bn2bin(rsa->n, rsa_pub->n);
165 rsa_pub->e_len = (uint32_t)BN_bn2bin(rsa->e, rsa_pub->e);
166
167 RSA_free(rsa);
168 return 0;
169 }
170
get_ecc_pub_from_cert_helper(ecc_pub_key_t * ecc_pub,const EC_GROUP * group,const EC_POINT * point)171 static int get_ecc_pub_from_cert_helper(ecc_pub_key_t *ecc_pub, const EC_GROUP *group, const EC_POINT *point)
172 {
173 BIGNUM *x = NULL;
174 BIGNUM *y = NULL;
175 BN_CTX *ctx = NULL;
176 int ret = -1;
177
178 x = BN_new();
179 y = BN_new();
180 ctx = BN_CTX_new();
181 if (x == NULL || y == NULL || ctx == NULL) {
182 tloge("all bn ctx failed");
183 goto clean;
184 }
185
186 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) {
187 tloge("all bn ctx failed");
188 goto clean;
189 }
190
191 if ((uint32_t)BN_num_bytes(x) <= sizeof(ecc_pub->x) && (uint32_t)BN_num_bytes(y) <= sizeof(ecc_pub->y)) {
192 ecc_pub->x_len = (uint32_t)BN_bn2bin(x, ecc_pub->x);
193 ecc_pub->y_len = (uint32_t)BN_bn2bin(y, ecc_pub->y);
194 ret = 0;
195 } else {
196 tloge("ec pub buffer too small");
197 }
198
199 clean:
200 BN_free(x);
201 BN_free(y);
202 BN_CTX_free(ctx);
203
204 return ret;
205 }
206
get_ecc_pub_from_cert(ecc_pub_key_t * ecc_pub,const uint8_t * in,uint32_t inlen)207 static int get_ecc_pub_from_cert(ecc_pub_key_t *ecc_pub, const uint8_t *in, uint32_t inlen)
208 {
209 EC_KEY *ec_key = NULL;
210 const EC_GROUP *group = NULL;
211 const EC_POINT *point = NULL;
212 int ret = -1;
213
214 ec_key = d2i_EC_PUBKEY(NULL, &in, inlen);
215 if (ec_key == NULL) {
216 tloge("d2i ec pub failed");
217 return -1;
218 }
219
220 group = EC_KEY_get0_group(ec_key);
221 if (group == NULL) {
222 tloge("get ec group failed");
223 goto clean;
224 }
225
226 ret = ecc_nid_boringssl2tom(EC_GROUP_get_curve_name(group));
227 if (ret < 0) {
228 tloge("get ec group failed");
229 goto clean;
230 }
231 ecc_pub->domain = (uint32_t)ret;
232
233 point = EC_KEY_get0_public_key(ec_key);
234 if (point == NULL) {
235 tloge("get ec group failed");
236 goto clean;
237 }
238
239 ret = get_ecc_pub_from_cert_helper(ecc_pub, group, point);
240 clean:
241 EC_KEY_free(ec_key);
242
243 return ret;
244 }
245
import_pub_from_sp(void * pub,const uint8_t * in,uint32_t inlen)246 int import_pub_from_sp(void *pub, const uint8_t *in, uint32_t inlen)
247 {
248 int32_t ret;
249 uint32_t keytype;
250
251 if (pub == NULL || in == NULL) {
252 tloge("invalid args");
253 return -1;
254 }
255
256 ret = get_keytype_from_sp(in, inlen);
257 if (ret < 0) {
258 tloge("get key type failed");
259 return -1;
260 }
261
262 keytype = (uint32_t)ret;
263 switch (keytype) {
264 case RSA_ALG:
265 return get_rsa_pub_from_cert(pub, in, inlen);
266 case ECC_ALG:
267 return get_ecc_pub_from_cert(pub, in, inlen);
268 default: /* Keytype not supported */
269 tloge("invalid key type");
270 return -1;
271 }
272 }
273
public_get_subject_public_key(uint8_t * pub,uint32_t pub_size,bool check_size,const uint8_t * cert,uint32_t cert_len)274 static int public_get_subject_public_key(uint8_t *pub, uint32_t pub_size,
275 bool check_size, const uint8_t *cert, uint32_t cert_len)
276 {
277 X509 *cert_x509 = NULL;
278 int len = -1;
279 EVP_PKEY *pkey = NULL;
280
281 if (pub == NULL || cert == NULL)
282 return -1;
283
284 cert_x509 = d2i_X509(NULL, (const unsigned char **)(&cert), cert_len);
285 if (cert_x509 == NULL) {
286 tloge("d2i x509 cert failed");
287 goto clean;
288 }
289
290 pkey = X509_get_pubkey(cert_x509);
291 if (pkey == NULL) {
292 tloge("x509 get pubkey failed");
293 goto clean;
294 }
295
296 if (check_size) {
297 int pub_len;
298
299 pub_len = i2d_PUBKEY(pkey, NULL);
300 if ((uint32_t)pub_len > pub_size) {
301 tloge("invalid pub size, %d", pub_len);
302 goto clean;
303 }
304 }
305
306 len = i2d_PUBKEY(pkey, &pub);
307
308 clean:
309 EVP_PKEY_free(pkey);
310 X509_free(cert_x509);
311
312 return len;
313 }
314
get_subject_public_key_new(uint8_t * pub,uint32_t pub_size,const uint8_t * cert,uint32_t cert_len)315 int get_subject_public_key_new(uint8_t *pub, uint32_t pub_size, const uint8_t *cert, uint32_t cert_len)
316 {
317 return public_get_subject_public_key(pub, pub_size, true, cert, cert_len);
318 }
319
320 /* this is not safe, but it's an export API */
get_subject_public_key(uint8_t * pub,const uint8_t * cert,uint32_t cert_len)321 int get_subject_public_key(uint8_t *pub, const uint8_t *cert, uint32_t cert_len)
322 {
323 return public_get_subject_public_key(pub, 0, false, cert, cert_len);
324 }
325
get_validity_from_cert(validity_period_t * vd,uint8_t * cert,uint32_t cert_len)326 int get_validity_from_cert(validity_period_t *vd, uint8_t *cert, uint32_t cert_len)
327 {
328 X509 *cert_x509 = NULL;
329 ASN1_STRING *time = NULL;
330 int ret = -1;
331
332 if (vd == NULL || cert == NULL) {
333 tloge("invalid args");
334 return -1;
335 }
336
337 cert_x509 = d2i_X509(NULL, (const unsigned char **)(&cert), cert_len);
338 if (cert_x509 == NULL) {
339 tloge("d2i x509 cert failed");
340 goto clean;
341 }
342
343 time = X509_get_notBefore(cert_x509);
344 if (memcpy_s(vd->start, sizeof(vd->start), ASN1_STRING_data(time), ASN1_STRING_length(time))) {
345 tloge("copy start time failed");
346 goto clean;
347 }
348
349 time = X509_get_notAfter(cert_x509);
350 if (memcpy_s(vd->end, sizeof(vd->end), ASN1_STRING_data(time), ASN1_STRING_length(time))) {
351 tloge("copy end time failed");
352 goto clean;
353 }
354
355 ret = 0;
356
357 clean:
358 X509_free(cert_x509);
359
360 return ret;
361 }
362
get_subject_by_name(uint8_t * buff,uint32_t len,const char * name,const uint8_t * cert,uint32_t cert_len)363 static int get_subject_by_name(uint8_t *buff, uint32_t len, const char *name, const uint8_t *cert, uint32_t cert_len)
364 {
365 X509 *cert_x509 = NULL;
366 X509_NAME *x_name = NULL;
367 ASN1_OBJECT *asn1_obj = NULL;
368 int ret = -1;
369
370 if (buff == NULL || cert == NULL)
371 return -1;
372
373 cert_x509 = d2i_X509(NULL, (const unsigned char **)(&cert), cert_len);
374 if (cert_x509 == NULL) {
375 tloge("d2i x509 cert failed");
376 goto clean;
377 }
378
379 x_name = X509_get_subject_name(cert_x509);
380 if (x_name == NULL) {
381 tloge("x509 get subject name failed");
382 goto clean;
383 }
384
385 asn1_obj = OBJ_txt2obj(name, 0);
386 if (asn1_obj == NULL) {
387 tloge("c2i asn1 obj failed");
388 goto clean;
389 }
390
391 ret = X509_NAME_get_text_by_OBJ(x_name, asn1_obj, (char *)buff, (int)len);
392 if (ret < 0) {
393 tloge("x509 get text by obj failed");
394 goto clean;
395 }
396
397 clean:
398 ASN1_OBJECT_free(asn1_obj);
399 X509_free(cert_x509);
400
401 return ret;
402 }
403
get_subject_x509_cn(uint8_t * name,uint32_t name_size,const uint8_t * cert,uint32_t cert_len)404 int get_subject_x509_cn(uint8_t *name, uint32_t name_size, const uint8_t *cert, uint32_t cert_len)
405 {
406 return get_subject_by_name(name, name_size, "CN", cert, cert_len);
407 }
408
get_subject_CN(uint8_t * name,uint32_t name_size,const uint8_t * cert,uint32_t cert_len)409 int get_subject_CN(uint8_t *name, uint32_t name_size, const uint8_t *cert, uint32_t cert_len)
410 {
411 return get_subject_x509_cn(name, name_size, cert, cert_len);
412 }
413
get_subject_x509_ou(uint8_t * name,uint32_t name_size,const uint8_t * cert,uint32_t cert_len)414 int get_subject_x509_ou(uint8_t *name, uint32_t name_size, const uint8_t *cert, uint32_t cert_len)
415 {
416 return get_subject_by_name(name, name_size, "OU", cert, cert_len);
417 }
418
get_subject_OU(uint8_t * name,uint32_t name_size,const uint8_t * cert,uint32_t cert_len)419 int get_subject_OU(uint8_t *name, uint32_t name_size, const uint8_t *cert, uint32_t cert_len)
420 {
421 return get_subject_x509_ou(name, name_size, cert, cert_len);
422 }
423
get_serial_number_from_cert(uint8_t * serial_number,uint32_t serial_number_size,uint8_t * cert,uint32_t cert_len)424 int get_serial_number_from_cert(uint8_t *serial_number, uint32_t serial_number_size, uint8_t *cert, uint32_t cert_len)
425 {
426 X509 *cert_x509 = NULL;
427 ASN1_INTEGER *asn1_serial = NULL;
428 int serial_len;
429 int ret = -1;
430
431 if (serial_number == NULL || cert == NULL)
432 return -1;
433
434 cert_x509 = d2i_X509(NULL, (const unsigned char **)(&cert), (long)cert_len);
435 if (cert_x509 == NULL) {
436 tloge("d2i x509 cert failed");
437 goto clean;
438 }
439
440 asn1_serial = X509_get_serialNumber(cert_x509);
441 if (asn1_serial == NULL) {
442 tloge("get serial num failed");
443 goto clean;
444 }
445
446 serial_len = i2d_ASN1_INTEGER(asn1_serial, NULL);
447 if ((uint32_t)serial_len > serial_number_size) {
448 tloge("serial buffer too small, %u/%d", serial_number_size, serial_len);
449 goto clean;
450 }
451
452 ret = i2d_ASN1_INTEGER(asn1_serial, &serial_number);
453
454 clean:
455 X509_free(cert_x509);
456
457 return ret;
458 }
459
get_issuer_from_cert(uint8_t * issuer,uint32_t issuer_size,uint8_t * crl,uint32_t crl_len)460 int get_issuer_from_cert(uint8_t *issuer, uint32_t issuer_size, uint8_t *crl, uint32_t crl_len)
461 {
462 X509 *crl_x509 = NULL;
463 X509_NAME *x_name = NULL;
464 int ret = -1;
465 int issuer_len;
466
467 if (issuer == NULL || crl == NULL)
468 return -1;
469
470 crl_x509 = d2i_X509(NULL, (const unsigned char **)(&crl), (long)crl_len);
471 if (crl_x509 == NULL) {
472 tloge("d2i x509 cert failed");
473 goto clean;
474 }
475
476 x_name = X509_get_issuer_name(crl_x509);
477 if (x_name == NULL) {
478 tloge("get issuer failed");
479 goto clean;
480 }
481
482 issuer_len = i2d_X509_NAME(x_name, NULL);
483 if ((uint32_t)issuer_len > issuer_size) {
484 tloge("crl len too small, %d/%u", issuer_len, issuer_size);
485 goto clean;
486 }
487
488 ret = i2d_X509_NAME(x_name, &issuer);
489 clean:
490 X509_free(crl_x509);
491
492 return ret;
493 }
494