Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/pkcs12/p12dec.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "pkcs12.h"
6
#include "plarena.h"
7
#include "secpkcs7.h"
8
#include "p12local.h"
9
#include "secoid.h"
10
#include "secitem.h"
11
#include "secport.h"
12
#include "secasn1.h"
13
#include "secder.h"
14
#include "secerr.h"
15
#include "cert.h"
16
#include "certdb.h"
17
#include "p12plcy.h"
18
#include "p12.h"
19
#include "secpkcs5.h"
20
21
/* PFX extraction and validation routines */
22
23
/* decode the DER encoded PFX item.  if unable to decode, check to see if it
24
 * is an older PFX item.  If that fails, assume the file was not a valid
25
 * pfx file.
26
 * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX
27
 */
28
static SEC_PKCS12PFXItem *
29
sec_pkcs12_decode_pfx(SECItem *der_pfx)
30
0
{
31
0
    SEC_PKCS12PFXItem *pfx;
32
0
    SECStatus rv;
33
0
34
0
    if (der_pfx == NULL) {
35
0
        return NULL;
36
0
    }
37
0
38
0
    /* allocate the space for a new PFX item */
39
0
    pfx = sec_pkcs12_new_pfx();
40
0
    if (pfx == NULL) {
41
0
        return NULL;
42
0
    }
43
0
44
0
    rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate,
45
0
                            der_pfx);
46
0
47
0
    /* if a failure occurred, check for older version...
48
0
     * we also get rid of the old pfx structure, because we don't
49
0
     * know where it failed and what data in may contain
50
0
     */
51
0
    if (rv != SECSuccess) {
52
0
        SEC_PKCS12DestroyPFX(pfx);
53
0
        pfx = sec_pkcs12_new_pfx();
54
0
        if (pfx == NULL) {
55
0
            return NULL;
56
0
        }
57
0
        rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD,
58
0
                                der_pfx);
59
0
        if (rv != SECSuccess) {
60
0
            PORT_SetError(SEC_ERROR_PKCS12_DECODING_PFX);
61
0
            PORT_FreeArena(pfx->poolp, PR_TRUE);
62
0
            return NULL;
63
0
        }
64
0
        pfx->old = PR_TRUE;
65
0
        rv = SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac);
66
0
        if (rv != SECSuccess) {
67
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
68
0
            PORT_FreeArena(pfx->poolp, PR_TRUE);
69
0
            return NULL;
70
0
        }
71
0
        rv = SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt);
72
0
        if (rv != SECSuccess) {
73
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
74
0
            PORT_FreeArena(pfx->poolp, PR_TRUE);
75
0
            return NULL;
76
0
        }
77
0
    } else {
78
0
        pfx->old = PR_FALSE;
79
0
    }
80
0
81
0
    /* convert bit string from bits to bytes */
82
0
    pfx->macData.macSalt.len /= 8;
83
0
84
0
    return pfx;
85
0
}
86
87
/* validate the integrity MAC used in the PFX.  The MAC is generated
88
 * per the PKCS 12 document.  If the MAC is incorrect, it is most likely
89
 * due to an invalid password.
90
 * pwitem is the integrity password
91
 * pfx is the decoded pfx item
92
 */
93
static PRBool
94
sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx,
95
                         SECItem *pwitem)
