1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <stdio.h> 29*7c478bd9Sstevel@tonic-gate #include <alloca.h> 30*7c478bd9Sstevel@tonic-gate #include <unistd.h> 31*7c478bd9Sstevel@tonic-gate #include <strings.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <libintl.h> 34*7c478bd9Sstevel@tonic-gate #include <locale.h> 35*7c478bd9Sstevel@tonic-gate #include <limits.h> 36*7c478bd9Sstevel@tonic-gate #include <libgen.h> 37*7c478bd9Sstevel@tonic-gate #include <errno.h> 38*7c478bd9Sstevel@tonic-gate #include <ctype.h> 39*7c478bd9Sstevel@tonic-gate #include <wanbootutil.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/wanboot_impl.h> 45*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 46*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* Return codes */ 49*7c478bd9Sstevel@tonic-gate #define KEYMGMT_SUCCESS 0 50*7c478bd9Sstevel@tonic-gate #define KEYMGMT_ERROR 1 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* Suboption. */ 53*7c478bd9Sstevel@tonic-gate #define TYPE 0 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate static char *opts[] = { "type", NULL }; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * This routine is used to parse the suboptions of '-o' option. 59*7c478bd9Sstevel@tonic-gate * 60*7c478bd9Sstevel@tonic-gate * The option should be of the form: type=<3des|aes|sha1|rsa> 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * This routine will pass the value of the suboption back in the 63*7c478bd9Sstevel@tonic-gate * supplied arguments, 'ka'. 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * Returns: 66*7c478bd9Sstevel@tonic-gate * KEYMGMT_SUCCESS or KEYMGMT_ERROR. 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate static int 69*7c478bd9Sstevel@tonic-gate process_option(char *arg, wbku_key_attr_t *ka) 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate char *value; 72*7c478bd9Sstevel@tonic-gate wbku_retcode_t ret; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate while (*arg != '\0') { 75*7c478bd9Sstevel@tonic-gate switch (getsubopt(&arg, opts, &value)) { 76*7c478bd9Sstevel@tonic-gate case TYPE: 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate * Key type. 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate ret = wbku_str_to_keyattr(value, ka, WBKU_ANY_KEY); 81*7c478bd9Sstevel@tonic-gate if (ret != WBKU_SUCCESS) { 82*7c478bd9Sstevel@tonic-gate wbku_printerr("%s\n", wbku_retmsg(ret)); 83*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate break; 86*7c478bd9Sstevel@tonic-gate default: 87*7c478bd9Sstevel@tonic-gate wbku_printerr("%s is not a valid option\n", value); 88*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * Success. 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate return (KEYMGMT_SUCCESS); 96*7c478bd9Sstevel@tonic-gate } 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * This routine extracts a key of type 'ka' from the keystore named 100*7c478bd9Sstevel@tonic-gate * 'keystore_name' and writes it the the file identified by 'name'. 101*7c478bd9Sstevel@tonic-gate * 102*7c478bd9Sstevel@tonic-gate * Returns: 103*7c478bd9Sstevel@tonic-gate * KEYMGMT_SUCCESS or KEYMGMT_ERROR. 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate static int 106*7c478bd9Sstevel@tonic-gate process_extract(const char *keystore_name, const char *name, 107*7c478bd9Sstevel@tonic-gate wbku_key_attr_t *ka) 108*7c478bd9Sstevel@tonic-gate { 109*7c478bd9Sstevel@tonic-gate size_t i; 110*7c478bd9Sstevel@tonic-gate uint8_t ex_key[WANBOOT_MAXKEYLEN]; 111*7c478bd9Sstevel@tonic-gate FILE *keystore_fp; 112*7c478bd9Sstevel@tonic-gate FILE *fp; 113*7c478bd9Sstevel@tonic-gate wbku_retcode_t ret; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * Open the keystore for reading. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate if ((keystore_fp = fopen(keystore_name, "r")) == NULL) { 119*7c478bd9Sstevel@tonic-gate wbku_printerr("Cannot open %s", keystore_name); 120*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * Find the client key. 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate ret = wbku_find_key(keystore_fp, NULL, ka, ex_key, B_FALSE); 127*7c478bd9Sstevel@tonic-gate if (ret != WBKU_SUCCESS) { 128*7c478bd9Sstevel@tonic-gate if (ret == WBKU_NOKEY) { 129*7c478bd9Sstevel@tonic-gate wbku_printerr("The client %s key does not exist\n", 130*7c478bd9Sstevel@tonic-gate ka->ka_str); 131*7c478bd9Sstevel@tonic-gate } else { 132*7c478bd9Sstevel@tonic-gate wbku_printerr("%s\n", wbku_retmsg(ret)); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 135*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* 140*7c478bd9Sstevel@tonic-gate * Open the output file. 141*7c478bd9Sstevel@tonic-gate */ 142*7c478bd9Sstevel@tonic-gate if ((fp = fopen(name, "w")) == NULL) { 143*7c478bd9Sstevel@tonic-gate wbku_printerr("Cannot open %s", name); 144*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 145*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * Dump the key to the output file. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate i = fwrite(ex_key, sizeof (uint8_t), ka->ka_len, fp); 152*7c478bd9Sstevel@tonic-gate if (i != ka->ka_len) { 153*7c478bd9Sstevel@tonic-gate wbku_printerr("Error writing to %s", name); 154*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 155*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * Success. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate return (KEYMGMT_SUCCESS); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * There is a key which needs to be removed from the keystore. Given basic 167*7c478bd9Sstevel@tonic-gate * information about the key to be deleted, go through the keystore and 168*7c478bd9Sstevel@tonic-gate * remove it. The steps are: 169*7c478bd9Sstevel@tonic-gate * 1) create a temp file in the same directory as the keystore. 170*7c478bd9Sstevel@tonic-gate * 2) copy the existing keystore to the temp file, omitting the key being 171*7c478bd9Sstevel@tonic-gate * removed. 172*7c478bd9Sstevel@tonic-gate * 3) shuffle files. Close the keystore and move it aside. Close the 173*7c478bd9Sstevel@tonic-gate * temp file and move in to the keystore. 174*7c478bd9Sstevel@tonic-gate * 175*7c478bd9Sstevel@tonic-gate * Returns: 176*7c478bd9Sstevel@tonic-gate * B_TRUE on success 177*7c478bd9Sstevel@tonic-gate * B_FALSE on error 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate static boolean_t 180*7c478bd9Sstevel@tonic-gate compress_keystore(const char *keystore_name, FILE *fp, 181*7c478bd9Sstevel@tonic-gate const wbku_key_attr_t *ka) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate char *tmp_path; 184*7c478bd9Sstevel@tonic-gate FILE *tmp_fp; 185*7c478bd9Sstevel@tonic-gate int tmp_fd; 186*7c478bd9Sstevel@tonic-gate int len; 187*7c478bd9Sstevel@tonic-gate wbku_retcode_t ret; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * Allocate storage for the temporary path from the stack. 191*7c478bd9Sstevel@tonic-gate */ 192*7c478bd9Sstevel@tonic-gate len = strlen(keystore_name) + sizeof (".XXXXXX"); 193*7c478bd9Sstevel@tonic-gate tmp_path = alloca(len); 194*7c478bd9Sstevel@tonic-gate (void) snprintf(tmp_path, len, "%s.XXXXXX", keystore_name); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * Make the temp working file where a new store will be created. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate if ((tmp_fd = mkstemp(tmp_path)) == -1) { 200*7c478bd9Sstevel@tonic-gate wbku_printerr("Error creating %s\n", tmp_path); 201*7c478bd9Sstevel@tonic-gate return (B_FALSE); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * Need to reference this file as a stream. 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate if ((tmp_fp = fdopen(tmp_fd, "w")) == NULL) { 208*7c478bd9Sstevel@tonic-gate wbku_printerr("Error opening %s", tmp_path); 209*7c478bd9Sstevel@tonic-gate (void) close(tmp_fd); 210*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_path); 211*7c478bd9Sstevel@tonic-gate return (B_FALSE); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Copy the existing keystore to the temp one, omitting the 216*7c478bd9Sstevel@tonic-gate * key being deleted. 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate ret = wbku_delete_key(fp, tmp_fp, ka); 219*7c478bd9Sstevel@tonic-gate (void) fclose(tmp_fp); 220*7c478bd9Sstevel@tonic-gate if (ret != WBKU_SUCCESS) { 221*7c478bd9Sstevel@tonic-gate wbku_printerr("%s\n", wbku_retmsg(ret)); 222*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_path); 223*7c478bd9Sstevel@tonic-gate return (B_FALSE); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * Shuffle files. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate if (rename(tmp_path, keystore_name) == -1) { 230*7c478bd9Sstevel@tonic-gate wbku_printerr("Error moving new keystore file from %s to %s", 231*7c478bd9Sstevel@tonic-gate tmp_path, keystore_name); 232*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_path); 233*7c478bd9Sstevel@tonic-gate return (B_FALSE); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate return (B_TRUE); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * This routine reads a key of type 'ka' from the file identified 'name' and 241*7c478bd9Sstevel@tonic-gate * inserts it into the keystore named 'keystore_name'. 242*7c478bd9Sstevel@tonic-gate * 243*7c478bd9Sstevel@tonic-gate * Returns: 244*7c478bd9Sstevel@tonic-gate * KEYMGMT_SUCCESS or KEYMGMT_ERROR. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate static int 247*7c478bd9Sstevel@tonic-gate process_insert(const char *keystore_name, const char *name, 248*7c478bd9Sstevel@tonic-gate wbku_key_attr_t *ka) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate int fd; 251*7c478bd9Sstevel@tonic-gate FILE *keystore_fp = NULL; 252*7c478bd9Sstevel@tonic-gate FILE *fp; 253*7c478bd9Sstevel@tonic-gate fpos_t pos; 254*7c478bd9Sstevel@tonic-gate uint8_t rd_key[WANBOOT_MAXKEYLEN]; 255*7c478bd9Sstevel@tonic-gate int inlen; 256*7c478bd9Sstevel@tonic-gate boolean_t newfile = B_TRUE; 257*7c478bd9Sstevel@tonic-gate wbku_retcode_t ret; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * If the file already exists, then open the file for update. 261*7c478bd9Sstevel@tonic-gate * Otherwise, create it and open it for writing. 262*7c478bd9Sstevel@tonic-gate */ 263*7c478bd9Sstevel@tonic-gate fd = open(keystore_name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); 264*7c478bd9Sstevel@tonic-gate if (fd < 0) { 265*7c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 266*7c478bd9Sstevel@tonic-gate keystore_fp = fopen(keystore_name, "r+"); 267*7c478bd9Sstevel@tonic-gate newfile = B_FALSE; 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate } else { 270*7c478bd9Sstevel@tonic-gate if ((keystore_fp = fdopen(fd, "w")) == NULL) { 271*7c478bd9Sstevel@tonic-gate (void) close(fd); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (keystore_fp == NULL) { 276*7c478bd9Sstevel@tonic-gate wbku_printerr("Cannot open %s", keystore_name); 277*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Open the input file. 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate fp = fopen(name, "r"); 284*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 285*7c478bd9Sstevel@tonic-gate wbku_printerr("Cannot open %s", name); 286*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 287*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * Read the key from the file. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate inlen = fread(rd_key, sizeof (uint8_t), ka->ka_maxlen, fp); 294*7c478bd9Sstevel@tonic-gate if (inlen == 0 && ferror(fp) != 0) { 295*7c478bd9Sstevel@tonic-gate wbku_printerr("Error reading %s", name); 296*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 297*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 298*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if ((inlen < ka->ka_minlen) || (inlen > ka->ka_maxlen)) { 303*7c478bd9Sstevel@tonic-gate wbku_printerr("Key length is not valid\n"); 304*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 305*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * If the keystore exists, search for a key of the type 310*7c478bd9Sstevel@tonic-gate * being inserted. If found, note its file position. 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate ret = WBKU_NOKEY; 313*7c478bd9Sstevel@tonic-gate if (!newfile) { 314*7c478bd9Sstevel@tonic-gate ret = wbku_find_key(keystore_fp, &pos, ka, NULL, B_FALSE); 315*7c478bd9Sstevel@tonic-gate if (ret != WBKU_SUCCESS && ret != WBKU_NOKEY) { 316*7c478bd9Sstevel@tonic-gate wbku_printerr("%s\n", wbku_retmsg(ret)); 317*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 318*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * Unfortuantely, RSA keys have variable lengths. If 323*7c478bd9Sstevel@tonic-gate * the one being inserted is a different length than 324*7c478bd9Sstevel@tonic-gate * than the one that already exists in the file, then 325*7c478bd9Sstevel@tonic-gate * the key must be removed from the keystore and then 326*7c478bd9Sstevel@tonic-gate * readded. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate if (ret == WBKU_SUCCESS && inlen != ka->ka_len) { 329*7c478bd9Sstevel@tonic-gate if (!compress_keystore(keystore_name, 330*7c478bd9Sstevel@tonic-gate keystore_fp, ka)) { 331*7c478bd9Sstevel@tonic-gate wbku_printerr("Insertion required compression" 332*7c478bd9Sstevel@tonic-gate " of keystore, but compression failed\n" 333*7c478bd9Sstevel@tonic-gate "Key was not inserted\n"); 334*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 335*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * The original keystore is history. Close the 340*7c478bd9Sstevel@tonic-gate * stream and open a stream to the new keystore. 341*7c478bd9Sstevel@tonic-gate */ 342*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 343*7c478bd9Sstevel@tonic-gate keystore_fp = fopen(keystore_name, "r+"); 344*7c478bd9Sstevel@tonic-gate if (keystore_fp == NULL) { 345*7c478bd9Sstevel@tonic-gate wbku_printerr("Cannot open %s", keystore_name); 346*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* Force new key to end of file */ 350*7c478bd9Sstevel@tonic-gate ret = WBKU_NOKEY; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate ka->ka_len = inlen; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * If wbku_find_key() did not find the key position for us, 357*7c478bd9Sstevel@tonic-gate * then we should set position to the end of the file. 358*7c478bd9Sstevel@tonic-gate */ 359*7c478bd9Sstevel@tonic-gate if (ret == WBKU_NOKEY && (fseek(keystore_fp, 0, SEEK_END) != 0 || 360*7c478bd9Sstevel@tonic-gate fgetpos(keystore_fp, &pos) != 0)) { 361*7c478bd9Sstevel@tonic-gate wbku_printerr("Internal error"); 362*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 363*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * Write the key to the keystore. 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate ret = wbku_write_key(keystore_fp, &pos, ka, rd_key, B_FALSE); 370*7c478bd9Sstevel@tonic-gate (void) fclose(keystore_fp); 371*7c478bd9Sstevel@tonic-gate if (ret != WBKU_SUCCESS) { 372*7c478bd9Sstevel@tonic-gate wbku_printerr("%s\n", wbku_retmsg(ret)); 373*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate (void) printf(gettext("The client's %s key has been set\n"), 377*7c478bd9Sstevel@tonic-gate ka->ka_str); 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * Success. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate return (KEYMGMT_SUCCESS); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate /* 385*7c478bd9Sstevel@tonic-gate * Prints usage(). 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate static void 388*7c478bd9Sstevel@tonic-gate usage(const char *cmd) 389*7c478bd9Sstevel@tonic-gate { 390*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage: %s" 391*7c478bd9Sstevel@tonic-gate " -i -k <key_file> -s <keystore> -o type=<%s|%s|%s|%s>\n" 392*7c478bd9Sstevel@tonic-gate " %s -x -f <out_file> -s <keystore> -o" 393*7c478bd9Sstevel@tonic-gate " type=<%s|%s|%s|%s>\n"), 394*7c478bd9Sstevel@tonic-gate cmd, WBKU_KW_3DES, WBKU_KW_AES_128, WBKU_KW_HMAC_SHA1, WBKU_KW_RSA, 395*7c478bd9Sstevel@tonic-gate cmd, WBKU_KW_3DES, WBKU_KW_AES_128, WBKU_KW_HMAC_SHA1, WBKU_KW_RSA); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * This program is used to insert and extract WAN boot encryption and 400*7c478bd9Sstevel@tonic-gate * hash keys into and from keystores. The paths to the keystores are 401*7c478bd9Sstevel@tonic-gate * provided by the user as are the input and output files. 402*7c478bd9Sstevel@tonic-gate * 403*7c478bd9Sstevel@tonic-gate * Note: 404*7c478bd9Sstevel@tonic-gate * This program assumes all keys being inserted or extracted 405*7c478bd9Sstevel@tonic-gate * are client keys. There is no way for a user to insert or 406*7c478bd9Sstevel@tonic-gate * extract a master key using this program. 407*7c478bd9Sstevel@tonic-gate * 408*7c478bd9Sstevel@tonic-gate * We do not do any file locking scheme. This means that if two 409*7c478bd9Sstevel@tonic-gate * keymgmt commands are run concurrently, results can be disastrous. 410*7c478bd9Sstevel@tonic-gate * 411*7c478bd9Sstevel@tonic-gate * Returns: 412*7c478bd9Sstevel@tonic-gate * KEYMGMT_SUCCESS or KEYMGMT_ERROR. 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate int 415*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 416*7c478bd9Sstevel@tonic-gate { 417*7c478bd9Sstevel@tonic-gate int c; 418*7c478bd9Sstevel@tonic-gate boolean_t is_insert = B_FALSE; 419*7c478bd9Sstevel@tonic-gate boolean_t is_extract = B_FALSE; 420*7c478bd9Sstevel@tonic-gate char *keystore_name = NULL; 421*7c478bd9Sstevel@tonic-gate char *filename = NULL; 422*7c478bd9Sstevel@tonic-gate wbku_key_attr_t ka; 423*7c478bd9Sstevel@tonic-gate int ret; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Do the necessary magic for localization support. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 429*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 430*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 431*7c478bd9Sstevel@tonic-gate #endif 432*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Initialize program name for use by wbku_printerr(). 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate wbku_errinit(argv[0]); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * At the very least, we'll need one arg. 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate if (argc < 2) { 443*7c478bd9Sstevel@tonic-gate usage(argv[0]); 444*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* 448*7c478bd9Sstevel@tonic-gate * Parse the options. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate ka.ka_type = WBKU_KEY_UNKNOWN; 451*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "ixf:k:s:o:")) != EOF) { 452*7c478bd9Sstevel@tonic-gate switch (c) { 453*7c478bd9Sstevel@tonic-gate case 'i': 454*7c478bd9Sstevel@tonic-gate is_insert = B_TRUE; 455*7c478bd9Sstevel@tonic-gate break; 456*7c478bd9Sstevel@tonic-gate case 'x': 457*7c478bd9Sstevel@tonic-gate is_extract = B_TRUE; 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate case 'o': 460*7c478bd9Sstevel@tonic-gate /* 461*7c478bd9Sstevel@tonic-gate * Suboptions. 462*7c478bd9Sstevel@tonic-gate */ 463*7c478bd9Sstevel@tonic-gate if (process_option(optarg, &ka) != KEYMGMT_SUCCESS) { 464*7c478bd9Sstevel@tonic-gate usage(argv[0]); 465*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate case 's': 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * Keystore path. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate keystore_name = optarg; 473*7c478bd9Sstevel@tonic-gate break; 474*7c478bd9Sstevel@tonic-gate case 'f': 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * Input file. 477*7c478bd9Sstevel@tonic-gate */ 478*7c478bd9Sstevel@tonic-gate if (is_insert || filename != NULL) { 479*7c478bd9Sstevel@tonic-gate usage(argv[0]); 480*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate filename = optarg; 483*7c478bd9Sstevel@tonic-gate break; 484*7c478bd9Sstevel@tonic-gate case 'k': 485*7c478bd9Sstevel@tonic-gate /* 486*7c478bd9Sstevel@tonic-gate * Input file. 487*7c478bd9Sstevel@tonic-gate */ 488*7c478bd9Sstevel@tonic-gate if (is_extract || filename != NULL) { 489*7c478bd9Sstevel@tonic-gate usage(argv[0]); 490*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate filename = optarg; 493*7c478bd9Sstevel@tonic-gate break; 494*7c478bd9Sstevel@tonic-gate default: 495*7c478bd9Sstevel@tonic-gate usage(argv[0]); 496*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * Must be inserting or extracting a key and we must have a 502*7c478bd9Sstevel@tonic-gate * key type, keystore filename and an input or output filename. 503*7c478bd9Sstevel@tonic-gate */ 504*7c478bd9Sstevel@tonic-gate if ((is_insert == is_extract) || keystore_name == NULL || 505*7c478bd9Sstevel@tonic-gate filename == NULL || ka.ka_type == WBKU_KEY_UNKNOWN) { 506*7c478bd9Sstevel@tonic-gate usage(argv[0]); 507*7c478bd9Sstevel@tonic-gate return (KEYMGMT_ERROR); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate /* 511*7c478bd9Sstevel@tonic-gate * Insert or extract the key. 512*7c478bd9Sstevel@tonic-gate */ 513*7c478bd9Sstevel@tonic-gate if (is_insert) { 514*7c478bd9Sstevel@tonic-gate ret = process_insert(keystore_name, filename, &ka); 515*7c478bd9Sstevel@tonic-gate } else { 516*7c478bd9Sstevel@tonic-gate ret = process_extract(keystore_name, filename, &ka); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate return (ret); 520*7c478bd9Sstevel@tonic-gate } 521