Coverage Report

Created: 2026-02-14 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/ssl_p7p12.c
Line
Count
Source
1
/* ssl_p7p12.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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#if defined(OPENSSL_EXTRA) && (defined(HAVE_FIPS) || defined(HAVE_SELFTEST))
25
    #include <wolfssl/wolfcrypt/pkcs7.h>
26
#endif
27
#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7)
28
    #include <wolfssl/openssl/pkcs7.h>
29
#endif
30
31
#if !defined(WOLFSSL_SSL_P7P12_INCLUDED)
32
    #ifndef WOLFSSL_IGNORE_FILE_WARN
33
        #warning ssl_p7p12.c does not need to be compiled separately from ssl.c
34
    #endif
35
#else
36
37
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
38
39
/*******************************************************************************
40
 * START OF PKCS7 APIs
41
 ******************************************************************************/
42
#ifdef HAVE_PKCS7
43
44
#ifdef OPENSSL_ALL
45
PKCS7* wolfSSL_PKCS7_new(void)
46
{
47
    WOLFSSL_PKCS7* pkcs7;
48
    int ret = 0;
49
50
    pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(WOLFSSL_PKCS7), NULL,
51
                                    DYNAMIC_TYPE_PKCS7);
52
    if (pkcs7 != NULL) {
53
        XMEMSET(pkcs7, 0, sizeof(WOLFSSL_PKCS7));
54
        ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID);
55
    }
56
57
    if (ret != 0 && pkcs7 != NULL) {
58
        XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7);
59
        pkcs7 = NULL;
60
    }
61
62
    return (PKCS7*)pkcs7;
63
}
64
65
/******************************************************************************
66
* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data
67
*
68
* RETURNS:
69
* returns pointer to the PKCS7 structure on success, otherwise returns NULL
70
*/
71
PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void)
72
{
73
    byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
74
    PKCS7* pkcs7 = NULL;
75
76
    if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL)
77
        return NULL;
78
    pkcs7->contentOID = SIGNED_DATA;
79
    if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) {
80
        if (pkcs7) {
81
            wolfSSL_PKCS7_free(pkcs7);
82
            return NULL;
83
        }
84
    }
85
    return pkcs7;
86
}
87
88
void wolfSSL_PKCS7_free(PKCS7* pkcs7)
89
{
90
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
91
92
    if (p7 != NULL) {
93
        XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
94
        wc_PKCS7_Free(&p7->pkcs7);
95
        if (p7->certs)
96
            wolfSSL_sk_pop_free(p7->certs, NULL);
97
        XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7);
98
    }
99
}
100
101
void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7)
102
{
103
    wolfSSL_PKCS7_free(p7);
104
    return;
105
}
106
107
/**
108
 * Convert DER/ASN.1 encoded signedData structure to internal PKCS7
109
 * structure. Note, does not support detached content.
110
 *
111
 * p7 - pointer to set to address of newly created PKCS7 structure on return
112
 * in - pointer to pointer of DER/ASN.1 data
113
 * len - length of input data, bytes
114
 *
115
 * Returns newly allocated and populated PKCS7 structure or NULL on error.
116
 */
117
PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len)
118
{
119
    return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0);
120
}
121
122
/* This internal function is only decoding and setting up the PKCS7 struct. It
123
* does not verify the PKCS7 signature.
124
*
125
* RETURNS:
126
* returns pointer to a PKCS7 structure on success, otherwise returns NULL
127
*/
128
static PKCS7* wolfSSL_d2i_PKCS7_only(PKCS7** p7, const unsigned char** in,
129
    int len, byte* content, word32 contentSz)
130
{
131
    WOLFSSL_PKCS7* pkcs7 = NULL;
132
133
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex");
134
135
    if (in == NULL || *in == NULL || len < 0)
136
        return NULL;
137
138
    if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
139
        return NULL;
140
141
    pkcs7->len = len;
142
    pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
143
    if (pkcs7->data == NULL) {
144
        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
145
        return NULL;
146
    }
147
    XMEMCPY(pkcs7->data, *in, pkcs7->len);
148
149
    if (content != NULL) {
150
        pkcs7->pkcs7.content = content;
151
        pkcs7->pkcs7.contentSz = contentSz;
152
    }
153
154
    if (p7 != NULL)
155
        *p7 = (PKCS7*)pkcs7;
156
    *in += pkcs7->len;
157
    return (PKCS7*)pkcs7;
158
}
159
160
161
/*****************************************************************************
162
* wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len
163
* into a PKCS7 object.  Optionally, accepts a byte buffer of content which
164
* is stored as the PKCS7 object's content, to support detached signatures.
165
* @param content The content which is signed, in case the signature is
166
*                detached.  Ignored if NULL.
167
* @param contentSz The size of the passed in content.
168
*
169
* RETURNS:
170
* returns pointer to a PKCS7 structure on success, otherwise returns NULL
171
*/
172
PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len,
173
        byte* content, word32 contentSz)
174
{
175
    WOLFSSL_PKCS7* pkcs7 = NULL;
176
177
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex");
178
179
    if (in == NULL || *in == NULL || len < 0)
180
        return NULL;
181
182
    pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_d2i_PKCS7_only(p7, in, len, content,
183
            contentSz);
184
    if (pkcs7 != NULL) {
185
        if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
186
                                                                         != 0) {
187
            WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
188
            wolfSSL_PKCS7_free((PKCS7*)pkcs7);
189
            if (p7 != NULL) {
190
                *p7 = NULL;
191
            }
192
            return NULL;
193
        }
194
    }
195
196
    return (PKCS7*)pkcs7;
197
}
198
199
200
/**
201
 * This API was added as a helper function for libest. It
202
 * extracts a stack of certificates from the pkcs7 object.
203
 * @param pkcs7 PKCS7 parameter object
204
 * @return WOLFSSL_STACK_OF(WOLFSSL_X509)*
205
 */
206
WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7)
207
{
208
    int i;
209
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
210
    WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL;
211
212
    WOLFSSL_ENTER("wolfSSL_PKCS7_to_stack");
213
214
    if (!p7) {
215
        WOLFSSL_MSG("Bad parameter");
216
        return NULL;
217
    }
218
219
    if (p7->certs)
220
        return p7->certs;
221
222
    for (i = 0; i < MAX_PKCS7_CERTS && p7->pkcs7.cert[i]; i++) {
223
        WOLFSSL_X509* x509 = wolfSSL_X509_d2i_ex(NULL, p7->pkcs7.cert[i],
224
            p7->pkcs7.certSz[i], pkcs7->heap);
225
        if (!ret)
226
            ret = wolfSSL_sk_X509_new_null();
227
        if (x509) {
228
            if (wolfSSL_sk_X509_push(ret, x509) <= 0) {
229
                wolfSSL_X509_free(x509);
230
                x509 = NULL;
231
                WOLFSSL_MSG("wolfSSL_sk_X509_push error");
232
                goto error;
233
            }
234
        }
235
        else {
236
            WOLFSSL_MSG("wolfSSL_X509_d2i error");
237
            goto error;
238
        }
239
    }
240
241
    /* Save stack to free later */
242
    if (p7->certs)
243
        wolfSSL_sk_pop_free(p7->certs, NULL);
244
    p7->certs = ret;
245
246
    return ret;
247
error:
248
    if (ret) {
249
        wolfSSL_sk_pop_free(ret, NULL);
250
    }
251
    return NULL;
252
}
253
254
/**
255
 * Return stack of signers contained in PKCS7 cert.
256
 * Notes:
257
 * - Currently only PKCS#7 messages with a single signer cert is supported.
258
 * - Returned WOLFSSL_STACK must be freed by caller.
259
 *
260
 * pkcs7 - PKCS7 struct to retrieve signer certs from.
261
 * certs - currently unused
262
 * flags - flags to control function behavior.
263
 *
264
 * Return WOLFSSL_STACK of signers on success, NULL on error.
265
 */
266
WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs,
267
                                          int flags)
268
{
269
    WOLFSSL_X509* x509 = NULL;
270
    WOLFSSL_STACK* signers = NULL;
271
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
272
273
    if (p7 == NULL)
274
        return NULL;
275
276
    /* Only PKCS#7 messages with a single cert that is the verifying certificate
277
     * is supported.
278
     */
279
    if (flags & PKCS7_NOINTERN) {
280
        WOLFSSL_MSG("PKCS7_NOINTERN flag not supported");
281
        return NULL;
282
    }
283
284
    signers = wolfSSL_sk_X509_new_null();
285
    if (signers == NULL)
286
        return NULL;
287
288
    if (wolfSSL_d2i_X509(&x509, (const byte**)&p7->pkcs7.singleCert,
289
                         p7->pkcs7.singleCertSz) == NULL) {
290
        wolfSSL_sk_X509_pop_free(signers, NULL);
291
        return NULL;
292
    }
293
294
    if (wolfSSL_sk_X509_push(signers, x509) <= 0) {
295
        wolfSSL_sk_X509_pop_free(signers, NULL);
296
        return NULL;
297
    }
298
299
    (void)certs;
300
301
    return signers;
302
}
303
304
#ifndef NO_BIO
305
306
PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7)
307
{
308
    WOLFSSL_PKCS7* pkcs7;
309
    int ret;
310
311
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_bio");
312
313
    if (bio == NULL)
314
        return NULL;
315
316
    if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)
317
        return NULL;
