Coverage Report

Created: 2023-11-19 07:14

/src/wolf-ssl-ssh-fuzzers/oss-fuzz/projects/wolf-ssl-ssh/fuzzers/wolfssl/wolfssl/wolfcrypt/src/pkcs12.c
Line
Count
Source (jump to first uncovered line)
1
/* pkcs12.c
2
 *
3
 * Copyright (C) 2006-2023 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
/* PKCS#12 allows storage of key and certificates into containers */
23
24
#ifdef HAVE_CONFIG_H
25
    #include <config.h>
26
#endif
27
28
#include <wolfssl/wolfcrypt/settings.h>
29
30
#if defined(HAVE_PKCS12) && \
31
    !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_HMAC) && \
32
    !defined(NO_CERTS)
33
34
#include <wolfssl/wolfcrypt/asn.h>
35
#include <wolfssl/wolfcrypt/asn_public.h>
36
#include <wolfssl/wolfcrypt/error-crypt.h>
37
#include <wolfssl/wolfcrypt/hmac.h>
38
#include <wolfssl/wolfcrypt/logging.h>
39
#ifdef NO_INLINE
40
    #include <wolfssl/wolfcrypt/misc.h>
41
#else
42
    #define WOLFSSL_MISC_INCLUDED
43
    #include <wolfcrypt/src/misc.c>
44
#endif
45
#include <wolfssl/wolfcrypt/pkcs12.h>
46
#include <wolfssl/wolfcrypt/pwdbased.h>
47
#include <wolfssl/wolfcrypt/hash.h>
48
49
50
0
#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
51
52
enum {
53
    WC_PKCS12_KeyBag = 667,
54
    WC_PKCS12_ShroudedKeyBag = 668,
55
    WC_PKCS12_CertBag = 669,
56
    WC_PKCS12_CertBag_Type1 = 675,
57
    WC_PKCS12_CrlBag = 670,
58
    WC_PKCS12_SecretBag = 671,
59
    WC_PKCS12_SafeContentsBag = 672,
60
    WC_PKCS12_DATA = 651,
61
    WC_PKCS12_ENCRYPTED_DATA = 656,
62
63
    WC_PKCS12_DATA_OBJ_SZ = 11,
64
    WC_PKCS12_MAC_SALT_SZ = 8
65
};
66
67
static const byte WC_PKCS12_ENCRYPTED_OID[] =
68
                         {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06};
69
static const byte WC_PKCS12_DATA_OID[] =
70
                         {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01};
71
static const byte WC_PKCS12_CertBag_Type1_OID[] =
72
                   {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01};
73
static const byte WC_PKCS12_CertBag_OID[] =
74
             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03};
75
static const byte WC_PKCS12_KeyBag_OID[] =
76
             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01};
77
static const byte WC_PKCS12_ShroudedKeyBag_OID[] =
78
             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02};
79
80
81
typedef struct ContentInfo {
82
    byte* data;
83
    struct ContentInfo* next;
84
    word32 encC;  /* encryptedContent */
85
    word32 dataSz;
86
    int type; /* DATA / encrypted / enveloped */
87
} ContentInfo;
88
89
90
typedef struct AuthenticatedSafe {
91
    ContentInfo* CI;
92
    byte* data; /* T contents.... */
93
    word32 oid; /* encrypted or not */
94
    word32 numCI; /* number of Content Info structs */
95
    word32 dataSz;
96
} AuthenticatedSafe;
97
98
99
typedef struct MacData {
100
    byte* digest;
101
    byte* salt;
102
    word32 oid;
103
    word32 digestSz;
104
    word32 saltSz;
105
    int itt; /* number of iterations when creating HMAC key */
106
} MacData;
107
108
109
struct WC_PKCS12 {
110
    void* heap;
111
    AuthenticatedSafe* safe;
112
    MacData* signData;
113
    word32 oid; /* DATA / Enveloped DATA ... */
114
    byte   indefinite;
115
#ifdef ASN_BER_TO_DER
116
    byte*  safeDer; /* der encoded version of message */
117
    byte*  der; /* der encoded version of message */
118
    word32 safeDersz;
119
    word32 derSz;
120
#endif
121
};
122
123
124
/* for friendlyName, localKeyId .... */
125
typedef struct WC_PKCS12_ATTRIBUTE {
126
    byte* data;
127
    word32 oid;
128
    word32 dataSz;
129
} WC_PKCS12_ATTRIBUTE;
130
131
132
WC_PKCS12* wc_PKCS12_new(void)
133
0
{
134
0
    WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12),
135
0
                                                      NULL, DYNAMIC_TYPE_PKCS);
136
0
    if (pkcs12 == NULL) {
137
0
        WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct");
138
0
        return NULL;
139
0
    }
140
141
0
    XMEMSET(pkcs12, 0, sizeof(WC_PKCS12));
142
143
0
    return pkcs12;
144
0
}
145
146
147
static void freeSafe(AuthenticatedSafe* safe, void* heap)
148
0
{
149
0
    int i;
150
151
0
    if (safe == NULL) {
152
0
        return;
153
0
    }
154
155
    /* free content info structs */
156
0
    for (i = (int)safe->numCI; i > 0; i--) {
157
0
        ContentInfo* ci = safe->CI;
158
0
        safe->CI = ci->next;
159
0
        XFREE(ci, heap, DYNAMIC_TYPE_PKCS);
160
0
    }
161
0
    if (safe->data != NULL) {
162
0
        XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS);
163
0
    }
164
0
    XFREE(safe, heap, DYNAMIC_TYPE_PKCS);
165
166
0
    (void)heap;
167
0
}
168
169
170
void wc_PKCS12_free(WC_PKCS12* pkcs12)
171
0
{
172
0
    void* heap;
173
174
    /* if null pointer is passed in do nothing */
175
0
    if (pkcs12 == NULL) {
176
0
        WOLFSSL_MSG("Trying to free null WC_PKCS12 object");
177
0
        return;
178
0
    }
179
180
0
    heap = pkcs12->heap;
181
0
    if (pkcs12->safe != NULL) {
182
0
        freeSafe(pkcs12->safe, heap);
183
0
    }
184
185
    /* free mac data */
186
0
    if (pkcs12->signData != NULL) {
187
0
        if (pkcs12->signData->digest != NULL) {
188
0
            XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST);
189
0
        }
190
0
        if (pkcs12->signData->salt != NULL) {
191
0
            XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT);
192
0
        }
193
0
        XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS);
194
0
    }
195
196
0
#ifdef ASN_BER_TO_DER
197
0
    if (pkcs12->der != NULL) {
198
0
        XFREE(pkcs12->der, pkcs12->heap, DYNAMIC_TYPE_PKCS);
199
0
    }
200
0
    if (pkcs12->safeDer != NULL) {
201
0
        XFREE(pkcs12->safeDer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
202
0
    }
203
0
#endif
204
205
0
    XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS);
206
0
}
207
208
209
/* return 0 on success */
210
static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input,
211
                          word32* idx, word32 maxIdx)
212
0
{
213
0
    AuthenticatedSafe* safe;
214
0
    word32 oid;
215
0
    word32 localIdx = *idx;
216
0
    int ret;
217
0
    int size = 0;
218
0
    byte tag;
219
220
0
    safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap,
221
0
                                       DYNAMIC_TYPE_PKCS);
222
0
    if (safe == NULL) {
223
0
        return MEMORY_E;
224
0
    }
225
0
    XMEMSET(safe, 0, sizeof(AuthenticatedSafe));
226
227
0
    ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx);
228
0
    if (ret < 0) {
229
0
        WOLFSSL_LEAVE("Get object id failed", ret);
230
0
        freeSafe(safe, pkcs12->heap);
231
0
        return ASN_PARSE_E;
232
0
    }
233
234
0
    safe->oid = oid;
235
    /* check tag, length */
236
0
    if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) {
237
0
        freeSafe(safe, pkcs12->heap);
238
0
        return ASN_PARSE_E;
239
0
    }
240
241
0
    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
242
0
        WOLFSSL_MSG("Unexpected tag in PKCS12 DER");
243
0
        freeSafe(safe, pkcs12->heap);
244
0
        return ASN_PARSE_E;
245
0
    }
246
0
    if (GetLength(input, &localIdx, &size, maxIdx) <= 0) {
247
0
        freeSafe(safe, pkcs12->heap);
248
0
        return ASN_PARSE_E;
249
0
    }
250
251
0
    switch (oid) {
252
0
        case WC_PKCS12_ENCRYPTED_DATA:
253
0
            WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA");
254
0
            break;
255
256
0
        case WC_PKCS12_DATA:
257
0
            WOLFSSL_MSG("Found PKCS12 OBJECT: DATA");
258
            /* get octets holding contents */
259
0
            if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) {
260
0
                freeSafe(safe, pkcs12->heap);
261
0
                return ASN_PARSE_E;
262
0
            }
263
264
0
            if (tag != ASN_OCTET_STRING) {
265
0
                WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA");
266
0
                freeSafe(safe, pkcs12->heap);
267
0
                return ASN_PARSE_E;
268
0
            }
269
0
            if (GetLength(input, &localIdx, &size, maxIdx) <= 0) {
270
0
                freeSafe(safe, pkcs12->heap);
271
0
                return ASN_PARSE_E;
272
0
            }
273
274
0
            break;
275
0
    }
276
277
0
    safe->dataSz = (word32)size;
278
0
    safe->data = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
279
0
    if (safe->data == NULL) {
280
0
        freeSafe(safe, pkcs12->heap);
281
0
        return MEMORY_E;
282
0
    }
283
0
    XMEMCPY(safe->data, input + localIdx, (size_t)size);
284
0
    *idx = localIdx;
285
286
0
    localIdx = 0;
287
0
    input = safe->data;
288
0
    size = (int)safe->dataSz;
289
290
0
#ifdef ASN_BER_TO_DER
291
0
     if (pkcs12->indefinite) {
292
0
        if (wc_BerToDer(input, safe->dataSz, NULL,
293
0
                        &pkcs12->safeDersz) != LENGTH_ONLY_E) {
294
0
            WOLFSSL_MSG("Not BER sequence");
295
0
            return ASN_PARSE_E;
296
0
        }
297
298
0
        pkcs12->safeDer = (byte*)XMALLOC(pkcs12->safeDersz, pkcs12->heap,
299
0
                DYNAMIC_TYPE_PKCS);
300
0
        if (pkcs12->safeDer == NULL) {
301
0
            freeSafe(safe, pkcs12->heap);
302
0
            return MEMORY_E;
303
0
        }
304
305
0
        ret = wc_BerToDer(input, safe->dataSz, pkcs12->safeDer, &pkcs12->safeDersz);
306
0
        if (ret < 0) {
307
0
            freeSafe(safe, pkcs12->heap);
308
0
            return ret;
309
0
        }
310
311
0
        input = pkcs12->safeDer;
312
0
     }
313
0
#endif /* ASN_BER_TO_DER */
314
315
    /* an instance of AuthenticatedSafe is created from
316
     * ContentInfo's strung together in a SEQUENCE. Here we iterate
317
     * through the ContentInfo's and add them to our
318
     * AuthenticatedSafe struct */
319
0
    {
320
0
        int CISz;
321
0
        ret = GetSequence(input, &localIdx, &CISz, (word32)size);
322
0
        if (ret < 0) {
323
0
            freeSafe(safe, pkcs12->heap);
324
0
            return ASN_PARSE_E;
325
0
        }
326
0
        CISz += (int)localIdx;
327
0
        while (localIdx < (word32)CISz) {
328
0
            int curSz = 0;
329
0
            word32 curIdx;
330
0
            ContentInfo* ci = NULL;
331
332
        #ifdef WOLFSSL_DEBUG_PKCS12
333
            printf("\t\tlooking for Content Info.... ");
334
        #endif
335
336
0
            if ((ret = GetSequence(input, &localIdx, &curSz, (word32)size)) < 0) {
337
0
                freeSafe(safe, pkcs12->heap);
338
0
                return ret;
339
0
            }
340
341
0
            if (curSz > CISz) {
342
                /* subset should not be larger than universe */
343
0
                freeSafe(safe, pkcs12->heap);
344
0
                return ASN_PARSE_E;
345
0
            }
346
347
0
            curIdx = localIdx;
348
0
            if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType,
349
0
                                                           (word32)size)) < 0) {
350
0
                WOLFSSL_LEAVE("Get object id failed", ret);
351
0
                freeSafe(safe, pkcs12->heap);
352
0
                return ret;
353
0
            }
354
355
            /* create new content info struct ... possible OID sanity check? */
356
0
            ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap,
357
0
                                       DYNAMIC_TYPE_PKCS);
358
0
            if (ci == NULL) {
359
0
                freeSafe(safe, pkcs12->heap);
360
0
                return MEMORY_E;
361
0
            }
362
363
0
            ci->type   = (int)oid;