96
0
{
97
0
    SECItem *key = NULL, *mac = NULL, *data = NULL;
98
0
    SECItem *vpwd = NULL;
99
0
    SECOidTag algorithm;
100
0
    PRBool ret = PR_FALSE;
101
0
102
0
    if (pfx == NULL) {
103
0
        return PR_FALSE;
104
0
    }
105
0
106
0
    algorithm = SECOID_GetAlgorithmTag(&pfx->macData.safeMac.digestAlgorithm);
107
0
    switch (algorithm) {
108
0
        /* only SHA1 hashing supported as a MACing algorithm */
109
0
        case SEC_OID_SHA1:
110
0
            if (pfx->old == PR_FALSE) {
111
0
                pfx->swapUnicode = PR_FALSE;
112
0
            }
113
0
114
0
        recheckUnicodePassword:
115
0
            vpwd = sec_pkcs12_create_virtual_password(pwitem,
116
0
                                                      &pfx->macData.macSalt,
117
0
                                                      pfx->swapUnicode);
118
0
            if (vpwd == NULL) {
119
0
                return PR_FALSE;
120
0
            }
121
0
122
0
            key = sec_pkcs12_generate_key_from_password(algorithm,
123
0
                                                        &pfx->macData.macSalt,
124
0
                                                        (pfx->old ? pwitem : vpwd));
125
0
            /* free vpwd only for newer PFX */
126
0
            if (vpwd) {
127
0
                SECITEM_ZfreeItem(vpwd, PR_TRUE);
128
0
            }
129
0
            if (key == NULL) {
130
0
                return PR_FALSE;
131
0
            }
132
0
133
0
            data = SEC_PKCS7GetContent(&pfx->authSafe);
134
0
            if (data == NULL) {
135
0
                break;
136
0
            }
137
0
138
0
            /* check MAC */
139
0
            mac = sec_pkcs12_generate_mac(key, data, pfx->old);
140
0
            ret = PR_TRUE;
141
0
            if (mac) {
142
0
                SECItem *safeMac = &pfx->macData.safeMac.digest;
143
0
                if (SECITEM_CompareItem(mac, safeMac) != SECEqual) {
144
0
145
0
                    /* if we encounter an invalid mac, lets invert the
146
0
                     * password in case of unicode changes
147
0
                     */
148
0
                    if (((!pfx->old) && pfx->swapUnicode) || (pfx->old)) {
149
0
                        PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
150
0
                        ret = PR_FALSE;
151
0
                    } else {
152
0
                        SECITEM_ZfreeItem(mac, PR_TRUE);
153
0
                        pfx->swapUnicode = PR_TRUE;
154
0
                        goto recheckUnicodePassword;
155
0
                    }
156
0
                }
157
0
                SECITEM_ZfreeItem(mac, PR_TRUE);
158
0
            } else {
159
0
                ret = PR_FALSE;
160
0
            }
161
0
            break;
162
0
        default:
163
0
            PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM);
164
0
            ret = PR_FALSE;
165
0
            break;
166
0
    }
167
0
168
0
    /* let success fall through */
169
0
    if (key != NULL)
170
0
        SECITEM_ZfreeItem(key, PR_TRUE);
171
0
172
0
    return ret;
173
0
}
174
175
/* check the validity of the pfx structure.  we currently only support
176
 * password integrity mode, so we check the MAC.
177
 */
178
static PRBool
179
sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx,
180
                        SECItem *pwitem)
181
0
{
182
0
    SECOidTag contentType;
183
0
184
0
    contentType = SEC_PKCS7ContentType(&pfx->authSafe);
185
0
    switch (contentType) {
186
0
        case SEC_OID_PKCS7_DATA:
187
0
            return sec_pkcs12_check_pfx_mac(pfx, pwitem);
188
0
            break;
189
0
        case SEC_OID_PKCS7_SIGNED_DATA:
190
0
        default:
191
0
            PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
192
0
            break;
193
0
    }
194
0
195
0
    return PR_FALSE;
196
0
}
197
198
/* decode and return the valid PFX.  if the PFX item is not valid,
199
 * NULL is returned.
200
 */
201
static SEC_PKCS12PFXItem *
202
sec_pkcs12_get_pfx(SECItem *pfx_data,
203
                   SECItem *pwitem)
204
0
{
205
0
    SEC_PKCS12PFXItem *pfx;
206
0
    PRBool valid_pfx;
207
0
208
0
    if ((pfx_data == NULL) || (pwitem == NULL)) {
209
0
        return NULL;
210
0
    }
211
0
212
0
    pfx = sec_pkcs12_decode_pfx(pfx_data);
213
0
    if (pfx == NULL) {
214
0
        return NULL;
215
0
    }
216
0
217
0
    valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem);
218
0
    if (valid_pfx != PR_TRUE) {
219
0
        SEC_PKCS12DestroyPFX(pfx);
220
0
        pfx = NULL;
221
0
    }