318
319
    pkcs7->len = wolfSSL_BIO_get_len(bio);
320
    if (pkcs7->len < 0){
321
        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
322
        return NULL;
323
    }
324
    pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7);
325
    if (pkcs7->data == NULL) {
326
        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
327
        return NULL;
328
    }
329
330
    if ((ret = wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len)) <= 0) {
331
        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
332
        return NULL;
333
    }
334
    /* pkcs7->len may change if using b64 for example */
335
    pkcs7->len = ret;
336
337
    if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len)
338
                                                                         != 0) {
339
        WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed");
340
        wolfSSL_PKCS7_free((PKCS7*)pkcs7);
341
        return NULL;
342
    }
343
344
    if (p7 != NULL)
345
        *p7 = (PKCS7*)pkcs7;
346
    return (PKCS7*)pkcs7;
347
}
348
349
int wolfSSL_i2d_PKCS7(PKCS7 *p7, unsigned char **out)
350
{
351
    byte* output = NULL;
352
    int localBuf = 0;
353
    int len;
354
    WC_RNG rng;
355
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
356
    WOLFSSL_ENTER("wolfSSL_i2d_PKCS7");
357
358
    if (!out || !p7) {
359
        WOLFSSL_MSG("Bad parameter");
360
        return WOLFSSL_FAILURE;
361
    }
362
363
    if (!p7->rng) {
364
        if (wc_InitRng(&rng) != 0) {
365
            WOLFSSL_MSG("wc_InitRng error");
366
            return WOLFSSL_FAILURE;
367
        }
368
        p7->rng = &rng; /* cppcheck-suppress autoVariables
369
                         */
370
    }
371
372
    if ((len = wc_PKCS7_EncodeSignedData(p7, NULL, 0)) < 0) {
373
        WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
374
        goto cleanup;
375
    }
376
377
    if (*out == NULL) {
378
        output = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
379
        if (!output) {
380
            WOLFSSL_MSG("malloc error");
381
            goto cleanup;
382
        }
383
        localBuf = 1;
384
    }
385
    else {
386
        output = *out;
387
    }
388
389
    if ((len = wc_PKCS7_EncodeSignedData(p7, output, (word32)len)) < 0) {
390
        WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error");
391
        goto cleanup;
392
    }
393
394
    ret = len;
395
cleanup:
396
    if (p7->rng == &rng) {
397
        wc_FreeRng(&rng);
398
        p7->rng = NULL;
399
    }
400
    if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE) && localBuf)
401
        XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
402
    if (ret != WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
403
        *out = output;
404
    return ret;
405
}
406
407
int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7)
408
{
409
    byte* output = NULL;
410
    int len;
411
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
412
    WOLFSSL_ENTER("wolfSSL_i2d_PKCS7_bio");
413
414
    if (!bio || !p7) {
415
        WOLFSSL_MSG("Bad parameter");
416
        return WOLFSSL_FAILURE;
417
    }
418
419
    if ((len = wolfSSL_i2d_PKCS7(p7, &output)) ==
420
        WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
421
    {
422
        WOLFSSL_MSG("wolfSSL_i2d_PKCS7 error");
423
        goto cleanup;
424
    }
425
426
    if (wolfSSL_BIO_write(bio, output, len) <= 0) {
427
        WOLFSSL_MSG("wolfSSL_BIO_write error");
428
        goto cleanup;
429
    }
430
431
    ret = WOLFSSL_SUCCESS;
432
cleanup:
433
    XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
434
    return ret;
435
}
436
437
/**
438
 * Creates and returns a PKCS7 signedData structure.
439
 *
440
 * Inner content type is set to DATA to match OpenSSL behavior.
441
 *
442
 * signer   - certificate to sign bundle with
443
 * pkey     - private key matching signer
444
 * certs    - optional additional set of certificates to include
445
 * in       - input data to be signed
446
 * flags    - optional set of flags to control sign behavior
447
 *
448
 *    PKCS7_BINARY   - Do not translate input data to MIME canonical
449
 *                     format (\r\n line endings), thus preventing corruption of
450
 *                     binary content.
451
 *    PKCS7_TEXT     - Prepend MIME headers for text/plain to content.
452
 *    PKCS7_DETACHED - Set signature detached, omit content from output bundle.
453
 *    PKCS7_STREAM   - initialize PKCS7 struct for signing, do not read data.
454
 *
455
 * Flags not currently supported:
456
 *    PKCS7_NOCERTS  - Do not include the signer cert in the output bundle.
457
 *    PKCS7_PARTIAL  - Allow for PKCS7_sign() to be only partially set up,
458
 *                     then signers etc to be added separately before
459
 *                     calling PKCS7_final().
460
 *
461
 * Returns valid PKCS7 structure pointer, or NULL if an error occurred.
462
 */
463
PKCS7* wolfSSL_PKCS7_sign(WOLFSSL_X509* signer, WOLFSSL_EVP_PKEY* pkey,
464
        WOLFSSL_STACK* certs, WOLFSSL_BIO* in, int flags)
465
{
466
    int err = 0;
467
    WOLFSSL_PKCS7* p7 = NULL;
468
    WOLFSSL_STACK* cert = certs;
469
470
    WOLFSSL_ENTER("wolfSSL_PKCS7_sign");
471
472
    if (flags & PKCS7_NOCERTS) {
473
        WOLFSSL_MSG("PKCS7_NOCERTS flag not yet supported");
474
        err = 1;
475
    }
476
477
    if (flags & PKCS7_PARTIAL) {
478
        WOLFSSL_MSG("PKCS7_PARTIAL flag not yet supported");
479
        err = 1;
480
    }
481
482
    if ((err == 0) && (signer == NULL || signer->derCert == NULL ||
483
                       signer->derCert->length == 0)) {
484
        WOLFSSL_MSG("Bad function arg, signer is NULL or incomplete");
485
        err = 1;
486
    }
487
488
    if ((err == 0) && (pkey == NULL || pkey->pkey.ptr == NULL ||
489
                       pkey->pkey_sz <= 0)) {
490
        WOLFSSL_MSG("Bad function arg, pkey is NULL or incomplete");
491
        err = 1;
492
    }
493
494
    if ((err == 0) && (in == NULL) && !(flags & PKCS7_STREAM)) {
495
        WOLFSSL_MSG("input data required unless PKCS7_STREAM used");
496
        err = 1;
497
    }
498
499
    if ((err == 0) && ((p7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)) {
500
        WOLFSSL_MSG("Error allocating new WOLFSSL_PKCS7");
501
        err = 1;
502
    }
503
504
    /* load signer certificate */
505
    if (err == 0) {
506
        if (wc_PKCS7_InitWithCert(&p7->pkcs7, signer->derCert->buffer,
507
                                  signer->derCert->length) != 0) {
508
            WOLFSSL_MSG("Failed to load signer certificate");
509
            err = 1;
510
        }
511
    }
512
513
    /* set signer private key, data types, defaults */
514
    if (err == 0) {
515
        p7->pkcs7.privateKey = (byte*)pkey->pkey.ptr;
516
        p7->pkcs7.privateKeySz = (word32)pkey->pkey_sz;
517
        p7->pkcs7.contentOID = DATA;  /* inner content default is DATA */
518
        p7->pkcs7.hashOID = SHA256h;  /* default to SHA-256 hash type */
519
        p7->type = SIGNED_DATA;       /* PKCS7_final switches on type */
520
    }
521
522
    /* add additional chain certs if provided */
523
    while (cert && (err == 0)) {
524
        if (cert->data.x509 != NULL && cert->data.x509->derCert != NULL) {
525
            if (wc_PKCS7_AddCertificate(&p7->pkcs7,
526
                                cert->data.x509->derCert->buffer,
527
                                cert->data.x509->derCert->length) != 0) {
528
                WOLFSSL_MSG("Error in wc_PKCS7_AddCertificate");
529
                err = 1;
530
            }
531
        }
532
        cert = cert->next;
533
    }
534
535
    if ((err == 0) && (flags & PKCS7_DETACHED)) {
536
        if (wc_PKCS7_SetDetached(&p7->pkcs7, 1) != 0) {
537
            WOLFSSL_MSG("Failed to set signature detached");
538
            err = 1;
539
        }
540
    }
541
542
    if ((err == 0) && (flags & PKCS7_STREAM)) {
543
        /* if streaming, return before finalizing */
544
        return (PKCS7*)p7;
545
    }
546
547
    if ((err == 0) && (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1)) {
548
        WOLFSSL_MSG("Error calling wolfSSL_PKCS7_final");
549
        err = 1;
550
    }
551
552
    if ((err != 0) && (p7 != NULL)) {
553
        wolfSSL_PKCS7_free((PKCS7*)p7);
554
        p7 = NULL;
555
    }
556
557
    return (PKCS7*)p7;
558
}
559
560
#ifdef HAVE_SMIME
561
562
#ifndef MAX_MIME_LINE_LEN
563
    #define MAX_MIME_LINE_LEN 1024
564
#endif
565
566
/**
567
 * Copy input BIO to output BIO, but convert all line endings to CRLF (\r\n),
568
 * used by PKCS7_final().
569
 *
570
 * in  - input WOLFSSL_BIO to be converted
571
 * out - output WOLFSSL_BIO to hold copy of in, with line endings adjusted
572
 *
573
 * Return 0 on success, negative on error
574
 */
575
static int wolfSSL_BIO_to_MIME_crlf(WOLFSSL_BIO* in, WOLFSSL_BIO* out)
576
{
577
    int ret = 0;
578
    int lineLen = 0;
579
    word32 canonLineLen = 0;
580
    char* canonLine = NULL;
581
    WC_DECLARE_VAR(line, char, MAX_MIME_LINE_LEN, 0);
582
583
    if (in == NULL || out == NULL) {
584
        return BAD_FUNC_ARG;
585
    }
586
587
#ifdef WOLFSSL_SMALL_STACK
588
    line = (char*)XMALLOC(MAX_MIME_LINE_LEN, in->heap,
589
                          DYNAMIC_TYPE_TMP_BUFFER);
590
    if (line == NULL) {
591
        return MEMORY_E;
592
    }
593
#endif
594
    XMEMSET(line, 0, MAX_MIME_LINE_LEN);
595
596
    while ((lineLen = wolfSSL_BIO_gets(in, line, MAX_MIME_LINE_LEN)) > 0) {
597
598
        if (line[lineLen - 1] == '\r' || line[lineLen - 1] == '\n') {
599
            canonLineLen = (word32)lineLen;
600
            if ((canonLine = wc_MIME_single_canonicalize(
601
                                line, &canonLineLen)) == NULL) {
602
                ret = WOLFSSL_FATAL_ERROR;
603
                break;
604
            }
605
606
            /* remove trailing null */
607
            if (canonLineLen >= 1 && canonLine[canonLineLen-1] == '\0') {
608
                canonLineLen--;
609
            }
610
611
            if (wolfSSL_BIO_write(out, canonLine, (int)canonLineLen) < 0) {
612
                ret = WOLFSSL_FATAL_ERROR;
613
                break;
614
            }
615
            XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
616
            canonLine = NULL;
617
        }
618
        else {
619
            /* no line ending in current line, write direct to out */
620
            if (wolfSSL_BIO_write(out, line, lineLen) < 0) {
621
                ret = WOLFSSL_FATAL_ERROR;
622
                break;
623
            }
624
        }
625
    }
626
627
    XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
628
    WC_FREE_VAR_EX(line, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
629
630
    return ret;
631
}
632
633
#endif /* HAVE_SMIME */
634
635
/* Used by both PKCS7_final() and PKCS7_verify() */
636
static const char contTypeText[] = "Content-Type: text/plain\r\n\r\n";
637
638
/**
639
 * Finalize PKCS7 structure, currently supports signedData only.
640
 *
641
 * Does not generate final bundle (ie: signedData), but finalizes
642
 * the PKCS7 structure in preparation for a output function to be called next.
643
 *
644
 * pkcs7 - initialized PKCS7 structure, populated with signer, etc
645
 * in    - input data
646
 * flags - flags to control PKCS7 behavior. Other flags except those noted
647
 *         below are ignored:
648
 *
649
 *    PKCS7_BINARY - Do not translate input data to MIME canonical
650
 *                   format (\r\n line endings), thus preventing corruption of
651
 *                   binary content.
652
 *    PKCS7_TEXT   - Prepend MIME headers for text/plain to content.
653
 *
654
 * Returns 1 on success, 0 on error
655
 */
656
int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags)
657
{
658
    int ret = 1;
659
    int memSz = 0;
660
    unsigned char* mem = NULL;
661
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
662
    WOLFSSL_BIO* data = NULL;
663
664
    WOLFSSL_ENTER("wolfSSL_PKCS7_final");
665
666
    if (p7 == NULL || in == NULL) {
667
        WOLFSSL_MSG("Bad input args to PKCS7_final");
668
        ret = 0;
669
    }
670
671
    if (ret == 1) {
672
        if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) {
673
            WOLFSSL_MSG("Error in wolfSSL_BIO_new");
674
            ret = 0;
675
        }
676
    }
677
678
    /* prepend Content-Type header if PKCS7_TEXT */
679
    if ((ret == 1) && (flags & PKCS7_TEXT)) {
680
        if (wolfSSL_BIO_write(data, contTypeText,
681
                              (int)XSTR_SIZEOF(contTypeText)) < 0) {
682
            WOLFSSL_MSG("Error prepending Content-Type header");
683
            ret = 0;
684
        }
685
    }
686
687
    /* convert line endings to CRLF if !PKCS7_BINARY */
688
    if (ret == 1) {
689
        if (flags & PKCS7_BINARY) {
690
691
            /* no CRLF conversion, direct copy content */
692
            if ((memSz = wolfSSL_BIO_get_len(in)) <= 0) {
693
                ret = 0;
694
            }
695
            if (ret == 1) {
696
                mem = (unsigned char*)XMALLOC(memSz, in->heap,
697
                                              DYNAMIC_TYPE_TMP_BUFFER);
698
                if (mem == NULL) {
699
                    WOLFSSL_MSG("Failed to allocate memory for input data");
700
                    ret = 0;
701
                }
702
            }
703
704
            if (ret == 1) {
705
                if (wolfSSL_BIO_read(in, mem, memSz) != memSz) {
706
                    WOLFSSL_MSG("Error reading from input BIO");
707
                    ret = 0;
708
                }
709
                else if (wolfSSL_BIO_write(data, mem, memSz) < 0) {
710
                    ret = 0;
711
                }
712
            }
713
714
            XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER);
715
        }
716
        else {
717
    #ifdef HAVE_SMIME
718
            /* convert content line endings to CRLF */
719
            if (wolfSSL_BIO_to_MIME_crlf(in, data) != 0) {
720
                WOLFSSL_MSG("Error converting line endings to CRLF");
721
                ret = 0;
722
            }
723
            else {
724
                p7->pkcs7.contentCRLF = 1;
725
            }
726
    #else
727
            WOLFSSL_MSG("Without PKCS7_BINARY requires wolfSSL to be built "
728
                        "with HAVE_SMIME");
729
            ret = 0;
730
    #endif
731
        }
732
    }
733
734
    if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) {
735
        WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data");
736
        ret = 0;
737
    }