364
0
            ci->dataSz = (word32)curSz - (localIdx-curIdx);
365
0
            ci->data   = (byte*)input + localIdx;
366
0
            localIdx  += ci->dataSz;
367
368
        #ifdef WOLFSSL_DEBUG_PKCS12
369
            switch (oid) {
370
                case WC_PKCS12_ENCRYPTED_DATA:
371
                    printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz);
372
                    break;
373
374
                case WC_PKCS12_DATA:
375
                    printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz);
376
                    break;
377
                default:
378
                    printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz);
379
            }
380
        #endif
381
382
            /* insert to head of list */
383
0
            ci->next = safe->CI;
384
0
            safe->CI = ci;
385
0
            safe->numCI += 1;
386
0
        }
387
0
    }
388
389
0
    pkcs12->safe = safe;
390
0
    *idx += localIdx;
391
392
0
    return ret;
393
0
}
394
395
396
/* parse optional mac data
397
 * return 0 on success */
398
static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx,
399
                       word32 totalSz)
400
0
{
401
0
    MacData* mac;
402
0
    word32 curIdx = *idx;
403
0
    word32 oid = 0;
404
0
    int size, ret;
405
0
    byte tag;
406
407
    /* Digest Info : Sequence
408
     *      DigestAlgorithmIdentifier
409
     *      Digest
410
     */
411
0
    if (GetSequence(mem, &curIdx, &size, totalSz) <= 0) {
412
0
        WOLFSSL_MSG("Failed to get PKCS12 sequence");
413
0
        return ASN_PARSE_E;
414
0
    }
415
416
#ifdef WOLFSSL_DEBUG_PKCS12
417
    printf("\t\tSEQUENCE: DigestInfo size = %d\n", size);
418
#endif
419
420
0
    mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS);
421
0
    if (mac == NULL) {
422
0
        return MEMORY_E;
423
0
    }
424
0
    XMEMSET(mac, 0, sizeof(MacData));
425
426
    /* DigestAlgorithmIdentifier */
427
0
    if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) {
428
0
        WOLFSSL_MSG("Failed to get PKCS12 sequence");
429
0
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
430
0
        return ret;
431
0
    }
432
0
    mac->oid = oid;
433
434
#ifdef WOLFSSL_DEBUG_PKCS12
435
    printf("\t\tALGO ID = %d\n", oid);
436
#endif
437
438
    /* Digest: should be octet type holding digest */
439
0
    if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) {
440
0
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
441
0
        return ASN_PARSE_E;
442
0
    }
443
444
0
    if (tag != ASN_OCTET_STRING) {
445
0
        WOLFSSL_MSG("Failed to get digest");
446
0
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
447
0
        return ASN_PARSE_E;
448
0
    }
449
450
0
    if (GetLength(mem, &curIdx, &size, totalSz) <= 0) {
451
0
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
452
0
        return ASN_PARSE_E;
453
0
    }
454
0
    mac->digestSz = (word32)size;
455
0
    mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap,
456
0
                                 DYNAMIC_TYPE_DIGEST);
457
0
    if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) {
458
0
        ERROR_OUT(MEMORY_E, exit_gsd);
459
0
    }
460
0
    XMEMCPY(mac->digest, mem + curIdx, mac->digestSz);
461
462
#ifdef WOLFSSL_DEBUG_PKCS12
463
    {
464
        byte* p;
465
        for (printf("\t\tDigest = "), p = (byte*)mem+curIdx;
466
             p < (byte*)mem + curIdx + mac->digestSz;
467
             printf("%02X", *p), p++);
468
        printf(" : size = %d\n", mac->digestSz);
469
    }
470
#endif
471
472
0
    curIdx += mac->digestSz;
473
474
    /* get salt, should be octet string */
475
0
    if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) {
476
0
        ERROR_OUT(ASN_PARSE_E, exit_gsd);
477
0
    }
478
479
0
    if (tag != ASN_OCTET_STRING) {
480
0
        WOLFSSL_MSG("Failed to get salt");
481
0
        ERROR_OUT(ASN_PARSE_E, exit_gsd);
482
0
    }
483
484
0
    if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) {
485
0
        goto exit_gsd;
486
0
    }
487
0
    mac->saltSz = (word32)size;
488
0
    mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT);
489
0
    if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) {
490
0
        ERROR_OUT(MEMORY_E, exit_gsd);
491
0
    }
492
0
    XMEMCPY(mac->salt, mem + curIdx, mac->saltSz);
493
494
#ifdef WOLFSSL_DEBUG_PKCS12
495
    {
496
        byte* p;
497
        for (printf("\t\tSalt = "), p = (byte*)mem + curIdx;
498
             p < (byte*)mem + curIdx + mac->saltSz;
499
             printf("%02X", *p), p++);
500
        printf(" : size = %d\n", mac->saltSz);
501
    }
502
#endif
503
504
0
    curIdx += mac->saltSz;
505
506
    /* check for MAC iterations, default to 1 */
507
0
    mac->itt = WC_PKCS12_MAC_DEFAULT;
508
0
    if (curIdx < totalSz) {
509
0
        int number = 0;
510
0
        if (GetShortInt(mem, &curIdx, &number, totalSz) >= 0) {
511
            /* found a iteration value */
512
0
            mac->itt = number;
513
0
        }
514
0
    }
515
516
#ifdef WOLFSSL_DEBUG_PKCS12
517
    printf("\t\tITERATIONS : %d\n", mac->itt);
518
#endif
519
520
0
    *idx = curIdx;
521
0
    pkcs12->signData = mac;
522
0
    ret = 0; /* success */
523
524
0
exit_gsd:
525
526
    /* failure cleanup */
527
0
    if (ret != 0) {
528
0
        if (mac) {
529
0
            if (mac->digest)
530
0
                XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST);
531
0
            XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
532
0
        }
533
0
    }
534
535
0
    return ret;
536
0
}
537
538
539
/* expects PKCS12 signData to be set up with OID
540
 *
541
 * returns the size of mac created on success. A negative value will be returned
542
 *         in the case that an error happened.
543
 */
544
static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
545
                         const byte* psw, word32 pswSz, byte* out, word32 outSz)
546
0
{
547
0
    Hmac     hmac;
548
0
    MacData* mac;
549
0
    int ret, kLen;
550
0
    enum wc_HashType hashT;
551
0
    int idx = 0;
552
0
    int id  = 3; /* value from RFC 7292 indicating key is used for MAC */
553
0
    word32 i;
554
0
    byte unicodePasswd[MAX_UNICODE_SZ];
555
0
    byte key[PKCS_MAX_KEY_SIZE];
556
557
0
    if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL ||
558
0
            out == NULL) {
559
0
        return BAD_FUNC_ARG;
560
0
    }
561
562
0
    mac = pkcs12->signData;
563
564
    /* unicode set up from asn.c */
565
0
    if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
566
0
        WOLFSSL_MSG("PKCS12 max unicode size too small");
567
0
        return UNICODE_SIZE_E;
568
0
    }
569
570
0
    for (i = 0; i < pswSz; i++) {
571
0
        unicodePasswd[idx++] = 0x00;
572
0
        unicodePasswd[idx++] = (byte)psw[i];
573
0
    }
574
    /* add trailing NULL */
575
0
    unicodePasswd[idx++] = 0x00;
576
0
    unicodePasswd[idx++] = 0x00;
577
578
    /* get hash type used and resulting size of HMAC key */
579
0
    hashT = wc_OidGetHash((int)mac->oid);
580
0
    if (hashT == WC_HASH_TYPE_NONE) {
581
0
        ForceZero(unicodePasswd, MAX_UNICODE_SZ);
582
0
        WOLFSSL_MSG("Unsupported hash used");
583
0
        return BAD_FUNC_ARG;
584
0
    }
585
0
    kLen = wc_HashGetDigestSize(hashT);
586
587
    /* check out buffer is large enough */
588
0
    if (kLen < 0 || outSz < (word32)kLen) {
589
0
        ForceZero(unicodePasswd, MAX_UNICODE_SZ);
590
0
        return BAD_FUNC_ARG;
591
0
    }
592
593
    /* idx contains size of unicodePasswd */
594
0
    ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, (int)mac->saltSz,
595
0
                                  mac->itt, kLen, (int)hashT, id, pkcs12->heap);
596
0
    ForceZero(unicodePasswd, MAX_UNICODE_SZ);
597
0
    if (ret < 0) {
598
0
        return ret;
599
0
    }
600
601
    /* now that key has been created use it to get HMAC hash on data */
602
0
    if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) {
603
0
        return ret;
604
0
    }
605
0
    ret = wc_HmacSetKey(&hmac, (int)hashT, key, (word32)kLen);
606
0
    if (ret == 0)
607
0
        ret = wc_HmacUpdate(&hmac, data, dataSz);
608
0
    if (ret == 0)
609
0
        ret = wc_HmacFinal(&hmac, out);
610
0
    wc_HmacFree(&hmac);
611
612
0
    if (ret != 0)
613
0
        return ret;
614
615
0
    return kLen; /* same as digest size */
616
0
}
617
618
/* check mac on pkcs12, pkcs12->mac has been sanity checked before entering *
619
 * returns the result of comparison, success is 0 */
620
static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
621
                            const byte* psw, word32 pswSz)
622
0
{
623
0
    MacData* mac;
624
0
    int ret;
625
0
    byte digest[WC_MAX_DIGEST_SIZE];
626
627
0
    if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) {
628
0
        return BAD_FUNC_ARG;
629
0
    }
630
631
0
    mac = pkcs12->signData;
632
633
#ifdef WOLFSSL_DEBUG_PKCS12
634
    printf("Verifying MAC with OID = %d\n", mac->oid);
635
#endif
636
637
    /* check if this builds digest size is too small */
638
0
    if (mac->digestSz > WC_MAX_DIGEST_SIZE) {
639
0
        WOLFSSL_MSG("PKCS12 max digest size too small");
640
0
        return BAD_FUNC_ARG;
641
0
    }
642
643
0
    if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz,
644
0
            digest, WC_MAX_DIGEST_SIZE)) < 0) {
645
0
        return ret;
646
0
    }
647
648
#ifdef WOLFSSL_DEBUG_PKCS12
649
    {
650
        byte* p;
651
        for (printf("\t\tHash = "), p = (byte*)digest;
652
             p < (byte*)digest + mac->digestSz;
653
             printf("%02X", *p), p++);
654
        printf(" : size = %d\n", mac->digestSz);
655
    }
656
#endif
657
658
0
    return XMEMCMP(digest, mac->digest, mac->digestSz);
659
0
}
660
661
int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12, const byte* psw, word32 pswSz)
662
0
{
663
0
    if (pkcs12 == NULL || pkcs12->safe == NULL) {
664
0
        return BAD_FUNC_ARG;
665
0
    }
666
0
    return wc_PKCS12_verify(pkcs12, pkcs12->safe->data, pkcs12->safe->dataSz,
667
0
            psw, pswSz);
668
0
}
669
670
671
/* Convert DER format stored in der buffer to WC_PKCS12 struct
672
 * Puts the raw contents of Content Info into structure without completely
673
 * parsing or decoding.
674
 * der    : pointer to der buffer holding PKCS12
675
 * derSz  : size of der buffer
676
 * pkcs12 : non-null pkcs12 pointer
677
 * return 0 on success and negative on failure.
678
 */
679
int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12)
680
0
{
681
0
    word32 idx  = 0;
682
0
    word32 totalSz = 0;
683
0
    int ret;
684
0
    int size    = 0;
685
0
    int version = 0;
686
687
0
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12");
688
689
0
    if (der == NULL || pkcs12 == NULL) {
690
0
        return BAD_FUNC_ARG;
691
0
    }
692
693
0
    totalSz = derSz;
694
0
    if (GetSequence(der, &idx, &size, totalSz) < 0) {
695
0
        WOLFSSL_MSG("Failed to get PKCS12 sequence");
696
0
        return ASN_PARSE_E;
697
0
    }
698
699
    /* get version */
700
0
    if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) {
701
0
        return ret;
702
0
    }
703
704
0
    #ifdef ASN_BER_TO_DER
705
0
     if (size == 0) {
706
0
         if (wc_BerToDer(der, totalSz, NULL,
707
0
                         (word32*)&size) != LENGTH_ONLY_E) {
708
0
             WOLFSSL_MSG("Not BER sequence");
709
0
             return ASN_PARSE_E;
710
0
         }
711
712
0
         pkcs12->der = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
713
0
         if (pkcs12->der == NULL)
714
0
             return MEMORY_E;
715
0
         ret = wc_BerToDer(der, derSz, pkcs12->der, (word32*)&size);
716
0
         if (ret < 0) {
717
0
             return ret;
718
0
         }
719
720
0
         der  = pkcs12->der;
721
0
         pkcs12->derSz = (word32)size;
722
0
         totalSz = (word32)size;
723
0
         idx = 0;
724
725
0
         if (GetSequence(der, &idx, &size, totalSz) < 0) {
726
0
             WOLFSSL_MSG("Failed to get PKCS12 sequence");
727
0
             return ASN_PARSE_E;
728
0
         }
729
730
         /* get version */
731
0
         if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) {
732
0
             return ret;
733
0
         }
