Bug Summary

File:s/cmd/pk1sign/pk1sign.c
Warning:line 237, column 21
Potential leak of memory pointed to by 'keyName'

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 pk1sign.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/pk1sign -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/pk1sign -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 pk1sign.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 * pk1sign
7 */
8
9#include "nspr.h"
10#include "plgetopt.h"
11#include "secutil.h"
12#include "secpkcs7.h"
13#include "cert.h"
14#include "certdb.h"
15#include "sechash.h" /* for HASH_GetHashObject() */
16#include "nss.h"
17#include "pk11func.h"
18#include "cryptohi.h"
19#include "plbase64.h"
20
21#if defined(XP_UNIX1)
22#include <unistd.h>
23#endif
24
25#include <stdio.h>
26#include <string.h>
27
28#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
29extern int fread(char *, size_t, size_t, FILE *);
30extern int fwrite(char *, size_t, size_t, FILE *);
31extern int fprintf(FILE *, char *, ...);
32#endif
33
34static secuPWData pwdata = { PW_NONE, 0 };
35
36SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
37
38SEC_ASN1Template CERTSignatureDataTemplate[] = {
39 { SEC_ASN1_SEQUENCE0x10,
40 0, NULL((void*)0), sizeof(CERTSignedData) },
41 { SEC_ASN1_INLINE0x00800,
42 offsetof(CERTSignedData, signatureAlgorithm)__builtin_offsetof(CERTSignedData, signatureAlgorithm),
43 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
44 { SEC_ASN1_BIT_STRING0x03,
45 offsetof(CERTSignedData, signature)__builtin_offsetof(CERTSignedData, signature) },
46 { 0 }
47};
48
49static void
50Usage(char *progName)
51{
52 fprintf(stderrstderr,
53 "Usage: %s -k keyname [-d keydir] [-i input] [-o output]\n",
54 progName);
55 fprintf(stderrstderr, "%-20s Nickname of key to use for signature\n",
56 "-k keyname");
57 fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n",
58 "-d keydir");
59 fprintf(stderrstderr, "%-20s Define an input file to use (default is stdin)\n",
60 "-i input");
61 fprintf(stderrstderr, "%-20s Define an output file to use (default is stdout)\n",
62 "-o output");
63 fprintf(stderrstderr, "%-20s Password to the key databse\n", "-p");
64 fprintf(stderrstderr, "%-20s password file\n", "-f");
65 exit(-1);
66}
67
68static int
69ExportPublicKey(FILE *outFile, CERTCertificate *cert)
70{
71 char *data;
72 SECKEYPublicKey *publicKey;
73 SECItem *item;
74
75 if (!cert)
76 return -1;
77
78 publicKey = CERT_ExtractPublicKey(cert);
79 if (!publicKey)
80 return -1;
81
82 item = SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey);
83 SECKEY_DestroyPublicKey(publicKey);
84 if (!item)
85 return -1;
86
87 data = PL_Base64Encode((const char *)item->data, item->len, NULL((void*)0));
88 SECITEM_FreeItemSECITEM_FreeItem_Util(item, PR_TRUE1);
89 if (!data)
90 return -1;
91
92 fputs("pubkey:\n", outFile);
93 fputs(data, outFile);
94 fputs("\n", outFile);
95 PR_Free(data);
96
97 return 0;
98}
99
100static int
101SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert)
102{
103 SECItem data2sign;
104 SECStatus rv;
105 SECOidTag algID;
106 CERTSignedData sd;
107 SECKEYPrivateKey *privKey = NULL((void*)0);
108 char *data = NULL((void*)0);
109 PLArenaPool *arena = NULL((void*)0);
110 SECItem *result = NULL((void*)0);
111 int returnValue = 0;
112
113 if (outFile == NULL((void*)0) || inFile == NULL((void*)0) || cert == NULL((void*)0)) {
114 return -1;
115 }
116
117 /* suck the file in */
118 if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE0,
119 PR_FALSE0) != SECSuccess) {
120 return -1;
121 }
122
123 privKey = NULL((void*)0);
124 privKey = PK11_FindKeyByAnyCert(cert, NULL((void*)0));
125 if (!privKey) {
126 returnValue = -1;
127 goto loser;
128 }
129
130 algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
131 if (algID == SEC_OID_UNKNOWN) {
132 returnValue = -1;
133 goto loser;
134 }
135
136 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
137
138 PORT_Memsetmemset(&sd, 0, sizeof(CERTSignedData));
139
140 rv = SEC_SignData(&(sd.signature), data2sign.data, data2sign.len, privKey, algID);
141 if (rv != SECSuccess) {
142 fprintf(stderrstderr, "Could not sign.\n");
143 returnValue = -1;
144 goto loser;
145 }
146 sd.signature.len = sd.signature.len << 3;
147
148 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &sd.signatureAlgorithm, algID, 0);
149 if (rv != SECSuccess) {
150 fprintf(stderrstderr, "Could not set alg id.\n");
151 returnValue = -1;
152 goto loser;
153 }
154
155 result = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, NULL((void*)0), &sd, CERTSignatureDataTemplate);
156 SECITEM_FreeItemSECITEM_FreeItem_Util(&(sd.signature), PR_FALSE0);
157
158 if (!result) {
159 fprintf(stderrstderr, "Could not encode.\n");
160 returnValue = -1;
161 goto loser;
162 }
163
164 data = PL_Base64Encode((const char *)result->data, result->len, NULL((void*)0));
165 if (!data) {
166 returnValue = -1;
167 goto loser;
168 }
169
170 fputs("signature:\n", outFile);
171 fputs(data, outFile);
172 fputs("\n", outFile);
173 ExportPublicKey(outFile, cert);
174
175loser:
176 if (privKey) {
177 SECKEY_DestroyPrivateKey(privKey);
178 }
179 if (data) {
180 PR_Free(data);
181 }
182 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
183
184 return returnValue;
185}
186
187int
188main(int argc, char **argv)
189{
190 char *progName;
191 FILE *outFile;
192 PRFileDesc *inFile;
193 char *keyName = NULL((void*)0);
194 CERTCertDBHandle *certHandle;
195 CERTCertificate *cert = NULL((void*)0);
196 PLOptState *optstate;
197 PLOptStatus status;
198 SECStatus rv;
199
200 progName = strrchr(argv[0], '/');
201 progName = progName ? progName + 1 : argv[0];
1
Assuming 'progName' is non-null
2
'?' condition is true
202
203 inFile = NULL((void*)0);
204 outFile = NULL((void*)0);
205 keyName = NULL((void*)0);
206
207 /*
208 * Parse command line arguments
209 */
210 optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:");
211 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 211
8
Assuming the condition is true
9
Loop condition is true. Entering loop body
212 switch (optstate->option) {
5
Control jumps to 'case 107:' at line 230
10
Control jumps to 'case 111:' at line 234
213 case '?':
214 Usage(progName);
215 break;
216
217 case 'd':
218 SECU_ConfigDirectory(optstate->value);
219 break;
220
221 case 'i':
222 inFile = PR_Open(optstate->value, PR_RDONLY0x01, 0);
223 if (!inFile) {
224 fprintf(stderrstderr, "%s: unable to open \"%s\" for reading\n",
225 progName, optstate->value);
226 return -1;
227 }
228 break;
229
230 case 'k':
231 keyName = strdup(optstate->value);
6
Memory is allocated
232 break;
233
234 case 'o':
235 outFile = fopen(optstate->value, "wb");
236 if (!outFile) {
11
Assuming 'outFile' is null
12
Taking true branch
237 fprintf(stderrstderr, "%s: unable to open \"%s\" for writing\n",
13
Potential leak of memory pointed to by 'keyName'
238 progName, optstate->value);
239 return -1;
240 }
241 break;
242 case 'p':
243 pwdata.source = PW_PLAINTEXT;
244 pwdata.data = strdup(optstate->value);
245 break;
246
247 case 'f':
248 pwdata.source = PW_FROMFILE;
249 pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value);
250 break;
251 }
252 }
253
254 if (!keyName)
255 Usage(progName);
256
257 if (!inFile)
258 inFile = PR_STDINPR_GetSpecialFD(PR_StandardInput);
259 if (!outFile)
260 outFile = stdoutstdout;
261
262 /* Call the initialization routines */
263 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
264 rv = NSS_Init(SECU_ConfigDirectory(NULL((void*)0)));
265 if (rv != SECSuccess) {
266 SECU_PrintPRandOSError(progName);
267 goto loser;
268 }
269
270 PK11_SetPasswordFunc(SECU_GetModulePassword);
271
272 /* open cert database */
273 certHandle = CERT_GetDefaultCertDB();
274 if (certHandle == NULL((void*)0)) {
275 rv = SECFailure;
276 goto loser;
277 }
278
279 /* find cert */
280 cert = CERT_FindCertByNickname(certHandle, keyName);
281 if (cert == NULL((void*)0)) {
282 SECU_PrintError(progName,
283 "the corresponding cert for key \"%s\" does not exist",
284 keyName);
285 rv = SECFailure;
286 goto loser;
287 }
288
289 if (SignFile(outFile, inFile, cert)) {
290 SECU_PrintError(progName, "problem signing data");
291 rv = SECFailure;
292 goto loser;
293 }
294
295loser:
296 if (pwdata.data) {
297 PORT_FreePORT_Free_Util(pwdata.data);
298 }
299 if (keyName) {
300 PORT_FreePORT_Free_Util(keyName);
301 }
302 if (cert) {
303 CERT_DestroyCertificate(cert);
304 }
305 if (inFile && inFile != PR_STDINPR_GetSpecialFD(PR_StandardInput)) {
306 PR_Close(inFile);
307 }
308 if (outFile && outFile != stdoutstdout) {
309 fclose(outFile);
310 }
311 if (NSS_Shutdown() != SECSuccess) {
312 SECU_PrintError(progName, "NSS shutdown:");
313 exit(1);
314 }
315
316 return (rv != SECSuccess);
317}