738
739
    if (ret == 1) {
740
        XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7);
741
        p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7);
742
        if (p7->data == NULL) {
743
            ret = 0;
744
        }
745
        else {
746
            XMEMCPY(p7->data, mem, memSz);
747
            p7->len = memSz;
748
        }
749
    }
750
751
    if (ret == 1) {
752
        p7->pkcs7.content = p7->data;
753
        p7->pkcs7.contentSz = (word32)p7->len;
754
    }
755
756
    if (data != NULL) {
757
        wolfSSL_BIO_free(data);
758
    }
759
760
    return ret;
761
}
762
763
int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
764
        WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags)
765
{
766
    int i, ret = 0;
767
    unsigned char* mem = NULL;
768
    int memSz = 0;
769
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
770
    int contTypeLen;
771
    WOLFSSL_X509* signer = NULL;
772
    WOLFSSL_STACK* signers = NULL;
773
    X509_STORE_CTX* ctx = NULL;
774
775
776
    WOLFSSL_ENTER("wolfSSL_PKCS7_verify");
777
778
    if (pkcs7 == NULL)
779
        return WOLFSSL_FAILURE;
780
781
    if (in != NULL) {
782
        if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0)
783
            return WOLFSSL_FAILURE;
784
785
        p7->pkcs7.content = mem;
786
        p7->pkcs7.contentSz = (word32)memSz;
787
    }
788
789
    /* certs is the list of certificates to find the cert with issuer/serial. */
790
    (void)certs;
791
    /* store is the certificate store to use to verify signer certificate
792
     * associated with the signers.
793
     */
794
    (void)store;
795
796
    ret = wc_PKCS7_VerifySignedData(&p7->pkcs7, p7->data, p7->len);
797
    if (ret != 0)
798
        return WOLFSSL_FAILURE;
799
800
    if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
801
        /* Verify signer certificates */
802
        if (store == NULL || store->cm == NULL) {
803
            WOLFSSL_MSG("No store or store certs, but PKCS7_NOVERIFY not set");
804
            return WOLFSSL_FAILURE;
805
        }
806
807
        ctx = X509_STORE_CTX_new();
808
        if (ctx == NULL) {
809
            WOLFSSL_MSG("Error allocating X509 Store Context");
810
            return WOLFSSL_FAILURE;
811
        }
812
813
        signers = wolfSSL_PKCS7_get0_signers(pkcs7, certs, flags);
814
        if (signers == NULL) {
815
            WOLFSSL_MSG("No signers found to verify");
816
            wolfSSL_X509_STORE_CTX_free(ctx);
817
            return WOLFSSL_FAILURE;
818
        }
819
820
        for (i = 0; i < wolfSSL_sk_X509_num(signers); i++) {
821
            signer = wolfSSL_sk_X509_value(signers, i);
822
            if (wolfSSL_X509_STORE_CTX_init(ctx, store, signer, NULL)
823
                        != WOLFSSL_SUCCESS) {
824
                WOLFSSL_MSG("Failed to initialize X509 STORE CTX");
825
                wolfSSL_sk_X509_pop_free(signers, NULL);
826
                wolfSSL_X509_STORE_CTX_free(ctx);
827
                return WOLFSSL_FAILURE;
828
            }
829
            if (wolfSSL_X509_verify_cert(ctx) != WOLFSSL_SUCCESS) {
830
                WOLFSSL_MSG("Failed to verify signer certificate");
831
                wolfSSL_sk_X509_pop_free(signers, NULL);
832
                wolfSSL_X509_STORE_CTX_free(ctx);
833
                return WOLFSSL_FAILURE;
834
            }
835
        }