734
735
0
         pkcs12->indefinite = 1;
736
737
0
     }
738
0
     else
739
0
#endif /* ASN_BER_TO_DER */
740
0
    {
741
0
        pkcs12->indefinite = 0;
742
0
    }
743
744
#ifdef WOLFSSL_DEBUG_PKCS12
745
    printf("\nBEGIN: PKCS12 size = %d\n", totalSz);
746
    printf("version = %d\n", version);
747
#endif
748
749
0
    if (version != WC_PKCS12_VERSION_DEFAULT) {
750
0
        WOLFSSL_MSG("PKCS12 unsupported version!");
751
0
        WOLFSSL_ERROR_VERBOSE(ASN_VERSION_E);
752
0
        return ASN_VERSION_E;
753
0
    }
754
755
0
    if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
756
0
        return ret;
757
0
    }
758
759
#ifdef WOLFSSL_DEBUG_PKCS12
760
    printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size);
761
#endif
762
763
0
    if ((ret = GetSafeContent(pkcs12, der, &idx, (word32)size + idx)) < 0) {
764
0
        WOLFSSL_MSG("GetSafeContent error");
765
0
        return ret;
766
0
    }
767
768
0
#ifdef ASN_BER_TO_DER
769
    /* If indef, skip EOF */
770
0
    if (pkcs12->indefinite) {
771
0
        while((idx < totalSz) && (der[idx] == ASN_EOC)) {
772
0
            idx+=1;
773
0
        }
774
0
    }
775
0
#endif
776
777
    /* if more buffer left check for MAC data */
778
0
    if (idx < totalSz) {
779
0
        if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
780
0
            WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer");
781
0
        }
782
0
        else {
783
        #ifdef WOLFSSL_DEBUG_PKCS12
784
            printf("\tSEQUENCE: Signature size = %d\n", size);
785
        #endif
786
787
0
            if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) {
788
0
                return ASN_PARSE_E;
789
0
            }
790
0
        }
791
0
    }
792
793
#ifdef WOLFSSL_DEBUG_PKCS12
794
    printf("END: PKCS12\n");
795
#endif
796
797
0
    return ret;
798
0
}
799
800
#ifndef NO_FILESYSTEM
801
/* Parse the DER-encoded PKCS #12 object in the provided file. Populate the
802
 * WC_PKCS12 object pointed to by the passed in pointer, allocating the object
803
 * if necessary.
804
 *
805
 * file  : path to PKCS #12 file.
806
 * pkcs12: pointer to a pointer to a WC_PKCS12 object to populate. If *pkcs12 is
807
 *         NULL, this function will allocate a new WC_PKCS12.
808
 * return 0 on success and negative on failure.
809
 */
810
int wc_d2i_PKCS12_fp(const char* file, WC_PKCS12** pkcs12)
811
0
{
812
0
    int ret = 0;
813
0
    byte* buf = NULL;
814
0
    size_t bufSz = 0;
815
0
    WC_PKCS12* tmpPkcs12 = NULL;
816
0
    int callerAlloc = 1;
817
818
0
    WOLFSSL_ENTER("wc_d2i_PKCS12_fp");
819
820
0
    if (pkcs12 == NULL) {
821
0
        WOLFSSL_MSG("pkcs12 parameter NULL.");
822
0
        ret = BAD_FUNC_ARG;
823
0
    }
824
825
0
    if (ret == 0)
826
0
        ret = wc_FileLoad(file, &buf, &bufSz, NULL);
827
828
0
    if (ret == 0) {
829
0
        if (*pkcs12 == NULL) {
830
0
            tmpPkcs12 = wc_PKCS12_new();
831
0
            if (tmpPkcs12 == NULL) {
832
0
                WOLFSSL_MSG("Failed to allocate PKCS12 object.");
833
0
                ret = MEMORY_E;
834
0
            }
835
0
            else {
836
0
                *pkcs12 = tmpPkcs12;
837
0
                callerAlloc = 0;
838
0
            }
839
0
        }
840
0
    }
841
0
    if (ret == 0) {
842
0
        ret = wc_d2i_PKCS12(buf, (word32)bufSz, *pkcs12);
843
0
        if (ret != 0) {
844
0
            WOLFSSL_MSG("wc_d2i_PKCS12 failed.");
845
0
        }
846
0
    }
847
848
0
    if (ret != 0 && callerAlloc == 0 && *pkcs12 != NULL) {
849
0
        wc_PKCS12_free(*pkcs12);
850
0
        *pkcs12 = NULL;
851
0
    }
852
0
    if (buf != NULL) {
853
0
        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
854
0
    }
855
856
0
    WOLFSSL_LEAVE("wc_d2i_PKCS12_fp", ret);
857
858
0
    return ret;
859
0
}
860
#endif /* NO_FILESYSTEM */
861
862
/* Convert WC_PKCS12 struct to allocated DER buffer.
863
 * pkcs12 : non-null pkcs12 pointer
864
 * der    : pointer-pointer to der buffer. If NULL space will be
865
 *          allocated for der, which must be freed by application.
866
 * derSz  : size of buffer passed in when der is not NULL. NULL arg disables
867
 *          sanity checks on buffer read/writes. Max size gets set to derSz when
868
 *          the "der" buffer passed in is NULL and LENGTH_ONLY_E is returned.
869
 * return size of DER on success and negative on failure.
870
 */
871
int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz)
872
0
{
873
0
    int ret = 0;
874
0
    word32 seqSz = 0, verSz = 0, totalSz = 0, idx = 0, sdBufSz = 0;
875
0
    byte *buf = NULL;
876
0
    byte ver[MAX_VERSION_SZ];
877
0
    byte seq[MAX_SEQ_SZ];
878
0
    byte *sdBuf = NULL;
879
880
0
    if ((pkcs12 == NULL) || (pkcs12->safe == NULL) ||
881
0
            (der == NULL && derSz == NULL)) {
882
0
        return BAD_FUNC_ARG;
883
0
    }
884
885
    /* Create the MAC portion */
886
0
    if (pkcs12->signData != NULL) {
887
0
        MacData *mac = (MacData*)pkcs12->signData;
888
0
        word32 innerSz = 0;
889
0
        word32 outerSz = 0;
890
891
        /* get exact size */
892
0
        {
893
0
            byte ASNLENGTH[MAX_LENGTH_SZ];
894
0
            byte ASNSHORT[MAX_SHORT_SZ];
895
0
            byte ASNALGO[MAX_ALGO_SZ];
896
0
            word32 tmpIdx = 0;
897
898
            /* algo id */
899
0
            innerSz += SetAlgoID((int)mac->oid, ASNALGO, oidHashType, 0);
900
901
            /* Octet string holding digest */
902
0
            innerSz += ASN_TAG_SZ;
903
0
            innerSz += SetLength(mac->digestSz, ASNLENGTH);
904
0
            innerSz += mac->digestSz;
905
906
            /* salt */
907
0
            outerSz += ASN_TAG_SZ;
908
0
            outerSz += SetLength(mac->saltSz, ASNLENGTH);
909
0
            outerSz += mac->saltSz;
910
911
            /* MAC iterations */
912
0
            ret = SetShortInt(ASNSHORT, &tmpIdx, (word32)mac->itt, MAX_SHORT_SZ);
913
0
            if (ret >= 0) {
914
0
                outerSz += (word32)ret;
915
0
                ret = 0;
916
0
            }
917
0
            else {
918
0
                return ret;
919
0
            }
920
921
            /* sequence of inner data */
922
0
            outerSz += SetSequence(innerSz, seq);
923
0
            outerSz += innerSz;
924
0
        }
925
0
        sdBufSz = outerSz + SetSequence(outerSz, seq);
926
0
        sdBuf = (byte*)XMALLOC(sdBufSz, pkcs12->heap, DYNAMIC_TYPE_PKCS);
927
0
        if (sdBuf == NULL) {
928
0
            ret = MEMORY_E;
929
0
        }
930
931
0
        if (ret == 0) {
932
0
            idx += SetSequence(outerSz, sdBuf);
933
0
            idx += SetSequence(innerSz, &sdBuf[idx]);
934
935
            /* Set Algorithm Identifier */
936
0
            {
937
0
                word32 algoIdSz;
938
939
0
                algoIdSz = SetAlgoID((int)mac->oid, &sdBuf[idx], oidHashType, 0);
940
0
                if (algoIdSz == 0) {
941
0
                    ret = ALGO_ID_E;
942
0
                }
943
0
                else {
944
0
                    idx += algoIdSz;
945
0
                }
946
0
            }
947
0
        }
948
949
0
        if (ret == 0) {
950
951
952
            /* Octet string holding digest */
953
0
            idx += SetOctetString(mac->digestSz, &sdBuf[idx]);
954
0
            XMEMCPY(&sdBuf[idx], mac->digest, mac->digestSz);
955
0
            idx += mac->digestSz;
956
957
            /* Set salt */
958
0
            idx += SetOctetString(mac->saltSz, &sdBuf[idx]);
959
0
            XMEMCPY(&sdBuf[idx], mac->salt, mac->saltSz);
960
0
            idx += mac->saltSz;
961
962
            /* MAC iterations */
963
0
            {
964
0
                int tmpSz;
965
0
                word32 tmpIdx = 0;
966
0
                byte ar[MAX_SHORT_SZ];
967
0
                tmpSz = SetShortInt(ar, &tmpIdx, (word32)mac->itt, MAX_SHORT_SZ);
968
0
                if (tmpSz < 0) {
969
0
                    ret = tmpSz;
970
0
                }
971
0
                else {
972
0
                    XMEMCPY(&sdBuf[idx], ar, (size_t)tmpSz);
973
0
                }
974
0
            }
975
0
            totalSz += sdBufSz;
976
0
        }
977
0
    }
978
979
    /* Calculate size of der */
980
0
    if (ret == 0) {
981
0
        totalSz += pkcs12->safe->dataSz;
982
983
0
        totalSz += 4; /* Octet string */
984
985
0
        totalSz += 4; /* Element */
986
987
0
        totalSz += 2 + sizeof(WC_PKCS12_DATA_OID);
988
989
0
        totalSz += 4; /* Seq */
990
991
0
        ret = SetMyVersion(WC_PKCS12_VERSION_DEFAULT, ver, FALSE);
992
0
        if (ret > 0) {
993
0
            verSz = (word32)ret;
994
0
            ret   = 0; /* value larger than 0 is success */
995
0
            totalSz += verSz;
996
997
0
            seqSz = SetSequence(totalSz, seq);
998
0
            totalSz += seqSz;
999
1000
            /* check if getting length only */
1001
0
            if (der == NULL && derSz != NULL) {
1002
0
                *derSz = (int)totalSz;
1003
0
                XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1004
0
                return LENGTH_ONLY_E;
1005
0
            }
1006
1007
0
            if (*der == NULL) {
1008
                /* Allocate if requested */
1009
0
                buf = (byte*)XMALLOC(totalSz, NULL, DYNAMIC_TYPE_PKCS);
1010
0
            }
1011
0
            else {
1012
0
                buf = *der;
1013
1014
                /* sanity check on buffer size if passed in */
1015
0
                if (derSz != NULL) {
1016
0
                    if (*derSz < (int)totalSz) {
1017
0
                        WOLFSSL_MSG("Buffer passed in is too small");
1018
0
                        ret = BUFFER_E;
1019
0
                    }
1020
0
                }
1021
0
            }
1022
0
        }
1023
0
    }
1024
1025
0
    if (buf == NULL) {
1026
0
        ret = MEMORY_E;
1027
0
    }
1028
1029
0
    if (ret == 0) {
1030
0
        idx = 0;
1031
1032
        /* Copy parts to buf */
1033
0
        XMEMCPY(&buf[idx], seq, seqSz);
1034
0
        idx += seqSz;
1035
1036
0
        XMEMCPY(&buf[idx], ver, verSz);
1037
0
        idx += verSz;
1038
1039
0
        seqSz = SetSequence(totalSz - sdBufSz - idx - 4, seq);
1040
0
        XMEMCPY(&buf[idx], seq, seqSz);
1041
0
        idx += seqSz;
1042
1043
        /* OID */
1044
0
        idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), &buf[idx]);
