Coverage Report

Created: 2025-11-16 07:15

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