/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
*/
/*
* Developer command for adding the signature section to an ELF object
* PSARC 2001/488
*
* DEBUG Information:
* This command uses the cryptodebug() function from libcryptoutil.
* Set SUNW_CRYPTO_DEBUG to stderr or syslog for all debug to go to auth.debug
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <libintl.h>
#include <locale.h>
#include <errno.h>
#include <strings.h>
#include <cryptoutil.h>
#include <libelfsign.h>
#include <kmfapi.h>
enum cmd_e {
};
enum field_e {
};
static struct {
/* -r <certificate_request_file> */
int elfcnt;
int extracnt;
} cmd_info;
enum ret_e {
};
struct field_s {
char *name;
} fields[] = {
{ "subject", FLD_SUBJECT },
{ "issuer", FLD_ISSUER },
{ "format", FLD_FORMAT },
{ "signer", FLD_SIGNER },
{ "time", FLD_TIME },
NULL, 0
};
static void usage(void);
static char *getpin(void);
static ret_t do_cert_request(char *);
int
{
extern char *optarg;
char c; /* current getopts flag */
#if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
cryptodebug_init("elfsign");
usage();
return (EXIT_INVALID_ARG);
}
opts = VERIFY_OPTS;
opts = REQUEST_OPTS;
} else {
scmd);
usage();
return (EXIT_INVALID_ARG);
}
/*
* Note: There is no need to check that optarg isn't NULL
* because getopt does that for us.
*/
else
cryptodebug("c=%c", c);
switch (c) {
case 'c':
break;
case 'e':
"Too many elf objects specified."));
return (EXIT_INVALID_ARG);
}
break;
case 'f':
{
break;
}
}
cryptodebug("Invalid field option");
errflag++;
}
}
break;
case 'F':
else {
cryptodebug("Invalid format option");
errflag++;
}
break;
case 'i': /* Undocumented internal Sun use only */
break;
case 'k':
errflag++;
break;
case 'P':
errflag++;
break;
case 'r':
break;
case 'T':
errflag++;
break;
case 'v':
break;
default:
errflag++;
}
}
optind++; /* we skipped over subcommand */
cryptodebug("Extra arguments, optind=%d, argc=%d",
errflag++;
}
case ES_VERIFY:
cryptodebug("Missing elfobj");
errflag++;
}
break;
case ES_SIGN:
cryptodebug("Missing privpath|token_label/cert/elfobj");
errflag++;
}
break;
case ES_REQUEST:
cryptodebug("Missing privpath|token_label/certreq");
errflag++;
}
break;
case ES_LIST:
cryptodebug("Neither or both of cert/elfobj");
errflag++;
}
break;
}
if (errflag) {
usage();
return (EXIT_INVALID_ARG);
}
case ES_REQUEST:
case ES_LIST:
break;
default:
{
int i;
}
}
break;
}
}
return (ret);
}
static void
usage(void)
{
/* BEGIN CSTYLED */
"usage:\n"
"\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
"\t\t[-F <format>] -k <private_key_file> [elf_object]..."
"\n"
"\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
"\t\t[-F <format>] -T <token_label> [-P <pin_file>] [elf_object]..."
"\n\n"
"\telfsign verify [-v] [-c <certificate_file>] [-e <elf_object>]\n"
"\t\t[elf_object]..."
"\n\n"
"\telfsign request -r <certificate_request_file> -k <private_key_file>"
"\n"
"\telfsign request -r <certificate_request_file> -T <token_label>"
"\n\n"
"\telfsign list -f field -c <certificate_file>"
"\n"
"\telfsign list -f field -e <elf_object>"
"\n"));
/* END CSTYLED */
}
static ret_t
{
switch (estatus) {
case ELFSIGN_SUCCESS:
break;
case ELFSIGN_INVALID_ELFOBJ:
"Unable to open %s as an ELF object."),
elfpath);
break;
default:
}
}
return (ret);
}
static ret_t
setcertpath(void)
{
return (EXIT_OKAY);
switch (estatus) {
case ELFSIGN_SUCCESS:
break;
case ELFSIGN_INVALID_CERTPATH:
}
ret = EXIT_BAD_CERT;
break;
default:
}
}
return (ret);
}
/*
* getpin - return pointer to token PIN in static storage
*/
static char *
getpin(void)
{
char *pp;
return (getpassphrase(
gettext("Enter PIN for PKCS#11 token: ")));
return (NULL);
}
return (NULL);
}
if (*pp == '\n')
*pp = '\0';
return (pinbuf);
}
/*
* Add the .SUNW_signature sections for the ELF signature
*/
static ret_t
{
char *dn;
cryptodebug("do_sign");
return (ret);
if (cmd_info.token_label &&
goto cleanup;
}
goto cleanup;
ret = EXIT_BAD_CERT;
goto cleanup;
}
goto cleanup;
}
} else {
goto cleanup;
}
goto cleanup;
}
}
/*
* Get the DN from the certificate.
*/
goto cleanup;
}
if (elfstat != ELFSIGN_SUCCESS) {
if (elfstat != ELFSIGN_NOTSIGNED) {
"signature block in %s"), object);
goto cleanup;
}
/*
* force creation and naming of signature section
* so the hash doesn't change
*/
"signature block into %s"), object);
goto cleanup;
}
}
object);
goto cleanup;
}
goto cleanup;
}
{ /* DEBUG START */
} /* DEBUG END */
object);
goto cleanup;
}
object);
goto cleanup;
}
gettext("elfsign: %s signed successfully.\n"),
object);
}
}
}
return (ret);
}
/*
* Verify the signature of the object
* This subcommand is intended to be used by developers during their build
* processes. Therefore we can not assume that the certificate is in
*/
static ret_t
{
cryptodebug("do_verify");
return (retval);
return (retval);
}
switch (res) {
case ELFSIGN_SUCCESS:
gettext("elfsign: verification of %s passed.\n"),
object);
break;
case ELFSIGN_FAILED:
case ELFSIGN_INVALID_CERTPATH:
object);
break;
case ELFSIGN_NOTSIGNED:
object);
break;
default:
"of %s."), object);
break;
}
return (retval);
}
#define SET_VALUE(f, s) \
kmfrv = f; \
char *e = NULL; \
(void) kmf_get_kmf_error_str(kmfrv, &e); \
gettext("Failed to %s: %s\n"), \
s, (e ? e : "unknown error")); \
if (e) free(e); \
goto cleanup; \
}
static KMF_RETURN
{
char *err;
int numattr;
gettext("Error initializing KMF: %s\n"),
if (err)
return (kmfrv);
}
} else {
/* args checking verified (cmd_info.token_label != NULL) */
/* Get a PIN to store the private key in the token */
(void) kmf_finalize(kmfhandle);
return (KMF_ERR_AUTH_FAILED);
}
numattr = 0;
goto cleanup;
}
}
/* Create the RSA keypair */
numattr = 0;
}
if (kstype == KMF_KEYSTORE_OPENSSL) {
}
gettext("Create RSA keypair failed: %s"),
goto cleanup;
}
gettext("Error parsing subject name: %s\n"),
goto cleanup;
}
KMF_OK) {
}
(void) kmf_free_data(&signedCsr);
(void) kmf_free_signed_csr(&csr);
(void) kmf_finalize(kmfhandle);
return (kmfrv);
}
/*
* Generate a certificate request into the file named cmd_info.cert
*/
/*ARGSUSED*/
static ret_t
{
const char PartnerDNFMT[] =
"CN=%s, "
"OU=Class B, "
"OU=Solaris Cryptographic Framework, "
"OU=Partner Object Signing, "
"O=Sun Microsystems Inc";
const char SunCDNFMT[] =
"CN=%s, "
"OU=Class B, "
"OU=Solaris Cryptographic Framework, "
"OU=Corporate Object Signing, "
"O=Sun Microsystems Inc";
const char SunSDNFMT[] =
"CN=%s, "
"OU=Class B, "
"OU=Solaris Signed Execution, "
"OU=Corporate Object Signing, "
"O=Sun Microsystems Inc";
cryptodebug("do_cert_request");
/*
* Get the DN prefix from the user
*/
switch (cmd_info.internal_req) {
case 'c':
"Enter Sun Microsystems, Inc. Release name.\n"
"This will be the prefix of the Certificate DN: "));
break;
case 's':
"Enter Sun Microsystems, Inc. Release name.\n"
"This will be the prefix of the Certificate DN: "));
break;
default:
"Enter Company Name / Stock Symbol"
" or some other globally unique identifier.\n"
"This will be the prefix of the Certificate DN: "));
break;
}
return (EXIT_INVALID_ARG);
}
} else {
"of no more than %d characters"), CN_MAX_LENGTH);
return (EXIT_INVALID_ARG);
}
/* Update DN string */
return (EXIT_OKAY);
else
return (EXIT_CSR_FAILED);
}
static void
str_print(char *s)
{
if (s == NULL)
return;
}
/*ARGSUSED*/
static ret_t
{
return (retval);
if (elfstat == ELFSIGN_SUCCESS) {
case FLD_FORMAT:
break;
case FLD_SIGNER:
break;
case FLD_TIME:
else
break;
default:
}
}
} else
} else {
/*
* Initialize the ESS record here even though we are not
* actually opening any ELF files.
*/
return (EXIT_MEMORY_ERROR);
case FLD_SUBJECT:
break;
case FLD_ISSUER:
break;
default:
}
} else
}
return (retval);
}
static void
{
}
static char *
{
char *bufp;
return (bufp);
}
static void
{
return;
return;
}