222
0
223
0
    return pfx;
224
0
}
225
226
/* authenticated safe decoding, validation, and access routines
227
 */
228
229
/* convert dogbert beta 3 authenticated safe structure to a post
230
 * beta three structure, so that we don't have to change more routines.
231
 */
232
static SECStatus
233
sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
234
0
{
235
0
    SEC_PKCS12Baggage *baggage;
236
0
    SEC_PKCS12BaggageItem *bag;
237
0
    SECStatus rv = SECSuccess;
238
0
239
0
    if (asafe->old_baggage.espvks == NULL) {
240
0
        /* XXX should the ASN1 engine produce a single NULL element list
241
0
         * rather than setting the pointer to NULL?
242
0
         * There is no need to return an error -- assume that the list
243
0
         * was empty.
244
0
         */
245
0
        return SECSuccess;
246
0
    }
247
0
248
0
    baggage = sec_pkcs12_create_baggage(asafe->poolp);
249
0
    if (!baggage) {
250
0
        return SECFailure;
251
0
    }
252
0
    bag = sec_pkcs12_create_external_bag(baggage);
253
0
    if (!bag) {
254
0
        return SECFailure;
255
0
    }
256
0
257
0
    PORT_Memcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage));
258
0
259
0
    /* if there are shrouded keys, append them to the bag */
260
0
    rv = SECSuccess;
261
0
    if (asafe->old_baggage.espvks[0] != NULL) {
262
0
        int nEspvk = 0;
263
0
        rv = SECSuccess;
264
0
        while ((asafe->old_baggage.espvks[nEspvk] != NULL) &&
265
0
               (rv == SECSuccess)) {
266
0
            rv = sec_pkcs12_append_shrouded_key(bag,
267
0
                                                asafe->old_baggage.espvks[nEspvk]);
268
0
            nEspvk++;
269
0
        }
270
0
    }
271
0
272
0
    return rv;
273
0
}
274
275
/* decodes the authenticated safe item.  a return of NULL indicates
276
 * an error.  however, the error will have occurred either in memory
277
 * allocation or in decoding the authenticated safe.
278
 *
279
 * if an old PFX item has been found, we want to convert the
280
 * old authenticated safe to the new one.
281
 */
282
static SEC_PKCS12AuthenticatedSafe *
283
sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx)
284
0
{
285
0
    SECItem *der_asafe = NULL;
286
0
    SEC_PKCS12AuthenticatedSafe *asafe = NULL;
287
0
    SECStatus rv;
288
0
289
0
    if (pfx == NULL) {
290
0
        return NULL;
291
0
    }
292
0
293
0
    der_asafe = SEC_PKCS7GetContent(&pfx->authSafe);
294
0
    if (der_asafe == NULL) {
295
0
        /* XXX set error ? */
296
0
        goto loser;
297
0
    }
298
0
299
0
    asafe = sec_pkcs12_new_asafe(pfx->poolp);
300
0
    if (asafe == NULL) {
301
0
        goto loser;
302
0
    }
303
0
304
0
    if (pfx->old == PR_FALSE) {
305
0
        rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
306
0
                                SEC_PKCS12AuthenticatedSafeTemplate,
307
0
                                der_asafe);
308
0
        asafe->old = PR_FALSE;
309
0
        asafe->swapUnicode = pfx->swapUnicode;
310
0
    } else {
311
0
        /* handle beta exported files */
312
0
        rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
313
0
                                SEC_PKCS12AuthenticatedSafeTemplate_OLD,
314
0
                                der_asafe);
315
0
        asafe->safe = &(asafe->old_safe);
316
0
        rv = sec_pkcs12_convert_old_auth_safe(asafe);
317
0
        asafe->old = PR_TRUE;
318
0
    }
319
0
320
0
    if (rv != SECSuccess) {
321
0
        goto loser;
322
0
    }
323
0
324
0
    asafe->poolp = pfx->poolp;
325
0
326
0
    return asafe;
327
0
328
0
loser:
329
0
    return NULL;