1045
0
        XMEMCPY(&buf[idx], WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
1046
0
        idx += sizeof(WC_PKCS12_DATA_OID);
1047
1048
        /* Element */
1049
0
        buf[idx++] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC;
1050
0
        idx += SetLength(totalSz - sdBufSz - idx - 3, &buf[idx]);
1051
1052
        /* Octet string */
1053
0
        idx += SetOctetString(totalSz - sdBufSz - idx - 4, &buf[idx]);
1054
1055
0
        XMEMCPY(&buf[idx], pkcs12->safe->data, pkcs12->safe->dataSz);
1056
0
        idx += pkcs12->safe->dataSz;
1057
1058
0
        if (pkcs12->signData != NULL) {
1059
0
            XMEMCPY(&buf[idx], sdBuf, sdBufSz);
1060
0
        }
1061
1062
0
        if (*der == NULL) {
1063
            /* Point to start of data allocated for DER */
1064
0
            *der = buf;
1065
0
        }
1066
0
        else {
1067
            /* Increment pointer to byte past DER */
1068
0
            *der = &buf[totalSz];
1069
0
        }
1070
1071
        /* Return size of der */
1072
0
        ret = (int)totalSz;
1073
0
    }
1074
1075
0
    XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1076
    /* Allocation of buf was the last time ret could be a failure,
1077
     * so no need to free here */
1078
1079
0
    return ret;
1080
0
}
1081
1082
1083
/* helper function to free WC_DerCertList */
1084
void wc_FreeCertList(WC_DerCertList* list, void* heap)
1085
0
{
1086
0
    WC_DerCertList* current = list;
1087
0
    WC_DerCertList* next;
1088
1089
0
    if (list == NULL) {
1090
0
        return;
1091
0
    }
1092
1093
0
    while (current != NULL) {
1094
0
        next = current->next;
1095
0
        if (current->buffer != NULL) {
1096
0
            XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
1097
0
        }
1098
0
        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
1099
0
        current = next;
1100
0
    }
1101
1102
0
    (void)heap;
1103
0
}
1104
1105
static WARN_UNUSED_RESULT int freeDecCertList(WC_DerCertList** list,
1106
    byte** pkey, word32* pkeySz, byte** cert, word32* certSz, void* heap)
1107
0
{
1108
0
    WC_DerCertList* current  = *list;
1109
0
    WC_DerCertList* previous = NULL;
1110
0
#ifdef WOLFSSL_SMALL_STACK
1111
0
    DecodedCert *DeCert = (DecodedCert *)XMALLOC(
1112
0
        sizeof(*DeCert), heap, DYNAMIC_TYPE_PKCS);
1113
0
    if (DeCert == NULL)
1114
0
        return MEMORY_E;
1115
#else
1116
    DecodedCert DeCert[1];
1117
#endif
1118
1119
0
    while (current != NULL) {
1120
1121
0
        InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
1122
0
        if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) {
1123
0
            if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert) == 1) {
1124
0
                WOLFSSL_MSG("Key Pair found");
1125
0
                *cert = current->buffer;
1126
0
                *certSz = current->bufferSz;
1127
1128
0
                if (previous == NULL) {
1129
0
                    *list = current->next;
1130
0
                }
1131
0
                else {
1132
0
                    previous->next = current->next;
1133
0
                }
1134
0
                FreeDecodedCert(DeCert);
1135
0
                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
1136
0
                break;
1137
0
            }
1138
0
        }
1139
0
        FreeDecodedCert(DeCert);
1140
1141
0
        previous = current;
1142
0
        current  = current->next;
1143
0
    }
1144
1145
0
#ifdef WOLFSSL_SMALL_STACK
1146
0
    XFREE(DeCert, heap, DYNAMIC_TYPE_PKCS);
1147
0
#endif
1148
1149
0
    return 0;
1150
0
}
1151
1152
#ifdef ASN_BER_TO_DER
1153
/* append data to encrypted content cache in PKCS12 structure
1154
 * return buffer on success, NULL on error */
1155
static byte* PKCS12_ConcatonateContent(WC_PKCS12* pkcs12,byte* mergedData,
1156
        word32* mergedSz, byte* in, word32 inSz)
1157
0
{
1158
0
    byte* oldContent;
1159
0
    word32 oldContentSz;
1160
1161
0
    (void)pkcs12;
1162
1163
0
    if (mergedData == NULL || in == NULL)
1164
0
        return NULL;
1165
1166
    /* save pointer to old cache */
1167
0
    oldContent = mergedData;
1168
0
    oldContentSz = *mergedSz;
1169
1170
    /* re-allocate new buffer to fit appended data */
1171
0
    mergedData = (byte*)XMALLOC(oldContentSz + inSz, pkcs12->heap,
1172
0
            DYNAMIC_TYPE_PKCS);
1173
0
    if (mergedData != NULL) {
1174
0
        if (oldContent != NULL) {
1175
0
            XMEMCPY(mergedData, oldContent, oldContentSz);
1176
0
        }
1177
0
        XMEMCPY(mergedData + oldContentSz, in, inSz);
1178
0
        *mergedSz += inSz;
1179
0
    }
1180
0
    XFREE(oldContent, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1181
1182
0
    return mergedData;
1183
0
}
1184
1185
/* Check if constructed [0] is seen after wc_BerToDer() or not.
1186
 * returns 1 if seen, 0 if not, ASN_PARSE_E on error */
1187
static int PKCS12_CheckConstructedZero(byte* data, word32 dataSz, word32* idx)
1188
0
{
1189
0
    word32 oid;
1190
0
    int    ret = 0;
1191
0
    int    number, size;
1192
0
    byte   tag = 0;
1193
1194
0
    if (GetSequence(data, idx, &size, dataSz) < 0) {
1195
0
        ret = ASN_PARSE_E;
1196
0
    }
1197
1198
0
    if (ret == 0 && GetObjectId(data, idx, &oid, oidIgnoreType, dataSz)) {
1199
0
        ret = ASN_PARSE_E;
1200
0
    }
1201
1202
0
    if (ret == 0 && GetSequence(data, idx, &size, dataSz) < 0) {
1203
0
        ret = ASN_PARSE_E;
1204
0
    }
1205
1206
0
    if (ret == 0 && GetOctetString(data, idx, &size, dataSz) < 0) {
1207
0
        ret = ASN_PARSE_E;
1208
0
    }
1209
1210
0
    *idx += (word32)size;
1211
0
    if (ret == 0 && GetShortInt(data, idx, &number, dataSz) < 0) {
1212
0
        ret = ASN_PARSE_E;
1213
0
    }
1214
1215
    /* Check if wc_BerToDer() handled constructed [0] and octet
1216
     * strings properly, manually fix it if not. */
1217
0
    if (ret == 0 && GetASNTag(data, idx, &tag, dataSz) < 0) {
1218
0
        ret = ASN_PARSE_E;
1219
0
    }
1220
0
    else if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1221
0
        ret = 1;
1222
0
    }
1223
1224
0
    return ret;
1225
0
}
1226
1227
/* Manually coalesce definite length octet strings into one unconstructed
1228
 * definite length octet string.
1229
 * returns 0 on success, negative on failure */
1230
static int PKCS12_CoalesceOctetStrings(WC_PKCS12* pkcs12, byte* data,
1231
        word32 dataSz, word32* idx, int* curIdx)
1232
0
{
1233
0
    byte*  mergedData = NULL; /* buffer for concatenated strings */
1234
0
    word32 mergedSz = 0;      /* total size of merged strings */
1235
0
    int    encryptedContentSz = 0;
1236
0
    int    originalEncSz = 0;
1237
0
    int    ret = 0;
1238
0
    word32 saveIdx;
1239
0
    byte   tag;
1240
1241
0
    saveIdx = *idx;
1242
1243
0
    if (GetLength(data, idx, &originalEncSz, dataSz) < 0) {
1244
0
        ret = ASN_PARSE_E;
1245
0
    }
1246
1247
    /* Loop through octet strings and concatenate them without
1248
     * the tags and length */
1249
0
    while ((int)*idx < originalEncSz + *curIdx) {
1250
0
        if (GetASNTag(data, idx, &tag, dataSz) < 0) {
1251
0
            ret = ASN_PARSE_E;
1252
0
        }
1253
0
        if (ret == 0 && (tag != ASN_OCTET_STRING)) {
1254
0
            ret = ASN_PARSE_E;
1255
0
        }
1256
0
        if (ret == 0 && GetLength(data, idx,
1257
0
                    &encryptedContentSz, dataSz) <= 0) {
1258
0
            ret = ASN_PARSE_E;
1259
0
        }
1260
0
        if (ret == 0) {
1261
0
            if (mergedData == NULL) {
1262
0
                mergedData = (byte*)XMALLOC((size_t)encryptedContentSz,
1263
0
                            pkcs12->heap, DYNAMIC_TYPE_PKCS);
1264
0
                if (mergedData == NULL) {
1265
0
                    ret = MEMORY_E;
1266
0
                }
1267
0
            }
1268
0
            mergedData = PKCS12_ConcatonateContent(pkcs12, mergedData,
1269
0
                    &mergedSz, &data[*idx], (word32)encryptedContentSz);
1270
0
            if (mergedData == NULL) {
1271
0
                ret = MEMORY_E;
1272
0
            }
1273
0
        }
1274
0
        if (ret != 0) {
1275
0
            break;
1276
0
        }
1277
0
        *idx += (word32)encryptedContentSz;
1278
0
    }
1279
1280
0
    *idx = saveIdx;
1281
1282
0
    *idx += SetLength(mergedSz, &data[*idx]);
1283
1284
0
    if (mergedSz > 0) {
1285
        /* Copy over concatenated octet strings into data buffer */
1286
0
        XMEMCPY(&data[*idx], mergedData, mergedSz);
1287
1288
0
        XFREE(mergedData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1289
0
    }
1290
1291
0
    return ret;
1292
0
}
1293
#endif
1294
1295
/* return 0 on success and negative on failure.
1296
 * By side effect returns private key, cert, and optionally ca.
1297
 * Parses and decodes the parts of PKCS12
1298
 *
1299
 * NOTE: can parse with USER RSA enabled but may return cert that is not the
1300
 *       pair for the key when using RSA key pairs.
1301
 *
1302
 * pkcs12 : non-null WC_PKCS12 struct
1303
 * psw    : password to use for PKCS12 decode
1304
 * pkey   : Private key returned
1305
 * cert   : x509 cert returned
1306
 * ca     : optional ca returned
1307
 */
1308
int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
1309
        byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
1310
        WC_DerCertList** ca)
1311
0
{
1312
0
    ContentInfo* ci       = NULL;
1313
0
    WC_DerCertList* certList = NULL;
1314
0
    WC_DerCertList* tailList = NULL;
1315
0
    byte* buf             = NULL;
1316
0
    word32 i, oid;
1317
0
    word32 algId;
1318
0
    int ret, pswSz;
1319
0
#ifdef ASN_BER_TO_DER
1320
0
    int curIdx;
1321
0
#endif
1322
1323
0
    WOLFSSL_ENTER("wc_PKCS12_parse");
1324
1325
0
    if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL ||
1326
0
        pkey == NULL   || pkeySz == NULL) {
1327
0
        return BAD_FUNC_ARG;
1328
0
    }
1329
1330
0
    pswSz = (int)XSTRLEN(psw);
1331
0
    *cert = NULL;
1332
0
    *pkey = NULL;
1333
0
    if (ca != NULL)
1334
0
        *ca = NULL;
1335
1336
    /* if there is sign data then verify the MAC */
1337
0
    if (pkcs12->signData != NULL ) {
1338
0
        if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data,
1339
0
                               pkcs12->safe->dataSz, (byte*)psw, (word32)pswSz)) != 0) {
1340
0
            WOLFSSL_MSG("PKCS12 Bad MAC on verify");
1341
0
            WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret);
1342
0
            (void)ret;
1343
0
            return MAC_CMP_FAILED_E;
1344
0
        }
1345
0
    }
1346
1347
0
    if (pkcs12->safe == NULL) {
1348
0
        WOLFSSL_MSG("No PKCS12 safes to parse");
1349
0
        return BAD_FUNC_ARG;
1350
0
    }
1351
1352
    /* Decode content infos */
1353
0
    ci = pkcs12->safe->CI;
1354
0
    for (i = 0; i < pkcs12->safe->numCI; i++) {
1355
0
        byte*  data;
1356
0
        word32 idx = 0;
1357
0
        int    size, totalSz;
1358
0
        byte   tag;
1359
1360
0
        data = ci->data;
1361
1362
0
        if (ci->type == WC_PKCS12_ENCRYPTED_DATA) {
1363
0
            int number;
1364
1365
0
            WOLFSSL_MSG("Decrypting PKCS12 Content Info Container");
1366
0
            if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1367
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1368
0
            }
1369
1370
0
            if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1371
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1372
0
            }
1373
0
            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
1374
0
                goto exit_pk12par;
1375
0
            }
1376
1377
0
            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
1378
0
                goto exit_pk12par;
1379
0
            }
1380
1381
0
            if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) {
1382
0
                goto exit_pk12par;
1383
0
            }
