7d23b9d35b7583ae90b0d7a0481b7eaae0b41b41
[openwrt/staging/nbd.git] / package / utils / ucode-mod-pkgen / src / pkcs12.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
4 */
5 #include "pk.h"
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>
14
15 #define OID_TAG(n) MBEDTLS_OID_##n, MBEDTLS_OID_SIZE(MBEDTLS_OID_##n)
16
17 #ifndef MBEDTLS_OID_AES_256_CBC
18 #define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a"
19 #endif
20
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"
24
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"
28
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"
33 #endif
34
35 #define NUM_ITER 2048
36 #define SALT_LEN 16
37 #define IV_LEN 16
38 #define IV_LEN_LEGACY 8
39 #define KEY_LEN 32
40 #define CERT_HASH_LEN 20
41
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)
45
46 #define CTX_ADD(ctx, n) \
47 do { \
48 int __n = (n); \
49 if ((ctx)->p - (ctx)->start <= __n) \
50 return -1; \
51 (ctx)->p -= __n; \
52 } while (0)
53
54 struct pkcs12_ctx {
55 uint8_t *p, *start;
56
57 uint8_t cert_hash[20];
58 uint8_t *key_cert_hash;
59
60 uint8_t salt[SALT_LEN];
61 uint8_t iv[IV_LEN];
62
63 const char *password;
64 uint8_t *pwd;
65 size_t pwd_len;
66
67 bool legacy;
68 };
69
70 #ifdef MBEDTLS_LEGACY
71 static inline int
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)
76 {
77 mbedtls_md_context_t md_ctx;
78 const mbedtls_md_info_t *md_info;
79 int ret;
80
81 md_info = mbedtls_md_info_from_type(md_alg);
82 if (!md_info)
83 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
84
85 mbedtls_md_init(&md_ctx);
86 ret = mbedtls_md_setup(&md_ctx, md_info, 1);
87 if (ret)
88 goto out;
89
90 ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,
91 iteration_count, key_length, output);
92
93 out:
94 mbedtls_md_free(&md_ctx);
95 return ret;
96 }
97 #endif
98
99 static void
100 uc_p12_add_tag(struct pkcs12_ctx *ctx, uint8_t *end, uint8_t tag)
101 {
102 mbedtls_asn1_write_len(&ctx->p, ctx->start, end - ctx->p);
103 mbedtls_asn1_write_tag(&ctx->p, ctx->start, tag);
104 }
105
106 static void
107 uc_p12_add_sequence(struct pkcs12_ctx *ctx, uint8_t *end)
108 {
109 uc_p12_add_tag(ctx, end, SEQUENCE_TAG);
110 }
111
112 static void
113 uc_p12_add_algo(struct pkcs12_ctx *ctx, const char *oid, size_t oid_len, size_t par_len)
114 {
115 mbedtls_asn1_write_algorithm_identifier(&ctx->p, ctx->start, oid, oid_len, par_len);
116 }
117
118 static void
119 uc_p12_add_attribute(struct pkcs12_ctx *ctx, uint8_t *end, const char *oid, size_t oid_len)
120 {
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);
124 }
125
126 static void
127 uc_p12_add_localkeyid(struct pkcs12_ctx *ctx, bool key)
128 {
129 uint8_t *end = ctx->p;
130
131 ctx->p -= CERT_HASH_LEN;
132 if (key)
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));
138 }
139
140 static void
141 uc_p12_add_bag(struct pkcs12_ctx *ctx, uint8_t *data_end, uint8_t *end, const char *oid, size_t oid_len)
142 {
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);
146 }
147
148 static int
149 uc_p12_enc_setup(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher)
150 {
151 const mbedtls_cipher_info_t *cipher_info;
152 uint8_t key[KEY_LEN];
153 int ret;
154
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,
159 KEY_LEN, key);
160 if (ret < 0)
161 return ret;
162
163 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC);
164 ret = mbedtls_cipher_setup(cipher, cipher_info);
165 if (ret < 0)
166 return ret;
167
168 return mbedtls_cipher_setkey(cipher, key, 8 * KEY_LEN, MBEDTLS_ENCRYPT);
169 }
170
171 static int
172 uc_p12_enc_legacy(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher)
173 {
174 const mbedtls_cipher_info_t *cipher_info;
175 uint8_t key[24];
176 int ret;
177
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);
181 if (ret < 0)
182 return ret;
183
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);
187 if (ret < 0)
188 return ret;
189
190 cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC);
191 ret = mbedtls_cipher_setup(cipher, cipher_info);
192 if (ret < 0)
193 return ret;
194
195 return mbedtls_cipher_setkey(cipher, key, 8 * sizeof(key), MBEDTLS_ENCRYPT);
196 }
197
198 static int
199 uc_p12_encrypt(struct pkcs12_ctx *ctx, uint8_t *end)
200 {
201 mbedtls_cipher_context_t cipher;
202 size_t iv_len = ctx->legacy ? IV_LEN_LEGACY : IV_LEN;
203 size_t out_len = 0;
204 int ret;
205
206 random_cb(NULL, ctx->salt, SALT_LEN);
207
208 if (ctx->legacy)
209 ret = uc_p12_enc_legacy(ctx, &cipher);
210 else
211 ret = uc_p12_enc_setup(ctx, &cipher);
212 if (ret < 0)
213 goto out;
214
215 ret = mbedtls_cipher_set_padding_mode(&cipher, MBEDTLS_PADDING_PKCS7);
216 if (ret < 0)
217 goto out;
218
219 ret = mbedtls_cipher_crypt(&cipher, ctx->iv, iv_len, ctx->p, end - ctx->p,
220 (void *)buf, &out_len);
221
222 if (ret < 0)
223 goto out;
224
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);
228
229 out:
230 mbedtls_cipher_free(&cipher);
231
232 return ret;
233 }
234
235 static int
236 uc_p12_add_enc_params(struct pkcs12_ctx *ctx)
237 {
238 uint8_t *par_end = ctx->p;
239 uint8_t *kdf_end;
240
241 if (ctx->legacy) {
242 mbedtls_asn1_write_int(&ctx->p, ctx->start, NUM_ITER);
243
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);
247
248 uc_p12_add_sequence(ctx, par_end);
249
250 uc_p12_add_algo(ctx, OID_TAG(PKCS12_PBE_SHA1_DES3_EDE_CBC), par_end - ctx->p);
251 } else {
252 CTX_ADD(ctx, IV_LEN);
253 memcpy(ctx->p, ctx->iv, IV_LEN);
254
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);
257
258 kdf_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);
265
266 uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBKDF2), kdf_end - ctx->p);
267 uc_p12_add_sequence(ctx, par_end);
268
269 uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBES2), par_end - ctx->p);
270 }
271
272 return 0;
273 }
274
275 static int
276 uc_p12_add_cert(struct pkcs12_ctx *ctx, uc_value_t *arg, bool ca)
277 {
278 const char *str = ucv_string_get(arg), *str_end;
279 uint8_t *bag_end, *end;
280 size_t len;
281 int ret;
282
283 #define START_TAG "-----BEGIN CERTIFICATE-----"
284 #define END_TAG "-----END CERTIFICATE-----"
285
286 if (!str)
287 return -1;
288
289 str = strstr(str, START_TAG);
290 if (!str)
291 return -1;
292
293 str += sizeof(START_TAG);
294 str_end = strstr(str, END_TAG);
295 if (!str_end)
296 return -1;
297
298 if ((size_t)(str_end - str) > sizeof(buf) / 2)
299 return -1;
300
301 ret = mbedtls_base64_decode((void *)buf, sizeof(buf) / 2, &len,
302 (const void *)str, str_end - str);
303 if (ret)
304 return ret;
305
306 bag_end = ctx->p;
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);
311 }
312
313 end = ctx->p;
314 CTX_ADD(ctx, len);
315 memcpy(ctx->p, buf, len);
316 uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
317
318 /* CertBag */
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);
322
323 uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_CERT_BAG));
324
325 return 0;
326 }
327
328 static int
329 uc_p12_add_key(struct pkcs12_ctx *ctx, uc_value_t *arg)
330 {
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;
335 const char *oid;
336 size_t oid_len = 0;
337 int ret, len;
338
339 if (!pk)
340 return -1;
341
342 bag_end = ctx->p;
343 uc_p12_add_localkeyid(ctx, true);
344 uc_p12_add_tag(ctx, bag_end, SET_TAG);
345
346 end = ctx->p;
347 len = mbedtls_pk_write_key_der(pk, (void *)ctx->start, end - ctx->start);
348 if (len < 0)
349 return len;
350
351 ctx->p -= len;
352
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;
359 uint8_t *p = ctx->p;
360 uint8_t *_end = end;
361 uint8_t *_start;
362 int version;
363
364 ret = mbedtls_asn1_get_tag(&p, end, &seq_len, SEQUENCE_TAG);
365 if (ret < 0)
366 return ret;
367
368 _start = p;
369 _end = p + seq_len;
370 ret = mbedtls_asn1_get_int(&p, _end, &version);
371 if (ret < 0)
372 return ret;
373
374 /* private key */
375 ret = mbedtls_asn1_get_tag(&p, _end, &pkey_len, MBEDTLS_ASN1_OCTET_STRING);
376 if (ret < 0)
377 return ret;
378 pkey_start = p;
379 p += pkey_len;
380 pkey_end = p;
381
382 /* parameters */
383 ret = mbedtls_asn1_get_tag(&p, _end, &param_len, CONTEXT_TAG(0));
384 if (ret < 0)
385 return ret;
386
387 param = memcpy(buf, p, param_len);
388 p += param_len;
389
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);
395
396 /* replace sequence tag */
397 ctx->p = _start;
398 uc_p12_add_sequence(ctx, end);
399
400 /* check for Curve25519 or Curve448 */
401 tag_buf = (mbedtls_asn1_buf){
402 .p = (uint8_t *)buf,
403 .len = param_len,
404 };
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);
407 if (ret < 0)
408 return ret;
409
410 oid = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
411 oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_ALG_UNRESTRICTED);
412
413 #ifdef MBEDTLS_LEGACY
414 (void)pkey_start;
415 (void)grp_id;
416 #else
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);
423 }
424 #endif
425 } else {
426 mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_get_type(pk), &oid, &oid_len);
427 }
428
429 uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING);
430
431 /* KeyBag */
432 if (param_len) {
433 CTX_ADD(ctx, param_len);
434 memcpy(ctx->p, param, param_len);
435 }
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);
439
440 ret = uc_p12_encrypt(ctx, end);
441 if (ret < 0)
442 return ret;
443
444 ret = uc_p12_add_enc_params(ctx);
445 if (ret < 0)
446 return ret;
447
448 uc_p12_add_sequence(ctx, end);
449
450 uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_SHROUDED_KEY_BAG));
451
452 return 0;
453 }
454
455 static int
456 uc_p12_add_authsafe(struct pkcs12_ctx *ctx, uc_value_t *arg)
457 {
458 uc_value_t *extra;
459 uint8_t *end = ctx->p;
460 size_t len;
461 int ret;
462
463 /* authSafe contents */
464 extra = ucv_object_get(arg, "extra", NULL);
465 if (extra) {
466 size_t len;
467
468 if (ucv_type(extra) != UC_ARRAY)
469 return -1;
470
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);
474 if (ret < 0)
475 return ret;
476 }
477 }
478
479 ret = uc_p12_add_key(ctx, ucv_object_get(arg, "key", NULL));
480 if (ret < 0)
481 return ret;
482
483 ret = uc_p12_add_cert(ctx, ucv_object_get(arg, "cert", NULL), false);
484 if (ret < 0)
485 return ret;
486
487 /* encrypted */
488 uc_p12_add_sequence(ctx, end);
489
490 ret = uc_p12_encrypt(ctx, end);
491 if (ret < 0)
492 return ret;
493
494 uc_p12_add_tag(ctx, end, CONTEXT_TAG(0));
495
496 ret = uc_p12_add_enc_params(ctx);
497 if (ret < 0)
498 return ret;
499
500 mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_DATA));
501 uc_p12_add_sequence(ctx, end);
502
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);
508
509 /* authSafe contents */
510 uc_p12_add_sequence(ctx, end);
511
512 /* authSafe header */
513 len = end - ctx->p;
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);
518
519 return len;
520 }
521
522 static void *
523 uc_p12_add_mac_digest_info(struct pkcs12_ctx *ctx)
524 {
525 uint8_t *end = ctx->p;
526 size_t len = 20;
527
528 ctx->p -= len;
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);
532
533 return end - len;
534 }
535
536 uc_value_t *uc_generate_pkcs12(uc_vm_t *vm, size_t nargs)
537 {
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],
543 .p = end,
544 };
545 uint8_t *hash, *data;
546 uint8_t key[20], *salt;
547 size_t salt_len = 8;
548 int data_len;
549 uc_value_t *ret = NULL;
550 const char *passwd;
551
552 if (ucv_type(arg) != UC_OBJECT)
553 INVALID_ARG();
554
555 ctx.legacy = ucv_is_truish(ucv_object_get(arg, "legacy", NULL));
556
557 mbedtls_md_init(&hmac);
558 pwd_arg = ucv_object_get(arg, "password", NULL);
559 passwd = ucv_string_get(pwd_arg);
560 if (!passwd)
561 INVALID_ARG();
562
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) {
568 ctx.pwd[i] = 0;
569 ctx.pwd[i + 1] = passwd[i / 2];
570 }
571
572 /* MacData */
573 mbedtls_asn1_write_int(&ctx.p, ctx.start, NUM_ITER);
574
575 ctx.p -= salt_len;
576 salt = ctx.p;
577 random_cb(NULL, salt, salt_len);
578 uc_p12_add_tag(&ctx, salt + salt_len, MBEDTLS_ASN1_OCTET_STRING);
579
580 hash = uc_p12_add_mac_digest_info(&ctx);
581 uc_p12_add_sequence(&ctx, end);
582
583 data = ctx.p;
584 data_len = uc_p12_add_authsafe(&ctx, arg);
585 if (C(data_len) < 0)
586 goto out;
587 data -= data_len;
588
589 mbedtls_asn1_write_int(&ctx.p, ctx.start, 3);
590 uc_p12_add_sequence(&ctx, end);
591
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)))
595 goto out;
596
597 if (C(mbedtls_md_setup(&hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1)))
598 goto out;
599 if (C(mbedtls_md_hmac_starts(&hmac, key, sizeof(key))))
600 goto out;
601 if (C(mbedtls_md_hmac_update(&hmac, data, data_len)))
602 goto out;
603 if (C(mbedtls_md_hmac_finish(&hmac, hash)))
604 goto out;
605
606 ret = ucv_string_new_length((char *)ctx.p, end - ctx.p);
607
608 out:
609 free(ctx.pwd);
610 mbedtls_md_free(&hmac);
611 return ret;
612 }