1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file comprises the main driver for this tool. 28 * Upon parsing the command verbs from user input, it 29 * branches to the appropriate modules to perform the 30 * requested task. 31 */ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <ctype.h> 36 #include <malloc.h> 37 #include <libintl.h> 38 #include <libgen.h> 39 #include <errno.h> 40 #include <cryptoutil.h> 41 #include <security/cryptoki.h> 42 #include "common.h" 43 44 /* 45 * The verbcmd construct allows genericizing information about a verb so 46 * that it is easier to manipulate. Makes parsing code easier to read, 47 * fix, and extend with new verbs. 48 */ 49 typedef struct verbcmd_s { 50 char *verb; 51 int (*action)(int, char *[]); 52 int mode; 53 char *summary; 54 char *synopsis; 55 } verbcmd; 56 57 /* External declarations for supported verb actions. */ 58 extern int pk_setpin(int argc, char *argv[]); 59 extern int pk_list(int argc, char *argv[]); 60 extern int pk_delete(int argc, char *argv[]); 61 extern int pk_import(int argc, char *argv[]); 62 extern int pk_export(int argc, char *argv[]); 63 extern int pk_tokens(int argc, char *argv[]); 64 extern int pk_gencert(int argc, char *argv[]); 65 extern int pk_gencsr(int argc, char *argv[]); 66 extern int pk_download(int argc, char *argv[]); 67 extern int pk_genkey(int argc, char *argv[]); 68 extern int pk_signcsr(int argc, char *argv[]); 69 extern int pk_inittoken(int argc, char *argv[]); 70 extern int pk_genkeypair(int argc, char *argv[]); 71 72 /* Forward declarations for "built-in" verb actions. */ 73 static int pk_help(int argc, char *argv[]); 74 75 #define TOKEN_IDX 0 76 #define TOKEN_VERB "tokens" 77 #define TOKEN_SUMM gettext("lists all visible PKCS#11 tokens") 78 #define TOKEN_SYN "tokens" 79 80 #define SETPIN_IDX 1 81 #define SETPIN_VERB "setpin" 82 #define SETPIN_SUMM gettext("changes user authentication passphrase "\ 83 "for keystore access") 84 #define SETPIN_SYN \ 85 "setpin [ keystore=pkcs11 ]\n\t\t" \ 86 "[ token=token[:manuf[:serial]]]\n\t\t" \ 87 "[ usertype=so|user ]\n\t" \ 88 \ 89 "setpin keystore=nss\n\t\t" \ 90 "[ token=token ]\n\t\t" \ 91 "[ dir=directory-path ]\n\t\t" \ 92 "[ prefix=DBprefix ]\n\t" 93 94 #define LIST_IDX 2 95 #define LIST_VERB "list" 96 #define LIST_SUMM gettext("lists a summary of objects in the keystore") 97 #define LIST_SYN \ 98 "list [ token=token[:manuf[:serial]]]\n\t\t" \ 99 "[ objtype=private|public|both ]\n\t\t" \ 100 "[ label=label ]\n\t" \ 101 \ 102 "list objtype=cert[:[public | private | both ]]\n\t\t" \ 103 "[ subject=subject-DN ]\n\t\t" \ 104 "[ keystore=pkcs11 ]\n\t\t" \ 105 "[ issuer=issuer-DN ]\n\t\t" \ 106 "[ serial=serial number ]\n\t\t" \ 107 "[ label=cert-label ]\n\t\t" \ 108 "[ token=token[:manuf[:serial]]]\n\t\t" \ 109 "[ criteria=valid|expired|both ]\n\t" \ 110 \ 111 "list objtype=key[:[public | private | both ]]\n\t\t" \ 112 "[ keystore=pkcs11 ]\n\t\t" \ 113 "[ subject=subject-DN ]\n\t\t" \ 114 "[ label=key-label ]\n\t\t" \ 115 "[ token=token[:manuf[:serial]]]\n\t" \ 116 \ 117 "list keystore=pkcs11 objtype=crl\n\t\t" \ 118 "infile=crl-fn\n\t" \ 119 \ 120 "list keystore=nss objtype=cert\n\t\t" \ 121 "[ subject=subject-DN ]\n\t\t" \ 122 "[ issuer=issuer-DN ]\n\t\t" \ 123 "[ serial=serial number ]\n\t\t" \ 124 "[ nickname=cert-nickname ]\n\t\t" \ 125 "[ token=token[:manuf[:serial]]]\n\t\t" \ 126 "[ dir=directory-path ]\n\t\t" \ 127 "[ prefix=DBprefix ]\n\t\t" \ 128 "[ criteria=valid|expired|both ]\n\t" \ 129 \ 130 "list keystore=nss objtype=key\n\t\t" \ 131 "[ token=token[:manuf[:serial]]]\n\t\t" \ 132 "[ dir=directory-path ]\n\t\t" \ 133 "[ prefix=DBprefix ]\n\t\t" \ 134 "[ nickname=key-nickname ]\n\t" \ 135 \ 136 "list keystore=file objtype=cert\n\t\t" \ 137 "[ subject=subject-DN ]\n\t\t" \ 138 "[ issuer=issuer-DN ]\n\t\t" \ 139 "[ serial=serial number ]\n\t\t" \ 140 "[ infile=cert-fn ]\n\t\t" \ 141 "[ dir=directory-path ]\n\t\t" \ 142 "[ criteria=valid|expired|both ]\n\t" \ 143 \ 144 "list keystore=file objtype=key\n\t\t" \ 145 "[ infile=key-fn ]\n\t\t" \ 146 "[ dir=directory-path ]\n\t" \ 147 \ 148 "list keystore=file objtype=crl\n\t\t" \ 149 "infile=crl-fn\n\t" 150 151 #define DELETE_IDX 3 152 #define DELETE_VERB "delete" 153 #define DELETE_SUMM gettext("deletes objects in the keystore") 154 #define DELETE_SYN \ 155 "delete [ token=token[:manuf[:serial]]]\n\t\t" \ 156 "[ objtype=private|public|both ]\n\t\t" \ 157 "[ label=object-label ]\n\t" \ 158 \ 159 "delete keystore=nss objtype=cert\n\t\t" \ 160 "[ subject=subject-DN ]\n\t\t" \ 161 "[ issuer=issuer-DN ]\n\t\t" \ 162 "[ serial=serial number ]\n\t\t" \ 163 "[ label=cert-label ]\n\t\t" \ 164 "[ token=token[:manuf[:serial]]]\n\t\t" \ 165 "[ dir=directory-path ]\n\t\t" \ 166 "[ prefix=DBprefix ]\n\t\t" \ 167 "[ criteria=valid|expired|both ]\n\t" \ 168 \ 169 "delete keystore=nss objtype=key\n\t\t" \ 170 "[ token=token[:manuf[:serial]]]\n\t\t" \ 171 "[ dir=directory-path ]\n\t\t" \ 172 "[ prefix=DBprefix ]\n\t\t" \ 173 "[ nickname=key-nickname ]\n\t\t" \ 174 \ 175 "delete keystore=nss objtype=crl\n\t\t" \ 176 "[ nickname=issuer-nickname ]\n\t\t" \ 177 "[ subject=subject-DN ]\n\t\t" \ 178 "[ token=token[:manuf[:serial]]]\n\t\t" \ 179 "[ dir=directory-path ]\n\t\t" \ 180 "[ prefix=DBprefix ]\n\t" \ 181 \ 182 "delete keystore=pkcs11 " \ 183 "objtype=cert[:[public | private | both]]\n\t\t" \ 184 "[ subject=subject-DN ]\n\t\t" \ 185 "[ issuer=issuer-DN ]\n\t\t" \ 186 "[ serial=serial number ]\n\t\t" \ 187 "[ label=cert-label ]\n\t\t" \ 188 "[ token=token[:manuf[:serial]]]\n\t\t" \ 189 "[ criteria=valid|expired|both ]\n\t" \ 190 \ 191 "delete keystore=pkcs11 " \ 192 "objtype=key[:[public | private | both]]\n\t\t" \ 193 "[ subject=subject-DN ]\n\t\t" \ 194 "[ label=key-label ]\n\t\t" \ 195 "[ token=token[:manuf[:serial]]]\n\t" \ 196 \ 197 "delete keystore=pkcs11 objtype=crl\n\t\t" \ 198 "infile=crl-fn\n\t" \ 199 \ 200 "delete keystore=file objtype=cert\n\t\t" \ 201 "[ subject=subject-DN ]\n\t\t" \ 202 "[ issuer=issuer-DN ]\n\t\t" \ 203 "[ serial=serial number ]\n\t\t" \ 204 "[ infile=cert-fn ]\n\t\t" \ 205 "[ dir=directory-path ]\n\t\t" \ 206 "[ criteria=valid|expired|both ]\n\t" \ 207 \ 208 "delete keystore=file objtype=key\n\t\t" \ 209 "[ infile=key-fn ]\n\t\t" \ 210 "[ dir=directory-path ]\n\t" \ 211 \ 212 "delete keystore=file objtype=crl\n\t\t" \ 213 "infile=crl-fn\n\t" 214 215 #define IMPORT_IDX 4 216 #define IMPORT_VERB "import" 217 #define IMPORT_SUMM gettext("imports objects from an external source") 218 #define IMPORT_SYN \ 219 "import [token=token[:manuf[:serial]]]\n\t\t" \ 220 "infile=input-fn\n\t" \ 221 \ 222 "import keystore=nss objtype=cert\n\t\t" \ 223 "infile=input-fn\n\t\t" \ 224 "label=cert-label\n\t\t" \ 225 "[ trust=trust-value ]\n\t\t" \ 226 "[ token=token[:manuf[:serial]]]\n\t\t" \ 227 "[ dir=directory-path ]\n\t\t" \ 228 "[ prefix=DBprefix ]\n\t" \ 229 \ 230 "import keystore=nss objtype=crl\n\t\t" \ 231 "infile=input-fn\n\t\t" \ 232 "[ verifycrl=y|n ]\n\t\t" \ 233 "[ token=token[:manuf[:serial]]]\n\t\t" \ 234 "[ dir=directory-path ]\n\t\t" \ 235 "[ prefix=DBprefix ]\n\t" \ 236 \ 237 "import keystore=pkcs11\n\t\t" \ 238 "infile=input-fn\n\t\t" \ 239 "label=label\n\t\t" \ 240 "[ objtype=cert|key ]\n\t\t" \ 241 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 242 "[ sensitive=y|n ]\n\t\t" \ 243 "[ extractable=y|n ]\n\t\t" \ 244 "[ token=token[:manuf[:serial]]]\n\t" \ 245 \ 246 "import keystore=pkcs11 objtype=crl\n\t\t" \ 247 "infile=input-crl-fn\n\t\t" \ 248 "outcrl=output-crl-fn\n\t\t" \ 249 "outformat=pem|der\n\t" \ 250 \ 251 "import keystore=file\n\t\t" \ 252 "infile=input-fn\n\t\t" \ 253 "outkey=output-key-fn\n\t\t" \ 254 "outcert=output-cert-fn\n\t\t" \ 255 "[ outformat=pem|der|pkcs12 ]\n\t" \ 256 \ 257 "import keystore=file objtype=crl\n\t\t" \ 258 "infile=input-crl-fn\n\t\t" \ 259 "outcrl=output-crl-fn\n\t\t" \ 260 "outformat=pem|der\n\t" 261 262 #define EXPORT_IDX 5 263 #define EXPORT_VERB "export" 264 #define EXPORT_SUMM gettext("exports objects from the keystore to a file") 265 #define EXPORT_SYN \ 266 "export [token=token[:manuf[:serial]]]\n\t\t" \ 267 "outfile=output-fn\n\t" \ 268 \ 269 "export keystore=nss\n\t\t" \ 270 "outfile=output-fn\n\t\t" \ 271 "[ objtype=cert|key ]\n\t\t" \ 272 "[ subject=subject-DN ]\n\t\t" \ 273 "[ issuer=issuer-DN ]\n\t\t" \ 274 "[ serial=serial number ]\n\t\t" \ 275 "[ nickname=cert-nickname ]\n\t\t" \ 276 "[ token=token[:manuf[:serial]]]\n\t\t" \ 277 "[ dir=directory-path ]\n\t\t" \ 278 "[ prefix=DBPrefix ]\n\t\t" \ 279 "[ outformat=pem|der|pkcs12 ]\n\t" \ 280 \ 281 "export keystore=pkcs11\n\t\t" \ 282 "outfile=output-fn\n\t\t" \ 283 "[ objtype=cert|key ]\n\t\t" \ 284 "[ label=label ]\n\t\t" \ 285 "[ subject=subject-DN ]\n\t\t" \ 286 "[ issuer=issuer-DN ]\n\t\t" \ 287 "[ serial=serial number ]\n\t\t" \ 288 "[ outformat=pem|der|pkcs12|raw ]\n\t\t" \ 289 "[ token=token[:manuf[:serial]]]\n\t" \ 290 \ 291 "export keystore=file\n\t\t" \ 292 "certfile=cert-input-fn\n\t\t" \ 293 "keyfile=key-input-fn\n\t\t" \ 294 "outfile=output-pkcs12-fn\n\t" 295 296 #define GENCERT_IDX 6 297 #define GENCERT_VERB "gencert" 298 #define GENCERT_SUMM gettext("creates a self-signed X.509v3 certificate") 299 #define GENCERT_SYN \ 300 "gencert listcurves\n\t" \ 301 \ 302 "gencert keystore=nss\n\t\t" \ 303 "label=cert-nickname\n\t\t" \ 304 "serial=serial number hex string\n\t\t" \ 305 "[ -i ] | [subject=subject-DN]\n\t\t" \ 306 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 307 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 308 "[ token=token[:manuf[:serial]]]\n\t\t" \ 309 "[ dir=directory-path ]\n\t\t" \ 310 "[ prefix=DBprefix ]\n\t\t" \ 311 "[ keytype=rsa | ec [curve=ECC Curve Name] " \ 312 "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 313 "[ keytype=dsa [hash=sha1]]\n\t\t" \ 314 "[ keylen=key-size ]\n\t\t" \ 315 "[ trust=trust-value ]\n\t\t" \ 316 "[ eku=[critical:]EKU name,...]\n\t\t" \ 317 "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 318 \ 319 "gencert [ keystore=pkcs11 ]\n\t\t" \ 320 "label=key/cert-label\n\t\t" \ 321 "serial=serial number hex string\n\t\t" \ 322 "[ -i ] | [subject=subject-DN]\n\t\t" \ 323 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 324 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 325 "[ token=token[:manuf[:serial]]]\n\t\t" \ 326 "[ keytype=rsa | ec [curve=ECC Curve Name] " \ 327 "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 328 "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \ 329 "[ keylen=key-size ]\n\t\t" \ 330 "[ eku=[critical:]EKU name,...]\n\t\t" \ 331 "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 332 \ 333 "gencert keystore=file\n\t\t" \ 334 "outcert=cert_filename\n\t\t" \ 335 "outkey=key_filename\n\t\t" \ 336 "serial=serial number hex string\n\t\t" \ 337 "[ -i ] | [subject=subject-DN]\n\t\t" \ 338 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 339 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 340 "[ format=der|pem ]\n\t\t" \ 341 "[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 342 "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \ 343 "[ keylen=key-size ]\n\t\t" \ 344 "[ eku=[critical:]EKU name,...]\n\t\t" \ 345 "[ lifetime=number-hour|number-day|number-year ]\n\t" 346 347 #define GENCSR_IDX 7 348 #define GENCSR_VERB "gencsr" 349 #define GENCSR_SUMM gettext("creates a PKCS#10 certificate signing " \ 350 "request file") 351 352 #define GENCSR_SYN \ 353 "gencsr listcurves\n\t" \ 354 \ 355 "gencsr keystore=nss \n\t\t" \ 356 "nickname=cert-nickname\n\t\t" \ 357 "outcsr=csr-fn\n\t\t" \ 358 "[ -i ] | [subject=subject-DN]\n\t\t" \ 359 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 360 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 361 "[ token=token[:manuf[:serial]]]\n\t\t" \ 362 "[ dir=directory-path ]\n\t\t" \ 363 "[ prefix=DBprefix ]\n\t\t" \ 364 "[ keytype=rsa | ec [curve=ECC Curve Name] " \ 365 "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 366 "[ keytype=dsa [hash=sha1]]\n\t\t" \ 367 "[ keylen=key-size ]\n\t\t" \ 368 "[ eku=[critical:]EKU name,...]\n\t\t" \ 369 "[ format=pem|der ]\n\t" \ 370 \ 371 "gencsr [ keystore=pkcs11 ]\n\t\t" \ 372 "label=key-label\n\t\t" \ 373 "outcsr=csr-fn\n\t\t" \ 374 "[ -i ] | [subject=subject-DN]\n\t\t" \ 375 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 376 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 377 "[ token=token[:manuf[:serial]]]\n\t\t" \ 378 "[ keytype=rsa | ec [curve=ECC Curve Name] " \ 379 "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 380 "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \ 381 "[ keylen=key-size ]\n\t\t" \ 382 "[ eku=[critical:]EKU name,...]\n\t\t" \ 383 "[ format=pem|der ]]\n\t" \ 384 \ 385 "gencsr keystore=file\n\t\t" \ 386 "outcsr=csr-fn\n\t\t" \ 387 "outkey=key-fn\n\t\t" \ 388 "[ -i ] | [subject=subject-DN]\n\t\t" \ 389 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 390 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 391 "[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \ 392 "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \ 393 "[ keylen=key-size ]\n\t\t" \ 394 "[ eku=[critical:]EKU name,...]\n\t\t" \ 395 "[ format=pem|der ]\n\t" 396 397 #define DOWNLOAD_IDX 8 398 #define DOWNLOAD_VERB "download" 399 #define DOWNLOAD_SUMM gettext("downloads a CRL or certificate file " \ 400 "from an external source") 401 #define DOWNLOAD_SYN \ 402 "download url=url_str\n\t\t" \ 403 "[ objtype=crl|cert ]\n\t\t" \ 404 "[ http_proxy=proxy_str ]\n\t\t" \ 405 "[ outfile = outfile ]\n\t" 406 407 #define GENKEY_IDX 9 408 #define GENKEY_VERB "genkey" 409 #define GENKEY_SUMM gettext("creates a symmetric key in the keystore") 410 #define GENKEY_SYN \ 411 "genkey [ keystore=pkcs11 ]\n\t\t" \ 412 "label=key-label\n\t\t" \ 413 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 414 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 415 "[ token=token[:manuf[:serial]]]\n\t\t" \ 416 "[ sensitive=y|n ]\n\t\t" \ 417 "[ extractable=y|n ]\n\t\t" \ 418 "[ print=y|n ]\n\t" \ 419 \ 420 "genkey keystore=nss\n\t\t" \ 421 "label=key-label\n\t\t" \ 422 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 423 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 424 "[ token=token[:manuf[:serial]]]\n\t\t" \ 425 "[ dir=directory-path ]\n\t\t" \ 426 "[ prefix=DBprefix ]\n\t" \ 427 \ 428 "genkey keystore=file\n\t\t" \ 429 "outkey=key-fn\n\t\t" \ 430 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 431 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 432 "[ print=y|n ]\n\t" 433 434 #define SIGNCSR_IDX 10 435 #define SIGNCSR_VERB "signcsr" 436 #define SIGNCSR_SUMM gettext("Sign a PKCS#10 Certificate Signing Request") 437 #define SIGNCSR_SYN \ 438 "signcsr keystore=pkcs11\n\t\t" \ 439 "signkey=label (label of signing key)\n\t\t" \ 440 "csr=CSR filename\n\t\t" \ 441 "serial=serial number hex string\n\t\t" \ 442 "outcert=filename for final certificate\n\t\t" \ 443 "issuer=issuer-DN\n\t\t" \ 444 "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 445 "[ outlabel=certificate label ]\n\t\t" \ 446 "[ format=pem|der ] (output format)\n\t\t" \ 447 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 448 "[ altname=subjectAltName ]\n\t\t" \ 449 "[ keyusage=[critical:]usage,...]\n\t\t" \ 450 "[ eku=[critical:]EKU Name,...]\n\t\t" \ 451 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 452 "[ token=token[:manuf[:serial]]]\n\t" \ 453 \ 454 "signcsr keystore=file\n\t\t" \ 455 "signkey=filename\n\t\t" \ 456 "csr=CSR filename\n\t\t" \ 457 "serial=serial number hex string\n\t\t" \ 458 "outcert=filename for final certificate\n\t\t" \ 459 "issuer=issuer-DN\n\t\t" \ 460 "[ format=pem|der ] (output format)\n\t\t" \ 461 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 462 "[ altname=subjectAltName ]\n\t\t" \ 463 "[ keyusage=[critical:]usage,...]\n\t\t" \ 464 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 465 "[ eku=[critical:]EKU Name,...]\n\t" \ 466 \ 467 "signcsr keystore=nss\n\t\t" \ 468 "signkey=label (label of signing key)\n\t\t" \ 469 "csr=CSR filename\n\t\t" \ 470 "serial=serial number hex string\n\t\t" \ 471 "outcert=filename for final certificate\n\t\t" \ 472 "issuer=issuer-DN\n\t\t" \ 473 "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 474 "[ outlabel=certificate label ]\n\t\t" \ 475 "[ format=pem|der ] (output format)\n\t\t" \ 476 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 477 "[ altname=subjectAltName ]\n\t\t" \ 478 "[ keyusage=[critical:]usage,...]\n\t\t" \ 479 "[ eku=[critical:]EKU Name,...]\n\t\t" \ 480 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 481 "[ token=token[:manuf[:serial]]]\n\t\t" \ 482 "[ dir=directory-path ]\n\t\t" \ 483 "[ prefix=DBprefix ]\n\t" 484 485 #define INITTOKEN_IDX 11 486 #define INITTOKEN_VERB "inittoken" 487 #define INITTOKEN_SUMM gettext("Initialize a PKCS11 token") 488 #define INITTOKEN_SYN \ 489 "inittoken \n\t\t" \ 490 "[ currlabel=token[:manuf[:serial]]]\n\t\t" \ 491 "[ newlabel=new token label ]\n\t" 492 493 #define GENKEYPAIR_IDX 12 494 #define GENKEYPAIR_VERB "genkeypair" 495 #define GENKEYPAIR_SUMM gettext("creates an asymmetric keypair") 496 #define GENKEYPAIR_SYN \ 497 "genkeypair listcurves\n\t" \ 498 \ 499 "genkeypair keystore=nss\n\t\t" \ 500 "label=key-nickname\n\t\t" \ 501 "[ token=token[:manuf[:serial]]]\n\t\t" \ 502 "[ dir=directory-path ]\n\t\t" \ 503 "[ prefix=DBprefix ]\n\t\t" \ 504 "[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \ 505 "[ keylen=key-size ]\n\t" \ 506 \ 507 "genkeypair [ keystore=pkcs11 ]\n\t\t" \ 508 "label=key-label\n\t\t" \ 509 "[ token=token[:manuf[:serial]]]\n\t\t" \ 510 "[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \ 511 "[ keylen=key-size ]\n\t" \ 512 \ 513 "genkeypair keystore=file\n\t\t" \ 514 "outkey=key_filename\n\t\t" \ 515 "[ format=der|pem ]\n\t\t" \ 516 "[ keytype=rsa|dsa ]\n\t\t" \ 517 "[ keylen=key-size ]\n\t" 518 519 #define HELP_IDX 13 520 #define HELP_VERB "help" 521 #define HELP_SUMM gettext("displays help message") 522 #define HELP_SYN "help\t(help and usage)" 523 524 /* Command structure for verbs and their actions. Do NOT i18n/l10n. */ 525 static verbcmd cmds[] = { 526 { NULL, pk_tokens, 0, NULL, NULL}, 527 { NULL, pk_setpin, 0, NULL, NULL}, 528 { NULL, pk_list, 0, NULL, NULL}, 529 { NULL, pk_delete, 0, NULL, NULL}, 530 { NULL, pk_import, 0, NULL, NULL}, 531 { NULL, pk_export, 0, NULL, NULL}, 532 { NULL, pk_gencert, 0, NULL, NULL}, 533 { NULL, pk_gencsr, 0, NULL, NULL}, 534 { NULL, pk_download, 0, NULL, NULL}, 535 { NULL, pk_genkey, 0, NULL, NULL}, 536 { NULL, pk_signcsr, 0, NULL, NULL}, 537 { NULL, pk_inittoken, 0, NULL, NULL}, 538 { NULL, pk_genkeypair, 0, NULL, NULL}, 539 { NULL, pk_help, 0, NULL, NULL} 540 }; 541 542 static int num_cmds = sizeof (cmds) / sizeof (verbcmd); 543 544 static char *prog; 545 static void usage(int); 546 547 static void 548 init_command_list() 549 { 550 cmds[TOKEN_IDX].verb = TOKEN_VERB; 551 cmds[TOKEN_IDX].summary = TOKEN_SUMM; 552 cmds[TOKEN_IDX].synopsis = TOKEN_SYN; 553 554 cmds[SETPIN_IDX].verb = SETPIN_VERB; 555 cmds[SETPIN_IDX].summary = SETPIN_SUMM; 556 cmds[SETPIN_IDX].synopsis = SETPIN_SYN; 557 558 cmds[LIST_IDX].verb = LIST_VERB; 559 cmds[LIST_IDX].summary = LIST_SUMM; 560 cmds[LIST_IDX].synopsis = LIST_SYN; 561 562 cmds[DELETE_IDX].verb = DELETE_VERB; 563 cmds[DELETE_IDX].summary = DELETE_SUMM; 564 cmds[DELETE_IDX].synopsis = DELETE_SYN; 565 566 cmds[IMPORT_IDX].verb = IMPORT_VERB; 567 cmds[IMPORT_IDX].summary = IMPORT_SUMM; 568 cmds[IMPORT_IDX].synopsis = IMPORT_SYN; 569 570 cmds[EXPORT_IDX].verb = EXPORT_VERB; 571 cmds[EXPORT_IDX].summary = EXPORT_SUMM; 572 cmds[EXPORT_IDX].synopsis = EXPORT_SYN; 573 574 cmds[GENCERT_IDX].verb = GENCERT_VERB; 575 cmds[GENCERT_IDX].summary = GENCERT_SUMM; 576 cmds[GENCERT_IDX].synopsis = GENCERT_SYN; 577 578 cmds[GENCSR_IDX].verb = GENCSR_VERB; 579 cmds[GENCSR_IDX].summary = GENCSR_SUMM; 580 cmds[GENCSR_IDX].synopsis = GENCSR_SYN; 581 582 cmds[DOWNLOAD_IDX].verb = DOWNLOAD_VERB; 583 cmds[DOWNLOAD_IDX].summary = DOWNLOAD_SUMM; 584 cmds[DOWNLOAD_IDX].synopsis = DOWNLOAD_SYN; 585 586 cmds[GENKEY_IDX].verb = GENKEY_VERB; 587 cmds[GENKEY_IDX].summary = GENKEY_SUMM; 588 cmds[GENKEY_IDX].synopsis = GENKEY_SYN; 589 590 cmds[SIGNCSR_IDX].verb = SIGNCSR_VERB; 591 cmds[SIGNCSR_IDX].summary = SIGNCSR_SUMM; 592 cmds[SIGNCSR_IDX].synopsis = SIGNCSR_SYN; 593 594 cmds[INITTOKEN_IDX].verb = INITTOKEN_VERB; 595 cmds[INITTOKEN_IDX].summary = INITTOKEN_SUMM; 596 cmds[INITTOKEN_IDX].synopsis = INITTOKEN_SYN; 597 598 cmds[GENKEYPAIR_IDX].verb = GENKEYPAIR_VERB; 599 cmds[GENKEYPAIR_IDX].summary = GENKEYPAIR_SUMM; 600 cmds[GENKEYPAIR_IDX].synopsis = GENKEYPAIR_SYN; 601 602 cmds[HELP_IDX].verb = HELP_VERB; 603 cmds[HELP_IDX].summary = HELP_SUMM; 604 cmds[HELP_IDX].synopsis = HELP_SYN; 605 } 606 607 /* 608 * Usage information. This function must be updated when new verbs or 609 * options are added. 610 */ 611 static void 612 usage(int idx) 613 { 614 int i; 615 616 /* Display this block only in command-line mode. */ 617 (void) fprintf(stdout, gettext("Usage:\n")); 618 (void) fprintf(stdout, gettext(" %s -?\t(help and usage)\n"), 619 prog); 620 (void) fprintf(stdout, gettext(" %s -f option_file\n"), prog); 621 (void) fprintf(stdout, gettext(" %s subcommand [options...]\n"), 622 prog); 623 (void) fprintf(stdout, gettext("where subcommands may be:\n")); 624 625 /* Display only those verbs that match the current tool mode. */ 626 if (idx == -1) { 627 for (i = 0; i < num_cmds; i++) { 628 /* Do NOT i18n/l10n. */ 629 (void) fprintf(stdout, " %-8s - %s\n", 630 cmds[i].verb, cmds[i].summary); 631 } 632 (void) fprintf(stdout, "%s \'help\'.\n" 633 "Ex: pktool gencert help\n\n", 634 gettext("\nFurther details on the " 635 "subcommands can be found by adding")); 636 } else { 637 (void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis); 638 } 639 } 640 641 /* 642 * Provide help, in the form of displaying the usage. 643 */ 644 static int 645 pk_help(int argc, char *argv[]) 646 /* ARGSUSED */ 647 { 648 usage(-1); 649 return (0); 650 } 651 652 /* 653 * Process arguments from the argfile and create a new 654 * argv/argc list to be processed later. 655 */ 656 static int 657 process_arg_file(char *argfile, char ***argv, int *argc) 658 { 659 FILE *fp; 660 char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */ 661 char *p; 662 int nargs = 0; 663 664 if ((fp = fopen(argfile, "rF")) == NULL) { 665 (void) fprintf(stderr, 666 gettext("Cannot read argfile %s: %s\n"), 667 argfile, strerror(errno)); 668 return (errno); 669 } 670 671 while (fgets(argline, sizeof (argline), fp) != NULL) { 672 int j; 673 /* remove trailing whitespace */ 674 j = strlen(argline) - 1; 675 while (j >= 0 && isspace(argline[j])) { 676 argline[j] = 0; 677 j--; 678 } 679 /* If it was a blank line, get the next one. */ 680 if (!strlen(argline)) 681 continue; 682 683 (*argv) = realloc((*argv), 684 (nargs + 1) * sizeof (char *)); 685 if ((*argv) == NULL) { 686 perror("memory error"); 687 (void) fclose(fp); 688 return (errno); 689 } 690 p = (char *)strdup(argline); 691 if (p == NULL) { 692 perror("memory error"); 693 (void) fclose(fp); 694 return (errno); 695 } 696 (*argv)[nargs] = p; 697 nargs++; 698 } 699 *argc = nargs; 700 (void) fclose(fp); 701 return (0); 702 } 703 704 /* 705 * MAIN() -- where all the action is 706 */ 707 int 708 main(int argc, char *argv[], char *envp[]) 709 /* ARGSUSED2 */ 710 { 711 int i, found = -1; 712 int rv; 713 int pk_argc = 0; 714 char **pk_argv = NULL; 715 int save_errno = 0; 716 717 /* Set up for i18n/l10n. */ 718 (void) setlocale(LC_ALL, ""); 719 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 720 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 721 #endif 722 (void) textdomain(TEXT_DOMAIN); 723 724 init_command_list(); 725 726 /* Get program base name and move pointer over 0th arg. */ 727 prog = basename(argv[0]); 728 argv++, argc--; 729 730 /* Set up for debug and error output. */ 731 if (argc == 0) { 732 usage(-1); 733 return (1); 734 } 735 736 /* Check for help options. For CLIP-compliance. */ 737 if (strcmp(argv[0], "-?") == 0) { 738 return (pk_help(argc, argv)); 739 } else if (strcmp(argv[0], "-f") == 0 && argc == 2) { 740 rv = process_arg_file(argv[1], &pk_argv, &pk_argc); 741 if (rv) 742 return (rv); 743 } else if (argc >= 1 && argv[0][0] == '-') { 744 usage(-1); 745 return (1); 746 } 747 748 /* Always turns off Metaslot so that we can see softtoken. */ 749 if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 750 save_errno = errno; 751 cryptoerror(LOG_STDERR, 752 gettext("Disabling Metaslot failed (%s)."), 753 strerror(save_errno)); 754 return (1); 755 } 756 757 /* Begin parsing command line. */ 758 if (pk_argc == 0 && pk_argv == NULL) { 759 pk_argc = argc; 760 pk_argv = argv; 761 } 762 763 /* Check for valid verb (or an abbreviation of it). */ 764 found = -1; 765 for (i = 0; i < num_cmds; i++) { 766 if (strcmp(cmds[i].verb, pk_argv[0]) == 0) { 767 if (found < 0) { 768 found = i; 769 break; 770 } 771 } 772 } 773 /* Stop here if no valid verb found. */ 774 if (found < 0) { 775 cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"), 776 pk_argv[0]); 777 return (1); 778 } 779 780 /* Get to work! */ 781 rv = (*cmds[found].action)(pk_argc, pk_argv); 782 switch (rv) { 783 case PK_ERR_NONE: 784 break; /* Command succeeded, do nothing. */ 785 case PK_ERR_USAGE: 786 usage(found); 787 break; 788 case PK_ERR_QUIT: 789 exit(0); 790 /* NOTREACHED */ 791 case PK_ERR_PK11: 792 case PK_ERR_SYSTEM: 793 case PK_ERR_OPENSSL: 794 case PK_ERR_NSS: 795 default: 796 break; 797 } 798 return (rv); 799 } 800