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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
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 | |
27 | |
28 | |
29 | #if defined(XP_UNIX) |
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 | |
45 | static char *progName; |
46 | |
47 | char *dbDir = NULL; |
48 | |
49 | static void |
50 | Usage() |
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_TYPE 0x40000000 |
69 | #define SFTK_TOKEN_TYPE 0x80000000 |
70 | |
71 | |
72 | |
73 | |
74 | static const CK_ATTRIBUTE_TYPE known_attributes[] = { |
75 | CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION, |
76 | CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER, |
77 | CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED, |
78 | CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL, |
79 | CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY, |
80 | CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE, |
81 | CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER, |
82 | CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE, |
83 | CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, |
84 | CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, |
85 | CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS, |
86 | CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE, |
87 | CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE, |
88 | CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS, |
89 | CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, |
90 | CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE, |
91 | CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, |
92 | CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS, |
93 | CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, |
94 | CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE, |
95 | CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES, |
96 | CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NSS_URL, CKA_NSS_EMAIL, |
97 | CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP, |
98 | CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES, |
99 | CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED, |
100 | CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC, |
101 | CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION, |
102 | CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT, |
103 | CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, |
104 | CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, |
105 | CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM, |
106 | CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING, |
107 | CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, |
108 | CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS, |
109 | CKA_PUBLIC_KEY_INFO |
110 | }; |
111 | |
112 | static unsigned int known_attributes_size = sizeof(known_attributes) / |
113 | sizeof(known_attributes[0]); |
114 | |
115 | PRBool |
116 | isULONGAttribute(CK_ATTRIBUTE_TYPE type) |
117 | { |
118 | switch (type) { |
119 | case CKA_CERTIFICATE_CATEGORY: |
120 | case CKA_CERTIFICATE_TYPE: |
121 | case CKA_CLASS: |
122 | case CKA_JAVA_MIDP_SECURITY_DOMAIN: |
123 | case CKA_KEY_GEN_MECHANISM: |
124 | case CKA_KEY_TYPE: |
125 | case CKA_MECHANISM_TYPE: |
126 | case CKA_MODULUS_BITS: |
127 | case CKA_PRIME_BITS: |
128 | case CKA_SUBPRIME_BITS: |
129 | case CKA_VALUE_BITS: |
130 | case CKA_VALUE_LEN: |
131 | |
132 | case CKA_TRUST_DIGITAL_SIGNATURE: |
133 | case CKA_TRUST_NON_REPUDIATION: |
134 | case CKA_TRUST_KEY_ENCIPHERMENT: |
135 | case CKA_TRUST_DATA_ENCIPHERMENT: |
136 | case CKA_TRUST_KEY_AGREEMENT: |
137 | case CKA_TRUST_KEY_CERT_SIGN: |
138 | case CKA_TRUST_CRL_SIGN: |
139 | |
140 | case CKA_TRUST_SERVER_AUTH: |
141 | case CKA_TRUST_CLIENT_AUTH: |
142 | case CKA_TRUST_CODE_SIGNING: |
143 | case CKA_TRUST_EMAIL_PROTECTION: |
144 | case CKA_TRUST_IPSEC_END_SYSTEM: |
145 | case CKA_TRUST_IPSEC_TUNNEL: |
146 | case CKA_TRUST_IPSEC_USER: |
147 | case CKA_TRUST_TIME_STAMPING: |
148 | case CKA_TRUST_STEP_UP_APPROVED: |
149 | return PR_TRUE; |
150 | default: |
151 | break; |
152 | } |
153 | return PR_FALSE; |
154 | } |
155 | |
156 | |
157 | static PRBool |
158 | isPrivateAttribute(CK_ATTRIBUTE_TYPE type) |
159 | { |
160 | switch (type) { |
161 | case CKA_VALUE: |
162 | case CKA_PRIVATE_EXPONENT: |
163 | case CKA_PRIME_1: |
164 | case CKA_PRIME_2: |
165 | case CKA_EXPONENT_1: |
166 | case CKA_EXPONENT_2: |
167 | case CKA_COEFFICIENT: |
168 | return PR_TRUE; |
169 | default: |
170 | break; |
171 | } |
172 | return PR_FALSE; |
173 | } |
174 | |
175 | |
176 | static PRBool |
177 | isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type) |
178 | { |
179 | switch (type) { |
180 | case CKA_MODULUS: |
181 | case CKA_PUBLIC_EXPONENT: |
182 | case CKA_CERT_SHA1_HASH: |
183 | case CKA_CERT_MD5_HASH: |
184 | case CKA_TRUST_SERVER_AUTH: |
185 | case CKA_TRUST_CLIENT_AUTH: |
186 | case CKA_TRUST_EMAIL_PROTECTION: |
187 | case CKA_TRUST_CODE_SIGNING: |
188 | case CKA_TRUST_STEP_UP_APPROVED: |
189 | case CKA_NSS_OVERRIDE_EXTENSIONS: |
190 | return PR_TRUE; |
191 | default: |
192 | break; |
193 | } |
194 | return PR_FALSE; |
195 | } |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | static CK_ULONG |
202 | sdbULong2ULong(unsigned char *data) |
203 | { |
204 | int i; |
205 | CK_ULONG value = 0; |
206 | |
207 | for (i = 0; i < SDB_ULONG_SIZE; i++) { |
208 | value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE - 1 - i) * PR_BITS_PER_BYTE); |
209 | } |
210 | return value; |
211 | } |
212 | |
213 | |
214 | SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
215 | |
216 | typedef struct EncryptedDataInfoStr { |
217 | SECAlgorithmID algorithm; |
218 | SECItem encryptedData; |
219 | } EncryptedDataInfo; |
220 | |
221 | static const SEC_ASN1Template encryptedDataInfoTemplate[] = { |
222 | { SEC_ASN1_SEQUENCE, |
223 | 0, NULL, sizeof(EncryptedDataInfo) }, |
224 | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
225 | offsetof(EncryptedDataInfo, algorithm), |
226 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
227 | { SEC_ASN1_OCTET_STRING, |
228 | offsetof(EncryptedDataInfo, encryptedData) }, |
229 | { 0 } |
230 | }; |
231 | |
232 | typedef struct PBEParameterStr { |
233 | SECAlgorithmID prfAlg; |
234 | SECItem salt; |
235 | SECItem iteration; |
236 | SECItem keyLength; |
237 | } PBEParameter; |
238 | |
239 | static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = { |
240 | { SEC_ASN1_SEQUENCE, |
241 | 0, NULL, sizeof(PBEParameter) }, |
242 | { SEC_ASN1_OCTET_STRING, |
243 | offsetof(PBEParameter, salt) }, |
244 | { SEC_ASN1_INTEGER, |
245 | offsetof(PBEParameter, iteration) }, |
246 | { 0 } |
247 | }; |
248 | |
249 | static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = { |
250 | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, |
251 | { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, |
252 | { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, |
253 | { 0 } |
254 | }; |
255 | |
256 | static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = { |
257 | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, |
258 | |
259 | |
260 | { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, |
261 | { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, |
262 | { SEC_ASN1_INTEGER, offsetof(PBEParameter, keyLength) }, |
263 | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
264 | offsetof(PBEParameter, prfAlg), |
265 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
266 | { 0 } |
267 | }; |
268 | |
269 | typedef struct Pkcs5v2PBEParameterStr { |
270 | SECAlgorithmID keyParams; |
271 | SECAlgorithmID algParams; |
272 | } Pkcs5v2PBEParameter; |
273 | |
274 | static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = { |
275 | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(Pkcs5v2PBEParameter) }, |
276 | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
277 | offsetof(Pkcs5v2PBEParameter, keyParams), |
278 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
279 | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
280 | offsetof(Pkcs5v2PBEParameter, algParams), |
281 | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
282 | { 0 } |
283 | }; |
284 | |
285 | static inline PRBool |
286 | isPKCS12PBE(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_TRUE; |
296 | default: |
297 | break; |
298 | } |
299 | return PR_FALSE; |
300 | } |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | const char * |
307 | makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType) |
308 | { |
309 | static char nss_name[256]; |
310 | const char *name = NULL; |
311 | if ((attribute >= CKA_NSS) && (attribute < 0xffffffffUL)) { |
312 | sprintf(nss_name, "%s+%d", nameType, (int)(attribute - CKA_NSS)); |
313 | name = nss_name; |
314 | } |
315 | return name; |
316 | } |
317 | |
318 | |
319 | const char * |
320 | AttributeName(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 | |
331 | const char * |
332 | ErrorName(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 | |
342 | const char * |
343 | oid2string(SECOidTag alg) |
344 | { |
345 | const char *oidstring = SECOID_FindOIDTagDescription(alg); |
346 | const char *def = "Invalid oid tag"; |
347 | return oidstring ? oidstring : def; |
348 | } |
349 | |
350 | |
351 | #define ASCCHAR(val) ((val) >= ' ' && (val) <= 0x7e ? (val) : '.') |
352 | #define LINE_LENGTH 16 |
353 | void |
354 | dumpValue(const unsigned char *v, int len) |
355 | { |
356 | int i, next = 0; |
357 | char string[LINE_LENGTH + 1]; |
358 | char space[LINE_LENGTH * 2 + 1]; |
359 | char *nl = ""; |
360 | char *sp = ""; |
361 | PORT_Memset(string, 0, sizeof(string)); |
362 | |
363 | for (i = 0; i < len; i++) { |
364 | if ((i % LINE_LENGTH) == 0) { |
365 | printf("%s%s%s ", sp, string, nl); |
366 | PORT_Memset(string, 0, sizeof(string)); |
367 | next = 0; |
368 | nl = "\n"; |
369 | sp = " "; |
370 | } |
371 | printf("%02x", v[i]); |
372 | string[next++] = ASCCHAR(v[i]); |
373 | } |
374 | PORT_Memset(space, 0, sizeof(space)); |
375 | i = LINE_LENGTH - (len % LINE_LENGTH); |
376 | if (i != LINE_LENGTH) { |
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 | |
387 | void |
388 | dumpPKCS(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_FALSE; |
402 | } |
403 | |
404 | data.data = val; |
405 | data.len = len; |
406 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
407 | if (arena == NULL) { |
408 | printf("Couldn't allocate arena\n"); |
409 | return; |
410 | } |
411 | |
412 | |
413 | PORT_Memset(&pbeParam, 0, sizeof(pbeParam)); |
414 | pbeParam.keyLength.data = &zero; |
415 | pbeParam.keyLength.len = sizeof(zero); |
416 | SECOID_SetAlgorithmID(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL); |
417 | |
418 | |
419 | rv = SEC_QuickDERDecodeItem(arena, &edi, encryptedDataInfoTemplate, &data); |
420 | if (rv != SECSuccess) { |
421 | printf("Encrypted Data, failed to decode\n"); |
422 | dumpValue(val, len); |
423 | PORT_FreeArena(arena, PR_FALSE); |
424 | return; |
425 | } |
426 | |
427 | alg = SECOID_GetAlgorithmTag(&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_QuickDERDecodeItem(arena, ¶m, |
434 | pkcs5v2PBES2ParameterTemplate, |
435 | &edi.algorithm.parameters); |
436 | if (rv != SECSuccess) { |
437 | printf("%s, failed to decode\n", typeName); |
438 | dumpValue(val, len); |
439 | PORT_FreeArena(arena, PR_FALSE); |
440 | return; |
441 | } |
442 | palg = SECOID_GetAlgorithmTag(¶m.algParams); |
443 | printf("%s alg=%s ", typeName, oid2string(palg)); |
444 | if (hasSig && palg == SEC_OID_AES_256_CBC) { |
445 | *hasSig = PR_TRUE; |
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_QuickDERDecodeItem(arena, &pbeParam, |
460 | template, |
461 | &edi.algorithm.parameters); |
462 | if (rv != SECSuccess) { |
463 | printf("( failed to decode params)\n"); |
464 | PORT_FreeArena(arena, PR_FALSE); |
465 | return; |
466 | } |
467 | |
468 | iter = DER_GetInteger(&pbeParam.iteration); |
469 | keyLen = DER_GetInteger(&pbeParam.keyLength); |
470 | prfAlg = SECOID_GetAlgorithmTag(&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 | |
477 | dumpValue(edi.encryptedData.data, edi.encryptedData.len); |
478 | PORT_FreeArena(arena, PR_FALSE); |
479 | } |
480 | |
481 | |
482 | |
483 | void |
484 | dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value) |
485 | { |
486 | const char *nameType = "CK_NSS"; |
487 | ConstType constType = ConstNone; |
488 | const char *valueName = NULL; |
489 | |
490 | switch (type) { |
491 | case CKA_CLASS: |
492 | nameType = "CKO_NSS"; |
493 | constType = ConstObject; |
494 | break; |
495 | case CKA_CERTIFICATE_TYPE: |
496 | nameType = "CKC_NSS"; |
497 | constType = ConstCertType; |
498 | break; |
499 | case CKA_KEY_TYPE: |
500 | nameType = "CKK_NSS"; |
501 | constType = ConstKeyType; |
502 | break; |
503 | case CKA_MECHANISM_TYPE: |
504 | nameType = "CKM_NSS"; |
505 | constType = ConstMechanism; |
506 | break; |
507 | case CKA_TRUST_SERVER_AUTH: |
508 | case CKA_TRUST_CLIENT_AUTH: |
509 | case CKA_TRUST_CODE_SIGNING: |
510 | case CKA_TRUST_EMAIL_PROTECTION: |
511 | case CKA_TRUST_IPSEC_END_SYSTEM: |
512 | case CKA_TRUST_IPSEC_TUNNEL: |
513 | case CKA_TRUST_IPSEC_USER: |
514 | case CKA_TRUST_TIME_STAMPING: |
515 | nameType = "CKT_NSS"; |
516 | constType = ConstTrust; |
517 | break; |
518 | default: |
519 | break; |
520 | } |
521 | |
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 | |
536 | static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x"; |
537 | void |
538 | dumpSignature(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_LEN]; |
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); |
557 | if ((crv != CKR_OK) && isKey) { |
558 | sprintf(id, META_SIG_TEMPLATE, |
559 | isKey ? "key" : "cert", (unsigned int)(objectID | SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE), |
560 | (unsigned int)attribute); |
561 | crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL); |
562 | } |
563 | if (crv != CKR_OK) { |
564 | printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int)crv); |
565 | return; |
566 | } |
567 | dumpPKCS(signText.data, signText.len, NULL); |
568 | return; |
569 | } |
570 | |
571 | |
572 | void |
573 | dumpAttribute(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) { |
579 | printf("NULL (%d)\n", (int)template->ulValueLen); |
580 | return; |
581 | } |
582 | if (template->ulValueLen == SDB_ULONG_SIZE && 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)); |
598 | break; |
599 | } |
600 | return; |
601 | } |
602 | if (isKey && isPrivateAttribute(attribute)) { |
603 | PRBool hasSig = PR_FALSE; |
604 | dumpPKCS(template->pValue, template->ulValueLen, &hasSig); |
605 | if (hasSig) { |
606 | dumpSignature(attribute, keydb, isKey, id, PR_TRUE); |
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 | |
618 | void |
619 | dumpObject(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; |
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; |
632 | template.ulValueLen = 0; |
633 | crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1); |
634 | |
635 | if (crv != CKR_OK) { |
636 | if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { |
637 | PR_fprintf(PR_STDERR, " " |
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_Alloc(template.ulValueLen); |
649 | template.pValue = alloc; |
650 | } |
651 | if (template.pValue == NULL) { |
652 | PR_fprintf(PR_STDERR, " " |
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_OK) { |
661 | if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { |
662 | PR_fprintf(PR_STDERR, " " |
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_Free(alloc); |
669 | alloc = NULL; |
670 | } |
671 | continue; |
672 | } |
673 | |
674 | dumpAttribute(&template, keydb, isKey, id); |
675 | dumpSignature(template.type, keydb, isKey, id, PR_FALSE); |
676 | if (alloc) { |
677 | PORT_Free(alloc); |
678 | alloc = NULL; |
679 | } |
680 | } |
681 | } |
682 | |
683 | |
684 | void |
685 | dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey) |
686 | { |
687 | SDBFind *findHandle = NULL; |
688 | CK_BBOOL isTrue = 1; |
689 | CK_ATTRIBUTE allObjectTemplate = { CKA_TOKEN, NULL, 1 }; |
690 | CK_ULONG allObjectTemplateCount = 1; |
691 | PRBool recordFound = PR_FALSE; |
692 | CK_RV crv = CKR_OK; |
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_FALSE; |
702 | crv = (*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount); |
703 | if ((crv == CKR_OK) && (objectCount == 1)) { |
704 | recordFound = PR_TRUE; |
705 | dumpObject(id, db, keydb, isKey); |
706 | } |
707 | } while (recordFound); |
708 | if (crv != CKR_OK) { |
709 | PR_fprintf(PR_STDERR, |
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 | |
716 | static char * |
717 | secu_ConfigDirectory(const char *base) |
718 | { |
719 | static PRBool initted = PR_FALSE; |
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 || *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_TRUE; |
743 | return buf; |
744 | } |
745 | |
746 | int |
747 | main(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; |
755 | SDB *keydb = NULL; |
756 | PRBool isNew = PR_FALSE; |
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 ? progName + 1 : argv[0]; |
| |
| |
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_Strdup(optstate->value); |
776 | break; |
777 | |
778 | case 'c': |
779 | certPrefix = PORT_Strdup(optstate->value); |
780 | break; |
781 | |
782 | case 'k': |
783 | keyPrefix = PORT_Strdup(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 | |
|
| |
797 | Usage(); |
798 | |
799 | if (dbDir) { |
| |
800 | char *tmp = dbDir; |
801 | dbDir = secu_ConfigDirectory(tmp); |
802 | PORT_Free(tmp); |
803 | } else { |
804 | dbDir = secu_ConfigDirectory(NULL); |
805 | } |
806 | PR_fprintf(PR_STDERR, "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_STDERR, |
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_RDONLY, &certdb, &keydb, &isNew); |
819 | if (crv != CKR_OK) { |
820 | PR_fprintf(PR_STDERR, |
821 | "Couldn't open databased in %s, error=%s (0x%08x)\n", |
822 | dbDir, ErrorName(crv), (int)crv); |
823 | return 1; |
824 | } |
825 | |
826 | |
827 | dumpDB(certdb, "CertDB", keydb, PR_FALSE); |
828 | dumpDB(keydb, "KeyDB", keydb, PR_TRUE); |
829 | return 0; |
830 | } |