836
        wolfSSL_sk_X509_pop_free(signers, NULL);
837
        wolfSSL_X509_STORE_CTX_free(ctx);
838
    }
839
840
    if (flags & PKCS7_TEXT) {
841
        /* strip MIME header for text/plain, otherwise error */
842
        contTypeLen = XSTR_SIZEOF(contTypeText);
843
        if ((p7->pkcs7.contentSz < (word32)contTypeLen) ||
844
            (XMEMCMP(p7->pkcs7.content, contTypeText, contTypeLen) != 0)) {
845
            WOLFSSL_MSG("Error PKCS7 Content-Type not found with PKCS7_TEXT");
846
            return WOLFSSL_FAILURE;
847
        }
848
        p7->pkcs7.content += contTypeLen;
849
        p7->pkcs7.contentSz -= contTypeLen;
850
    }
851
852
    if (out != NULL) {
853
        wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz);
854
    }
855
856
    WOLFSSL_LEAVE("wolfSSL_PKCS7_verify", WOLFSSL_SUCCESS);
857
858
    return WOLFSSL_SUCCESS;
859
}
860
861
/**
862
 * This API was added as a helper function for libest. It
863
 * encodes a stack of certificates to pkcs7 format.
864
 * @param pkcs7 PKCS7 parameter object
865
 * @param certs WOLFSSL_STACK_OF(WOLFSSL_X509)*
866
 * @param out   Output bio
867
 * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
868
 */
869
int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
870
        WOLFSSL_BIO* out)
871
{
872
    int ret;
873
    WOLFSSL_PKCS7* p7;
874
    WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs");
875
876
    if (!pkcs7 || !certs || !out) {
877
        WOLFSSL_MSG("Bad parameter");
878
        return WOLFSSL_FAILURE;
879
    }
880
881
    p7 = (WOLFSSL_PKCS7*)pkcs7;
882
883
    /* take ownership of certs */
884
    p7->certs = certs;
885
    /* TODO: takes ownership even on failure below but not on above failure. */
886
887
    if (pkcs7->certList) {
888
        WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same "
889
                    "struct");
890
        return WOLFSSL_FAILURE;
891
    }
892
893
    if (certs) {
894
        /* Save some of the values */
895
        int hashOID = pkcs7->hashOID;
896
        byte version = pkcs7->version;
897
898
        if (!certs->data.x509 || !certs->data.x509->derCert) {
899
            WOLFSSL_MSG("Missing cert");
900
            return WOLFSSL_FAILURE;
901
        }
902
903
        if (wc_PKCS7_InitWithCert(pkcs7, certs->data.x509->derCert->buffer,
904
                                      certs->data.x509->derCert->length) != 0) {
905
            WOLFSSL_MSG("wc_PKCS7_InitWithCert error");
906
            return WOLFSSL_FAILURE;
907
        }
908
        certs = certs->next;
909
910
        pkcs7->hashOID = hashOID;
911
        pkcs7->version = version;
912
    }
913
914
    /* Add the certs to the PKCS7 struct */
915
    while (certs) {
916
        if (!certs->data.x509 || !certs->data.x509->derCert) {
917
            WOLFSSL_MSG("Missing cert");
918
            return WOLFSSL_FAILURE;
919
        }
920
        if (wc_PKCS7_AddCertificate(pkcs7, certs->data.x509->derCert->buffer,
921
                                      certs->data.x509->derCert->length) != 0) {
922
            WOLFSSL_MSG("wc_PKCS7_AddCertificate error");
923
            return WOLFSSL_FAILURE;
924
        }
925
        certs = certs->next;
926
    }
927
928
    if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) {
929
        WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error");
930
        return WOLFSSL_FAILURE;
931
    }
932
933
    ret = wolfSSL_i2d_PKCS7_bio(out, pkcs7);
934
935
    return ret;
936
}
937
938
/******************************************************************************
939
* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO
940
*
941
* RETURNS:
942
* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE
943
*/
944
int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
945
{
946
#ifdef WOLFSSL_SMALL_STACK
947
    byte* outputHead;
948
    byte* outputFoot;
949
#else
950
    byte outputHead[2048];
951
    byte outputFoot[2048];
952
#endif
953
    word32 outputHeadSz = 2048;
954
    word32 outputFootSz = 2048;
955
    word32 outputSz = 0;
956
    byte*  output = NULL;
957
    byte*  pem = NULL;
958
    int    pemSz = -1;
959
    enum wc_HashType hashType;
960
    byte hashBuf[WC_MAX_DIGEST_SIZE];
961
    word32 hashSz = 0;
962
963
    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7");
964
965
    if (bio == NULL || p7 == NULL)
966
        return WOLFSSL_FAILURE;
967
968
#ifdef WOLFSSL_SMALL_STACK
969
    outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap,
970
        DYNAMIC_TYPE_TMP_BUFFER);
971
    if (outputHead == NULL)
972
        return MEMORY_E;
973
974
    outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap,
975
        DYNAMIC_TYPE_TMP_BUFFER);
976
    if (outputFoot == NULL)
977
        goto error;
978
979
#endif
980
981
    XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE);
982
    XMEMSET(outputHead, 0, outputHeadSz);
983
    XMEMSET(outputFoot, 0, outputFootSz);
984
985
    hashType = wc_OidGetHash(p7->hashOID);
986
    hashSz = (word32)wc_HashGetDigestSize(hashType);
987
    if (hashSz > WC_MAX_DIGEST_SIZE)
988
        goto error;
989
990
    /* only SIGNED_DATA is supported */
991
    switch (p7->contentOID) {
992
        case SIGNED_DATA:
993
            break;
994
        default:
995
            WOLFSSL_MSG("Unknown PKCS#7 Type");
996
            goto error;
997
    };
998
999
    if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz,
1000
        outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0)
1001
        goto error;
1002
1003
    outputSz = outputHeadSz + p7->contentSz + outputFootSz;
1004
    output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1005
1006
    if (!output)
1007
        goto error;
1008
1009
    XMEMSET(output, 0, outputSz);
1010
    outputSz = 0;
1011
    XMEMCPY(&output[outputSz], outputHead, outputHeadSz);
1012
    outputSz += outputHeadSz;
1013
    XMEMCPY(&output[outputSz], p7->content, p7->contentSz);
1014
    outputSz += p7->contentSz;
1015
    XMEMCPY(&output[outputSz], outputFoot, outputFootSz);
1016
    outputSz += outputFootSz;
1017
1018
    /* get PEM size */
1019
    pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE);
1020
    if (pemSz < 0)
1021
        goto error;
1022
1023
    pemSz++; /* for '\0'*/
1024
1025
    /* create PEM buffer and convert from DER to PEM*/
1026
    if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER))
1027
                                                                        == NULL)
1028
        goto error;
1029
1030
    XMEMSET(pem, 0, pemSz);
1031
1032
    if (wc_DerToPemEx(output, outputSz, pem, (word32)pemSz, NULL,CERT_TYPE)
1033
                                                                          < 0) {
1034
        goto error;
1035
    }
1036
    if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
