Bug Summary

File:s/cmd/dbtool/dbtool.c
Warning:line 808, column 9
Array access (from variable 'dbDir') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dbtool.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/dbtool -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/dbtool -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D NSS_USE_STATIC_LIBS -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c dbtool.c
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/*
6** dbtool.c
7**
8** tool to dump the underlying encoding of a database. This tool duplicates
9** some private functions in softoken. It uses libsec and libutil, but no
10** other portions of NSS. It currently only works on sqlite databases. For
11** an even more primitive dump, use sqlite3 on the individual files.
12**
13** TODO: dump the meta data for the databases.
14** optionally dump more PKCS5 information (KDF/salt/iterations)
15** take a password and decode encrypted attributes/verify signed
16** attributes.
17*/
18#include <stdio.h>
19#include <string.h>
20
21#if defined(WIN32)
22#include "fcntl.h"
23#include "io.h"
24#endif
25
26/*#include "secutil.h" */
27/*#include "pk11pub.h" */
28
29#if defined(XP_UNIX1)
30#include <unistd.h>
31#endif
32
33#include "nspr.h"
34#include "prtypes.h"
35#include "nss.h"
36#include "secasn1.h"
37#include "secder.h"
38#include "pk11table.h"
39#include "sftkdbt.h"
40#include "sdb.h"
41#include "secoid.h"
42
43#include "plgetopt.h"
44
45static char *progName;
46
47char *dbDir = NULL((void*)0);
48
49static void
50Usage()
51{
52 printf("Usage: %s [-c certprefix] [-k keyprefix] "
53 "[-V certversion] [-v keyversion]\n"
54 " [-d dbdir]\n",
55 progName);
56 printf("%-20s Directory with cert database (default is .)\n",
57 "-d certdir");
58 printf("%-20s prefix for the cert database (default is \"\")\n",
59 "-c certprefix");
60 printf("%-20s prefix for the key database (default is \"\")\n",
61 "-k keyprefix");
62 printf("%-20s version of the cert database (default is 9)\n",
63 "-V certversion");
64 printf("%-20s version of the key database (default is 4)\n",
65 "-v keyversion");
66 exit(1);
67}
68#define SFTK_KEYDB_TYPE0x40000000 0x40000000
69#define SFTK_TOKEN_TYPE0x80000000 0x80000000
70
71/*
72 * known attributes
73 */
74static const CK_ATTRIBUTE_TYPE known_attributes[] = {
75 CKA_CLASS0x00000000UL, CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_LABEL0x00000003UL, CKA_APPLICATION0x00000010UL,
76 CKA_VALUE0x00000011UL, CKA_OBJECT_ID0x00000012UL, CKA_CERTIFICATE_TYPE0x00000080UL, CKA_ISSUER0x00000081UL,
77 CKA_SERIAL_NUMBER0x00000082UL, CKA_AC_ISSUER0x00000083UL, CKA_OWNER0x00000084UL, CKA_ATTR_TYPES0x00000085UL, CKA_TRUSTED0x00000086UL,
78 CKA_CERTIFICATE_CATEGORY0x00000087UL, CKA_JAVA_MIDP_SECURITY_DOMAIN0x00000088UL, CKA_URL0x00000089UL,
79 CKA_HASH_OF_SUBJECT_PUBLIC_KEY0x0000008AUL, CKA_HASH_OF_ISSUER_PUBLIC_KEY0x0000008BUL,
80 CKA_CHECK_VALUE0x00000090UL, CKA_KEY_TYPE0x00000100UL, CKA_SUBJECT0x00000101UL, CKA_ID0x00000102UL, CKA_SENSITIVE0x00000103UL,
81 CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL, CKA_SIGN0x00000108UL, CKA_SIGN_RECOVER0x00000109UL,
82 CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, CKA_DERIVE0x0000010CUL, CKA_START_DATE0x00000110UL, CKA_END_DATE0x00000111UL,
83 CKA_MODULUS0x00000120UL, CKA_MODULUS_BITS0x00000121UL, CKA_PUBLIC_EXPONENT0x00000122UL, CKA_PRIVATE_EXPONENT0x00000123UL,
84 CKA_PRIME_10x00000124UL, CKA_PRIME_20x00000125UL, CKA_EXPONENT_10x00000126UL, CKA_EXPONENT_20x00000127UL, CKA_COEFFICIENT0x00000128UL,
85 CKA_PRIME0x00000130UL, CKA_SUBPRIME0x00000131UL, CKA_BASE0x00000132UL, CKA_PRIME_BITS0x00000133UL,
86 CKA_SUB_PRIME_BITS0x00000134UL, CKA_VALUE_BITS0x00000160UL, CKA_VALUE_LEN0x00000161UL, CKA_EXTRACTABLE0x00000162UL,
87 CKA_LOCAL0x00000163UL, CKA_NEVER_EXTRACTABLE0x00000164UL, CKA_ALWAYS_SENSITIVE0x00000165UL,
88 CKA_KEY_GEN_MECHANISM0x00000166UL, CKA_MODIFIABLE0x00000170UL, CKA_EC_PARAMS0x00000180UL,
89 CKA_EC_POINT0x00000181UL, CKA_SECONDARY_AUTH0x00000200UL, CKA_AUTH_PIN_FLAGS0x00000201UL,
90 CKA_ALWAYS_AUTHENTICATE0x00000202UL, CKA_WRAP_WITH_TRUSTED0x00000210UL, CKA_WRAP_TEMPLATE(0x40000000UL | 0x00000211UL),
91 CKA_UNWRAP_TEMPLATE(0x40000000UL | 0x00000212UL), CKA_HW_FEATURE_TYPE0x00000300UL, CKA_RESET_ON_INIT0x00000301UL,
92 CKA_HAS_RESET0x00000302UL, CKA_PIXEL_X0x00000400UL, CKA_PIXEL_Y0x00000401UL, CKA_RESOLUTION0x00000402UL, CKA_CHAR_ROWS0x00000403UL,
93 CKA_CHAR_COLUMNS0x00000404UL, CKA_COLOR0x00000405UL, CKA_BITS_PER_PIXEL0x00000406UL, CKA_CHAR_SETS0x00000480UL,
94 CKA_ENCODING_METHODS0x00000481UL, CKA_MIME_TYPES0x00000482UL, CKA_MECHANISM_TYPE0x00000500UL,
95 CKA_REQUIRED_CMS_ATTRIBUTES0x00000501UL, CKA_DEFAULT_CMS_ATTRIBUTES0x00000502UL,
96 CKA_SUPPORTED_CMS_ATTRIBUTES0x00000503UL, CKA_NSS_URL((0x80000000UL | 0x4E534350) + 1), CKA_NSS_EMAIL((0x80000000UL | 0x4E534350) + 2),
97 CKA_NSS_SMIME_INFO((0x80000000UL | 0x4E534350) + 3), CKA_NSS_SMIME_TIMESTAMP((0x80000000UL | 0x4E534350) + 4),
98 CKA_NSS_PKCS8_SALT((0x80000000UL | 0x4E534350) + 5), CKA_NSS_PASSWORD_CHECK((0x80000000UL | 0x4E534350) + 6), CKA_NSS_EXPIRES((0x80000000UL | 0x4E534350) + 7),
99 CKA_NSS_KRL((0x80000000UL | 0x4E534350) + 8), CKA_NSS_PQG_COUNTER((0x80000000UL | 0x4E534350) + 20), CKA_NSS_PQG_SEED((0x80000000UL | 0x4E534350) + 21),
100 CKA_NSS_PQG_H((0x80000000UL | 0x4E534350) + 22), CKA_NSS_PQG_SEED_BITS((0x80000000UL | 0x4E534350) + 23), CKA_NSS_MODULE_SPEC((0x80000000UL | 0x4E534350) + 24),
101 CKA_TRUST_DIGITAL_SIGNATURE(((0x80000000UL | 0x4E534350) + 0x2000) + 1), CKA_TRUST_NON_REPUDIATION(((0x80000000UL | 0x4E534350) + 0x2000) + 2),
102 CKA_TRUST_KEY_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 3), CKA_TRUST_DATA_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 4),
103 CKA_TRUST_KEY_AGREEMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 5), CKA_TRUST_KEY_CERT_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 6), CKA_TRUST_CRL_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 7),
104 CKA_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8), CKA_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9), CKA_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10),
105 CKA_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11), CKA_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12),
106 CKA_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13), CKA_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14), CKA_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15),
107 CKA_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16), CKA_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100), CKA_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101),
108 CKA_NSS_DB0xD5A0DB00L, CKA_NSS_TRUST0x80000001L, CKA_NSS_OVERRIDE_EXTENSIONS((0x80000000UL | 0x4E534350) + 25),
109 CKA_PUBLIC_KEY_INFO0x00000129UL
110};
111
112static unsigned int known_attributes_size = sizeof(known_attributes) /
113 sizeof(known_attributes[0]);
114
115PRBool
116isULONGAttribute(CK_ATTRIBUTE_TYPE type)
117{
118 switch (type) {
119 case CKA_CERTIFICATE_CATEGORY0x00000087UL:
120 case CKA_CERTIFICATE_TYPE0x00000080UL:
121 case CKA_CLASS0x00000000UL:
122 case CKA_JAVA_MIDP_SECURITY_DOMAIN0x00000088UL:
123 case CKA_KEY_GEN_MECHANISM0x00000166UL:
124 case CKA_KEY_TYPE0x00000100UL:
125 case CKA_MECHANISM_TYPE0x00000500UL:
126 case CKA_MODULUS_BITS0x00000121UL:
127 case CKA_PRIME_BITS0x00000133UL:
128 case CKA_SUBPRIME_BITS0x00000134UL:
129 case CKA_VALUE_BITS0x00000160UL:
130 case CKA_VALUE_LEN0x00000161UL:
131
132 case CKA_TRUST_DIGITAL_SIGNATURE(((0x80000000UL | 0x4E534350) + 0x2000) + 1):
133 case CKA_TRUST_NON_REPUDIATION(((0x80000000UL | 0x4E534350) + 0x2000) + 2):
134 case CKA_TRUST_KEY_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 3):
135 case CKA_TRUST_DATA_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 4):
136 case CKA_TRUST_KEY_AGREEMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 5):
137 case CKA_TRUST_KEY_CERT_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 6):
138 case CKA_TRUST_CRL_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 7):
139
140 case CKA_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
141 case CKA_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
142 case CKA_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
143 case CKA_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
144 case CKA_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12):
145 case CKA_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13):
146 case CKA_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14):
147 case CKA_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15):
148 case CKA_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16):
149 return PR_TRUE1;
150 default:
151 break;
152 }
153 return PR_FALSE0;
154}
155
156/* are the attributes private? */
157static PRBool
158isPrivateAttribute(CK_ATTRIBUTE_TYPE type)
159{
160 switch (type) {
161 case CKA_VALUE0x00000011UL:
162 case CKA_PRIVATE_EXPONENT0x00000123UL:
163 case CKA_PRIME_10x00000124UL:
164 case CKA_PRIME_20x00000125UL:
165 case CKA_EXPONENT_10x00000126UL:
166 case CKA_EXPONENT_20x00000127UL:
167 case CKA_COEFFICIENT0x00000128UL:
168 return PR_TRUE1;
169 default:
170 break;
171 }
172 return PR_FALSE0;
173}
174
175/* These attributes must be authenticated with an hmac. */
176static PRBool
177isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type)
178{
179 switch (type) {
180 case CKA_MODULUS0x00000120UL:
181 case CKA_PUBLIC_EXPONENT0x00000122UL:
182 case CKA_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100):
183 case CKA_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101):
184 case CKA_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
185 case CKA_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
186 case CKA_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
187 case CKA_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
188 case CKA_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16):
189 case CKA_NSS_OVERRIDE_EXTENSIONS((0x80000000UL | 0x4E534350) + 25):
190 return PR_TRUE1;
191 default:
192 break;
193 }
194 return PR_FALSE0;
195}
196
197/*
198 * convert a database ulong back to a native ULONG. (reverse of the above
199 * function.
200 */
201static CK_ULONG
202sdbULong2ULong(unsigned char *data)
203{
204 int i;
205 CK_ULONG value = 0;
206
207 for (i = 0; i < SDB_ULONG_SIZE4; i++) {
208 value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE4 - 1 - i) * PR_BITS_PER_BYTE8);
209 }
210 return value;
211}
212
213/* PBE defines and functions */
214SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
215
216typedef struct EncryptedDataInfoStr {
217 SECAlgorithmID algorithm;
218 SECItem encryptedData;
219} EncryptedDataInfo;
220
221static const SEC_ASN1Template encryptedDataInfoTemplate[] = {
222 { SEC_ASN1_SEQUENCE0x10,
223 0, NULL((void*)0), sizeof(EncryptedDataInfo) },
224 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
225 offsetof(EncryptedDataInfo, algorithm)__builtin_offsetof(EncryptedDataInfo, algorithm),
226 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
227 { SEC_ASN1_OCTET_STRING0x04,
228 offsetof(EncryptedDataInfo, encryptedData)__builtin_offsetof(EncryptedDataInfo, encryptedData) },
229 { 0 }
230};
231
232typedef struct PBEParameterStr {
233 SECAlgorithmID prfAlg;
234 SECItem salt;
235 SECItem iteration;
236 SECItem keyLength;
237} PBEParameter;
238
239static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = {
240 { SEC_ASN1_SEQUENCE0x10,
241 0, NULL((void*)0), sizeof(PBEParameter) },
242 { SEC_ASN1_OCTET_STRING0x04,
243 offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
244 { SEC_ASN1_INTEGER0x02,
245 offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
246 { 0 }
247};
248
249static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = {
250 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(PBEParameter) },
251 { SEC_ASN1_OCTET_STRING0x04, offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
252 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
253 { 0 }
254};
255
256static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = {
257 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(PBEParameter) },
258 /* this is really a choice, but since we don't understand any other
259 * choice, just inline it. */
260 { SEC_ASN1_OCTET_STRING0x04, offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
261 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
262 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, keyLength)__builtin_offsetof(PBEParameter, keyLength) },
263 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
264 offsetof(PBEParameter, prfAlg)__builtin_offsetof(PBEParameter, prfAlg),
265 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
266 { 0 }
267};
268
269typedef struct Pkcs5v2PBEParameterStr {
270 SECAlgorithmID keyParams; /* parameters of the key generation */
271 SECAlgorithmID algParams; /* parameters for the encryption or mac op */
272} Pkcs5v2PBEParameter;
273
274static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = {
275 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(Pkcs5v2PBEParameter) },
276 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
277 offsetof(Pkcs5v2PBEParameter, keyParams)__builtin_offsetof(Pkcs5v2PBEParameter, keyParams),
278 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
279 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
280 offsetof(Pkcs5v2PBEParameter, algParams)__builtin_offsetof(Pkcs5v2PBEParameter, algParams),
281 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
282 { 0 }
283};
284
285static inline PRBool
286isPKCS12PBE(SECOidTag alg)
287{
288 switch (alg) {
289 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
290 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
291 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
292 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
293 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
294 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
295 return PR_TRUE1;
296 default:
297 break;
298 }
299 return PR_FALSE0;
300}
301
302/* helper functions */
303
304/* output an NSS specific attribute or name that wasn't found in our
305 * pkcs #11 table */
306const char *
307makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType)
308{
309 static char nss_name[256];
310 const char *name = NULL((void*)0);
311 if ((attribute >= CKA_NSS(0x80000000UL | 0x4E534350)) && (attribute < 0xffffffffUL)) {
312 sprintf(nss_name, "%s+%d", nameType, (int)(attribute - CKA_NSS(0x80000000UL | 0x4E534350)));
313 name = nss_name;
314 }
315 return name;
316}
317
318/* turn and attribute into a name */
319const char *
320AttributeName(CK_ATTRIBUTE_TYPE attribute)
321{
322 const char *name = getNameFromAttribute(attribute);
323 if (!name) {
324 name = makeNSSVendorName(attribute, "CKA_NSS");
325 }
326
327 return name ? name : "UNKNOWN_ATTRIBUTE_TYPE";
328}
329
330/* turn and error code into a name */
331const char *
332ErrorName(CK_RV crv)
333{
334 const char *error = getName(crv, ConstResult);
335 if (!error) {
336 error = makeNSSVendorName(crv, "CKR_NSS");
337 }
338 return error ? error : "UNKNOWN_ERROR";
339}
340
341/* turn an oud tag into a string */
342const char *
343oid2string(SECOidTag alg)
344{
345 const char *oidstring = SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(alg);
346 const char *def = "Invalid oid tag"; /* future build a dotted oid string value here */
347 return oidstring ? oidstring : def;
348}
349
350/* dump an arbitary data blob. Dump it has hex with ascii on the side */
351#define ASCCHAR(val)((val) >= ' ' && (val) <= 0x7e ? (val) : '.') ((val) >= ' ' && (val) <= 0x7e ? (val) : '.')
352#define LINE_LENGTH16 16
353void
354dumpValue(const unsigned char *v, int len)
355{
356 int i, next = 0;
357 char string[LINE_LENGTH16 + 1];
358 char space[LINE_LENGTH16 * 2 + 1];
359 char *nl = "";
360 char *sp = "";
361 PORT_Memsetmemset(string, 0, sizeof(string));
362
363 for (i = 0; i < len; i++) {
364 if ((i % LINE_LENGTH16) == 0) {
365 printf("%s%s%s ", sp, string, nl);
366 PORT_Memsetmemset(string, 0, sizeof(string));
367 next = 0;
368 nl = "\n";
369 sp = " ";
370 }
371 printf("%02x", v[i]);
372 string[next++] = ASCCHAR(v[i])((v[i]) >= ' ' && (v[i]) <= 0x7e ? (v[i]) : '.'
)
;
373 }
374 PORT_Memsetmemset(space, 0, sizeof(space));
375 i = LINE_LENGTH16 - (len % LINE_LENGTH16);
376 if (i != LINE_LENGTH16) {
377 int j;
378 for (j = 0; j < i; j++) {
379 space[j * 2] = ' ';
380 space[j * 2 + 1] = ' ';
381 }
382 }
383 printf("%s%s%s%s", space, sp, string, nl);
384}
385
386/* dump a PKCS5/12 PBE blob */
387void
388dumpPKCS(unsigned char *val, CK_ULONG len, PRBool *hasSig)
389{
390 EncryptedDataInfo edi;
391 SECStatus rv;
392 SECItem data;
393 PLArenaPool *arena;
394 SECOidTag alg, prfAlg;
395 PBEParameter pbeParam;
396 unsigned char zero = 0;
397 const SEC_ASN1Template *template = pkcs5V1PBEParameterTemplate;
398 int iter, keyLen, i;
399
400 if (hasSig) {
401 *hasSig = PR_FALSE0;
402 }
403
404 data.data = val;
405 data.len = len;
406 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
407 if (arena == NULL((void*)0)) {
408 printf("Couldn't allocate arena\n");
409 return;
410 }
411
412 /* initialize default values */
413 PORT_Memsetmemset(&pbeParam, 0, sizeof(pbeParam));
414 pbeParam.keyLength.data = &zero;
415 pbeParam.keyLength.len = sizeof(zero);
416 SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL((void*)0));
417
418 /* first crack the encrypted data from the PBE algorithm ID */
419 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &edi, encryptedDataInfoTemplate, &data);
420 if (rv != SECSuccess) {
421 printf("Encrypted Data, failed to decode\n");
422 dumpValue(val, len);
423 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
424 return;
425 }
426 /* now use the pbe secalg to dump info on the pbe */
427 alg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&edi.algorithm);
428 if ((alg == SEC_OID_PKCS5_PBES2) || (alg == SEC_OID_PKCS5_PBMAC1)) {
429 Pkcs5v2PBEParameter param;
430 SECOidTag palg;
431 const char *typeName = (alg == SEC_OID_PKCS5_PBES2) ? "Encrypted Data PBES2" : "Mac Data PBMAC1";
432
433 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &param,
434 pkcs5v2PBES2ParameterTemplate,
435 &edi.algorithm.parameters);
436 if (rv != SECSuccess) {
437 printf("%s, failed to decode\n", typeName);
438 dumpValue(val, len);
439 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
440 return;
441 }
442 palg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&param.algParams);
443 printf("%s alg=%s ", typeName, oid2string(palg));
444 if (hasSig && palg == SEC_OID_AES_256_CBC) {
445 *hasSig = PR_TRUE1;
446 }
447 template = pkcs5V2PBEParameterTemplate;
448 edi.algorithm.parameters = param.keyParams.parameters;
449 } else {
450 printf("Encrypted Data alg=%s ", oid2string(alg));
451 if (alg == SEC_OID_PKCS5_PBKDF2) {
452 template = pkcs5V2PBEParameterTemplate;
453 } else if (isPKCS12PBE(alg)) {
454 template = pkcs12V2PBEParameterTemplate;
455 } else {
456 template = pkcs5V1PBEParameterTemplate;
457 }
458 }
459 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &pbeParam,
460 template,
461 &edi.algorithm.parameters);
462 if (rv != SECSuccess) {
463 printf("( failed to decode params)\n");
464 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
465 return;
466 }
467 /* dump the pbe parmeters */
468 iter = DER_GetIntegerDER_GetInteger_Util(&pbeParam.iteration);
469 keyLen = DER_GetIntegerDER_GetInteger_Util(&pbeParam.keyLength);
470 prfAlg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&pbeParam.prfAlg);
471 printf("(prf=%s iter=%d keyLen=%d salt=0x",
472 oid2string(prfAlg), iter, keyLen);
473 for (i = 0; i < pbeParam.salt.len; i++)
474 printf("%02x", pbeParam.salt.data[i]);
475 printf(")\n");
476 /* finally dump the raw encrypted data */
477 dumpValue(edi.encryptedData.data, edi.encryptedData.len);
478 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
479}
480
481/* dump a long attribute, convert to an unsigned long. PKCS #11 Longs are
482 * limited to 32 bits by the spec, even if the CK_ULONG is longer */
483void
484dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value)
485{
486 const char *nameType = "CK_NSS";
487 ConstType constType = ConstNone;
488 const char *valueName = NULL((void*)0);
489
490 switch (type) {
491 case CKA_CLASS0x00000000UL:
492 nameType = "CKO_NSS";
493 constType = ConstObject;
494 break;
495 case CKA_CERTIFICATE_TYPE0x00000080UL:
496 nameType = "CKC_NSS";
497 constType = ConstCertType;
498 break;
499 case CKA_KEY_TYPE0x00000100UL:
500 nameType = "CKK_NSS";
501 constType = ConstKeyType;
502 break;
503 case CKA_MECHANISM_TYPE0x00000500UL:
504 nameType = "CKM_NSS";
505 constType = ConstMechanism;
506 break;
507 case CKA_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
508 case CKA_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
509 case CKA_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
510 case CKA_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
511 case CKA_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12):
512 case CKA_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13):
513 case CKA_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14):
514 case CKA_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15):
515 nameType = "CKT_NSS";
516 constType = ConstTrust;
517 break;
518 default:
519 break;
520 }
521 /* if value has a symbolic name, use it */
522 if (constType != ConstNone) {
523 valueName = getName(value, constType);
524 }
525 if (!valueName) {
526 valueName = makeNSSVendorName(value, nameType);
527 }
528 if (!valueName) {
529 printf("%d (0x%08x)\n", (int)value, (int)value);
530 } else {
531 printf("%s (0x%08x)\n", valueName, (int)value);
532 }
533}
534
535/* dump a signature for an object */
536static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x";
537void
538dumpSignature(CK_ATTRIBUTE_TYPE attribute, SDB *keydb, PRBool isKey,
539 CK_OBJECT_HANDLE objectID, PRBool force)
540{
541 char id[30];
542 CK_RV crv;
543 SECItem signText;
544 unsigned char signData[SDB_MAX_META_DATA_LEN256];
545
546 if (!force && !isAuthenticatedAttribute(attribute)) {
547 return;
548 }
549 sprintf(id, META_SIG_TEMPLATE,
550 isKey ? "key" : "cert",
551 (unsigned int)objectID, (unsigned int)attribute);
552 printf(" Signature %s:", id);
553 signText.data = signData;
554 signText.len = sizeof(signData);
555
556 crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL((void*)0));
557 if ((crv != CKR_OK0x00000000UL) && isKey) {
558 sprintf(id, META_SIG_TEMPLATE,
559 isKey ? "key" : "cert", (unsigned int)(objectID | SFTK_KEYDB_TYPE0x40000000 | SFTK_TOKEN_TYPE0x80000000),
560 (unsigned int)attribute);
561 crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL((void*)0));
562 }
563 if (crv != CKR_OK0x00000000UL) {
564 printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int)crv);
565 return;
566 }
567 dumpPKCS(signText.data, signText.len, NULL((void*)0));
568 return;
569}
570
571/* dump an attribute. use the helper functions above */
572void
573dumpAttribute(CK_ATTRIBUTE *template, SDB *keydb, PRBool isKey,
574 CK_OBJECT_HANDLE id)
575{
576 CK_ATTRIBUTE_TYPE attribute = template->type;
577 printf(" %s(0x%08x): ", AttributeName(attribute), (int)attribute);
578 if (template->pValue == NULL((void*)0)) {
579 printf("NULL (%d)\n", (int)template->ulValueLen);
580 return;
581 }
582 if (template->ulValueLen == SDB_ULONG_SIZE4 && isULONGAttribute(attribute)) {
583 CK_ULONG value = sdbULong2ULong(template->pValue);
584 dumpLongAttribute(attribute, value);
585 return;
586 }
587 if (template->ulValueLen == 1) {
588 unsigned char val = *(unsigned char *)template->pValue;
589 switch (val) {
590 case 0:
591 printf("CK_FALSE\n");
592 break;
593 case 1:
594 printf("CK_TRUE\n");
595 break;
596 default:
597 printf("%d 0x%02x %c\n", val, val, ASCCHAR(val)((val) >= ' ' && (val) <= 0x7e ? (val) : '.'));
598 break;
599 }
600 return;
601 }
602 if (isKey && isPrivateAttribute(attribute)) {
603 PRBool hasSig = PR_FALSE0;
604 dumpPKCS(template->pValue, template->ulValueLen, &hasSig);
605 if (hasSig) {
606 dumpSignature(attribute, keydb, isKey, id, PR_TRUE1);
607 }
608 return;
609 }
610 if (template->ulValueLen == 0) {
611 printf("empty");
612 }
613 printf("\n");
614 dumpValue(template->pValue, template->ulValueLen);
615}
616
617/* dump all the attributes in an object */
618void
619dumpObject(CK_OBJECT_HANDLE id, SDB *db, SDB *keydb, PRBool isKey)
620{
621 CK_RV crv;
622 int i;
623 CK_ATTRIBUTE template;
624 char buffer[2048];
625 char *alloc = NULL((void*)0);
626
627 printf(" Object 0x%08x:\n", (int)id);
628 for (i = 0; i < known_attributes_size; i++) {
629 CK_ATTRIBUTE_TYPE attribute = known_attributes[i];
630 template.type = attribute;
631 template.pValue = NULL((void*)0);
632 template.ulValueLen = 0;
633 crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
634
635 if (crv != CKR_OK0x00000000UL) {
636 if (crv != CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL) {
637 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
638 "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
639 AttributeName(attribute), (int)attribute,
640 ErrorName(crv), (int)crv);
641 }
642 continue;
643 }
644
645 if (template.ulValueLen < sizeof(buffer)) {
646 template.pValue = buffer;
647 } else {
648 alloc = PORT_AllocPORT_Alloc_Util(template.ulValueLen);
649 template.pValue = alloc;
650 }
651 if (template.pValue == NULL((void*)0)) {
652 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
653 "Could allocate %d bytes for Attribute %s (0x%08x)\n",
654 (int)template.ulValueLen,
655 AttributeName(attribute), (int)attribute);
656 continue;
657 }
658 crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
659
660 if (crv != CKR_OK0x00000000UL) {
661 if (crv != CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL) {
662 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
663 "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
664 AttributeName(attribute), (int)attribute,
665 ErrorName(crv), (int)crv);
666 }
667 if (alloc) {
668 PORT_FreePORT_Free_Util(alloc);
669 alloc = NULL((void*)0);
670 }
671 continue;
672 }
673
674 dumpAttribute(&template, keydb, isKey, id);
675 dumpSignature(template.type, keydb, isKey, id, PR_FALSE0);
676 if (alloc) {
677 PORT_FreePORT_Free_Util(alloc);
678 alloc = NULL((void*)0);
679 }
680 }
681}
682
683/* dump all the objects in a database */
684void
685dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey)
686{
687 SDBFind *findHandle = NULL((void*)0);
688 CK_BBOOL isTrue = 1;
689 CK_ATTRIBUTE allObjectTemplate = { CKA_TOKEN0x00000001UL, NULL((void*)0), 1 };
690 CK_ULONG allObjectTemplateCount = 1;
691 PRBool recordFound = PR_FALSE0;
692 CK_RV crv = CKR_OK0x00000000UL;
693 CK_ULONG objectCount = 0;
694 printf("%s:\n", name);
695
696 allObjectTemplate.pValue = &isTrue;
697 crv = (*db->sdb_FindObjectsInit)(db, &allObjectTemplate,
698 allObjectTemplateCount, &findHandle);
699 do {
700 CK_OBJECT_HANDLE id;
701 recordFound = PR_FALSE0;
702 crv = (*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount);
703 if ((crv == CKR_OK0x00000000UL) && (objectCount == 1)) {
704 recordFound = PR_TRUE1;
705 dumpObject(id, db, keydb, isKey);
706 }
707 } while (recordFound);
708 if (crv != CKR_OK0x00000000UL) {
709 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
710 "Last record return PKCS #11 error = %s (0x%08x)\n",
711 ErrorName(crv), (int)crv);
712 }
713 (*db->sdb_FindObjectsFinal)(db, findHandle);
714}
715
716static char *
717secu_ConfigDirectory(const char *base)
718{
719 static PRBool initted = PR_FALSE0;
720 const char *dir = ".netscape";
721 char *home;
722 static char buf[1000];
723
724 if (initted)
725 return buf;
726
727 if (base == NULL((void*)0) || *base == 0) {
728 home = PR_GetEnvSecure("HOME");
729 if (!home)
730 home = "";
731
732 if (*home && home[strlen(home) - 1] == '/')
733 sprintf(buf, "%.900s%s", home, dir);
734 else
735 sprintf(buf, "%.900s/%s", home, dir);
736 } else {
737 sprintf(buf, "%.900s", base);
738 if (buf[strlen(buf) - 1] == '/')
739 buf[strlen(buf) - 1] = 0;
740 }
741
742 initted = PR_TRUE1;
743 return buf;
744}
745
746int
747main(int argc, char **argv)
748{
749 PLOptState *optstate;
750 PLOptStatus optstatus;
751 char *certPrefix = "", *keyPrefix = "";
752 int cert_version = 9;
753 int key_version = 4;
754 SDB *certdb = NULL((void*)0);
755 SDB *keydb = NULL((void*)0);
756 PRBool isNew = PR_FALSE0;
757
758 CK_RV crv;
759
760 progName = strrchr(argv[0], '/');
761 if (!progName)
1
Assuming 'progName' is non-null
762 progName = strrchr(argv[0], '\\');
763 progName = progName
2.1
'progName' is non-null
? progName + 1 : argv[0];
2
Taking false branch
3
'?' condition is true
764
765 optstate = PL_CreateOptState(argc, argv, "d:c:k:v:V:h");
766
767 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 795
768 switch (optstate->option) {
769 case 'h':
770 default:
771 Usage();
772 break;
773
774 case 'd':
775 dbDir = PORT_StrdupPORT_Strdup_Util(optstate->value);
776 break;
777
778 case 'c':
779 certPrefix = PORT_StrdupPORT_Strdup_Util(optstate->value);
780 break;
781
782 case 'k':
783 keyPrefix = PORT_StrdupPORT_Strdup_Util(optstate->value);
784 break;
785
786 case 'v':
787 key_version = atoi(optstate->value);
788 break;
789
790 case 'V':
791 cert_version = atoi(optstate->value);
792 break;
793 }
794 }
795 PL_DestroyOptState(optstate);
796 if (optstatus == PL_OPT_BAD)
6
Assuming 'optstatus' is not equal to PL_OPT_BAD
7
Taking false branch
797 Usage();
798
799 if (dbDir
7.1
'dbDir' is null
) {
8
Taking false branch
800 char *tmp = dbDir;
801 dbDir = secu_ConfigDirectory(tmp);
802 PORT_FreePORT_Free_Util(tmp);
803 } else {
804 dbDir = secu_ConfigDirectory(NULL((void*)0));
805 }
806 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "dbdir selected is %s\n\n", dbDir);
9
Null pointer value stored to 'dbDir'
807
808 if (dbDir[0] == '\0') {
10
Array access (from variable 'dbDir') results in a null pointer dereference
809 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
810 "ERROR: Directory \"%s\" does not exist.\n", dbDir);
811 return 1;
812 }
813
814 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
815 SECOID_Init();
816
817 crv = s_open(dbDir, certPrefix, keyPrefix, cert_version, key_version,
818 SDB_RDONLY1, &certdb, &keydb, &isNew);
819 if (crv != CKR_OK0x00000000UL) {
820 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
821 "Couldn't open databased in %s, error=%s (0x%08x)\n",
822 dbDir, ErrorName(crv), (int)crv);
823 return 1;
824 }
825
826 /* now dump the objects in the cert database */
827 dumpDB(certdb, "CertDB", keydb, PR_FALSE0);
828 dumpDB(keydb, "KeyDB", keydb, PR_TRUE1);
829 return 0;
830}