1384
1385
0
            if (number != 0) {
1386
0
                WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12");
1387
0
            }
1388
1389
0
            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
1390
0
                goto exit_pk12par;
1391
0
            }
1392
1393
0
            ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz);
1394
0
            if (ret < 0 || oid != WC_PKCS12_DATA) {
1395
0
                WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error");
1396
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1397
0
            }
1398
1399
1400
0
#ifdef ASN_BER_TO_DER
1401
0
            curIdx = (int)idx;
1402
            /* If indefinite length format, ensure it is in the ASN format
1403
             * the DecryptContent() expects */
1404
0
            if (pkcs12->indefinite && PKCS12_CheckConstructedZero(data,
1405
0
                                                    ci->dataSz, &idx) == 1) {
1406
0
                data[idx-1] = ASN_LONG_LENGTH;
1407
0
                ret = PKCS12_CoalesceOctetStrings(pkcs12, data, ci->dataSz,
1408
0
                                                  &idx, &curIdx);
1409
0
                if (ret < 0) {
1410
0
                    goto exit_pk12par;
1411
0
                }
1412
0
            }
1413
0
            idx = (word32)curIdx;
1414
0
#endif
1415
1416
        /* decrypted content overwrites input buffer */
1417
0
            size = (int)(ci->dataSz - idx);
1418
0
            buf = (byte*)XMALLOC((size_t)size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1419
0
            if (buf == NULL) {
1420
0
                ERROR_OUT(MEMORY_E, exit_pk12par);
1421
0
            }
1422
0
            XMEMCPY(buf, data + idx, (size_t)size);
1423
1424
0
            if ((ret = DecryptContent(buf, (word32)size, psw, pswSz)) < 0) {
1425
0
                WOLFSSL_MSG("Decryption failed, algorithm not compiled in?");
1426
0
                goto exit_pk12par;
1427
0
            }
1428
1429
0
            data = buf;
1430
0
            idx = 0;
1431
1432
        #ifdef WOLFSSL_DEBUG_PKCS12
1433
            {
1434
                byte* p;
1435
                for (printf("\tData = "), p = (byte*)buf;
1436
                    p < (byte*)buf + size;
1437
                    printf("%02X", *p), p++);
1438
                printf("\n");
1439
            }
1440
        #endif
1441
0
        }
1442
0
        else { /* type DATA */
1443
0
            WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container");
1444
0
            if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1445
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1446
0
            }
1447
1448
0
            if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1449
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1450
0
            }
1451
0
            if (GetLength(data, &idx, &size, ci->dataSz) <= 0) {
1452
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1453
0
            }
1454
1455
0
            if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1456
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1457
0
            }
1458
0
            if (tag != ASN_OCTET_STRING) {
1459
0
                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1460
0
            }
1461
0
            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
1462
0
                goto exit_pk12par;
1463
0
            }
1464
1465
0
        }
1466
1467
        /* parse through bags in ContentInfo */
1468
0
        if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) {
1469
0
            goto exit_pk12par;
1470
0
        }
1471
0
        totalSz += (int)idx;
1472
1473
0
        while ((int)idx < totalSz) {
1474
0
            int bagSz;
1475
0
            if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) {
1476
0
                goto exit_pk12par;
1477
0
            }
1478
0
            bagSz += (int)idx;
1479
1480
0
            if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
1481
0
                                                             ci->dataSz)) < 0) {
1482
0
                goto exit_pk12par;
1483
0
            }
1484
1485
0
            switch (oid) {
1486
0
                case WC_PKCS12_KeyBag: /* 667 */
1487
0
                    WOLFSSL_MSG("PKCS12 Key Bag found");
1488
0
                    if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1489
0
                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1490
0
                    }
1491
0
                    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1492
0
                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1493
0
                    }
1494
0
                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
1495
0
                        if (ret == 0)
1496
0
                            ret = ASN_PARSE_E;
1497
0
                        goto exit_pk12par;
1498
0
                    }
1499
0
                    if (*pkey == NULL) {
1500
0
                        *pkey = (byte*)XMALLOC((size_t)size, pkcs12->heap,
1501
0
                                                       DYNAMIC_TYPE_PUBLIC_KEY);
1502
0
                        if (*pkey == NULL) {
1503
0
                            ERROR_OUT(MEMORY_E, exit_pk12par);
1504
0
                        }
1505
0
                        XMEMCPY(*pkey, data + idx, (size_t)size);
1506
0
                        *pkeySz = (word32)ToTraditional_ex(*pkey, (word32)size, &algId);
1507
0
                    }
1508
1509
                #ifdef WOLFSSL_DEBUG_PKCS12
1510
                    {
1511
                        byte* p;
1512
                        for (printf("\tKey = "), p = (byte*)*pkey;
1513
                            p < (byte*)*pkey + size;
1514
                            printf("%02X", *p), p++);
1515
                        printf("\n");
1516
                    }
1517
                #endif
1518
0
                    idx += (word32)size;
1519
0
                    break;
1520
1521
0
                case WC_PKCS12_ShroudedKeyBag: /* 668 */
1522
0
                    {
1523
0
                        byte* k;
1524
1525
0
                        WOLFSSL_MSG("PKCS12 Shrouded Key Bag found");
1526
0
                        if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1527
0
                            ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1528
0
                        }
1529
0
                        if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1530
0
                            ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1531
0
                        }
1532
0
                        if ((ret = GetLength(data, &idx, &size,
1533
0
                                                             ci->dataSz)) < 0) {
1534
0
                            goto exit_pk12par;
1535
0
                        }
1536
1537
0
                        k = (byte*)XMALLOC((size_t)size, pkcs12->heap,
1538
0
                                                       DYNAMIC_TYPE_PUBLIC_KEY);
1539
0
                        if (k == NULL) {
1540
0
                            ERROR_OUT(MEMORY_E, exit_pk12par);
1541
0
                        }
1542
0
                        XMEMCPY(k, data + idx, (size_t)size);
1543
1544
                        /* overwrites input, be warned */
1545
0
                        if ((ret = ToTraditionalEnc(k, (word32)size, psw, pswSz,
1546
0
                                                                 &algId)) < 0) {
1547
0
                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1548
0
                            goto exit_pk12par;
1549
0
                        }
1550
1551
0
                        if (ret < size) {
1552
                            /* shrink key buffer */
1553
0
                            byte* tmp = (byte*)XMALLOC((size_t)ret, pkcs12->heap,
1554
0
                                                 DYNAMIC_TYPE_PUBLIC_KEY);
1555
0
                            if (tmp == NULL) {
1556
0
                                XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1557
0
                                ERROR_OUT(MEMORY_E, exit_pk12par);
1558
0
                            }
1559
0
                            XMEMCPY(tmp, k, (size_t)ret);
1560
0
                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1561
0
                            k = tmp;
1562
0
                        }
1563
0
                        size = ret;
1564
1565
0
                        if (*pkey == NULL) {
1566
0
                            *pkey = k;
1567
0
                            *pkeySz = (word32)size;
1568
0
                        }
1569
0
                        else { /* only expecting one key */
1570
0
                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1571
0
                        }
1572
0
                        idx += (word32)size;
1573
1574
                    #ifdef WOLFSSL_DEBUG_PKCS12
1575
                        {
1576
                            byte* p;
1577
                            for (printf("\tKey = "), p = (byte*)k;
1578
                                p < (byte*)k + ret;
1579
                                printf("%02X", *p), p++);
1580
                            printf("\n");
1581
                        }
1582
                    #endif
1583
0
                    }
1584
0
                    break;
1585
1586
0
                case WC_PKCS12_CertBag: /* 669 */
1587
0
                {
1588
0
                    WC_DerCertList* node;
1589
0
                    WOLFSSL_MSG("PKCS12 Cert Bag found");
1590
0
                    if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1591
0
                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1592
0
                    }
1593
0
                    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
1594
0
                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1595
0
                    }
1596
0
                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
1597
0
                        goto exit_pk12par;
1598
0
                    }
1599
1600
                    /* get cert bag type */
1601
0
                    if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) {
1602
0
                        goto exit_pk12par;
1603
0
                    }
1604
1605
0
                    if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
1606
0
                                                             ci->dataSz)) < 0) {
1607
0
                        goto exit_pk12par;
1608
0
                    }
1609
1610
0
                    switch (oid) {
1611
0
                        case WC_PKCS12_CertBag_Type1:  /* 675 */
1612
                            /* type 1 */
1613
0
                            WOLFSSL_MSG("PKCS12 cert bag type 1");
1614
0
                            if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1615
0
                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1616
0
                            }
1617
0
                            if (tag != (ASN_CONSTRUCTED |
1618
0
                                        ASN_CONTEXT_SPECIFIC)) {
1619
0
                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1620
0
                            }
1621
0
                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
1622
0
                                                                         <= 0) {
1623
0
                                if (ret == 0)
1624
0
                                    ret = ASN_PARSE_E;
1625
0
                                goto exit_pk12par;
1626
0
                            }
1627
0
                            if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) {
1628
0
                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1629
0
                            }
1630
0
                            if (tag != ASN_OCTET_STRING) {
1631
0
                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1632
1633
0
                            }
1634
0
                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
1635
0
                                                                          < 0) {
1636
0
                                goto exit_pk12par;
1637
0
                            }
1638
0
                            break;
1639
0
                       default:
1640
0
                            WOLFSSL_MSG("Unknown PKCS12 cert bag type");
1641
0
                    }
1642
1643
0
                    if (size + (int)idx > bagSz) {
1644
0
                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
1645
0
                    }
1646
1647
                    /* list to hold all certs found */
1648
0
                    node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList),
1649
0
                                               pkcs12->heap, DYNAMIC_TYPE_PKCS);
1650
0
                    if (node == NULL) {
1651
0
                        ERROR_OUT(MEMORY_E, exit_pk12par);
1652
0
                    }
1653
0
                    XMEMSET(node, 0, sizeof(WC_DerCertList));
1654
1655
0
                    node->buffer = (byte*)XMALLOC((size_t)size, pkcs12->heap,
1656
0
                                                             DYNAMIC_TYPE_PKCS);
1657
0
                    if (node->buffer == NULL) {
1658
0
                        XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1659
0
                        ERROR_OUT(MEMORY_E, exit_pk12par);
1660
0
                    }
1661
0
                    XMEMCPY(node->buffer, data + idx, (size_t)size);
1662
0
                    node->bufferSz = (word32)size;
1663
1664
                    /* put the new node into the list */
1665
0
                    if (certList != NULL) {
1666
0
                        WOLFSSL_MSG("Pushing new cert onto queue");
1667
0
                        tailList->next = node;
1668
0
                        tailList = node;
1669
0
                    }
1670
0
                    else {
1671
0
                        certList = node;
1672
0
                        tailList = node;
1673
0
                    }
1674
1675
                    /* on to next */
1676
0
                    idx += (word32)size;
1677
0
                }
1678
0
                    break;
1679
1680
0
                case WC_PKCS12_CrlBag: /* 670 */
1681
0
                    WOLFSSL_MSG("PKCS12 CRL BAG not yet supported");
1682
0
                    break;
1683
1684
0
                case WC_PKCS12_SecretBag: /* 671 */
1685
0
                    WOLFSSL_MSG("PKCS12 Secret BAG not yet supported");
1686
0
                    break;
1687
1688
0
                case WC_PKCS12_SafeContentsBag: /* 672 */
1689
0
                    WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported");
1690
0
                    break;
1691
1692
0
                default:
1693
0
                    WOLFSSL_MSG("Unknown PKCS12 BAG type found");
1694
0
            }
1695
1696
            /* Attribute, unknown bag or unsupported */
1697
0
            if ((int)idx < bagSz) {
1698
0
                idx = (word32)bagSz; /* skip for now */
1699
0
            }
1700
0
        }
1701
1702
        /* free temporary buffer */
1703
0
        if (buf != NULL) {
1704
0
            XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1705
0
            buf = NULL;
1706
0
        }
1707
1708
0
        ci = ci->next;
1709
0
        WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container");
1710
0
    }
1711
1712
    /* check if key pair, remove from list */
1713
0
    if (*pkey != NULL) {
1714
0
        ret = freeDecCertList(&certList, pkey, pkeySz, cert, certSz,
1715
0
                              pkcs12->heap);
1716
0
        if (ret < 0)
1717
0
            goto exit_pk12par;
1718
0
    }
1719
1720
    /* if ca arg provided return certList, otherwise free it */
1721
0
    if (ca != NULL) {
1722
0
        *ca = certList;
1723
0
    }
1724
0
    else {
1725
        /* free list, not wanted */
1726
0
        wc_FreeCertList(certList, pkcs12->heap);
1727
0
    }
1728
0
    (void)tailList; /* not used */
1729
1730
0
    ret = 0; /* success */