1037
        XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1038
        XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1039
        WC_FREE_VAR_EX(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1040
        WC_FREE_VAR_EX(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1041
        return WOLFSSL_SUCCESS;
1042
    }
1043
1044
error:
1045
    WC_FREE_VAR_EX(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1046
    WC_FREE_VAR_EX(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1047
    XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1048
    XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1049
    return WOLFSSL_FAILURE;
1050
}
1051
1052
#ifdef HAVE_SMIME
1053
/*****************************************************************************
1054
* wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into
1055
* a PKCS7 object. In case of a multipart message, stores the signed data in
1056
* bcont.
1057
*
1058
* RETURNS:
1059
* returns pointer to a PKCS7 structure on success, otherwise returns NULL
1060
*/
1061
PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in,
1062
        WOLFSSL_BIO** bcont)
1063
{
1064
    MimeHdr* allHdrs = NULL;
1065
    MimeHdr* curHdr = NULL;
1066
    MimeParam* curParam = NULL;
1067
    int inLen = 0;
1068
    byte* bcontMem = NULL;
1069
    int bcontMemSz = 0;
1070
    int sectionLen = 0;
1071
    int ret = -1;
1072
    char* section = NULL;
1073
    char* canonLine = NULL;
1074
    char* canonSection = NULL;
1075
    PKCS7* pkcs7 = NULL;
1076
    word32 outLen = 0;
1077
    word32 canonLineLen = 0;
1078
    byte* out = NULL;
1079
    byte* outHead = NULL;
1080
1081
    int canonPos = 0;
1082
    int lineLen = 0;
1083
    int remainLen = 0;
1084
    byte isEnd = 0;
1085
    size_t canonSize = 0;
1086
    size_t boundLen = 0;
1087
    char* boundary = NULL;
1088
1089
    static const char kContType[] = "Content-Type";
1090
    static const char kCTE[] = "Content-Transfer-Encoding";
1091
    static const char kMultSigned[] = "multipart/signed";
1092
    static const char kAppPkcsSign[] = "application/pkcs7-signature";
1093
    static const char kAppXPkcsSign[] = "application/x-pkcs7-signature";
1094
    static const char kAppPkcs7Mime[] = "application/pkcs7-mime";
1095
    static const char kAppXPkcs7Mime[] = "application/x-pkcs7-mime";
1096
1097
    WOLFSSL_ENTER("wolfSSL_SMIME_read_PKCS7");
1098
1099
    if (in == NULL || bcont == NULL) {
1100
        goto error;
1101
    }
1102
    inLen = wolfSSL_BIO_get_len(in);
1103
    if (inLen <= 0) {
1104
        goto error;
1105
    }
1106
    remainLen = wolfSSL_BIO_get_len(in);
1107
    if (remainLen <= 0) {
1108
        goto error;
1109
    }
1110
1111
    section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7);
1112
    if (section == NULL) {
1113
        goto error;
1114
    }
1115
    lineLen = wolfSSL_BIO_gets(in, section, remainLen);
1116
    if (lineLen <= 0) {
1117
        goto error;
1118
    }
1119
    while (isEnd == 0 && remainLen > 0) {
1120
        sectionLen += lineLen;
1121
        remainLen -= lineLen;
1122
        lineLen = wolfSSL_BIO_gets(in, &section[sectionLen], remainLen);
1123
        if (lineLen <= 0) {
1124
            goto error;
1125
        }
1126
        /* Line with just newline signals end of headers. */
1127
        if ((lineLen==2 && !XSTRNCMP(&section[sectionLen],
1128
                                     "\r\n", 2)) ||
1129
            (lineLen==1 && (section[sectionLen] == '\r' ||
1130
                            section[sectionLen] == '\n'))) {
1131
            isEnd = 1;
1132
        }
1133
    }
1134
    section[sectionLen] = '\0';
1135
    ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
1136
    if (ret < 0) {
1137
        WOLFSSL_MSG("Parsing MIME headers failed.");
1138
        goto error;
1139
    }
1140
    isEnd = 0;
1141
    section[0] = '\0';
1142
    sectionLen = 0;
1143
1144
    curHdr = wc_MIME_find_header_name(kContType, allHdrs);
1145
    if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned,
1146
                            XSTR_SIZEOF(kMultSigned))) {
1147
        curParam = wc_MIME_find_param_attr("protocol", curHdr->params);
1148
        if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign,
1149
                                   XSTR_SIZEOF(kAppPkcsSign)) ||
1150
                         !XSTRNCMP(curParam->value, kAppXPkcsSign,
1151
                                   XSTR_SIZEOF(kAppXPkcsSign)))) {
1152
            curParam = wc_MIME_find_param_attr("boundary", curHdr->params);
1153
            if (curParam == NULL) {
1154
                goto error;
1155
            }
1156
1157
            boundLen = XSTRLEN(curParam->value) + 2;
1158
            boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7);
1159
            if (boundary == NULL) {
1160
                goto error;
1161
            }
1162
            XMEMSET(boundary, 0, (word32)(boundLen+1));
1163
            boundary[0] = boundary[1] = '-';
1164
            /* analyzers have issues with using strncpy and strcpy here */
1165
            XMEMCPY(&boundary[2], curParam->value, boundLen - 2);
1166
1167
            /* Parse up to first boundary, ignore everything here. */
1168
            lineLen = wolfSSL_BIO_gets(in, section, remainLen);
1169
            if (lineLen <= 0) {
1170
                goto error;
1171
            }
1172
            while (XSTRNCMP(&section[sectionLen], boundary, boundLen) &&
1173
                   remainLen > 0) {
1174
                sectionLen += lineLen;
1175
                remainLen -= lineLen;
1176
                lineLen = wolfSSL_BIO_gets(in, &section[sectionLen],
1177
                                           remainLen);
1178
                if (lineLen <= 0) {
1179
                    goto error;
1180
                }
1181
            }
1182
1183
            section[0] = '\0';
1184
            sectionLen = 0;
1185
            canonSize = (size_t)remainLen + 1;
1186
            canonSection = (char*)XMALLOC(canonSize, NULL,
1187
                                          DYNAMIC_TYPE_PKCS7);
1188
            if (canonSection == NULL) {
1189
                goto error;
1190
            } else {
1191
                XMEMSET(canonSection, 0, (word32)canonSize);
1192
            }
1193
1194
            lineLen = wolfSSL_BIO_gets(in, section, remainLen);
1195
            if (lineLen < 0) {
1196
                goto error;
1197
            }
1198
            while (XSTRNCMP(&section[sectionLen], boundary, boundLen) &&
1199
                            remainLen > 0) {
1200
                canonLineLen = (word32)lineLen;
1201
                canonLine = wc_MIME_single_canonicalize(&section[sectionLen],
1202
                                                        &canonLineLen);
1203
                if (canonLine == NULL) {
1204
                    goto error;
1205
                }
1206
                /* If line endings were added, the initial length may be
1207
                 * exceeded. */
1208
                if ((canonPos + canonLineLen) >= canonSize) {
1209
                    char* newCanonSection;
1210
                    canonSize = canonPos + canonLineLen;
1211
                    newCanonSection = (char*)XREALLOC(canonSection, canonSize,
1212
                                                   NULL, DYNAMIC_TYPE_PKCS7);
1213
                    if (newCanonSection == NULL) {
1214
                        goto error;
1215
                    }
1216
                    canonSection = newCanonSection;
1217
                }
1218
                XMEMCPY(&canonSection[canonPos], canonLine,
1219
                        (int)canonLineLen - 1);
1220
                canonPos += canonLineLen - 1;
1221
                XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
1222
                canonLine = NULL;
1223
1224
                sectionLen += lineLen;
1225
                remainLen -= lineLen;
1226
1227
                lineLen = wolfSSL_BIO_gets(in, &section[sectionLen],
1228
                                           remainLen);
1229
                if (lineLen <= 0) {
1230
                    goto error;
1231
                }
1232
            }
1233
1234
            if (canonPos > 0) {
1235
                canonPos--;
1236
            }
1237
1238
            /* Strip the final trailing newline.  Support \r, \n or \r\n. */
1239
            if (canonSection[canonPos] == '\n') {
1240
                if (canonPos > 0) {
1241
                    canonPos--;
1242
                }
1243
            }
1244
1245
            if (canonSection[canonPos] == '\r') {
1246
                if (canonPos > 0) {
1247
                    canonPos--;
1248
                }
1249
            }
1250
1251
            canonSection[canonPos+1] = '\0';
1252
1253
            *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
1254
            ret = wolfSSL_BIO_write(*bcont, canonSection,
1255
                                    canonPos + 1);
1256
            if (ret != (canonPos+1)) {
1257
                goto error;
1258
            }
1259
            if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem))
1260
                                                                          < 0) {
1261
                goto error;
1262
            }
1263
            XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
1264
            canonSection = NULL;
1265
1266
            wc_MIME_free_hdrs(allHdrs);
1267
            allHdrs = NULL;
1268
            section[0] = '\0';
1269
            sectionLen = 0;
1270
            lineLen = wolfSSL_BIO_gets(in, section, remainLen);
1271
            if (lineLen <= 0) {
1272
                goto error;
1273
            }
1274
            while (isEnd == 0 && remainLen > 0) {
1275
                sectionLen += lineLen;
1276
                remainLen -= lineLen;
1277
                lineLen = wolfSSL_BIO_gets(in, &section[sectionLen],
1278
                                           remainLen);
1279
                if (lineLen <= 0) {
1280
                    goto error;
1281
                }
1282
                /* Line with just newline signals end of headers. */
1283
                if ((lineLen==2 && !XSTRNCMP(&section[sectionLen],
1284
                                             "\r\n", 2)) ||
1285
                    (lineLen==1 && (section[sectionLen] == '\r' ||
1286
                                    section[sectionLen] == '\n'))) {
1287
                    isEnd = 1;
1288
                }
1289
            }
1290
            section[sectionLen] = '\0';
1291
            ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs);
1292
            if (ret < 0) {
1293
                WOLFSSL_MSG("Parsing MIME headers failed.");
1294
                goto error;
1295
            }
1296
            curHdr = wc_MIME_find_header_name(kContType, allHdrs);
1297
            if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign,
1298
                                   XSTR_SIZEOF(kAppPkcsSign)) &&
1299
                                   XSTRNCMP(curHdr->body, kAppXPkcsSign,
1300
                                   XSTR_SIZEOF(kAppXPkcsSign)))) {
1301
                WOLFSSL_MSG("S/MIME headers not found inside "
1302
                            "multipart message.\n");
1303
                goto error;
1304
            }
1305
1306
            section[0] = '\0';
1307
            sectionLen = 0;
1308
            lineLen = wolfSSL_BIO_gets(in, section, remainLen);
1309
            while (XSTRNCMP(&section[sectionLen], boundary, boundLen) &&
1310
                   remainLen > 0) {
1311
                sectionLen += lineLen;
1312
                remainLen -= lineLen;
1313
                lineLen = wolfSSL_BIO_gets(in, &section[sectionLen],
1314
                                           remainLen);
1315
                if (lineLen <= 0) {
1316
                    goto error;
1317
                }
1318
            }
1319
1320
            XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
1321
            boundary = NULL;
1322
        }
1323
    }
1324
    else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime,
1325
                                  XSTR_SIZEOF(kAppPkcs7Mime)) ||
