/src/nss/fuzz/targets/pkcs12.cc
Line | Count | Source |
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 <algorithm> |
6 | | #include <cassert> |
7 | | #include <cstddef> |
8 | | #include <cstdint> |
9 | | #include <cstdio> |
10 | | |
11 | | #include "nss_scoped_ptrs.h" |
12 | | #include "p12.h" |
13 | | #include "pk11pub.h" |
14 | | #include "seccomon.h" |
15 | | |
16 | | #include "asn1/mutators.h" |
17 | | #include "base/database.h" |
18 | | |
19 | | static SECItem* nicknameCollision(SECItem* oldNick, PRBool* cancel, |
20 | 0 | void* wincx) { |
21 | 0 | static unsigned int counter = 0; |
22 | | |
23 | | // Always return a unique nickname. |
24 | 0 | SECItem* item = SECITEM_AllocItem(nullptr, nullptr, 12); |
25 | 0 | item->len = snprintf((char*)item->data, 12, "%u", counter++) + 1; |
26 | |
|
27 | 0 | return item; |
28 | 0 | } |
29 | | |
30 | 12.6k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
31 | 12.6k | static NSSDatabase db = NSSDatabase(); |
32 | | |
33 | 12.6k | ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
34 | 12.6k | assert(slot); |
35 | | |
36 | | // Initialize the decoder. |
37 | 12.6k | SECItem pwItem = {siBuffer, nullptr, 0}; |
38 | 12.6k | ScopedSEC_PKCS12DecoderContext dcx( |
39 | 12.6k | SEC_PKCS12DecoderStart(&pwItem, slot.get(), nullptr, nullptr, nullptr, |
40 | 12.6k | nullptr, nullptr, nullptr)); |
41 | 12.6k | assert(dcx); |
42 | | |
43 | | // Cap the max element length at 1 MB to avoid OOMs during fuzzing. |
44 | 12.6k | SEC_PKCS12DecoderSetMaxElementLen(dcx.get(), |
45 | 12.6k | std::max(1024 * 1024, (int)size)); |
46 | | |
47 | | // Cycle through target token CA modes. |
48 | 12.6k | SECPKCS12TargetTokenCAs modes[] = {SECPKCS12TargetTokenNoCAs, |
49 | 12.6k | SECPKCS12TargetTokenIntermediateCAs, |
50 | 12.6k | SECPKCS12TargetTokenAllCAs}; |
51 | 12.6k | SEC_PKCS12DecoderSetTargetTokenCAs(dcx.get(), modes[size % 3]); |
52 | | |
53 | 12.6k | SECStatus rv = SEC_PKCS12DecoderUpdate(dcx.get(), (unsigned char*)data, size); |
54 | 12.6k | if (rv != SECSuccess) { |
55 | 1.39k | return 0; |
56 | 1.39k | } |
57 | | |
58 | | // Verify the blob. |
59 | 11.2k | rv = SEC_PKCS12DecoderVerify(dcx.get()); |
60 | 11.2k | if (rv != SECSuccess) { |
61 | 11.1k | return 0; |
62 | 11.1k | } |
63 | | |
64 | | // Validate bags. |
65 | 152 | rv = SEC_PKCS12DecoderValidateBags(dcx.get(), nicknameCollision); |
66 | 152 | if (rv != SECSuccess) { |
67 | 133 | return 0; |
68 | 133 | } |
69 | | |
70 | | // Import cert and key. |
71 | 19 | rv = SEC_PKCS12DecoderImportBags(dcx.get()); |
72 | 19 | if (rv != SECSuccess) { |
73 | 0 | return 0; |
74 | 0 | } |
75 | | |
76 | 19 | return 0; |
77 | 19 | } |
78 | | |
79 | | extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, |
80 | 0 | size_t maxSize, unsigned int seed) { |
81 | 0 | return ASN1Mutators::CustomMutator(data, size, maxSize, seed); |
82 | 0 | } |
83 | | |
84 | | extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1, |
85 | | const uint8_t* data2, size_t size2, |
86 | | uint8_t* out, size_t maxOutSize, |
87 | 0 | unsigned int seed) { |
88 | 0 | return ASN1Mutators::CustomCrossOver(data1, size1, data2, size2, out, |
89 | 0 | maxOutSize, seed); |
90 | 0 | } |