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