summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libelfsign/common/elfcertlib.c30
-rw-r--r--usr/src/lib/libelfsign/common/elfsignlib.c2
-rw-r--r--usr/src/lib/libelfsign/common/libelfsign.h5
-rw-r--r--usr/src/lib/pkcs11/libpkcs11/common/pkcs11Conf.c282
4 files changed, 190 insertions, 129 deletions
diff --git a/usr/src/lib/libelfsign/common/elfcertlib.c b/usr/src/lib/libelfsign/common/elfcertlib.c
index c8238fbfe9..98d71d0fd0 100644
--- a/usr/src/lib/libelfsign/common/elfcertlib.c
+++ b/usr/src/lib/libelfsign/common/elfcertlib.c
@@ -52,11 +52,17 @@ const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR;
/*
* The CACERT and OBJCACERT are the Cryptographic Trust Anchors
* for the Solaris Cryptographic Framework.
+ *
+ * The SECACERT is the Signed Execution Trust Anchor that the
+ * Cryptographic Framework uses for FIPS-140 validation of non-crypto
+ * binaries
*/
static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA";
static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA";
+static const char _PATH_CRYPTO_SECACERT[] = ETC_CERTS_DIR "/SUNWSolarisCA";
static ELFCert_t CACERT = NULL;
static ELFCert_t OBJCACERT = NULL;
+static ELFCert_t SECACERT = NULL;
static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER;
static void elfcertlib_freecert(ELFsign_t, ELFCert_t);
@@ -95,10 +101,18 @@ elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT,
NULL, &CACERT, ES_GET);
}
+
if (OBJCACERT == NULL) {
(void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT,
NULL, &OBJCACERT, ES_GET);
}
+
+ if (SECACERT == NULL) {
+ (void) elfcertlib_getcert(ess,
+ (char *)_PATH_CRYPTO_SECACERT, NULL, &SECACERT,
+ ES_GET_FIPS140);
+ }
+
(void) pthread_mutex_unlock(&ca_mutex);
if (CACERT != NULL) {
@@ -139,6 +153,19 @@ elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert)
}
}
+ if (SECACERT != NULL) {
+ rv = KMF_VerifyCertWithCert(ess->es_kmfhandle,
+ (const KMF_DATA *)&cert->c_cert,
+ (const KMF_DATA *)&SECACERT->c_cert.certificate);
+ if (rv == KMF_OK) {
+ if (ess->es_certCAcallback != NULL)
+ (ess->es_certvercallback)(ess->es_callbackctx,
+ cert, SECACERT);
+ cert->c_verified = E_OK;
+ return (B_TRUE);
+ }
+ }
+
return (B_FALSE);
}
@@ -266,7 +293,8 @@ elfcertlib_getcert(ELFsign_t ess, char *cert_pathname,
*/
if (cert_pathname != NULL && (
strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 ||
- strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0)) {
+ strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0 ||
+ strcmp(cert_pathname, _PATH_CRYPTO_SECACERT) == 0)) {
if (ess->es_certCAcallback != NULL)
(ess->es_certCAcallback)(ess->es_callbackctx, cert,
cert_pathname);
diff --git a/usr/src/lib/libelfsign/common/elfsignlib.c b/usr/src/lib/libelfsign/common/elfsignlib.c
index 1eacfd1db7..8ef0aa4d0b 100644
--- a/usr/src/lib/libelfsign/common/elfsignlib.c
+++ b/usr/src/lib/libelfsign/common/elfsignlib.c
@@ -256,6 +256,7 @@ elfsign_begin(const char *filename, enum ES_ACTION action, ELFsign_t *essp)
switch (action) {
case ES_GET:
case ES_GET_CRYPTO:
+ case ES_GET_FIPS140:
cryptodebug("elfsign_begin for get");
elfcmd = ELF_C_READ;
oflags = O_RDONLY | O_NOCTTY | O_NDELAY;
@@ -1155,6 +1156,7 @@ elfsign_verify_signature(ELFsign_t ess, struct ELFsign_sig_info **esipp)
* force verification of crypto certs
*/
if ((ess->es_action == ES_GET_CRYPTO ||
+ ess->es_action == ES_GET_FIPS140 ||
strstr(fsx.fsx_signer_DN, ELFSIGN_CRYPTO)) &&
!elfcertlib_verifycert(ess, cert)) {
cryptodebug("elfsign_verify_signature: invalid cert");
diff --git a/usr/src/lib/libelfsign/common/libelfsign.h b/usr/src/lib/libelfsign/common/libelfsign.h
index 8637fc4c6d..cfbb627eea 100644
--- a/usr/src/lib/libelfsign/common/libelfsign.h
+++ b/usr/src/lib/libelfsign/common/libelfsign.h
@@ -20,15 +20,13 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _LIBELFSIGN_H
#define _LIBELFSIGN_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -78,6 +76,7 @@ typedef struct ELFCert_s {
enum ES_ACTION {
ES_GET,
ES_GET_CRYPTO,
+ ES_GET_FIPS140,
ES_UPDATE,
ES_UPDATE_RSA_MD5_SHA1,
ES_UPDATE_RSA_SHA1
diff --git a/usr/src/lib/pkcs11/libpkcs11/common/pkcs11Conf.c b/usr/src/lib/pkcs11/libpkcs11/common/pkcs11Conf.c
index 5528ebb8c6..2299628a2c 100644
--- a/usr/src/lib/pkcs11/libpkcs11/common/pkcs11Conf.c
+++ b/usr/src/lib/pkcs11/libpkcs11/common/pkcs11Conf.c
@@ -271,6 +271,150 @@ cryptosvc_is_down(void)
return (ret);
}
+
+/* Generic function for all door calls to kcfd. */
+ELFsign_status_t
+kcfd_door_call(char *fullpath, boolean_t fips140, CK_RV *rv)
+{
+ boolean_t try_door_open_again = B_FALSE;
+ int kcfdfd = -1;
+ door_arg_t darg;
+ kcf_door_arg_t *kda = NULL;
+ kcf_door_arg_t *rkda = NULL;
+ int r;
+ int is_cryptosvc_up_count = 0;
+ int door_errno = 0;
+ ELFsign_status_t estatus = ELFSIGN_UNKNOWN;
+
+open_door_file:
+ while ((kcfdfd = open(_PATH_KCFD_DOOR, O_RDONLY)) == -1) {
+ /* save errno and test for EINTR or EAGAIN */
+ door_errno = errno;
+ if (door_errno == EINTR ||
+ door_errno == EAGAIN)
+ continue;
+ /* if disabled or maintenance mode - bail */
+ if (cryptosvc_is_down())
+ break;
+ /* exceeded our number of tries? */
+ if (is_cryptosvc_up_count > MAX_CRYPTOSVC_ONLINE_TRIES)
+ break;
+ /* any other state, try again up to 1/2 minute */
+ (void) sleep(5);
+ is_cryptosvc_up_count++;
+ }
+ if (kcfdfd == -1) {
+ if (!cryptosvc_is_online()) {
+ cryptoerror(LOG_ERR, "libpkcs11: unable to open"
+ " kcfd door_file %s: %s. %s is not online."
+ " (see svcs -xv for details).",
+ _PATH_KCFD_DOOR, strerror(door_errno),
+ CRYPTOSVC_DEFAULT_INSTANCE_FMRI);
+ } else {
+ cryptoerror(LOG_ERR, "libpkcs11: unable to open"
+ " kcfd door_file %s: %s.", _PATH_KCFD_DOOR,
+ strerror(door_errno));
+ }
+ *rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ estatus = ELFSIGN_UNKNOWN;
+ goto verifycleanup;
+ }
+
+ /* Mark the door "close on exec" */
+ (void) fcntl(kcfdfd, F_SETFD, FD_CLOEXEC);
+
+ if ((kda = malloc(sizeof (kcf_door_arg_t))) == NULL) {
+ cryptoerror(LOG_ERR, "libpkcs11: malloc of kda "
+ "failed: %s", strerror(errno));
+ goto verifycleanup;
+ }
+
+ if (fips140 == B_TRUE)
+ kda->da_version = KCFD_FIPS140_INTCHECK;
+ else {
+ kda->da_version = KCF_KCFD_VERSION1;
+ (void) strlcpy(kda->da_u.filename, fullpath,
+ strlen(fullpath) + 1);
+ }
+
+ kda->da_iskernel = B_FALSE;
+
+ darg.data_ptr = (char *)kda;
+ darg.data_size = sizeof (kcf_door_arg_t);
+ darg.desc_ptr = NULL;
+ darg.desc_num = 0;
+ darg.rbuf = (char *)kda;
+ darg.rsize = sizeof (kcf_door_arg_t);
+
+ while ((r = door_call(kcfdfd, &darg)) != 0) {
+ /* save errno and test for certain errors */
+ door_errno = errno;
+ if (door_errno == EINTR || door_errno == EAGAIN)
+ continue;
+ /* if disabled or maintenance mode - bail */
+ if (cryptosvc_is_down())
+ break;
+ /* exceeded our number of tries? */
+ if (is_cryptosvc_up_count > MAX_CRYPTOSVC_ONLINE_TRIES)
+ break;
+ /* if stale door_handle, retry the open */
+ if (door_errno == EBADF) {
+ try_door_open_again = B_TRUE;
+ is_cryptosvc_up_count++;
+ (void) sleep(5);
+ goto verifycleanup;
+ } else
+ break;
+ }
+
+ if (r != 0) {
+ if (!cryptosvc_is_online()) {
+ cryptoerror(LOG_ERR, "%s is not online "
+ " - unable to utilize cryptographic "
+ "services. (see svcs -xv for details).",
+ CRYPTOSVC_DEFAULT_INSTANCE_FMRI);
+ } else {
+ cryptoerror(LOG_ERR, "libpkcs11: door_call "
+ "of door_file %s failed with error %s.",
+ _PATH_KCFD_DOOR, strerror(door_errno));
+ }
+ *rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ estatus = ELFSIGN_UNKNOWN;
+ goto verifycleanup;
+ }
+
+ /*LINTED*/
+ rkda = (kcf_door_arg_t *)darg.rbuf;
+ if ((fips140 == B_FALSE && rkda->da_version != KCF_KCFD_VERSION1) ||
+ (fips140 == B_TRUE && rkda->da_version != KCFD_FIPS140_INTCHECK)) {
+ cryptoerror(LOG_ERR,
+ "libpkcs11: kcfd and libelfsign versions "
+ "don't match: got %d expected %d", rkda->da_version,
+ (fips140) ? KCFD_FIPS140_INTCHECK : KCF_KCFD_VERSION1);
+ goto verifycleanup;
+ }
+ estatus = rkda->da_u.result.status;
+verifycleanup:
+ if (kcfdfd != -1) {
+ (void) close(kcfdfd);
+ }
+ if (rkda != NULL && rkda != kda)
+ (void) munmap((char *)rkda, darg.rsize);
+ if (kda != NULL) {
+ bzero(kda, sizeof (kda));
+ free(kda);
+ kda = NULL;
+ rkda = NULL; /* rkda is an alias of kda */
+ }
+ if (try_door_open_again) {
+ try_door_open_again = B_FALSE;
+ goto open_door_file;
+ }
+
+ return (estatus);
+}
+
+
/*
* For each provider found in pkcs11.conf: expand $ISA if necessary,
* verify the module is signed, load the provider, find all of its
@@ -313,14 +457,18 @@ pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs)
ELFsign_status_t estatus = ELFSIGN_UNKNOWN;
char *estatus_str = NULL;
- int kcfdfd = -1;
- door_arg_t darg;
- kcf_door_arg_t *kda = NULL;
- kcf_door_arg_t *rkda = NULL;
- int r;
- int is_cryptosvc_up_count = 0;
- int door_errno = 0;
- boolean_t try_door_open_again = B_FALSE;
+ int fips140_mode = CRYPTO_FIPS_MODE_DISABLED;
+
+ /* Check FIPS 140 configuration and execute check if enabled */
+ (void) get_fips_mode(&fips140_mode);
+ if (fips140_mode) {
+ estatus = kcfd_door_call(NULL, B_TRUE, &rv);
+ if (estatus != ELFSIGN_SUCCESS) {
+ cryptoerror(LOG_ERR, "libpkcs11: failed FIPS 140 "
+ "integrity check.");
+ return (CKR_GENERAL_ERROR);
+ }
+ }
phead = pplist;
@@ -538,123 +686,7 @@ pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs)
* kcfd libelfsign door protocol to use and fd instead
* of a path - but that wouldn't work in the kernel case.
*/
-open_door_file:
- while ((kcfdfd = open(_PATH_KCFD_DOOR, O_RDONLY)) == -1) {
- /* save errno and test for EINTR or EAGAIN */
- door_errno = errno;
- if (door_errno == EINTR ||
- door_errno == EAGAIN)
- continue;
- /* if disabled or maintenance mode - bail */
- if (cryptosvc_is_down())
- break;
- /* exceeded our number of tries? */
- if (is_cryptosvc_up_count > MAX_CRYPTOSVC_ONLINE_TRIES)
- break;
- /* any other state, try again up to 1/2 minute */
- (void) sleep(5);
- is_cryptosvc_up_count++;
- }
- if (kcfdfd == -1) {
- if (!cryptosvc_is_online()) {
- cryptoerror(LOG_ERR, "libpkcs11: unable to open"
- " kcfd door_file %s: %s. %s is not online."
- " (see svcs -xv for details).",
- _PATH_KCFD_DOOR, strerror(door_errno),
- CRYPTOSVC_DEFAULT_INSTANCE_FMRI);
- } else {
- cryptoerror(LOG_ERR, "libpkcs11: unable to open"
- " kcfd door_file %s: %s.", _PATH_KCFD_DOOR,
- strerror(door_errno));
- }
- rv = CKR_CRYPTOKI_NOT_INITIALIZED;
- estatus = ELFSIGN_UNKNOWN;
- goto verifycleanup;
- }
-
- /* Mark the door "close on exec" */
- (void) fcntl(kcfdfd, F_SETFD, FD_CLOEXEC);
-
- if ((kda = malloc(sizeof (kcf_door_arg_t))) == NULL) {
- cryptoerror(LOG_ERR, "libpkcs11: malloc of kda "
- "failed: %s", strerror(errno));
- goto verifycleanup;
- }
- kda->da_version = KCF_KCFD_VERSION1;
- kda->da_iskernel = B_FALSE;
- (void) strlcpy(kda->da_u.filename, fullpath,
- strlen(fullpath) + 1);
-
- darg.data_ptr = (char *)kda;
- darg.data_size = sizeof (kcf_door_arg_t);
- darg.desc_ptr = NULL;
- darg.desc_num = 0;
- darg.rbuf = (char *)kda;
- darg.rsize = sizeof (kcf_door_arg_t);
-
- while ((r = door_call(kcfdfd, &darg)) != 0) {
- /* save errno and test for certain errors */
- door_errno = errno;
- if (door_errno == EINTR || door_errno == EAGAIN)
- continue;
- /* if disabled or maintenance mode - bail */
- if (cryptosvc_is_down())
- break;
- /* exceeded our number of tries? */
- if (is_cryptosvc_up_count > MAX_CRYPTOSVC_ONLINE_TRIES)
- break;
- /* if stale door_handle, retry the open */
- if (door_errno == EBADF) {
- try_door_open_again = B_TRUE;
- is_cryptosvc_up_count++;
- (void) sleep(5);
- goto verifycleanup;
- } else
- break;
- }
-
- if (r != 0) {
- if (!cryptosvc_is_online()) {
- cryptoerror(LOG_ERR, "%s is not online "
- " - unable to utilize cryptographic "
- "services. (see svcs -xv for details).",
- CRYPTOSVC_DEFAULT_INSTANCE_FMRI);
- } else {
- cryptoerror(LOG_ERR, "libpkcs11: door_call "
- "of door_file %s failed with error %s.",
- _PATH_KCFD_DOOR, strerror(door_errno));
- }
- rv = CKR_CRYPTOKI_NOT_INITIALIZED;
- estatus = ELFSIGN_UNKNOWN;
- goto verifycleanup;
- }
-
- /*LINTED*/
- rkda = (kcf_door_arg_t *)darg.rbuf;
- if (rkda->da_version != KCF_KCFD_VERSION1) {
- cryptoerror(LOG_ERR,
- "libpkcs11: kcfd and libelfsign versions "
- "don't match: got %d expected %d",
- rkda->da_version, KCF_KCFD_VERSION1);
- goto verifycleanup;
- }
- estatus = rkda->da_u.result.status;
-verifycleanup:
- if (kcfdfd != -1) {
- (void) close(kcfdfd);
- }
- if (rkda != NULL && rkda != kda)
- (void) munmap((char *)rkda, darg.rsize);
- if (kda != NULL) {
- bzero(kda, sizeof (kda));
- free(kda);
- kda = NULL;
- rkda = NULL; /* rkda is an alias of kda */
- }
- if (try_door_open_again) {
- try_door_open_again = B_FALSE;
- goto open_door_file;
- }
+ estatus = kcfd_door_call(fullpath, B_FALSE, &rv);
switch (estatus) {
case ELFSIGN_UNKNOWN: