]> Git Repo - u-boot.git/blob - lib/mbedtls/x509_cert_parser.c
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sh
[u-boot.git] / lib / mbedtls / x509_cert_parser.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * X509 cert parser using MbedTLS X509 library
4  *
5  * Copyright (c) 2024 Linaro Limited
6  * Author: Raymond Mao <[email protected]>
7  */
8
9 #include <linux/err.h>
10 #include <crypto/public_key.h>
11 #include <crypto/x509_parser.h>
12
13 static void x509_free_mbedtls_ctx(struct x509_cert_mbedtls_ctx *ctx)
14 {
15         if (!ctx)
16                 return;
17
18         kfree(ctx->tbs);
19         kfree(ctx->raw_serial);
20         kfree(ctx->raw_issuer);
21         kfree(ctx->raw_subject);
22         kfree(ctx->raw_skid);
23         kfree(ctx);
24 }
25
26 static int x509_set_cert_flags(struct x509_certificate *cert)
27 {
28         struct public_key_signature *sig = cert->sig;
29
30         if (!sig || !cert->pub) {
31                 pr_err("Signature or public key is not initialized\n");
32                 return -ENOPKG;
33         }
34
35         if (!cert->pub->pkey_algo)
36                 cert->unsupported_key = true;
37
38         if (!sig->pkey_algo)
39                 cert->unsupported_sig = true;
40
41         if (!sig->hash_algo)
42                 cert->unsupported_sig = true;
43
44         /* TODO: is_hash_blacklisted()? */
45
46         /* Detect self-signed certificates and set self_signed flag */
47         return x509_check_for_self_signed(cert);
48 }
49
50 time64_t x509_get_timestamp(const mbedtls_x509_time *x509_time)
51 {
52         unsigned int year, mon, day, hour, min, sec;
53
54         /* Adjust for year since 1900 */
55         year = x509_time->year - 1900;
56         /* Adjust for 0-based month */
57         mon = x509_time->mon - 1;
58         day = x509_time->day;
59         hour = x509_time->hour;
60         min = x509_time->min;
61         sec = x509_time->sec;
62
63         return (time64_t)mktime64(year, mon, day, hour, min, sec);
64 }
65
66 static char *x509_populate_dn_name_string(const mbedtls_x509_name *name)
67 {
68         size_t len = 256;
69         int wb;
70         char *name_str;
71
72         do {
73                 name_str = kzalloc(len, GFP_KERNEL);
74                 if (!name_str)
75                         return NULL;
76
77                 wb = mbedtls_x509_dn_gets(name_str, len, name);
78                 if (wb < 0) {
79                         pr_err("Get DN string failed, ret:-0x%04x\n",
80                                (unsigned int)-wb);
81                         kfree(name_str);
82                         len = len * 2; /* Try with a bigger buffer */
83                 }
84         } while (wb < 0);
85
86         name_str[wb] = '\0'; /* add the terminator */
87
88         return name_str;
89 }
90
91 static int x509_populate_signature_params(const mbedtls_x509_crt *cert,
92                                           struct public_key_signature **sig)
93 {
94         struct public_key_signature *s;
95         struct image_region region;
96         size_t akid_len;
97         unsigned char *akid_data;
98         int ret;
99
100         /* Check if signed data exist */
101         if (!cert->tbs.p || !cert->tbs.len)
102                 return -EINVAL;
103
104         region.data = cert->tbs.p;
105         region.size = cert->tbs.len;
106
107         s = kzalloc(sizeof(*s), GFP_KERNEL);
108         if (!s)
109                 return -ENOMEM;
110
111         /*
112          * Get the public key algorithm.
113          * Note:
114          * ECRDSA (Elliptic Curve Russian Digital Signature Algorithm) is not
115          * supported by MbedTLS.
116          */
117         switch (cert->sig_pk) {
118         case MBEDTLS_PK_RSA:
119                 s->pkey_algo = "rsa";
120                 break;
121         default:
122                 ret = -EINVAL;
123                 goto error_sig;
124         }
125
126         /* Get the hash algorithm */
127         switch (cert->sig_md) {
128         case MBEDTLS_MD_SHA1:
129                 s->hash_algo = "sha1";
130                 s->digest_size = SHA1_SUM_LEN;
131                 break;
132         case MBEDTLS_MD_SHA256:
133                 s->hash_algo = "sha256";
134                 s->digest_size = SHA256_SUM_LEN;
135                 break;
136         case MBEDTLS_MD_SHA384:
137                 s->hash_algo = "sha384";
138                 s->digest_size = SHA384_SUM_LEN;
139                 break;
140         case MBEDTLS_MD_SHA512:
141                 s->hash_algo = "sha512";
142                 s->digest_size = SHA512_SUM_LEN;
143                 break;
144         /* Unsupported algo */
145         case MBEDTLS_MD_MD5:
146         case MBEDTLS_MD_SHA224:
147         default:
148                 ret = -EINVAL;
149                 goto error_sig;
150         }
151
152         /*
153          * Optional attributes:
154          * auth_ids holds AuthorityKeyIdentifier (information of issuer),
155          * aka akid, which is used to match with a cert's id or skid to
156          * indicate that is the issuer when we lookup a cert chain.
157          *
158          * auth_ids[0]:
159          *      [PKCS#7 or CMS ver 1] - generated from "Issuer + Serial number"
160          *      [CMS ver 3] - generated from skid (subjectKeyId)
161          * auth_ids[1]: generated from skid (subjectKeyId)
162          *
163          * Assume that we are using PKCS#7 (msg->version=1),
164          * not CMS ver 3 (msg->version=3).
165          */
166         akid_len = cert->authority_key_id.authorityCertSerialNumber.len;
167         akid_data = cert->authority_key_id.authorityCertSerialNumber.p;
168
169         /* Check if serial number exists */
170         if (akid_len && akid_data) {
171                 s->auth_ids[0] = asymmetric_key_generate_id(akid_data,
172                                                             akid_len,
173                                                             cert->issuer_raw.p,
174                                                             cert->issuer_raw.len);
175                 if (!s->auth_ids[0]) {
176                         ret = -ENOMEM;
177                         goto error_sig;
178                 }
179         }
180
181         akid_len = cert->authority_key_id.keyIdentifier.len;
182         akid_data = cert->authority_key_id.keyIdentifier.p;
183
184         /* Check if subjectKeyId exists */
185         if (akid_len && akid_data) {
186                 s->auth_ids[1] = asymmetric_key_generate_id(akid_data,
187                                                             akid_len,
188                                                             "", 0);
189                 if (!s->auth_ids[1]) {
190                         ret = -ENOMEM;
191                         goto error_sig;
192                 }
193         }
194
195         /*
196          * Encoding can be pkcs1 or raw, but only pkcs1 is supported.
197          * Set the encoding explicitly to pkcs1.
198          */
199         s->encoding = "pkcs1";
200
201         /* Copy the signature data */
202         s->s = kmemdup(cert->sig.p, cert->sig.len, GFP_KERNEL);
203         if (!s->s) {
204                 ret = -ENOMEM;
205                 goto error_sig;
206         }
207         s->s_size = cert->sig.len;
208
209         /* Calculate the digest of signed data (tbs) */
210         s->digest = kzalloc(s->digest_size, GFP_KERNEL);
211         if (!s->digest) {
212                 ret = -ENOMEM;
213                 goto error_sig;
214         }
215
216         ret = hash_calculate(s->hash_algo, &region, 1, s->digest);
217         if (!ret)
218                 *sig = s;
219
220         return ret;
221
222 error_sig:
223         public_key_signature_free(s);
224         return ret;
225 }
226
227 static int x509_save_mbedtls_ctx(const mbedtls_x509_crt *cert,
228                                  struct x509_cert_mbedtls_ctx **pctx)
229 {
230         struct x509_cert_mbedtls_ctx *ctx;
231
232         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
233         if (!ctx)
234                 return -ENOMEM;
235
236         /* Signed data (tbs - The part that is To Be Signed)*/
237         ctx->tbs = kmemdup(cert->tbs.p, cert->tbs.len,
238                            GFP_KERNEL);
239         if (!ctx->tbs)
240                 goto error_ctx;
241
242         /* Raw serial number */
243         ctx->raw_serial = kmemdup(cert->serial.p,
244                                   cert->serial.len, GFP_KERNEL);
245         if (!ctx->raw_serial)
246                 goto error_ctx;
247
248         /* Raw issuer */
249         ctx->raw_issuer = kmemdup(cert->issuer_raw.p,
250                                   cert->issuer_raw.len, GFP_KERNEL);
251         if (!ctx->raw_issuer)
252                 goto error_ctx;
253
254         /* Raw subject */
255         ctx->raw_subject = kmemdup(cert->subject_raw.p,
256                                    cert->subject_raw.len, GFP_KERNEL);
257         if (!ctx->raw_subject)
258                 goto error_ctx;
259
260         /* Raw subjectKeyId */
261         ctx->raw_skid = kmemdup(cert->subject_key_id.p,
262                                 cert->subject_key_id.len, GFP_KERNEL);
263         if (!ctx->raw_skid)
264                 goto error_ctx;
265
266         *pctx = ctx;
267
268         return 0;
269
270 error_ctx:
271         x509_free_mbedtls_ctx(ctx);
272         return -ENOMEM;
273 }
274
275 /*
276  * Free an X.509 certificate
277  */
278 void x509_free_certificate(struct x509_certificate *cert)
279 {
280         if (cert) {
281                 public_key_free(cert->pub);
282                 public_key_signature_free(cert->sig);
283                 kfree(cert->issuer);
284                 kfree(cert->subject);
285                 kfree(cert->id);
286                 kfree(cert->skid);
287                 x509_free_mbedtls_ctx(cert->mbedtls_ctx);
288                 kfree(cert);
289         }
290 }
291
292 int x509_populate_pubkey(mbedtls_x509_crt *cert, struct public_key **pub_key)
293 {
294         struct public_key *pk;
295
296         pk = kzalloc(sizeof(*pk), GFP_KERNEL);
297         if (!pk)
298                 return -ENOMEM;
299
300         pk->key = kzalloc(cert->pk_raw.len, GFP_KERNEL);
301         if (!pk->key) {
302                 kfree(pk);
303                 return -ENOMEM;
304         }
305         memcpy(pk->key, cert->pk_raw.p, cert->pk_raw.len);
306         pk->keylen = cert->pk_raw.len;
307
308         /*
309          * For ECC keys, params field might include information about the curve used,
310          * the generator point, or other algorithm-specific parameters.
311          * For RSA keys, it's common for the params field to be NULL.
312          * FIXME: Assume that we just support RSA keys with id_type X509.
313          */
314         pk->params = NULL;
315         pk->paramlen = 0;
316
317         pk->key_is_private = false;
318         pk->id_type = "X509";
319         pk->pkey_algo = "rsa";
320         pk->algo = OID_rsaEncryption;
321
322         *pub_key = pk;
323
324         return 0;
325 }
326
327 int x509_populate_cert(mbedtls_x509_crt *mbedtls_cert,
328                        struct x509_certificate **pcert)
329 {
330         struct x509_certificate *cert;
331         struct asymmetric_key_id *kid;
332         struct asymmetric_key_id *skid;
333         int ret;
334
335         cert = kzalloc(sizeof(*cert), GFP_KERNEL);
336         if (!cert)
337                 return -ENOMEM;
338
339         /* Public key details */
340         ret = x509_populate_pubkey(mbedtls_cert, &cert->pub);
341         if (ret)
342                 goto error_cert_pop;
343
344         /* Signature parameters */
345         ret = x509_populate_signature_params(mbedtls_cert, &cert->sig);
346         if (ret)
347                 goto error_cert_pop;
348
349         ret = -ENOMEM;
350
351         /* Name of certificate issuer */
352         cert->issuer = x509_populate_dn_name_string(&mbedtls_cert->issuer);
353         if (!cert->issuer)
354                 goto error_cert_pop;
355
356         /* Name of certificate subject */
357         cert->subject = x509_populate_dn_name_string(&mbedtls_cert->subject);
358         if (!cert->subject)
359                 goto error_cert_pop;
360
361         /* Certificate validity */
362         cert->valid_from = x509_get_timestamp(&mbedtls_cert->valid_from);
363         cert->valid_to = x509_get_timestamp(&mbedtls_cert->valid_to);
364
365         /* Save mbedtls context we need */
366         ret = x509_save_mbedtls_ctx(mbedtls_cert, &cert->mbedtls_ctx);
367         if (ret)
368                 goto error_cert_pop;
369
370         /* Signed data (tbs - The part that is To Be Signed)*/
371         cert->tbs = cert->mbedtls_ctx->tbs;
372         cert->tbs_size = mbedtls_cert->tbs.len;
373
374         /* Raw serial number */
375         cert->raw_serial = cert->mbedtls_ctx->raw_serial;
376         cert->raw_serial_size = mbedtls_cert->serial.len;
377
378         /* Raw issuer */
379         cert->raw_issuer = cert->mbedtls_ctx->raw_issuer;
380         cert->raw_issuer_size = mbedtls_cert->issuer_raw.len;
381
382         /* Raw subject */
383         cert->raw_subject = cert->mbedtls_ctx->raw_subject;
384         cert->raw_subject_size = mbedtls_cert->subject_raw.len;
385
386         /* Raw subjectKeyId */
387         cert->raw_skid = cert->mbedtls_ctx->raw_skid;
388         cert->raw_skid_size = mbedtls_cert->subject_key_id.len;
389
390         /* Generate cert issuer + serial number key ID */
391         kid = asymmetric_key_generate_id(cert->raw_serial,
392                                          cert->raw_serial_size,
393                                          cert->raw_issuer,
394                                          cert->raw_issuer_size);
395         if (IS_ERR(kid)) {
396                 ret = PTR_ERR(kid);
397                 goto error_cert_pop;
398         }
399         cert->id = kid;
400
401         /* Generate subject + subjectKeyId */
402         skid = asymmetric_key_generate_id(cert->raw_skid, cert->raw_skid_size, "", 0);
403         if (IS_ERR(skid)) {
404                 ret = PTR_ERR(skid);
405                 goto error_cert_pop;
406         }
407         cert->skid = skid;
408
409         /*
410          * Set the certificate flags:
411          * self_signed, unsupported_key, unsupported_sig, blacklisted
412          */
413         ret = x509_set_cert_flags(cert);
414         if (!ret) {
415                 *pcert = cert;
416                 return 0;
417         }
418
419 error_cert_pop:
420         x509_free_certificate(cert);
421         return ret;
422 }
423
424 struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
425 {
426         mbedtls_x509_crt mbedtls_cert;
427         struct x509_certificate *cert = NULL;
428         long ret;
429
430         /* Parse DER encoded certificate */
431         mbedtls_x509_crt_init(&mbedtls_cert);
432         ret = mbedtls_x509_crt_parse_der(&mbedtls_cert, data, datalen);
433         if (ret)
434                 goto clean_up_ctx;
435
436         /* Populate x509_certificate from mbedtls_x509_crt */
437         ret = x509_populate_cert(&mbedtls_cert, &cert);
438         if (ret)
439                 goto clean_up_ctx;
440
441 clean_up_ctx:
442         mbedtls_x509_crt_free(&mbedtls_cert);
443         if (!ret)
444                 return cert;
445
446         return ERR_PTR(ret);
447 }
This page took 0.056983 seconds and 4 git commands to generate.