1326
                        !XSTRNCMP(curHdr->body, kAppXPkcs7Mime,
1327
                                  XSTR_SIZEOF(kAppXPkcs7Mime)))) {
1328
        sectionLen = wolfSSL_BIO_get_len(in);
1329
        if (sectionLen <= 0) {
1330
            goto error;
1331
        }
1332
        ret = wolfSSL_BIO_read(in, section, sectionLen);
1333
        if (ret < 0 || ret != sectionLen) {
1334
            WOLFSSL_MSG("Error reading input BIO.");
1335
            goto error;
1336
        }
1337
    }
1338
    else {
1339
        WOLFSSL_MSG("S/MIME headers not found.");
1340
        goto error;
1341
    }
1342
1343
    curHdr = wc_MIME_find_header_name(kCTE, allHdrs);
1344
    if (curHdr == NULL) {
1345
        WOLFSSL_MSG("Content-Transfer-Encoding header not found, "
1346
                    "assuming base64 encoding.");
1347
    }
1348
    else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) {
1349
        WOLFSSL_MSG("S/MIME encodings other than base64 are not "
1350
                    "currently supported.\n");
1351
        goto error;
1352
    }
1353
1354
    if (section == NULL || sectionLen <= 0) {
1355
        goto error;
1356
    }
1357
    outLen = (word32)((sectionLen*3+3)/4)+1;
1358
    out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7);
1359
    outHead = out;
1360
    if (outHead == NULL) {
1361
        goto error;
1362
    }
1363
    /* Strip trailing newlines. */
1364
    while ((sectionLen > 0) &&
1365
           (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) {
1366
        sectionLen--;
1367
    }
1368
    section[sectionLen] = '\0';
1369
    ret = Base64_Decode((const byte*)section, (word32)sectionLen, out, &outLen);
1370
    if (ret < 0) {
1371
        WOLFSSL_MSG("Error base64 decoding S/MIME message.");
1372
        goto error;
1373
    }
1374
    pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out,
1375
        (int)outLen, bcontMem, (word32)bcontMemSz);
1376
1377
    wc_MIME_free_hdrs(allHdrs);
1378
    XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
1379
    XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
1380
1381
    return pkcs7;
1382
1383
error:
1384
    wc_MIME_free_hdrs(allHdrs);
1385
    XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7);
1386
    XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
1387
    XFREE(section, NULL, DYNAMIC_TYPE_PKCS7);
1388
    XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7);
1389
    XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7);
1390
    if (bcont) {
1391
        wolfSSL_BIO_free(*bcont);
1392
        *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */
1393
    }
1394
1395
    return NULL;
1396
}
1397
1398
/* Convert hash algo OID (from Hash_Sum in asn.h) to SMIME string equivalent.
1399
 * Returns hash algorithm string or "unknown" if not found */
1400
static const char* wolfSSL_SMIME_HashOIDToString(int hashOID)
1401
{
1402
    switch (hashOID) {
1403
        case MD5h:
1404
            return "md5";
1405
        case SHAh:
1406
            return "sha1";
1407
        case SHA224h:
1408
            return "sha-224";
1409
        case SHA256h:
1410
            return "sha-256";
1411
        case SHA384h:
1412
            return "sha-384";
1413
        case SHA512h:
1414
            return "sha-512";
1415
        case SHA3_224h:
1416
            return "sha3-224";
1417
        case SHA3_384h:
1418
            return "sha3-384";
1419
        case SHA3_512h:
1420
            return "sha3-512";
1421
        default:
1422
            break;
1423
    }
1424
1425
    return "unknown";
1426
}
1427
1428
/* Convert PKCS#7 type (from PKCS7_TYPES in pkcs7.h) to SMIME string.
1429
 * RFC2633 only defines signed-data, enveloped-data, certs-only.
1430
 * Returns string on success, NULL on unknown type. */
1431
static const char* wolfSSL_SMIME_PKCS7TypeToString(int type)
1432
{
1433
    switch (type) {
1434
        case SIGNED_DATA:
1435
            return "signed-data";
1436
        case ENVELOPED_DATA:
1437
            return "enveloped-data";
1438
        default:
1439
            break;
1440
    }
1441
1442
    return NULL;
1443
}
1444
1445
/**
1446
 * Convert PKCS7 structure to SMIME format, adding necessary headers.
1447
 *
1448
 * Handles generation of PKCS7 bundle (ie: signedData). PKCS7 structure
1449
 * should be set up beforehand with PKCS7_sign/final/etc. Output is always
1450
 * Base64 encoded.
1451
 *
1452
 * out   - output BIO for SMIME formatted data to be placed
1453
 * pkcs7 - input PKCS7 structure, initialized and set up
1454
 * in    - input content to be encoded into PKCS7
1455
 * flags - flags to control behavior of PKCS7 generation
1456
 *
1457
 * Returns 1 on success, 0 or negative on failure
1458
 */
1459
int wolfSSL_SMIME_write_PKCS7(WOLFSSL_BIO* out, PKCS7* pkcs7, WOLFSSL_BIO* in,
1460
                              int flags)
1461
{
1462
    int i;
1463
    int ret = 1;
1464
    WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7;
1465
    byte* p7out = NULL;
1466
    int len = 0;
1467
1468
    char boundary[33]; /* 32 chars + \0 */
1469
    byte* sigBase64 = NULL;
1470
    word32 sigBase64Len = 0;
1471
    const char* p7TypeString = NULL;
1472
1473
    static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1474
1475
    if (out == NULL || p7 == NULL) {
1476
        WOLFSSL_MSG("Bad function arguments");
1477
        return 0;
1478
    }
1479
1480
    if (in != NULL && (p7->pkcs7.content == NULL || p7->pkcs7.contentSz == 0 ||
1481
                       p7->pkcs7.contentCRLF == 0)) {
1482
        /* store and adjust content line endings for CRLF if needed */
1483
        if (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1) {
1484
            ret = 0;
1485
        }
1486
    }
1487
1488
    if (ret > 0) {
1489
        /* Generate signedData bundle, DER in output (dynamic) */
1490
        if ((len = wolfSSL_i2d_PKCS7((PKCS7*)p7, &p7out)) ==
1491
            WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
1492
        {
1493
            WOLFSSL_MSG("Error in wolfSSL_i2d_PKCS7");
1494
            ret = 0;
1495
        }
1496
    }
1497
1498
    /* Base64 encode signedData bundle */
1499
    if (ret > 0) {
1500
        if (Base64_Encode(p7out, (word32)len, NULL, &sigBase64Len) !=
1501
            WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
1502
            ret = 0;
1503
        }
1504
        else {
1505
            sigBase64 = (byte*)XMALLOC(sigBase64Len, NULL,
1506
                                       DYNAMIC_TYPE_TMP_BUFFER);
1507
            if (sigBase64 == NULL) {
1508
                ret = 0;
1509
            }
1510
        }
1511
    }
1512
1513
    if (ret > 0) {
1514
        XMEMSET(sigBase64, 0, sigBase64Len);
1515
        if (Base64_Encode(p7out, (word32)len, sigBase64, &sigBase64Len) < 0) {
1516
            WOLFSSL_MSG("Error in Base64_Encode of signature");
1517
            ret = 0;
1518
        }
1519
    }
1520
1521
    /* build up SMIME message */
1522
    if (ret > 0) {
1523
        if (flags & PKCS7_DETACHED) {
1524
1525
            /* generate random boundary */
1526
            if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) {
1527
                WOLFSSL_MSG("No RNG to use");
1528
                ret = 0;
1529
            }
1530
1531
            /* no need to generate random byte for null terminator (size-1) */
1532
            if ((ret > 0) && (wc_RNG_GenerateBlock(&globalRNG, (byte*)boundary,
1533
                                  sizeof(boundary) - 1 ) != 0)) {
1534
                    WOLFSSL_MSG("Error in wc_RNG_GenerateBlock");
1535
                    ret = 0;
1536
            }
1537
1538
            if (ret > 0) {
1539
                for (i = 0; i < (int)sizeof(boundary) - 1; i++) {
1540
                    boundary[i] =
1541
                        alphanum[boundary[i] % XSTR_SIZEOF(alphanum)];
1542
                }
1543
                boundary[sizeof(boundary)-1] = 0;
1544
            }
1545
1546
            if (ret > 0) {
1547
                /* S/MIME header beginning */
1548
                ret = wolfSSL_BIO_printf(out,
1549
                        "MIME-Version: 1.0\n"
1550
                        "Content-Type: multipart/signed; "
1551
                        "protocol=\"application/x-pkcs7-signature\"; "
1552
                        "micalg=\"%s\"; "
1553
                        "boundary=\"----%s\"\n\n"
1554
                        "This is an S/MIME signed message\n\n"
1555
                        "------%s\n",
1556
                        wolfSSL_SMIME_HashOIDToString(p7->pkcs7.hashOID),
1557
                        boundary, boundary);
1558
            }
1559
1560
            if (ret > 0) {
1561
                /* S/MIME content */
1562
                ret = wolfSSL_BIO_write(out,
1563
                        p7->pkcs7.content, p7->pkcs7.contentSz);
1564
            }
1565
1566
            if (ret > 0) {
1567
                /* S/SMIME header end boundary */
1568
                ret = wolfSSL_BIO_printf(out,
1569
                        "\n------%s\n", boundary);
1570
            }
1571
1572
            if (ret > 0) {
1573
                /* Signature and header */
1574
                ret = wolfSSL_BIO_printf(out,
1575
                        "Content-Type: application/x-pkcs7-signature; "
1576
                        "name=\"smime.p7s\"\n"
1577
                        "Content-Transfer-Encoding: base64\n"
1578
                        "Content-Disposition: attachment; "
1579
                        "filename=\"smime.p7s\"\n\n"
1580
                        "%.*s\n" /* Base64 encoded signature */
1581
                        "------%s--\n\n",
1582
                        sigBase64Len, sigBase64,
1583
                        boundary);
1584
            }
1585
        }
1586
        else {
1587
            p7TypeString = wolfSSL_SMIME_PKCS7TypeToString(p7->type);
1588
            if (p7TypeString == NULL) {
1589
                WOLFSSL_MSG("Unsupported PKCS7 SMIME type");
1590
                ret = 0;
1591
            }
1592
1593
            if (ret > 0) {
1594
                /* not detached */
1595
                ret = wolfSSL_BIO_printf(out,
1596
                        "MIME-Version: 1.0\n"
1597
                        "Content-Disposition: attachment; "
1598
                        "filename=\"smime.p7m\"\n"
1599
                        "Content-Type: application/x-pkcs7-mime; "
1600
                        "smime-type=%s; name=\"smime.p7m\"\n"
1601
                        "Content-Transfer-Encoding: base64\n\n"
1602
                        "%.*s\n" /* signature */,
1603
                        p7TypeString, sigBase64Len, sigBase64);
1604
            }
1605
        }
1606
    }
1607
1608
    XFREE(p7out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1609
    XFREE(sigBase64, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1610
1611
    if (ret > 0) {
1612
        return WOLFSSL_SUCCESS;
1613
    }
1614
1615
    return WOLFSSL_FAILURE;
1616
}
1617
1618
#endif /* HAVE_SMIME */
1619
#endif /* !NO_BIO */
1620
#endif /* OPENSSL_ALL */
1621
1622
#endif /* HAVE_PKCS7 */
1623
/*******************************************************************************
1624
 * END OF PKCS7 APIs
1625
 ******************************************************************************/
1626
1627
/*******************************************************************************
1628
 * START OF PKCS12 APIs
1629
 ******************************************************************************/
1630
#ifdef OPENSSL_EXTRA
1631
1632
/* no-op function. Was initially used for adding encryption algorithms available
1633
 * for PKCS12 */
1634
void wolfSSL_PKCS12_PBE_add(void)
1635
0
{
1636
0
    WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
1637
0
}
1638
1639
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
1640
WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp,
1641
        WOLFSSL_X509_PKCS12 **pkcs12)
1642
0
{
1643
0
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
1644
0
    return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12,
1645
0
        PKCS12_TYPE);
1646
0
}
1647
#endif /* !NO_FILESYSTEM */
1648
1649
#endif /* OPENSSL_EXTRA */
1650
1651
#if defined(HAVE_PKCS12)
1652
1653
#ifdef OPENSSL_EXTRA
1654
1655
#if !defined(NO_ASN) && !defined(NO_PWDBASED)
1656
1657
#ifndef NO_BIO
1658
WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
1659
0
{
1660
0
    WC_PKCS12* localPkcs12 = NULL;
1661
0
    unsigned char* mem = NULL;
1662
0
    long memSz;
1663
0
    int ret = -1;
1664
1665
0
    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
1666
1667
0
    if (bio == NULL) {
1668
0
        WOLFSSL_MSG("Bad Function Argument bio is NULL");
1669
0
        return NULL;
1670
0
    }
1671
1672
0
    memSz = wolfSSL_BIO_get_len(bio);
1673
0
    if (memSz <= 0) {
1674
0
        return NULL;
1675
0
    }
1676
0
    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1677
0
    if (mem == NULL) {
1678
0
        return NULL;
1679
0
    }
1680
1681
0
    if (mem != NULL) {
1682
0
        localPkcs12 = wc_PKCS12_new_ex(bio->heap);
1683
0
        if (localPkcs12 == NULL) {
1684
0
            WOLFSSL_MSG("Memory error");
1685
0
        }
1686
0
    }
1687
1688
0
    if (mem != NULL && localPkcs12 != NULL) {
1689
0
        if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
1690
0
            ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12);
1691
0
            if (ret < 0) {
1692
0
                WOLFSSL_MSG("Failed to get PKCS12 sequence");
1693
0
            }
1694
0
        }