330
0
}
331
332
/* validates the safe within the authenticated safe item.
333
 * in order to be valid:
334
 *  1.  the privacy salt must be present
335
 *  2.  the encryption algorithm must be supported (including
336
 *      export policy)
337
 * PR_FALSE indicates an error, PR_TRUE indicates a valid safe
338
 */
339
static PRBool
340
sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe)
341
0
{
342
0
    PRBool valid = PR_FALSE;
343
0
    SECAlgorithmID *algid;
344
0
345
0
    if (asafe == NULL) {
346
0
        return PR_FALSE;
347
0
    }
348
0
349
0
    /* if mode is password privacy, then privacySalt is assumed
350
0
     * to be non-zero.
351
0
     */
352
0
    if (asafe->privacySalt.len != 0) {
353
0
        valid = PR_TRUE;
354
0
        asafe->privacySalt.len /= 8;
355
0
    } else {
356
0
        PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
357
0
        return PR_FALSE;
358
0
    }
359
0
360
0
    /* until spec changes, content will have between 2 and 8 bytes depending
361
0
     * upon the algorithm used if certs are unencrypted...
362
0
     * also want to support case where content is empty -- which we produce
363
0
     */
364
0
    if (SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE) {
365
0
        asafe->emptySafe = PR_TRUE;
366
0
        return PR_TRUE;
367
0
    }
368
0
369
0
    asafe->emptySafe = PR_FALSE;
370
0
371
0
    /* make sure that a pbe algorithm is being used */
372
0
    algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe);
373
0
    if (algid != NULL) {
374
0
        if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
375
0
            valid = SEC_PKCS12DecryptionAllowed(algid);
376
0
377
0
            if (valid == PR_FALSE) {
378
0
                PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
379
0
            }
380
0
        } else {
381
0
            PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
382
0
            valid = PR_FALSE;
383
0
        }
384
0
    } else {
385
0
        valid = PR_FALSE;
386
0
        PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
387
0
    }
388
0
389
0
    return valid;
390
0
}
391
392
/* validates authenticates safe:
393
 *  1.  checks that the version is supported
394
 *  2.  checks that only password privacy mode is used (currently)
395
 *  3.  further, makes sure safe has appropriate policies per above function
396
 * PR_FALSE indicates failure.
397
 */
398
static PRBool
399
sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
400
0
{
401
0
    PRBool valid = PR_TRUE;
402
0
    SECOidTag safe_type;
403
0
    int version;
404
0
405
0
    if (asafe == NULL) {
406
0
        return PR_FALSE;
407
0
    }
408
0
409
0
    /* check version, since it is default it may not be present.
410
0
     * therefore, assume ok
411
0
     */
412
0
    if ((asafe->version.len > 0) && (asafe->old == PR_FALSE)) {
413
0
        version = DER_GetInteger(&asafe->version);
414
0
        if (version > SEC_PKCS12_PFX_VERSION) {
415
0
            PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION);
416
0
            return PR_FALSE;
417
0
        }
418
0
    }
419
0
420
0
    /* validate password mode is being used */
421
0
    safe_type = SEC_PKCS7ContentType(asafe->safe);
422
0
    switch (safe_type) {
423
0
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
424
0
            valid = sec_pkcs12_validate_encrypted_safe(asafe);
425
0
            break;
426
0
        case SEC_OID_PKCS7_ENVELOPED_DATA:
427
0
        default:
428
0
            PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
429
0
            valid = PR_FALSE;
430
0
            break;
431
0
    }
432
0
433
0
    return valid;
434
0
}
435
436
/* retrieves the authenticated safe item from the PFX item
437
 *  before returning the authenticated safe, the validity of the
438
 *  authenticated safe is checked and if valid, returned.
439
 * a return of NULL indicates that an error occurred.
440
 */
