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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/wanboot_impl.h> 31 #include <libinetutil.h> 32 #include <wanbootutil.h> 33 #include <libintl.h> 34 #include <locale.h> 35 #include <unistd.h> 36 #include <stdlib.h> 37 #include <strings.h> 38 #include <stdio.h> 39 #include <fcntl.h> 40 #include <ctype.h> 41 #include <assert.h> 42 #include <sys/openpromio.h> 43 44 #define TYPE 0 45 static char *progopts[] = { 46 "type", 47 NULL 48 }; 49 50 /* 51 * The key's handle is the name by which a user knows the key (i.e. the 52 * name specified on the command line. The keyname is the name this 53 * utility uses to store the keys and the name OBP and wanboot use to 54 * retrieve them. 55 */ 56 static struct keylist { 57 const char *handle; 58 const char *keyname; 59 const int keysize; /* size of hex string representation */ 60 } keylist[] = { 61 WBKU_KW_3DES, WANBOOT_DES3_KEY_NAME, 62 (DES3_KEY_SIZE * 2), 63 WBKU_KW_AES_128, WANBOOT_AES_128_KEY_NAME, 64 (AES_128_KEY_SIZE * 2), 65 WBKU_KW_HMAC_SHA1, WANBOOT_HMAC_SHA1_KEY_NAME, 66 (WANBOOT_HMAC_KEY_SIZE * 2) 67 }; 68 69 static const struct keylist *knownkeytype(char *); 70 static char *getkey(const struct keylist *); 71 static void deletekey(const struct keylist *); 72 static void installkey(const struct keylist *); 73 static void usage(const char *) __NORETURN; 74 75 static boolean_t delete = B_FALSE; 76 77 int 78 main(int ac, char **av) 79 { 80 int i; 81 const struct keylist *k; 82 char *typestring = NULL; 83 char *options; 84 char *value; 85 86 /* 87 * Do the necessary magic for localization support. 88 */ 89 (void) setlocale(LC_ALL, ""); 90 #if !defined(TEXT_DOMAIN) 91 #define TEXT_DOMAIN "SYS_TEST" 92 #endif 93 (void) textdomain(TEXT_DOMAIN); 94 95 /* 96 * Initialize program name for use by wbku_printerr(). 97 */ 98 wbku_errinit(av[0]); 99 100 while ((i = getopt(ac, av, "do:")) != -1) 101 switch (i) { 102 case 'd': 103 delete = B_TRUE; 104 break; 105 106 case 'o': 107 options = optarg; 108 while (*options != '\0') { 109 switch (getsubopt(&options, progopts, 110 &value)) { 111 case TYPE: 112 typestring = value; 113 break; 114 115 default: 116 /* unknown token */ 117 usage(*av); 118 /* NOTREACHED */ 119 } 120 } 121 break; 122 123 case '?': 124 usage(*av); 125 /* NOTREACHED */ 126 } 127 128 if ((optind >= ac) && (typestring != NULL) && 129 ((k = knownkeytype(typestring)) != NULL)) { 130 if (delete == B_TRUE) 131 deletekey(k); 132 else 133 installkey(k); 134 return (0); 135 } else { 136 usage(*av); 137 /* NOTREACHED */ 138 } 139 } 140 141 static const struct keylist * 142 knownkeytype(char *type) 143 { 144 int i; 145 146 for (i = 0; i < sizeof (keylist)/sizeof (keylist[0]); i++) { 147 if (strcmp(keylist[i].handle, type) == 0) 148 return (&keylist[i]); 149 } 150 151 return (NULL); 152 } 153 154 static void 155 deletekey(const struct keylist *k) 156 { 157 int fd; 158 struct wankeyio wkio; 159 struct openpromio *oio; 160 161 (void) strlcpy(wkio.wk_keyname, k->keyname, WANBOOT_MAXKEYNAMELEN); 162 wkio.wk_keysize = 0; /* zero key size indicates a deletion */ 163 164 oio = malloc(sizeof (struct openpromio) + sizeof (struct wankeyio)); 165 if (oio == NULL) { 166 wbku_printerr("openpromio malloc (%d) failed\n", 167 sizeof (struct openpromio) + 168 sizeof (struct wankeyio)); 169 exit(1); 170 } 171 oio->oprom_size = sizeof (struct wankeyio); 172 bcopy(&wkio, oio->oprom_array, sizeof (struct wankeyio)); 173 fd = open("/dev/openprom", O_RDWR); 174 if (fd == -1) { 175 wbku_printerr("open: /dev/openprom"); 176 exit(1); 177 } 178 179 if (ioctl(fd, WANBOOT_SETKEY, oio) == -1) { 180 wbku_printerr("setkey: ioctl"); 181 exit(1); 182 } 183 184 (void) close(fd); 185 } 186 187 static void 188 installkey(const struct keylist *k) 189 { 190 char *keyptr; 191 int fd; 192 struct wankeyio wkio; 193 struct openpromio *oio; 194 uint_t rawkeysize; 195 int err; 196 197 (void) strlcpy(wkio.wk_keyname, k->keyname, WANBOOT_MAXKEYNAMELEN); 198 assert((k->keysize % 2) == 0); 199 wkio.wk_keysize = k->keysize / 2; 200 201 if ((keyptr = getkey(k)) != NULL) { 202 rawkeysize = sizeof (wkio.wk_u); 203 if ((err = hexascii_to_octet(keyptr, strlen(keyptr), 204 wkio.wk_u.key, &rawkeysize)) != 0) { 205 wbku_printerr( 206 "internal error: hexascii_to_octet returned %d\n", 207 err); 208 exit(1); 209 } else if (rawkeysize != wkio.wk_keysize) { 210 wbku_printerr("internal error: key size mismatch\n"); 211 exit(1); 212 } 213 214 oio = malloc(sizeof (struct openpromio) + 215 sizeof (struct wankeyio)); 216 if (oio == NULL) { 217 wbku_printerr("openpromio malloc (%d) failed\n", 218 sizeof (struct openpromio) + 219 sizeof (struct wankeyio)); 220 exit(1); 221 } 222 oio->oprom_size = sizeof (struct wankeyio); 223 bcopy(&wkio, oio->oprom_array, sizeof (struct wankeyio)); 224 fd = open("/dev/openprom", O_RDWR); 225 if (fd == -1) { 226 wbku_printerr("open: /dev/openprom"); 227 exit(1); 228 } 229 230 if (ioctl(fd, WANBOOT_SETKEY, oio) == -1) { 231 wbku_printerr("setkey: ioctl"); 232 exit(1); 233 } 234 235 (void) close(fd); 236 } else { 237 wbku_printerr("getpassphrase"); /* getpassphrase() failed */ 238 exit(1); 239 } 240 } 241 242 static char * 243 getkey(const struct keylist *k) 244 { 245 char prompt[BUFSIZ]; 246 char *p; 247 char *q; 248 int len; 249 250 (void) snprintf(prompt, sizeof (prompt), 251 gettext("Enter %s key: "), k->handle); 252 p = getpassphrase(prompt); 253 if (p) { 254 /* skip over initial "0[xX]" */ 255 if ((p[0] == '0') && (p[1] == 'x' || p[1] == 'X')) 256 p += 2; 257 len = strlen(p); 258 if (len != k->keysize) { 259 wbku_printerr( 260 "key length mismatch (expected %d, got %d)\n", 261 k->keysize, len); 262 exit(1); 263 } 264 for (q = p; q < p + len; q++) 265 if (!isxdigit(*q)) { 266 wbku_printerr( 267 "non-hexadecimal characters in key\n"); 268 exit(1); 269 } 270 } 271 272 return (p); 273 } 274 275 static void 276 usage(const char *progname) 277 { 278 int i; 279 280 (void) fprintf(stderr, gettext( 281 "usage: %s [ -d ] -o type=keytype\nwhere keytype is one of "), 282 progname); 283 for (i = 0; i < sizeof (keylist)/sizeof (keylist[0]); i++) 284 (void) fprintf(stderr, "%s ", keylist[i].handle); 285 (void) fputc('\n', stderr); 286 exit(1); 287 } 288