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 p7sign.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/p7sign -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/p7sign -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 -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/seccmd -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 p7sign.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "nspr.h" |
11 | #include "plgetopt.h" |
12 | #include "secutil.h" |
13 | #include "secpkcs7.h" |
14 | #include "cert.h" |
15 | #include "certdb.h" |
16 | #include "sechash.h" /* for HASH_GetHashObject() */ |
17 | #include "nss.h" |
18 | #include "pk11func.h" |
19 | |
20 | #if defined(XP_UNIX) |
21 | #include <unistd.h> |
22 | #endif |
23 | |
24 | #include <stdio.h> |
25 | #include <string.h> |
26 | |
27 | #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4)) |
28 | extern int fread(char *, size_t, size_t, FILE *); |
29 | extern int fwrite(char *, size_t, size_t, FILE *); |
30 | extern int fprintf(FILE *, char *, ...); |
31 | #endif |
32 | |
33 | static secuPWData pwdata = { PW_NONE, 0 }; |
34 | |
35 | static void |
36 | Usage(char *progName) |
37 | { |
38 | HASH_HashType hashAlg; |
39 | |
40 | fprintf(stderr, |
41 | "Usage: %s -k keyname [-d keydir] [-i input] [-o output] [-e]\n", |
42 | progName); |
43 | fprintf(stderr, |
44 | " %*s [-p password|-f password file] [-a hash] [-u certusage]\n", |
45 | (int)strlen(progName), ""); |
46 | fprintf(stderr, "%-20s Nickname of key to use for signature\n", |
47 | "-k keyname"); |
48 | fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", |
49 | "-d keydir"); |
50 | fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n", |
51 | "-i input"); |
52 | fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", |
53 | "-o output"); |
54 | fprintf(stderr, "%-20s Encapsulate content in signature message\n", |
55 | "-e"); |
56 | fprintf(stderr, "%-20s Password to the key databse\n", "-p password"); |
57 | fprintf(stderr, "%-20s File to read password from\n", "-f password file"); |
58 | fprintf(stderr, "%-20s Use case-insensitive hash algorithm (default: SHA-1)\n", |
59 | "-a hash"); |
60 | fprintf(stderr, "%-25s ", ""); |
61 | for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL; ++hashAlg) |
62 | fprintf(stderr, "%s%s", hashAlg == HASH_AlgNULL + 1 ? "" : ", ", |
63 | SECOID_FindOIDByTag(HASH_GetHashOidTagByHashType(hashAlg))->desc); |
64 | fputc('\n', stderr); |
65 | fprintf(stderr, "%-20s Sign for usage (default: certUsageEmailSigner)\n", |
66 | "-u certusage"); |
67 | fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", ""); |
68 | fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", ""); |
69 | fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", ""); |
70 | fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", ""); |
71 | fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", ""); |
72 | fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", ""); |
73 | fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", ""); |
74 | fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", ""); |
75 | fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", ""); |
76 | fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", ""); |
77 | fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", ""); |
78 | fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", ""); |
79 | fprintf(stderr, "%-25s 12 - certUsageIPsec\n", ""); |
80 | exit(-1); |
81 | } |
82 | |
83 | static void |
84 | SignOut(void *arg, const char *buf, unsigned long len) |
85 | { |
86 | FILE *out; |
87 | |
88 | out = (FILE *)arg; |
89 | fwrite(buf, len, 1, out); |
90 | } |
91 | |
92 | static int |
93 | CreateDigest(SECItem *data, char *digestdata, unsigned int *len, |
94 | unsigned int maxlen, HASH_HashType hashAlg) |
95 | { |
96 | const SECHashObject *hashObj; |
97 | void *hashcx; |
98 | |
99 | hashObj = HASH_GetHashObject(hashAlg); |
100 | |
101 | hashcx = (*hashObj->create)(); |
102 | if (hashcx == NULL) |
103 | return -1; |
104 | |
105 | (*hashObj->begin)(hashcx); |
106 | (*hashObj->update)(hashcx, data->data, data->len); |
107 | (*hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen); |
108 | (*hashObj->destroy)(hashcx, PR_TRUE); |
109 | return 0; |
110 | } |
111 | |
112 | static int |
113 | SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, |
114 | PRBool encapsulated, HASH_HashType hashAlg, SECOidTag hashAlgOid, |
115 | SECCertUsage usage) |
116 | { |
117 | char digestdata[HASH_LENGTH_MAX]; |
118 | unsigned int len; |
119 | SECItem digest, data2sign; |
120 | SEC_PKCS7ContentInfo *cinfo; |
121 | SECStatus rv; |
122 | |
123 | if (outFile == NULL || inFile == NULL || cert == NULL) |
124 | return -1; |
125 | |
126 | |
127 | if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE, |
128 | PR_FALSE) != SECSuccess) |
129 | return -1; |
130 | |
131 | if (!encapsulated) { |
132 | |
133 | |
134 | |
135 | |
136 | if (CreateDigest(&data2sign, digestdata, &len, |
137 | sizeof(digestdata), hashAlg) < 0) { |
138 | SECITEM_FreeItem(&data2sign, PR_FALSE); |
139 | return -1; |
140 | } |
141 | digest.data = (unsigned char *)digestdata; |
142 | digest.len = len; |
143 | } |
144 | |
145 | cinfo = SEC_PKCS7CreateSignedData(cert, usage, NULL, |
146 | hashAlgOid, |
147 | encapsulated ? NULL : &digest, |
148 | NULL, NULL); |
149 | if (cinfo == NULL) { |
150 | SECITEM_FreeItem(&data2sign, PR_FALSE); |
151 | return -1; |
152 | } |
153 | |
154 | if (encapsulated) { |
155 | SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len); |
156 | } |
157 | |
158 | rv = SEC_PKCS7IncludeCertChain(cinfo, NULL); |
159 | if (rv != SECSuccess) { |
160 | SEC_PKCS7DestroyContentInfo(cinfo); |
161 | SECITEM_FreeItem(&data2sign, PR_FALSE); |
162 | return -1; |
163 | } |
164 | |
165 | rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, |
166 | NULL, &pwdata); |
167 | |
168 | SECITEM_FreeItem(&data2sign, PR_FALSE); |
169 | SEC_PKCS7DestroyContentInfo(cinfo); |
170 | |
171 | if (rv != SECSuccess) |
172 | return -1; |
173 | |
174 | return 0; |
175 | } |
176 | |
177 | int |
178 | main(int argc, char **argv) |
179 | { |
180 | char *progName; |
181 | FILE *outFile; |
182 | PRFileDesc *inFile; |
183 | char *keyName = NULL; |
184 | CERTCertDBHandle *certHandle; |
185 | CERTCertificate *cert = NULL; |
186 | PRBool encapsulated = PR_FALSE; |
187 | HASH_HashType hashAlg = HASH_AlgSHA1; |
188 | SECOidTag hashAlgOid = SEC_OID_SHA1; |
189 | SECCertUsage usage = certUsageEmailSigner; |
190 | PLOptState *optstate; |
191 | PLOptStatus status; |
192 | SECStatus rv; |
193 | |
194 | progName = strrchr(argv[0], '/'); |
195 | progName = progName ? progName + 1 : argv[0]; |
| 1 | Assuming 'progName' is non-null | |
|
| |
196 | |
197 | inFile = NULL; |
198 | outFile = NULL; |
199 | keyName = NULL; |
200 | |
201 | |
202 | |
203 | |
204 | optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:a:u:"); |
205 | while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
| 3 | | Assuming the condition is true | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 7 | | Execution continues on line 205 | |
|
| 8 | | Assuming the condition is true | |
|
| 9 | | Loop condition is true. Entering loop body | |
|
206 | switch (optstate->option) { |
| 5 | | Control jumps to 'case 107:' at line 229 | |
|
| 10 | | Control jumps to 'case 111:' at line 233 | |
|
207 | case '?': |
208 | Usage(progName); |
209 | break; |
210 | |
211 | case 'e': |
212 | |
213 | encapsulated = PR_TRUE; |
214 | break; |
215 | |
216 | case 'd': |
217 | SECU_ConfigDirectory(optstate->value); |
218 | break; |
219 | |
220 | case 'i': |
221 | inFile = PR_Open(optstate->value, PR_RDONLY, 0); |
222 | if (!inFile) { |
223 | fprintf(stderr, "%s: unable to open \"%s\" for reading\n", |
224 | progName, optstate->value); |
225 | return -1; |
226 | } |
227 | break; |
228 | |
229 | case 'k': |
230 | keyName = strdup(optstate->value); |
| |
231 | break; |
232 | |
233 | case 'o': |
234 | outFile = fopen(optstate->value, "wb"); |
235 | if (!outFile) { |
| 11 | | Assuming 'outFile' is null | |
|
| |
236 | fprintf(stderr, "%s: unable to open \"%s\" for writing\n", |
| 13 | | Potential leak of memory pointed to by 'keyName' |
|
237 | progName, optstate->value); |
238 | return -1; |
239 | } |
240 | break; |
241 | case 'p': |
242 | pwdata.source = PW_PLAINTEXT; |
243 | pwdata.data = strdup(optstate->value); |
244 | break; |
245 | |
246 | case 'f': |
247 | pwdata.source = PW_FROMFILE; |
248 | pwdata.data = PORT_Strdup(optstate->value); |
249 | break; |
250 | |
251 | case 'a': |
252 | for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL; |
253 | ++hashAlg) { |
254 | hashAlgOid = HASH_GetHashOidTagByHashType(hashAlg); |
255 | if (!PORT_Strcasecmp(optstate->value, |
256 | SECOID_FindOIDByTag(hashAlgOid)->desc)) |
257 | break; |
258 | } |
259 | if (hashAlg == HASH_AlgTOTAL) |
260 | Usage(progName); |
261 | break; |
262 | |
263 | case 'u': |
264 | usage = atoi(optstate->value); |
265 | if (usage < certUsageSSLClient || usage > certUsageIPsec) |
266 | Usage(progName); |
267 | break; |
268 | } |
269 | } |
270 | PL_DestroyOptState(optstate); |
271 | |
272 | if (!keyName) |
273 | Usage(progName); |
274 | |
275 | if (!inFile) |
276 | inFile = PR_STDIN; |
277 | if (!outFile) |
278 | outFile = stdout; |
279 | |
280 | |
281 | PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
282 | rv = NSS_Init(SECU_ConfigDirectory(NULL)); |
283 | if (rv != SECSuccess) { |
284 | SECU_PrintPRandOSError(progName); |
285 | goto loser; |
286 | } |
287 | |
288 | PK11_SetPasswordFunc(SECU_GetModulePassword); |
289 | |
290 | |
291 | certHandle = CERT_GetDefaultCertDB(); |
292 | if (certHandle == NULL) { |
293 | rv = SECFailure; |
294 | goto loser; |
295 | } |
296 | |
297 | |
298 | cert = SECU_FindCertByNicknameOrFilename(certHandle, keyName, PR_FALSE, NULL); |
299 | if (cert == NULL) { |
300 | SECU_PrintError(progName, |
301 | "the corresponding cert for key \"%s\" does not exist", |
302 | keyName); |
303 | rv = SECFailure; |
304 | goto loser; |
305 | } |
306 | |
307 | if (SignFile(outFile, inFile, cert, encapsulated, |
308 | hashAlg, hashAlgOid, usage)) { |
309 | SECU_PrintError(progName, "problem signing data"); |
310 | rv = SECFailure; |
311 | goto loser; |
312 | } |
313 | |
314 | loser: |
315 | if (pwdata.data) { |
316 | PORT_Free(pwdata.data); |
317 | } |
318 | if (keyName) { |
319 | PORT_Free(keyName); |
320 | } |
321 | if (cert) { |
322 | CERT_DestroyCertificate(cert); |
323 | } |
324 | if (inFile && inFile != PR_STDIN) { |
325 | PR_Close(inFile); |
326 | } |
327 | if (outFile && outFile != stdout) { |
328 | fclose(outFile); |
329 | } |
330 | if (NSS_Shutdown() != SECSuccess) { |
331 | SECU_PrintError(progName, "NSS shutdown:"); |
332 | exit(1); |
333 | } |
334 | |
335 | return (rv != SECSuccess); |
336 | } |