441
static SEC_PKCS12AuthenticatedSafe *
442
sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx)
443
0
{
444
0
    SEC_PKCS12AuthenticatedSafe *asafe;
445
0
    PRBool valid_safe;
446
0
447
0
    if (pfx == NULL) {
448
0
        return NULL;
449
0
    }
450
0
451
0
    asafe = sec_pkcs12_decode_authenticated_safe(pfx);
452
0
    if (asafe == NULL) {
453
0
        return NULL;
454
0
    }
455
0
456
0
    valid_safe = sec_pkcs12_validate_auth_safe(asafe);
457
0
    if (valid_safe != PR_TRUE) {
458
0
        asafe = NULL;
459
0
    } else if (asafe) {
460
0
        asafe->baggage.poolp = asafe->poolp;
461
0
    }
462
0
463
0
    return asafe;
464
0
}
465
466
/* decrypts the authenticated safe.
467
 * a return of anything but SECSuccess indicates an error.  the
468
 * password is not known to be valid until the call to the
469
 * function sec_pkcs12_get_safe_contents.  If decoding the safe
470
 * fails, it is assumed the password was incorrect and the error
471
 * is set then.  any failure here is assumed to be due to
472
 * internal problems in SEC_PKCS7DecryptContents or below.
473
 */
474
static SECStatus
475
sec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe,
476
                             SECItem *pwitem,
477
                             void *wincx)
478
0
{
479
0
    SECStatus rv = SECFailure;
480
0
    SECItem *vpwd = NULL;
481
0
482
0
    if ((asafe == NULL) || (pwitem == NULL)) {
483
0
        return SECFailure;
484
0
    }
485
0
486
0
    if (asafe->old == PR_FALSE) {
487
0
        vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt,
488
0
                                                  asafe->swapUnicode);
489
0
        if (vpwd == NULL) {
490
0
            return SECFailure;
491
0
        }
492
0
    }
493
0
494
0
    rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe,
495
0
                                  (asafe->old ? pwitem : vpwd), wincx);
496
0
497
0
    if (asafe->old == PR_FALSE) {
498
0
        SECITEM_ZfreeItem(vpwd, PR_TRUE);
499
0
    }
500
0
501
0
    return rv;
502
0
}
503
504
/* extract the safe from the authenticated safe.
505
 *  if we are unable to decode the safe, then it is likely that the
506
 *  safe has not been decrypted or the password used to decrypt
507
 *  the safe was invalid.  we assume that the password was invalid and
508
 *  set an error accordingly.
509
 * a return of NULL indicates that an error occurred.
510
 */
511
static SEC_PKCS12SafeContents *
512
sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe)
513
0
{
514
0
    SECItem *src = NULL;
515
0
    SEC_PKCS12SafeContents *safe = NULL;
516
0
    SECStatus rv = SECFailure;
517
0
518
0
    if (asafe == NULL) {
519
0
        return NULL;
520
0
    }
521
0
522
0
    safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(asafe->poolp,
523
0
                                                      sizeof(SEC_PKCS12SafeContents));
524
0
    if (safe == NULL) {
525
0
        return NULL;
526
0
    }
527
0
    safe->poolp = asafe->poolp;
528
0
    safe->old = asafe->old;
529
0
    safe->swapUnicode = asafe->swapUnicode;
530
0
531
0
    src = SEC_PKCS7GetContent(asafe->safe);
532
0
    if (src != NULL) {
533
0
        const SEC_ASN1Template *theTemplate;
534
0
        if (asafe->old != PR_TRUE) {
535
0
            theTemplate = SEC_PKCS12SafeContentsTemplate;
536
0
        } else {
537
0
            theTemplate = SEC_PKCS12SafeContentsTemplate_OLD;
538
0
        }
539
0
540
0
        rv = SEC_ASN1DecodeItem(asafe->poolp, safe, theTemplate, src);
541
0
542
0
        /* if we could not decode the item, password was probably invalid */
543
0
        if (rv != SECSuccess) {
544
0
            safe = NULL;
545
0
            PORT_SetError(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT);
546
0
        }
547
0
    } else {
548
0
        PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
549
0
        rv = SECFailure;
550
0
    }
551
0
552
0
    return safe;
553
0
}
554
555
/* import PFX item
556
 * der_pfx is the der encoded pfx structure
557
 * pbef and pbearg are the integrity/encryption password call back
558
 * ncCall is the nickname collision calllback
559
 * slot is the destination token
560
 * wincx window handler
561
 *
562
 * on error, error code set and SECFailure returned
563
 */