1731
1732
0
exit_pk12par:
1733
1734
0
    if (ret != 0) {
1735
        /* failure cleanup */
1736
0
        if (*pkey) {
1737
0
            XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1738
0
            *pkey = NULL;
1739
0
        }
1740
0
        if (buf) {
1741
0
            XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
1742
0
            buf = NULL;
1743
0
        }
1744
1745
0
        wc_FreeCertList(certList, pkcs12->heap);
1746
0
    }
1747
1748
0
    return ret;
1749
0
}
1750
1751
1752
/* Helper function to shroud keys.
1753
 *
1754
 * pkcs12 structure to use with shrouding key
1755
 * rng    random number generator used
1756
 * out    buffer to hold results
1757
 * outSz  size of out buffer
1758
 * key    key that is going to be shrouded
1759
 * keySz  size of key buffer
1760
 * vAlgo  algorithm version
1761
 * pass   password to use
1762
 * passSz size of pass buffer
1763
 * itt    number of iterations
1764
 *
1765
 * returns the size of the shrouded key on success
1766
 */
1767
static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
1768
        byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo,
1769
        const char* pass, int passSz, int itt)
1770
0
{
1771
0
    void* heap;
1772
0
    word32 tmpIdx = 0;
1773
0
    int vPKCS     = 1; /* PKCS#12 default set to 1 */
1774
0
    word32 sz;
1775
0
    word32 totalSz = 0;
1776
0
    int ret;
1777
0
    byte* pkcs8Key = NULL;
1778
1779
0
    if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL ||
1780
0
            pass == NULL) {
1781
0
        return BAD_FUNC_ARG;
1782
0
    }
1783
1784
0
    heap = wc_PKCS12_GetHeap(pkcs12);
1785
1786
    /* check if trying to get size */
1787
0
    if (out != NULL) {
1788
0
        tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */
1789
0
        sz = *outSz - tmpIdx;
1790
0
        pkcs8Key = out + tmpIdx;
1791
0
    }
1792
1793
    /* case of no encryption */
1794
0
    if (vAlgo < 0) {
1795
0
        const byte* curveOID = NULL;
1796
0
        word32 oidSz = 0;
1797
0
        int algoID;
1798
1799
0
        WOLFSSL_MSG("creating PKCS12 Key Bag");
1800
1801
        /* check key type and get OID if ECC */
1802
0
        if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))
1803
0
                < 0) {
1804
0
            return ret;
1805
0
        }
1806
1807
        /* PKCS#8 wrapping around key */
1808
0
        ret = wc_CreatePKCS8Key(pkcs8Key, &sz, key, keySz, algoID, curveOID,
1809
0
                oidSz);
1810
0
    }
1811
0
    else {
1812
0
        WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag");
1813
1814
0
        if (vAlgo == PBE_SHA1_DES) {
1815
0
            vPKCS = PKCS5;
1816
0
            vAlgo = 10;
1817
0
        }
1818
1819
0
        ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz,
1820
0
                vPKCS, vAlgo, NULL, 0, itt, rng, heap);
1821
0
    }
1822
0
    if (ret == LENGTH_ONLY_E) {
1823
0
        *outSz =  sz + MAX_LENGTH_SZ + 1;
1824
0
        return LENGTH_ONLY_E;
1825
0
    }
1826
0
    if (ret < 0) {
1827
0
        return ret;
1828
0
    }
1829
1830
0
    totalSz += (word32)ret;
1831
1832
    /* out should not be null at this point but check before writing */
1833
0
    if (out == NULL) {
1834
0
        return BAD_FUNC_ARG;
1835
0
    }
1836
1837
    /* rewind index and set tag and length */
1838
0
    tmpIdx -= MAX_LENGTH_SZ + 1;
1839
0
    sz = (word32)SetExplicit(0, (word32)ret, out + tmpIdx);
1840
0
    tmpIdx += sz; totalSz += sz;
1841
0
    XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, (size_t)ret);
1842
1843
0
    return (int)totalSz;
1844
0
}
1845
1846
1847
/* Helper function to create key bag.
1848
 *
1849
 * pkcs12 structure to use with key bag
1850
 * rng    random number generator used
1851
 * out    buffer to hold results
1852
 * outSz  size of out buffer
1853
 * key    key that is going into key bag
1854
 * keySz  size of key buffer
1855
 * algo   algorithm version
1856
 * iter   number of iterations
1857
 * pass   password to use
1858
 * passSz size of pass buffer
1859
 *
1860
 * returns the size of the key bag on success
1861
 */
1862
static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng,
1863
        byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter,
1864
        char* pass, int passSz)
1865
0
{
1866
0
    void* heap;
1867
0
    byte* tmp;
1868
0
    word32 length  = 0;
1869
0
    word32 idx     = 0;
1870
0
    word32 totalSz = 0;
1871
0
    word32 sz;
1872
0
    word32 i;
1873
0
    word32 tmpSz;
1874
0
    int ret;
1875
1876
    /* get max size for shrouded key */
1877
0
    ret =  wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz,
1878
0
            algo, pass, passSz, iter);
1879
0
    if (ret != LENGTH_ONLY_E && ret < 0) {
1880
0
        return ret;
1881
0
    }
1882
1883
0
    if (out == NULL) {
1884
0
        *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ +
1885
0
            length;
1886
0
        return LENGTH_ONLY_E;
1887
0
    }
1888
1889
0
    heap = wc_PKCS12_GetHeap(pkcs12);
1890
1891
    /* leave room for sequence */
1892
0
    idx += MAX_SEQ_SZ;
1893
1894
0
    if (algo < 0) { /* not encrypted */
1895
0
        out[idx++] = ASN_OBJECT_ID; totalSz++;
1896
0
        sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx);
1897
0
        idx += sz; totalSz += sz;
1898
0
        for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) {
1899
0
            out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++;
1900
0
        }
1901
0
    }
1902
0
    else { /* encrypted */
1903
0
        out[idx++] = ASN_OBJECT_ID; totalSz++;
1904
0
        sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx);
1905
0
        idx += sz; totalSz += sz;
1906
0
        for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) {
1907
0
            out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++;
1908
0
        }
1909
0
    }
1910
1911
    /* shroud key */
1912
0
    tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER);
1913
0
    if (tmp == NULL) {
1914
0
        return MEMORY_E;
1915
0
    }
1916
1917
0
    ret =  wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz,
1918
0
            algo, pass, passSz, iter);
1919
0
    if (ret < 0) {
1920
0
        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
1921
0
        return ret;
1922
0
    }
1923
0
    length = (word32)ret;
1924
0
    XMEMCPY(out + idx, tmp, (size_t)length);
1925
0
    XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
1926
0
    totalSz += length;
1927
1928
    /* set beginning sequence */
1929
0
    tmpSz = SetSequence(totalSz, out);
1930
0
    XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
1931
1932
0
    (void)heap;
1933
0
    return (int)(totalSz + tmpSz);
1934
0
}
1935
1936
1937
/* Helper function to create cert bag.
1938
 *
1939
 * pkcs12 structure to use with cert bag
1940
 * out    buffer to hold results
1941
 * outSz  size of out buffer
1942
 * cert   cert that is going into cert bag
1943
 * certSz size of cert buffer
1944
 *
1945
 * returns the size of the cert bag on success
1946
 */
1947
static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12,
1948
        byte* out, word32* outSz, byte* cert, word32 certSz)
1949
0
{
1950
0
    word32 length = 0;
1951
0
    word32 idx = 0;
1952
0
    word32 totalSz = 0;
1953
0
    word32 sz;
1954
0
    int WC_CERTBAG_OBJECT_ID  = 13;
1955
0
    int WC_CERTBAG1_OBJECT_ID = 12;
1956
0
    word32 i;
1957
0
    word32 tmpSz;
1958
1959
0
    if (out == NULL) {
1960
0
        *outSz = (word32)(MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
1961
0
            MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
1962
0
            MAX_LENGTH_SZ + (int)certSz);
1963
0
        return LENGTH_ONLY_E;
1964
0
    }
1965
1966
    /* check buffer size able to handle max size */
1967
0
    if (*outSz < (word32)(MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
1968
0
            MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
1969
0
            MAX_LENGTH_SZ + (int)certSz)) {
1970
0
        return BUFFER_E;
1971
0
    }
1972
1973
    /* save room for sequence */
1974
0
    idx += MAX_SEQ_SZ;
1975
1976
    /* objectId WC_PKCS12_CertBag */
1977
0
    out[idx++] = ASN_OBJECT_ID; totalSz++;
1978
0
    sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx);
1979
0
    idx += sz; totalSz += sz;
1980
0
    for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) {
1981
0
        out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++;
1982
0
    }
1983
1984
    /**** Cert Bag type 1 ****/
1985
0
    out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++;
1986
1987
    /* save room for length and sequence */
1988
0
    idx += MAX_LENGTH_SZ;
1989
0
    idx += MAX_SEQ_SZ;
1990
1991
    /* object id WC_PKCS12_CertBag_Type1 */
1992
0
    out[idx++] = ASN_OBJECT_ID; length++;
1993
0
    sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx);
1994
0
    idx += sz; length += sz;
1995
0
    for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) {
1996
0
        out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++;
1997
0
    }
1998
1999
0
    out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++;
2000
0
    sz = 0;
2001
0
    idx += MAX_LENGTH_SZ; /* save room for length */
2002
2003
    /* place the cert in the buffer */
2004
0
    out[idx++] = ASN_OCTET_STRING; sz++;
2005
0
    tmpSz = SetLength(certSz, out + idx);
2006
0
    idx += tmpSz; sz += tmpSz;
2007
0
    XMEMCPY(out + idx, cert, certSz);
2008
0
    idx += certSz; sz += certSz;
2009
2010
    /* rewind idx and place length */
2011
0
    idx -= (sz + MAX_LENGTH_SZ);
2012
0
    tmpSz = SetLength(sz, out + idx);
2013
0
    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz);
2014
0
    idx += tmpSz + sz; length += tmpSz + sz;
2015
2016
    /* rewind idx and set sequence */
2017
0
    idx -= (length + MAX_SEQ_SZ);
2018
0
    tmpSz = SetSequence(length, out + idx);
2019
0
    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length);
2020
0
    length += tmpSz;
2021
2022
    /* place final length */
2023
0
    idx -= MAX_LENGTH_SZ;
2024
0
    tmpSz = SetLength(length, out + idx);
2025
0
    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length);
2026
0
    length += tmpSz;
2027
2028
    /* place final sequence */
2029
0
    totalSz += length;
2030
0
    tmpSz = SetSequence(totalSz, out);
2031
0
    XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
2032
2033
0
    (void)pkcs12;
2034
2035
0
    return (int)(totalSz + tmpSz);
2036
0
}
2037
2038
2039
/* Helper function to encrypt content.
2040
 *
2041
 * pkcs12    structure to use with key bag
2042
 * rng       random number generator used
2043
 * out       buffer to hold results
2044
 * outSz     size of out buffer
2045
 * content   content to encrypt
2046
 * contentSz size of content buffer
2047
 * vAlgo     algorithm version
2048
 * pass      password to use
2049
 * passSz    size of pass buffer
2050
 * iter      number of iterations
2051
 * type      content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA
2052
 *
2053
 * returns the size of result on success
2054
 */
2055
static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng,
2056
        byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo,
2057
        const char* pass, int passSz, int iter, int type)
2058
0
{
2059
0
    void* heap;
2060
0
    int vPKCS     = 1; /* PKCS#12 is always set to 1 */
2061
0
    int ret;
2062
0
    byte*  tmp;
2063
0
    word32 idx = 0;
2064
0
    word32 totalSz = 0;
2065
0
    word32 length = 0;
2066
0
    word32 tmpSz;
2067
0
    word32 encSz;
2068
2069
0
    byte seq[MAX_SEQ_SZ];
2070
2071
0
    WOLFSSL_MSG("encrypting PKCS12 content");
2072
2073
0
    heap = wc_PKCS12_GetHeap(pkcs12);
2074
2075
    /* ENCRYPTED DATA
2076
     * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
2077
     * length
2078
     * sequence
2079
     * short int
2080
     * sequence
2081
     * get object id */
2082
0
    if (type == WC_PKCS12_ENCRYPTED_DATA) {
2083
0
        word32 outerSz = 0;
2084
2085
0
        encSz = contentSz;
2086
0
        if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz,
2087
0
                   pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
2088
0
            if (ret != LENGTH_ONLY_E) {
2089
0
                return ret;
2090
0
            }
2091
0
        }
2092
2093
        /* calculate size */
2094
0
        totalSz  = (word32)SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), seq);
2095
0
        totalSz += sizeof(WC_PKCS12_ENCRYPTED_OID);
2096
0
        totalSz += ASN_TAG_SZ;
2097
2098
0
        length  = (word32)SetMyVersion(0, seq, 0);
2099
0
        tmpSz   = (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq);