1695
0
        else {
1696
0
            WOLFSSL_MSG("Failed to get data from bio struct");
1697
0
        }
1698
0
    }
1699
1700
    /* cleanup */
1701
0
    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
1702
0
    if (ret < 0 && localPkcs12 != NULL) {
1703
0
        wc_PKCS12_free(localPkcs12);
1704
0
        localPkcs12 = NULL;
1705
0
    }
1706
0
    if (pkcs12 != NULL)
1707
0
        *pkcs12 = localPkcs12;
1708
1709
0
    return localPkcs12;
1710
0
}
1711
1712
/* Converts the PKCS12 to DER format and outputs it into bio.
1713
 *
1714
 * bio is the structure to hold output DER
1715
 * pkcs12 structure to create DER from
1716
 *
1717
 * return 1 for success or 0 if an error occurs
1718
 */
1719
int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12)
1720
0
{
1721
0
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
1722
1723
0
    WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio");
1724
1725
0
    if ((bio != NULL) && (pkcs12 != NULL)) {
1726
0
        word32 certSz = 0;
1727
0
        byte *certDer = NULL;
1728
1729
0
        certSz = (word32)wc_i2d_PKCS12(pkcs12, &certDer, NULL);
1730
0
        if ((certSz > 0) && (certDer != NULL)) {
1731
0
            if (wolfSSL_BIO_write(bio, certDer, (int)certSz) == (int)certSz) {
1732
0
                ret = WOLFSSL_SUCCESS;
1733
0
            }
1734
0
        }
1735
1736
0
        XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS);
1737
0
    }
1738
1739
0
    return ret;
1740
0
}
1741
#endif /* !NO_BIO */
1742
1743
/* Creates a new WC_PKCS12 structure
1744
 *
1745
 * pass  password to use
1746
 * name  friendlyName to use
1747
 * pkey  private key to go into PKCS12 bundle
1748
 * cert  certificate to go into PKCS12 bundle
1749
 * ca    extra certificates that can be added to bundle. Can be NULL
1750
 * keyNID  type of encryption to use on the key (-1 means no encryption)
1751
 * certNID type of encryption to use on the certificate
1752
 * itt     number of iterations with encryption
1753
 * macItt  number of iterations with mac creation
1754
 * keyType flag for signature and/or encryption key
1755
 *
1756
 * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
1757
 */
1758
WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey,
1759
        WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, int keyNID,
1760
        int certNID, int itt, int macItt, int keyType)
1761
0
{
1762
0
    WC_PKCS12* pkcs12;
1763
0
    WC_DerCertList* list = NULL;
1764
0
    word32 passSz;
1765
0
    byte* keyDer = NULL;
1766
0
    word32 keyDerSz;
1767
0
    byte* certDer;
1768
0
    int certDerSz;
1769
1770
0
    WOLFSSL_ENTER("wolfSSL_PKCS12_create");
1771
1772
0
    if (pass == NULL || pkey == NULL || cert == NULL) {
1773
0
        WOLFSSL_LEAVE("wolfSSL_PKCS12_create", BAD_FUNC_ARG);
1774
0
        return NULL;
1775
0
    }
1776
0
    passSz = (word32)XSTRLEN(pass);
1777
1778
0
    keyDer = (byte*)pkey->pkey.ptr;
1779
0
    keyDerSz = (word32)pkey->pkey_sz;
1780
1781
0
    certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
1782
0
    if (certDer == NULL) {
1783
0
        return NULL;
1784
0
    }
1785
1786
0
    if (ca != NULL) {
1787
0
        unsigned long numCerts = ca->num;
1788
0
        WOLFSSL_STACK* sk = ca;
1789
1790
0
        while (numCerts > 0 && sk != NULL) {
1791
0
            byte* curDer;
1792
0
            WC_DerCertList* cur;
1793
0
            int   curDerSz = 0;
1794
1795
0
            cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
1796
0
                    DYNAMIC_TYPE_PKCS);
1797
0
            if (cur == NULL) {
1798
0
                wc_FreeCertList(list, NULL);
1799
0
                return NULL;
1800
0
            }
1801
1802
0
            curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
1803
0
            if (curDer == NULL || curDerSz < 0) {
1804
0
                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
1805
0
                wc_FreeCertList(list, NULL);
1806
0
                return NULL;
1807
0
            }
1808
1809
0
            cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
1810
0
            if (cur->buffer == NULL) {
1811
0
                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
1812
0
                wc_FreeCertList(list, NULL);
1813
0
                return NULL;
1814
0
            }
1815
0
            XMEMCPY(cur->buffer, curDer, curDerSz);
1816
0
            cur->bufferSz = (word32)curDerSz;
1817
0
            cur->next = list;
1818
0
            list = cur;
1819
1820
0
            sk = sk->next;
1821
0
            numCerts--;
1822
0
        }
1823
0
    }
1824
1825
0
    pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
1826
0
            certDer, (word32)certDerSz, list, keyNID, certNID, itt, macItt,
1827
0
            keyType, NULL);
1828
1829
0
    if (ca != NULL) {
1830
0
        wc_FreeCertList(list, NULL);
1831
0
    }
