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
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.
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]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/wanboot_impl.h>
38 * Size of 'empty' pkcs12 key file (with no key in it) plus 1
39 * This is the minimum length for our RSA keys, because we
40 * only use RSA keys that are stored in PKCS12 format.
42 #define PKCS12_MIN_LEN 76
45 * Program name to be used by wbku_printerr()
47 static const char *wbku_pname
= NULL
;
50 * Note: must be kept in sync with codes in <key_util.h>
52 static char *wbku_retmsgs
[WBKU_NRET
] = {
53 /* 0 WBKU_SUCCESS */ "Success",
54 /* 1 WBKU_INTERNAL_ERR */ "Internal error",
55 /* 2 WBKU_WRITE_ERR */ "Keystore write error",
56 /* 3 WBKU_NOKEY */ "Key does not exist in keystore",
57 /* 4 WBKU_BAD_KEYTYPE */ "Invalid keytype specified"
61 * Initialize library for calls to wbku_printerr().
64 wbku_errinit(const char *arg0
)
66 wbku_pname
= strrchr(arg0
, '/');
68 if (wbku_pname
== NULL
)
75 * Print an error message to standard error and optionally
76 * append a system error.
80 wbku_printerr(const char *format
, ...)
85 if (wbku_pname
!= NULL
)
86 (void) fprintf(stderr
, "%s: ", wbku_pname
);
89 * Note that gettext() is used in order to obtain the
90 * message from the consumer's domain.
93 (void) vfprintf(stderr
, gettext(format
), ap
);
96 if (strchr(format
, '\n') == NULL
)
97 (void) fprintf(stderr
, ": %s\n", strerror(err
));
101 * Return the appropriate message for a given WBKU return code.
104 wbku_retmsg(wbku_retcode_t retcode
)
106 if ((retcode
< WBKU_SUCCESS
) || (retcode
>= WBKU_NRET
))
107 return (dgettext(TEXT_DOMAIN
, "<unknown code>"));
109 return (dgettext(TEXT_DOMAIN
, wbku_retmsgs
[retcode
]));
113 * This routine is a simple helper routine that initializes a
114 * wbku_key_attr_t object.
117 wbku_keyattr_init(wbku_key_attr_t
*attr
, wbku_key_type_t type
, uint_t atype
,
118 uint_t len
, uint_t minlen
, uint_t maxlen
,
119 char *str
, char *oid
, boolean_t (*keycheck
)(const uint8_t *))
121 attr
->ka_type
= type
;
122 attr
->ka_atype
= atype
;
124 attr
->ka_minlen
= minlen
;
125 attr
->ka_maxlen
= maxlen
;
128 attr
->ka_keycheck
= keycheck
;
133 * This routine is used to build a key attribute structure of the type
134 * defined by 'str' and 'flag'. This structure, 'attr', is the common
135 * structure used by the utilities that defines the attributes of a
139 * WBKU_SUCCESS or WBKU_BAD_KEYTYPE.
142 wbku_str_to_keyattr(const char *str
, wbku_key_attr_t
*attr
, uint_t flag
)
145 return (WBKU_BAD_KEYTYPE
);
147 if (flag
& WBKU_ENCR_KEY
) {
148 if (strcmp(str
, WBKU_KW_3DES
) == 0) {
149 wbku_keyattr_init(attr
, WBKU_KEY_3DES
,
150 WBKU_ENCR_KEY
, DES3_KEY_SIZE
, DES3_KEY_SIZE
,
151 DES3_KEY_SIZE
, "3DES", WBKU_DES3_OID
,
153 return (WBKU_SUCCESS
);
155 if (strcmp(str
, WBKU_KW_AES_128
) == 0) {
156 wbku_keyattr_init(attr
, WBKU_KEY_AES_128
,
157 WBKU_ENCR_KEY
, AES_128_KEY_SIZE
, AES_128_KEY_SIZE
,
158 AES_128_KEY_SIZE
, "AES", WBKU_AES_128_OID
, NULL
);
159 return (WBKU_SUCCESS
);
161 if (strcmp(str
, WBKU_KW_RSA
) == 0) {
162 wbku_keyattr_init(attr
, WBKU_KEY_RSA
,
163 WBKU_ENCR_KEY
, 0, PKCS12_MIN_LEN
,
164 WBKU_MAX_KEYLEN
, "RSA", WBKU_RSA_OID
, NULL
);
165 return (WBKU_SUCCESS
);
168 if (flag
& WBKU_HASH_KEY
) {
169 if (strcmp(str
, WBKU_KW_HMAC_SHA1
) == 0) {
170 wbku_keyattr_init(attr
, WBKU_KEY_HMAC_SHA1
,
171 WBKU_HASH_KEY
, WANBOOT_HMAC_KEY_SIZE
,
172 WANBOOT_HMAC_KEY_SIZE
, WANBOOT_HMAC_KEY_SIZE
,
173 "HMAC/SHA1", WBKU_HMAC_SHA1_OID
, NULL
);
174 return (WBKU_SUCCESS
);
177 return (WBKU_BAD_KEYTYPE
);
181 * This routine is used to search a key file (whose handle, fp, has been
182 * initialized by the caller) for the key of type 'ka'. The search is further
183 * constrained by the 'master' argument which is used to signify that the
184 * key being searched for is the master key.
186 * This routine may be used for a number of purposes:
187 * - Check for the existence of key of type foo.
188 * - Get the value for the key of type foo.
189 * - Return the file position of the key of type foo.
191 * To faciliate the uses above, both 'ppos' and 'ekey' will only be
192 * returned if they are not NULL pointers.
195 * WBKU_SUCCESS, WBKU_INTERNAL_ERR or WBKU_NOKEY.
198 wbku_find_key(FILE *fp
, fpos_t *ppos
, wbku_key_attr_t
*ka
, uint8_t *ekey
,
208 * Always, start at the beginning.
213 * Initialize the XDR stream.
216 xdrstdio_create(&xdrs
, fp
, XDR_DECODE
);
217 if (xdrs
.x_ops
== NULL
) {
218 return (WBKU_INTERNAL_ERR
);
222 * The XDR routines may examine the content of the keyobj
223 * structure to determine whether or not to provide memory
224 * resources. Since XDR does not provide an init routine
225 * for XDR generated objects, it seems that the safest thing
226 * to do is to bzero() the object as a means of initialization.
228 bzero(&keyobj
, sizeof (keyobj
));
231 * Read a key and check to see if matches the criteria.
233 for (keyno
= 0; !feof(fp
); keyno
++) {
236 * Returning the file position is conditional.
239 if (fgetpos(fp
, &pos
) != 0) {
240 ret
= WBKU_INTERNAL_ERR
;
246 * Read the key. Unfortuantely, XDR does not provide
247 * the ability to tell an EOF from some other IO error.
248 * Therefore, a faliure to read is assumed to be EOF.
250 if (!xdr_wbku_key(&xdrs
, &keyobj
)) {
256 * Check this key against the criteria.
258 if ((strcmp(keyobj
.wk_oid
, ka
->ka_oid
) == 0) &&
259 (keyobj
.wk_master
== master
)) {
261 ka
->ka_len
= keyobj
.wk_key_len
;
264 * Conditionally return the key value and file
268 (void) memcpy(ekey
, keyobj
.wk_key_val
,
275 xdr_free(xdr_wbku_key
, (char *)&keyobj
);
279 xdr_free(xdr_wbku_key
, (char *)&keyobj
);
287 * This routine writes a key object to the key file at the location
288 * specified by the caller.
291 * WBKU_SUCCESS, WBKU_INTERNAL_ERR or WBKU_WRITE_ERR.
294 wbku_write_key(FILE *fp
, const fpos_t *ppos
, const wbku_key_attr_t
*ka
,
295 uint8_t *rand_key
, boolean_t master
)
301 * Set the file position as specified by the caller.
303 if (fsetpos(fp
, ppos
) != 0) {
304 return (WBKU_INTERNAL_ERR
);
308 * Initialize the XDR stream.
311 xdrstdio_create(&xdrs
, fp
, XDR_ENCODE
);
312 if (xdrs
.x_ops
== NULL
) {
313 return (WBKU_INTERNAL_ERR
);
317 * Build the key object.
319 keyobj
.wk_master
= master
;
320 keyobj
.wk_oid
= ka
->ka_oid
;
321 keyobj
.wk_key_len
= ka
->ka_len
;
322 keyobj
.wk_key_val
= (char *)rand_key
;
327 if (!xdr_wbku_key(&xdrs
, &keyobj
)) {
328 xdr_free(xdr_wbku_key
, (char *)&keyobj
);
330 return (WBKU_WRITE_ERR
);
334 * Free the stream and return success.
337 return (WBKU_SUCCESS
);
341 * This routine reads the contents of one keystore file and copies it to
342 * another, omitting the key of the type defined by 'ka'.
345 * WBKU_SUCCESS, WBKU_INTERNAL_ERR or WBKU_WRITE_ERR.
348 wbku_delete_key(FILE *from_fp
, FILE *to_fp
, const wbku_key_attr_t
*ka
)
357 * Always, start at the beginning.
363 * Initialize the XDR streams.
365 from_xdrs
.x_ops
= NULL
;
366 xdrstdio_create(&from_xdrs
, from_fp
, XDR_DECODE
);
367 if (from_xdrs
.x_ops
== NULL
) {
368 return (WBKU_INTERNAL_ERR
);
371 to_xdrs
.x_ops
= NULL
;
372 xdrstdio_create(&to_xdrs
, to_fp
, XDR_ENCODE
);
373 if (to_xdrs
.x_ops
== NULL
) {
374 xdr_destroy(&from_xdrs
);
375 return (WBKU_INTERNAL_ERR
);
379 * The XDR routines may examine the content of the keyobj
380 * structure to determine whether or not to provide memory
381 * resources. Since XDR does not provide an init routine
382 * for XDR generated objects, it seems that the safest thing
383 * to do is to bzero() the object as a means of initialization.
385 bzero(&keyobj
, sizeof (keyobj
));
388 * Read a key and check to see if matches the criteria.
391 for (keyno
= 0; !feof(from_fp
); keyno
++) {
394 * Read the key. Unfortuantely, XDR does not provide
395 * the ability to tell an EOF from some other IO error.
396 * Therefore, a faliure to read is assumed to be EOF.
398 if (!xdr_wbku_key(&from_xdrs
, &keyobj
)) {
403 * If this isn't the key to skip, then write it.
405 if (strcmp(keyobj
.wk_oid
, ka
->ka_oid
) != 0) {
407 * Write this to the copy.
409 if (!xdr_wbku_key(&to_xdrs
, &keyobj
)) {
410 xdr_free(xdr_wbku_key
, (char *)&keyobj
);
411 ret
= WBKU_WRITE_ERR
;
417 xdr_free(xdr_wbku_key
, (char *)&keyobj
);
420 xdr_destroy(&from_xdrs
);
421 xdr_destroy(&to_xdrs
);