2100
0
        tmpSz  += sizeof(WC_PKCS12_DATA_OID);
2101
0
        tmpSz  += encSz;
2102
0
        length += SetSequence(tmpSz, seq) + tmpSz;
2103
0
        outerSz = SetSequence(length, seq) + length;
2104
2105
0
        totalSz += SetLength(outerSz, seq) + outerSz;
2106
0
        if (out == NULL) {
2107
0
            *outSz = totalSz + SetSequence(totalSz, seq);
2108
0
            return LENGTH_ONLY_E;
2109
0
        }
2110
2111
0
        if (*outSz < totalSz + SetSequence(totalSz, seq)) {
2112
0
            return BUFFER_E;
2113
0
        }
2114
2115
0
        idx = 0;
2116
0
        idx += SetSequence(totalSz, out + idx);
2117
0
        idx += (word32)SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), out + idx);
2118
0
        if (idx + sizeof(WC_PKCS12_ENCRYPTED_OID) > *outSz){
2119
0
            return BUFFER_E;
2120
0
        }
2121
0
        XMEMCPY(out + idx, WC_PKCS12_ENCRYPTED_OID,
2122
0
                sizeof(WC_PKCS12_ENCRYPTED_OID));
2123
0
        idx += sizeof(WC_PKCS12_ENCRYPTED_OID);
2124
2125
0
        if (idx + 1 > *outSz){
2126
0
            return BUFFER_E;
2127
0
        }
2128
0
        out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC);
2129
0
        idx += SetLength(outerSz, out + idx);
2130
2131
0
        idx += SetSequence(length, out + idx);
2132
0
        idx += (word32)SetMyVersion(0, out + idx, 0);
2133
0
        tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
2134
0
        if (tmp == NULL) {
2135
0
            return MEMORY_E;
2136
0
        }
2137
2138
0
        if ((ret = EncryptContent(content, contentSz, tmp, &encSz,
2139
0
                   pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
2140
0
            XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
2141
0
            return ret;
2142
0
        }
2143
0
        encSz = (word32)ret;
2144
2145
        #ifdef WOLFSSL_DEBUG_PKCS12
2146
        {
2147
            byte* p;
2148
            for (printf("(size %u) Encrypted Content = ", encSz),
2149
                    p = (byte*)tmp;
2150
                p < (byte*)tmp + encSz;
2151
                printf("%02X", *p), p++);
2152
            printf("\n");
2153
        }
2154
        #endif
2155
2156
0
        idx += SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx);
2157
0
        idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx);
2158
0
        if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){
2159
0
            WOLFSSL_MSG("Buffer not large enough for DATA OID");
2160
0
            XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
2161
0
            return BUFFER_E;
2162
0
        }
2163
0
        XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
2164
0
        idx += sizeof(WC_PKCS12_DATA_OID);
2165
2166
        /* copy over encrypted data */
2167
0
        if (idx + encSz > *outSz){
2168
0
            XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
2169
0
            return BUFFER_E;
2170
0
        }
2171
0
        XMEMCPY(out + idx, tmp, encSz);
2172
0
        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
2173
0
        idx += encSz;
2174
0
        return (int)idx;
2175
0
    }
2176
2177
    /* DATA
2178
     * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
2179
     * length
2180
     * ASN_OCTET_STRING
2181
     * length
2182
     * sequence containing all bags */
2183
0
    if (type == WC_PKCS12_DATA) {
2184
        /* calculate size */
2185
0
        totalSz = (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq);
2186
0
        totalSz += sizeof(WC_PKCS12_DATA_OID);
2187
0
        totalSz += ASN_TAG_SZ;
2188
2189
0
        length   = SetOctetString(contentSz, seq);
2190
0
        length  += contentSz;
2191
0
        totalSz += SetLength(length, seq);
2192
0
        totalSz += length;
2193
2194
0
        if (out == NULL) {
2195
0
            *outSz = totalSz + SetSequence(totalSz, seq);
2196
0
            return LENGTH_ONLY_E;
2197
0
        }
2198
2199
0
        if (*outSz < (totalSz + SetSequence(totalSz, seq))) {
2200
0
            return BUFFER_E;
2201
0
        }
2202
2203
        /* place data in output buffer */
2204
0
        idx  = 0;
2205
0
        idx += SetSequence(totalSz, out);
2206
0
        idx += (word32)SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx);
2207
0
        if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){
2208
0
            WOLFSSL_MSG("Buffer not large enough for DATA OID");
2209
0
            return BUFFER_E;
2210
0
        }
2211
0
        XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID));
2212
0
        idx += sizeof(WC_PKCS12_DATA_OID);
2213
2214
0
        if (idx + 1 > *outSz){
2215
0
            return BUFFER_E;
2216
0
        }
2217
0
        out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC);
2218
0
        idx += SetLength(length, out + idx);
2219
0
        idx += SetOctetString(contentSz, out + idx);
2220
2221
0
        if (idx + contentSz > *outSz){
2222
0
            return BUFFER_E;
2223
0
        }
2224
0
        XMEMCPY(out + idx, content, contentSz);
2225
0
        idx += contentSz;
2226
2227
0
        return (int)idx;
2228
0
    }
2229
2230
0
    WOLFSSL_MSG("Unknown/Unsupported content type");
2231
0
    return BAD_FUNC_ARG;
2232
0
}
2233
2234
2235
/* helper function to create the PKCS12 key content
2236
 * keyCiSz is output buffer size
2237
 * returns a pointer to be free'd by caller on success and NULL on failure */
2238
static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey,
2239
        word32* keyCiSz, WC_RNG* rng, char* pass, word32 passSz,
2240
        byte* key, word32 keySz, int iter)
2241
0
{
2242
0
    byte*  keyBuf;
2243
0
    word32 keyBufSz = 0;
2244
0
    byte* keyCi = NULL;
2245
0
    word32 tmpSz;
2246
0
    int ret;
2247
0
    int algo;
2248
0
    void* heap;
2249
2250
0
    heap = wc_PKCS12_GetHeap(pkcs12);
2251
0
    *keyCiSz = 0;
2252
0
    switch (nidKey) {
2253
0
        case PBE_SHA1_RC4_128:
2254
0
            algo = 1;
2255
0
            break;
2256
2257
0
        case PBE_SHA1_DES:
2258
0
            algo = 2;
2259
0
            break;
2260
2261
0
        case PBE_SHA1_DES3:
2262
0
            algo = 3;
2263
0
            break;
2264
2265
        /* no encryption */
2266
0
        case -1:
2267
0
            algo = -1;
2268
0
            break;
2269
2270
0
        default:
2271
0
            WOLFSSL_MSG("Unknown/Unsupported key encryption");
2272
0
            return NULL;
2273
0
    }
2274
2275
    /* get max size for key bag */
2276
0
    ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz,
2277
0
            algo, iter, pass, (int)passSz);
2278
0
    if (ret != LENGTH_ONLY_E && ret < 0) {
2279
0
        WOLFSSL_MSG("Error getting key bag size");
2280
0
        return NULL;
2281
0
    }
2282
2283
    /* account for sequence around bag */
2284
0
    keyBufSz += MAX_SEQ_SZ;
2285
0
    keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
2286
0
    if (keyBuf == NULL) {
2287
0
        WOLFSSL_MSG("Memory error creating keyBuf buffer");
2288
0
        return NULL;
2289
0
    }
2290
2291
0
    ret = wc_PKCS12_create_key_bag(pkcs12, rng, keyBuf + MAX_SEQ_SZ, &keyBufSz,
2292
0
            key, keySz, algo, iter, pass, (int)passSz);
2293
0
    if (ret < 0) {
2294
0
        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2295
0
        WOLFSSL_MSG("Error creating key bag");
2296
0
        return NULL;
2297
0
    }
2298
0
    keyBufSz = (word32)ret;
2299
2300
0
    tmpSz = SetSequence(keyBufSz, keyBuf);
2301
0
    XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz);
2302
0
    keyBufSz += tmpSz;
2303
2304
    #ifdef WOLFSSL_DEBUG_PKCS12
2305
    {
2306
        word32 i;
2307
        printf("(size %u) Key Bag = ", keyBufSz);
2308
        for (i = 0; i < keyBufSz; i++)
2309
            printf("%02X", keyBuf[i]);
2310
        printf("\n");
2311
    }
2312
    #endif
2313
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz,
2314
0
            NULL, keyBufSz, algo, pass, (int)passSz, iter, WC_PKCS12_DATA);
2315
0
    if (ret != LENGTH_ONLY_E) {
2316
0
        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2317
0
        WOLFSSL_MSG("Error getting key encrypt content size");
2318
0
        return NULL;
2319
0
    }
2320
0
    keyCi = (byte*)XMALLOC(*keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
2321
0
    if (keyCi == NULL) {
2322
0
        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2323
0
        return NULL;
2324
0
    }
2325
2326
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, keyCi, keyCiSz,
2327
0
            keyBuf, keyBufSz, algo, pass, (int)passSz, iter, WC_PKCS12_DATA);
2328
0
    XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2329
0
    if (ret < 0 ) {
2330
0
        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
2331
0
        WOLFSSL_MSG("Error creating key encrypt content");
2332
0
        return NULL;
2333
0
    }
2334
0
    *keyCiSz = (word32)ret;
2335
2336
    #ifdef WOLFSSL_DEBUG_PKCS12
2337
    {
2338
        word32 i;
2339
        printf("(size %u) Key Content Info = ", *keyCiSz);
2340
        for (i = 0; i < *keyCiSz; i++)
2341
            printf("%02X", keyCi[i]);
2342
        printf("\n");
2343
    }
2344
    #endif
2345
2346
0
    (void)heap;
2347
0
    return keyCi;
2348
0
}
2349
2350
2351
/* helper function to create the PKCS12 certificate content
2352
 * certCiSz is output buffer size
2353
 * returns a pointer to be free'd by caller on success and NULL on failure */
2354
static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert,
2355
        WC_DerCertList* ca, byte* cert, word32 certSz, word32* certCiSz,
2356
        WC_RNG* rng, char* pass, word32 passSz, int iter)
2357
0
{
2358
0
    int algo;
2359
0
    int ret;
2360
0
    int type;
2361
2362
0
    byte*  certBuf = NULL;
2363
0
    word32 certBufSz;
2364
0
    word32 idx;
2365
0
    word32 sz;
2366
0
    word32 tmpSz;
2367
2368
0
    byte* certCi;
2369
0
    void* heap;
2370
2371
0
    heap = wc_PKCS12_GetHeap(pkcs12);
2372
0
    switch (nidCert) {
2373
0
        case PBE_SHA1_RC4_128:
2374
0
            type = WC_PKCS12_ENCRYPTED_DATA;
2375
0
            algo = 1;
2376
0
            break;
2377
2378
0
        case PBE_SHA1_DES:
2379
0
            type = WC_PKCS12_ENCRYPTED_DATA;
2380
0
            algo = 2;
2381
0
            break;
2382
2383
0
        case PBE_SHA1_DES3:
2384
0
            type = WC_PKCS12_ENCRYPTED_DATA;
2385
0
            algo = 3;
2386
0
            break;
2387
2388
0
        case -1:
2389
0
            type = WC_PKCS12_DATA;
2390
0
            algo = -1;
2391
0
            break;
2392
2393
0
        default:
2394
0
            WOLFSSL_MSG("Unknown/Unsupported certificate encryption");
2395
0
            return NULL;
2396
0
    }
2397
2398
    /* get max size of buffer needed */
2399
0
    ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz);
2400
0
    if (ret != LENGTH_ONLY_E) {
2401
0
        return NULL;
2402
0
    }
2403
2404
0
    if (ca != NULL) {
2405
0
        WC_DerCertList* current = ca;
2406
0
        word32 curBufSz = 0;
2407
2408
        /* get max buffer size */
2409
0
        while (current != NULL) {
2410
0
            ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz,
2411
0
                    current->buffer, current->bufferSz);
2412
0
            if (ret != LENGTH_ONLY_E) {
2413
0
                return NULL;
2414
0
            }
2415
0
            certBufSz += curBufSz;
2416
0
            current    = current->next;
2417
0
        }
2418
0
    }
2419
2420
    /* account for Sequence that holds all certificate bags */
2421
0
    certBufSz += MAX_SEQ_SZ;
2422
2423
    /* completed getting max size, now create buffer and start adding bags */
2424
0
    certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
2425
0
    if (certBuf == NULL) {
2426
0
        WOLFSSL_MSG("Memory error creating certificate bags");
2427
0
        return NULL;
2428
0
    }
2429
2430
0
    idx = 0;
2431
0
    idx += MAX_SEQ_SZ;
2432
2433
0
    sz = certBufSz - idx;
2434
0
    if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
2435
0
            cert, certSz)) < 0) {
2436
0
        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2437
0
        return NULL;
2438
0
    }
2439
0
    idx += (word32)ret;
