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 2002-2003 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 /* 30 * This provides the interface to store a named key in stable local 31 * storage. These keys are retrieved and used by OBP and WAN boot 32 * to do decryption and HMAC verification of network-downloaded data. 33 */ 34 35 #include <sys/promimpl.h> 36 #ifdef PROM_32BIT_ADDRS 37 #include <sys/sunddi.h> 38 #endif /* PROM_32BIT_ADDRS */ 39 40 int 41 prom_set_security_key(char *keyname, caddr_t buf, int buflen, int *reslen, 42 int *status) 43 { 44 int rv; 45 cell_t ci[7]; 46 int result; 47 #ifdef PROM_32BIT_ADDRS 48 char *okeyname = NULL; 49 char *obuf = NULL; 50 size_t keynamelen; 51 52 if ((uintptr_t)keyname > (uint32_t)-1) { 53 okeyname = keyname; 54 keynamelen = prom_strlen(okeyname) + 1; /* include '\0' */ 55 keyname = promplat_alloc(keynamelen); 56 if (keyname == NULL) 57 return (-1); 58 (void) prom_strcpy(keyname, okeyname); 59 } 60 61 /* 62 * A key length of zero is used to delete the named key. 63 * No need to reallocate and copy buf[] in this case. 64 */ 65 if (buflen > 0 && ((uintptr_t)buf > (uint32_t)-1)) { 66 obuf = buf; 67 buf = promplat_alloc(buflen); 68 if ((buf == NULL) && (okeyname != NULL)) { 69 promplat_free(keyname, keynamelen); 70 return (-1); 71 } 72 promplat_bcopy(obuf, buf, buflen); 73 } 74 #endif /* PROM_32BIT_ADDRS */ 75 76 /* 77 * The arguments to the SUNW,set-security-key service 78 * that stores a key are 79 * ci[0] the service name 80 * ci[1] the number of ``in'' arguments 81 * ci[2] the number of ``out'' arguments 82 * ci[3] the key's name, as a string 83 * ci[4] the key buffer itself 84 * ci[5] the length of the key buffer 85 * 86 * When p1275_cif_handler() returns, the return value is 87 * ci[6] the length of the key stored, or (if 88 * negative) an error code. 89 */ 90 ci[0] = p1275_ptr2cell("SUNW,set-security-key"); 91 ci[1] = 3; 92 ci[2] = 1; 93 ci[3] = p1275_ptr2cell(keyname); 94 ci[4] = p1275_ptr2cell(buf); 95 ci[5] = p1275_uint2cell(buflen); 96 97 promif_preprom(); 98 rv = p1275_cif_handler(ci); 99 promif_postprom(); 100 101 #ifdef PROM_32BIT_ADDRS 102 if (okeyname != NULL) 103 promplat_free(keyname, keynamelen); 104 if (obuf != NULL) 105 promplat_free(buf, buflen); 106 #endif /* PROM_32BIT_ADDRS */ 107 108 if (rv != 0) 109 return (-1); 110 111 result = p1275_cell2int(ci[6]); 112 if (result >= 0) { 113 *reslen = result; 114 *status = 0; 115 } else { 116 *reslen = 0; 117 *status = result; 118 } 119 return (0); 120 } 121 122 int 123 prom_get_security_key(char *keyname, caddr_t buf, int buflen, int *keylen, 124 int *status) 125 { 126 int rv; 127 cell_t ci[7]; 128 int result; 129 #ifdef PROM_32BIT_ADDRS 130 char *okeyname = NULL; 131 char *obuf = NULL; 132 size_t keynamelen; 133 134 if ((uintptr_t)keyname > (uint32_t)-1) { 135 okeyname = keyname; 136 keynamelen = prom_strlen(okeyname) + 1; /* include '\0' */ 137 keyname = promplat_alloc(keynamelen); 138 if (keyname == NULL) 139 return (-1); 140 (void) prom_strcpy(keyname, okeyname); 141 } 142 if ((uintptr_t)buf > (uint32_t)-1) { 143 obuf = buf; 144 buf = promplat_alloc(buflen); 145 if ((buf == NULL) && (okeyname != NULL)) { 146 promplat_free(keyname, keynamelen); 147 return (-1); 148 } 149 } 150 #endif /* PROM_32BIT_ADDRS */ 151 152 /* 153 * The arguments to the SUNW,get-security-key service 154 * that stores a key are 155 * ci[0] the service name 156 * ci[1] the number of ``in'' arguments 157 * ci[2] the number of ``out'' arguments 158 * ci[3] the key's name, as a string 159 * ci[4] the key buffer itself 160 * ci[5] the length of the key buffer 161 * 162 * When p1275_cif_handler() returns, the return value is 163 * ci[6] the length of the key, or (if 164 * negative) an error code. 165 */ 166 ci[0] = p1275_ptr2cell("SUNW,get-security-key"); 167 ci[1] = 3; 168 ci[2] = 1; 169 ci[3] = p1275_ptr2cell(keyname); 170 ci[4] = p1275_ptr2cell(buf); 171 ci[5] = p1275_uint2cell(buflen); 172 173 promif_preprom(); 174 rv = p1275_cif_handler(ci); 175 promif_postprom(); 176 177 #ifdef PROM_32BIT_ADDRS 178 if (okeyname != NULL) 179 promplat_free(keyname, keynamelen); 180 if (obuf != NULL) { 181 promplat_bcopy(buf, obuf, buflen); 182 promplat_free(buf, buflen); 183 } 184 #endif /* PROM_32BIT_ADDRS */ 185 186 if (rv != 0) 187 return (-1); 188 189 result = p1275_cell2int(ci[6]); 190 if (result > 0) { 191 *keylen = result; 192 *status = 0; 193 } else { 194 *keylen = 0; 195 *status = result; 196 } 197 return (0); 198 } 199