564
SECStatus
565
SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem,
566
                 SEC_PKCS12NicknameCollisionCallback ncCall,
567
                 PK11SlotInfo *slot,
568
                 void *wincx)
569
0
{
570
0
    SEC_PKCS12PFXItem *pfx;
571
0
    SEC_PKCS12AuthenticatedSafe *asafe;
572
0
    SEC_PKCS12SafeContents *safe_contents = NULL;
573
0
    SECStatus rv;
574
0
575
0
    if (!der_pfx || !pwitem || !slot) {
576
0
        return SECFailure;
577
0
    }
578
0
579
0
    /* decode and validate each section */
580
0
    rv = SECFailure;
581
0
582
0
    pfx = sec_pkcs12_get_pfx(der_pfx, pwitem);
583
0
    if (pfx != NULL) {
584
0
        asafe = sec_pkcs12_get_auth_safe(pfx);
585
0
        if (asafe != NULL) {
586
0
587
0
            /* decrypt safe -- only if not empty */
588
0
            if (asafe->emptySafe != PR_TRUE) {
589
0
                rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx);
590
0
                if (rv == SECSuccess) {
591
0
                    safe_contents = sec_pkcs12_get_safe_contents(asafe);
592
0
                    if (safe_contents == NULL) {
593
0
                        rv = SECFailure;
594
0
                    }
595
0
                }
596
0
            } else {
597
0
                safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp);
598
0
                if (safe_contents == NULL) {
599
0
                    rv = SECFailure;
600
0
                } else {
601
0
                    safe_contents->swapUnicode = pfx->swapUnicode;
602
0
                    rv = SECSuccess;
603
0
                }
604
0
            }
605
0
606
0
            /* get safe contents and begin import */
607
0
            if (rv == SECSuccess) {
608
0
                SEC_PKCS12DecoderContext *p12dcx;
609
0
610
0
                p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot,
611
0
                                                       pfx->swapUnicode,
612
0
                                                       pwitem, wincx, safe_contents,
613
0
                                                       &asafe->baggage);
614
0
                if (!p12dcx) {
615
0
                    rv = SECFailure;
616
0
                    goto loser;
617
0
                }
618
0
619
0
                if (SEC_PKCS12DecoderValidateBags(p12dcx, ncCall) != SECSuccess) {
620
0
                    rv = SECFailure;
621
0
                    goto loser;
622
0
                }
623
0
624
0
                rv = SEC_PKCS12DecoderImportBags(p12dcx);
625
0
            }
626
0
        }
627
0
    }
628
0
629
0
loser:
630
0
631
0
    if (pfx) {
632
0
        SEC_PKCS12DestroyPFX(pfx);
633
0
    }
634
0
635
0
    return rv;
636
0
}
637
638
PRBool
639
SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength)
640
0
{
641
0
    int lengthLength;
642
0
643
0
    PRBool valid = PR_FALSE;
644
0
645
0
    if (buf == NULL) {
646
0
        return PR_FALSE;
647
0
    }
648
0
649
0
    /* check for constructed sequence identifier tag */
650
0
    if (*buf == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) {
651
0
        totalLength--; /* header byte taken care of */
652
0
        buf++;
653
0
654
0
        lengthLength = (long int)SEC_ASN1LengthLength(totalLength - 1);
655
0
        if (totalLength > 0x7f) {
656
0
            lengthLength--;
657
0
            *buf &= 0x7f; /* remove bit 8 indicator */
658
0
            if ((*buf - (char)lengthLength) == 0) {
659
0
                valid = PR_TRUE;
660
0
            }
661
0
        } else {
662
0
            lengthLength--;
663
0
            if ((*buf - (char)lengthLength) == 0) {
664
0
                valid = PR_TRUE;
665
0
            }
666
0
        }
667
0
    }
668
0
669
0
    return valid;
670
0
}