Bug Summary

File:s/cmd/dbtool/dbtool.c
Warning:line 791, 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=/nss/cmd/dbtool -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/nss/cmd/dbtool -resource-dir /usr/lib/llvm-22/lib/clang/22 -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/Linux6.1_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../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 -fskip-odr-check-in-gmf -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-11-18-221358-3012168-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 */
74extern const CK_ATTRIBUTE_TYPE sftkdb_known_attributes[];
75extern size_t sftkdb_known_attributes_size;
76
77PRBool
78isULONGAttribute(CK_ATTRIBUTE_TYPE type)
79{
80 switch (type) {
81 case CKA_CERTIFICATE_CATEGORY0x00000087UL:
82 case CKA_CERTIFICATE_TYPE0x00000080UL:
83 case CKA_CLASS0x00000000UL:
84 case CKA_JAVA_MIDP_SECURITY_DOMAIN0x00000088UL:
85 case CKA_KEY_GEN_MECHANISM0x00000166UL:
86 case CKA_KEY_TYPE0x00000100UL:
87 case CKA_MECHANISM_TYPE0x00000500UL:
88 case CKA_MODULUS_BITS0x00000121UL:
89 case CKA_PRIME_BITS0x00000133UL:
90 case CKA_SUBPRIME_BITS0x00000134UL:
91 case CKA_VALUE_BITS0x00000160UL:
92 case CKA_VALUE_LEN0x00000161UL:
93
94 case CKA_NSS_TRUST_DIGITAL_SIGNATURE(((0x80000000UL | 0x4E534350) + 0x2000) + 1):
95 case CKA_NSS_TRUST_NON_REPUDIATION(((0x80000000UL | 0x4E534350) + 0x2000) + 2):
96 case CKA_NSS_TRUST_KEY_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 3):
97 case CKA_NSS_TRUST_DATA_ENCIPHERMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 4):
98 case CKA_NSS_TRUST_KEY_AGREEMENT(((0x80000000UL | 0x4E534350) + 0x2000) + 5):
99 case CKA_NSS_TRUST_KEY_CERT_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 6):
100 case CKA_NSS_TRUST_CRL_SIGN(((0x80000000UL | 0x4E534350) + 0x2000) + 7):
101
102 case CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
103 case CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
104 case CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
105 case CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
106 case CKA_NSS_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12):
107 case CKA_NSS_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13):
108 case CKA_NSS_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14):
109 case CKA_NSS_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15):
110 case CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL:
111 case CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL:
112 case CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL:
113 case CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL:
114 case CKA_TRUST_IPSEC_IKE0x00000630UL:
115 case CKA_PKCS_TRUST_TIME_STAMPING0x00000631UL:
116 case CKA_NAME_HASH_ALGORITHM0x0000008cUL:
117 return PR_TRUE1;
118 default:
119 break;
120 }
121 return PR_FALSE0;
122}
123
124/* are the attributes private? */
125static PRBool
126isPrivateAttribute(CK_ATTRIBUTE_TYPE type)
127{
128 switch (type) {
129 case CKA_VALUE0x00000011UL:
130 case CKA_PRIVATE_EXPONENT0x00000123UL:
131 case CKA_PRIME_10x00000124UL:
132 case CKA_PRIME_20x00000125UL:
133 case CKA_EXPONENT_10x00000126UL:
134 case CKA_EXPONENT_20x00000127UL:
135 case CKA_COEFFICIENT0x00000128UL:
136 return PR_TRUE1;
137 default:
138 break;
139 }
140 return PR_FALSE0;
141}
142
143/* These attributes must be authenticated with an hmac. */
144static PRBool
145isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type)
146{
147 switch (type) {
148 case CKA_MODULUS0x00000120UL:
149 case CKA_PUBLIC_EXPONENT0x00000122UL:
150 case CKA_NSS_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100):
151 case CKA_NSS_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101):
152 case CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
153 case CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
154 case CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
155 case CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
156 case CKA_HASH_OF_CERTIFICATE0x00000635UL:
157 case CKA_NAME_HASH_ALGORITHM0x0000008cUL:
158 case CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL:
159 case CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL:
160 case CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL:
161 case CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL:
162 case CKA_NSS_OVERRIDE_EXTENSIONS((0x80000000UL | 0x4E534350) + 25):
163 return PR_TRUE1;
164 default:
165 break;
166 }
167 return PR_FALSE0;
168}
169
170/*
171 * convert a database ulong back to a native ULONG. (reverse of the above
172 * function.
173 */
174static CK_ULONG
175sdbULong2ULong(unsigned char *data)
176{
177 int i;
178 CK_ULONG value = 0;
179
180 for (i = 0; i < SDB_ULONG_SIZE4; i++) {
181 value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE4 - 1 - i) * PR_BITS_PER_BYTE8);
182 }
183 return value;
184}
185
186/* PBE defines and functions */
187SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
188
189typedef struct EncryptedDataInfoStr {
190 SECAlgorithmID algorithm;
191 SECItem encryptedData;
192} EncryptedDataInfo;
193
194static const SEC_ASN1Template encryptedDataInfoTemplate[] = {
195 { SEC_ASN1_SEQUENCE0x10,
196 0, NULL((void*)0), sizeof(EncryptedDataInfo) },
197 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
198 offsetof(EncryptedDataInfo, algorithm)__builtin_offsetof(EncryptedDataInfo, algorithm),
199 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
200 { SEC_ASN1_OCTET_STRING0x04,
201 offsetof(EncryptedDataInfo, encryptedData)__builtin_offsetof(EncryptedDataInfo, encryptedData) },
202 { 0 }
203};
204
205typedef struct PBEParameterStr {
206 SECAlgorithmID prfAlg;
207 SECItem salt;
208 SECItem iteration;
209 SECItem keyLength;
210} PBEParameter;
211
212static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = {
213 { SEC_ASN1_SEQUENCE0x10,
214 0, NULL((void*)0), sizeof(PBEParameter) },
215 { SEC_ASN1_OCTET_STRING0x04,
216 offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
217 { SEC_ASN1_INTEGER0x02,
218 offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
219 { 0 }
220};
221
222static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = {
223 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(PBEParameter) },
224 { SEC_ASN1_OCTET_STRING0x04, offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
225 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
226 { 0 }
227};
228
229static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = {
230 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(PBEParameter) },
231 /* this is really a choice, but since we don't understand any other
232 * choice, just inline it. */
233 { SEC_ASN1_OCTET_STRING0x04, offsetof(PBEParameter, salt)__builtin_offsetof(PBEParameter, salt) },
234 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, iteration)__builtin_offsetof(PBEParameter, iteration) },
235 { SEC_ASN1_INTEGER0x02, offsetof(PBEParameter, keyLength)__builtin_offsetof(PBEParameter, keyLength) },
236 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
237 offsetof(PBEParameter, prfAlg)__builtin_offsetof(PBEParameter, prfAlg),
238 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
239 { 0 }
240};
241
242typedef struct Pkcs5v2PBEParameterStr {
243 SECAlgorithmID keyParams; /* parameters of the key generation */
244 SECAlgorithmID algParams; /* parameters for the encryption or mac op */
245} Pkcs5v2PBEParameter;
246
247static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = {
248 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(Pkcs5v2PBEParameter) },
249 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
250 offsetof(Pkcs5v2PBEParameter, keyParams)__builtin_offsetof(Pkcs5v2PBEParameter, keyParams),
251 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
252 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
253 offsetof(Pkcs5v2PBEParameter, algParams)__builtin_offsetof(Pkcs5v2PBEParameter, algParams),
254 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
255 { 0 }
256};
257
258static inline PRBool
259isPKCS12PBE(SECOidTag alg)
260{
261 switch (alg) {
262 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
263 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
264 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
265 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
266 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
267 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
268 return PR_TRUE1;
269 default:
270 break;
271 }
272 return PR_FALSE0;
273}
274
275/* helper functions */
276
277/* output an NSS specific attribute or name that wasn't found in our
278 * pkcs #11 table */
279const char *
280makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType)
281{
282 static char nss_name[256];
283 const char *name = NULL((void*)0);
284 if ((attribute >= CKA_NSS(0x80000000UL | 0x4E534350)) && (attribute < 0xffffffffUL)) {
285 snprintf(nss_name, sizeof(nss_name), "%s+%d", nameType, (int)(attribute - CKA_NSS(0x80000000UL | 0x4E534350)));
286 name = nss_name;
287 }
288 return name;
289}
290
291/* turn and attribute into a name */
292const char *
293AttributeName(CK_ATTRIBUTE_TYPE attribute)
294{
295 const char *name = getNameFromAttribute(attribute);
296 if (!name) {
297 name = makeNSSVendorName(attribute, "CKA_NSS");
298 }
299
300 return name ? name : "UNKNOWN_ATTRIBUTE_TYPE";
301}
302
303/* turn and error code into a name */
304const char *
305ErrorName(CK_RV crv)
306{
307 const char *error = getName(crv, ConstResult);
308 if (!error) {
309 error = makeNSSVendorName(crv, "CKR_NSS");
310 }
311 return error ? error : "UNKNOWN_ERROR";
312}
313
314/* turn an oud tag into a string */
315const char *
316oid2string(SECOidTag alg)
317{
318 const char *oidstring = SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(alg);
319 const char *def = "Invalid oid tag"; /* future build a dotted oid string value here */
320 return oidstring ? oidstring : def;
321}
322
323/* dump an arbitary data blob. Dump it has hex with ascii on the side */
324#define ASCCHAR(val)((val) >= ' ' && (val) <= 0x7e ? (val) : '.') ((val) >= ' ' && (val) <= 0x7e ? (val) : '.')
325#define LINE_LENGTH16 16
326void
327dumpValue(const unsigned char *v, int len)
328{
329 int i, next = 0;
330 char string[LINE_LENGTH16 + 1];
331 char space[LINE_LENGTH16 * 2 + 1];
332 char *nl = "";
333 char *sp = "";
334 PORT_Memsetmemset(string, 0, sizeof(string));
335
336 for (i = 0; i < len; i++) {
337 if ((i % LINE_LENGTH16) == 0) {
338 printf("%s%s%s ", sp, string, nl);
339 PORT_Memsetmemset(string, 0, sizeof(string));
340 next = 0;
341 nl = "\n";
342 sp = " ";
343 }
344 printf("%02x", v[i]);
345 string[next++] = ASCCHAR(v[i])((v[i]) >= ' ' && (v[i]) <= 0x7e ? (v[i]) : '.'
)
;
346 }
347 PORT_Memsetmemset(space, 0, sizeof(space));
348 i = LINE_LENGTH16 - (len % LINE_LENGTH16);
349 if (i != LINE_LENGTH16) {
350 int j;
351 for (j = 0; j < i; j++) {
352 space[j * 2] = ' ';
353 space[j * 2 + 1] = ' ';
354 }
355 }
356 printf("%s%s%s%s", space, sp, string, nl);
357}
358
359/* dump a PKCS5/12 PBE blob */
360void
361dumpPKCS(unsigned char *val, CK_ULONG len, PRBool *hasSig)
362{
363 EncryptedDataInfo edi;
364 SECStatus rv;
365 SECItem data;
366 PLArenaPool *arena;
367 SECOidTag alg, prfAlg;
368 PBEParameter pbeParam;
369 unsigned char zero = 0;
370 const SEC_ASN1Template *template = pkcs5V1PBEParameterTemplate;
371 int iter, keyLen, i;
372
373 if (hasSig) {
374 *hasSig = PR_FALSE0;
375 }
376
377 data.data = val;
378 data.len = len;
379 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
380 if (arena == NULL((void*)0)) {
381 printf("Couldn't allocate arena\n");
382 return;
383 }
384
385 /* initialize default values */
386 PORT_Memsetmemset(&pbeParam, 0, sizeof(pbeParam));
387 pbeParam.keyLength.data = &zero;
388 pbeParam.keyLength.len = sizeof(zero);
389 SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL((void*)0));
390
391 /* first crack the encrypted data from the PBE algorithm ID */
392 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &edi, encryptedDataInfoTemplate, &data);
393 if (rv != SECSuccess) {
394 printf("Encrypted Data, failed to decode\n");
395 dumpValue(val, len);
396 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
397 return;
398 }
399 /* now use the pbe secalg to dump info on the pbe */
400 alg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&edi.algorithm);
401 if ((alg == SEC_OID_PKCS5_PBES2) || (alg == SEC_OID_PKCS5_PBMAC1)) {
402 Pkcs5v2PBEParameter param;
403 SECOidTag palg;
404 const char *typeName = (alg == SEC_OID_PKCS5_PBES2) ? "Encrypted Data PBES2" : "Mac Data PBMAC1";
405
406 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &param,
407 pkcs5v2PBES2ParameterTemplate,
408 &edi.algorithm.parameters);
409 if (rv != SECSuccess) {
410 printf("%s, failed to decode\n", typeName);
411 dumpValue(val, len);
412 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
413 return;
414 }
415 palg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&param.algParams);
416 printf("%s alg=%s ", typeName, oid2string(palg));
417 if (hasSig && palg == SEC_OID_AES_256_CBC) {
418 *hasSig = PR_TRUE1;
419 }
420 template = pkcs5V2PBEParameterTemplate;
421 edi.algorithm.parameters = param.keyParams.parameters;
422 } else {
423 printf("Encrypted Data alg=%s ", oid2string(alg));
424 if (alg == SEC_OID_PKCS5_PBKDF2) {
425 template = pkcs5V2PBEParameterTemplate;
426 } else if (isPKCS12PBE(alg)) {
427 template = pkcs12V2PBEParameterTemplate;
428 } else {
429 template = pkcs5V1PBEParameterTemplate;
430 }
431 }
432 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &pbeParam,
433 template,
434 &edi.algorithm.parameters);
435 if (rv != SECSuccess) {
436 printf("( failed to decode params)\n");
437 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
438 return;
439 }
440 /* dump the pbe parmeters */
441 iter = DER_GetIntegerDER_GetInteger_Util(&pbeParam.iteration);
442 keyLen = DER_GetIntegerDER_GetInteger_Util(&pbeParam.keyLength);
443 prfAlg = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&pbeParam.prfAlg);
444 printf("(prf=%s iter=%d keyLen=%d salt=0x",
445 oid2string(prfAlg), iter, keyLen);
446 for (i = 0; i < pbeParam.salt.len; i++)
447 printf("%02x", pbeParam.salt.data[i]);
448 printf(")\n");
449 /* finally dump the raw encrypted data */
450 dumpValue(edi.encryptedData.data, edi.encryptedData.len);
451 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
452}
453
454/* dump a long attribute, convert to an unsigned long. PKCS #11 Longs are
455 * limited to 32 bits by the spec, even if the CK_ULONG is longer */
456void
457dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value)
458{
459 const char *nameType = "CK_NSS";
460 ConstType constType = ConstNone;
461 const char *valueName = NULL((void*)0);
462
463 switch (type) {
464 case CKA_CLASS0x00000000UL:
465 nameType = "CKO_NSS";
466 constType = ConstObject;
467 break;
468 case CKA_CERTIFICATE_TYPE0x00000080UL:
469 nameType = "CKC_NSS";
470 constType = ConstCertType;
471 break;
472 case CKA_KEY_TYPE0x00000100UL:
473 nameType = "CKK_NSS";
474 constType = ConstKeyType;
475 break;
476 case CKA_MECHANISM_TYPE0x00000500UL:
477 case CKA_NAME_HASH_ALGORITHM0x0000008cUL:
478 nameType = "CKM_NSS";
479 constType = ConstMechanism;
480 break;
481 case CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8):
482 case CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9):
483 case CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10):
484 case CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11):
485 case CKA_NSS_TRUST_IPSEC_END_SYSTEM(((0x80000000UL | 0x4E534350) + 0x2000) + 12):
486 case CKA_NSS_TRUST_IPSEC_TUNNEL(((0x80000000UL | 0x4E534350) + 0x2000) + 13):
487 case CKA_NSS_TRUST_IPSEC_USER(((0x80000000UL | 0x4E534350) + 0x2000) + 14):
488 case CKA_NSS_TRUST_TIME_STAMPING(((0x80000000UL | 0x4E534350) + 0x2000) + 15):
489 nameType = "CKT_NSS";
490 constType = ConstTrust;
491 break;
492 case CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL:
493 case CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL:
494 case CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL:
495 case CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL:
496 case CKA_TRUST_IPSEC_IKE0x00000630UL:
497 case CKA_PKCS_TRUST_TIME_STAMPING0x00000631UL:
498 nameType = "CKT_";
499 constType = ConstTrust;
500 break;
501 default:
502 break;
503 }
504 /* if value has a symbolic name, use it */
505 if (constType != ConstNone) {
506 valueName = getName(value, constType);
507 }
508 if (!valueName) {
509 valueName = makeNSSVendorName(value, nameType);
510 }
511 if (!valueName) {
512 printf("%d (0x%08x)\n", (int)value, (int)value);
513 } else {
514 printf("%s (0x%08x)\n", valueName, (int)value);
515 }
516}
517
518/* dump a signature for an object */
519static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x";
520void
521dumpSignature(CK_ATTRIBUTE_TYPE attribute, SDB *keydb, PRBool isKey,
522 CK_OBJECT_HANDLE objectID, PRBool force)
523{
524 char id[30];
525 CK_RV crv;
526 SECItem signText;
527 unsigned char signData[SDB_MAX_META_DATA_LEN256];
528
529 if (!force && !isAuthenticatedAttribute(attribute)) {
530 return;
531 }
532 snprintf(id, sizeof(id), META_SIG_TEMPLATE,
533 isKey ? "key" : "cert",
534 (unsigned int)objectID, (unsigned int)attribute);
535 printf(" Signature %s:", id);
536 signText.data = signData;
537 signText.len = sizeof(signData);
538
539 crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL((void*)0));
540 if ((crv != CKR_OK0x00000000UL) && isKey) {
541 snprintf(id, sizeof(id), META_SIG_TEMPLATE,
542 isKey ? "key" : "cert", (unsigned int)(objectID | SFTK_KEYDB_TYPE0x40000000 | SFTK_TOKEN_TYPE0x80000000),
543 (unsigned int)attribute);
544 crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL((void*)0));
545 }
546 if (crv != CKR_OK0x00000000UL) {
547 printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int)crv);
548 return;
549 }
550 dumpPKCS(signText.data, signText.len, NULL((void*)0));
551 return;
552}
553
554/* dump an attribute. use the helper functions above */
555void
556dumpAttribute(CK_ATTRIBUTE *template, SDB *keydb, PRBool isKey,
557 CK_OBJECT_HANDLE id)
558{
559 CK_ATTRIBUTE_TYPE attribute = template->type;
560 printf(" %s(0x%08x): ", AttributeName(attribute), (int)attribute);
561 if (template->pValue == NULL((void*)0)) {
562 printf("NULL (%d)\n", (int)template->ulValueLen);
563 return;
564 }
565 if (template->ulValueLen == SDB_ULONG_SIZE4 && isULONGAttribute(attribute)) {
566 CK_ULONG value = sdbULong2ULong(template->pValue);
567 dumpLongAttribute(attribute, value);
568 return;
569 }
570 if (template->ulValueLen == 1) {
571 unsigned char val = *(unsigned char *)template->pValue;
572 switch (val) {
573 case 0:
574 printf("CK_FALSE\n");
575 break;
576 case 1:
577 printf("CK_TRUE\n");
578 break;
579 default:
580 printf("%d 0x%02x %c\n", val, val, ASCCHAR(val)((val) >= ' ' && (val) <= 0x7e ? (val) : '.'));
581 break;
582 }
583 return;
584 }
585 if (isKey && isPrivateAttribute(attribute)) {
586 PRBool hasSig = PR_FALSE0;
587 dumpPKCS(template->pValue, template->ulValueLen, &hasSig);
588 if (hasSig) {
589 dumpSignature(attribute, keydb, isKey, id, PR_TRUE1);
590 }
591 return;
592 }
593 if (template->ulValueLen == 0) {
594 printf("empty");
595 }
596 printf("\n");
597 dumpValue(template->pValue, template->ulValueLen);
598}
599
600/* dump all the attributes in an object */
601void
602dumpObject(CK_OBJECT_HANDLE id, SDB *db, SDB *keydb, PRBool isKey)
603{
604 CK_RV crv;
605 size_t i;
606 CK_ATTRIBUTE template;
607 char buffer[2048];
608 char *alloc = NULL((void*)0);
609
610 printf(" Object 0x%08x:\n", (int)id);
611 for (i = 0; i < sftkdb_known_attributes_size; i++) {
612 CK_ATTRIBUTE_TYPE attribute = sftkdb_known_attributes[i];
613 template.type = attribute;
614 template.pValue = NULL((void*)0);
615 template.ulValueLen = 0;
616 crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
617
618 if (crv != CKR_OK0x00000000UL) {
619 if (crv != CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL) {
620 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
621 "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
622 AttributeName(attribute), (int)attribute,
623 ErrorName(crv), (int)crv);
624 }
625 continue;
626 }
627
628 if (template.ulValueLen < sizeof(buffer)) {
629 template.pValue = buffer;
630 } else {
631 alloc = PORT_AllocPORT_Alloc_Util(template.ulValueLen);
632 template.pValue = alloc;
633 }
634 if (template.pValue == NULL((void*)0)) {
635 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
636 "Could allocate %d bytes for Attribute %s (0x%08x)\n",
637 (int)template.ulValueLen,
638 AttributeName(attribute), (int)attribute);
639 continue;
640 }
641 crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
642
643 if (crv != CKR_OK0x00000000UL) {
644 if (crv != CKR_ATTRIBUTE_TYPE_INVALID0x00000012UL) {
645 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " "
646 "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
647 AttributeName(attribute), (int)attribute,
648 ErrorName(crv), (int)crv);
649 }
650 if (alloc) {
651 PORT_FreePORT_Free_Util(alloc);
652 alloc = NULL((void*)0);
653 }
654 continue;
655 }
656
657 dumpAttribute(&template, keydb, isKey, id);
658 dumpSignature(template.type, keydb, isKey, id, PR_FALSE0);
659 if (alloc) {
660 PORT_FreePORT_Free_Util(alloc);
661 alloc = NULL((void*)0);
662 }
663 }
664}
665
666/* dump all the objects in a database */
667void
668dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey)
669{
670 SDBFind *findHandle = NULL((void*)0);
671 CK_BBOOL isTrue = 1;
672 CK_ATTRIBUTE allObjectTemplate = { CKA_TOKEN0x00000001UL, NULL((void*)0), 1 };
673 CK_ULONG allObjectTemplateCount = 1;
674 PRBool recordFound = PR_FALSE0;
675 CK_RV crv = CKR_OK0x00000000UL;
676 CK_ULONG objectCount = 0;
677 printf("%s:\n", name);
678
679 allObjectTemplate.pValue = &isTrue;
680 crv = (*db->sdb_FindObjectsInit)(db, &allObjectTemplate,
681 allObjectTemplateCount, &findHandle);
682 do {
683 CK_OBJECT_HANDLE id;
684 recordFound = PR_FALSE0;
685 crv = (*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount);
686 if ((crv == CKR_OK0x00000000UL) && (objectCount == 1)) {
687 recordFound = PR_TRUE1;
688 dumpObject(id, db, keydb, isKey);
689 }
690 } while (recordFound);
691 if (crv != CKR_OK0x00000000UL) {
692 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
693 "Last record return PKCS #11 error = %s (0x%08x)\n",
694 ErrorName(crv), (int)crv);
695 }
696 (*db->sdb_FindObjectsFinal)(db, findHandle);
697}
698
699static char *
700secu_ConfigDirectory(const char *base)
701{
702 static PRBool initted = PR_FALSE0;
703 const char *dir = ".netscape";
704 char *home;
705 static char buf[1000];
706
707 if (initted)
708 return buf;
709
710 if (base == NULL((void*)0) || *base == 0) {
711 home = PR_GetEnvSecure("HOME");
712 if (!home)
713 home = "";
714
715 if (*home && home[strlen(home) - 1] == '/')
716 snprintf(buf, sizeof(buf), "%.900s%s", home, dir);
717 else
718 snprintf(buf, sizeof(buf), "%.900s/%s", home, dir);
719 } else {
720 snprintf(buf, sizeof(buf), "%.900s", base);
721 if (buf[strlen(buf) - 1] == '/')
722 buf[strlen(buf) - 1] = 0;
723 }
724
725 initted = PR_TRUE1;
726 return buf;
727}
728
729int
730main(int argc, char **argv)
731{
732 PLOptState *optstate;
733 PLOptStatus optstatus;
734 char *certPrefix = "", *keyPrefix = "";
735 int cert_version = 9;
736 int key_version = 4;
737 SDB *certdb = NULL((void*)0);
738 SDB *keydb = NULL((void*)0);
739 PRBool isNew = PR_FALSE0;
740
741 CK_RV crv;
742
743 progName = strrchr(argv[0], '/');
744 if (!progName)
1
Assuming 'progName' is non-null
745 progName = strrchr(argv[0], '\\');
746 progName = progName
2.1
'progName' is non-null
? progName + 1 : argv[0];
2
Taking false branch
3
'?' condition is true
747
748 optstate = PL_CreateOptState(argc, argv, "d:c:k:v:V:h");
749
750 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 778
751 switch (optstate->option) {
752 case 'h':
753 default:
754 Usage();
755 break;
756
757 case 'd':
758 dbDir = PORT_StrdupPORT_Strdup_Util(optstate->value);
759 break;
760
761 case 'c':
762 certPrefix = PORT_StrdupPORT_Strdup_Util(optstate->value);
763 break;
764
765 case 'k':
766 keyPrefix = PORT_StrdupPORT_Strdup_Util(optstate->value);
767 break;
768
769 case 'v':
770 key_version = atoi(optstate->value);
771 break;
772
773 case 'V':
774 cert_version = atoi(optstate->value);
775 break;
776 }
777 }
778 PL_DestroyOptState(optstate);
779 if (optstatus == PL_OPT_BAD)
6
Assuming 'optstatus' is not equal to PL_OPT_BAD
7
Taking false branch
780 Usage();
781
782 if (dbDir
7.1
'dbDir' is null
) {
8
Taking false branch
783 char *tmp = dbDir;
784 dbDir = secu_ConfigDirectory(tmp);
785 PORT_FreePORT_Free_Util(tmp);
786 } else {
787 dbDir = secu_ConfigDirectory(NULL((void*)0));
788 }
789 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "dbdir selected is %s\n\n", dbDir);
9
Null pointer value stored to 'dbDir'
790
791 if (dbDir[0] == '\0') {
10
Array access (from variable 'dbDir') results in a null pointer dereference
792 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
793 "ERROR: Directory \"%s\" does not exist.\n", dbDir);
794 return 1;
795 }
796
797 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
798 SECOID_Init();
799
800 crv = s_open(dbDir, certPrefix, keyPrefix, cert_version, key_version,
801 SDB_RDONLY1, &certdb, &keydb, &isNew);
802 if (crv != CKR_OK0x00000000UL) {
803 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
804 "Couldn't open databased in %s, error=%s (0x%08x)\n",
805 dbDir, ErrorName(crv), (int)crv);
806 return 1;
807 }
808
809 /* now dump the objects in the cert database */
810 dumpDB(certdb, "CertDB", keydb, PR_FALSE0);
811 dumpDB(keydb, "KeyDB", keydb, PR_TRUE1);
812
813 crv = sdb_Close(certdb);
814 if (crv != CKR_OK0x00000000UL) {
815 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
816 "Couldn't close cert database in %s, error=%s (0x%08x)\n",
817 dbDir, ErrorName(crv), (int)crv);
818 }
819
820 crv = sdb_Close(keydb);
821 if (crv != CKR_OK0x00000000UL) {
822 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
823 "Couldn't close key database in %s, error=%s (0x%08x)\n",
824 dbDir, ErrorName(crv), (int)crv);
825 }
826
827 crv = s_shutdown();
828 if (crv != CKR_OK0x00000000UL) {
829 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
830 "Error in s_shutdown, error=%s (0x%08x)\n",
831 ErrorName(crv), (int)crv);
832 }
833 return 0;
834}