Bug Summary

File:s/cmd/signtool/certgen.c
Warning:line 245, column 23
Null pointer passed to 1st parameter expecting 'nonnull'

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 certgen.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/signtool -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/signtool -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 certgen.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#include "signtool.h"
6
7#include "secoid.h"
8#include "cryptohi.h"
9#include "certdb.h"
10
11static char *GetSubjectFromUser(unsigned long serial);
12static CERTCertificate *GenerateSelfSignedObjectSigningCert(char *nickname,
13 CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
14 char *token);
15static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
16 CERTCertificate *cert, char *trusts);
17static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
18static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
19static CERTCertificate *install_cert(CERTCertDBHandle *db, SECItem *derCert,
20 char *nickname);
21static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
22 SECKEYPrivateKey **privk, int keysize);
23static CERTCertificateRequest *make_cert_request(char *subject,
24 SECKEYPublicKey *pubk);
25static CERTCertificate *make_cert(CERTCertificateRequest *req,
26 unsigned long serial, CERTName *ca_subject);
27static void output_ca_cert(CERTCertificate *cert, CERTCertDBHandle *db);
28
29/***********************************************************************
30 *
31 * G e n e r a t e C e r t
32 *
33 * Runs the whole process of creating a new cert, getting info from the
34 * user, etc.
35 */
36int
37GenerateCert(char *nickname, int keysize, char *token)
38{
39 CERTCertDBHandle *db;
40 CERTCertificate *cert;
41 char *subject;
42 unsigned long serial;
43 char stdinbuf[160];
44
45 /* Print warning about having the browser open */
46 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput) /*always go to console*/,
47 "\nWARNING: Performing this operation while the browser is running could cause"
48 "\ncorruption of your security databases. If the browser is currently running,"
49 "\nyou should exit the browser before continuing this operation. Enter "
50 "\n\"y\" to continue, or anything else to abort: ");
51 pr_fgets(stdinbuf, 160, PR_STDINPR_GetSpecialFD(PR_StandardInput));
52 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\n");
53 if (tolower(stdinbuf[0]) != 'y') {
1
Assuming the condition is false
2
Taking false branch
54 PR_fprintf(errorFD, "Operation aborted at user's request.\n");
55 errorCount++;
56 return -1;
57 }
58
59 db = CERT_GetDefaultCertDB();
60 if (!db) {
3
Assuming 'db' is non-null
4
Taking false branch
61 FatalError("Unable to open certificate database");
62 }
63
64 if (PK11_FindCertFromNickname(nickname, &pwdata)) {
5
Assuming the condition is false
6
Taking false branch
65 PR_fprintf(errorFD,
66 "ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
67 "must choose a different nickname.\n",
68 nickname);
69 errorCount++;
70 exit(ERRX(-1));
71 }
72
73 LL_L2UI(serial, PR_Now())((serial) = (PRUint32)(PR_Now()));
74
75 subject = GetSubjectFromUser(serial);
7
Calling 'GetSubjectFromUser'
76 if (!subject) {
77 FatalError("Unable to get subject from user");
78 }
79
80 cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
81 serial, keysize, token);
82
83 if (cert) {
84 output_ca_cert(cert, db);
85 CERT_DestroyCertificate(cert);
86 }
87
88 PORT_FreePORT_Free_Util(subject);
89 return 0;
90}
91
92#undef VERBOSE_PROMPTS
93
94/*********************************************************************8
95 * G e t S u b j e c t F r o m U s e r
96 *
97 * Construct the subject information line for a certificate by querying
98 * the user on stdin.
99 */
100static char *
101GetSubjectFromUser(unsigned long serial)
102{
103 char buf[STDIN_BUF_SIZE160];
104 char common_name_buf[STDIN_BUF_SIZE160];
105 char *common_name, *state, *orgunit, *country, *org, *locality;
106 char *email, *uid;
107 char *subject;
108 char *cp;
109 int subjectlen = 0;
110
111 common_name = state = orgunit = country = org = locality = email =
112 uid = subject = NULL((void*)0);
113
114 /* Get subject information */
115 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput),
116 "\nEnter certificate information. All fields are optional. Acceptable\n"
117 "characters are numbers, letters, spaces, and apostrophes.\n");
118
119#ifdef VERBOSE_PROMPTS
120 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nCOMMON NAME\n"
121 "Enter the full name you want to give your certificate. (Example: Test-Only\n"
122 "Object Signing Certificate)\n"
123 "-->");
124#else
125 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "certificate common name: ");
126#endif
127 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
8
Assuming the condition is false
9
Taking false branch
128 return NULL((void*)0);
129 }
130 cp = chop(buf);
131 if (*cp == '\0') {
10
Assuming the condition is false
11
Taking false branch
132 snprintf(common_name_buf, sizeof(common_name_buf), "%s (%lu)", DEFAULT_COMMON_NAME"Signtool " "3.101" " Beta" " Testing Certificate",
133 serial);
134 cp = common_name_buf;
135 }
136 common_name = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 6);
137 if (!common_name) {
12
Assuming 'common_name' is non-null
13
Taking false branch
138 out_of_memory();
139 }
140 snprintf(common_name, strlen(cp) + 6, "CN=%s, ", cp);
141 subjectlen += strlen(common_name);
142
143#ifdef VERBOSE_PROMPTS
144 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nORGANIZATION NAME\n"
145 "Enter the name of your organization. For example, this could be the name\n"
146 "of your company.\n"
147 "-->");
148#else
149 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "organization: ");
150#endif
151 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
14
Assuming the condition is false
15
Taking false branch
152 return NULL((void*)0);
153 }
154 cp = chop(buf);
155 if (*cp != '\0') {
16
Assuming the condition is false
17
Taking false branch
156 org = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 5);
157 if (!org) {
158 out_of_memory();
159 }
160 snprintf(org, strlen(cp) + 5, "O=%s, ", cp);
161 subjectlen += strlen(org);
162 }
163
164#ifdef VERBOSE_PROMPTS
165 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nORGANIZATION UNIT\n"
166 "Enter the name of your organization unit. For example, this could be the\n"
167 "name of your department.\n"
168 "-->");
169#else
170 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "organization unit: ");
171#endif
172 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
18
Assuming the condition is false
19
Taking false branch
173 return NULL((void*)0);
174 }
175 cp = chop(buf);
176 if (*cp != '\0') {
20
Assuming the condition is false
21
Taking false branch
177 orgunit = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 6);
178 if (!orgunit) {
179 out_of_memory();
180 }
181 snprintf(orgunit, strlen(cp) + 6, "OU=%s, ", cp);
182 subjectlen += strlen(orgunit);
183 }
184
185#ifdef VERBOSE_PROMPTS
186 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nSTATE\n"
187 "Enter the name of your state or province.\n"
188 "-->");
189#else
190 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "state or province: ");
191#endif
192 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
22
Assuming the condition is false
23
Taking false branch
193 return NULL((void*)0);
194 }
195 cp = chop(buf);
196 if (*cp != '\0') {
24
Assuming the condition is false
25
Taking false branch
197 state = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 6);
198 if (!state) {
199 out_of_memory();
200 }
201 snprintf(state, strlen(cp) + 6, "ST=%s, ", cp);
202 subjectlen += strlen(state);
203 }
204
205#ifdef VERBOSE_PROMPTS
206 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nCOUNTRY\n"
207 "Enter the 2-character abbreviation for the name of your country.\n"
208 "-->");
209#else
210 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "country (must be exactly 2 characters): ");
211#endif
212 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
26
Assuming the condition is false
27
Taking false branch
213 return NULL((void*)0);
214 }
215 cp = chop(cp);
216 if (strlen(cp) != 2) {
28
Assuming the condition is false
29
Taking false branch
217 *cp = '\0'; /* country code must be 2 chars */
218 }
219 if (*cp != '\0') {
30
Assuming the condition is false
31
Taking false branch
220 country = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 5);
221 if (!country) {
222 out_of_memory();
223 }
224 snprintf(country, strlen(cp) + 5, "C=%s, ", cp);
225 subjectlen += strlen(country);
226 }
227
228#ifdef VERBOSE_PROMPTS
229 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nUSERNAME\n"
230 "Enter your system username or UID\n"
231 "-->");
232#else
233 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "username: ");
234#endif
235 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
32
Assuming the condition is false
33
Taking false branch
236 return NULL((void*)0);
237 }
238 cp = chop(buf);
239 if (*cp != '\0') {
34
Assuming the condition is true
35
Taking true branch
240 uid = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 7);
36
Value assigned to 'uid'
241 if (!uid) {
37
Assuming 'uid' is null
38
Taking true branch
242 out_of_memory();
243 }
244 snprintf(uid, strlen(cp) + 7, "UID=%s, ", cp);
245 subjectlen += strlen(uid);
39
Null pointer passed to 1st parameter expecting 'nonnull'
246 }
247
248#ifdef VERBOSE_PROMPTS
249 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "\nEMAIL ADDRESS\n"
250 "Enter your email address.\n"
251 "-->");
252#else
253 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "email address: ");
254#endif
255 if (!fgets(buf, STDIN_BUF_SIZE160, stdinstdin)) {
256 return NULL((void*)0);
257 }
258 cp = chop(buf);
259 if (*cp != '\0') {
260 email = PORT_ZAllocPORT_ZAlloc_Util(strlen(cp) + 5);
261 if (!email) {
262 out_of_memory();
263 }
264 snprintf(email, strlen(cp) + 5, "E=%s,", cp);
265 subjectlen += strlen(email);
266 }
267
268 subjectlen++;
269
270 subject = PORT_ZAllocPORT_ZAlloc_Util(subjectlen);
271 if (!subject) {
272 out_of_memory();
273 }
274
275 snprintf(subject, subjectlen, "%s%s%s%s%s%s%s",
276 common_name ? common_name : "",
277 org ? org : "",
278 orgunit ? orgunit : "",
279 state ? state : "",
280 country ? country : "",
281 uid ? uid : "",
282 email ? email : "");
283 if ((strlen(subject) > 1) && (subject[strlen(subject) - 1] == ' ')) {
284 subject[strlen(subject) - 2] = '\0';
285 }
286
287 PORT_FreePORT_Free_Util(common_name);
288 PORT_FreePORT_Free_Util(org);
289 PORT_FreePORT_Free_Util(orgunit);
290 PORT_FreePORT_Free_Util(state);
291 PORT_FreePORT_Free_Util(country);
292 PORT_FreePORT_Free_Util(uid);
293 PORT_FreePORT_Free_Util(email);
294
295 return subject;
296}
297
298/**************************************************************************
299 *
300 * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
301 * *phew*^
302 *
303 */
304static CERTCertificate *
305GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
306 char *subject, unsigned long serial, int keysize, char *token)
307{
308 CERTCertificate *cert, *temp_cert;
309 SECItem *derCert;
310 CERTCertificateRequest *req;
311
312 PK11SlotInfo *slot = NULL((void*)0);
313 SECKEYPrivateKey *privk = NULL((void*)0);
314 SECKEYPublicKey *pubk = NULL((void*)0);
315
316 if (token) {
317 slot = PK11_FindSlotByName(token);
318 } else {
319 slot = PK11_GetInternalKeySlot();
320 }
321
322 if (slot == NULL((void*)0)) {
323 PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
324 token ? token : "");
325 errorCount++;
326 exit(ERRX(-1));
327 }
328
329 if (GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
330 FatalError("Error generating keypair.");
331 }
332 req = make_cert_request(subject, pubk);
333 temp_cert = make_cert(req, serial, &req->subject);
334 if (set_cert_type(temp_cert,
335 NS_CERT_TYPE_OBJECT_SIGNING(0x10) |
336 NS_CERT_TYPE_OBJECT_SIGNING_CA(0x01)) !=
337 SECSuccess) {
338 FatalError("Unable to set cert type");
339 }
340
341 derCert = sign_cert(temp_cert, privk);
342 cert = install_cert(db, derCert, nickname);
343 if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
344 FatalError("Unable to change trust on generated certificate");
345 }
346
347 /* !!! Free memory ? !!! */
348 PK11_FreeSlot(slot);
349 SECKEY_DestroyPrivateKey(privk);
350 SECKEY_DestroyPublicKey(pubk);
351 CERT_DestroyCertificate(temp_cert);
352 CERT_DestroyCertificateRequest(req);
353
354 return cert;
355}
356
357/**************************************************************************
358 *
359 * C h a n g e T r u s t A t t r i b u t e s
360 */
361static SECStatus
362ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
363{
364
365 CERTCertTrust *trust;
366
367 if (!db || !cert || !trusts) {
368 PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n");
369 errorCount++;
370 return SECFailure;
371 }
372
373 trust = (CERTCertTrust *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(CERTCertTrust));
374 if (!trust) {
375 PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
376 "CERTCertTrust\n");
377 errorCount++;
378 return SECFailure;
379 }
380
381 if (CERT_DecodeTrustString(trust, trusts)) {
382 return SECFailure;
383 }
384
385 if (CERT_ChangeCertTrust(db, cert, trust)) {
386 PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
387 cert->nickname ? cert->nickname : "");
388 errorCount++;
389 return SECFailure;
390 }
391
392 PORT_FreePORT_Free_Util(trust);
393 return SECSuccess;
394}
395
396/*************************************************************************
397 *
398 * s e t _ c e r t _ t y p e
399 */
400static SECStatus
401set_cert_type(CERTCertificate *cert, unsigned int type)
402{
403 void *context;
404 SECStatus status = SECSuccess;
405 SECItem certType;
406 char ctype;
407
408 context = CERT_StartCertExtensions(cert);
409
410 certType.type = siBuffer;
411 certType.data = (unsigned char *)&ctype;
412 certType.len = 1;
413 ctype = (unsigned char)type;
414 if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
415 &certType, PR_TRUE1 /*critical*/) !=
416 SECSuccess) {
417 status = SECFailure;
418 }
419
420 if (CERT_FinishExtensions(context) != SECSuccess) {
421 status = SECFailure;
422 }
423
424 return status;
425}
426
427/********************************************************************
428 *
429 * s i g n _ c e r t
430 */
431static SECItem *
432sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
433{
434 SECStatus rv;
435
436 SECItem der2;
437 SECItem *result2;
438
439 SECOidTag alg = SEC_OID_UNKNOWN;
440
441 alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
442 if (alg == SEC_OID_UNKNOWN) {
443 FatalError("Unknown key type");
444 }
445
446 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(cert->arena, &cert->signature, alg, 0);
447
448 if (rv != SECSuccess) {
449 PR_fprintf(errorFD, "%s: unable to set signature alg id\n",
450 PROGRAM_NAME"signtool");
451 errorCount++;
452 exit(ERRX(-1));
453 }
454
455 der2.len = 0;
456 der2.data = NULL((void*)0);
457
458 (void)SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(cert->arena, &der2, cert, SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate);
459
460 if (rv != SECSuccess) {
461 PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME"signtool");
462 errorCount++;
463 exit(ERRX(-1));
464 }
465
466 result2 = (SECItem *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(cert->arena, sizeof(SECItem));
467 if (result2 == NULL((void*)0))
468 out_of_memory();
469
470 rv = SEC_DerSignData(cert->arena, result2, der2.data, der2.len, privk, alg);
471
472 if (rv != SECSuccess) {
473 PR_fprintf(errorFD, "can't sign encoded certificate data\n");
474 errorCount++;
475 exit(ERRX(-1));
476 } else if (verbosity >= 0) {
477 PR_fprintf(outputFD, "certificate has been signed\n");
478 }
479
480 cert->derCert = *result2;
481
482 return result2;
483}
484
485/*********************************************************************
486 *
487 * i n s t a l l _ c e r t
488 *
489 * Installs the cert in the permanent database.
490 */
491static CERTCertificate *
492install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
493{
494 CERTCertificate *newcert;
495 PK11SlotInfo *newSlot;
496
497 newSlot = PK11_ImportDERCertForKey(derCert, nickname, &pwdata);
498 if (newSlot == NULL((void*)0)) {
499 PR_fprintf(errorFD, "Unable to install certificate\n");
500 errorCount++;
501 exit(ERRX(-1));
502 }
503
504 newcert = PK11_FindCertFromDERCertItem(newSlot, derCert, &pwdata);
505 PK11_FreeSlot(newSlot);
506 if (newcert == NULL((void*)0)) {
507 PR_fprintf(errorFD, "%s: can't find new certificate\n",
508 PROGRAM_NAME"signtool");
509 errorCount++;
510 exit(ERRX(-1));
511 }
512
513 if (verbosity >= 0) {
514 PR_fprintf(outputFD, "certificate \"%s\" added to database\n",
515 nickname);
516 }
517
518 return newcert;
519}
520
521/******************************************************************
522 *
523 * G e n e r a t e K e y P a i r
524 */
525static SECStatus
526GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
527 SECKEYPrivateKey **privk, int keysize)
528{
529
530 PK11RSAGenParams rsaParams;
531
532 if (keysize == -1) {
533 rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE1024;
534 } else {
535 rsaParams.keySizeInBits = keysize;
536 }
537 rsaParams.pe = 0x10001;
538
539 if (PK11_Authenticate(slot, PR_FALSE0 /*loadCerts*/, &pwdata) !=
540 SECSuccess) {
541 SECU_PrintError(progName, "failure authenticating to key database.\n");
542 exit(ERRX(-1));
543 }
544
545 *privk = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN0x00000000UL, &rsaParams,
546
547 pubk, PR_TRUE1 /*isPerm*/, PR_TRUE1 /*isSensitive*/, &pwdata);
548
549 if (*privk != NULL((void*)0) && *pubk != NULL((void*)0)) {
550 if (verbosity >= 0) {
551 PR_fprintf(outputFD, "generated public/private key pair\n");
552 }
553 } else {
554 SECU_PrintError(progName, "failure generating key pair\n");
555 exit(ERRX(-1));
556 }
557
558 return SECSuccess;
559}
560
561/******************************************************************
562 *
563 * m a k e _ c e r t _ r e q u e s t
564 */
565static CERTCertificateRequest *
566make_cert_request(char *subject, SECKEYPublicKey *pubk)
567{
568 CERTName *subj;
569 CERTSubjectPublicKeyInfo *spki;
570
571 CERTCertificateRequest *req;
572
573 /* Create info about public key */
574 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
575 if (!spki) {
576 SECU_PrintError(progName, "unable to create subject public key");
577 exit(ERRX(-1));
578 }
579
580 subj = CERT_AsciiToName(subject);
581 if (subj == NULL((void*)0)) {
582 FatalError("Invalid data in certificate description");
583 }
584
585 /* Generate certificate request */
586 req = CERT_CreateCertificateRequest(subj, spki, 0);
587 if (!req) {
588 SECU_PrintError(progName, "unable to make certificate request");
589 exit(ERRX(-1));
590 }
591
592 SECKEY_DestroySubjectPublicKeyInfo(spki);
593 CERT_DestroyName(subj);
594
595 if (verbosity >= 0) {
596 PR_fprintf(outputFD, "certificate request generated\n");
597 }
598
599 return req;
600}
601
602/******************************************************************
603 *
604 * m a k e _ c e r t
605 */
606static CERTCertificate *
607make_cert(CERTCertificateRequest *req, unsigned long serial,
608 CERTName *ca_subject)
609{
610 CERTCertificate *cert;
611
612 CERTValidity *validity = NULL((void*)0);
613
614 PRTime now, after;
615 PRExplodedTime printableTime;
616
617 now = PR_Now();
618 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
619
620 printableTime.tm_month += 3;
621 after = PR_ImplodeTime(&printableTime);
622
623 validity = CERT_CreateValidity(now, after);
624
625 if (validity == NULL((void*)0)) {
626 PR_fprintf(errorFD, "%s: error creating certificate validity\n",
627 PROGRAM_NAME"signtool");
628 errorCount++;
629 exit(ERRX(-1));
630 }
631
632 cert = CERT_CreateCertificate(serial, ca_subject, validity, req);
633 CERT_DestroyValidity(validity);
634
635 if (cert == NULL((void*)0)) {
636 /* should probably be more precise here */
637 PR_fprintf(errorFD, "%s: error while generating certificate\n",
638 PROGRAM_NAME"signtool");
639 errorCount++;
640 exit(ERRX(-1));
641 }
642
643 return cert;
644}
645
646/*************************************************************************
647 *
648 * o u t p u t _ c a _ c e r t
649 */
650static void
651output_ca_cert(CERTCertificate *cert, CERTCertDBHandle *db)
652{
653 FILE *out;
654
655 SECItem *encodedCertChain;
656 SEC_PKCS7ContentInfo *certChain;
657 char *filename, *certData;
658
659 /* the raw */
660
661 filename = PORT_ZAllocPORT_ZAlloc_Util(strlen(DEFAULT_X509_BASENAME"x509") + 8);
662 if (!filename)
663 out_of_memory();
664
665 snprintf(filename, strlen(DEFAULT_X509_BASENAME"x509") + 8, "%s.raw", DEFAULT_X509_BASENAME"x509");
666 if ((out = fopen(filename, "wb")) == NULL((void*)0)) {
667 PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME"signtool",
668 filename);
669 errorCount++;
670 exit(ERRX(-1));
671 }
672
673 certChain = SEC_PKCS7CreateCertsOnly(cert, PR_TRUE1, db);
674 encodedCertChain =
675 SEC_PKCS7EncodeItem(NULL((void*)0), NULL((void*)0), certChain, NULL((void*)0), NULL((void*)0), NULL((void*)0));
676 SEC_PKCS7DestroyContentInfo(certChain);
677
678 if (encodedCertChain) {
679 fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
680 fwrite(encodedCertChain->data, 1, encodedCertChain->len,
681 out);
682 SECITEM_FreeItemSECITEM_FreeItem_Util(encodedCertChain, PR_TRUE1);
683 } else {
684 PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n",
685 PROGRAM_NAME"signtool");
686 errorCount++;
687 exit(ERRX(-1));
688 }
689
690 fclose(out);
691
692 /* and the cooked */
693
694 snprintf(filename, strlen(DEFAULT_X509_BASENAME"x509") + 8, "%s.cacert", DEFAULT_X509_BASENAME"x509");
695 if ((out = fopen(filename, "wb")) == NULL((void*)0)) {
696 PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME"signtool",
697 filename);
698 errorCount++;
699 return;
700 }
701
702 certData = BTOA_DataToAsciiBTOA_DataToAscii_Util(cert->derCert.data, cert->derCert.len);
703 fprintf(out, "%s\n%s\n%s\n", NS_CERT_HEADER"-----BEGIN CERTIFICATE-----", certData, NS_CERT_TRAILER"-----END CERTIFICATE-----");
704 PORT_FreePORT_Free_Util(certData);
705
706 PORT_FreePORT_Free_Util(filename);
707 fclose(out);
708
709 if (verbosity >= 0) {
710 PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
711 DEFAULT_X509_BASENAME"x509", DEFAULT_X509_BASENAME"x509");
712 }
713}