1832
1833
0
    return pkcs12;
1834
0
}
1835
1836
1837
/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
1838
int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
1839
          WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
1840
          WOLF_STACK_OF(WOLFSSL_X509)** ca)
1841
0
{
1842
0
    void* heap = NULL;
1843
0
    int ret;
1844
0
    byte* certData = NULL;
1845
0
    word32 certDataSz;
1846
0
    byte* pk = NULL;
1847
0
    word32 pkSz;
1848
0
    WC_DerCertList* certList = NULL;
1849
0
    WC_DECLARE_VAR(DeCert, DecodedCert, 1, 0);
1850
1851
0
    WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
1852
1853
    /* make sure we init return args */
1854
0
    if (pkey) *pkey = NULL;
1855
0
    if (cert) *cert = NULL;
1856
0
    if (ca)   *ca = NULL;
1857
1858
0
    if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
1859
0
        WOLFSSL_MSG("Bad argument value");
1860
0
        return WOLFSSL_FAILURE;
1861
0
    }
1862
1863
0
    heap  = wc_PKCS12_GetHeap(pkcs12);
1864
1865
0
    if (ca == NULL) {
1866
0
        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
1867
0
            NULL);
1868
0
    }
1869
0
    else {
1870
0
        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
1871
0
            &certList);
1872
0
    }
1873
0
    if (ret < 0) {
1874
0
        WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
1875
0
        return WOLFSSL_FAILURE;
1876
0
    }
1877
1878
0
#ifdef WOLFSSL_SMALL_STACK
1879
0
    DeCert = (DecodedCert *)XMALLOC(sizeof(*DeCert), heap,
1880
0
                                    DYNAMIC_TYPE_DCERT);
1881
0
    if (DeCert == NULL) {
1882
0
        WOLFSSL_MSG("out of memory");
1883
0
        return WOLFSSL_FAILURE;
1884
0
    }
1885
0
#endif
1886
1887
    /* Decode cert and place in X509 stack struct */
1888
0
    if (certList != NULL) {
1889
0
        WC_DerCertList* current = certList;
1890
1891
0
        *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(
1892
0
            sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509);
1893
0
        if (*ca == NULL) {
1894
0
            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
1895
0
            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
1896
            /* Free up WC_DerCertList and move on */
1897
0
            while (current != NULL) {
1898
0
                WC_DerCertList* next = current->next;
1899
1900
0
                XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
1901
0
                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
1902
0
                current = next;
1903
0
            }
1904
0
            ret = WOLFSSL_FAILURE;
1905
0
            goto out;
1906
0
        }
1907
0
        XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
1908
1909
        /* add list of DER certs as X509's to stack */
1910
0
        while (current != NULL) {
1911
0
            WC_DerCertList*  toFree = current;
1912
0
            WOLFSSL_X509* x509;
1913
1914
0
            x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
1915
0
                DYNAMIC_TYPE_X509);
1916
0
            InitX509(x509, 1, heap);
1917
0
            InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
1918
0
            if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL)
1919
0
                                                                         != 0) {
1920
0
                WOLFSSL_MSG("Issue with parsing certificate");
1921
0
                FreeDecodedCert(DeCert);
1922
0
                wolfSSL_X509_free(x509);
1923
0
                x509 = NULL;
1924
0
            }
1925
0
            else {
1926
0
                if (CopyDecodedToX509(x509, DeCert) != 0) {
1927
0
                    WOLFSSL_MSG("Failed to copy decoded cert");
1928
0
                    FreeDecodedCert(DeCert);
1929
0
                    wolfSSL_X509_free(x509);
1930
0
                    x509 = NULL;
1931
0
                    wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
1932
0
                    XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
1933
0
                    XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
1934
                    /* Free up WC_DerCertList */
1935
0
                    while (current != NULL) {
1936
0
                        WC_DerCertList* next = current->next;
1937
1938
0
                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
1939
0
                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
1940
0
                        current = next;
1941
0
                    }
1942
0
                    ret = WOLFSSL_FAILURE;
1943
0
                    goto out;
1944
0
                }
1945
0
                FreeDecodedCert(DeCert);
1946
1947
0
                if (wolfSSL_sk_X509_push(*ca, x509) <= 0) {
1948
0
                    WOLFSSL_MSG("Failed to push x509 onto stack");
1949
0
                    wolfSSL_X509_free(x509);
1950
0
                    x509 = NULL;
1951
0
                    wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
1952
0
                    XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
1953
0
                    XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
1954
1955
                    /* Free up WC_DerCertList */
1956
0
                    while (current != NULL) {
1957
0
                        WC_DerCertList* next = current->next;
1958
1959
0
                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
1960
0
                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
1961
0
                        current = next;
1962
0
                    }
1963
0
                    ret = WOLFSSL_FAILURE;
1964
0
                    goto out;
1965
0
                }
1966
0
            }
1967
0
            current = current->next;
1968
0
            XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
1969
0
            XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
1970
0
        }
1971
0
    }
1972
1973
1974
    /* Decode cert and place in X509 struct */
1975
0
    if (certData != NULL) {
1976
0
        *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
1977
0
            DYNAMIC_TYPE_X509);
1978
0
        if (*cert == NULL) {
1979
0
            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
1980
0
            if (ca != NULL) {
1981
0
                wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
1982
0
            }
1983
0
            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
1984
0
            ret = WOLFSSL_FAILURE;
1985
0
            goto out;
1986
0
        }
1987
0
        InitX509(*cert, 1, heap);
1988
0
        InitDecodedCert(DeCert, certData, certDataSz, heap);
1989
0
        if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) {
1990
0
            WOLFSSL_MSG("Issue with parsing certificate");
1991
0
        }
1992
0
        if (CopyDecodedToX509(*cert, DeCert) != 0) {
1993
0
            WOLFSSL_MSG("Failed to copy decoded cert");
1994
0
            FreeDecodedCert(DeCert);
1995
0
            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
1996
0
            if (ca != NULL) {
1997
0
                wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
1998
0
            }
1999
0
            wolfSSL_X509_free(*cert); *cert = NULL;
2000
0
            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
2001
0
            ret = WOLFSSL_FAILURE;
2002
0
            goto out;
2003
0
        }
2004
0
        FreeDecodedCert(DeCert);
2005
0
        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
2006
0
    }
2007
2008
2009
    /* get key type */
2010
0
    ret = BAD_STATE_E;
2011
0
    if (pk != NULL) { /* decode key if present */
2012
0
        *pkey = wolfSSL_EVP_PKEY_new_ex(heap);
2013
0
        if (*pkey == NULL) {
2014
0
            wolfSSL_X509_free(*cert); *cert = NULL;
2015
0
            if (ca != NULL) {
2016
0
                wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
2017
0
            }
2018
0
            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
2019
0
            ret = WOLFSSL_FAILURE;
2020
0
            goto out;
2021
0
        }
2022
2023
0
    #ifndef NO_RSA
2024
0
        {
2025
0
            const unsigned char* pt = pk;
2026
0
            if (wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_RSA, pkey, &pt, pkSz) !=
2027
0
                    NULL) {
2028
0
                ret = 0;
2029
0
            }
2030
0
        }
2031
0
    #endif /* NO_RSA */
2032
2033
0
    #ifdef HAVE_ECC
2034
0
        if (ret != 0) { /* if is in fail state check if ECC key */
2035
0
            const unsigned char* pt = pk;
2036
0
            if (wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_EC, pkey, &pt, pkSz) !=
2037
0
                    NULL) {
2038
0
                ret = 0;
2039
0
            }
2040
0
        }
2041
0
    #endif /* HAVE_ECC */
2042
0
        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
2043
0
        if (ret != 0) { /* if is in fail state and no PKEY then fail */
2044
0
            wolfSSL_X509_free(*cert); *cert = NULL;
2045
0
            if (ca != NULL) {
2046
0
                wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
2047
0
            }
2048
0
            wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
2049
0
            WOLFSSL_MSG("Bad PKCS12 key format");
2050
0
            ret = WOLFSSL_FAILURE;
2051
0
            goto out;
2052
0
        }
2053
2054
0
        if (pkey != NULL && *pkey != NULL) {
2055
0
            (*pkey)->save_type = 0;
2056
0
        }
2057
0
    }
2058
2059
0
    (void)ret;
2060
0
    (void)ca;
2061
2062
0
    ret = WOLFSSL_SUCCESS;
2063
2064
0
out:
2065
2066
0
    WC_FREE_VAR_EX(DeCert, heap, DYNAMIC_TYPE_DCERT);
2067
2068
0
    return ret;
2069
0
}
2070
2071
int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw,
2072
        int pswLen)
2073
0
{
2074
0
    WOLFSSL_ENTER("wolfSSL_PKCS12_verify_mac");
2075
2076
0
    if (!pkcs12) {
2077
0
        return WOLFSSL_FAILURE;
2078
0
    }
2079
2080
0
    return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, (word32)pswLen) == 0 ?
2081
0
            WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
2082
0
}
2083
2084
#endif /* !NO_ASN && !NO_PWDBASED */
2085
2086
#endif /* OPENSSL_EXTRA */
2087
2088
#endif /* HAVE_PKCS12 */
2089
/*******************************************************************************
2090
 * END OF PKCS12 APIs
2091
 ******************************************************************************/
2092
2093
#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
2094
2095
#endif /* !WOLFSSL_SSL_P7P12_INCLUDED */