2440
2441
0
    if (ca != NULL) {
2442
0
        WC_DerCertList* current = ca;
2443
2444
0
        while (current != NULL) {
2445
0
            sz = certBufSz - idx;
2446
0
            if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
2447
0
               current->buffer, current->bufferSz)) < 0) {
2448
0
                XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2449
0
                return NULL;
2450
0
            }
2451
0
            idx += (word32)ret;
2452
0
            current = current->next;
2453
0
        }
2454
0
    }
2455
2456
    /* set sequence and create encrypted content with all certificate bags */
2457
0
    tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf);
2458
0
    XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ);
2459
0
    certBufSz = tmpSz + (idx - MAX_SEQ_SZ);
2460
2461
    /* get buffer size needed for content info */
2462
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz,
2463
0
            NULL, certBufSz, algo, pass, (int)passSz, iter, type);
2464
0
    if (ret != LENGTH_ONLY_E) {
2465
0
        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2466
0
        WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
2467
0
        return NULL;
2468
0
    }
2469
0
    certCi = (byte*)XMALLOC(*certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
2470
0
    if (certCi == NULL) {
2471
0
        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2472
0
        return NULL;
2473
0
    }
2474
2475
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, certCi, certCiSz,
2476
0
            certBuf, certBufSz, algo, pass, (int)passSz, iter, type);
2477
0
    XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2478
0
    if (ret < 0) {
2479
0
        WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
2480
0
        XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
2481
0
        return NULL;
2482
0
    }
2483
0
    *certCiSz = (word32)ret;
2484
2485
    #ifdef WOLFSSL_DEBUG_PKCS12
2486
    {
2487
        word32 i;
2488
        printf("(size %u) Encrypted Certificate Content Info = ", *certCiSz);
2489
        for (i = 0; i < *certCiSz; i++)
2490
            printf("%02X", certCi[i]);
2491
        printf("\n");
2492
    }
2493
    #endif
2494
2495
0
    (void)heap;
2496
0
    return certCi;
2497
0
}
2498
2499
2500
/* helper function to create the PKCS12 safe
2501
 * returns 0 on success */
2502
static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz,
2503
        byte* keyCi, word32 keyCiSz, WC_RNG* rng, char* pass, word32 passSz,
2504
        int iter)
2505
0
{
2506
0
    int length;
2507
0
    int ret;
2508
0
    byte seq[MAX_SEQ_SZ];
2509
0
    word32 safeDataSz;
2510
0
    word32 innerDataSz;
2511
0
    byte *innerData = NULL;
2512
0
    byte *safeData  = NULL;
2513
0
    word32 idx;
2514
2515
0
    innerDataSz = certCiSz + keyCiSz+SetSequence(certCiSz + keyCiSz, seq);
2516
2517
    /* add Content Info structs to safe, key first then cert */
2518
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz,
2519
0
            NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA);
2520
0
    if (ret != LENGTH_ONLY_E) {
2521
0
        return ret;
2522
0
    }
2523
2524
0
    safeData = (byte*)XMALLOC(safeDataSz, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
2525
0
    if (safeData == NULL) {
2526
0
        WOLFSSL_MSG("Error malloc'ing safe data buffer");
2527
0
        return MEMORY_E;
2528
0
    }
2529
2530
    /* create sequence of inner data */
2531
0
    innerData = (byte*)XMALLOC(innerDataSz, pkcs12->heap, DYNAMIC_TYPE_PKCS);
2532
0
    if (innerData == NULL) {
2533
0
        WOLFSSL_MSG("Error malloc'ing inner data buffer");
2534
0
        XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
2535
0
        return MEMORY_E;
2536
0
    }
2537
0
    idx  = 0;
2538
0
    idx += SetSequence(certCiSz + keyCiSz, innerData);
2539
0
    XMEMCPY(innerData + idx, certCi, certCiSz);
2540
0
    XMEMCPY(innerData + idx + certCiSz, keyCi, keyCiSz);
2541
2542
0
    ret = wc_PKCS12_encrypt_content(pkcs12, rng, safeData, &safeDataSz,
2543
0
            innerData, innerDataSz, 0, pass, (int)passSz, iter, WC_PKCS12_DATA);
2544
0
    XFREE(innerData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
2545
0
    if (ret < 0 ) {
2546
0
        WOLFSSL_MSG("Error setting data type for safe contents");
2547
0
        XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
2548
0
        return ret;
2549
0
    }
2550
0
    idx = 0;
2551
2552
0
    ret = GetSequence(safeData, &idx, &length, safeDataSz);
2553
0
    if (ret < 0) {
2554
0
        WOLFSSL_MSG("Error getting first sequence of safe");
2555
0
        XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
2556
0
        return ret;
2557
0
    }
2558
2559
0
    ret = GetSafeContent(pkcs12, safeData, &idx, safeDataSz);
2560
0
    XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER);
2561
0
    if (ret < 0) {
2562
0
        WOLFSSL_MSG("Unable to create safe contents");
2563
0
        return ret;
2564
0
    }
2565
0
    return 0;
2566
0
}
2567
2568
2569
/*
2570
 * pass : password to use with encryption
2571
 * passSz : size of the password buffer
2572
 * name : friendlyName to use
2573
 * key  : DER format of key
2574
 * keySz : size of key buffer
2575
 * cert : DER format of certificate
2576
 * certSz : size of the certificate buffer
2577
 * ca   : a list of extra certificates
2578
 * nidKey  : type of encryption to use on the key (-1 means no encryption)
2579
 * nidCert : type of encryption to use on the certificate
2580
 *           (-1 means no encryption)
2581
 * iter    : number of iterations with encryption
2582
 * macIter : number of iterations when creating MAC
2583
 * keyType : flag for signature and/or encryption key
2584
 * heap : pointer to allocate from memory
2585
 *
2586
 * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed
2587
 */
2588
WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name,
2589
        byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca,
2590
        int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap)
2591
0
{
2592
0
    WC_PKCS12* pkcs12;
2593
0
    WC_RNG     rng;
2594
0
    int ret;
2595
2596
0
    byte*  certCi = NULL;
2597
0
    byte*  keyCi  = NULL;
2598
0
    word32 certCiSz;
2599
0
    word32 keyCiSz;
2600
2601
0
    WOLFSSL_ENTER("wc_PKCS12_create");
2602
2603
0
    if (wc_InitRng_ex(&rng, heap, INVALID_DEVID) != 0) {
2604
0
        return NULL;
2605
0
    }
2606
2607
0
    if ((pkcs12 = wc_PKCS12_new()) == NULL) {
2608
0
        wc_FreeRng(&rng);
2609
0
        WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E);
2610
0
        return NULL;
2611
0
    }
2612
2613
0
    if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) {
2614
0
        wc_PKCS12_free(pkcs12);
2615
0
        wc_FreeRng(&rng);
2616
0
        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
2617
0
        (void)ret;
2618
0
        return NULL;
2619
0
    }
2620
2621
0
    if (iter <= 0) {
2622
0
        iter = WC_PKCS12_ITT_DEFAULT;
2623
0
    }
2624
2625
    /**** add private key bag ****/
2626
0
    keyCi = PKCS12_create_key_content(pkcs12, nidKey, &keyCiSz, &rng,
2627
0
            pass, passSz, key, keySz, iter);
2628
0
    if (keyCi == NULL) {
2629
0
        wc_PKCS12_free(pkcs12);
2630
0
        wc_FreeRng(&rng);
2631
0
        return NULL;
2632
0
    }
2633
2634
    /**** add main certificate bag and extras ****/
2635
0
    certCi = PKCS12_create_cert_content(pkcs12, nidCert, ca, cert, certSz,
2636
0
            &certCiSz, &rng, pass, passSz, iter);
2637
0
    if (certCi == NULL) {
2638
0
        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
2639
0
        wc_PKCS12_free(pkcs12);
2640
0
        wc_FreeRng(&rng);
2641
0
        return NULL;
2642
0
    }
2643
2644
    /**** create safe and Content Info ****/
2645
0
    ret = PKCS12_create_safe(pkcs12, certCi, certCiSz, keyCi, keyCiSz, &rng,
2646
0
            pass, passSz, iter);
2647
0
    XFREE(keyCi,  heap, DYNAMIC_TYPE_TMP_BUFFER);
2648
0
    XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
2649
0
    if (ret != 0) {
2650
0
        WOLFSSL_MSG("Unable to create PKCS12 safe");
2651
0
        wc_PKCS12_free(pkcs12);
2652
0
        wc_FreeRng(&rng);
2653
0
        return NULL;
2654
0
    }
2655
2656
    /* create MAC */
2657
0
    if (macIter > 0) {
2658
0
        MacData* mac;
2659
0
        byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */
2660
2661
0
        mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS);
2662
0
        if (mac == NULL) {
2663
0
            wc_PKCS12_free(pkcs12);
2664
0
            wc_FreeRng(&rng);
2665
0
            WOLFSSL_MSG("Error malloc'ing mac data buffer");
2666
0
            return NULL;
2667
0
        }
2668
0
        XMEMSET(mac, 0, sizeof(MacData));
2669
0
        pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */
2670
2671
0
        #ifndef NO_SHA256
2672
0
            mac->oid = SHA256h;
2673
        #elif !defined(NO_SHA)
2674
            mac->oid = SHA;
2675
        #elif defined(WOLFSSL_SHA384)
2676
            mac->oid = SHA384;
2677
        #elif defined(WOLFSSL_SHA512)
2678
            mac->oid = SHA512;
2679
        #else
2680
            WOLFSSL_MSG("No supported hash algorithm compiled in!");
2681
            wc_PKCS12_free(pkcs12);
2682
            wc_FreeRng(&rng);
2683
            return NULL;
2684
        #endif
2685
2686
        /* store number of iterations */
2687
0
        mac->itt = macIter;
2688
2689
        /* set mac salt */
2690
0
        mac->saltSz = WC_PKCS12_MAC_SALT_SZ;
2691
0
        mac->salt = (byte*)XMALLOC(WC_PKCS12_MAC_SALT_SZ, heap,
2692
0
                DYNAMIC_TYPE_PKCS);
2693
0
        if (mac->salt == NULL) {
2694
0
            wc_PKCS12_free(pkcs12);
2695
0
            wc_FreeRng(&rng);
2696
0
            WOLFSSL_MSG("Error malloc'ing salt data buffer");
2697
0
            return NULL;
2698
0
        }
2699
2700
0
        if (wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz) != 0) {
2701
0
            WOLFSSL_MSG("Error generating random salt");
2702
0
            wc_PKCS12_free(pkcs12);
2703
0
            wc_FreeRng(&rng);
2704
0
            return NULL;
2705
0
        }
2706
0
        ret = wc_PKCS12_create_mac(pkcs12, pkcs12->safe->data,
2707
0
                pkcs12->safe->dataSz, (const byte*)pass, passSz, digest,
2708
0
                WC_MAX_DIGEST_SIZE);
2709
0
        if (ret < 0) {
2710
0
            wc_PKCS12_free(pkcs12);
2711
0
            wc_FreeRng(&rng);
2712
0
            WOLFSSL_MSG("Error creating mac");
2713
0
            WOLFSSL_LEAVE("wc_PKCS12_create", ret);
2714
0
            return NULL;
2715
0
        }
2716
2717
0
        mac->digestSz = (word32)ret;
2718
0
        mac->digest = (byte*)XMALLOC((size_t)ret, heap, DYNAMIC_TYPE_PKCS);
2719
0
        if (mac->digest == NULL) {
2720
0
            WOLFSSL_MSG("Error malloc'ing mac digest buffer");
2721
0
            wc_PKCS12_free(pkcs12);
2722
0
            wc_FreeRng(&rng);
2723
0
            return NULL;
2724
0
        }
2725
0
        XMEMCPY(mac->digest, digest, mac->digestSz);
2726
0
    }
2727
0
    else {
2728
0
        pkcs12->signData = NULL;
2729
0
    }
2730
2731
0
    wc_FreeRng(&rng);
2732
0
    (void)name;
2733
0
    (void)keyType;
2734
2735
0
    return pkcs12;
2736
0
}
2737
2738
2739
/* if using a specific memory heap */
2740
int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap)
2741
0
{
2742
0
    if (pkcs12 == NULL) {
2743
0
        return BAD_FUNC_ARG;
2744
0
    }
2745
0
    pkcs12->heap = heap;
2746
2747
0
    return 0;
2748
0
}
2749
2750
2751
/* getter for heap */
2752
void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12)
2753
0
{
2754
0
    if (pkcs12 == NULL) {
2755
0
        return NULL;
2756
0
    }
2757
2758
0
    return pkcs12->heap;
2759
0
}
2760
2761
#undef ERROR_OUT
2762
2763
#endif /* HAVE_PKCS12 && !NO_ASN && !NO_PWDBASED && !NO_HMAC */