1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
6 #include <mbedtls/x509_crt.h>
7 #include <mbedtls/ecp.h>
8 #include <mbedtls/rsa.h>
9 #include <mbedtls/asn1write.h>
10 #include <mbedtls/pkcs5.h>
11 #include <mbedtls/pkcs12.h>
12 #include <mbedtls/base64.h>
13 #include <mbedtls/sha1.h>
15 #define OID_TAG(n) MBEDTLS_OID_##n, MBEDTLS_OID_SIZE(MBEDTLS_OID_##n)
17 #ifndef MBEDTLS_OID_AES_256_CBC
18 #define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a"
21 #define MBEDTLS_OID_PKCS9_LOCAL_KEY_ID MBEDTLS_OID_PKCS9 "\x15"
22 #define MBEDTLS_OID_PKCS9_CERT_TYPE MBEDTLS_OID_PKCS9 "\x16"
23 #define MBEDTLS_OID_PKCS9_CERT_TYPE_X509 MBEDTLS_OID_PKCS9_CERT_TYPE "\x01"
25 #define MBEDTLS_OID_PKCS12_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x01"
26 #define MBEDTLS_OID_PKCS12_SHROUDED_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x02"
27 #define MBEDTLS_OID_PKCS12_CERT_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x03"
29 #ifndef MBEDTLS_OID_PKCS7
30 #define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07"
31 #define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01"
32 #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06"
38 #define IV_LEN_LEGACY 8
40 #define CERT_HASH_LEN 20
42 #define CONTEXT_TAG(n) (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | (n))
43 #define SEQUENCE_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
44 #define SET_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)
46 #define CTX_ADD(ctx, n) \
49 if ((ctx)->p - (ctx)->start <= __n) \
57 uint8_t cert_hash
[20];
58 uint8_t *key_cert_hash
;
60 uint8_t salt
[SALT_LEN
];
72 mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg
, const unsigned char *password
,
73 size_t plen
, const unsigned char *salt
, size_t slen
,
74 unsigned int iteration_count
,
75 uint32_t key_length
, unsigned char *output
)
77 mbedtls_md_context_t md_ctx
;
78 const mbedtls_md_info_t
*md_info
;
81 md_info
= mbedtls_md_info_from_type(md_alg
);
83 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE
;
85 mbedtls_md_init(&md_ctx
);
86 ret
= mbedtls_md_setup(&md_ctx
, md_info
, 1);
90 ret
= mbedtls_pkcs5_pbkdf2_hmac(&md_ctx
, password
, plen
, salt
, slen
,
91 iteration_count
, key_length
, output
);
94 mbedtls_md_free(&md_ctx
);
100 uc_p12_add_tag(struct pkcs12_ctx
*ctx
, uint8_t *end
, uint8_t tag
)
102 mbedtls_asn1_write_len(&ctx
->p
, ctx
->start
, end
- ctx
->p
);
103 mbedtls_asn1_write_tag(&ctx
->p
, ctx
->start
, tag
);
107 uc_p12_add_sequence(struct pkcs12_ctx
*ctx
, uint8_t *end
)
109 uc_p12_add_tag(ctx
, end
, SEQUENCE_TAG
);
113 uc_p12_add_algo(struct pkcs12_ctx
*ctx
, const char *oid
, size_t oid_len
, size_t par_len
)
115 mbedtls_asn1_write_algorithm_identifier(&ctx
->p
, ctx
->start
, oid
, oid_len
, par_len
);
119 uc_p12_add_attribute(struct pkcs12_ctx
*ctx
, uint8_t *end
, const char *oid
, size_t oid_len
)
121 uc_p12_add_tag(ctx
, end
, SET_TAG
);
122 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, oid
, oid_len
);
123 uc_p12_add_sequence(ctx
, end
);
127 uc_p12_add_localkeyid(struct pkcs12_ctx
*ctx
, bool key
)
129 uint8_t *end
= ctx
->p
;
131 ctx
->p
-= CERT_HASH_LEN
;
133 ctx
->key_cert_hash
= ctx
->p
;
134 else if (ctx
->key_cert_hash
)
135 memcpy(ctx
->p
, ctx
->key_cert_hash
, CERT_HASH_LEN
);
136 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
137 uc_p12_add_attribute(ctx
, end
, OID_TAG(PKCS9_LOCAL_KEY_ID
));
141 uc_p12_add_bag(struct pkcs12_ctx
*ctx
, uint8_t *data_end
, uint8_t *end
, const char *oid
, size_t oid_len
)
143 uc_p12_add_tag(ctx
, data_end
, CONTEXT_TAG(0));
144 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, oid
, oid_len
);
145 uc_p12_add_sequence(ctx
, end
);
149 uc_p12_enc_setup(struct pkcs12_ctx
*ctx
, mbedtls_cipher_context_t
*cipher
)
151 const mbedtls_cipher_info_t
*cipher_info
;
152 uint8_t key
[KEY_LEN
];
155 random_cb(NULL
, ctx
->iv
, IV_LEN
);
156 ret
= mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA256
,
157 (void *)ctx
->password
, strlen(ctx
->password
),
158 ctx
->salt
, SALT_LEN
, NUM_ITER
,
163 cipher_info
= mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC
);
164 ret
= mbedtls_cipher_setup(cipher
, cipher_info
);
168 return mbedtls_cipher_setkey(cipher
, key
, 8 * KEY_LEN
, MBEDTLS_ENCRYPT
);
172 uc_p12_enc_legacy(struct pkcs12_ctx
*ctx
, mbedtls_cipher_context_t
*cipher
)
174 const mbedtls_cipher_info_t
*cipher_info
;
178 ret
= mbedtls_pkcs12_derivation(key
, sizeof(key
), ctx
->pwd
, ctx
->pwd_len
,
179 ctx
->salt
, SALT_LEN
, MBEDTLS_MD_SHA1
,
180 MBEDTLS_PKCS12_DERIVE_KEY
, NUM_ITER
);
184 ret
= mbedtls_pkcs12_derivation(ctx
->iv
, IV_LEN_LEGACY
, ctx
->pwd
, ctx
->pwd_len
,
185 ctx
->salt
, SALT_LEN
, MBEDTLS_MD_SHA1
,
186 MBEDTLS_PKCS12_DERIVE_IV
, NUM_ITER
);
190 cipher_info
= mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC
);
191 ret
= mbedtls_cipher_setup(cipher
, cipher_info
);
195 return mbedtls_cipher_setkey(cipher
, key
, 8 * sizeof(key
), MBEDTLS_ENCRYPT
);
199 uc_p12_encrypt(struct pkcs12_ctx
*ctx
, uint8_t *end
)
201 mbedtls_cipher_context_t cipher
;
202 size_t iv_len
= ctx
->legacy
? IV_LEN_LEGACY
: IV_LEN
;
206 random_cb(NULL
, ctx
->salt
, SALT_LEN
);
209 ret
= uc_p12_enc_legacy(ctx
, &cipher
);
211 ret
= uc_p12_enc_setup(ctx
, &cipher
);
215 ret
= mbedtls_cipher_set_padding_mode(&cipher
, MBEDTLS_PADDING_PKCS7
);
219 ret
= mbedtls_cipher_crypt(&cipher
, ctx
->iv
, iv_len
, ctx
->p
, end
- ctx
->p
,
220 (void *)buf
, &out_len
);
225 CTX_ADD(ctx
, out_len
- (end
- ctx
->p
));
226 memcpy(ctx
->p
, buf
, out_len
);
227 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
230 mbedtls_cipher_free(&cipher
);
236 uc_p12_add_enc_params(struct pkcs12_ctx
*ctx
)
238 uint8_t *par_end
= ctx
->p
;
242 mbedtls_asn1_write_int(&ctx
->p
, ctx
->start
, NUM_ITER
);
244 CTX_ADD(ctx
, SALT_LEN
);
245 memcpy(ctx
->p
, ctx
->salt
, SALT_LEN
);
246 uc_p12_add_tag(ctx
, ctx
->p
+ SALT_LEN
, MBEDTLS_ASN1_OCTET_STRING
);
248 uc_p12_add_sequence(ctx
, par_end
);
250 uc_p12_add_algo(ctx
, OID_TAG(PKCS12_PBE_SHA1_DES3_EDE_CBC
), par_end
- ctx
->p
);
252 CTX_ADD(ctx
, IV_LEN
);
253 memcpy(ctx
->p
, ctx
->iv
, IV_LEN
);
255 uc_p12_add_tag(ctx
, par_end
, MBEDTLS_ASN1_OCTET_STRING
);
256 uc_p12_add_algo(ctx
, OID_TAG(AES_256_CBC
), par_end
- ctx
->p
);
259 uc_p12_add_algo(ctx
, OID_TAG(HMAC_SHA256
), 0);
260 mbedtls_asn1_write_int(&ctx
->p
, ctx
->start
, NUM_ITER
);
261 CTX_ADD(ctx
, SALT_LEN
);
262 memcpy(ctx
->p
, ctx
->salt
, SALT_LEN
);
263 uc_p12_add_tag(ctx
, ctx
->p
+ SALT_LEN
, MBEDTLS_ASN1_OCTET_STRING
);
264 uc_p12_add_sequence(ctx
, kdf_end
);
266 uc_p12_add_algo(ctx
, OID_TAG(PKCS5_PBKDF2
), kdf_end
- ctx
->p
);
267 uc_p12_add_sequence(ctx
, par_end
);
269 uc_p12_add_algo(ctx
, OID_TAG(PKCS5_PBES2
), par_end
- ctx
->p
);
276 uc_p12_add_cert(struct pkcs12_ctx
*ctx
, uc_value_t
*arg
, bool ca
)
278 const char *str
= ucv_string_get(arg
), *str_end
;
279 uint8_t *bag_end
, *end
;
283 #define START_TAG "-----BEGIN CERTIFICATE-----"
284 #define END_TAG "-----END CERTIFICATE-----"
289 str
= strstr(str
, START_TAG
);
293 str
+= sizeof(START_TAG
);
294 str_end
= strstr(str
, END_TAG
);
298 if ((size_t)(str_end
- str
) > sizeof(buf
) / 2)
301 ret
= mbedtls_base64_decode((void *)buf
, sizeof(buf
) / 2, &len
,
302 (const void *)str
, str_end
- str
);
307 if (!ca
&& ctx
->key_cert_hash
) {
308 mbedtls_sha1((const void *)buf
, len
, ctx
->key_cert_hash
);
309 uc_p12_add_localkeyid(ctx
, false);
310 uc_p12_add_tag(ctx
, bag_end
, SET_TAG
);
315 memcpy(ctx
->p
, buf
, len
);
316 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
319 uc_p12_add_tag(ctx
, end
, CONTEXT_TAG(0));
320 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, OID_TAG(PKCS9_CERT_TYPE_X509
));
321 uc_p12_add_sequence(ctx
, end
);
323 uc_p12_add_bag(ctx
, end
, bag_end
, OID_TAG(PKCS12_CERT_BAG
));
329 uc_p12_add_key(struct pkcs12_ctx
*ctx
, uc_value_t
*arg
)
331 mbedtls_pk_context
*pk
= ucv_resource_data(arg
, "mbedtls.pk");
332 uint8_t *bag_end
, *end
;
333 uint8_t *param
= NULL
;
334 size_t param_len
= 0;
343 uc_p12_add_localkeyid(ctx
, true);
344 uc_p12_add_tag(ctx
, bag_end
, SET_TAG
);
347 len
= mbedtls_pk_write_key_der(pk
, (void *)ctx
->start
, end
- ctx
->start
);
353 /* Convert EC key contents to PKCS#8 style */
354 if (mbedtls_pk_get_type(pk
) == MBEDTLS_PK_ECKEY
) {
355 mbedtls_ecp_group_id grp_id
;
356 mbedtls_asn1_buf tag_buf
;
357 uint8_t *pkey_start
, *pkey_end
;
358 size_t seq_len
, pkey_len
, param_tag_len
;
364 ret
= mbedtls_asn1_get_tag(&p
, end
, &seq_len
, SEQUENCE_TAG
);
370 ret
= mbedtls_asn1_get_int(&p
, _end
, &version
);
375 ret
= mbedtls_asn1_get_tag(&p
, _end
, &pkey_len
, MBEDTLS_ASN1_OCTET_STRING
);
383 ret
= mbedtls_asn1_get_tag(&p
, _end
, ¶m_len
, CONTEXT_TAG(0));
387 param
= memcpy(buf
, p
, param_len
);
390 /* overwrite parameters */
391 param_tag_len
= p
- pkey_end
;
392 ctx
->p
+= param_tag_len
;
393 _start
+= param_tag_len
;
394 memmove(ctx
->p
, ctx
->p
- param_tag_len
, p
- ctx
->p
);
396 /* replace sequence tag */
398 uc_p12_add_sequence(ctx
, end
);
400 /* check for Curve25519 or Curve448 */
401 tag_buf
= (mbedtls_asn1_buf
){
405 tag_buf
.tag
= *tag_buf
.p
;
406 ret
= mbedtls_asn1_get_tag(&tag_buf
.p
, tag_buf
.p
+ param_len
, &tag_buf
.len
, tag_buf
.tag
);
410 oid
= MBEDTLS_OID_EC_ALG_UNRESTRICTED
;
411 oid_len
= MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_ALG_UNRESTRICTED
);
413 #ifdef MBEDTLS_LEGACY
417 ret
= mbedtls_oid_get_ec_grp_algid(&tag_buf
, &grp_id
);
418 if (!ret
&& (grp_id
== MBEDTLS_ECP_DP_CURVE25519
||
419 grp_id
== MBEDTLS_ECP_DP_CURVE448
)) {
420 ctx
->p
= end
- pkey_len
;
421 memmove(ctx
->p
, pkey_start
, pkey_len
);
422 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
426 mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_get_type(pk
), &oid
, &oid_len
);
429 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
433 CTX_ADD(ctx
, param_len
);
434 memcpy(ctx
->p
, param
, param_len
);
436 uc_p12_add_algo(ctx
, oid
, oid_len
, param_len
);
437 mbedtls_asn1_write_int(&ctx
->p
, ctx
->start
, 0);
438 uc_p12_add_sequence(ctx
, end
);
440 ret
= uc_p12_encrypt(ctx
, end
);
444 ret
= uc_p12_add_enc_params(ctx
);
448 uc_p12_add_sequence(ctx
, end
);
450 uc_p12_add_bag(ctx
, end
, bag_end
, OID_TAG(PKCS12_SHROUDED_KEY_BAG
));
456 uc_p12_add_authsafe(struct pkcs12_ctx
*ctx
, uc_value_t
*arg
)
459 uint8_t *end
= ctx
->p
;
463 /* authSafe contents */
464 extra
= ucv_object_get(arg
, "extra", NULL
);
468 if (ucv_type(extra
) != UC_ARRAY
)
471 len
= ucv_array_length(extra
);
472 for (size_t i
= 0; i
< len
; i
++) {
473 ret
= uc_p12_add_cert(ctx
, ucv_array_get(extra
, i
), true);
479 ret
= uc_p12_add_key(ctx
, ucv_object_get(arg
, "key", NULL
));
483 ret
= uc_p12_add_cert(ctx
, ucv_object_get(arg
, "cert", NULL
), false);
488 uc_p12_add_sequence(ctx
, end
);
490 ret
= uc_p12_encrypt(ctx
, end
);
494 uc_p12_add_tag(ctx
, end
, CONTEXT_TAG(0));
496 ret
= uc_p12_add_enc_params(ctx
);
500 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, OID_TAG(PKCS7_DATA
));
501 uc_p12_add_sequence(ctx
, end
);
503 mbedtls_asn1_write_int(&ctx
->p
, ctx
->start
, 0);
504 uc_p12_add_sequence(ctx
, end
);
505 uc_p12_add_tag(ctx
, end
, CONTEXT_TAG(0));
506 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, OID_TAG(PKCS7_ENCRYPTED_DATA
));
507 uc_p12_add_sequence(ctx
, end
);
509 /* authSafe contents */
510 uc_p12_add_sequence(ctx
, end
);
512 /* authSafe header */
514 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
515 uc_p12_add_tag(ctx
, end
, CONTEXT_TAG(0));
516 mbedtls_asn1_write_oid(&ctx
->p
, ctx
->start
, OID_TAG(PKCS7_DATA
));
517 uc_p12_add_sequence(ctx
, end
);
523 uc_p12_add_mac_digest_info(struct pkcs12_ctx
*ctx
)
525 uint8_t *end
= ctx
->p
;
529 uc_p12_add_tag(ctx
, end
, MBEDTLS_ASN1_OCTET_STRING
);
530 uc_p12_add_algo(ctx
, OID_TAG(DIGEST_ALG_SHA1
), 0);
531 uc_p12_add_sequence(ctx
, end
);
536 uc_value_t
*uc_generate_pkcs12(uc_vm_t
*vm
, size_t nargs
)
538 uc_value_t
*arg
= uc_fn_arg(0), *pwd_arg
;
539 mbedtls_md_context_t hmac
;
540 uint8_t *end
= (uint8_t *)&buf
[sizeof(buf
)];
541 struct pkcs12_ctx ctx
= {
542 .start
= (uint8_t *)&buf
[sizeof(buf
) / 2],
545 uint8_t *hash
, *data
;
546 uint8_t key
[20], *salt
;
549 uc_value_t
*ret
= NULL
;
552 if (ucv_type(arg
) != UC_OBJECT
)
555 ctx
.legacy
= ucv_is_truish(ucv_object_get(arg
, "legacy", NULL
));
557 mbedtls_md_init(&hmac
);
558 pwd_arg
= ucv_object_get(arg
, "password", NULL
);
559 passwd
= ucv_string_get(pwd_arg
);
563 /* password is expected to be a UTF-16 string */
564 ctx
.password
= passwd
;
565 ctx
.pwd_len
= 2 * strlen(passwd
) + 2;
566 ctx
.pwd
= malloc(ctx
.pwd_len
);
567 for (size_t i
= 0; i
< ctx
.pwd_len
; i
+= 2) {
569 ctx
.pwd
[i
+ 1] = passwd
[i
/ 2];
573 mbedtls_asn1_write_int(&ctx
.p
, ctx
.start
, NUM_ITER
);
577 random_cb(NULL
, salt
, salt_len
);
578 uc_p12_add_tag(&ctx
, salt
+ salt_len
, MBEDTLS_ASN1_OCTET_STRING
);
580 hash
= uc_p12_add_mac_digest_info(&ctx
);
581 uc_p12_add_sequence(&ctx
, end
);
584 data_len
= uc_p12_add_authsafe(&ctx
, arg
);
589 mbedtls_asn1_write_int(&ctx
.p
, ctx
.start
, 3);
590 uc_p12_add_sequence(&ctx
, end
);
592 if (C(mbedtls_pkcs12_derivation(key
, sizeof(key
), ctx
.pwd
, ctx
.pwd_len
,
593 salt
, salt_len
, MBEDTLS_MD_SHA1
,
594 MBEDTLS_PKCS12_DERIVE_MAC_KEY
, NUM_ITER
)))
597 if (C(mbedtls_md_setup(&hmac
, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1
), 1)))
599 if (C(mbedtls_md_hmac_starts(&hmac
, key
, sizeof(key
))))
601 if (C(mbedtls_md_hmac_update(&hmac
, data
, data_len
)))
603 if (C(mbedtls_md_hmac_finish(&hmac
, hash
)))
606 ret
= ucv_string_new_length((char *)ctx
.p
, end
- ctx
.p
);
610 mbedtls_md_free(&hmac
);