/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <strings.h>
#include <libintl.h>
#include <locale.h>
#include <limits.h>
#include <libgen.h>
#include <errno.h>
#include <assert.h>
#include <wanbootutil.h>
#include <sys/sysmacros.h>
#include <sys/wanboot_impl.h>
/* Return codes */
#define KEYGEN_SUCCESS 0
/* Defaults */
/* Suboption. */
#define NET 0
/*
* This routine is used to parse the suboptions of '-o' option.
*
* The option should be of the form:
* net=<addr>,cid=<cid>,type=<3des|aes|sha1|rsa>
*
* This routine will pass the values of each of the suboptions back in the
* supplied arguments, 'net', 'cid' and 'ka'.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
{
char *value;
while (*arg != '\0') {
case NET:
/*
* Network number.
*/
break;
case CID:
/*
* Client ID.
*/
break;
case TYPE:
/*
* Key type.
*/
if (ret != WBKU_SUCCESS) {
return (KEYGEN_ERROR);
}
break;
default:
return (KEYGEN_ERROR);
}
}
/*
* Sanity checks
*/
wbku_printerr("Missing net option value\n");
return (KEYGEN_ERROR);
}
wbku_printerr("Missing cid option value\n");
return (KEYGEN_ERROR);
}
"The cid option requires net option specification\n");
return (KEYGEN_ERROR);
}
wbku_printerr("Missing key type option value\n");
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}
/*
* This routine parses a buffer to determine whether or not it
* contains a hexascii string. If the buffer contains any characters
* that are not hexascii, then it is not a hexascii string. Since
* this function is used to validate a CID value (which is then used
* to identify a directory in the filesystem), no evaluation of the
* string is performed. That is, hex strings are not padded (e.g. "A"
* is not padded to "0A").
*
* Returns:
* B_TRUE or B_FALSE
*/
static boolean_t
{
return (B_FALSE);
}
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* This routine uses the 'net' and the 'cid' to generate the client's
* keystore filename and, if requested, creates the directory path to
* the file if any of the directories do not exist. If directory path
* creation is not requested and any of the directories do not exist,
* then an error is returned.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
{
return (KEYGEN_ERROR);
"%s must be an even number of hexadecimal characters\n",
cid);
return (KEYGEN_ERROR);
} else {
}
/*
* Shouldn't be a problem, but make sure buffer was big enough.
*/
wbku_printerr("Keystore path too long\n");
return (KEYGEN_ERROR);
}
/*
* If directory creation is allowed, then try to create it.
* If the directory already exists, then march on.
*/
if (create) {
wbku_printerr("Cannot create client keystore");
return (KEYGEN_ERROR);
}
}
/*
* Append the filename.
*/
wbku_printerr("Keystore path too long\n");
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}
/*
* This routine generates a random key of the type defined by 'ka'.
* The key value is returned in 'rand_key' and the buffer pointed to
* by 'rand_key' is assumed to be of the correct size.
*
* Note:
* If 'ka' has a non-NULL keycheck value, then the routine will
* generate randon keys until a non-weak key is generated.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
{
/*
* Generate key, until non-weak key generated.
*/
for (;;) {
wbku_printerr("Cannot generate random number");
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}
}
}
/*
* This routine generates a random master key of the type (currently only
* HMAC SHA1 supported) defined by 'ka' and stores it in the master key
* file.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
{
int fd;
/*
* If the file already exists (possibly via keymgmt), then open
* the file for update. Otherwise create it and open it for
* for writing.
*/
if (fd < 0) {
}
} else {
}
}
return (KEYGEN_ERROR);
}
/*
* If the file already exists, then see if a master key already
* exists. We will not overwrite it if it does.
*/
ret = WBKU_NOKEY;
if (exists) {
if (ret != WBKU_NOKEY) {
if (ret == WBKU_SUCCESS) {
wbku_printerr("The master %s key already "
"exists and will not be overwritten\n",
} else {
}
return (KEYGEN_ERROR);
}
}
/*
* If wbku_find_key() did not find the key position for us
* (expected behavior), then we should set position to
* the end of the file.
*/
if (ret == WBKU_NOKEY &&
wbku_printerr("Internal error");
return (KEYGEN_ERROR);
}
/*
* Generate a key and write it.
*/
return (KEYGEN_ERROR);
}
if (ret != WBKU_SUCCESS) {
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}
/*
* This routine generates a random client key of the type
* defined by 'ka' and stores it in the client keystore.
* file.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
const char *cid)
{
int fd;
/*
* If the file already exists (possibly via keymgmt), then open
* the file for update. Otherwise create it and open it for
* for writing.
*/
if (fd < 0) {
}
} else {
}
}
wbku_printerr("Cannot open client keystore");
return (KEYGEN_ERROR);
}
/*
* Generate the key. Encryption keys can be generated by simply
* calling gen_key(). An HMAC SHA1 key will be generated by
* hashing the master key.
*/
case WBKU_KEY_3DES:
case WBKU_KEY_AES_128:
return (KEYGEN_ERROR);
}
break;
case WBKU_KEY_HMAC_SHA1:
/*
* Follow RFC 3118 Appendix A's algorithm to generate
*/
/*
* Open the master keystore for reading only.
*/
wbku_printerr("Cannot open master keystore");
return (KEYGEN_ERROR);
}
/*
* Find the master key.
*/
if (ret != WBKU_SUCCESS) {
if (ret == WBKU_NOKEY) {
wbku_printerr("Cannot create a client key "
"without first creating a master key\n");
} else {
}
return (KEYGEN_ERROR);
}
/*
* Now generate the client's unique ID buffer.
*/
wbku_printerr("Unique id for client is too big\n");
return (KEYGEN_ERROR);
}
/*
* Hash the buffer to create the client key.
*/
break;
case WBKU_KEY_RSA:
wbku_printerr("Cannot generate RSA key using keygen\n");
return (KEYGEN_ERROR);
default:
wbku_printerr("Internal error\n");
return (KEYGEN_ERROR);
}
/*
* Look to see if a client key of this type exists and if
* it does note its position in the file.
*/
ret = WBKU_NOKEY;
if (exists) {
return (KEYGEN_ERROR);
}
}
/*
* If wbku_find_key() did not find the key position for us,
* then we should set position to the end of the file.
*/
if (ret == WBKU_NOKEY &&
wbku_printerr("Internal error");
return (KEYGEN_ERROR);
}
/*
* Write the key.
*/
if (ret != WBKU_SUCCESS) {
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}
/*
* This routine is used to print a hexascii version of a key.
* The hexascii version of the key will be twice the length
* of 'datalen'.
*/
static void
{
/*LINTED aligned*/
}
(void) printf("\n");
}
/*
* This routine is used to print a key of the type
* described by 'ka'. If 'master' is true, then the
* key to display is the master key. Otherwise, it's a
* client key.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
static int
{
/*
* Open the keystore for reading only.
*/
wbku_printerr("Cannot open keystore");
return (KEYGEN_ERROR);
}
/*
* Find the key.
*/
if (ret != WBKU_SUCCESS) {
if (ret == WBKU_NOKEY) {
wbku_printerr("The %s %s key does not exist\n",
} else {
}
return (KEYGEN_ERROR);
}
/*
* Dump the key in hex.
*/
return (KEYGEN_SUCCESS);
}
/*
* Prints usage().
*/
static void
{
"-o net=<addr>,cid=<cid>,type=<%s|%s|%s>]\n"
" %s -d [-m | -c -o net=<addr>,cid=<cid>,"
"type=<%s|%s|%s|%s>]\n"),
}
/*
* This program is used to generate and display WAN boot encryption and
* hash keys. The paths to the keystores are predetermined. That is, the
* master keystore (used to store a master HMAC SHA1 key) will always
* reside in the default location, MASTER_KEY_FILE. The client keystores
* will always reside in default locations that are computed using their
* network number and cid values.
*
* Note:
* The master keystore can store client keys too. This program
* cannot be used to insert client keys into the master keystore.
* However, it must not corrupt any client keystore inserted into
* the file by other means (keymgmt).
*
* We do not do any file locking scheme. This means that if two
* keygen commands are run concurrently, results can be disastrous.
*
* Returns:
* KEYGEN_SUCCESS or KEYGEN_ERROR.
*/
int
{
char *filenamep;
int c;
/*
* Do the necessary magic for localization support.
*/
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
/*
* Initialize program name for use by wbku_printerr().
*/
wbku_errinit(argv[0]);
/*
* At the very least, we'll need one arg.
*/
if (argc < 2) {
return (KEYGEN_ERROR);
}
/*
* Parse the options.
*/
switch (c) {
case 'd':
/*
* Display a key.
*/
break;
case 'o':
/*
* Suboptions.
*/
return (KEYGEN_ERROR);
}
break;
case 'c':
break;
case 'm':
break;
default:
return (KEYGEN_ERROR);
}
}
/*
* Must be operating on a master or client key and if
* it's a client key, then type must have been given.
*/
return (KEYGEN_ERROR);
}
/*
* If operating on the master key, then it is an HMAC SHA1
* key. Build the correct 'ka'. If we're working on a client
* key, the 'ka' was already built as part of option parsing.
*/
if (is_master) {
if (ret != WBKU_SUCCESS) {
wbku_printerr("Internal error\n");
return (KEYGEN_ERROR);
}
} else {
/*
* Build the path to the client keystore.
*/
return (KEYGEN_ERROR);
}
}
/*
* If display chosen, go do it.
*/
if (display) {
}
/*
* Can't generate RSA key here.
*/
wbku_printerr("keygen cannot create RSA key\n");
return (KEYGEN_ERROR);
}
/*
* If generating a master key, go do it.
*/
if (is_master) {
return (master_gen_key(&ka));
}
/*
* Must be generating a client key, go do it.
*/
net = default_net;
}
cid = default_cid;
}
return (KEYGEN_ERROR);
}
return (KEYGEN_SUCCESS);
}