summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorHai-May Chao <Hai-May.Chao@Sun.COM>2009-09-11 09:04:22 -0700
committerHai-May Chao <Hai-May.Chao@Sun.COM>2009-09-11 09:04:22 -0700
commitb5a2d8455dfa3190fc977c4bec53e91c99012767 (patch)
treebff1e4f897b4291273be1f3f4c90125be60353b7 /usr/src
parent44da779fd55c337eb9877e490e494037fc1ddf06 (diff)
downloadillumos-gate-b5a2d8455dfa3190fc977c4bec53e91c99012767.tar.gz
PSARC 2009/347 cryptoadm(1M) enhancement for FIPS-140 mode
6787364 Administration and policy configuration changes to support FIPS 140-2 6867384 Solaris Crypto Framework needs to implement self tests for FIPS 140-2 compliance
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c123
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c137
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_util.c88
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c176
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_util.c227
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c78
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.h26
-rw-r--r--usr/src/common/crypto/aes/aes_impl.h75
-rw-r--r--usr/src/common/crypto/des/des_impl.h61
-rw-r--r--usr/src/common/crypto/ecc/ec.c48
-rw-r--r--usr/src/common/crypto/ecc/ecc_impl.h6
-rw-r--r--usr/src/common/crypto/fips/fips_aes_util.c1765
-rw-r--r--usr/src/common/crypto/fips/fips_des_util.c658
-rw-r--r--usr/src/common/crypto/fips/fips_ecc_util.c220
-rw-r--r--usr/src/common/crypto/fips/fips_post.h61
-rw-r--r--usr/src/common/crypto/fips/fips_random_util.c89
-rw-r--r--usr/src/common/crypto/fips/fips_rsa_util.c942
-rw-r--r--usr/src/common/crypto/fips/fips_sha1_util.c369
-rw-r--r--usr/src/common/crypto/fips/fips_sha2_util.c779
-rw-r--r--usr/src/common/crypto/rng/fips_random.c35
-rw-r--r--usr/src/common/crypto/rng/fips_random.h10
-rw-r--r--usr/src/common/crypto/rsa/rsa_impl.h56
-rw-r--r--usr/src/common/crypto/sha1/sha1_impl.h96
-rw-r--r--usr/src/common/crypto/sha2/sha2_impl.h89
-rw-r--r--usr/src/lib/libcryptoutil/common/config_parsing.c106
-rw-r--r--usr/src/lib/libcryptoutil/common/cryptoutil.h12
-rw-r--r--usr/src/lib/libcryptoutil/common/mapfile-vers1
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com41
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSA.h68
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSAUtil.c503
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPost.c159
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPostUtil.c178
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c25
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softGlobal.h3
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c31
-rw-r--r--usr/src/uts/common/Makefile.files14
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/crypto/api/kcf_random.c5
-rw-r--r--usr/src/uts/common/crypto/core/kcf.c12
-rw-r--r--usr/src/uts/common/crypto/io/aes.c44
-rw-r--r--usr/src/uts/common/crypto/io/cryptoadm.c67
-rw-r--r--usr/src/uts/common/crypto/io/ecc.c90
-rw-r--r--usr/src/uts/common/crypto/io/rsa.c21
-rw-r--r--usr/src/uts/common/crypto/io/sha1_mod.c45
-rw-r--r--usr/src/uts/common/crypto/io/sha2_mod.c34
-rw-r--r--usr/src/uts/common/crypto/io/swrand.c18
-rw-r--r--usr/src/uts/common/des/des_crypt.c25
-rw-r--r--usr/src/uts/common/sys/crypto/impl.h1
-rw-r--r--usr/src/uts/common/sys/crypto/ioctladmin.h34
-rw-r--r--usr/src/uts/intel/ecc/Makefile10
-rw-r--r--usr/src/uts/intel/rsa/Makefile5
-rw-r--r--usr/src/uts/intel/sha1/Makefile15
-rw-r--r--[-rwxr-xr-x]usr/src/uts/intel/sha2/Makefile17
-rw-r--r--usr/src/uts/sparc/ecc/Makefile10
-rw-r--r--usr/src/uts/sparc/rsa/Makefile5
-rw-r--r--usr/src/uts/sparc/sha1/Makefile12
-rw-r--r--usr/src/uts/sparc/sha2/Makefile12
-rw-r--r--usr/src/uts/sun4u/Makefile.files2
-rw-r--r--usr/src/uts/sun4u/sha1/Makefile12
59 files changed, 7449 insertions, 409 deletions
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
index 752e8539d1..66b59a34fd 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -43,12 +43,15 @@ static int check_hardware_provider(char *, char *, int *, int *);
* Display the mechanism list for a kernel software provider.
* This implements part of the "cryptoadm list -m" command.
*
- * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
- * If NULL, this function obtains it by calling get_kcfconf_info() internally.
+ * Parameters phardlist, psoftlist and pfipslist are supplied by
+ * get_soft_info().
+ * If NULL, this function obtains it by calling getent_kef() and
+ * then get_kcfconf_info() via get_soft_info() internally.
*/
int
list_mechlist_for_soft(char *provname,
- entrylist_t *phardlist, entrylist_t *psoftlist)
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist)
{
mechlist_t *pmechlist = NULL;
int rc;
@@ -57,7 +60,8 @@ list_mechlist_for_soft(char *provname,
return (FAILURE);
}
- rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
+ rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist,
+ pfipslist);
if (rc == SUCCESS) {
(void) filter_mechlist(&pmechlist, RANDOM);
print_mechlist(provname, pmechlist);
@@ -113,12 +117,15 @@ list_mechlist_for_hard(char *provname)
* Display the policy information for a kernel software provider.
* This implements part of the "cryptoadm list -p" command.
*
- * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
- * If NULL, this function obtains it by calling get_kcfconf_info() internally.
+ * Parameters phardlist, psoftlist and pfipslist are supplied by
+ * getent_kef().
+ * If NULL, this function obtains it by calling get_kcfconf_info()
+ * via getent_kef() internally.
*/
int
list_policy_for_soft(char *provname,
- entrylist_t *phardlist, entrylist_t *psoftlist)
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist)
{
int rc;
entry_t *pent = NULL;
@@ -138,9 +145,11 @@ list_policy_for_soft(char *provname,
provname);
return (FAILURE);
}
- pent = getent_kef(provname, phardlist, psoftlist);
+ pent = getent_kef(provname, phardlist, psoftlist,
+ pfipslist);
- rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
+ rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist,
+ pfipslist);
if (rc == SUCCESS) {
has_random = filter_mechlist(&pmechlist, RANDOM);
if (pmechlist != NULL) {
@@ -165,15 +174,17 @@ list_policy_for_soft(char *provname,
* Display the policy information for a kernel hardware provider.
* This implements part of the "cryptoadm list -p" command.
*
- * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
- * If NULL, this function obtains it by calling get_kcfconf_info() internally.
- * Parameter pdevlist is supplied by get_dev_list().
- * If NULL, this function obtains it by calling get_dev_list() internally.
+ * Parameters phardlist, psoftlist and pfipslist are supplied by getent_kef().
+ * If NULL, this function obtains it by calling get_kcfconf_info() via
+ * getent_kef() internally.
+ * Parameter pdevlist is supplied by check_kernel_for_hard().
+ * If NULL, this function obtains it by calling get_dev_list() via
+ * check_kernel_for_hard() internally.
*/
int
list_policy_for_hard(char *provname,
entrylist_t *phardlist, entrylist_t *psoftlist,
- crypto_get_dev_list_t *pdevlist)
+ entrylist_t *pfipslist, crypto_get_dev_list_t *pdevlist)
{
entry_t *pent = NULL;
boolean_t in_kernel;
@@ -220,7 +231,8 @@ list_policy_for_hard(char *provname,
* the disabled list from the config file entry. Otherwise,
* if it is active, then all the mechanisms for it are enabled.
*/
- if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
+ if ((pent = getent_kef(provname, phardlist, psoftlist,
+ pfipslist)) != NULL) {
print_kef_policy(provname, pent, has_random, has_mechs);
free_entry(pent);
return (SUCCESS);
@@ -292,7 +304,7 @@ disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
* Get the entry of this hardware provider from the config file.
* If there is no entry yet, create one for it.
*/
- if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
+ if ((pent = getent_kef(provname, NULL, NULL, NULL)) == NULL) {
if ((pent = create_entry(provname)) == NULL) {
cryptoerror(LOG_STDERR, gettext("out of memory."));
free_mechlist(infolist);
@@ -387,6 +399,7 @@ disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
entry_t *pent = NULL;
entrylist_t *phardlist = NULL;
entrylist_t *psoftlist = NULL;
+ entrylist_t *pfipslist = NULL;
boolean_t in_kernel = B_FALSE;
int fd = -1;
int rc = SUCCESS;
@@ -400,7 +413,8 @@ disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
* If it is unloaded, return FAILURE, because the disable subcommand
* can not perform on inactive (unloaded) providers.
*/
- if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
+ if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
+ FAILURE) {
return (FAILURE);
} else if (in_kernel == B_FALSE) {
cryptoerror(LOG_STDERR,
@@ -409,7 +423,8 @@ disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
return (FAILURE);
}
- if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
+ if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) ==
+ FAILURE) {
cryptoerror(LOG_ERR,
"failed to retrieve the providers' "
"information from the configuration file - %s.",
@@ -421,7 +436,7 @@ disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
* Get the entry of this provider from the kcf.conf file, if any.
* Otherwise, create a new kcf.conf entry for writing back to the file.
*/
- pent = getent_kef(provname, phardlist, psoftlist);
+ pent = getent_kef(provname, phardlist, psoftlist, pfipslist);
if (pent == NULL) { /* create a new entry */
pent = create_entry(provname);
if (pent == NULL) {
@@ -432,8 +447,8 @@ disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
}
/* Get the mechanism list for the software provider from the kernel */
- if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
- FAILURE) {
+ if (get_soft_info(provname, &infolist, phardlist, psoftlist,
+ pfipslist) == FAILURE) {
rc = FAILURE;
goto out;
}
@@ -530,7 +545,7 @@ enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
/* Get the entry of this provider from the kcf.conf file, if any. */
- pent = getent_kef(provname, NULL, NULL);
+ pent = getent_kef(provname, NULL, NULL, NULL);
if (is_device(provname)) {
if (pent == NULL) {
@@ -711,7 +726,7 @@ install_kef(char *provname, mechlist_t *mlist)
}
/* Check if the provider already exists */
- if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
+ if ((pent = getent_kef(provname, NULL, NULL, NULL)) != NULL) {
cryptoerror(LOG_STDERR, gettext("%s exists already."),
provname);
free_entry(pent);
@@ -982,7 +997,7 @@ uninstall_kef(char *provname)
*/
/* Setup ioctl() parameter */
- pent = getent_kef(provname, NULL, NULL);
+ pent = getent_kef(provname, NULL, NULL, NULL);
if (pent != NULL) { /* in kcf.conf */
in_kcfconf = B_TRUE;
free_mechlist(pent->suplist);
@@ -1053,12 +1068,14 @@ refresh(void)
crypto_load_dev_disabled_t *pload_dev_dis = NULL;
entrylist_t *pdevlist = NULL;
entrylist_t *psoftlist = NULL;
+ entrylist_t *pfipslist = NULL;
entrylist_t *ptr;
int fd = -1;
int rc = SUCCESS;
int err;
- if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
+ if (get_kcfconf_info(&pdevlist, &psoftlist, &pfipslist) ==
+ FAILURE) {
cryptoerror(LOG_ERR, "failed to retrieve the providers' "
"information from the configuration file - %s.",
_PATH_KCF_CONF);
@@ -1189,6 +1206,18 @@ refresh(void)
}
}
+ /*
+ * handle fips_status=enabled|disabled
+ */
+ ptr = pfipslist;
+ if (ptr != NULL) {
+ if (ptr->pent->flag_fips_enabled) {
+ rc = do_fips_actions(FIPS140_ENABLE, REFRESH);
+ } else {
+ rc = do_fips_actions(FIPS140_DISABLE, REFRESH);
+ }
+ }
+
(void) close(fd);
return (rc);
}
@@ -1217,7 +1246,7 @@ unload_kef_soft(char *provname)
return (FAILURE);
}
- pent = getent_kef(provname, NULL, NULL);
+ pent = getent_kef(provname, NULL, NULL, NULL);
if (pent == NULL) { /* not in kcf.conf */
/* Construct an entry using the provname */
pent = create_entry(provname);
@@ -1360,3 +1389,43 @@ check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount)
free(dev_list);
return (SUCCESS);
}
+
+int
+fips_update_kcfconf(int action)
+{
+
+ char *str;
+
+ if (action == FIPS140_ENABLE)
+ str = "fips-140:fips_status=enabled\n";
+ else
+ str = "fips-140:fips_status=disabled\n";
+
+ if (update_conf(_PATH_KCF_CONF, str) != SUCCESS)
+ return (FAILURE);
+
+ return (SUCCESS);
+}
+
+void
+fips_status_kcfconf(int *status)
+{
+
+ entry_t *pent = NULL;
+
+ if ((pent = getent_kef(FIPS_KEYWORD, NULL, NULL, NULL)) == NULL) {
+ /*
+ * By default (no FIPS entry), we assume FIPS is disabled.
+ */
+ *status = CRYPTO_FIPS_MODE_DISABLED;
+ return;
+ }
+
+ if (pent->flag_fips_enabled)
+ *status = CRYPTO_FIPS_MODE_ENABLED;
+ else
+ *status = CRYPTO_FIPS_MODE_DISABLED;
+
+ return;
+
+}
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c
index ef9c95afa2..c1c759d86a 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -402,7 +402,8 @@ get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
*/
int
get_soft_info(char *provname, mechlist_t **ppmechlist,
- entrylist_t *phardlist, entrylist_t *psoftlist)
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist)
{
boolean_t in_kernel = B_FALSE;
crypto_get_soft_info_t *psoft_info;
@@ -421,8 +422,8 @@ get_soft_info(char *provname, mechlist_t **ppmechlist,
if (getzoneid() == GLOBAL_ZONEID) {
/* use kcf.conf for kernel software providers in global zone */
- if ((pent = getent_kef(provname, phardlist, psoftlist)) ==
- NULL) {
+ if ((pent = getent_kef(provname, phardlist, psoftlist,
+ pfipslist)) == NULL) {
/* No kcf.conf entry for this provider */
if (check_kernel_for_soft(provname, NULL, &in_kernel)
@@ -605,3 +606,131 @@ get_soft_list(crypto_get_soft_list_t **ppsoftlist)
(void) close(fd);
return (SUCCESS);
}
+
+/*
+ * Perform the FIPS related actions
+ */
+int
+do_fips_actions(int action, int caller)
+{
+
+ crypto_fips140_t fips_info;
+ int fd;
+ int rc = SUCCESS;
+ int kcf_fips_mode = 0;
+
+ /* Get FIPS-140 status from kcf.conf */
+ fips_status_kcfconf(&kcf_fips_mode);
+
+ if (action == FIPS140_STATUS) {
+ if (kcf_fips_mode == CRYPTO_FIPS_MODE_ENABLED)
+ (void) printf(gettext(
+ "\tFIPS-140 mode is enabled.\n"));
+ else
+ (void) printf(gettext(
+ "\tFIPS-140 mode is disabled.\n"));
+ return (SUCCESS);
+ }
+
+ if (caller == NOT_REFRESH) {
+ /* Is it a duplicate operation? */
+ if ((action == FIPS140_ENABLE) &&
+ (kcf_fips_mode == CRYPTO_FIPS_MODE_ENABLED)) {
+ cryptoerror(LOG_STDERR,
+ gettext("FIPS-140 mode has already "
+ "been enabled.\n"));
+ return (FAILURE);
+ }
+
+ if ((action == FIPS140_DISABLE) &&
+ (kcf_fips_mode == CRYPTO_FIPS_MODE_DISABLED)) {
+ cryptoerror(LOG_STDERR,
+ gettext("FIPS-140 mode has already "
+ "been disabled.\n"));
+ return (FAILURE);
+ }
+
+ if ((action == FIPS140_ENABLE) || (action == FIPS140_DISABLE)) {
+ /* Update kcf.conf */
+ if ((rc = fips_update_kcfconf(action)) != SUCCESS)
+ return (rc);
+ }
+
+ /* No need to inform kernel */
+ if (action == FIPS140_ENABLE) {
+ (void) printf(gettext(
+ "FIPS-140 mode was enabled successfully.\n"));
+ (void) printf(gettext(
+ "Warning: In this release, the Cryptographic "
+ "Framework has not been FIPS 140-2 "
+ "certified.\n\n"));
+ } else {
+ (void) printf(gettext(
+ "FIPS-140 mode was disabled successfully.\n"));
+ }
+
+ (void) printf(gettext(
+ "The FIPS-140 mode has changed.\n"));
+ (void) printf(gettext(
+ "The system will require a reboot.\n\n"));
+ return (SUCCESS);
+
+ }
+
+ /* This is refresh, need to inform kernel */
+ (void) memset(&fips_info, 0, sizeof (crypto_fips140_t));
+
+ if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
+ cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
+ ADMIN_IOCTL_DEVICE, strerror(errno));
+ return (FAILURE);
+ }
+
+ switch (action) {
+ case FIPS140_ENABLE:
+ /* make CRYPTO_FIPS_SET ioctl call */
+ fips_info.fips140_op = FIPS140_ENABLE;
+ if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
+ cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed: %s",
+ strerror(errno));
+ rc = FAILURE;
+ goto out;
+ }
+
+ if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
+ cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed, "
+ "return_value = %d",
+ fips_info.fips140_return_value);
+ rc = FAILURE;
+ }
+
+ break;
+
+ case FIPS140_DISABLE:
+ /* make CRYPTO_FIPS140_SET ioctl call */
+ fips_info.fips140_op = FIPS140_DISABLE;
+ if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
+ cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed: %s",
+ strerror(errno));
+ rc = FAILURE;
+ goto out;
+ }
+
+ if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
+ cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed, "
+ "return_value = %d",
+ fips_info.fips140_return_value);
+ rc = FAILURE;
+ }
+
+ break;
+
+ default:
+ rc = FAILURE;
+ break;
+ };
+
+out:
+ (void) close(fd);
+ return (rc);
+}
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_util.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_util.c
index 513578cfdc..e858a38d33 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_util.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_util.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,6 +35,7 @@
#include <zone.h>
#include <sys/stat.h>
#include "cryptoadm.h"
+#include <cryptoutil.h>
static int err; /* To store errno which may be overwritten by gettext() */
static int build_entrylist(entry_t *, entrylist_t **);
@@ -144,6 +145,7 @@ dup_entry(entry_t *pent1)
return (NULL);
}
+ pent2->flag_fips_enabled = pent1->flag_fips_enabled;
pent2->sup_count = pent1->sup_count;
pent2->dis_count = pent1->dis_count;
pent2->load = pent1->load;
@@ -246,6 +248,35 @@ parse_sup_dis_list(char *buf, entry_t *pent)
return (rc);
}
+static int
+parse_fips(char *buf, entry_t *pent)
+{
+ char *value;
+
+ if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) {
+ if (value = strpbrk(buf, SEP_EQUAL)) {
+ value++; /* get rid of = */
+ if (strcmp(value, DISABLED_KEYWORD) == 0) {
+ pent->flag_fips_enabled = B_FALSE;
+ } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
+ pent->flag_fips_enabled = B_TRUE;
+ } else {
+ cryptoerror(LOG_ERR, gettext(
+ "Failed to parse kcf.conf file.\n"));
+ return (FAILURE);
+ }
+ return (SUCCESS);
+ } else {
+ return (FAILURE);
+ }
+ } else {
+ /* should not come here */
+ cryptoerror(LOG_ERR, gettext(
+ "Failed to parse kcf.conf file.\n"));
+ return (FAILURE);
+ }
+
+}
/*
* Convert a char string containing a line about a provider
@@ -274,6 +305,15 @@ interpret(char *buf, entry_t **ppent)
return (FAILURE);
}
+ if (is_fips(token1)) {
+ if ((rc = parse_fips(buf + strlen(token1) + 1,
+ pent)) != SUCCESS) {
+ free_entry(pent);
+ }
+ *ppent = pent;
+ return (rc);
+ }
+
if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
/* The entry contains a provider name only */
free_entry(pent);
@@ -626,6 +666,16 @@ is_device(char *path)
}
}
+boolean_t
+is_fips(char *name)
+{
+ if (strcmp(name, FIPS_KEYWORD) == 0) {
+ return (B_TRUE);
+ } else {
+ return (B_FALSE);
+ }
+}
+
/*
* Split a hardware provider name with the "name/inst_num" format into
* a name and a number (e.g., split "mca/0" into "mca" instance 0).
@@ -667,7 +717,8 @@ split_hw_provname(char *provname, char *pname, int *inst_num)
* The kcf.conf file is available only in the global zone.
*/
int
-get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
+get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist,
+ entrylist_t **ppfipslist)
{
FILE *pfile = NULL;
char buffer[BUFSIZ];
@@ -682,6 +733,8 @@ get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
*ppdevlist = NULL;
*ppsoftlist = NULL;
+ *ppfipslist = NULL;
+
while (fgets(buffer, BUFSIZ, pfile) != NULL) {
if (buffer[0] == '#' || buffer[0] == ' ' ||
buffer[0] == '\n'|| buffer[0] == '\t') {
@@ -695,7 +748,15 @@ get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
buffer[len] = '\0';
if ((rc = interpret(buffer, &pent)) == SUCCESS) {
- if (is_device(pent->name)) {
+ if (is_fips(pent->name)) {
+ if (*ppfipslist != NULL) {
+ cryptoerror(LOG_STDERR, gettext(
+ "multiple fips entries."));
+ rc = FAILURE;
+ } else {
+ rc = build_entrylist(pent, ppfipslist);
+ }
+ } else if (is_device(pent->name)) {
rc = build_entrylist(pent, ppdevlist);
} else {
rc = build_entrylist(pent, ppsoftlist);
@@ -703,11 +764,13 @@ get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
} else {
cryptoerror(LOG_STDERR, gettext(
"failed to parse configuration."));
+ rc = FAILURE;
}
if (rc != SUCCESS) {
free_entrylist(*ppdevlist);
free_entrylist(*ppsoftlist);
+ free_entrylist(*ppfipslist);
free_entry(pent);
break;
}
@@ -737,6 +800,7 @@ get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
entrylist_t *tmp_pdev = NULL;
entrylist_t *tmp_psoft = NULL;
entrylist_t *phardlist = NULL, *psoftlist = NULL;
+ entrylist_t *pfipslist = NULL;
/*
* Get hardware providers
@@ -780,7 +844,8 @@ get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
* Get software providers
*/
if (getzoneid() == GLOBAL_ZONEID) {
- if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
+ if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) !=
+ SUCCESS) {
goto fail_out;
}
}
@@ -794,8 +859,8 @@ get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
i < psoftlist_kernel->sl_soft_count;
i++, psoftname = psoftname + strlen(psoftname) + 1) {
pmech = NULL;
- if (get_soft_info(psoftname, &pmech, phardlist, psoftlist) !=
- SUCCESS) {
+ if (get_soft_info(psoftname, &pmech, phardlist, psoftlist,
+ pfipslist) != SUCCESS) {
cryptodebug(
"failed to retrieve the mechanism list for %s.",
psoftname);
@@ -849,13 +914,15 @@ fail_out:
* If NULL, this function calls get_kcfconf_info() internally.
*/
entry_t *
-getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist)
+getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist)
{
entry_t *pent = NULL;
boolean_t memory_allocated = B_FALSE;
- if ((phardlist == NULL) || (psoftlist == NULL)) {
- if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
+ if ((phardlist == NULL) || (psoftlist == NULL) || (pfipslist == NULL)) {
+ if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) !=
+ SUCCESS) {
return (NULL);
}
memory_allocated = B_TRUE;
@@ -863,6 +930,8 @@ getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist)
if (is_device(provname)) {
pent = getent(provname, phardlist);
+ } else if (is_fips(provname)) {
+ pent = getent(provname, pfipslist);
} else {
pent = getent(provname, psoftlist);
}
@@ -870,6 +939,7 @@ getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist)
if (memory_allocated) {
free_entrylist(phardlist);
free_entrylist(psoftlist);
+ free_entrylist(pfipslist);
}
return (pent);
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
index 85944a381e..bf64d845cf 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -702,18 +702,9 @@ install_uef_lib(char *libname)
{
uentry_t *puent;
struct stat statbuf;
- boolean_t found;
- FILE *pfile;
- FILE *pfile_tmp;
- char tmpfile_name[MAXPATHLEN];
char libpath[MAXPATHLEN];
char libbuf[MAXPATHLEN];
char *isa;
- char buffer[BUFSIZ];
- char *ptr;
- int found_count;
- int rc = SUCCESS;
-
if (libname == NULL) {
/* should not happen */
@@ -769,163 +760,8 @@ install_uef_lib(char *libname)
return (FAILURE);
}
- if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
- return (FAILURE);
- }
-
- if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to lock the configuration - %s"),
- strerror(err));
- (void) fclose(pfile);
- return (FAILURE);
- }
-
- /*
- * Create a temporary file in the /etc/crypto directory.
- */
- (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
- if (mkstemp(tmpfile_name) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to create a temporary file - %s"),
- strerror(err));
- (void) fclose(pfile);
- return (FAILURE);
- }
-
- if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
- tmpfile_name, strerror(err));
- (void) fclose(pfile);
- return (FAILURE);
- }
-
- /*
- * Loop thru the config file. If the file was reserved within a
- * package bracket, just uncomment it. Other wise, append it at
- * the end. The resulting file will be saved in the temp file first.
- */
- found_count = 0;
- rc = SUCCESS;
- while (fgets(buffer, BUFSIZ, pfile) != NULL) {
- found = B_FALSE;
- if (buffer[0] == '#') {
- ptr = buffer;
- ptr++;
- if (strcmp(libname, ptr) == 0) {
- found = B_TRUE;
- found_count++;
- }
- }
-
- if (found == B_FALSE) {
- if (fputs(buffer, pfile_tmp) == EOF) {
- rc = FAILURE;
- }
- } else {
- if (found_count == 1) {
- if (fputs(ptr, pfile_tmp) == EOF) {
- rc = FAILURE;
- }
- } else {
- /*
- * Found a second entry with #libname.
- * Should not happen. The pkcs11.conf file
- * is corrupted. Give a warning and skip
- * this entry.
- */
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) Found an additional reserved "
- "entry for %s."), libname);
- }
- }
-
- if (rc == FAILURE) {
- break;
- }
- }
-
- if (rc == FAILURE) {
- cryptoerror(LOG_STDERR, gettext("write error."));
- (void) fclose(pfile);
- (void) fclose(pfile_tmp);
- if (unlink(tmpfile_name) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"), tmpfile_name,
- strerror(err));
- }
- return (FAILURE);
- }
-
- if (found_count == 0) {
- /*
- * This libname was not in package before, append it to the
- * end of the temp file.
- */
- if (fputs(libname, pfile_tmp) == EOF) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "failed to write to %s: %s"), tmpfile_name,
- strerror(err));
- (void) fclose(pfile);
- (void) fclose(pfile_tmp);
- if (unlink(tmpfile_name) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"),
- tmpfile_name, strerror(err));
- }
- return (FAILURE);
- }
- }
+ return (update_conf(_PATH_PKCS11_CONF, libname));
- (void) fclose(pfile);
- if (fclose(pfile_tmp) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to close %s: %s"), tmpfile_name,
- strerror(err));
- return (FAILURE);
- }
-
- if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
- _PATH_PKCS11_CONF, strerror(err));
- rc = FAILURE;
- } else if (chmod(_PATH_PKCS11_CONF,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
- strerror(err));
- rc = FAILURE;
- } else {
- rc = SUCCESS;
- }
-
- if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"), tmpfile_name,
- strerror(err));
- }
-
- return (rc);
}
@@ -1565,12 +1401,12 @@ uent2str(uentry_t *puent)
}
if (puent->flag_metaslot_enabled) {
- if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
+ if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
free(buf);
return (NULL);
}
} else {
- if (strlcat(buf, METASLOT_DISABLED, BUFSIZ)
+ if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ)
>= BUFSIZ) {
free(buf);
return (NULL);
@@ -1592,12 +1428,12 @@ uent2str(uentry_t *puent)
}
if (puent->flag_metaslot_auto_key_migrate) {
- if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
+ if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
free(buf);
return (NULL);
}
} else {
- if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) >= BUFSIZ) {
+ if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
free(buf);
return (NULL);
}
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_util.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_util.c
index cab90a14a4..84eb911d21 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_util.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_util.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -20,16 +19,17 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctype.h>
#include <strings.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <sys/stat.h>
#include "cryptoadm.h"
-
+#include <cryptoutil.h>
/*
* Create one item of type mechlist_t with the mechanism name. A null is
@@ -53,13 +53,13 @@ create_mech(char *name)
first = name;
while (isspace(*first)) /* nuke leading whitespace */
- first++;
+ first++;
(void) strlcpy(pres->name, first, sizeof (pres->name));
last = strrchr(pres->name, '\0');
last--;
while (isspace(*last)) /* nuke trailing whitespace */
- *last-- = '\0';
+ *last-- = '\0';
pres->next = NULL;
@@ -104,3 +104,212 @@ is_in_list(char *mechname, mechlist_t *plist)
return (found);
}
+
+int
+update_conf(char *conf_file, char *entry)
+{
+
+ boolean_t found;
+ FILE *pfile;
+ FILE *pfile_tmp;
+ char tmpfile_name[MAXPATHLEN];
+ char *ptr;
+ char *name;
+ char buffer[BUFSIZ];
+ char buffer2[BUFSIZ];
+ int found_count;
+ int rc = SUCCESS;
+ int err;
+
+ if ((pfile = fopen(conf_file, "r+")) == NULL) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to update the configuration - %s"),
+ strerror(err));
+ cryptodebug("failed to open %s for write.", conf_file);
+ return (FAILURE);
+ }
+
+ if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to lock the configuration - %s"),
+ strerror(err));
+ (void) fclose(pfile);
+ return (FAILURE);
+ }
+
+ /*
+ * Create a temporary file in the /etc/crypto directory.
+ */
+ (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
+ if (mkstemp(tmpfile_name) == -1) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to create a temporary file - %s"),
+ strerror(err));
+ (void) fclose(pfile);
+ return (FAILURE);
+ }
+
+ if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
+ err = errno;
+ cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
+ tmpfile_name, strerror(err));
+ (void) fclose(pfile);
+ return (FAILURE);
+ }
+
+
+ /*
+ * Loop thru the config file. If the provider was reserved within a
+ * package bracket, just uncomment it. Otherwise, append it at
+ * the end. The resulting file will be saved in the temp file first.
+ */
+ found_count = 0;
+ rc = SUCCESS;
+
+ while (fgets(buffer, BUFSIZ, pfile) != NULL) {
+ found = B_FALSE;
+ if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
+ if (buffer[0] == '#') {
+ ptr = buffer;
+ ptr++;
+ if (strcmp(entry, ptr) == 0) {
+ found = B_TRUE;
+ found_count++;
+ }
+ }
+ } else { /* _PATH_KCF_CONF */
+ if (buffer[0] == '#') {
+ (void) strlcpy(buffer2, buffer, BUFSIZ);
+ ptr = buffer2;
+ ptr++; /* skip # */
+ if ((name = strtok(ptr, SEP_COLON)) == NULL) {
+ rc = FAILURE;
+ break;
+ } else if (strcmp(FIPS_KEYWORD, name) == 0) {
+ found = B_TRUE;
+ found_count++;
+ }
+ } else {
+ (void) strlcpy(buffer2, buffer, BUFSIZ);
+ ptr = buffer2;
+ if ((name = strtok(ptr, SEP_COLON)) == NULL) {
+ rc = FAILURE;
+ break;
+ } else if (strcmp(FIPS_KEYWORD, name) == 0) {
+ found = B_TRUE;
+ found_count++;
+ }
+ }
+ }
+
+ if (found == B_FALSE) {
+ if (fputs(buffer, pfile_tmp) == EOF) {
+ rc = FAILURE;
+ }
+ } else {
+ if (found_count == 1) {
+ if (strcmp(conf_file, _PATH_PKCS11_CONF) == 0) {
+ if (fputs(ptr, pfile_tmp) == EOF) {
+ rc = FAILURE;
+ }
+ } else {
+ if (fputs(entry, pfile_tmp) == EOF) {
+ rc = FAILURE;
+ }
+ }
+ } else {
+ /*
+ * Found a second entry with same tag name.
+ * Should not happen. The config file
+ * is corrupted. Give a warning and skip
+ * this entry.
+ */
+ cryptoerror(LOG_STDERR, gettext(
+ "(Warning) Found an additional reserved "
+ "entry for %s."), entry);
+ }
+ }
+
+ if (rc == FAILURE) {
+ break;
+ }
+ }
+
+ (void) fclose(pfile);
+
+ if (rc == FAILURE) {
+ cryptoerror(LOG_STDERR, gettext("write error."));
+ (void) fclose(pfile_tmp);
+ if (unlink(tmpfile_name) != 0) {
+ err = errno;
+ cryptoerror(LOG_STDERR, gettext(
+ "(Warning) failed to remove %s: %s"), tmpfile_name,
+ strerror(err));
+ }
+ return (FAILURE);
+ }
+
+ if (found_count == 0) {
+ /*
+ * The entry was not in config file before, append it to the
+ * end of the temp file.
+ */
+ if (fputs(entry, pfile_tmp) == EOF) {
+ cryptoerror(LOG_STDERR, gettext(
+ "failed to write to %s: %s"), tmpfile_name,
+ strerror(errno));
+ (void) fclose(pfile_tmp);
+ if (unlink(tmpfile_name) != 0) {
+ err = errno;
+ cryptoerror(LOG_STDERR, gettext(
+ "(Warning) failed to remove %s: %s"),
+ tmpfile_name, strerror(err));
+ }
+ return (FAILURE);
+ }
+ }
+
+ if (fclose(pfile_tmp) != 0) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to close %s: %s"), tmpfile_name,
+ strerror(err));
+ return (FAILURE);
+ }
+
+ if (rename(tmpfile_name, conf_file) == -1) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to update the configuration - %s"),
+ strerror(err));
+ cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
+ conf_file, strerror(err));
+ rc = FAILURE;
+ } else if (chmod(conf_file,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
+ err = errno;
+ cryptoerror(LOG_STDERR,
+ gettext("failed to update the configuration - %s"),
+ strerror(err));
+ cryptodebug("failed to chmod to %s: %s", conf_file,
+ strerror(err));
+ rc = FAILURE;
+ } else {
+ rc = SUCCESS;
+ }
+
+ if (rc == FAILURE) {
+ if (unlink(tmpfile_name) != 0) {
+ err = errno;
+ cryptoerror(LOG_STDERR, gettext(
+ "(Warning) failed to remove %s: %s"),
+ tmpfile_name, strerror(err));
+ }
+ }
+
+ return (rc);
+
+}
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c b/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c
index f4455dc445..145c33fad9 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -208,6 +208,8 @@ usage(void)
" [mechanism=<%s>]\n",
gettext("provider-name"), gettext("mechanism-list"));
(void) fprintf(stderr,
+ " cryptoadm list fips-140\n");
+ (void) fprintf(stderr,
" cryptoadm disable provider=<%s>"
" mechanism=<%s> | random | all\n",
gettext("provider-name"), gettext("mechanism-list"));
@@ -216,6 +218,8 @@ usage(void)
" [auto-key-migrate] [mechanism=<%s>]\n",
gettext("mechanism-list"));
(void) fprintf(stderr,
+ " cryptoadm disable fips-140\n");
+ (void) fprintf(stderr,
" cryptoadm enable provider=<%s>"
" mechanism=<%s> | random | all\n",
gettext("provider-name"), gettext("mechanism-list"));
@@ -226,6 +230,8 @@ usage(void)
gettext("mechanism-list"), gettext("token-label"),
gettext("slot-description"));
(void) fprintf(stderr,
+ " cryptoadm enable fips-140\n");
+ (void) fprintf(stderr,
" cryptoadm install provider=<%s>\n",
gettext("provider-name"));
(void) fprintf(stderr,
@@ -542,6 +548,15 @@ do_list(int argc, char **argv)
cryptoadm_provider_t *prov = NULL;
int rc = SUCCESS;
+ if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD,
+ strlen(FIPS_KEYWORD))) == 0) {
+ /*
+ * cryptoadm list fips-140
+ */
+ rc = do_fips_actions(FIPS140_STATUS, NOT_REFRESH);
+ return (rc);
+ }
+
argc -= 1;
argv += 1;
@@ -644,7 +659,7 @@ do_list(int argc, char **argv)
break;
case PROV_KEF_SOFT:
rc = list_mechlist_for_soft(provname,
- NULL, NULL);
+ NULL, NULL, NULL);
break;
case PROV_KEF_HARD:
rc = list_mechlist_for_hard(provname);
@@ -661,7 +676,7 @@ do_list(int argc, char **argv)
case PROV_KEF_SOFT:
if (getzoneid() == GLOBAL_ZONEID) {
rc = list_policy_for_soft(provname,
- NULL, NULL);
+ NULL, NULL, NULL);
} else {
/*
* TRANSLATION_NOTE
@@ -678,7 +693,7 @@ do_list(int argc, char **argv)
case PROV_KEF_HARD:
if (getzoneid() == GLOBAL_ZONEID) {
rc = list_policy_for_hard(
- provname, NULL, NULL, NULL);
+ provname, NULL, NULL, NULL, NULL);
} else {
/*
* TRANSLATION_NOTE
@@ -724,6 +739,15 @@ do_disable(int argc, char **argv)
int rc = SUCCESS;
boolean_t auto_key_migrate_flag = B_FALSE;
+ if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD,
+ strlen(FIPS_KEYWORD))) == 0) {
+ /*
+ * cryptoadm disable fips-140
+ */
+ rc = do_fips_actions(FIPS140_DISABLE, NOT_REFRESH);
+ return (rc);
+ }
+
if ((argc < 3) || (argc > 5)) {
usage();
return (ERROR_USAGE);
@@ -843,6 +867,15 @@ do_enable(int argc, char **argv)
boolean_t use_default = B_FALSE;
boolean_t auto_key_migrate_flag = B_FALSE;
+ if ((argc == 3) && (strncmp(argv[2], FIPS_KEYWORD,
+ strlen(FIPS_KEYWORD))) == 0) {
+ /*
+ * cryptoadm enable fips-140
+ */
+ rc = do_fips_actions(FIPS140_ENABLE, NOT_REFRESH);
+ return (rc);
+ }
+
if ((argc < 3) || (argc > 6)) {
usage();
return (ERROR_USAGE);
@@ -1153,7 +1186,7 @@ do_unload(int argc, char **argv)
}
/* Get kcf.conf entry. If none, build a new entry */
- if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
+ if ((pent = getent_kef(provname, NULL, NULL, NULL)) == NULL) {
if ((pent = create_entry(provname)) == NULL) {
cryptoerror(LOG_STDERR, gettext("out of memory."));
rc = FAILURE;
@@ -1289,6 +1322,7 @@ list_simple_for_all(boolean_t verbose)
char *psoftname;
entrylist_t *pdevlist_conf = NULL;
entrylist_t *psoftlist_conf = NULL;
+ entrylist_t *pfipslist_conf = NULL;
if (get_soft_list(&psoftlist_kernel) == FAILURE) {
cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
@@ -1297,8 +1331,8 @@ list_simple_for_all(boolean_t verbose)
} else {
sl_soft_count = psoftlist_kernel->sl_soft_count;
- if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
- == FAILURE) {
+ if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
+ &pfipslist_conf) == FAILURE) {
cryptoerror(LOG_ERR,
"failed to retrieve the providers' "
"information from file kcf.conf - %s.",
@@ -1312,13 +1346,15 @@ list_simple_for_all(boolean_t verbose)
i < sl_soft_count;
++i, psoftname += strlen(psoftname) + 1) {
pent = getent_kef(psoftname,
- pdevlist_conf, psoftlist_conf);
+ pdevlist_conf, psoftlist_conf,
+ pfipslist_conf);
(void) printf("\t%s%s\n", psoftname,
(pent == NULL) || (pent->load) ?
"" : gettext(" (inactive)"));
}
free_entrylist(pdevlist_conf);
free_entrylist(psoftlist_conf);
+ free_entrylist(pfipslist_conf);
}
free(psoftlist_kernel);
}
@@ -1434,6 +1470,7 @@ list_mechlist_for_all(boolean_t verbose)
int i;
entrylist_t *pdevlist_conf = NULL;
entrylist_t *psoftlist_conf = NULL;
+ entrylist_t *pfipslist_conf = NULL;
if (get_soft_list(&psoftlist_kernel) == FAILURE) {
cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
@@ -1442,8 +1479,8 @@ list_mechlist_for_all(boolean_t verbose)
}
sl_soft_count = psoftlist_kernel->sl_soft_count;
- if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
- == FAILURE) {
+ if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
+ &pfipslist_conf) == FAILURE) {
cryptoerror(LOG_ERR,
"failed to retrieve the providers' "
"information from file kcf.conf - %s.",
@@ -1456,10 +1493,10 @@ list_mechlist_for_all(boolean_t verbose)
i < sl_soft_count;
++i, psoftname += strlen(psoftname) + 1) {
pent = getent_kef(psoftname, pdevlist_conf,
- psoftlist_conf);
+ psoftlist_conf, pfipslist_conf);
if ((pent == NULL) || (pent->load)) {
rv = list_mechlist_for_soft(psoftname,
- NULL, NULL);
+ NULL, NULL, NULL);
if (rv == FAILURE) {
rc = FAILURE;
}
@@ -1472,11 +1509,13 @@ list_mechlist_for_all(boolean_t verbose)
free(psoftlist_kernel);
free_entrylist(pdevlist_conf);
free_entrylist(psoftlist_conf);
+ free_entrylist(pfipslist_conf);
} else {
/* kcf.conf not there in non-global zone, use /dev/cryptoadm */
entrylist_t *pdevlist_zone = NULL;
entrylist_t *psoftlist_zone = NULL;
+ entrylist_t *pfipslist_zone = NULL;
entrylist_t *ptr;
if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
@@ -1488,7 +1527,7 @@ list_mechlist_for_all(boolean_t verbose)
for (ptr = psoftlist_zone; ptr != NULL; ptr = ptr->next) {
rv = list_mechlist_for_soft(ptr->pent->name,
- pdevlist_zone, psoftlist_zone);
+ pdevlist_zone, psoftlist_zone, pfipslist_zone);
if (rv == FAILURE) {
(void) printf(gettext(
"%s: failed to get the mechanism list.\n"),
@@ -1549,6 +1588,7 @@ list_policy_for_all(void)
uentrylist_t *pliblist = NULL;
entrylist_t *pdevlist_conf = NULL;
entrylist_t *psoftlist_conf = NULL;
+ entrylist_t *pfipslist_conf = NULL;
entrylist_t *ptr = NULL;
entrylist_t *phead = NULL;
boolean_t found = B_FALSE;
@@ -1613,7 +1653,8 @@ list_policy_for_all(void)
i < sl_soft_count;
++i, psoftname += strlen(psoftname) + 1) {
(void) list_policy_for_soft(psoftname,
- pdevlist_conf, psoftlist_conf);
+ pdevlist_conf, psoftlist_conf,
+ pfipslist_conf);
}
free(psoftlist_kernel);
}
@@ -1657,7 +1698,8 @@ list_policy_for_all(void)
return (FAILURE);
}
- if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) == FAILURE) {
+ if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf,
+ &pfipslist_conf) == FAILURE) {
cryptoerror(LOG_ERR, "failed to retrieve the providers' "
"information from file kcf.conf - %s.",
_PATH_KCF_CONF);
@@ -1691,7 +1733,8 @@ list_policy_for_all(void)
if (found) {
(void) list_policy_for_hard(ptr->pent->name,
- pdevlist_conf, psoftlist_conf, pdevlist_kernel);
+ pdevlist_conf, psoftlist_conf, pfipslist_conf,
+ pdevlist_kernel);
if (phead == ptr) {
pdevlist_conf = pdevlist_conf->next;
} else {
@@ -1701,7 +1744,7 @@ list_policy_for_all(void)
free(ptr);
} else {
(void) list_policy_for_hard(provname, pdevlist_conf,
- psoftlist_conf, pdevlist_kernel);
+ psoftlist_conf, pfipslist_conf, pdevlist_kernel);
}
}
@@ -1716,6 +1759,7 @@ list_policy_for_all(void)
free_entrylist(pdevlist_conf);
free_entrylist(psoftlist_conf);
+ free_entrylist(pfipslist_conf);
free(pdevlist_kernel);
return (rc);
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.h b/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.h
index bbaa6587a4..5122c3e452 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.h
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/cryptoadm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,7 +35,6 @@
extern "C" {
#endif
-#define _PATH_KCF_CONF "/etc/crypto/kcf.conf"
#define _PATH_KCFD "/lib/crypto/kcfd"
#define TMPFILE_TEMPLATE "/etc/crypto/admXXXXXX"
@@ -56,6 +55,9 @@ extern "C" {
#define DELETE_MODE 2
#define MODIFY_MODE 3
+#define REFRESH 1
+#define NOT_REFRESH 0
+
typedef char prov_name_t[MAXNAMELEN];
typedef char mech_name_t[CRYPTO_MAX_MECH_NAME];
@@ -72,6 +74,7 @@ typedef struct entry {
mechlist_t *dislist; /* disabled list */
uint_t dis_count;
boolean_t load; /* B_FALSE after cryptoadm unload */
+ boolean_t flag_fips_enabled;
} entry_t;
@@ -94,16 +97,20 @@ extern void free_mechlist(mechlist_t *);
/* adm_kef_util */
extern boolean_t is_device(char *);
+extern boolean_t is_fips(char *);
+extern int fips_update_kcfconf(int);
+extern void fips_status_kcfconf(int *);
extern char *ent2str(entry_t *);
extern entry_t *getent_kef(char *provname,
- entrylist_t *pdevlist, entrylist_t *psoftlist);
+ entrylist_t *pdevlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist);
extern int check_kernel_for_soft(char *provname,
crypto_get_soft_list_t *psoftlist, boolean_t *in_kernel);
extern int check_kernel_for_hard(char *provname,
crypto_get_dev_list_t *pdevlist, boolean_t *in_kernel);
extern int disable_mechs(entry_t **, mechlist_t *, boolean_t, mechlist_t *);
extern int enable_mechs(entry_t **, boolean_t, mechlist_t *);
-extern int get_kcfconf_info(entrylist_t **, entrylist_t **);
+extern int get_kcfconf_info(entrylist_t **, entrylist_t **, entrylist_t **);
extern int get_admindev_info(entrylist_t **, entrylist_t **);
extern int get_mech_count(mechlist_t *);
extern entry_t *create_entry(char *provname);
@@ -138,12 +145,15 @@ extern int update_policylist(uentry_t *, mechlist_t *, int);
/* adm_kef */
extern int list_mechlist_for_soft(char *provname,
- entrylist_t *phardlist, entrylist_t *psoftlist);
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist);
extern int list_mechlist_for_hard(char *);
extern int list_policy_for_soft(char *provname,
- entrylist_t *phardlist, entrylist_t *psoftlist);
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist);
extern int list_policy_for_hard(char *provname,
entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist,
crypto_get_dev_list_t *pdevlist);
extern int disable_kef_software(char *, boolean_t, boolean_t, mechlist_t *);
extern int disable_kef_hardware(char *, boolean_t, boolean_t, mechlist_t *);
@@ -163,8 +173,10 @@ extern crypto_unload_soft_module_t *setup_unload_soft(entry_t *);
extern int get_dev_info(char *, int, int, mechlist_t **);
extern int get_dev_list(crypto_get_dev_list_t **);
extern int get_soft_info(char *provname, mechlist_t **ppmechlist,
- entrylist_t *phardlist, entrylist_t *psoftlist);
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ entrylist_t *pfipslist);
extern int get_soft_list(crypto_get_soft_list_t **);
+extern int do_fips_actions(int, int);
/* adm_metaslot */
extern int list_metaslot_info(boolean_t, boolean_t, mechlist_t *);
diff --git a/usr/src/common/crypto/aes/aes_impl.h b/usr/src/common/crypto/aes/aes_impl.h
index bb96a44394..c512d8470d 100644
--- a/usr/src/common/crypto/aes/aes_impl.h
+++ b/usr/src/common/crypto/aes/aes_impl.h
@@ -146,6 +146,81 @@ extern int aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length,
extern int aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length,
crypto_data_t *out);
+/*
+ * The following definitions and declarations are only used by AES FIPS POST
+ */
+#ifdef _AES_FIPS_POST
+
+#include <fips/fips_post.h>
+
+/*
+ * FIPS preprocessor directives for AES-ECB and AES-CBC.
+ */
+#define FIPS_AES_BLOCK_SIZE 16 /* 128-bits */
+#define FIPS_AES_ENCRYPT_LENGTH 16 /* 128-bits */
+#define FIPS_AES_DECRYPT_LENGTH 16 /* 128-bits */
+#define FIPS_AES_128_KEY_SIZE 16 /* 128-bits */
+#define FIPS_AES_192_KEY_SIZE 24 /* 192-bits */
+#define FIPS_AES_256_KEY_SIZE 32 /* 256-bits */
+
+
+#ifdef _KERNEL
+typedef enum aes_mech_type {
+ AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */
+ AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */
+ AES_CBC_PAD_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC_PAD */
+ AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */
+ AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */
+ AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */
+ AES_GMAC_MECH_INFO_TYPE /* SUN_CKM_AES_GMAC */
+} aes_mech_type_t;
+
+#undef CKM_AES_ECB
+#undef CKM_AES_CBC
+#undef CKM_AES_CTR
+
+#define CKM_AES_ECB AES_ECB_MECH_INFO_TYPE
+#define CKM_AES_CBC AES_CBC_MECH_INFO_TYPE
+#define CKM_AES_CTR AES_CTR_MECH_INFO_TYPE
+
+typedef struct soft_aes_ctx {
+ void *key_sched; /* pointer to key schedule */
+ size_t keysched_len; /* Length of the key schedule */
+ uint8_t ivec[AES_BLOCK_LEN]; /* initialization vector */
+ uint8_t data[AES_BLOCK_LEN]; /* for use by update */
+ size_t remain_len; /* for use by update */
+ void *aes_cbc; /* to be used by CBC mode */
+} soft_aes_ctx_t;
+#endif
+
+/* AES FIPS functions */
+extern int fips_aes_post(int);
+
+#ifdef _AES_IMPL
+#ifndef _KERNEL
+struct soft_aes_ctx;
+extern void fips_aes_free_context(struct soft_aes_ctx *);
+extern struct soft_aes_ctx *fips_aes_build_context(uint8_t *, int,
+ uint8_t *, CK_MECHANISM_TYPE);
+extern CK_RV fips_aes_encrypt(struct soft_aes_ctx *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR, CK_MECHANISM_TYPE);
+extern CK_RV fips_aes_decrypt(struct soft_aes_ctx *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR, CK_MECHANISM_TYPE);
+
+#else
+extern void fips_aes_free_context(soft_aes_ctx_t *);
+extern void *aes_cbc_ctx_init(void *, size_t, uint8_t *);
+extern soft_aes_ctx_t *fips_aes_build_context(uint8_t *, int,
+ uint8_t *, aes_mech_type_t, boolean_t);
+extern int fips_aes_encrypt(soft_aes_ctx_t *, uchar_t *,
+ ulong_t, uchar_t *, ulong_t *, aes_mech_type_t);
+extern int fips_aes_decrypt(soft_aes_ctx_t *, uchar_t *,
+ ulong_t, uchar_t *, ulong_t *, aes_mech_type_t);
+
+#endif /* _KERNEL */
+#endif /* _AES_IMPL */
+#endif /* _AES_FIPS_POST */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/common/crypto/des/des_impl.h b/usr/src/common/crypto/des/des_impl.h
index c59cd23a66..65509804ce 100644
--- a/usr/src/common/crypto/des/des_impl.h
+++ b/usr/src/common/crypto/des/des_impl.h
@@ -104,6 +104,67 @@ extern int des3_encrypt_block(const void *, const uint8_t *, uint8_t *);
extern int des_decrypt_block(const void *, const uint8_t *, uint8_t *);
extern int des3_decrypt_block(const void *, const uint8_t *, uint8_t *);
+/*
+ * The following definitions and declarations are only used by DES FIPS POST
+ */
+#ifdef _DES_FIPS_POST
+
+#include <modes/modes.h>
+#include <fips/fips_post.h>
+
+/* DES FIPS Declarations */
+#define FIPS_DES_ENCRYPT_LENGTH 8 /* 64-bits */
+#define FIPS_DES_DECRYPT_LENGTH 8 /* 64-bits */
+#define FIPS_DES3_ENCRYPT_LENGTH 8 /* 64-bits */
+#define FIPS_DES3_DECRYPT_LENGTH 8 /* 64-bits */
+
+#ifdef _KERNEL
+typedef enum des_mech_type {
+ DES_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES_ECB */
+ DES_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES_CBC */
+ DES_CFB_MECH_INFO_TYPE, /* SUN_CKM_DES_CFB */
+ DES3_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES3_ECB */
+ DES3_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES3_CBC */
+ DES3_CFB_MECH_INFO_TYPE /* SUN_CKM_DES3_CFB */
+} des_mech_type_t;
+
+
+#undef CKM_DES_ECB
+#undef CKM_DES3_ECB
+#undef CKM_DES_CBC
+#undef CKM_DES3_CBC
+
+#define CKM_DES_ECB DES_ECB_MECH_INFO_TYPE
+#define CKM_DES3_ECB DES3_ECB_MECH_INFO_TYPE
+#define CKM_DES_CBC DES_CBC_MECH_INFO_TYPE
+#define CKM_DES3_CBC DES3_CBC_MECH_INFO_TYPE
+#endif
+
+/* DES3 FIPS functions */
+extern int fips_des3_post(void);
+
+#ifndef _KERNEL
+#ifdef _DES_IMPL
+struct soft_des_ctx;
+extern struct soft_des_ctx *des_build_context(uint8_t *, uint8_t *,
+ CK_KEY_TYPE, CK_MECHANISM_TYPE);
+extern void fips_des_free_context(struct soft_des_ctx *);
+extern CK_RV fips_des_encrypt(struct soft_des_ctx *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR, CK_MECHANISM_TYPE);
+extern CK_RV fips_des_decrypt(struct soft_des_ctx *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR, CK_MECHANISM_TYPE);
+#endif /* _DES_IMPL */
+#else
+extern des_ctx_t *des_build_context(uint8_t *, uint8_t *,
+ des_mech_type_t);
+extern void fips_des_free_context(des_ctx_t *);
+extern int fips_des_encrypt(des_ctx_t *, uint8_t *,
+ ulong_t, uint8_t *, ulong_t *, des_mech_type_t);
+extern int fips_des_decrypt(des_ctx_t *, uint8_t *,
+ ulong_t, uint8_t *, ulong_t *, des_mech_type_t);
+#endif /* _KERNEL */
+#endif /* _DES_FIPS_POST */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/common/crypto/ecc/ec.c b/usr/src/common/crypto/ecc/ec.c
index 49a3643763..547dc67f2d 100644
--- a/usr/src/common/crypto/ecc/ec.c
+++ b/usr/src/common/crypto/ecc/ec.c
@@ -37,13 +37,12 @@
*
* ***** END LICENSE BLOCK ***** */
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Sun elects to use this software under the MPL license.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "mplogic.h"
#include "ec.h"
@@ -1066,3 +1065,48 @@ cleanup:
return rv;
}
+/*
+ * Copy all of the fields from srcParams into dstParams
+ */
+SECStatus
+EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams)
+{
+ SECStatus rv = SECFailure;
+
+ dstParams->arena = arena;
+ dstParams->type = srcParams->type;
+ dstParams->fieldID.size = srcParams->fieldID.size;
+ dstParams->fieldID.type = srcParams->fieldID.type;
+ if (srcParams->fieldID.type == ec_field_GFp) {
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
+ &srcParams->fieldID.u.prime, 0));
+ } else {
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
+ &srcParams->fieldID.u.poly, 0));
+ }
+ dstParams->fieldID.k1 = srcParams->fieldID.k1;
+ dstParams->fieldID.k2 = srcParams->fieldID.k2;
+ dstParams->fieldID.k3 = srcParams->fieldID.k3;
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
+ &srcParams->curve.a, 0));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
+ &srcParams->curve.b, 0));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
+ &srcParams->curve.seed, 0));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
+ &srcParams->base, 0));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
+ &srcParams->order, 0));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
+ &srcParams->DEREncoding, 0));
+ dstParams->name = srcParams->name;
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
+ &srcParams->curveOID, 0));
+ dstParams->cofactor = srcParams->cofactor;
+
+ return SECSuccess;
+
+cleanup:
+ return SECFailure;
+}
diff --git a/usr/src/common/crypto/ecc/ecc_impl.h b/usr/src/common/crypto/ecc/ecc_impl.h
index 01728001d9..a2bfed2b21 100644
--- a/usr/src/common/crypto/ecc/ecc_impl.h
+++ b/usr/src/common/crypto/ecc/ecc_impl.h
@@ -229,6 +229,12 @@ extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
const SECItem *, int);
extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
SECItem *, int);
+extern SECStatus EC_CopyParams(PRArenaPool *, ECParams *, const ECParams *);
+extern SECStatus EC_ValidatePublicKey(ECParams *, SECItem *, int);
+extern SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *, SECItem *,
+ const SECItem *, const unsigned char *, const int kblen, int);
+extern SECStatus ec_NewKey(ECParams *, ECPrivateKey **,
+ const unsigned char *, int, int);
#ifdef __cplusplus
}
diff --git a/usr/src/common/crypto/fips/fips_aes_util.c b/usr/src/common/crypto/fips/fips_aes_util.c
new file mode 100644
index 0000000000..9e53da9d9c
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_aes_util.c
@@ -0,0 +1,1765 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/cmn_err.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/crypto/common.h>
+#include <modes/modes.h>
+#define _AES_FIPS_POST
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softCrypt.h"
+#else
+#define _AES_IMPL
+#include <aes/aes_impl.h>
+#endif
+
+
+#ifdef _KERNEL
+void *
+aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
+{
+
+ cbc_ctx_t *cbc_ctx;
+
+ if ((cbc_ctx = kmem_zalloc(sizeof (cbc_ctx_t), KM_SLEEP)) == NULL)
+ return (NULL);
+
+ cbc_ctx->cbc_keysched = key_sched;
+ cbc_ctx->cbc_keysched_len = size;
+
+ (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
+
+ cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
+ cbc_ctx->cbc_flags |= CBC_MODE;
+
+ return (cbc_ctx);
+}
+
+/*
+ * Allocate and initialize a context for AES CTR mode of operation.
+ */
+void *
+aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
+{
+
+ ctr_ctx_t *ctr_ctx;
+ CK_AES_CTR_PARAMS *pp;
+
+ /* LINTED: pointer alignment */
+ pp = (CK_AES_CTR_PARAMS *)param;
+
+ if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), KM_SLEEP)) == NULL)
+ return (NULL);
+
+ ctr_ctx->ctr_keysched = key_sched;
+ ctr_ctx->ctr_keysched_len = size;
+
+ if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb,
+ aes_copy_block) != CRYPTO_SUCCESS) {
+ kmem_free(ctr_ctx, sizeof (ctr_ctx_t));
+ return (NULL);
+ }
+ ctr_ctx->ctr_flags |= CTR_MODE;
+
+ return (ctr_ctx);
+}
+
+/*
+ * Allocate and initialize a context for AES CCM mode of operation.
+ */
+void *
+aes_ccm_ctx_init(void *key_sched, size_t size, uint8_t *param,
+ boolean_t is_encrypt_init)
+{
+
+ ccm_ctx_t *ccm_ctx;
+
+ if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), KM_SLEEP)) == NULL)
+ return (NULL);
+
+ ccm_ctx->ccm_keysched = key_sched;
+ ccm_ctx->ccm_keysched_len = size;
+
+ if (ccm_init_ctx(ccm_ctx, (char *)param, KM_SLEEP,
+ is_encrypt_init, AES_BLOCK_LEN, aes_encrypt_block,
+ aes_xor_block) != CRYPTO_SUCCESS) {
+ kmem_free(ccm_ctx, sizeof (ccm_ctx_t));
+ return (NULL);
+ }
+ ccm_ctx->ccm_flags |= CCM_MODE;
+
+ return (ccm_ctx);
+}
+
+/*
+ * Allocate and initialize a context for AES CCM mode of operation.
+ */
+void *
+aes_gcm_ctx_init(void *key_sched, size_t size, uint8_t *param)
+{
+
+ gcm_ctx_t *gcm_ctx;
+
+ if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), KM_SLEEP)) == NULL)
+ return (NULL);
+
+ gcm_ctx->gcm_keysched = key_sched;
+ gcm_ctx->gcm_keysched_len = size;
+
+ if (gcm_init_ctx(gcm_ctx, (char *)param, AES_BLOCK_LEN,
+ aes_encrypt_block, aes_copy_block,
+ aes_xor_block) != CRYPTO_SUCCESS) {
+ kmem_free(gcm_ctx, sizeof (gcm_ctx_t));
+ return (NULL);
+ }
+ gcm_ctx->gcm_flags |= GCM_MODE;
+
+ return (gcm_ctx);
+}
+
+void *
+aes_gmac_ctx_init(void *key_sched, size_t size, uint8_t *param)
+{
+
+ gcm_ctx_t *gcm_ctx;
+
+ if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), KM_SLEEP)) == NULL)
+ return (NULL);
+
+ gcm_ctx->gcm_keysched = key_sched;
+ gcm_ctx->gcm_keysched_len = size;
+
+ if (gmac_init_ctx(gcm_ctx, (char *)param, AES_BLOCK_LEN,
+ aes_encrypt_block, aes_copy_block,
+ aes_xor_block) != CRYPTO_SUCCESS) {
+ kmem_free(gcm_ctx, sizeof (gcm_ctx_t));
+ return (NULL);
+ }
+ gcm_ctx->gcm_flags |= GMAC_MODE;
+
+ return (gcm_ctx);
+}
+#endif
+
+
+/*
+ * Allocate context for the active encryption or decryption operation, and
+ * generate AES key schedule to speed up the operation.
+ */
+soft_aes_ctx_t *
+#ifdef _KERNEL
+fips_aes_build_context(uint8_t *key, int key_len, uint8_t *iv,
+ aes_mech_type_t mechanism, boolean_t is_encrypt_init)
+#else
+fips_aes_build_context(uint8_t *key, int key_len, uint8_t *iv,
+ CK_MECHANISM_TYPE mechanism)
+#endif
+{
+ size_t size;
+ soft_aes_ctx_t *soft_aes_ctx;
+ CK_AES_CTR_PARAMS pp;
+
+#ifdef _KERNEL
+ if ((soft_aes_ctx = kmem_zalloc(sizeof (soft_aes_ctx_t),
+ KM_SLEEP)) == NULL)
+#else
+ if ((soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t)))
+ == NULL)
+#endif
+ return (NULL);
+
+
+ soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
+
+ if (soft_aes_ctx->key_sched == NULL) {
+#ifdef _KERNEL
+ kmem_free(soft_aes_ctx, sizeof (soft_aes_ctx_t));
+#else
+ free(soft_aes_ctx);
+#endif
+ return (NULL);
+ }
+
+ soft_aes_ctx->keysched_len = size;
+
+#ifdef __sparcv9
+ aes_init_keysched(key, (uint_t)(key_len * 8),
+ soft_aes_ctx->key_sched);
+#else /* !__sparcv9 */
+ aes_init_keysched(key, (key_len * 8),
+ soft_aes_ctx->key_sched);
+#endif /* __sparcv9 */
+
+ switch (mechanism) {
+
+ case CKM_AES_CBC:
+
+ /* Save Initialization Vector (IV) in the context. */
+ (void) memcpy(soft_aes_ctx->ivec, iv, AES_BLOCK_LEN);
+ /* Allocate a context for AES cipher-block chaining. */
+ soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len,
+ soft_aes_ctx->ivec);
+ break;
+
+ case CKM_AES_CTR:
+
+ pp.ulCounterBits = 16;
+ (void) memcpy(pp.cb, iv, AES_BLOCK_LEN);
+ soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len,
+ (uint8_t *)&pp);
+ break;
+
+#ifdef _KERNEL
+ case AES_CCM_MECH_INFO_TYPE:
+ soft_aes_ctx->aes_cbc = aes_ccm_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len, iv,
+ is_encrypt_init);
+ break;
+
+ case AES_GCM_MECH_INFO_TYPE:
+ soft_aes_ctx->aes_cbc = aes_gcm_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len, iv);
+ break;
+
+ case AES_GMAC_MECH_INFO_TYPE:
+ soft_aes_ctx->aes_cbc = aes_gmac_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len, iv);
+ break;
+#endif
+ default:
+ return (soft_aes_ctx);
+ }
+
+ if (soft_aes_ctx->aes_cbc == NULL) {
+ bzero(soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len);
+#ifdef _KERNEL
+ kmem_free(soft_aes_ctx->key_sched, size);
+#else
+ free(soft_aes_ctx->key_sched);
+#endif
+ return (NULL);
+ }
+
+ return (soft_aes_ctx);
+}
+
+#ifdef _KERNEL
+void
+fips_aes_free_context(soft_aes_ctx_t *soft_aes_ctx)
+{
+
+ common_ctx_t *aes_ctx;
+
+ aes_ctx = (common_ctx_t *)soft_aes_ctx->aes_cbc;
+
+ if (aes_ctx != NULL) {
+ bzero(aes_ctx->cc_keysched, aes_ctx->cc_keysched_len);
+ kmem_free(aes_ctx->cc_keysched,
+ aes_ctx->cc_keysched_len);
+ crypto_free_mode_ctx(aes_ctx);
+ } else {
+ /* ECB MODE */
+ bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
+ kmem_free(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
+ }
+
+ kmem_free(soft_aes_ctx, sizeof (soft_aes_ctx_t));
+
+}
+
+#else
+void
+fips_aes_free_context(soft_aes_ctx_t *soft_aes_ctx)
+{
+
+ common_ctx_t *aes_ctx;
+
+ aes_ctx = (common_ctx_t *)soft_aes_ctx->aes_cbc;
+
+ if (aes_ctx != NULL) {
+ bzero(aes_ctx->cc_keysched, aes_ctx->cc_keysched_len);
+ free(aes_ctx->cc_keysched);
+ free(soft_aes_ctx->aes_cbc);
+ } else {
+ /* ECB MODE */
+ bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
+ free(soft_aes_ctx->key_sched);
+ }
+
+ free(soft_aes_ctx);
+
+}
+#endif
+
+/*
+ * fips_aes_encrypt()
+ *
+ * Arguments:
+ * soft_aes_ctx: pointer to AES context
+ * in_buf: pointer to the input data to be encrypted
+ * ulDataLen: length of the input data
+ * out_buf: pointer to the output data after encryption
+ * pulEncryptedLen: pointer to the length of the output data
+ * mechanism: CKM_AES_ECB or CKM_AES_CBC
+ *
+ * Description:
+ * This function calls the corresponding low-level encrypt
+ * routine based on the mechanism.
+ *
+ */
+#ifdef _KERNEL
+int
+fips_aes_encrypt(soft_aes_ctx_t *soft_aes_ctx, uchar_t *in_buf,
+ ulong_t ulDataLen, uchar_t *out_buf,
+ ulong_t *pulEncryptedLen, aes_mech_type_t mechanism)
+#else
+CK_RV
+fips_aes_encrypt(soft_aes_ctx_t *soft_aes_ctx, CK_BYTE_PTR in_buf,
+ CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
+ CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
+#endif
+{
+
+ int rc = 0;
+ CK_RV rv = CKR_OK;
+ ulong_t out_len;
+
+ /*
+ * AES only takes input length that is a multiple of 16-byte
+ */
+ if ((ulDataLen % AES_BLOCK_LEN) != 0)
+ return (CKR_DATA_LEN_RANGE);
+
+ /*
+ * For non-padding mode, the output length will
+ * be same as the input length.
+ */
+ out_len = ulDataLen;
+
+ /*
+ * Begin Encryption now.
+ */
+ switch (mechanism) {
+
+ case CKM_AES_ECB:
+ {
+
+ ulong_t i;
+ uint8_t *tmp_inbuf;
+ uint8_t *tmp_outbuf;
+
+ for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
+ tmp_inbuf = &in_buf[i];
+ tmp_outbuf = &out_buf[i];
+ /* Crunch one block of data for AES. */
+ (void) aes_encrypt_block(soft_aes_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf);
+ }
+
+ *pulEncryptedLen = out_len;
+
+ break;
+ }
+
+ case CKM_AES_CBC:
+ {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = out_len;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = out_len;
+
+ /* Encrypt multiple blocks of data. */
+ rc = aes_encrypt_contiguous_blocks(
+ (aes_ctx_t *)soft_aes_ctx->aes_cbc,
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0)
+ goto encrypt_failed;
+
+ if (rc == 0) {
+ *pulEncryptedLen = out_len;
+ break;
+ }
+encrypt_failed:
+ *pulEncryptedLen = 0;
+ return (CKR_DEVICE_ERROR);
+ }
+
+ case CKM_AES_CTR:
+ {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = out_len;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = out_len;
+
+ rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0) {
+ *pulEncryptedLen = 0;
+ return (CKR_DEVICE_ERROR);
+ }
+ /*
+ * Since AES counter mode is a stream cipher, we call
+ * aes_counter_final() to pick up any remaining bytes.
+ * It is an internal function that does not destroy
+ * the context like *normal* final routines.
+ */
+ if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
+ > 0) {
+ rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
+ aes_encrypt_block);
+ if (rc != 0) {
+ *pulEncryptedLen = 0;
+ return (CKR_DEVICE_ERROR);
+ }
+ }
+
+ *pulEncryptedLen = out_len;
+ break;
+ }
+
+#ifdef _KERNEL
+ case AES_CCM_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t saved_length, length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+ ccm_ctx_t *ccm_ctx = soft_aes_ctx->aes_cbc;
+
+ length_needed = ulDataLen + aes_ctx->ac_mac_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = length_needed;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = length_needed;
+
+ saved_length = out.cd_length;
+
+ rc = aes_encrypt_contiguous_blocks(aes_ctx,
+ (char *)in_buf, ulDataLen, &out);
+
+ if (rc != 0) {
+ *pulEncryptedLen = 0;
+ return (rc);
+ }
+
+ /*
+ * ccm_encrypt_final() will compute the MAC and append
+ * it to existing ciphertext. So, need to adjust the left over
+ * length value accordingly
+ */
+
+ /* order of following 2 lines MUST not be reversed */
+ out.cd_offset = ccm_ctx->ccm_processed_data_len;
+ out.cd_length = saved_length - ccm_ctx->ccm_processed_data_len;
+
+ rc = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulEncryptedLen = 0;
+ return (rc);
+ }
+
+ *pulEncryptedLen = length_needed;
+ break;
+ }
+
+ case AES_GCM_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t saved_length, length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+ gcm_ctx_t *gcm_ctx = soft_aes_ctx->aes_cbc;
+
+ /*
+ * Output:
+ * A ciphertext, denoted C, whose bit length is the same as
+ * that of the plaintext.
+ * An authentication tag, or tag, for short, denoted T.
+ */
+
+ length_needed = ulDataLen + aes_ctx->ac_tag_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = length_needed;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = length_needed;
+
+ saved_length = out.cd_length;
+
+ rc = aes_encrypt_contiguous_blocks(aes_ctx,
+ (char *)in_buf, ulDataLen, &out);
+
+ if (rc != 0) {
+ *pulEncryptedLen = 0;
+ return (rc);
+ }
+
+ /*
+ * ccm_encrypt_final() will compute the MAC and append
+ * it to existing ciphertext. So, need to adjust the left over
+ * length value accordingly
+ */
+
+ /* order of following 2 lines MUST not be reversed */
+ out.cd_offset = gcm_ctx->gcm_processed_data_len;
+ out.cd_length = saved_length - gcm_ctx->gcm_processed_data_len;
+
+ rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
+ aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulEncryptedLen = 0;
+ return (rc);
+ }
+
+ *pulEncryptedLen = length_needed;
+ break;
+ }
+
+ case AES_GMAC_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+
+ length_needed = aes_ctx->ac_tag_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = length_needed;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = length_needed;
+
+ rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
+ aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulEncryptedLen = 0;
+ return (rc);
+ }
+
+ *pulEncryptedLen = length_needed;
+ break;
+ }
+#endif /* _KERNEL */
+ } /* end switch */
+
+ return (rv);
+}
+
+/*
+ * fips_aes_decrypt()
+ *
+ * Arguments:
+ * soft_aes_ctx: pointer to AES context
+ * in_buf: pointer to the input data to be decrypted
+ * ulEncryptedLen: length of the input data
+ * out_buf: pointer to the output data
+ * pulDataLen: pointer to the length of the output data
+ * mechanism: CKM_AES_ECB or CKM_AES_CBC
+ *
+ * Description:
+ * This function calls the corresponding low-level decrypt
+ * function based on the mechanism.
+ *
+ */
+#ifdef _KERNEL
+int
+fips_aes_decrypt(soft_aes_ctx_t *soft_aes_ctx, uchar_t *in_buf,
+ ulong_t ulEncryptedLen, uchar_t *out_buf,
+ ulong_t *pulDataLen, aes_mech_type_t mechanism)
+#else
+CK_RV
+fips_aes_decrypt(soft_aes_ctx_t *soft_aes_ctx, CK_BYTE_PTR in_buf,
+ CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
+ CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
+#endif
+{
+
+ int rc = 0;
+ CK_RV rv = CKR_OK;
+ ulong_t out_len;
+
+ /*
+ * AES only takes input length that is a multiple of 16 bytes
+ */
+ if ((ulEncryptedLen % AES_BLOCK_LEN) != 0)
+ return (CKR_ENCRYPTED_DATA_LEN_RANGE);
+
+ /*
+ * For non-padding mode, the output length will
+ * be same as the input length.
+ */
+ out_len = ulEncryptedLen;
+
+ /*
+ * Begin Decryption.
+ */
+ switch (mechanism) {
+
+ case CKM_AES_ECB:
+ {
+
+ ulong_t i;
+ uint8_t *tmp_inbuf;
+ uint8_t *tmp_outbuf;
+
+ for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
+ tmp_inbuf = &in_buf[i];
+ tmp_outbuf = &out_buf[i];
+ /* Crunch one block of data for AES. */
+ (void) aes_decrypt_block(soft_aes_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf);
+ }
+
+ *pulDataLen = out_len;
+
+ break;
+ }
+
+ case CKM_AES_CBC:
+ {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = out_len;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = out_len;
+
+ /* Decrypt multiple blocks of data. */
+ rc = aes_decrypt_contiguous_blocks(
+ (aes_ctx_t *)soft_aes_ctx->aes_cbc,
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0)
+ goto decrypt_failed;
+
+
+ *pulDataLen = out_len;
+
+ if (rc == 0)
+ break;
+decrypt_failed:
+ *pulDataLen = 0;
+ return (CKR_DEVICE_ERROR);
+ }
+
+ case CKM_AES_CTR:
+ {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = *pulDataLen;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = *pulDataLen;
+
+ rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0) {
+ *pulDataLen = 0;
+ return (CKR_DEVICE_ERROR);
+ }
+
+ /*
+ * Since AES counter mode is a stream cipher, we call
+ * aes_counter_final() to pick up any remaining bytes.
+ * It is an internal function that does not destroy
+ * the context like *normal* final routines.
+ */
+ if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
+ > 0) {
+ rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
+ aes_encrypt_block);
+
+ if (rc == CKR_DATA_LEN_RANGE)
+ return (CKR_ENCRYPTED_DATA_LEN_RANGE);
+ }
+
+ *pulDataLen = out_len;
+ break;
+ }
+
+#ifdef _KERNEL
+ case AES_CCM_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+ ccm_ctx_t *ccm_ctx = soft_aes_ctx->aes_cbc;
+
+ length_needed = ulEncryptedLen + ccm_ctx->ccm_mac_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = ulEncryptedLen;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = ulEncryptedLen;
+
+ rc = aes_decrypt_contiguous_blocks(aes_ctx,
+ (char *)in_buf, length_needed, &out);
+
+ if (rc != 0) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ /* order of following 2 lines MUST not be reversed */
+ out.cd_offset = 0;
+ out.cd_length = ulEncryptedLen;
+
+ rc = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
+ aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ *pulDataLen = ulEncryptedLen;
+
+ break;
+ }
+
+ case AES_GCM_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+
+ length_needed = ulEncryptedLen + aes_ctx->ac_tag_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = ulEncryptedLen;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = ulEncryptedLen;
+
+ rc = aes_decrypt_contiguous_blocks(aes_ctx,
+ (char *)in_buf, length_needed, &out);
+
+ if (rc != 0) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ /* order of following 2 lines MUST not be reversed */
+ out.cd_offset = 0;
+ out.cd_length = aes_ctx->ac_tag_len;
+
+ rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block,
+ aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ *pulDataLen = ulEncryptedLen;
+
+ break;
+ }
+
+ case AES_GMAC_MECH_INFO_TYPE:
+ {
+ crypto_data_t out;
+ size_t length_needed;
+ aes_ctx_t *aes_ctx = soft_aes_ctx->aes_cbc;
+
+ length_needed = aes_ctx->ac_tag_len;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = 0;
+ out.cd_raw.iov_base = (char *)NULL;
+ out.cd_raw.iov_len = 0;
+
+ rc = aes_decrypt_contiguous_blocks(aes_ctx,
+ (char *)in_buf, length_needed, &out);
+
+ if (rc != 0) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ /* order of following 2 lines MUST not be reversed */
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = 0;
+ out.cd_raw.iov_base = (char *)NULL;
+ out.cd_raw.iov_len = 0;
+
+ rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
+ AES_BLOCK_LEN, aes_encrypt_block,
+ aes_xor_block);
+
+ if (rc != CRYPTO_SUCCESS) {
+ *pulDataLen = 0;
+ return (CRYPTO_FAILED);
+ }
+
+ *pulDataLen = 0;
+
+ break;
+ }
+#endif
+ } /* end switch */
+
+ return (rv);
+}
+
+/* AES self-test for 128-bit, 192-bit, or 256-bit key sizes */
+int
+fips_aes_post(int aes_key_size)
+{
+ /* AES Known Key (up to 256-bits). */
+ static uint8_t aes_known_key[] = {
+ "AES-128 RIJNDAELLEADNJIR 821-SEA"
+ };
+
+ /* AES-CBC Known Initialization Vector (128-bits). */
+ static uint8_t aes_cbc_known_initialization_vector[] =
+ { "SecurityytiruceS" };
+
+ /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
+ static uint8_t aes_known_plaintext[] = { "Sun Open Solaris" };
+
+ /* AES Known Ciphertext (128-bit key). */
+ static uint8_t aes_ecb128_known_ciphertext[] = {
+ 0xcc, 0xd1, 0xd0, 0xf3, 0xfd, 0x44, 0xb1, 0x4d,
+ 0xfe, 0x33, 0x20, 0x72, 0x3c, 0xf3, 0x4d, 0x27
+ };
+
+ static uint8_t aes_cbc128_known_ciphertext[] = {
+ 0x59, 0x34, 0x55, 0xd1, 0x89, 0x9b, 0xf4, 0xa5,
+ 0x16, 0x2c, 0x4c, 0x14, 0xd3, 0xe2, 0xe5, 0xed
+ };
+
+ /* AES Known Ciphertext (192-bit key). */
+ static uint8_t aes_ecb192_known_ciphertext[] = {
+ 0xa3, 0x78, 0x10, 0x44, 0xd8, 0xee, 0x8a, 0x98,
+ 0x41, 0xa4, 0xeb, 0x96, 0x57, 0xd8, 0xa0, 0xc5
+ };
+
+ static uint8_t aes_cbc192_known_ciphertext[] = {
+ 0x22, 0x9c, 0x68, 0xc6, 0x86, 0x68, 0xcc, 0x6a,
+ 0x56, 0x2c, 0xb8, 0xe0, 0x16, 0x4e, 0x8b, 0x78
+ };
+
+ /* AES Known Ciphertext (256-bit key). */
+ static uint8_t aes_ecb256_known_ciphertext[] = {
+ 0xe4, 0x65, 0x92, 0x7f, 0xd0, 0xdd, 0x59, 0x49,
+ 0x79, 0xc3, 0xac, 0x96, 0x30, 0xad, 0x32, 0x52
+ };
+
+ static uint8_t aes_cbc256_known_ciphertext[] = {
+ 0xd9, 0x44, 0x43, 0xe8, 0xdb, 0x60, 0x6b, 0xde,
+ 0xc2, 0x84, 0xbf, 0xb9, 0xaf, 0x43, 0x3f, 0x51
+ };
+
+ uint8_t *aes_ecb_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ecb128_known_ciphertext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ecb192_known_ciphertext :
+ aes_ecb256_known_ciphertext;
+
+ uint8_t *aes_cbc_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_cbc128_known_ciphertext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_cbc192_known_ciphertext :
+ aes_cbc256_known_ciphertext;
+
+ /* AES-CTR Known Key (128-bits). */
+ static uint8_t aes_ctr128_known_key[] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+ };
+
+ /* AES-CTR Known Key (192-bits). */
+ static uint8_t aes_ctr192_known_key[] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
+ };
+
+ /* AES-CTR Known Key (256-bits). */
+ static uint8_t aes_ctr256_known_key[] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+ };
+
+ /* AES-CTR Known Initialization Counter (128-bits). */
+ static uint8_t aes_ctr_known_counter[] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+
+ /* AES-CTR Known Plaintext (128-bits). */
+ static uint8_t aes_ctr_known_plaintext[] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+ };
+
+ /* AES-CTR Known Ciphertext. */
+ static uint8_t aes_ctr128_known_ciphertext[] = {
+ 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
+ 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce
+ };
+
+ static uint8_t aes_ctr192_known_ciphertext[] = {
+ 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2,
+ 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b
+ };
+
+ static uint8_t aes_ctr256_known_ciphertext[] = {
+ 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5,
+ 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28
+ };
+
+ uint8_t *aes_ctr_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ctr128_known_ciphertext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ctr192_known_ciphertext :
+ aes_ctr256_known_ciphertext;
+
+ uint8_t *aes_ctr_known_key =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ctr128_known_key :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ctr192_known_key :
+ aes_ctr256_known_key;
+
+#ifdef _KERNEL
+ /* AES-CCM Known Key (128-bits). */
+ static uint8_t aes_ccm128_known_key[] = {
+ 0x06, 0xfd, 0xf0, 0x83, 0xb5, 0xcb, 0x3b, 0xc7,
+ 0xc0, 0x6d, 0x4d, 0xe5, 0xa6, 0x34, 0xc6, 0x50
+ };
+
+ /* AES-CCM Known Key (192-bits). */
+ static uint8_t aes_ccm192_known_key[] = {
+ 0xde, 0x91, 0x08, 0x63, 0xbe, 0x59, 0xb8, 0x7a,
+ 0x45, 0x9b, 0xa6, 0xce, 0x2d, 0x7e, 0x71, 0x56,
+ 0x1c, 0x5c, 0x15, 0xea, 0x1b, 0x6b, 0x05, 0x06
+ };
+
+ /* AES-CCM Known Key (256-bits). */
+ static uint8_t aes_ccm256_known_key[] = {
+ 0x84, 0x9c, 0x1d, 0xeb, 0x80, 0xf8, 0x5b, 0x7d,
+ 0x25, 0x33, 0x64, 0x75, 0x4b, 0xdc, 0x5d, 0xf0,
+ 0xe8, 0x1c, 0x98, 0x8a, 0x78, 0x8f, 0x15, 0xd1,
+ 0xa2, 0x52, 0x49, 0xfa, 0x18, 0x5e, 0x1f, 0xd3
+ };
+
+ /* AES-CCM Known Nonce Nlen = 7 bytes (for 128-bits key). */
+ static uint8_t aes_ccm128_known_nonce[] = {
+ 0xfd, 0xe2, 0xd5, 0x4c, 0x65, 0x4e, 0xe4
+ };
+
+ /* AES-CCM Known Nonce Nlen = 7 bytes (192-bits). */
+ static uint8_t aes_ccm192_known_nonce[] = {
+ 0xcf, 0xb3, 0x48, 0xfa, 0x04, 0x36, 0xa2
+ };
+
+ /* AES-CCM Known Nonce Nlen = 7 bytes (256-bits). */
+ static uint8_t aes_ccm256_known_nonce[] = {
+ 0x75, 0xa5, 0x5b, 0x58, 0x33, 0x9d, 0x1c
+ };
+
+ /* AES-CCM Known Adata Alen = 30 bytes (128-bits). */
+ static uint8_t aes_ccm128_known_adata[] = {
+ 0xe0, 0xdf, 0xfc, 0x4c, 0x92, 0x90, 0xd8, 0x28,
+ 0xef, 0xe7, 0xc6, 0xbe, 0x4a, 0xbc, 0xd1, 0x3e,
+ 0x23, 0x61, 0x92, 0x2f, 0xfa, 0x27, 0xa4, 0x0e,
+ 0x61, 0x24, 0x58, 0x38, 0x55, 0x33
+ };
+
+ /* AES-CCM Known Adata Alen = 30 bytes (192-bits). */
+ static uint8_t aes_ccm192_known_adata[] = {
+ 0x4c, 0x5b, 0x4f, 0xfe, 0x80, 0xba, 0x7a, 0xe5,
+ 0xd3, 0xe8, 0xbc, 0xf6, 0x55, 0x83, 0xcf, 0x58,
+ 0xa2, 0x82, 0x59, 0x65, 0xba, 0xbd, 0x63, 0x53,
+ 0x0c, 0xb0, 0x0c, 0x14, 0xd4, 0x7b
+ };
+
+ /* AES-CCM Known Adata Alen = 30 bytes (256-bits). */
+ static uint8_t aes_ccm256_known_adata[] = {
+ 0x27, 0xb7, 0xec, 0x91, 0x08, 0xe1, 0x4d, 0x12,
+ 0xd3, 0xd3, 0xb8, 0x49, 0x09, 0xde, 0xd0, 0x9a,
+ 0x8f, 0x23, 0xbf, 0xd6, 0x02, 0x9b, 0x2a, 0x5e,
+ 0x4a, 0x5a, 0x63, 0x8c, 0x72, 0x14
+ };
+
+ /* AES-CCM Known Payload Plen = 32 bytes (128-bits). */
+ static uint8_t aes_ccm128_known_plaintext[] = {
+ 0x77, 0xca, 0xdf, 0xa5, 0xb1, 0x23, 0xfe, 0x07,
+ 0x8d, 0xca, 0x94, 0xe2, 0x66, 0x3f, 0x73, 0xd0,
+ 0x3f, 0x0b, 0x4d, 0xc8, 0x05, 0xf6, 0x1c, 0xef,
+ 0x13, 0x79, 0xc0, 0xb1, 0xfc, 0x76, 0xea, 0x11
+ };
+
+ /* AES-CCM Known Payload Plen = 32 bytes (192-bits). */
+ static uint8_t aes_ccm192_known_plaintext[] = {
+ 0xf9, 0x8a, 0x58, 0x59, 0x44, 0x2d, 0x2a, 0xf9,
+ 0x65, 0x03, 0x36, 0x6d, 0x8a, 0x58, 0x29, 0xf9,
+ 0xef, 0x47, 0x44, 0x30, 0xf4, 0x7e, 0x0d, 0xcd,
+ 0x73, 0x41, 0x45, 0xdf, 0x50, 0xb2, 0x1b, 0x29
+ };
+
+ /* AES-CCM Known Payload Plen = 32 bytes (256-bits). */
+ static uint8_t aes_ccm256_known_plaintext[] = {
+ 0x25, 0x28, 0x3f, 0x05, 0x41, 0xd6, 0x66, 0x3b,
+ 0xdb, 0x8f, 0xe9, 0xe7, 0x7b, 0x06, 0xc0, 0xee,
+ 0xfe, 0xf6, 0xc9, 0x8b, 0x45, 0x08, 0x18, 0x4e,
+ 0x2e, 0xf7, 0x8e, 0x64, 0xc3, 0xf2, 0xad, 0x18
+ };
+
+ /*
+ * AES-CCM Known Ciphertext
+ * Clen = 32 bytes + Tlen = 16 bytes (128-bits).
+ */
+ static uint8_t aes_ccm128_known_ciphertext[] = {
+ 0x33, 0x50, 0x58, 0xbb, 0x5f, 0x13, 0x8d, 0xc9,
+ 0x5b, 0x2c, 0xa4, 0x50, 0x1d, 0x7f, 0xd4, 0xa5,
+ 0xb9, 0xb8, 0x71, 0x83, 0x8f, 0x82, 0x27, 0x5f,
+ 0x75, 0x3e, 0x30, 0xf9, 0x9d, 0xad, 0xc2, 0xe9,
+ 0x66, 0x93, 0x56, 0x98, 0x01, 0x1e, 0x3c, 0x11,
+ 0x74, 0xdb, 0x9b, 0xca, 0xce, 0x0f, 0xc3, 0x35
+ };
+
+ /*
+ * AES-CCM Known Ciphertext
+ * Clen = 32 bytes + Tlen = 16 bytes (192-bits).
+ */
+ static uint8_t aes_ccm192_known_ciphertext[] = {
+ 0xa7, 0x40, 0xd0, 0x25, 0xbd, 0x3e, 0x8f, 0xd5,
+ 0x28, 0x3e, 0xee, 0xaa, 0xf9, 0xa7, 0xfc, 0xf2,
+ 0x33, 0xf6, 0x69, 0xb8, 0xdc, 0x9c, 0x74, 0xb1,
+ 0x46, 0xf4, 0xd6, 0xcc, 0x0a, 0x16, 0x12, 0x0c,
+ 0x7c, 0x3c, 0x43, 0x76, 0x94, 0xf6, 0x9a, 0x14,
+ 0xa0, 0xfb, 0xab, 0x9c, 0x2c, 0xd3, 0x5c, 0x09
+ };
+
+ /*
+ * AES-CCM Known Ciphertext
+ * Clen = 32 bytes + Tlen = 16 bytes (256-bits).
+ */
+ static uint8_t aes_ccm256_known_ciphertext[] = {
+ 0xf6, 0x4d, 0x24, 0x69, 0x0e, 0xde, 0xc9, 0xc0,
+ 0x1e, 0x42, 0xc0, 0x78, 0x29, 0xcf, 0xdb, 0xfe,
+ 0xab, 0x52, 0x9a, 0xb1, 0x07, 0xe4, 0xac, 0xdf,
+ 0x48, 0x46, 0x46, 0xc1, 0xe2, 0xb2, 0x0f, 0x36,
+ 0x5f, 0xeb, 0x44, 0xcf, 0xa8, 0x80, 0x80, 0x23,
+ 0xc9, 0xee, 0xc7, 0x56, 0x24, 0x63, 0x6e, 0x7e
+ };
+
+ uint8_t *aes_ccm_known_plaintext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ccm128_known_plaintext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ccm192_known_plaintext :
+ aes_ccm256_known_plaintext;
+
+ uint8_t *aes_ccm_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ccm128_known_ciphertext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ccm192_known_ciphertext :
+ aes_ccm256_known_ciphertext;
+
+ uint8_t *aes_ccm_known_key =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ccm128_known_key :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ccm192_known_key :
+ aes_ccm256_known_key;
+
+ uint8_t *aes_ccm_known_adata =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ccm128_known_adata :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ccm192_known_adata :
+ aes_ccm256_known_adata;
+
+ uint8_t *aes_ccm_known_nonce =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_ccm128_known_nonce :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_ccm192_known_nonce :
+ aes_ccm256_known_nonce;
+
+ /* AES-GCM Known Key (128-bits). */
+ static uint8_t aes_gcm128_known_key[] = {
+ 0x7d, 0xf9, 0x9c, 0xdf, 0x7d, 0x00, 0xd9, 0xea,
+ 0xd3, 0x85, 0x17, 0x1b, 0x29, 0xae, 0xcf, 0xbc
+ };
+
+ /* AES-GCM Known Key (192-bits). */
+ static uint8_t aes_gcm192_known_key[] = {
+ 0x85, 0xf4, 0x34, 0x7a, 0xf5, 0x98, 0x1e, 0xd9,
+ 0x89, 0x85, 0x98, 0x1a, 0x53, 0xfc, 0xc5, 0xbf,
+ 0x53, 0x6c, 0x91, 0x4b, 0x18, 0x3c, 0xe8, 0x12
+ };
+
+ /* AES-GCM Known Key (256-bits). */
+ static uint8_t aes_gcm256_known_key[] = {
+ 0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92,
+ 0x1c, 0x04, 0x65, 0x66, 0x5f, 0x8a, 0xe6, 0xd1,
+ 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
+ 0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
+ };
+
+ /* AES-GCM Known Initialization Vector (128-bits). */
+ static uint8_t aes_gcm128_known_iv[] = {
+ 0x27, 0x4c, 0x4e, 0xae, 0xfe, 0xef, 0xae, 0x26,
+ 0x80, 0xb0, 0xef, 0xd5
+ };
+
+ /* AES-GCM Known Initialization Vector (192-bits). */
+ static uint8_t aes_gcm192_known_iv[] = {
+ 0xd4, 0xfb, 0x33, 0xc6, 0x51, 0xc8, 0x86, 0xff,
+ 0x28, 0x80, 0xef, 0x96
+ };
+
+ /* AES-GCM Known Initialization Vector (256-bits). */
+ static uint8_t aes_gcm256_known_iv[] = {
+ 0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0,
+ 0xee, 0xd0, 0x66, 0x84
+ };
+
+ /* AES-GCM Known AAD Alen = 16 bytes (128-bits). */
+ static uint8_t aes_gcm128_known_adata[] = {
+ 0x60, 0xe8, 0xb0, 0x37, 0xec, 0xdf, 0x4d, 0x82,
+ 0x8c, 0x83, 0x0d, 0xcf, 0xc5, 0xce, 0xd4, 0x9c
+ };
+
+ /* AES-GCM Known AAD Alen = 16 bytes (192-bits). */
+ static uint8_t aes_gcm192_known_adata[] = {
+ 0x44, 0x3a, 0xdf, 0xad, 0xbb, 0x29, 0xd6, 0x8c,
+ 0x55, 0xe2, 0x02, 0x2d, 0xca, 0x62, 0x9b, 0x51
+ };
+
+ /* AES-GCM Known AAD Alen = 16 bytes (256-bits). */
+ static uint8_t aes_gcm256_known_adata[] = {
+ 0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b,
+ 0xdb, 0x37, 0x0c, 0x43, 0x7f, 0xec, 0x78, 0xde
+ };
+
+ /* AES-GCM Known Payload Plen = 16 bytes (128-bits). */
+ static uint8_t aes_gcm128_known_plaintext[] = {
+ 0x99, 0x66, 0x7d, 0xc9, 0x62, 0xb3, 0x9f, 0x14,
+ 0x8c, 0xdd, 0xfe, 0x68, 0xf9, 0x0a, 0x43, 0xf9
+ };
+
+ /* AES-GCM Known Payload Plen = 16 bytes (192-bits). */
+ static uint8_t aes_gcm192_known_plaintext[] = {
+ 0x7f, 0x9c, 0x08, 0x1d, 0x6a, 0xcc, 0xa8, 0xab,
+ 0x71, 0x75, 0xcb, 0xd0, 0x49, 0x42, 0xba, 0xad
+ };
+ /* AES-GCM Known Payload Plen = 16 bytes (256-bits). */
+ static uint8_t aes_gcm256_known_plaintext[] = {
+ 0xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e,
+ 0xeb, 0x31, 0xb2, 0xea, 0xcc, 0x2b, 0xf2, 0xa5
+ };
+
+ /* AES-GCM Known Ciphertext Clen = 16 bytes (128-bits) + tag */
+ static uint8_t aes_gcm128_known_ciphertext[] = {
+ 0x2b, 0x5f, 0x57, 0xf2, 0x62, 0x27, 0xe0, 0x94,
+ 0xe7, 0xf8, 0x01, 0x23, 0xf9, 0xed, 0xbd, 0xe8,
+ 0x16, 0xee, 0x08, 0xb4, 0xd8, 0x07, 0xe5, 0xdb,
+ 0xd5, 0x70, 0x3c, 0xb3, 0xcf, 0x53, 0x8c, 0x14
+ };
+
+ /* AES-GCM Known Ciphertext Clen = 16 bytes (192-bits) + tag */
+ static uint8_t aes_gcm192_known_ciphertext[] = {
+ 0xdd, 0x7e, 0x7e, 0x45, 0x5b, 0x21, 0xd8, 0x84,
+ 0x3d, 0x7b, 0xc3, 0x1f, 0x21, 0x07, 0xf9, 0x55,
+ 0x9f, 0x0e, 0x8d, 0xe2, 0x6d, 0xb4, 0x95, 0xf5,
+ 0x91, 0x1f, 0xb6, 0x0c, 0xf5, 0xf2, 0x3a, 0xf9
+ };
+
+ /* AES-GCM Known Ciphertext Clen = 16 bytes (256-bits)+ tag */
+ static uint8_t aes_gcm256_known_ciphertext[] = {
+ 0xf7, 0x26, 0x44, 0x13, 0xa8, 0x4c, 0x0e, 0x7c,
+ 0xd5, 0x36, 0x86, 0x7e, 0xb9, 0xf2, 0x17, 0x36,
+ 0x67, 0xba, 0x05, 0x10, 0x26, 0x2a, 0xe4, 0x87,
+ 0xd7, 0x37, 0xee, 0x62, 0x98, 0xf7, 0x7e, 0x0c
+ };
+
+ uint8_t *aes_gcm_known_key =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gcm128_known_key :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gcm192_known_key :
+ aes_gcm256_known_key;
+
+ uint8_t *aes_gcm_known_iv =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gcm128_known_iv :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gcm192_known_iv :
+ aes_gcm256_known_iv;
+
+ uint8_t *aes_gcm_known_plaintext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gcm128_known_plaintext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gcm192_known_plaintext :
+ aes_gcm256_known_plaintext;
+
+ uint8_t *aes_gcm_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gcm128_known_ciphertext :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gcm192_known_ciphertext :
+ aes_gcm256_known_ciphertext;
+
+ uint8_t *aes_gcm_known_adata =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gcm128_known_adata :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gcm192_known_adata :
+ aes_gcm256_known_adata;
+
+ /*
+ * Source: NIST gcmEncryptExtIV128.txt
+ * Count = 0, [Keylen = 128], [IVlen = 96], [PTlen = 0],
+ * [AADlen = 128], [Taglen = 128]
+ *
+ * Source: NIST gcmEncryptExtIV192.txt
+ * Count = 0, [Keylen = 192], [IVlen = 96], [PTlen = 0],
+ * [AADlen = 128], [Taglen = 128]
+ *
+ * Source: NIST gcmEncryptExtIV256.txt
+ * Count = 0, [Keylen = 256], [IVlen = 96], [PTlen = 0],
+ * [AADlen = 128], [Taglen = 128]
+ */
+
+ /* AES-GMAC Known Key (128-bits). */
+ static uint8_t aes_gmac128_known_key[] = {
+ 0x7d, 0x70, 0xd2, 0x32, 0x48, 0xc4, 0x7e, 0xb3,
+ 0xd2, 0x73, 0xdf, 0x81, 0xed, 0x30, 0x24, 0xbd
+ };
+
+ /* AES-GMAC Known Key (192-bits). */
+ static uint8_t aes_gmac192_known_key[] = {
+ 0x03, 0x60, 0x22, 0xfe, 0x26, 0x9a, 0xdc, 0xad,
+ 0xb5, 0x73, 0x11, 0xa4, 0xa0, 0xed, 0x2a, 0x84,
+ 0x18, 0x34, 0xb8, 0xb6, 0xd8, 0xa0, 0x7f, 0x41
+ };
+
+ /* AES-GMAC Known Key (256-bits). */
+ static uint8_t aes_gmac256_known_key[] = {
+ 0xbb, 0x10, 0x10, 0x06, 0x4f, 0xb8, 0x35, 0x23,
+ 0xea, 0x9d, 0xf3, 0x2b, 0xad, 0x9f, 0x1f, 0x2a,
+ 0x4f, 0xce, 0xfc, 0x0f, 0x21, 0x07, 0xc0, 0xaa,
+ 0xba, 0xd9, 0xb7, 0x56, 0xd8, 0x09, 0x21, 0x9d
+ };
+
+ /* AES-GMAC Known Initialization Vector (128-bits). */
+ static uint8_t aes_gmac128_known_iv[] = {
+ 0xab, 0x53, 0x23, 0x33, 0xd6, 0x76, 0x51, 0x20,
+ 0x8b, 0x8c, 0x34, 0x85
+ };
+
+ /* AES-GMAC Known Initialization Vector (192-bits). */
+ static uint8_t aes_gmac192_known_iv[] = {
+ 0x85, 0x65, 0xb2, 0x15, 0x3a, 0x3f, 0x34, 0x9a,
+ 0x07, 0x31, 0x06, 0x79
+ };
+
+ /* AES-GMAC Known Initialization Vector (256-bits). */
+ static uint8_t aes_gmac256_known_iv[] = {
+ 0x2f, 0x9a, 0xd0, 0x12, 0xad, 0xfc, 0x12, 0x73,
+ 0x43, 0xfb, 0xe0, 0x56
+ };
+
+ /* AES-GMAC Known Tag (128-bits). */
+ static uint8_t aes_gmac128_known_tag[] = {
+ 0xcf, 0x89, 0x50, 0xa3, 0x10, 0xf5, 0xab, 0x8b,
+ 0x69, 0xd5, 0x00, 0x11, 0x1a, 0x44, 0xb0, 0x96
+ };
+
+ /* AES-GMAC Known Tag (192-bits). */
+ static uint8_t aes_gmac192_known_tag[] = {
+ 0x90, 0x21, 0xaf, 0x4c, 0xa0, 0x8d, 0x01, 0xef,
+ 0x82, 0x5a, 0x42, 0xf9, 0xbe, 0x3a, 0xb3, 0xe9
+ };
+
+ /* AES-GMAC Known Tag (256-bits). */
+ static uint8_t aes_gmac256_known_tag[] = {
+ 0xef, 0x06, 0xd5, 0x4d, 0xfd, 0x00, 0x02, 0x1d,
+ 0x75, 0x27, 0xdf, 0xf2, 0x6f, 0xc9, 0xd4, 0x84
+ };
+
+ /* AES-GMAC Known AAD Alen = 16 bytes (128-bits). */
+ static uint8_t aes_gmac128_known_adata[] = {
+ 0x7d, 0x1d, 0x42, 0xe8, 0x94, 0x60, 0xe9, 0x44,
+ 0xbf, 0xa4, 0x83, 0xdb, 0xe6, 0x92, 0xf0, 0x8d
+ };
+
+ /* AES-GMAC Known AAD Alen = 16 bytes (192-bits). */
+ static uint8_t aes_gmac192_known_adata[] = {
+ 0xad, 0xcf, 0x4f, 0xbb, 0xa0, 0xe0, 0x6a, 0x63,
+ 0x70, 0x71, 0x1a, 0x57, 0xf8, 0xdc, 0xd0, 0xc9
+ };
+
+ /* AES-GMAC Known AAD Alen = 16 bytes (256-bits). */
+ static uint8_t aes_gmac256_known_adata[] = {
+ 0xdb, 0x98, 0xd9, 0x0d, 0x1b, 0x69, 0x5c, 0xdb,
+ 0x74, 0x7a, 0x34, 0x3f, 0xbb, 0xc9, 0xf1, 0x41
+ };
+
+ uint8_t *aes_gmac_known_key =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gmac128_known_key :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gmac192_known_key :
+ aes_gmac256_known_key;
+
+ uint8_t *aes_gmac_known_iv =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gmac128_known_iv :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gmac192_known_iv :
+ aes_gmac256_known_iv;
+
+ uint8_t *aes_gmac_known_tag =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gmac128_known_tag :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gmac192_known_tag :
+ aes_gmac256_known_tag;
+
+ uint8_t *aes_gmac_known_adata =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ?
+ aes_gmac128_known_adata :
+ (aes_key_size == FIPS_AES_192_KEY_SIZE) ?
+ aes_gmac192_known_adata :
+ aes_gmac256_known_adata;
+
+ /* AES variables. */
+ uint8_t aes_ccm_computed_ciphertext[3*FIPS_AES_ENCRYPT_LENGTH];
+ uint8_t aes_ccm_computed_plaintext[2*FIPS_AES_DECRYPT_LENGTH];
+ uint8_t aes_gcm_computed_ciphertext[2*FIPS_AES_ENCRYPT_LENGTH];
+ uint8_t aes_gcm_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
+ uint8_t aes_gmac_computed_tag[FIPS_AES_ENCRYPT_LENGTH];
+ CK_AES_CCM_PARAMS ccm_param;
+ CK_AES_GCM_PARAMS gcm_param;
+ CK_AES_GMAC_PARAMS gmac_param;
+#endif
+
+ uint8_t aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
+ uint8_t aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
+ soft_aes_ctx_t *aes_context;
+ ulong_t aes_bytes_encrypted;
+ ulong_t aes_bytes_decrypted;
+ int rv;
+
+ /* check if aes_key_size is 128, 192, or 256 bits */
+ if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
+ (aes_key_size != FIPS_AES_192_KEY_SIZE) &&
+ (aes_key_size != FIPS_AES_256_KEY_SIZE))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-ECB Known Answer Encryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, NULL, AES_ECB_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, NULL, CKM_AES_ECB);
+#endif
+
+ if (aes_context == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, aes_known_plaintext,
+ FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
+ &aes_bytes_encrypted, CKM_AES_ECB);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_computed_ciphertext, aes_ecb_known_ciphertext,
+ FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-ECB Known Answer Decryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, NULL, AES_ECB_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, NULL, CKM_AES_ECB);
+#endif
+
+ if (aes_context == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = fips_aes_decrypt(aes_context, aes_ecb_known_ciphertext,
+ FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
+ &aes_bytes_decrypted, CKM_AES_ECB);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+ (memcmp(aes_computed_plaintext, aes_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-CBC Known Answer Encryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, aes_cbc_known_initialization_vector,
+ AES_CBC_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, aes_cbc_known_initialization_vector,
+ CKM_AES_CBC);
+#endif
+
+ if (aes_context == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, aes_known_plaintext,
+ FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
+ &aes_bytes_encrypted, CKM_AES_CBC);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_computed_ciphertext, aes_cbc_known_ciphertext,
+ FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-CBC Known Answer Decryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, aes_cbc_known_initialization_vector,
+ AES_CBC_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_known_key,
+ aes_key_size, aes_cbc_known_initialization_vector,
+ CKM_AES_CBC);
+#endif
+
+ if (aes_context == NULL)
+ return (CRYPTO_HOST_MEMORY);
+
+ rv = fips_aes_decrypt(aes_context, aes_cbc_known_ciphertext,
+ FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
+ &aes_bytes_decrypted, CKM_AES_CBC);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+ (memcmp(aes_computed_plaintext, aes_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-CTR Known Answer Encryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_ctr_known_key,
+ aes_key_size, aes_ctr_known_counter,
+ AES_CTR_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_ctr_known_key,
+ aes_key_size, aes_ctr_known_counter, CKM_AES_CTR);
+#endif
+
+ if (aes_context == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, aes_ctr_known_plaintext,
+ FIPS_AES_ENCRYPT_LENGTH, aes_computed_ciphertext,
+ &aes_bytes_encrypted, CKM_AES_CTR);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_computed_ciphertext, aes_ctr_known_ciphertext,
+ FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * AES-CTR Known Answer Decryption Test
+ */
+#ifdef _KERNEL
+ aes_context = fips_aes_build_context(aes_ctr_known_key,
+ aes_key_size, aes_ctr_known_counter,
+ AES_CTR_MECH_INFO_TYPE, B_FALSE);
+#else
+ aes_context = fips_aes_build_context(aes_ctr_known_key,
+ aes_key_size, aes_ctr_known_counter,
+ CKM_AES_CTR);
+#endif
+ if (aes_context == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ rv = fips_aes_decrypt(aes_context, aes_ctr_known_ciphertext,
+ FIPS_AES_DECRYPT_LENGTH, aes_computed_plaintext,
+ &aes_bytes_decrypted, CKM_AES_CTR);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CKR_OK) ||
+ (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+ (memcmp(aes_computed_plaintext, aes_ctr_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * The following POSTs are only available in Kernel
+ *
+ * CCM, GCM, and GMAC
+ */
+#ifdef _KERNEL
+
+ /*
+ * AES-CCM Known Answer Encryption Test
+ */
+ ccm_param.ulMACSize = 16; /* Tlen */
+ ccm_param.ulNonceSize = 7; /* Nlen */
+ ccm_param.ulAuthDataSize = 30; /* Alen */
+ ccm_param.ulDataSize = 32; /* Plen or Clen */
+ ccm_param.nonce = aes_ccm_known_nonce;
+ ccm_param.authData = aes_ccm_known_adata;
+
+ aes_context = fips_aes_build_context(aes_ccm_known_key,
+ aes_key_size, (uint8_t *)&ccm_param,
+ AES_CCM_MECH_INFO_TYPE, B_TRUE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, aes_ccm_known_plaintext,
+ 2*FIPS_AES_ENCRYPT_LENGTH, aes_ccm_computed_ciphertext,
+ &aes_bytes_encrypted, AES_CCM_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_encrypted != 3*FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_ccm_computed_ciphertext, aes_ccm_known_ciphertext,
+ 3*FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+ /*
+ * AES-CCM Known Answer Decryption Test
+ */
+ ccm_param.ulMACSize = 16; /* Tlen */
+ ccm_param.ulNonceSize = 7; /* Nlen */
+ ccm_param.ulAuthDataSize = 30; /* Alen */
+ ccm_param.ulDataSize = 48; /* Plen or Clen */
+ ccm_param.nonce = aes_ccm_known_nonce;
+ ccm_param.authData = aes_ccm_known_adata;
+
+ aes_context = fips_aes_build_context(aes_ccm_known_key,
+ aes_key_size, (uint8_t *)&ccm_param,
+ AES_CCM_MECH_INFO_TYPE, B_FALSE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_decrypt(aes_context, aes_ccm_known_ciphertext,
+ 2*FIPS_AES_DECRYPT_LENGTH, aes_ccm_computed_plaintext,
+ &aes_bytes_decrypted, AES_CCM_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_decrypted != 2*FIPS_AES_DECRYPT_LENGTH) ||
+ (memcmp(aes_ccm_computed_plaintext, aes_ccm_known_plaintext,
+ 2*FIPS_AES_DECRYPT_LENGTH) != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+ /*
+ * AES-GCM Known Answer Encryption Test
+ */
+ gcm_param.pIv = aes_gcm_known_iv;
+ gcm_param.ulIvLen = AES_GMAC_IV_LEN; /* IVlen = 96 bits */
+ gcm_param.ulTagBits = AES_GMAC_TAG_BITS; /* Taglen = 128 bits */
+ gcm_param.ulAADLen = 16;
+ gcm_param.pAAD = aes_gcm_known_adata;
+
+ aes_context = fips_aes_build_context(aes_gcm_known_key,
+ aes_key_size, (uint8_t *)&gcm_param,
+ AES_GCM_MECH_INFO_TYPE, B_TRUE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, aes_gcm_known_plaintext,
+ FIPS_AES_ENCRYPT_LENGTH, aes_gcm_computed_ciphertext,
+ &aes_bytes_encrypted, AES_GCM_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_encrypted != 2*FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_gcm_computed_ciphertext, aes_gcm_known_ciphertext,
+ 2*FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+ /*
+ * AES-GCM Known Answer Decryption Test
+ */
+ aes_context = fips_aes_build_context(aes_gcm_known_key,
+ aes_key_size, (uint8_t *)&gcm_param,
+ AES_GCM_MECH_INFO_TYPE, B_FALSE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_decrypt(aes_context, aes_gcm_known_ciphertext,
+ FIPS_AES_DECRYPT_LENGTH, aes_gcm_computed_plaintext,
+ &aes_bytes_decrypted, AES_GCM_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+ (memcmp(aes_gcm_computed_plaintext, aes_gcm_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH) != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+ /*
+ * AES-GMAC Known Answer Encryption Test
+ */
+ gmac_param.pIv = aes_gmac_known_iv;
+ gmac_param.ulAADLen = 16;
+ gmac_param.pAAD = aes_gmac_known_adata;
+
+ aes_context = fips_aes_build_context(aes_gmac_known_key,
+ aes_key_size, (uint8_t *)&gmac_param,
+ AES_GMAC_MECH_INFO_TYPE, B_TRUE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_encrypt(aes_context, NULL,
+ 0, aes_gmac_computed_tag,
+ &aes_bytes_encrypted, AES_GMAC_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH) ||
+ (memcmp(aes_gmac_computed_tag, aes_gmac_known_tag,
+ FIPS_AES_ENCRYPT_LENGTH) != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+ /*
+ * AES-GMAC Known Answer Decryption Test
+ */
+
+ aes_context = fips_aes_build_context(aes_gmac_known_key,
+ aes_key_size, (uint8_t *)&gmac_param,
+ AES_GMAC_MECH_INFO_TYPE, B_FALSE);
+
+ if (aes_context == NULL) {
+ return (CRYPTO_HOST_MEMORY);
+ }
+
+ rv = fips_aes_decrypt(aes_context, aes_gmac_known_tag,
+ FIPS_AES_DECRYPT_LENGTH, NULL,
+ &aes_bytes_decrypted, AES_GMAC_MECH_INFO_TYPE);
+
+ fips_aes_free_context(aes_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (aes_bytes_decrypted != 0))
+ return (CRYPTO_DEVICE_ERROR);
+
+#endif /* _KERNEL */
+
+ return (CRYPTO_SUCCESS);
+}
diff --git a/usr/src/common/crypto/fips/fips_des_util.c b/usr/src/common/crypto/fips/fips_des_util.c
new file mode 100644
index 0000000000..4137229a11
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_des_util.c
@@ -0,0 +1,658 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/crypto/common.h>
+#include <sys/cmn_err.h>
+#include <modes/modes.h>
+#define _DES_FIPS_POST
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softCrypt.h"
+#else
+#define _DES_IMPL
+#include <des/des_impl.h>
+#endif
+
+#ifndef _KERNEL
+/*
+ * Allocate context for the DES encryption or decryption operation, and
+ * generate DES or DES3 key schedule to speed up the operation.
+ */
+soft_des_ctx_t *
+des_build_context(uint8_t *key, uint8_t *iv, CK_KEY_TYPE key_type,
+ CK_MECHANISM_TYPE mechanism)
+{
+
+ size_t size;
+ soft_des_ctx_t *soft_des_ctx;
+
+ soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
+ if (soft_des_ctx == NULL) {
+ return (NULL);
+ }
+
+ /* Allocate key schedule for DES or DES3 based on key type. */
+ if (key_type == CKK_DES) {
+ soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
+ if (soft_des_ctx->key_sched == NULL) {
+ free(soft_des_ctx);
+ return (NULL);
+ }
+ des_init_keysched(key, DES, soft_des_ctx->key_sched);
+ } else {
+ soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
+ if (soft_des_ctx->key_sched == NULL) {
+ free(soft_des_ctx);
+ return (NULL);
+ }
+ des_init_keysched(key, DES3, soft_des_ctx->key_sched);
+ }
+
+ soft_des_ctx->keysched_len = size;
+ soft_des_ctx->key_type = key_type;
+
+ if ((mechanism == CKM_DES_CBC) || (mechanism == CKM_DES3_CBC)) {
+ /* Save Initialization Vector (IV) in the context. */
+ (void) memcpy(soft_des_ctx->ivec, iv, DES_BLOCK_LEN);
+
+ /* Allocate a context for DES cipher-block chaining. */
+ soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
+ soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
+ soft_des_ctx->ivec, soft_des_ctx->key_type);
+
+ if (soft_des_ctx->des_cbc == NULL) {
+ bzero(soft_des_ctx->key_sched,
+ soft_des_ctx->keysched_len);
+ free(soft_des_ctx->key_sched);
+ return (NULL);
+ }
+ }
+
+ return (soft_des_ctx);
+}
+
+/*
+ * Free the DES context.
+ */
+void
+fips_des_free_context(soft_des_ctx_t *soft_des_ctx)
+{
+
+ des_ctx_t *des_ctx;
+
+ des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
+ if (des_ctx != NULL) {
+ bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
+ free(soft_des_ctx->des_cbc);
+ }
+
+ bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
+ free(soft_des_ctx->key_sched);
+ free(soft_des_ctx);
+}
+#else
+
+static void
+des_copy_block64(uint8_t *in, uint64_t *out)
+{
+ if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
+ /* LINTED: pointer alignment */
+ out[0] = *(uint64_t *)&in[0];
+ } else {
+ uint64_t tmp64;
+
+#ifdef _BIG_ENDIAN
+ tmp64 = (((uint64_t)in[0] << 56) |
+ ((uint64_t)in[1] << 48) |
+ ((uint64_t)in[2] << 40) |
+ ((uint64_t)in[3] << 32) |
+ ((uint64_t)in[4] << 24) |
+ ((uint64_t)in[5] << 16) |
+ ((uint64_t)in[6] << 8) |
+ (uint64_t)in[7]);
+#else
+ tmp64 = (((uint64_t)in[7] << 56) |
+ ((uint64_t)in[6] << 48) |
+ ((uint64_t)in[5] << 40) |
+ ((uint64_t)in[4] << 32) |
+ ((uint64_t)in[3] << 24) |
+ ((uint64_t)in[2] << 16) |
+ ((uint64_t)in[1] << 8) |
+ (uint64_t)in[0]);
+#endif /* _BIG_ENDIAN */
+
+ out[0] = tmp64;
+ }
+}
+
+des_ctx_t *
+des_build_context(uint8_t *key, uint8_t *iv,
+ des_mech_type_t mech_type)
+{
+ int rv = CRYPTO_SUCCESS;
+ void *keysched;
+ size_t size;
+ des_ctx_t *des_ctx = NULL;
+ des_strength_t strength;
+
+ switch (mech_type) {
+ case DES_ECB_MECH_INFO_TYPE:
+ des_ctx = ecb_alloc_ctx(KM_SLEEP);
+ /* FALLTHRU */
+ case DES_CBC_MECH_INFO_TYPE:
+ strength = DES;
+ if (des_ctx == NULL)
+ des_ctx = cbc_alloc_ctx(KM_SLEEP);
+ break;
+ case DES3_ECB_MECH_INFO_TYPE:
+ des_ctx = ecb_alloc_ctx(KM_SLEEP);
+ /* FALLTHRU */
+ case DES3_CBC_MECH_INFO_TYPE:
+ strength = DES3;
+ if (des_ctx == NULL)
+ des_ctx = cbc_alloc_ctx(KM_SLEEP);
+ break;
+ default:
+ return (NULL);
+ }
+
+ if ((keysched = des_alloc_keysched(&size, strength,
+ KM_SLEEP)) == NULL)
+ return (NULL);
+
+ /*
+ * Initialize key schedule.
+ * Key length is stored in the key.
+ */
+ des_init_keysched(key, strength, keysched);
+
+ des_ctx->dc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
+ des_ctx->dc_keysched_len = size;
+ des_ctx->dc_keysched = keysched;
+
+ if (strength == DES3) {
+ des_ctx->dc_flags |= DES3_STRENGTH;
+ }
+
+ switch (mech_type) {
+ case DES_CBC_MECH_INFO_TYPE:
+ case DES3_CBC_MECH_INFO_TYPE:
+ /* Save Initialization Vector (IV) in the context. */
+ rv = cbc_init_ctx((cbc_ctx_t *)des_ctx, (char *)iv,
+ DES_BLOCK_LEN, DES_BLOCK_LEN, des_copy_block64);
+ break;
+ case DES_ECB_MECH_INFO_TYPE:
+ case DES3_ECB_MECH_INFO_TYPE:
+ des_ctx->dc_flags |= ECB_MODE;
+ }
+
+ if (rv != CRYPTO_SUCCESS) {
+ if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
+ bzero(keysched, size);
+ kmem_free(keysched, size);
+ }
+ }
+
+ return (des_ctx);
+}
+
+void
+fips_des_free_context(des_ctx_t *des_ctx)
+{
+
+ if (des_ctx != NULL) {
+ if (des_ctx->dc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
+ ASSERT(des_ctx->dc_keysched_len != 0);
+ bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
+ kmem_free(des_ctx->dc_keysched,
+ des_ctx->dc_keysched_len);
+ }
+ }
+}
+#endif
+
+/*
+ * fips_des_encrypt()
+ *
+ * Arguments:
+ * soft_des_ctx: pointer to DES context
+ * in_buf: pointer to the input data to be encrypted
+ * ulDataLen: length of the input data
+ * out_buf: pointer to the output data after encryption
+ * pulEncryptedLen: pointer to the length of the output data
+ * mechanism: CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
+ *
+ * Description:
+ * This function calls the corresponding DES low-level encrypt
+ * routine based on the mechanism.
+ *
+ */
+#ifndef _KERNEL
+CK_RV
+fips_des_encrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
+ CK_ULONG ulDataLen, CK_BYTE_PTR out_buf,
+ CK_ULONG_PTR pulEncryptedLen, CK_MECHANISM_TYPE mechanism)
+#else
+int
+fips_des_encrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
+ ulong_t ulDataLen, uint8_t *out_buf,
+ ulong_t *pulEncryptedLen, des_mech_type_t mechanism)
+#endif
+{
+
+ CK_RV rv = CKR_OK;
+ int rc = 0;
+ ulong_t out_len;
+
+ /*
+ * DES only takes input length that is a multiple of blocksize
+ * with the mechanism CKM_DES<n>_ECB or CKM_DES<n>_CBC.
+ */
+ if ((ulDataLen % DES_BLOCK_LEN) != 0) {
+ return (CKR_DATA_LEN_RANGE);
+ }
+
+ /*
+ * For non-padding mode, the output length will
+ * be same as the input length.
+ */
+ out_len = ulDataLen;
+
+ /*
+ * Begin Encryption now.
+ */
+ switch (mechanism) {
+ case CKM_DES_ECB:
+ case CKM_DES3_ECB:
+ {
+
+ ulong_t i;
+ uint8_t *tmp_inbuf;
+ uint8_t *tmp_outbuf;
+
+ for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
+ tmp_inbuf = &in_buf[i];
+ tmp_outbuf = &out_buf[i];
+ /* Crunch one block of data for DES. */
+#ifndef _KERNEL
+ if (soft_des_ctx->key_type == CKK_DES)
+ (void) des_crunch_block(
+ soft_des_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf, B_FALSE);
+ else
+ (void) des3_crunch_block(
+ soft_des_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf, B_FALSE);
+#else
+ if (mechanism == DES_ECB_MECH_INFO_TYPE)
+ (void) des_crunch_block(des_ctx->dc_keysched,
+ tmp_inbuf, tmp_outbuf, B_FALSE);
+ else
+ (void) des3_crunch_block(des_ctx->dc_keysched,
+ tmp_inbuf, tmp_outbuf, B_FALSE);
+#endif
+ }
+
+ *pulEncryptedLen = out_len;
+ break;
+ }
+
+ case CKM_DES_CBC:
+ case CKM_DES3_CBC:
+ {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = out_len;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = out_len;
+
+ /* Encrypt multiple blocks of data. */
+ rc = des_encrypt_contiguous_blocks(
+#ifndef _KERNEL
+ (des_ctx_t *)soft_des_ctx->des_cbc,
+#else
+ des_ctx,
+#endif
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0)
+ goto encrypt_failed;
+
+ if (rc == 0) {
+ *pulEncryptedLen = out_len;
+ break;
+ }
+encrypt_failed:
+ *pulEncryptedLen = 0;
+
+ return (CKR_DEVICE_ERROR);
+
+ }
+ } /* end switch */
+
+ return (rv);
+}
+
+/*
+ * fips_des_decrypt()
+ *
+ * Arguments:
+ * soft_des_ctx: pointer to DES context
+ * in_buf: pointer to the input data to be decrypted
+ * ulEncryptedLen: length of the input data
+ * out_buf: pointer to the output data
+ * pulDataLen: pointer to the length of the output data
+ * mechanism: CKM_DES_ECB, CKM_DES3_ECB, CKM_DES_CBC, CKM_DES3_CBC
+ *
+ * Description:
+ * This function calls the corresponding DES low-level decrypt
+ * function based on the mechanism.
+ *
+ */
+#ifndef _KERNEL
+CK_RV
+fips_des_decrypt(soft_des_ctx_t *soft_des_ctx, CK_BYTE_PTR in_buf,
+ CK_ULONG ulEncryptedLen, CK_BYTE_PTR out_buf,
+ CK_ULONG_PTR pulDataLen, CK_MECHANISM_TYPE mechanism)
+#else
+int
+fips_des_decrypt(des_ctx_t *des_ctx, uint8_t *in_buf,
+ ulong_t ulEncryptedLen, uint8_t *out_buf,
+ ulong_t *pulDataLen, des_mech_type_t mechanism)
+#endif
+{
+
+ CK_RV rv = CKR_OK;
+ int rc = 0;
+ ulong_t out_len;
+
+ /*
+ * DES only takes input length that is a multiple of 8 bytes
+ * with the mechanism CKM_DES<n>_ECB, CKM_DES<n>_CBC or
+ * CKM_DES<n>_CBC_PAD.
+ */
+ if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
+ return (CKR_DATA_LEN_RANGE);
+ }
+
+ /* Set output length same as input length. */
+ out_len = ulEncryptedLen;
+
+ /*
+ * Begin Decryption.
+ */
+ switch (mechanism) {
+ case CKM_DES_ECB:
+ case CKM_DES3_ECB:
+ {
+ uint8_t *tmp_inbuf;
+ uint8_t *tmp_outbuf;
+ ulong_t i;
+
+ for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
+ tmp_inbuf = &in_buf[i];
+ tmp_outbuf = &out_buf[i];
+ /* Crunch one block of data for DES. */
+#ifndef _KERNEL
+ if (soft_des_ctx->key_type == CKK_DES)
+ (void) des_crunch_block(
+ soft_des_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf, B_TRUE);
+ else
+ (void) des3_crunch_block(
+ soft_des_ctx->key_sched,
+ tmp_inbuf, tmp_outbuf, B_TRUE);
+#else
+ if (mechanism == DES_ECB_MECH_INFO_TYPE)
+ (void) des_crunch_block(des_ctx->dc_keysched,
+ tmp_inbuf, tmp_outbuf, B_TRUE);
+ else
+ (void) des3_crunch_block(des_ctx->dc_keysched,
+ tmp_inbuf, tmp_outbuf, B_TRUE);
+#endif
+ }
+
+ *pulDataLen = out_len;
+ break;
+ }
+
+ case CKM_DES_CBC:
+ case CKM_DES3_CBC:
+ {
+ crypto_data_t out;
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = out_len;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = out_len;
+
+ /* Decrypt multiple blocks of data. */
+ rc = des_decrypt_contiguous_blocks(
+#ifndef _KERNEL
+ (des_ctx_t *)soft_des_ctx->des_cbc,
+#else
+ des_ctx,
+#endif
+ (char *)in_buf, out_len, &out);
+
+ if (rc != 0)
+ goto decrypt_failed;
+
+ *pulDataLen = out_len;
+
+ if (rc == 0)
+ break;
+decrypt_failed:
+ *pulDataLen = 0;
+
+ return (CKR_DEVICE_ERROR);
+
+ }
+ } /* end switch */
+
+ return (rv);
+}
+
+/*
+ * DES3 Power-On SelfTest(s).
+ */
+int
+fips_des3_post(void)
+{
+
+ /* DES3 Known Key. */
+ static uint8_t des3_known_key[] = { "ANSI Triple-DES Key Data" };
+
+ /* DES3-CBC Known Initialization Vector (64-bits). */
+ static uint8_t des3_cbc_known_iv[] = { "Security" };
+
+ /* DES3 Known Plaintext (64-bits). */
+ static uint8_t des3_ecb_known_plaintext[] = { "Solaris!" };
+ static uint8_t des3_cbc_known_plaintext[] = { "Solaris!" };
+
+ /* DES3 Known Ciphertext (64-bits). */
+ static uint8_t des3_ecb_known_ciphertext[] = {
+ 0x17, 0x0d, 0x1f, 0x13, 0xd3, 0xa0, 0x3a, 0x63
+ };
+
+ static uint8_t des3_cbc_known_ciphertext[] = {
+ 0x7f, 0x62, 0x44, 0xb3, 0xf8, 0x77, 0xf8, 0xf8
+ };
+
+ /* DES3 variables. */
+ uint8_t des3_computed_ciphertext[FIPS_DES3_ENCRYPT_LENGTH];
+ uint8_t des3_computed_plaintext[FIPS_DES3_DECRYPT_LENGTH];
+
+#ifdef _KERNEL
+ des_ctx_t *des3_context;
+#else
+ soft_des_ctx_t *des3_context;
+#endif
+
+ ulong_t des3_bytes_encrypted;
+ ulong_t des3_bytes_decrypted;
+ int rv;
+
+ /*
+ * DES3 ECB Known Answer Encryption Test
+ */
+#ifdef _KERNEL
+ des3_context = des_build_context(des3_known_key, NULL,
+ DES3_ECB_MECH_INFO_TYPE);
+#else
+ des3_context = des_build_context(des3_known_key, NULL,
+ CKK_DES3, CKM_DES3_ECB);
+#endif
+
+ if (des3_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+#ifdef _KERNEL
+ rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
+ FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
+ &des3_bytes_encrypted, DES3_ECB_MECH_INFO_TYPE);
+#else
+ rv = fips_des_encrypt(des3_context, des3_ecb_known_plaintext,
+ FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
+ &des3_bytes_encrypted, CKM_DES3_ECB);
+#endif
+
+ fips_des_free_context(des3_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
+ (memcmp(des3_computed_ciphertext, des3_ecb_known_ciphertext,
+ FIPS_DES3_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * DES3 ECB Known Answer Decryption Test
+ */
+#ifdef _KERNEL
+ des3_context = des_build_context(des3_known_key, NULL,
+ DES3_ECB_MECH_INFO_TYPE);
+#else
+ des3_context = des_build_context(des3_known_key, NULL,
+ CKK_DES3, CKM_DES3_ECB);
+#endif
+
+ if (des3_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+#ifdef _KERNEL
+ rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
+ FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
+ &des3_bytes_decrypted, DES3_ECB_MECH_INFO_TYPE);
+#else
+ rv = fips_des_decrypt(des3_context, des3_ecb_known_ciphertext,
+ FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
+ &des3_bytes_decrypted, CKM_DES3_ECB);
+#endif
+
+ fips_des_free_context(des3_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
+ (memcmp(des3_computed_plaintext, des3_ecb_known_plaintext,
+ FIPS_DES3_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * DES3 CBC Known Answer Encryption Test
+ */
+#ifdef _KERNEL
+ des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
+ DES3_CBC_MECH_INFO_TYPE);
+#else
+ des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
+ CKK_DES3, CKM_DES3_CBC);
+#endif
+
+ if (des3_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+#ifdef _KERNEL
+ rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
+ FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
+ &des3_bytes_encrypted, DES3_CBC_MECH_INFO_TYPE);
+#else
+ rv = fips_des_encrypt(des3_context, des3_cbc_known_plaintext,
+ FIPS_DES3_ENCRYPT_LENGTH, des3_computed_ciphertext,
+ &des3_bytes_encrypted, CKM_DES3_CBC);
+#endif
+
+ fips_des_free_context(des3_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (des3_bytes_encrypted != FIPS_DES3_ENCRYPT_LENGTH) ||
+ (memcmp(des3_computed_ciphertext, des3_cbc_known_ciphertext,
+ FIPS_DES3_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * DES3 CBC Known Answer Decryption Test
+ */
+#ifdef _KERNEL
+ des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
+ DES3_CBC_MECH_INFO_TYPE);
+#else
+ des3_context = des_build_context(des3_known_key, des3_cbc_known_iv,
+ CKK_DES3, CKM_DES3_CBC);
+#endif
+
+ if (des3_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+#ifdef _KERNEL
+ rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
+ FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
+ &des3_bytes_decrypted, DES3_CBC_MECH_INFO_TYPE);
+#else
+ rv = fips_des_decrypt(des3_context, des3_cbc_known_ciphertext,
+ FIPS_DES3_DECRYPT_LENGTH, des3_computed_plaintext,
+ &des3_bytes_decrypted, CKM_DES3_CBC);
+#endif
+
+ fips_des_free_context(des3_context);
+
+ if ((rv != CRYPTO_SUCCESS) ||
+ (des3_bytes_decrypted != FIPS_DES3_DECRYPT_LENGTH) ||
+ (memcmp(des3_computed_plaintext, des3_cbc_known_plaintext,
+ FIPS_DES3_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ return (CKR_OK);
+}
diff --git a/usr/src/common/crypto/fips/fips_ecc_util.c b/usr/src/common/crypto/fips/fips_ecc_util.c
new file mode 100644
index 0000000000..92c51fcb7e
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_ecc_util.c
@@ -0,0 +1,220 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sysmacros.h>
+#include <sys/crypto/common.h>
+#include <sys/cmn_err.h>
+#include <sys/sha1.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include "softMAC.h"
+#include "softEC.h"
+#endif
+#include <fips/fips_post.h>
+#include <ecc/ecc_impl.h>
+
+
+#define MAX_ECKEY_LEN 72
+#define SHA1_DIGEST_SIZE 20
+
+static int
+fips_ecdsa_sign_verify(uint8_t *encodedParams,
+ unsigned int encodedParamsLen,
+ uint8_t *knownSignature,
+ unsigned int knownSignatureLen) {
+
+ /* ECDSA Known Seed info for curves nistp256 */
+ static uint8_t ecdsa_Known_Seed[] = {
+ 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11,
+ 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1,
+ 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
+ 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
+ };
+
+ static uint8_t msg[] = {
+ "Sun Microsystems Solaris is awesome!"
+ };
+
+ unsigned char sha1[SHA1_DIGEST_SIZE]; /* SHA-1 hash (160 bits) */
+ unsigned char sig[2*MAX_ECKEY_LEN];
+ SECItem signature, digest;
+ SECItem encodedparams;
+ ECParams *ecparams = NULL;
+ ECPrivateKey *ecdsa_private_key = NULL;
+ ECPublicKey ecdsa_public_key;
+ SECStatus ecdsaStatus = SECSuccess;
+ SHA1_CTX *sha1_context = NULL;
+
+ /* construct the ECDSA private/public key pair */
+ encodedparams.type = siBuffer;
+ encodedparams.data = (unsigned char *) encodedParams;
+ encodedparams.len = encodedParamsLen;
+
+ if (EC_DecodeParams(&encodedparams, &ecparams, 0) != SECSuccess) {
+ return (CKR_ARGUMENTS_BAD);
+ }
+
+ /*
+ * Generates a new EC key pair. The private key is a supplied
+ * random value (in seed) and the public key is the result of
+ * performing a scalar point multiplication of that value with
+ * the curve's base point.
+ */
+
+ ecdsaStatus = ec_NewKey(ecparams, &ecdsa_private_key,
+ ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0);
+
+ if (ecdsaStatus != SECSuccess) {
+ return (CKR_DEVICE_ERROR);
+ }
+
+ /* construct public key from private key. */
+ ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena,
+ &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams);
+
+ if (ecdsaStatus != SECSuccess) {
+ goto loser;
+ }
+
+ ecdsa_public_key.publicValue = ecdsa_private_key->publicValue;
+
+ /* validate public key value */
+ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams,
+ &ecdsa_public_key.publicValue, 0);
+
+ if (ecdsaStatus != SECSuccess) {
+ goto loser;
+ }
+
+ /* validate public key value */
+ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams,
+ &ecdsa_private_key->publicValue, 0);
+
+ if (ecdsaStatus != SECSuccess) {
+ goto loser;
+ }
+
+ /*
+ * ECDSA Known Answer Signature Test.
+ */
+#ifdef _KERNEL
+ if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
+ KM_SLEEP)) == NULL)
+#else
+ if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL)
+#endif
+ return (CKR_HOST_MEMORY);
+
+ SHA1Init(sha1_context);
+
+#ifdef __sparcv9
+ SHA1Update(sha1_context, msg, (uint_t)sizeof (msg));
+#else /* !__sparcv9 */
+ SHA1Update(sha1_context, msg, sizeof (msg));
+#endif /* __sparcv9 */
+ SHA1Final(sha1, sha1_context);
+
+ digest.type = siBuffer;
+ digest.data = sha1;
+ digest.len = SHA1_DIGEST_SIZE;
+
+ (void) memset(sig, 0, sizeof (sig));
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = sizeof (sig);
+
+ ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
+ &digest, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0);
+
+ if (ecdsaStatus != SECSuccess) {
+ goto loser;
+ }
+
+ if ((signature.len != knownSignatureLen) ||
+ (memcmp(signature.data, knownSignature,
+ knownSignatureLen) != 0)) {
+ ecdsaStatus = SECFailure;
+ goto loser;
+ }
+
+ /*
+ * ECDSA Known Answer Verification Test.
+ */
+ ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature,
+ &digest, 0);
+
+loser:
+ if (ecdsaStatus != SECSuccess) {
+ return (CKR_DEVICE_ERROR);
+ }
+
+ return (CKR_OK);
+}
+
+int
+fips_ecdsa_post() {
+
+ /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */
+ static uint8_t ecdsa_known_P256_EncodedParams[] = {
+ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
+ 0x01, 0x07
+ };
+
+ static uint8_t ecdsa_known_P256_signature[] = {
+ 0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
+ 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
+ 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
+ 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
+ 0x2b, 0xdb, 0x86, 0x76, 0xe7, 0x32, 0xba, 0x13,
+ 0x03, 0x7f, 0x7f, 0x92, 0x77, 0xd8, 0x35, 0xfe,
+ 0x99, 0xb4, 0xb7, 0x85, 0x5a, 0xfb, 0xfb, 0xce,
+ 0x5d, 0x0e, 0xbc, 0x01, 0xfa, 0x44, 0x97, 0x7e
+ };
+
+ int rv;
+
+ /* ECDSA GF(p) prime field curve test */
+ rv = fips_ecdsa_sign_verify(ecdsa_known_P256_EncodedParams,
+ sizeof (ecdsa_known_P256_EncodedParams),
+ ecdsa_known_P256_signature,
+ sizeof (ecdsa_known_P256_signature));
+
+ if (rv != CKR_OK) {
+ return (CKR_DEVICE_ERROR);
+ }
+
+ return (CKR_OK);
+}
diff --git a/usr/src/common/crypto/fips/fips_post.h b/usr/src/common/crypto/fips/fips_post.h
new file mode 100644
index 0000000000..e622df7579
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_post.h
@@ -0,0 +1,61 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FIPS_POST_H
+#define _FIPS_POST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FIPS_KNOWN_HMAC_MESSAGE_LENGTH 64 /* 512-bits */
+
+#ifdef _KERNEL
+
+#define CK_BYTE uchar_t
+#define CK_ULONG ulong_t
+#define CK_RV int
+#define CKR_OK CRYPTO_SUCCESS
+#define CKR_HOST_MEMORY CRYPTO_HOST_MEMORY
+#define CKR_DEVICE_ERROR CRYPTO_DEVICE_ERROR
+#define CKR_DATA_LEN_RANGE CRYPTO_DATA_LEN_RANGE
+#define CKR_ENCRYPTED_DATA_LEN_RANGE CRYPTO_ENCRYPTED_DATA_LEN_RANGE
+#define CKR_ENCRYPTED_DATA_INVALID CRYPTO_ENCRYPTED_DATA_INVALID
+#define CKR_SIGNATURE_INVALID CRYPTO_SIGNATURE_INVALID
+#define CKR_ARGUMENTS_BAD CRYPTO_ARGUMENTS_BAD
+
+#else
+
+#define FIPS_RNG_XKEY_LENGTH 32 /* 256-bits */
+#define PAIRWISE_DIGEST_LENGTH 20 /* 160-bits */
+#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FIPS_POST_H */
diff --git a/usr/src/common/crypto/fips/fips_random_util.c b/usr/src/common/crypto/fips/fips_random_util.c
new file mode 100644
index 0000000000..3a162d4dcb
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_random_util.c
@@ -0,0 +1,89 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sha1.h>
+#include <sys/crypto/common.h>
+#include <sys/cmn_err.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softMAC.h"
+#endif
+#include <rng/fips_random.h>
+
+
+int
+fips_rng_post(void)
+{
+ static uint8_t XKeyValue[] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ static uint8_t XSeed[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ static uint8_t rng_known_GENX[] = {
+ 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
+ 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
+ 0xaf, 0xd8, 0x07, 0x09
+ };
+
+ uint8_t GENX[SHA1_HASH_SIZE];
+ uint8_t XKey[SHA1_HASH_SIZE];
+
+ (void) memcpy(XKey, XKeyValue, SHA1_HASH_SIZE);
+
+ /* Generate X with a known seed. */
+ fips_random_inner(
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ (uint32_t *)
+ XKey,
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ (uint32_t *)
+ GENX,
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ (uint32_t *)
+ XSeed);
+
+ /* Verify GENX to perform the RNG integrity check */
+ if ((memcmp(GENX, rng_known_GENX, (SHA1_HASH_SIZE)) != 0))
+ return (CKR_DEVICE_ERROR);
+ else
+ return (CKR_OK);
+}
diff --git a/usr/src/common/crypto/fips/fips_rsa_util.c b/usr/src/common/crypto/fips/fips_rsa_util.c
new file mode 100644
index 0000000000..37e2f93fc3
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_rsa_util.c
@@ -0,0 +1,942 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sysmacros.h>
+#include <sys/sha1.h>
+#define _SHA2_IMPL
+#include <sys/sha2.h>
+#include <sys/crypto/common.h>
+#define _RSA_FIPS_POST
+#include <rsa/rsa_impl.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softMAC.h"
+#endif
+#include <sha2/sha2_impl.h>
+
+int
+fips_rsa_encrypt(uint8_t *modulus, int modulus_len,
+ uint8_t *expo, int expo_len,
+ uint8_t *in, int in_len, uint8_t *out)
+{
+
+ RSAkey *rsakey;
+ BIGNUM msg;
+ CK_RV rv = CKR_OK;
+
+#ifdef _KERNEL
+ if ((rsakey = kmem_zalloc(sizeof (RSAkey), KM_SLEEP)) == NULL) {
+#else
+ if ((rsakey = calloc(1, sizeof (RSAkey))) == NULL) {
+#endif
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ if (RSA_key_init(rsakey, modulus_len * 4, modulus_len * 4) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean2;
+ }
+
+ /* Size for big_init is in (32-bit) words. */
+ if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean3;
+ }
+
+ /* Convert octet string exponent to big integer format. */
+ bytestring2bignum(&(rsakey->e), expo, expo_len);
+
+ /* Convert octet string modulus to big integer format. */
+ bytestring2bignum(&(rsakey->n), modulus, modulus_len);
+
+ /* Convert octet string input data to big integer format. */
+ bytestring2bignum(&msg, (uchar_t *)in, in_len);
+
+ if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
+ rv = CKR_DATA_LEN_RANGE;
+ goto clean4;
+ }
+
+ /* Perform RSA computation on big integer input data. */
+ if (big_modexp(&msg, &msg, &(rsakey->e), &(rsakey->n), NULL) !=
+ BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean4;
+ }
+
+ /* Convert the big integer output data to octet string. */
+ bignum2bytestring((uchar_t *)out, &msg, modulus_len);
+
+clean4:
+ big_finish(&msg);
+clean3:
+ RSA_key_finish(rsakey);
+clean2:
+#ifndef _KERNEL
+ free(rsakey);
+#else
+ kmem_free(rsakey, sizeof (RSAkey));
+#endif
+clean1:
+
+ return (rv);
+}
+
+int
+fips_rsa_decrypt(RSAPrivateKey_t *key, uint8_t *in, int in_len,
+ uint8_t *out)
+{
+
+ RSAkey *rsakey;
+ BIGNUM msg;
+ CK_RV rv = CKR_OK;
+
+#ifdef _KERNEL
+ if ((rsakey = kmem_zalloc(sizeof (RSAkey), KM_SLEEP)) == NULL) {
+#else
+ if ((rsakey = calloc(1, sizeof (RSAkey))) == NULL) {
+#endif
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ /* psize and qsize for RSA_key_init is in bits. */
+ if (RSA_key_init(rsakey, key->prime2_len * 8, key->prime1_len * 8)
+ != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean2;
+ }
+
+ /* Size for big_init is in (32-bit) words. */
+ if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean3;
+ }
+
+ /* Convert octet string input data to big integer format. */
+ bytestring2bignum(&msg, (uchar_t *)in, in_len);
+
+ /* Convert octet string modulus to big integer format. */
+ bytestring2bignum(&(rsakey->n), key->modulus, key->modulus_len);
+
+ if (big_cmp_abs(&msg, &(rsakey->n)) > 0) {
+ rv = CKR_DATA_LEN_RANGE;
+ goto clean4;
+ }
+
+ /* Convert the rest of private key attributes to big integer format. */
+ bytestring2bignum(&(rsakey->dmodpminus1), key->exponent2,
+ key->exponent2_len);
+ bytestring2bignum(&(rsakey->dmodqminus1), key->exponent1,
+ key->exponent1_len);
+ bytestring2bignum(&(rsakey->p), key->prime2, key->prime2_len);
+ bytestring2bignum(&(rsakey->q), key->prime1, key->prime1_len);
+ bytestring2bignum(&(rsakey->pinvmodq), key->coef, key->coef_len);
+
+ if ((big_cmp_abs(&(rsakey->dmodpminus1), &(rsakey->p)) > 0) ||
+ (big_cmp_abs(&(rsakey->dmodqminus1), &(rsakey->q)) > 0) ||
+ (big_cmp_abs(&(rsakey->pinvmodq), &(rsakey->q)) > 0)) {
+#ifndef _KERNEL
+ rv = CKR_KEY_SIZE_RANGE;
+#else
+ rv = CRYPTO_KEY_SIZE_RANGE;
+#endif
+ goto clean4;
+ }
+
+ /* Perform RSA computation on big integer input data. */
+ if (big_modexp_crt(&msg, &msg, &(rsakey->dmodpminus1),
+ &(rsakey->dmodqminus1), &(rsakey->p), &(rsakey->q),
+ &(rsakey->pinvmodq), NULL, NULL) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean4;
+ }
+
+ /* Convert the big integer output data to octet string. */
+ bignum2bytestring((uchar_t *)out, &msg, key->modulus_len);
+
+clean4:
+ big_finish(&msg);
+clean3:
+ RSA_key_finish(rsakey);
+clean2:
+#ifndef _KERNEL
+ free(rsakey);
+#else
+ kmem_free(rsakey, sizeof (RSAkey));
+#endif
+clean1:
+
+ return (rv);
+
+}
+
+int
+fips_rsa_sign(RSAPrivateKey_t *rsa_params, uint8_t *in,
+ uint32_t inlen, uint8_t *out)
+{
+ BIGNUM msg;
+ RSAkey rsakey;
+ CK_RV rv = CKR_OK;
+
+ /* psize and qsize for RSA_key_init is in bits. */
+ if (RSA_key_init(&rsakey, rsa_params->prime2_len * 8,
+ rsa_params->prime1_len * 8) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ /* Size for big_init is in BIG_CHUNK_TYPE words. */
+ if (big_init(&msg, CHARLEN2BIGNUMLEN(inlen)) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean2;
+ }
+
+ /* Convert octet string input data to big integer format. */
+ bytestring2bignum(&msg, (uchar_t *)in, inlen);
+
+ /* Convert octet string modulus to big integer format. */
+ bytestring2bignum(&(rsakey.n), rsa_params->modulus,
+ rsa_params->modulus_len);
+
+ if (big_cmp_abs(&msg, &(rsakey.n)) > 0) {
+ rv = CKR_DATA_LEN_RANGE;
+ goto clean3;
+ }
+
+ /* Convert the rest of private key attributes to big integer format. */
+ bytestring2bignum(&(rsakey.dmodpminus1), rsa_params->exponent2,
+ rsa_params->exponent2_len);
+ bytestring2bignum(&(rsakey.dmodqminus1), rsa_params->exponent1,
+ rsa_params->exponent1_len);
+ bytestring2bignum(&(rsakey.p), rsa_params->prime2,
+ rsa_params->prime2_len);
+ bytestring2bignum(&(rsakey.q), rsa_params->prime1,
+ rsa_params->prime1_len);
+ bytestring2bignum(&(rsakey.pinvmodq), rsa_params->coef,
+ rsa_params->coef_len);
+
+ if ((big_cmp_abs(&(rsakey.dmodpminus1), &(rsakey.p)) > 0) ||
+ (big_cmp_abs(&(rsakey.dmodqminus1), &(rsakey.q)) > 0) ||
+ (big_cmp_abs(&(rsakey.pinvmodq), &(rsakey.q)) > 0)) {
+#ifndef _KERNEL
+ rv = CKR_KEY_SIZE_RANGE;
+#else
+ rv = CRYPTO_KEY_SIZE_RANGE;
+#endif
+ goto clean3;
+ }
+
+ /* Perform RSA computation on big integer input data. */
+ if (big_modexp_crt(&msg, &msg, &(rsakey.dmodpminus1),
+ &(rsakey.dmodqminus1), &(rsakey.p), &(rsakey.q),
+ &(rsakey.pinvmodq), NULL, NULL) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean3;
+ }
+
+ /* Convert the big integer output data to octet string. */
+ bignum2bytestring((uchar_t *)out, &msg, rsa_params->modulus_len);
+
+clean3:
+ big_finish(&msg);
+clean2:
+ RSA_key_finish(&rsakey);
+clean1:
+
+ return (rv);
+
+}
+
+int
+fips_rsa_verify(RSAPrivateKey_t *rsa_params, uint8_t *in, uint32_t in_len,
+ uint8_t *out)
+{
+
+ BIGNUM msg;
+ RSAkey rsakey;
+ CK_RV rv = CKR_OK;
+
+ if (RSA_key_init(&rsakey, rsa_params->modulus_len * 4,
+ rsa_params->modulus_len * 4) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ /* Size for big_init is in BIG_CHUNK_TYPE words. */
+ if (big_init(&msg, CHARLEN2BIGNUMLEN(in_len)) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean2;
+ }
+
+ /* Convert octet string exponent to big integer format. */
+ bytestring2bignum(&(rsakey.e), rsa_params->public_expo,
+ rsa_params->public_expo_len);
+
+ /* Convert octet string modulus to big integer format. */
+ bytestring2bignum(&(rsakey.n), rsa_params->modulus,
+ rsa_params->modulus_len);
+
+ /* Convert octet string input data to big integer format. */
+ bytestring2bignum(&msg, (uchar_t *)in, in_len);
+
+ if (big_cmp_abs(&msg, &(rsakey.n)) > 0) {
+ rv = CKR_DATA_LEN_RANGE;
+ goto clean3;
+ }
+
+ /* Perform RSA computation on big integer input data. */
+ if (big_modexp(&msg, &msg, &(rsakey.e), &(rsakey.n), NULL) !=
+ BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean3;
+ }
+
+ /* Convert the big integer output data to octet string. */
+ bignum2bytestring((uchar_t *)out, &msg, rsa_params->modulus_len);
+
+clean3:
+ big_finish(&msg);
+clean2:
+ RSA_key_finish(&rsakey);
+clean1:
+
+ return (rv);
+}
+
+static CK_RV
+#ifdef _KERNEL
+fips_rsa_sign_verify_test(sha2_mech_t mechanism,
+#else
+fips_rsa_sign_verify_test(CK_MECHANISM_TYPE mechanism,
+#endif
+ RSAPrivateKey_t *rsa_private_key,
+ unsigned char *rsa_known_msg,
+ unsigned int rsa_msg_length,
+ unsigned char *rsa_computed_signature,
+ unsigned char *der_data, int sign)
+
+{
+ unsigned char hash[SHA512_DIGEST_LENGTH]; /* SHA digest */
+ SHA1_CTX *sha1_context = NULL;
+ SHA2_CTX *sha2_context = NULL;
+ int hash_len;
+ CK_RV rv;
+ CK_ULONG der_len;
+ CK_BYTE *der_prefix;
+ CK_ULONG der_data_len;
+ CK_BYTE plain_data[MAX_RSA_KEYLENGTH_IN_BYTES];
+ uint32_t modulus_len;
+
+ switch (mechanism) {
+#ifdef _KERNEL
+ case SHA1_TYPE:
+#else
+ case CKM_SHA_1:
+#endif
+ {
+
+#ifdef _KERNEL
+ if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
+ KM_SLEEP)) == NULL)
+#else
+ if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL)
+#endif
+ return (CKR_HOST_MEMORY);
+
+ SHA1Init(sha1_context);
+
+#ifdef __sparcv9
+ SHA1Update(sha1_context, rsa_known_msg,
+ (uint_t)rsa_msg_length);
+#else /* !__sparcv9 */
+ SHA1Update(sha1_context, rsa_known_msg, rsa_msg_length);
+#endif /* __sparcv9 */
+ SHA1Final(hash, sha1_context);
+
+ hash_len = SHA1_DIGEST_LENGTH;
+
+ /*
+ * Prepare the DER encoding of the DigestInfo value
+ * by setting it to:
+ * <MECH>_DER_PREFIX || H
+ */
+ der_len = SHA1_DER_PREFIX_Len;
+ der_prefix = (CK_BYTE *)SHA1_DER_PREFIX;
+ (void) memcpy(der_data, der_prefix, der_len);
+ (void) memcpy(der_data + der_len, hash, hash_len);
+ der_data_len = der_len + hash_len;
+ break;
+ }
+
+#ifdef _KERNEL
+ case SHA256_TYPE:
+#else
+ case CKM_SHA256:
+#endif
+ {
+
+ sha2_context = fips_sha2_build_context(mechanism);
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context, rsa_known_msg,
+ rsa_msg_length, hash);
+ hash_len = SHA256_DIGEST_LENGTH;
+
+ /*
+ * Prepare the DER encoding of the DigestInfo value
+ * by setting it to:
+ * <MECH>_DER_PREFIX || H
+ */
+ (void) memcpy(der_data, SHA256_DER_PREFIX,
+ SHA2_DER_PREFIX_Len);
+ (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
+ der_data_len = SHA2_DER_PREFIX_Len + hash_len;
+ break;
+ }
+#ifdef _KERNEL
+ case SHA384_TYPE:
+#else
+ case CKM_SHA384:
+#endif
+ {
+
+ sha2_context = fips_sha2_build_context(mechanism);
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context, rsa_known_msg,
+ rsa_msg_length, hash);
+ hash_len = SHA384_DIGEST_LENGTH;
+
+ /*
+ * Prepare the DER encoding of the DigestInfo value
+ * by setting it to:
+ * <MECH>_DER_PREFIX || H
+ */
+ (void) memcpy(der_data, SHA384_DER_PREFIX,
+ SHA2_DER_PREFIX_Len);
+ (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
+ der_data_len = SHA2_DER_PREFIX_Len + hash_len;
+ break;
+ }
+#ifdef _KERNEL
+ case SHA512_TYPE:
+#else
+ case CKM_SHA512:
+#endif
+ {
+
+ sha2_context = fips_sha2_build_context(mechanism);
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context, rsa_known_msg,
+ rsa_msg_length, hash);
+ hash_len = SHA512_DIGEST_LENGTH;
+
+ /*
+ * Prepare the DER encoding of the DigestInfo value
+ * by setting it to:
+ * <MECH>_DER_PREFIX || H
+ */
+ (void) memcpy(der_data, SHA512_DER_PREFIX,
+ SHA2_DER_PREFIX_Len);
+ (void) memcpy(der_data + SHA2_DER_PREFIX_Len, hash, hash_len);
+ der_data_len = SHA2_DER_PREFIX_Len + hash_len;
+ break;
+ }
+ }
+
+ modulus_len = rsa_private_key->modulus_len;
+
+ if (sign) {
+ rv = soft_sign_rsa_pkcs_encode(der_data, der_data_len,
+ plain_data, modulus_len);
+
+ if (rv != CKR_OK) {
+ return (CKR_DEVICE_ERROR);
+ }
+
+ rv = fips_rsa_sign(rsa_private_key, plain_data, modulus_len,
+ rsa_computed_signature);
+
+ if (rv != CKR_OK) {
+ return (CKR_DEVICE_ERROR);
+ }
+ } else {
+ /*
+ * Perform RSA decryption with the signer's RSA public key
+ * for verification process.
+ */
+ rv = fips_rsa_verify(rsa_private_key, rsa_computed_signature,
+ modulus_len, plain_data);
+
+ if (rv == CKR_OK) {
+
+ /*
+ * Strip off the encoded padding bytes in front of the
+ * recovered data, then compare the recovered data with
+ * the original data.
+ */
+ int data_len = modulus_len;
+
+ rv = soft_verify_rsa_pkcs_decode(plain_data, &data_len);
+ if (rv != CKR_OK) {
+ return (CKR_DEVICE_ERROR);
+ }
+
+ if ((CK_ULONG)data_len != der_data_len) {
+#ifdef _KERNEL
+ return (CRYPTO_SIGNATURE_LEN_RANGE);
+#else
+ return (CKR_SIGNATURE_LEN_RANGE);
+#endif
+ } else if (memcmp(der_data,
+ &plain_data[modulus_len - data_len],
+ data_len) != 0) {
+ return (CKR_SIGNATURE_INVALID);
+ }
+ } else {
+
+ return (CKR_DEVICE_ERROR);
+ }
+ }
+ return (CKR_OK);
+}
+
+
+/*
+ * RSA Power-On SelfTest(s).
+ */
+int
+fips_rsa_post(void)
+{
+ /*
+ * RSA Known Modulus used in both Public/Private Key Values (1024-bits).
+ */
+ static uint8_t rsa_modulus[FIPS_RSA_MODULUS_LENGTH] = {
+ 0xd5, 0x84, 0x95, 0x07, 0xf4, 0xd0, 0x1f, 0x82,
+ 0xf3, 0x79, 0xf4, 0x99, 0x48, 0x10, 0xe1, 0x71,
+ 0xa5, 0x62, 0x22, 0xa3, 0x4b, 0x00, 0xe3, 0x5b,
+ 0x3a, 0xcc, 0x10, 0x83, 0xe0, 0xaf, 0x61, 0x13,
+ 0x54, 0x6a, 0xa2, 0x6a, 0x2c, 0x5e, 0xb3, 0xcc,
+ 0xa3, 0x71, 0x9a, 0xb2, 0x3e, 0x78, 0xec, 0xb5,
+ 0x0e, 0x6e, 0x31, 0x3b, 0x77, 0x1f, 0x6e, 0x94,
+ 0x41, 0x60, 0xd5, 0x6e, 0xd9, 0xc6, 0xf9, 0x29,
+ 0xc3, 0x40, 0x36, 0x25, 0xdb, 0xea, 0x0b, 0x07,
+ 0xae, 0x76, 0xfd, 0x99, 0x29, 0xf4, 0x22, 0xc1,
+ 0x1a, 0x8f, 0x05, 0xfe, 0x98, 0x09, 0x07, 0x05,
+ 0xc2, 0x0f, 0x0b, 0x11, 0x83, 0x39, 0xca, 0xc7,
+ 0x43, 0x63, 0xff, 0x33, 0x80, 0xe7, 0xc3, 0x78,
+ 0xae, 0xf1, 0x73, 0x52, 0x98, 0x1d, 0xde, 0x5c,
+ 0x53, 0x6e, 0x01, 0x73, 0x0d, 0x12, 0x7e, 0x77,
+ 0x03, 0xf1, 0xef, 0x1b, 0xc8, 0xa8, 0x0f, 0x97
+ };
+
+ /* RSA Known Public Key Values (24-bits). */
+ static uint8_t rsa_public_exponent[FIPS_RSA_PUBLIC_EXPONENT_LENGTH] = {
+ 0x01, 0x00, 0x01
+ };
+
+ /*
+ * RSA Known Private Key Values (version is 8-bits),
+ * (private exponent is 1024-bits),
+ * (private prime0 is 512-bits),
+ * (private prime1 is 512-bits),
+ * (private prime exponent0 is 512-bits),
+ * (private prime exponent1 is 512-bits),
+ * and (private coefficient is 512-bits).
+ */
+ static uint8_t rsa_version[] = { 0x00 };
+
+ static uint8_t rsa_private_exponent[FIPS_RSA_PRIVATE_EXPONENT_LENGTH]
+ = {
+ 0x85, 0x27, 0x47, 0x61, 0x4c, 0xd4, 0xb5, 0xb2,
+ 0x0e, 0x70, 0x91, 0x8f, 0x3d, 0x97, 0xf9, 0x5f,
+ 0xcc, 0x09, 0x65, 0x1c, 0x7c, 0x5b, 0xb3, 0x6d,
+ 0x63, 0x3f, 0x7b, 0x55, 0x22, 0xbb, 0x7c, 0x48,
+ 0x77, 0xae, 0x80, 0x56, 0xc2, 0x10, 0xd5, 0x03,
+ 0xdb, 0x31, 0xaf, 0x8d, 0x54, 0xd4, 0x48, 0x99,
+ 0xa8, 0xc4, 0x23, 0x43, 0xb8, 0x48, 0x0b, 0xc7,
+ 0xbc, 0xf5, 0xcc, 0x64, 0x72, 0xbf, 0x59, 0x06,
+ 0x04, 0x1c, 0x32, 0xf5, 0x14, 0x2e, 0x6e, 0xe2,
+ 0x0f, 0x5c, 0xde, 0x36, 0x3c, 0x6e, 0x7c, 0x4d,
+ 0xcc, 0xd3, 0x00, 0x6e, 0xe5, 0x45, 0x46, 0xef,
+ 0x4d, 0x25, 0x46, 0x6d, 0x7f, 0xed, 0xbb, 0x4f,
+ 0x4d, 0x9f, 0xda, 0x87, 0x47, 0x8f, 0x74, 0x44,
+ 0xb7, 0xbe, 0x9d, 0xf5, 0xdd, 0xd2, 0x4c, 0xa5,
+ 0xab, 0x74, 0xe5, 0x29, 0xa1, 0xd2, 0x45, 0x3b,
+ 0x33, 0xde, 0xd5, 0xae, 0xf7, 0x03, 0x10, 0x21
+ };
+
+ static uint8_t rsa_prime0[FIPS_RSA_PRIME0_LENGTH] = {
+ 0xf9, 0x74, 0x8f, 0x16, 0x02, 0x6b, 0xa0, 0xee,
+ 0x7f, 0x28, 0x97, 0x91, 0xdc, 0xec, 0xc0, 0x7c,
+ 0x49, 0xc2, 0x85, 0x76, 0xee, 0x66, 0x74, 0x2d,
+ 0x1a, 0xb8, 0xf7, 0x2f, 0x11, 0x5b, 0x36, 0xd8,
+ 0x46, 0x33, 0x3b, 0xd8, 0xf3, 0x2d, 0xa1, 0x03,
+ 0x83, 0x2b, 0xec, 0x35, 0x43, 0x32, 0xff, 0xdd,
+ 0x81, 0x7c, 0xfd, 0x65, 0x13, 0x04, 0x7c, 0xfc,
+ 0x03, 0x97, 0xf0, 0xd5, 0x62, 0xdc, 0x0d, 0xbf
+ };
+
+ static uint8_t rsa_prime1[FIPS_RSA_PRIME1_LENGTH] = {
+ 0xdb, 0x1e, 0xa7, 0x3d, 0xe7, 0xfa, 0x8b, 0x04,
+ 0x83, 0x48, 0xf3, 0xa5, 0x31, 0x9d, 0x35, 0x5e,
+ 0x4d, 0x54, 0x77, 0xcc, 0x84, 0x09, 0xf3, 0x11,
+ 0x0d, 0x54, 0xed, 0x85, 0x39, 0xa9, 0xca, 0xa8,
+ 0xea, 0xae, 0x19, 0x9c, 0x75, 0xdb, 0x88, 0xb8,
+ 0x04, 0x8d, 0x54, 0xc6, 0xa4, 0x80, 0xf8, 0x93,
+ 0xf0, 0xdb, 0x19, 0xef, 0xd7, 0x87, 0x8a, 0x8f,
+ 0x5a, 0x09, 0x2e, 0x54, 0xf3, 0x45, 0x24, 0x29
+ };
+
+ static uint8_t rsa_exponent0[FIPS_RSA_EXPONENT0_LENGTH] = {
+ 0x6a, 0xd1, 0x25, 0x80, 0x18, 0x33, 0x3c, 0x2b,
+ 0x44, 0x19, 0xfe, 0xa5, 0x40, 0x03, 0xc4, 0xfc,
+ 0xb3, 0x9c, 0xef, 0x07, 0x99, 0x58, 0x17, 0xc1,
+ 0x44, 0xa3, 0x15, 0x7d, 0x7b, 0x22, 0x22, 0xdf,
+ 0x03, 0x58, 0x66, 0xf5, 0x24, 0x54, 0x52, 0x91,
+ 0x2d, 0x76, 0xfe, 0x63, 0x64, 0x4e, 0x0f, 0x50,
+ 0x2b, 0x65, 0x79, 0x1f, 0xf1, 0xbf, 0xc7, 0x41,
+ 0x26, 0xcc, 0xc6, 0x1c, 0xa9, 0x83, 0x6f, 0x03
+ };
+
+ static uint8_t rsa_exponent1[FIPS_RSA_EXPONENT1_LENGTH] = {
+ 0x12, 0x84, 0x1a, 0x99, 0xce, 0x9a, 0x8b, 0x58,
+ 0xcc, 0x47, 0x43, 0xdf, 0x77, 0xbb, 0xd3, 0x20,
+ 0xae, 0xe4, 0x2e, 0x63, 0x67, 0xdc, 0xf7, 0x5f,
+ 0x3f, 0x83, 0x27, 0xb7, 0x14, 0x52, 0x56, 0xbf,
+ 0xc3, 0x65, 0x06, 0xe1, 0x03, 0xcc, 0x93, 0x57,
+ 0x09, 0x7b, 0x6f, 0xe8, 0x81, 0x4a, 0x2c, 0xb7,
+ 0x43, 0xa9, 0x20, 0x1d, 0xf6, 0x56, 0x8b, 0xcc,
+ 0xe5, 0x4c, 0xd5, 0x4f, 0x74, 0x67, 0x29, 0x51
+ };
+
+ static uint8_t rsa_coefficient[FIPS_RSA_COEFFICIENT_LENGTH] = {
+ 0x23, 0xab, 0xf4, 0x03, 0x2f, 0x29, 0x95, 0x74,
+ 0xac, 0x1a, 0x33, 0x96, 0x62, 0xed, 0xf7, 0xf6,
+ 0xae, 0x07, 0x2a, 0x2e, 0xe8, 0xab, 0xfb, 0x1e,
+ 0xb9, 0xb2, 0x88, 0x1e, 0x85, 0x05, 0x42, 0x64,
+ 0x03, 0xb2, 0x8b, 0xc1, 0x81, 0x75, 0xd7, 0xba,
+ 0xaa, 0xd4, 0x31, 0x3c, 0x8a, 0x96, 0x23, 0x9d,
+ 0x3f, 0x06, 0x3e, 0x44, 0xa9, 0x62, 0x2f, 0x61,
+ 0x5a, 0x51, 0x82, 0x2c, 0x04, 0x85, 0x73, 0xd1
+ };
+
+ /* RSA Known Plaintext Message (1024-bits). */
+ static uint8_t rsa_known_plaintext_msg[FIPS_RSA_MESSAGE_LENGTH] = {
+ "Known plaintext message utilized"
+ "for RSA Encryption & Decryption"
+ "block, SHA1, SHA256, SHA384 and"
+ "SHA512 RSA Signature KAT tests."
+ };
+
+ /* RSA Known Ciphertext (1024-bits). */
+ static uint8_t rsa_known_ciphertext[] = {
+ 0x1e, 0x7e, 0x12, 0xbb, 0x15, 0x62, 0xd0, 0x23,
+ 0x53, 0x4c, 0x51, 0x97, 0x77, 0x06, 0xa0, 0xbb,
+ 0x26, 0x99, 0x9a, 0x8f, 0x39, 0xad, 0x88, 0x5c,
+ 0xc4, 0xce, 0x33, 0x40, 0x94, 0x92, 0xb4, 0x0e,
+ 0xab, 0x71, 0xa9, 0x5d, 0x9a, 0x37, 0xe3, 0x9a,
+ 0x24, 0x95, 0x13, 0xea, 0x0f, 0xbb, 0xf7, 0xff,
+ 0xdf, 0x31, 0x33, 0x23, 0x1d, 0xce, 0x26, 0x9e,
+ 0xd1, 0xde, 0x98, 0x40, 0xde, 0x57, 0x86, 0x12,
+ 0xf1, 0xe6, 0x5a, 0x3f, 0x08, 0x02, 0x81, 0x85,
+ 0xe0, 0xd9, 0xad, 0x3c, 0x8c, 0x71, 0xf8, 0xcf,
+ 0x0a, 0x98, 0xc5, 0x08, 0xdc, 0xc4, 0xca, 0x8c,
+ 0x23, 0x1b, 0x4d, 0x9b, 0xb5, 0x13, 0x44, 0xe1,
+ 0x5f, 0xf9, 0x30, 0x80, 0x25, 0xe0, 0x1e, 0x94,
+ 0xa3, 0x0c, 0xdc, 0x82, 0x2e, 0xfb, 0x30, 0xbe,
+ 0x89, 0xba, 0x76, 0xb6, 0x23, 0xf7, 0xda, 0x7c,
+ 0xca, 0xe6, 0x02, 0xbd, 0x92, 0xce, 0x64, 0xfc
+ };
+
+ /* RSA Known Signed Hash (1024-bits). */
+ static uint8_t rsa_known_sha1_signature[] = {
+ 0xd2, 0xa4, 0xe0, 0x2b, 0xc7, 0x03, 0x7f, 0xc6,
+ 0x06, 0x9e, 0xa2, 0x82, 0x19, 0xe9, 0x2b, 0xaf,
+ 0xe3, 0x48, 0x88, 0xc1, 0xf3, 0xb5, 0x0d, 0xe4,
+ 0x52, 0x9e, 0xad, 0xd5, 0x58, 0xb5, 0x9f, 0xe8,
+ 0x40, 0xe9, 0xb7, 0x2e, 0xc6, 0x71, 0x58, 0x56,
+ 0x04, 0xac, 0xb0, 0xf3, 0x3a, 0x42, 0x38, 0x08,
+ 0xc4, 0x43, 0x39, 0xba, 0x19, 0xce, 0xb1, 0x99,
+ 0xf1, 0x8d, 0x89, 0xd8, 0x50, 0x07, 0x14, 0x3d,
+ 0xcf, 0xd0, 0xb6, 0x79, 0xde, 0x9c, 0x89, 0x32,
+ 0xb0, 0x73, 0x3f, 0xed, 0x03, 0x0b, 0xdf, 0x6d,
+ 0x7e, 0xc9, 0x1c, 0x39, 0xe8, 0x2b, 0x16, 0x09,
+ 0xbb, 0x5f, 0x99, 0x2f, 0xeb, 0xf3, 0x37, 0x73,
+ 0x0d, 0x0e, 0xcc, 0x95, 0xad, 0x90, 0x80, 0x03,
+ 0x1d, 0x80, 0x55, 0x37, 0xa1, 0x2a, 0x71, 0x76,
+ 0x23, 0x87, 0x8c, 0x9b, 0x41, 0x07, 0xc6, 0x3d,
+ 0xc6, 0xa3, 0x7d, 0x1b, 0xff, 0x4e, 0x11, 0x19
+ };
+
+ /* RSA Known Signed Hash (1024-bits). */
+ static uint8_t rsa_known_sha256_signature[] = {
+ 0x27, 0x35, 0xdd, 0xc4, 0xf8, 0xe2, 0x0b, 0xa3,
+ 0xef, 0x63, 0x57, 0x3b, 0xe1, 0x58, 0x9a, 0xbc,
+ 0x20, 0x9c, 0x25, 0x12, 0x01, 0xbf, 0xbb, 0x29,
+ 0x80, 0x1a, 0xb1, 0x37, 0x9c, 0xcd, 0x67, 0xc7,
+ 0x0d, 0xf8, 0x64, 0x10, 0x9f, 0xe2, 0xa1, 0x9b,
+ 0x21, 0x90, 0xcc, 0xda, 0x8b, 0x76, 0x5e, 0x79,
+ 0x00, 0x9d, 0x58, 0x8b, 0x8a, 0xb3, 0xc3, 0xb5,
+ 0xf1, 0x54, 0xc5, 0x8c, 0x72, 0xba, 0xde, 0x51,
+ 0x3c, 0x6b, 0x94, 0xd6, 0xf3, 0x1b, 0xa2, 0x53,
+ 0xe6, 0x1a, 0x46, 0x1d, 0x7f, 0x14, 0x86, 0xcc,
+ 0xa6, 0x30, 0x92, 0x96, 0xc0, 0x96, 0x24, 0xf0,
+ 0x42, 0x53, 0x4c, 0xdd, 0x27, 0xdf, 0x1d, 0x2e,
+ 0x8b, 0x83, 0xbe, 0xed, 0x85, 0x1d, 0x50, 0x46,
+ 0xa3, 0x7d, 0x20, 0xea, 0x3e, 0x91, 0xfb, 0xf6,
+ 0x86, 0x51, 0xfd, 0x8c, 0xe5, 0x31, 0xe6, 0x7e,
+ 0x60, 0x08, 0x0e, 0xec, 0xa6, 0xea, 0x24, 0x8d
+ };
+
+ /* RSA Known Signed Hash (1024-bits). */
+ static uint8_t rsa_known_sha384_signature[] = {
+ 0x0b, 0x03, 0x94, 0x4f, 0x94, 0x78, 0x9b, 0x96,
+ 0x76, 0xeb, 0x72, 0x58, 0xe1, 0xc5, 0xc7, 0x5f,
+ 0x85, 0x01, 0xa8, 0xc4, 0xf6, 0x1a, 0xb5, 0x2c,
+ 0xd1, 0xd8, 0x87, 0xde, 0x3a, 0x9c, 0x9f, 0x57,
+ 0x81, 0x2a, 0x1e, 0x23, 0x07, 0x70, 0xb0, 0xf9,
+ 0x28, 0x3d, 0xfa, 0xe5, 0x2e, 0x1b, 0x9a, 0x72,
+ 0xc3, 0x74, 0xb3, 0x42, 0x1c, 0x9a, 0x13, 0xdc,
+ 0xc9, 0xd6, 0xd5, 0x88, 0xc9, 0x9c, 0x46, 0xf1,
+ 0x0c, 0xa6, 0xf7, 0xd8, 0x06, 0xa3, 0x1b, 0xdf,
+ 0x55, 0xb3, 0x1b, 0x7b, 0x58, 0x1d, 0xff, 0x19,
+ 0xc7, 0xe0, 0xdd, 0x59, 0xac, 0x2f, 0x78, 0x71,
+ 0xe7, 0xe0, 0x17, 0xa3, 0x1c, 0x5c, 0x92, 0xef,
+ 0xb6, 0x75, 0xed, 0xbe, 0x18, 0x39, 0x6b, 0xd7,
+ 0xc9, 0x08, 0x62, 0x55, 0x62, 0xac, 0x5d, 0xa1,
+ 0x9b, 0xd5, 0xb8, 0x98, 0x15, 0xc0, 0xf5, 0x41,
+ 0x85, 0x44, 0x96, 0xca, 0x10, 0xdc, 0x57, 0x21
+ };
+
+ /* RSA Known Signed Hash (1024-bits). */
+ static uint8_t rsa_known_sha512_signature[] = {
+ 0xa5, 0xd0, 0x80, 0x04, 0x22, 0xfc, 0x80, 0x73,
+ 0x7d, 0x46, 0xc8, 0x7b, 0xac, 0x44, 0x7b, 0xe6,
+ 0x07, 0xe5, 0x61, 0x4c, 0x33, 0x7f, 0x6f, 0x46,
+ 0x7c, 0x30, 0xe3, 0x75, 0x59, 0x4b, 0x42, 0xf3,
+ 0x9f, 0x35, 0x3c, 0x10, 0x56, 0xdb, 0xd2, 0x69,
+ 0x43, 0xcb, 0x77, 0xe9, 0x7d, 0xcd, 0x07, 0x43,
+ 0xc5, 0xd4, 0x0c, 0x9d, 0xf5, 0x92, 0xbd, 0x0e,
+ 0x3b, 0xb7, 0x68, 0x88, 0x84, 0xca, 0xae, 0x0d,
+ 0xab, 0x71, 0x10, 0xad, 0xab, 0x27, 0xe4, 0xa3,
+ 0x24, 0x41, 0xeb, 0x1c, 0xa6, 0x5f, 0xf1, 0x85,
+ 0xd0, 0xf6, 0x22, 0x74, 0x3d, 0x81, 0xbe, 0xdd,
+ 0x1b, 0x2a, 0x4c, 0xd1, 0x6c, 0xb5, 0x6d, 0x7a,
+ 0xbb, 0x99, 0x69, 0x01, 0xa6, 0xc0, 0x98, 0xfa,
+ 0x97, 0xa3, 0xd1, 0xb0, 0xdf, 0x09, 0xe3, 0x3d,
+ 0x88, 0xee, 0x90, 0xf3, 0x10, 0x41, 0x0f, 0x06,
+ 0x31, 0xe9, 0x60, 0x2d, 0xbf, 0x63, 0x7b, 0xf8
+ };
+
+ RSAPrivateKey_t rsa_private_key;
+ CK_RV rv;
+ uint8_t rsa_computed_ciphertext[FIPS_RSA_ENCRYPT_LENGTH];
+ uint8_t rsa_computed_plaintext[FIPS_RSA_DECRYPT_LENGTH];
+ uint8_t rsa_computed_signature[FIPS_RSA_SIGNATURE_LENGTH];
+ CK_BYTE der_data[SHA512_DIGEST_LENGTH + SHA2_DER_PREFIX_Len];
+
+ /*
+ * RSA Known Answer Encryption Test.
+ */
+
+ /* Perform RSA Public Key Encryption. */
+ rv = fips_rsa_encrypt(rsa_modulus, FIPS_RSA_MODULUS_LENGTH,
+ rsa_public_exponent, FIPS_RSA_PUBLIC_EXPONENT_LENGTH,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_ciphertext);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_ciphertext, rsa_known_ciphertext,
+ FIPS_RSA_ENCRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * RSA Known Answer Decryption Test.
+ */
+ rsa_private_key.version = rsa_version;
+ rsa_private_key.version_len = FIPS_RSA_PRIVATE_VERSION_LENGTH;
+ rsa_private_key.modulus = rsa_modulus;
+ rsa_private_key.modulus_len = FIPS_RSA_MODULUS_LENGTH;
+ rsa_private_key.public_expo = rsa_public_exponent;
+ rsa_private_key.public_expo_len = FIPS_RSA_PUBLIC_EXPONENT_LENGTH;
+ rsa_private_key.private_expo = rsa_private_exponent;
+ rsa_private_key.private_expo_len = FIPS_RSA_PRIVATE_EXPONENT_LENGTH;
+ rsa_private_key.prime1 = rsa_prime0;
+ rsa_private_key.prime1_len = FIPS_RSA_PRIME0_LENGTH;
+ rsa_private_key.prime2 = rsa_prime1;
+ rsa_private_key.prime2_len = FIPS_RSA_PRIME1_LENGTH;
+ rsa_private_key.exponent1 = rsa_exponent0;
+ rsa_private_key.exponent1_len = FIPS_RSA_EXPONENT0_LENGTH;
+ rsa_private_key.exponent2 = rsa_exponent1;
+ rsa_private_key.exponent2_len = FIPS_RSA_EXPONENT1_LENGTH;
+ rsa_private_key.coef = rsa_coefficient;
+ rsa_private_key.coef_len = FIPS_RSA_COEFFICIENT_LENGTH;
+
+ /* Perform RSA Private Key Decryption. */
+ rv = fips_rsa_decrypt(&rsa_private_key, rsa_known_ciphertext,
+ FIPS_RSA_MESSAGE_LENGTH, rsa_computed_plaintext);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_plaintext, rsa_known_plaintext_msg,
+ FIPS_RSA_DECRYPT_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /* SHA-1 Sign/Verify */
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA1_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA_1, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#endif
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_signature, rsa_known_sha1_signature,
+ FIPS_RSA_SIGNATURE_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA1_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA_1, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#endif
+
+ if (rv != CKR_OK)
+ goto rsa_loser;
+
+ /* SHA256 Sign/Verify */
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA256_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA256, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#endif
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_signature, rsa_known_sha256_signature,
+ FIPS_RSA_SIGNATURE_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA256_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA256, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#endif
+
+ if (rv != CKR_OK)
+ goto rsa_loser;
+
+ /* SHA384 Sign/Verify */
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA384_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA384, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#endif
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_signature, rsa_known_sha384_signature,
+ FIPS_RSA_SIGNATURE_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA384_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA384, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#endif
+
+ if (rv != CKR_OK)
+ goto rsa_loser;
+
+ /* SHA512 Sign/Verify */
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA512_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA512, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 1);
+#endif
+
+ if ((rv != CKR_OK) ||
+ (memcmp(rsa_computed_signature, rsa_known_sha512_signature,
+ FIPS_RSA_SIGNATURE_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#ifdef _KERNEL
+ rv = fips_rsa_sign_verify_test(SHA512_TYPE, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#else
+ rv = fips_rsa_sign_verify_test(CKM_SHA512, &rsa_private_key,
+ rsa_known_plaintext_msg, FIPS_RSA_MESSAGE_LENGTH,
+ rsa_computed_signature, der_data, 0);
+#endif
+
+rsa_loser:
+ if (rv != CKR_OK)
+ return (CKR_DEVICE_ERROR);
+ else
+ return (CKR_OK);
+
+}
diff --git a/usr/src/common/crypto/fips/fips_sha1_util.c b/usr/src/common/crypto/fips/fips_sha1_util.c
new file mode 100644
index 0000000000..08d218dec5
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_sha1_util.c
@@ -0,0 +1,369 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sha1.h>
+#include <sys/crypto/common.h>
+#include <sys/cmn_err.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softMAC.h"
+#endif
+#include <sha1/sha1_impl.h>
+
+/*
+ * fips_sha1_build_context()
+ *
+ * Description:
+ * This function allocates and initializes SHA1 context
+ * context.
+ */
+SHA1_CTX *
+fips_sha1_build_context(void)
+{
+ SHA1_CTX *sha1_context;
+
+
+#ifndef _KERNEL
+ if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL)
+#else
+ if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
+ KM_SLEEP)) == NULL)
+#endif
+ return (NULL);
+
+ SHA1Init(sha1_context);
+
+ return (sha1_context);
+
+}
+
+/*
+ * fips_sha1_hash()
+ *
+ * Arguments:
+ * sha1_context: pointer to SHA1 context
+ * in: pointer to the input data to be hashed
+ * inlen: length of the input data
+ * out: pointer to the output data after hashing
+ *
+ * Description:
+ * This function calls the low-level SHA1 routines for hashing.
+ *
+ */
+int
+fips_sha1_hash(SHA1_CTX *sha1_context, uchar_t *in, ulong_t inlen, uchar_t *out)
+{
+
+ if (in != NULL) {
+#ifdef __sparcv9
+ SHA1Update((SHA1_CTX *)sha1_context, in, (uint_t)inlen);
+#else /* !__sparcv9 */
+ SHA1Update((SHA1_CTX *)sha1_context, in, inlen);
+#endif /* __sparcv9 */
+ SHA1Final(out, (SHA1_CTX *)sha1_context);
+ return (CKR_OK);
+ } else
+ return (CKR_ARGUMENTS_BAD);
+
+}
+
+
+#ifndef _KERNEL
+soft_hmac_ctx_t *
+fips_sha1_hmac_build_context(uint8_t *secret_key,
+ unsigned int secret_key_length)
+{
+
+ soft_hmac_ctx_t *hmac_ctx;
+ uint32_t sha1_ipad[SHA1_HMAC_INTS_PER_BLOCK];
+ uint32_t sha1_opad[SHA1_HMAC_INTS_PER_BLOCK];
+
+ hmac_ctx = malloc(sizeof (soft_hmac_ctx_t));
+
+ if (hmac_ctx == NULL) {
+ return (NULL);
+ }
+
+ hmac_ctx->hmac_len = SHA1_HASH_SIZE;
+ bzero(sha1_ipad, SHA1_HMAC_BLOCK_SIZE);
+ bzero(sha1_opad, SHA1_HMAC_BLOCK_SIZE);
+
+ (void) memcpy(sha1_ipad, secret_key, secret_key_length);
+ (void) memcpy(sha1_opad, secret_key, secret_key_length);
+
+ sha1_hmac_ctx_init(&hmac_ctx->hc_ctx_u.sha1_ctx, sha1_ipad,
+ sha1_opad);
+
+ return (hmac_ctx);
+
+}
+
+CK_RV
+fips_hmac_sha1_hash(unsigned char *hmac_computed,
+ uint8_t *secret_key,
+ unsigned int secret_key_length,
+ uint8_t *message,
+ unsigned int message_length)
+{
+
+ soft_hmac_ctx_t *hmac_ctx = NULL;
+
+ hmac_ctx = fips_sha1_hmac_build_context(secret_key,
+ secret_key_length);
+
+ if (hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ if (message != NULL) {
+ SOFT_MAC_UPDATE(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx),
+ message, message_length);
+ }
+
+ SOFT_MAC_FINAL(SHA1, &(hmac_ctx->hc_ctx_u.sha1_ctx), hmac_computed);
+
+ free(hmac_ctx);
+ return (CKR_OK);
+}
+
+#else /* _KERNEL */
+
+/*
+ * Initialize a SHA1-HMAC context.
+ */
+void
+sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
+{
+ uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK];
+ uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK];
+ uint_t i;
+
+ bzero(ipad, SHA1_HMAC_BLOCK_SIZE);
+ bzero(opad, SHA1_HMAC_BLOCK_SIZE);
+
+ bcopy(keyval, ipad, length_in_bytes);
+ bcopy(keyval, opad, length_in_bytes);
+
+ /* XOR key with ipad (0x36) and opad (0x5c) */
+ for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) {
+ ipad[i] ^= 0x36363636;
+ opad[i] ^= 0x5c5c5c5c;
+ }
+
+ /* perform SHA1 on ipad */
+ SHA1Init(&ctx->hc_icontext);
+ SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE);
+
+ /* perform SHA1 on opad */
+ SHA1Init(&ctx->hc_ocontext);
+ SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE);
+}
+
+sha1_hmac_ctx_t *
+fips_sha1_hmac_build_context(uint8_t *secret_key,
+ unsigned int secret_key_length)
+{
+ sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl;
+
+
+ /*
+ * Allocate and initialize SHA1 context.
+ */
+ sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t),
+ KM_SLEEP);
+ if (sha1_hmac_ctx_tmpl == NULL)
+ return (NULL);
+
+ /*
+ * initialize ctx->hc_icontext and ctx->hc_ocontext
+ */
+ sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, secret_key,
+ secret_key_length);
+
+
+ sha1_hmac_ctx_tmpl->hc_mech_type = SHA1_HMAC_MECH_INFO_TYPE;
+
+
+ return (sha1_hmac_ctx_tmpl);
+}
+
+void
+fips_hmac_sha1_hash(sha1_hmac_ctx_t *sha1_hmac_ctx,
+ uint8_t *message, uint32_t message_len,
+ uint8_t *hmac_computed)
+{
+
+ /* do a SHA1 update of the inner context using the specified data */
+ SHA1Update(&((sha1_hmac_ctx)->hc_icontext), message,
+ message_len);
+
+ /*
+ * Do a SHA1 final on the inner context.
+ */
+ SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_icontext));
+
+ /*
+ * Do an SHA1 update on the outer context, feeding the inner
+ * digest as data.
+ */
+ SHA1Update(&((sha1_hmac_ctx)->hc_ocontext), hmac_computed,
+ SHA1_HASH_SIZE);
+
+ /*
+ * Do a SHA1 final on the outer context, storing the computed
+ * digest in the caller's buffer.
+ */
+ SHA1Final(hmac_computed, &((sha1_hmac_ctx)->hc_ocontext));
+
+}
+
+#endif
+
+/*
+ * SHA1 Power-On SelfTest(s).
+ */
+int
+fips_sha1_post(void)
+{
+
+ /*
+ * SHA-1 Known Hash Message
+ * Source from NIST SHA1ShortMsg (L = 512-bits).
+ */
+ static uint8_t sha1_known_hash_message[] = {
+ 0x7e, 0x3a, 0x4c, 0x32, 0x5c, 0xb9, 0xc5, 0x2b,
+ 0x88, 0x38, 0x7f, 0x93, 0xd0, 0x1a, 0xe8, 0x6d,
+ 0x42, 0x09, 0x8f, 0x5e, 0xfa, 0x7f, 0x94, 0x57,
+ 0x38, 0x8b, 0x5e, 0x74, 0xb6, 0xd2, 0x8b, 0x24,
+ 0x38, 0xd4, 0x2d, 0x8b, 0x64, 0x70, 0x33, 0x24,
+ 0xd4, 0xaa, 0x25, 0xab, 0x6a, 0xad, 0x15, 0x3a,
+ 0xe3, 0x0c, 0xd2, 0xb2, 0xaf, 0x4d, 0x5e, 0x5c,
+ 0x00, 0xa8, 0xa2, 0xd0, 0x22, 0x0c, 0x61, 0x16
+ };
+
+ /* SHA-1 Known Digest Message (160-bits). */
+ static uint8_t sha1_known_digest[] = {
+ 0xa3, 0x05, 0x44, 0x27, 0xcd, 0xb1, 0x3f, 0x16,
+ 0x4a, 0x61, 0x0b, 0x34, 0x87, 0x02, 0x72, 0x4c,
+ 0x80, 0x8a, 0x0d, 0xcc
+ };
+
+ /* Source from NIST HMAC.txt Count = 0 */
+ static uint8_t HMAC_known_secret_key[] = {
+ 0x7b, 0x10, 0xf4, 0x12, 0x4b, 0x15, 0xc8, 0x2e
+ };
+
+ static uint8_t HMAC_known_secret_key_length
+ = sizeof (HMAC_known_secret_key);
+
+ /* known SHA1 hmac - truncated (10 bytes) */
+ static uint8_t known_SHA1_hmac[] = {
+ 0x4e, 0xad, 0x12, 0xc2, 0xfe, 0x3d, 0x6e, 0xa4,
+ 0x3a, 0xcb
+ };
+
+ static uint8_t hmac_sha1_known_hash_message[] = {
+ 0x27, 0xdc, 0xb5, 0xb1, 0xda, 0xf6, 0x0c, 0xfd,
+ 0x3e, 0x2f, 0x73, 0xd4, 0xd6, 0x4c, 0xa9, 0xc6,
+ 0x84, 0xf8, 0xbf, 0x71, 0xfc, 0x68, 0x2a, 0x46,
+ 0x79, 0x3b, 0x17, 0x90, 0xaf, 0xa4, 0xfe, 0xb1,
+ 0x00, 0xca, 0x7a, 0xaf, 0xf2, 0x6f, 0x58, 0xf0,
+ 0xe1, 0xd0, 0xed, 0x42, 0xf1, 0xcd, 0xad, 0x1f,
+ 0x47, 0x4a, 0xfa, 0x2e, 0x79, 0xd5, 0x3a, 0x0c,
+ 0x42, 0x89, 0x2c, 0x4d, 0x7b, 0x32, 0x7c, 0xbe,
+ 0x46, 0xb2, 0x95, 0xed, 0x8d, 0xa3, 0xb6, 0xec,
+ 0xab, 0x3d, 0x48, 0x51, 0x68, 0x7a, 0x6f, 0x81,
+ 0x2b, 0x79, 0xdf, 0x2f, 0x6b, 0x20, 0xf1, 0x1f,
+ 0x67, 0x06, 0xf5, 0x30, 0x17, 0x90, 0xca, 0x99,
+ 0x62, 0x5a, 0xad, 0x73, 0x91, 0xd8, 0x4f, 0x78,
+ 0x04, 0x3d, 0x2a, 0x0a, 0x23, 0x9b, 0x14, 0x77,
+ 0x98, 0x4c, 0x15, 0x7b, 0xbc, 0x92, 0x76, 0x06,
+ 0x4e, 0x7a, 0x1a, 0x40, 0x6b, 0x06, 0x12, 0xca
+ };
+
+ /* SHA-1 variables. */
+ uint8_t sha1_computed_digest[SHA1_DIGEST_LENGTH];
+ uint8_t hmac_computed[SHA1_HMAC_BLOCK_SIZE];
+ SHA1_CTX *sha1_context = NULL;
+
+#ifdef _KERNEL
+ sha1_hmac_ctx_t *sha1_hmac_ctx = NULL;
+#endif
+
+ int rv;
+
+ /* SHA-1 Known Answer Hashing Test. */
+ sha1_context = fips_sha1_build_context();
+ if (sha1_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha1_hash(sha1_context, sha1_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH, sha1_computed_digest);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(sha1_computed_digest, sha1_known_digest,
+ SHA1_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#ifdef _KERNEL
+ /* SHA-1 HMAC Known Answer Hashing Test */
+ sha1_hmac_ctx = fips_sha1_hmac_build_context(HMAC_known_secret_key,
+ HMAC_known_secret_key_length);
+
+ if (sha1_hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ fips_hmac_sha1_hash(sha1_hmac_ctx, hmac_sha1_known_hash_message,
+ sizeof (hmac_sha1_known_hash_message), hmac_computed);
+#else
+ rv = fips_hmac_sha1_hash(hmac_computed, HMAC_known_secret_key,
+ HMAC_known_secret_key_length, hmac_sha1_known_hash_message,
+ sizeof (hmac_sha1_known_hash_message));
+
+#endif
+
+#ifdef _KERNEL
+ if (memcmp(hmac_computed, known_SHA1_hmac,
+ sizeof (known_SHA1_hmac)) != 0)
+ return (CKR_DEVICE_ERROR);
+#else
+ if ((rv != CKR_OK) ||
+ (memcmp(hmac_computed, known_SHA1_hmac,
+ sizeof (known_SHA1_hmac)) != 0))
+ return (CKR_DEVICE_ERROR);
+#endif
+
+ return (rv);
+
+}
diff --git a/usr/src/common/crypto/fips/fips_sha2_util.c b/usr/src/common/crypto/fips/fips_sha2_util.c
new file mode 100644
index 0000000000..3a76577718
--- /dev/null
+++ b/usr/src/common/crypto/fips/fips_sha2_util.c
@@ -0,0 +1,779 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#define _SHA2_IMPL
+#include <sys/sha2.h>
+#include <sys/crypto/common.h>
+#include <sys/cmn_err.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softMAC.h"
+#endif
+#include <sha2/sha2_impl.h>
+
+
+/*
+ * fips_sha2_build_context()
+ *
+ * Description:
+ * This function allocates and initializes SHA2 context.
+ */
+#ifndef _KERNEL
+SHA2_CTX *
+fips_sha2_build_context(CK_MECHANISM_TYPE mechanism)
+{
+ SHA2_CTX *sha2_context;
+
+ if ((sha2_context = malloc(sizeof (SHA2_CTX))) == NULL)
+ return (NULL);
+
+ switch (mechanism) {
+ case CKM_SHA256:
+ SHA2Init(SHA256, sha2_context);
+ break;
+
+ case CKM_SHA384:
+ SHA2Init(SHA384, sha2_context);
+ break;
+
+ case CKM_SHA512:
+ SHA2Init(SHA512, sha2_context);
+ break;
+ }
+
+ return (sha2_context);
+}
+
+#else
+SHA2_CTX *
+fips_sha2_build_context(sha2_mech_t mechanism)
+{
+ SHA2_CTX *sha2_context;
+
+ if ((sha2_context = kmem_zalloc(sizeof (SHA2_CTX),
+ KM_SLEEP)) == NULL)
+ return (NULL);
+
+ switch (mechanism) {
+ case SHA256_TYPE:
+ SHA2Init(SHA256, sha2_context);
+ break;
+
+ case SHA384_TYPE:
+ SHA2Init(SHA384, sha2_context);
+ break;
+
+ case SHA512_TYPE:
+ SHA2Init(SHA512, sha2_context);
+ break;
+ }
+
+ return (sha2_context);
+}
+#endif
+
+/*
+ * fips_sha2_hash()
+ *
+ * Arguments:
+ * sha2_context: pointer to SHA2 context
+ * in: pointer to the input data to be hashed
+ * inlen: length of the input data
+ * out: pointer to the output data after hashing
+ *
+ * Description:
+ * This function calls the low-level SHA2 routines for hashing.
+ *
+ */
+int
+fips_sha2_hash(SHA2_CTX *sha2_context, uchar_t *in,
+ ulong_t inlen, uchar_t *out)
+{
+
+ if (in != NULL) {
+ SHA2Update((SHA2_CTX *)sha2_context, in, inlen);
+ SHA2Final(out, (SHA2_CTX *)sha2_context);
+ return (CKR_OK);
+ } else {
+ return (CKR_ARGUMENTS_BAD);
+ }
+}
+
+#ifndef _KERNEL
+soft_hmac_ctx_t *
+fips_sha2_hmac_build_context(CK_MECHANISM_TYPE mechanism,
+ uint8_t *secret_key,
+ unsigned int secret_key_length)
+{
+
+ soft_hmac_ctx_t *hmac_ctx;
+
+ hmac_ctx = malloc(sizeof (soft_hmac_ctx_t));
+
+ if (hmac_ctx == NULL) {
+ return (NULL);
+ }
+
+ switch (mechanism) {
+ case CKM_SHA256_HMAC:
+ {
+ uint64_t sha_ipad[SHA256_HMAC_INTS_PER_BLOCK];
+ uint64_t sha_opad[SHA256_HMAC_INTS_PER_BLOCK];
+
+ hmac_ctx->hmac_len = SHA256_DIGEST_LENGTH;
+ bzero(sha_ipad, SHA256_HMAC_BLOCK_SIZE);
+ bzero(sha_opad, SHA256_HMAC_BLOCK_SIZE);
+
+ (void) memcpy(sha_ipad, secret_key, secret_key_length);
+ (void) memcpy(sha_opad, secret_key, secret_key_length);
+
+ sha2_hmac_ctx_init(CKM_TO_SHA2(mechanism),
+ &hmac_ctx->hc_ctx_u.sha2_ctx,
+ sha_ipad, sha_opad,
+ SHA256_HMAC_INTS_PER_BLOCK,
+ SHA256_HMAC_BLOCK_SIZE);
+
+ break;
+ }
+
+ case CKM_SHA384_HMAC:
+ {
+ uint64_t sha_ipad[SHA512_HMAC_INTS_PER_BLOCK];
+ uint64_t sha_opad[SHA512_HMAC_INTS_PER_BLOCK];
+
+ hmac_ctx->hmac_len = SHA384_DIGEST_LENGTH;
+ bzero(sha_ipad, SHA512_HMAC_BLOCK_SIZE);
+ bzero(sha_opad, SHA512_HMAC_BLOCK_SIZE);
+
+ (void) memcpy(sha_ipad, secret_key, secret_key_length);
+ (void) memcpy(sha_opad, secret_key, secret_key_length);
+
+ sha2_hmac_ctx_init(CKM_TO_SHA2(mechanism),
+ &hmac_ctx->hc_ctx_u.sha2_ctx,
+ sha_ipad, sha_opad,
+ SHA512_HMAC_INTS_PER_BLOCK,
+ SHA512_HMAC_BLOCK_SIZE);
+ break;
+ }
+
+ case CKM_SHA512_HMAC:
+ {
+ uint64_t sha_ipad[SHA512_HMAC_INTS_PER_BLOCK];
+ uint64_t sha_opad[SHA512_HMAC_INTS_PER_BLOCK];
+
+ hmac_ctx->hmac_len = SHA512_DIGEST_LENGTH;
+ bzero(sha_ipad, SHA512_HMAC_BLOCK_SIZE);
+ bzero(sha_opad, SHA512_HMAC_BLOCK_SIZE);
+
+ (void) memcpy(sha_ipad, secret_key, secret_key_length);
+ (void) memcpy(sha_opad, secret_key, secret_key_length);
+
+ sha2_hmac_ctx_init(CKM_TO_SHA2(mechanism),
+ &hmac_ctx->hc_ctx_u.sha2_ctx,
+ sha_ipad, sha_opad,
+ SHA512_HMAC_INTS_PER_BLOCK,
+ SHA512_HMAC_BLOCK_SIZE);
+
+ break;
+ }
+ }
+
+ return (hmac_ctx);
+}
+
+CK_RV
+fips_hmac_sha2_hash(unsigned char *hmac_computed,
+ uint8_t *secret_key,
+ unsigned int secret_key_length,
+ uint8_t *message,
+ unsigned int message_length,
+ CK_MECHANISM_TYPE mechanism)
+{
+
+ soft_hmac_ctx_t *hmac_ctx = NULL;
+
+ hmac_ctx = fips_sha2_hmac_build_context(mechanism,
+ secret_key, secret_key_length);
+
+ if (hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ switch (mechanism) {
+ case CKM_SHA256_HMAC:
+ if (message != NULL)
+ SHA2Update(&(hmac_ctx->hc_ctx_u.sha2_ctx.hc_icontext),
+ message, message_length);
+
+ SOFT_MAC_FINAL_2(SHA256, &(hmac_ctx->hc_ctx_u.sha2_ctx),
+ hmac_computed);
+ break;
+
+ case CKM_SHA384_HMAC:
+ if (message != NULL)
+ SHA2Update(&(hmac_ctx->hc_ctx_u.sha2_ctx.hc_icontext),
+ message, message_length);
+
+ SOFT_MAC_FINAL_2(SHA384, &(hmac_ctx->hc_ctx_u.sha2_ctx),
+ hmac_computed);
+ break;
+
+ case CKM_SHA512_HMAC:
+ if (message != NULL)
+ SHA2Update(&(hmac_ctx->hc_ctx_u.sha2_ctx.hc_icontext),
+ message, message_length);
+
+ SOFT_MAC_FINAL_2(SHA512, &(hmac_ctx->hc_ctx_u.sha2_ctx),
+ hmac_computed);
+ break;
+ }
+
+ free(hmac_ctx);
+ return (CKR_OK);
+}
+
+#else
+
+/*
+ * Initialize a SHA2-HMAC context.
+ */
+void
+sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
+{
+ uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
+ uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
+ int i, block_size, blocks_per_int64;
+
+ /* Determine the block size */
+ if (ctx->hc_mech_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
+ block_size = SHA256_HMAC_BLOCK_SIZE;
+ blocks_per_int64 = SHA256_HMAC_BLOCK_SIZE / sizeof (uint64_t);
+ } else {
+ block_size = SHA512_HMAC_BLOCK_SIZE;
+ blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t);
+ }
+
+ (void) bzero(ipad, block_size);
+ (void) bzero(opad, block_size);
+ (void) bcopy(keyval, ipad, length_in_bytes);
+ (void) bcopy(keyval, opad, length_in_bytes);
+
+ /* XOR key with ipad (0x36) and opad (0x5c) */
+ for (i = 0; i < blocks_per_int64; i ++) {
+ ipad[i] ^= 0x3636363636363636;
+ opad[i] ^= 0x5c5c5c5c5c5c5c5c;
+ }
+
+ /* perform SHA2 on ipad */
+ SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext);
+ SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size);
+
+ /* perform SHA2 on opad */
+ SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext);
+ SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size);
+
+}
+
+sha2_hmac_ctx_t *
+fips_sha2_hmac_build_context(sha2_mech_t mechanism,
+ uint8_t *secret_key,
+ unsigned int secret_key_length)
+{
+ sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl;
+
+ /*
+ * Allocate and initialize SHA2 context.
+ */
+ sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t),
+ KM_SLEEP);
+ if (sha2_hmac_ctx_tmpl == NULL)
+ return (NULL);
+
+ switch (mechanism) {
+ case SHA256_TYPE:
+ sha2_hmac_ctx_tmpl->hc_mech_type =
+ SHA256_HMAC_MECH_INFO_TYPE;
+ break;
+
+ case SHA384_TYPE:
+ sha2_hmac_ctx_tmpl->hc_mech_type =
+ SHA384_HMAC_MECH_INFO_TYPE;
+ break;
+
+ case SHA512_TYPE:
+ sha2_hmac_ctx_tmpl->hc_mech_type =
+ SHA512_HMAC_MECH_INFO_TYPE;
+ break;
+ }
+
+ /*
+ * initialize ctx->hc_icontext and ctx->hc_ocontext
+ */
+ sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, secret_key,
+ secret_key_length);
+
+ return (sha2_hmac_ctx_tmpl);
+}
+
+void
+fips_hmac_sha2_hash(sha2_hmac_ctx_t *sha2_hmac_ctx,
+ uint8_t *message,
+ uint32_t message_len,
+ uint8_t *hmac_computed,
+ sha2_mech_t mechanism)
+
+{
+
+ SHA2Update(&((sha2_hmac_ctx)->hc_icontext), message,
+ message_len);
+ SHA2Final(hmac_computed, &((sha2_hmac_ctx)->hc_icontext));
+
+ switch (mechanism) {
+ case SHA256_TYPE:
+ SHA2Update(&((sha2_hmac_ctx)->hc_ocontext),
+ hmac_computed, SHA256_DIGEST_LENGTH);
+ break;
+
+ case SHA384_TYPE:
+ SHA2Update(&((sha2_hmac_ctx)->hc_ocontext),
+ hmac_computed, SHA384_DIGEST_LENGTH);
+ break;
+
+ case SHA512_TYPE:
+ SHA2Update(&((sha2_hmac_ctx)->hc_ocontext),
+ hmac_computed, SHA512_DIGEST_LENGTH);
+ break;
+ }
+
+ SHA2Final(hmac_computed, &((sha2_hmac_ctx)->hc_ocontext));
+}
+
+#endif
+
+/*
+ * SHA2 Power-On SelfTest(s).
+ */
+int
+fips_sha2_post(void)
+{
+
+ /*
+ * SHA-256 Known Hash Message (512-bits).
+ * Source from NIST SHA256ShortMsg (Len = 512)
+ */
+ static uint8_t sha256_known_hash_message[] = {
+ 0x35, 0x92, 0xec, 0xfd, 0x1e, 0xac, 0x61, 0x8f,
+ 0xd3, 0x90, 0xe7, 0xa9, 0xc2, 0x4b, 0x65, 0x65,
+ 0x32, 0x50, 0x93, 0x67, 0xc2, 0x1a, 0x0e, 0xac,
+ 0x12, 0x12, 0xac, 0x83, 0xc0, 0xb2, 0x0c, 0xd8,
+ 0x96, 0xeb, 0x72, 0xb8, 0x01, 0xc4, 0xd2, 0x12,
+ 0xc5, 0x45, 0x2b, 0xbb, 0xf0, 0x93, 0x17, 0xb5,
+ 0x0c, 0x5c, 0x9f, 0xb1, 0x99, 0x75, 0x53, 0xd2,
+ 0xbb, 0xc2, 0x9b, 0xb4, 0x2f, 0x57, 0x48, 0xad
+ };
+
+ /* known SHA256 Digest Message (32 bytes) */
+ static uint8_t known_sha256_digest[] = {
+ 0x10, 0x5a, 0x60, 0x86, 0x58, 0x30, 0xac, 0x3a,
+ 0x37, 0x1d, 0x38, 0x43, 0x32, 0x4d, 0x4b, 0xb5,
+ 0xfa, 0x8e, 0xc0, 0xe0, 0x2d, 0xda, 0xa3, 0x89,
+ 0xad, 0x8d, 0xa4, 0xf1, 0x02, 0x15, 0xc4, 0x54
+ };
+
+ /*
+ * SHA-384 Known Hash Message (512-bits).
+ * Source from NIST SHA384ShortMsg (Len = 512)
+ */
+ static uint8_t sha384_known_hash_message[] = {
+ 0x58, 0xbe, 0xab, 0xf9, 0x79, 0xab, 0x35, 0xab,
+ 0xba, 0x29, 0x37, 0x6d, 0x5d, 0xc2, 0x27, 0xab,
+ 0xb3, 0xd2, 0xff, 0x4d, 0x90, 0x30, 0x49, 0x82,
+ 0xfc, 0x10, 0x79, 0xbc, 0x2b, 0x28, 0x80, 0xfc,
+ 0xb0, 0x12, 0x9e, 0x4f, 0xed, 0xf2, 0x78, 0x98,
+ 0xce, 0x58, 0x6a, 0x91, 0xb7, 0x68, 0x1e, 0x0d,
+ 0xba, 0x38, 0x5e, 0x80, 0x0e, 0x79, 0x26, 0xc0,
+ 0xbc, 0x5a, 0xfe, 0x0d, 0x9c, 0xa9, 0x86, 0x50
+ };
+
+ /* known SHA384 Digest Message (48 bytes) */
+ static uint8_t known_sha384_digest[] = {
+ 0xa0, 0x88, 0x8e, 0x1c, 0x4d, 0x7e, 0x80, 0xcb,
+ 0xaa, 0xaf, 0xa8, 0xbb, 0x1c, 0xa1, 0xca, 0x91,
+ 0x2a, 0x93, 0x21, 0x75, 0xc2, 0xef, 0x98, 0x2c,
+ 0xe1, 0xf1, 0x23, 0xa8, 0xc1, 0xae, 0xe9, 0x63,
+ 0x5a, 0xd7, 0x5b, 0xe5, 0x25, 0x90, 0xa9, 0x24,
+ 0xbe, 0xd3, 0xf5, 0xec, 0x36, 0xc3, 0x56, 0x90
+ };
+
+ /*
+ * SHA-512 Known Hash Message (512-bits).
+ * Source from NIST SHA512ShortMsg (Len = 512)
+ */
+ static uint8_t sha512_known_hash_message[] = {
+ 0x09, 0x5c, 0x7f, 0x30, 0x82, 0x4f, 0xc9, 0x28,
+ 0x58, 0xcc, 0x93, 0x47, 0xc0, 0x85, 0xd5, 0x78,
+ 0x88, 0x5f, 0xf3, 0x61, 0x4d, 0xd3, 0x8e, 0xe7,
+ 0xee, 0x94, 0xa0, 0xf4, 0x40, 0x72, 0xc8, 0x77,
+ 0x04, 0x7e, 0xe2, 0xad, 0x16, 0x6f, 0xdb, 0xa0,
+ 0xe7, 0x44, 0xc3, 0xed, 0x2c, 0x2b, 0x24, 0xc9,
+ 0xd8, 0xa2, 0x93, 0x46, 0x48, 0xdc, 0x84, 0xd3,
+ 0xbe, 0x66, 0x63, 0x02, 0x11, 0x0a, 0xe0, 0x8f
+ };
+
+ /* known SHA512 Digest Message (64 bytes) */
+ static uint8_t known_sha512_digest[] = {
+ 0xd5, 0xcd, 0xaf, 0x83, 0xbb, 0x4a, 0x27, 0xea,
+ 0xad, 0x8d, 0x8f, 0x18, 0xe4, 0xbe, 0xe9, 0xc2,
+ 0x5b, 0xe9, 0x49, 0xa7, 0x61, 0xa0, 0xfd, 0x0f,
+ 0xb2, 0x28, 0x4c, 0xab, 0x14, 0x3c, 0xad, 0x60,
+ 0xbe, 0xb5, 0x68, 0x87, 0x34, 0xb2, 0xf8, 0x1e,
+ 0x9e, 0x2d, 0x64, 0x0b, 0x42, 0x5f, 0xd3, 0x2c,
+ 0xcb, 0x3d, 0x20, 0xd0, 0x2d, 0x63, 0xc2, 0xc9,
+ 0x4c, 0x03, 0xab, 0x3d, 0x9e, 0x7d, 0x9b, 0x4a
+ };
+
+ /* SHA-2 HMAC Test Vectors */
+
+ /*
+ * SHA-256 HMAC Known Hash Message (512-bits).
+ */
+ static uint8_t sha256_hmac_known_hash_message[] = {
+ 0x54, 0x68, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x20, 0x66, 0x6F, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4D, 0x44, 0x32, 0x2C, 0x20, 0x4D, 0x44,
+ 0x35, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x53,
+ 0x48, 0x41, 0x2D, 0x31, 0x20, 0x68, 0x61, 0x73,
+ 0x68, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x6C, 0x67,
+ 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x73, 0x2E
+ };
+
+ static uint8_t sha256_hmac_known_secret_key[] = {
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x53, 0x48, 0x41, 0x2D,
+ 0x32, 0x35, 0x36, 0x20, 0x48, 0x4D, 0x41, 0x43,
+ 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x20,
+ 0x6B, 0x65, 0x79, 0x21
+ };
+
+ static uint8_t sha256_hmac_known_secret_key_length
+ = sizeof (sha256_hmac_known_secret_key);
+
+
+ /* known SHA256 hmac (32 bytes) */
+ static uint8_t known_sha256_hmac[] = {
+ 0x02, 0x87, 0x21, 0x93, 0x84, 0x8a, 0x35, 0xae,
+ 0xdb, 0xb6, 0x79, 0x26, 0x96, 0xf0, 0x50, 0xeb,
+ 0x33, 0x49, 0x57, 0xf1, 0xb2, 0x32, 0xd3, 0x63,
+ 0x03, 0x65, 0x57, 0xa2, 0xba, 0xa2, 0x5f, 0x35
+ };
+
+ /*
+ * SHA-384 HMAC Known Hash Message (512-bits).
+ * Source from NIST HMAC.txt (Count = 15, Klen = 16, Tlen = 48)
+ */
+ static uint8_t sha384_hmac_known_secret_key[] = {
+ 0x01, 0xac, 0x59, 0xf4, 0x2f, 0x8b, 0xb9, 0x1d,
+ 0x1b, 0xd1, 0x0f, 0xe6, 0x99, 0x0d, 0x7a, 0x87
+ };
+
+ static uint8_t sha384_hmac_known_secret_key_length
+ = sizeof (sha384_hmac_known_secret_key);
+
+ static uint8_t sha384_hmac_known_hash_message[] = {
+ 0x3c, 0xaf, 0x18, 0xc4, 0x76, 0xed, 0xd5, 0x61,
+ 0x5f, 0x34, 0x3a, 0xc7, 0xb7, 0xd3, 0xa9, 0xda,
+ 0x9e, 0xfa, 0xde, 0x75, 0x56, 0x72, 0xd5, 0xba,
+ 0x4b, 0x8a, 0xe8, 0xa7, 0x50, 0x55, 0x39, 0xea,
+ 0x2c, 0x12, 0x4f, 0xf7, 0x55, 0xec, 0x04, 0x57,
+ 0xfb, 0xe4, 0x9e, 0x43, 0x48, 0x0b, 0x3c, 0x71,
+ 0xe7, 0xf4, 0x74, 0x2e, 0xc3, 0x69, 0x3a, 0xad,
+ 0x11, 0x5d, 0x03, 0x9f, 0x90, 0x22, 0x2b, 0x03,
+ 0x0f, 0xdc, 0x94, 0x40, 0x31, 0x36, 0x91, 0x71,
+ 0x6d, 0x53, 0x02, 0x00, 0x58, 0x08, 0xc0, 0x76,
+ 0x27, 0x48, 0x3b, 0x91, 0x6f, 0xdf, 0x61, 0x98,
+ 0x30, 0x63, 0xc2, 0xeb, 0x12, 0x68, 0xf2, 0xde,
+ 0xee, 0xf4, 0x2f, 0xc7, 0x90, 0x33, 0x44, 0x56,
+ 0xbc, 0x6b, 0xad, 0x25, 0x6e, 0x31, 0xfc, 0x90,
+ 0x66, 0xde, 0x7c, 0xc7, 0xe4, 0x3d, 0x13, 0x21,
+ 0xb1, 0x86, 0x6d, 0xb4, 0x5e, 0x90, 0x56, 0x22
+ };
+
+ /* known SHA384 hmac (48 bytes) */
+ static uint8_t known_sha384_hmac[] = {
+ 0x19, 0x85, 0xfa, 0x21, 0x63, 0xa5, 0x94, 0x3f,
+ 0xc5, 0xd9, 0x2f, 0x1f, 0xe8, 0x83, 0x12, 0x15,
+ 0xe7, 0xe9, 0x1f, 0x0b, 0xff, 0x53, 0x32, 0xbc,
+ 0x71, 0x3a, 0x07, 0x2b, 0xdb, 0x3a, 0x8f, 0x9e,
+ 0x5c, 0x51, 0x57, 0x46, 0x3a, 0x3b, 0xfe, 0xb3,
+ 0x62, 0x31, 0x41, 0x6e, 0x65, 0x97, 0x3e, 0x64
+ };
+
+ /*
+ * SHA-512 HMAC Known Hash Message (512-bits).
+ * Source from NIST HMAC.txt (Count = 30, Klen = 20, Tlen = 64)
+ */
+ static uint8_t sha512_hmac_known_secret_key[] = {
+ 0xa7, 0x36, 0xf2, 0x74, 0xfd, 0xa6, 0x8e, 0x1b,
+ 0xd5, 0xf9, 0x47, 0x1e, 0x85, 0xfd, 0x41, 0x5d,
+ 0x7f, 0x2b, 0xa1, 0xbc
+ };
+
+ static uint8_t sha512_hmac_known_secret_key_length
+ = sizeof (sha512_hmac_known_secret_key);
+
+ static uint8_t sha512_hmac_known_hash_message[] = {
+ 0xa6, 0xcc, 0xc3, 0x55, 0x2c, 0x33, 0xe9, 0x17,
+ 0x8b, 0x6b, 0x82, 0xc6, 0x53, 0xd6, 0x3d, 0xe2,
+ 0x54, 0x0f, 0x17, 0x08, 0x07, 0xc3, 0xd9, 0x6a,
+ 0x2a, 0xc2, 0xe2, 0x7d, 0xab, 0x55, 0x26, 0xf1,
+ 0xc7, 0xd3, 0x77, 0xe6, 0x73, 0x6f, 0x04, 0x5d,
+ 0xfb, 0x54, 0x1f, 0xec, 0xe9, 0xf4, 0x43, 0xb7,
+ 0x28, 0x9c, 0x55, 0x9b, 0x69, 0x4c, 0x2a, 0xac,
+ 0xc6, 0xc7, 0x4a, 0xe2, 0xa5, 0xe6, 0xf3, 0x0f,
+ 0xe0, 0x31, 0x61, 0x14, 0x23, 0xb0, 0x4d, 0x55,
+ 0x95, 0xff, 0xb4, 0x6a, 0xba, 0xa1, 0xd9, 0x18,
+ 0x98, 0x96, 0x8d, 0x7f, 0x18, 0x30, 0xae, 0x94,
+ 0xb0, 0x22, 0xee, 0xd2, 0x3f, 0xda, 0xd5, 0x2d,
+ 0x38, 0x11, 0x0a, 0x48, 0x03, 0xa0, 0xce, 0xe7,
+ 0xa0, 0x95, 0xc9, 0xa7, 0x8e, 0x86, 0x09, 0xed,
+ 0xeb, 0x25, 0x48, 0x1c, 0xdc, 0x15, 0x6d, 0x0b,
+ 0x2f, 0xfc, 0x56, 0xb6, 0x3f, 0xda, 0xd5, 0x33
+ };
+
+ /* known SHA512 hmac (64 bytes) */
+ static uint8_t known_sha512_hmac[] = {
+ 0xf7, 0x18, 0x03, 0x43, 0x1e, 0x07, 0xa5, 0xa6,
+ 0xe5, 0xfd, 0x4a, 0xe4, 0xcf, 0xc2, 0x75, 0x3b,
+ 0xc8, 0x0d, 0x26, 0xe1, 0x67, 0x23, 0xd9, 0xe8,
+ 0x8b, 0x40, 0x5a, 0x02, 0x34, 0x8e, 0xf4, 0xb9,
+ 0x67, 0x92, 0xc9, 0x9c, 0xed, 0x64, 0xdc, 0x70,
+ 0xea, 0x47, 0x53, 0x78, 0xb7, 0x46, 0x6a, 0xc2,
+ 0xca, 0xf4, 0xa4, 0x20, 0xb0, 0x1f, 0xf6, 0x1e,
+ 0x72, 0xc5, 0xb5, 0xee, 0x8e, 0xaa, 0xd4, 0xd4
+ };
+
+ /* SHA-2 variables. */
+ uint8_t sha256_computed_digest[SHA256_DIGEST_LENGTH];
+ uint8_t sha384_computed_digest[SHA384_DIGEST_LENGTH];
+ uint8_t sha512_computed_digest[SHA512_DIGEST_LENGTH];
+
+ uint8_t hmac_computed[SHA512_DIGEST_LENGTH];
+ SHA2_CTX *sha2_context = NULL;
+
+#ifdef _KERNEL
+ sha2_hmac_ctx_t *sha2_hmac_ctx;
+#endif
+
+ int rv;
+
+ /*
+ * SHA-2 Known Answer Hashing Test.
+ */
+
+ /* SHA-256 POST */
+
+#ifdef _KERNEL
+ sha2_context = fips_sha2_build_context(SHA256_TYPE);
+#else
+ sha2_context = fips_sha2_build_context(CKM_SHA256);
+#endif
+
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context,
+ sha256_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH,
+ sha256_computed_digest);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(sha256_computed_digest, known_sha256_digest,
+ SHA256_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /* SHA-384 POST */
+
+#ifdef _KERNEL
+ sha2_context = fips_sha2_build_context(SHA384_TYPE);
+#else
+ sha2_context = fips_sha2_build_context(CKM_SHA384);
+#endif
+
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context,
+ sha384_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH,
+ sha384_computed_digest);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(sha384_computed_digest, known_sha384_digest,
+ SHA384_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /* SHA-512 POST */
+
+#ifdef _KERNEL
+ sha2_context = fips_sha2_build_context(SHA512_TYPE);
+#else
+ sha2_context = fips_sha2_build_context(CKM_SHA512);
+#endif
+
+ if (sha2_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha2_hash(sha2_context,
+ sha512_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH,
+ sha512_computed_digest);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(sha512_computed_digest, known_sha512_digest,
+ SHA512_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * SHA-2 HMAC Known Answer Hashing Test.
+ */
+
+ /* HMAC SHA-256 POST */
+
+#ifdef _KERNEL
+ sha2_hmac_ctx = fips_sha2_hmac_build_context(
+ SHA256_TYPE,
+ sha256_hmac_known_secret_key,
+ sha256_hmac_known_secret_key_length);
+
+ if (sha2_hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ fips_hmac_sha2_hash(sha2_hmac_ctx,
+ sha256_hmac_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH,
+ hmac_computed,
+ SHA256_TYPE);
+
+ if (memcmp(hmac_computed, known_sha256_hmac,
+ SHA256_DIGEST_LENGTH) != 0)
+ return (CKR_DEVICE_ERROR);
+
+#else
+ rv = fips_hmac_sha2_hash(hmac_computed,
+ sha256_hmac_known_secret_key,
+ sha256_hmac_known_secret_key_length,
+ sha256_hmac_known_hash_message,
+ FIPS_KNOWN_HMAC_MESSAGE_LENGTH,
+ CKM_SHA256_HMAC);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(hmac_computed, known_sha256_hmac,
+ SHA256_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#endif
+
+ /* HMAC SHA-384 POST */
+
+#ifdef _KERNEL
+ sha2_hmac_ctx = fips_sha2_hmac_build_context(
+ SHA384_TYPE,
+ sha384_hmac_known_secret_key,
+ sha384_hmac_known_secret_key_length);
+
+ if (sha2_hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ fips_hmac_sha2_hash(sha2_hmac_ctx,
+ sha384_hmac_known_hash_message,
+ sizeof (sha384_hmac_known_hash_message),
+ hmac_computed,
+ SHA384_TYPE);
+
+ if (memcmp(hmac_computed, known_sha384_hmac,
+ SHA384_DIGEST_LENGTH) != 0)
+ return (CKR_DEVICE_ERROR);
+#else
+ rv = fips_hmac_sha2_hash(hmac_computed,
+ sha384_hmac_known_secret_key,
+ sha384_hmac_known_secret_key_length,
+ sha384_hmac_known_hash_message,
+ sizeof (sha384_hmac_known_hash_message),
+ CKM_SHA384_HMAC);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(hmac_computed, known_sha384_hmac,
+ SHA384_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#endif
+
+ /* HMAC SHA-512 POST */
+
+#ifdef _KERNEL
+ sha2_hmac_ctx = fips_sha2_hmac_build_context(
+ SHA512_TYPE,
+ sha512_hmac_known_secret_key,
+ sha512_hmac_known_secret_key_length);
+
+ if (sha2_hmac_ctx == NULL)
+ return (CKR_HOST_MEMORY);
+
+ fips_hmac_sha2_hash(sha2_hmac_ctx,
+ sha512_hmac_known_hash_message,
+ sizeof (sha512_hmac_known_hash_message),
+ hmac_computed,
+ SHA512_TYPE);
+
+ if (memcmp(hmac_computed, known_sha512_hmac,
+ SHA512_DIGEST_LENGTH) != 0)
+ return (CKR_DEVICE_ERROR);
+
+#else
+ rv = fips_hmac_sha2_hash(hmac_computed,
+ sha512_hmac_known_secret_key,
+ sha512_hmac_known_secret_key_length,
+ sha512_hmac_known_hash_message,
+ sizeof (sha512_hmac_known_hash_message),
+ CKM_SHA512_HMAC);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(hmac_computed, known_sha512_hmac,
+ SHA512_DIGEST_LENGTH) != 0))
+ return (CKR_DEVICE_ERROR);
+
+#endif
+
+ return (CKR_OK);
+}
diff --git a/usr/src/common/crypto/rng/fips_random.c b/usr/src/common/crypto/rng/fips_random.c
index a01394ccc8..bb8d11d9ad 100644
--- a/usr/src/common/crypto/rng/fips_random.c
+++ b/usr/src/common/crypto/rng/fips_random.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,6 +65,25 @@ fips_add160(uint32_t *sum, uint32_t const *val1, uint32_t const *val2,
return (((non_zero != 0) * 2) | carry);
}
+#ifdef _LITTLE_ENDIAN
+#define SWAP16(value) \
+ ((((value) & 0xff) << 8) | ((value) >> 8))
+
+#define SWAP32(value) \
+ (((uint32_t)SWAP16((uint16_t)((value) & 0xffff)) << 16) | \
+ (uint32_t)SWAP16((uint16_t)((value) >> 16)))
+
+static void
+xvalconv(uint32_t *dest, uint32_t *src, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ dest [i] = SWAP32(src[i]);
+ }
+}
+#endif /* _LITTLE_ENDIAN */
+
/*
* Computes a new random value, which is stored in x_j; updates
* XKEY. XSEED_j is additional input. In principle, we should
@@ -86,7 +105,6 @@ void
fips_random_inner(uint32_t *key, uint32_t *x_j,
uint32_t *XSEED_j)
{
- int i;
SHA1_CTX sha1_context;
/* Alias to preserve terminology from FIPS 186-2 */
#define XVAL XSEED_j
@@ -124,9 +142,18 @@ fips_random_inner(uint32_t *key, uint32_t *x_j,
* sha1_context, which is of type SHA1_CTX, defined in sha1.h.
*/
/* copy out to x_j */
- for (i = 0; i < 5; i++) {
- x_j[i] = sha1_context.state[i];
+
+#ifdef _BIG_ENDIAN
+ {
+ int i;
+ for (i = 0; i < 5; i++) {
+ x_j[i] = sha1_context.state[i];
+ }
}
+#else
+ xvalconv(x_j, sha1_context.state, SHA1BYTES/4);
+#endif
+
/*
* Step 3d: XKEY = (1 + XKEY + x_sub_j) mod 2^b. b=160. The
* mod 2^160 is implicit in the 160 bit representation. The
diff --git a/usr/src/common/crypto/rng/fips_random.h b/usr/src/common/crypto/rng/fips_random.h
index c1fcb0ff1d..bbbd013b29 100644
--- a/usr/src/common/crypto/rng/fips_random.h
+++ b/usr/src/common/crypto/rng/fips_random.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,7 +38,15 @@ extern "C" {
#define BYTES_IN_WORD 4
#define SHA1BYTES (BYTES_IN_WORD * SHA1WORDS)
+#ifdef _KERNEL
+#define SHA1_HASH_SIZE 20
+#define CK_RV int
+#define CKR_OK CRYPTO_SUCCESS
+#define CKR_DEVICE_ERROR CRYPTO_DEVICE_ERROR
+#endif
+
extern void fips_random_inner(uint32_t *, uint32_t *, uint32_t *);
+extern int fips_rng_post(void);
#ifdef __cplusplus
}
diff --git a/usr/src/common/crypto/rsa/rsa_impl.h b/usr/src/common/crypto/rsa/rsa_impl.h
index 49851be59b..89a7d49a50 100644
--- a/usr/src/common/crypto/rsa/rsa_impl.h
+++ b/usr/src/common/crypto/rsa/rsa_impl.h
@@ -91,7 +91,6 @@ typedef struct {
BIGNUM n_rr; /* 2^(2*(32*n->len)) mod n */
} RSAkey;
-
BIG_ERR_CODE RSA_key_init(RSAkey *key, int psize, int qsize);
void RSA_key_finish(RSAkey *key);
@@ -108,6 +107,61 @@ int knzero_random_generator(uint8_t *ran_out, size_t ran_len);
void kmemset(uint8_t *buf, char pattern, size_t len);
#endif
+/*
+ * The following definitions and declarations are only used by RSA FIPS POST
+ */
+#ifdef _RSA_FIPS_POST
+
+/* RSA FIPS Declarations */
+#define FIPS_RSA_PUBLIC_EXPONENT_LENGTH 3 /* 24-bits */
+#define FIPS_RSA_PRIVATE_VERSION_LENGTH 1 /* 8-bits */
+#define FIPS_RSA_MESSAGE_LENGTH 128 /* 1024-bits */
+#define FIPS_RSA_COEFFICIENT_LENGTH 64 /* 512-bits */
+#define FIPS_RSA_PRIME0_LENGTH 64 /* 512-bits */
+#define FIPS_RSA_PRIME1_LENGTH 64 /* 512-bits */
+#define FIPS_RSA_EXPONENT0_LENGTH 64 /* 512-bits */
+#define FIPS_RSA_EXPONENT1_LENGTH 64 /* 512-bits */
+#define FIPS_RSA_PRIVATE_EXPONENT_LENGTH 128 /* 1024-bits */
+#define FIPS_RSA_ENCRYPT_LENGTH 128 /* 1024-bits */
+#define FIPS_RSA_DECRYPT_LENGTH 128 /* 1024-bits */
+#define FIPS_RSA_SIGNATURE_LENGTH 128 /* 1024-bits */
+#define FIPS_RSA_MODULUS_LENGTH 128 /* 1024-bits */
+#define MAX_KEY_ATTR_BUFLEN 1024
+
+typedef struct RSAPrivateKey_s {
+ uint8_t *version;
+ int version_len;
+ uint8_t *modulus;
+ int modulus_len;
+ uint8_t *public_expo;
+ int public_expo_len;
+ uint8_t *private_expo;
+ int private_expo_len;
+ uint8_t *prime1;
+ int prime1_len;
+ uint8_t *prime2;
+ int prime2_len;
+ uint8_t *exponent1;
+ int exponent1_len;
+ uint8_t *exponent2;
+ int exponent2_len;
+ uint8_t *coef;
+ int coef_len;
+} RSAPrivateKey_t;
+
+/* RSA FIPS functions */
+extern int fips_rsa_post(void);
+extern int fips_rsa_encrypt(uint8_t *, int, uint8_t *,
+ int, uint8_t *, int, uint8_t *);
+extern int fips_rsa_decrypt(RSAPrivateKey_t *, uint8_t *,
+ int, uint8_t *);
+extern int fips_rsa_sign(RSAPrivateKey_t *, uint8_t *,
+ uint32_t, uint8_t *);
+extern int fips_rsa_verify(RSAPrivateKey_t *, uint8_t *, uint32_t,
+ uint8_t *);
+
+#endif /* _RSA_FIPS_POST */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/common/crypto/sha1/sha1_impl.h b/usr/src/common/crypto/sha1/sha1_impl.h
new file mode 100644
index 0000000000..0dba1f0bcd
--- /dev/null
+++ b/usr/src/common/crypto/sha1/sha1_impl.h
@@ -0,0 +1,96 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SHA1_IMPL_H
+#define _SHA1_IMPL_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fips/fips_post.h>
+
+#ifdef _KERNEL
+#define SHA1_HASH_SIZE 20 /* SHA_1 digest length in bytes */
+#define SHA1_DIGEST_LENGTH 20 /* SHA1 digest length in bytes */
+#define SHA1_HMAC_BLOCK_SIZE 64 /* SHA1-HMAC block size */
+#define SHA1_HMAC_MIN_KEY_LEN 1 /* SHA1-HMAC min key length in bytes */
+#define SHA1_HMAC_MAX_KEY_LEN INT_MAX /* SHA1-HMAC max key length in bytes */
+#define SHA1_HMAC_INTS_PER_BLOCK (SHA1_HMAC_BLOCK_SIZE/sizeof (uint32_t))
+
+/*
+ * CSPI information (entry points, provider info, etc.)
+ */
+typedef enum sha1_mech_type {
+ SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */
+ SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */
+ SHA1_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA1_HMAC_GENERAL */
+} sha1_mech_type_t;
+
+/*
+ * Context for SHA1 mechanism.
+ */
+typedef struct sha1_ctx {
+ sha1_mech_type_t sc_mech_type; /* type of context */
+ SHA1_CTX sc_sha1_ctx; /* SHA1 context */
+} sha1_ctx_t;
+
+/*
+ * Context for SHA1-HMAC and SHA1-HMAC-GENERAL mechanisms.
+ */
+typedef struct sha1_hmac_ctx {
+ sha1_mech_type_t hc_mech_type; /* type of context */
+ uint32_t hc_digest_len; /* digest len in bytes */
+ SHA1_CTX hc_icontext; /* inner SHA1 context */
+ SHA1_CTX hc_ocontext; /* outer SHA1 context */
+} sha1_hmac_ctx_t;
+
+#endif
+
+extern int fips_sha1_post(void);
+
+/* SHA1 funtions */
+extern SHA1_CTX *fips_sha1_build_context(void);
+extern int fips_sha1_hash(SHA1_CTX *, uchar_t *, ulong_t, uchar_t *);
+
+/* SHA1 HMAC functions */
+#ifndef _KERNEL
+extern soft_hmac_ctx_t *fips_sha1_hmac_build_context(uint8_t *,
+ unsigned int);
+extern CK_RV fips_hmac_sha1_hash(unsigned char *, uint8_t *,
+ unsigned int, uint8_t *, unsigned int);
+#else
+extern sha1_hmac_ctx_t *fips_sha1_hmac_build_context(uint8_t *,
+ unsigned int);
+extern void fips_hmac_sha1_hash(sha1_hmac_ctx_t *, uint8_t *,
+ uint32_t, uint8_t *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHA1_IMPL_H */
diff --git a/usr/src/common/crypto/sha2/sha2_impl.h b/usr/src/common/crypto/sha2/sha2_impl.h
new file mode 100644
index 0000000000..521eca6e11
--- /dev/null
+++ b/usr/src/common/crypto/sha2/sha2_impl.h
@@ -0,0 +1,89 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SHA2_IMPL_H
+#define _SHA2_IMPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fips/fips_post.h>
+
+typedef enum {
+ SHA1_TYPE,
+ SHA256_TYPE,
+ SHA384_TYPE,
+ SHA512_TYPE
+} sha2_mech_t;
+
+#ifdef _KERNEL
+
+/*
+ * Context for SHA2 mechanism.
+ */
+typedef struct sha2_ctx {
+ sha2_mech_type_t sc_mech_type; /* type of context */
+ SHA2_CTX sc_sha2_ctx; /* SHA2 context */
+} sha2_ctx_t;
+
+/*
+ * Context for SHA2 HMAC and HMAC GENERAL mechanisms.
+ */
+typedef struct sha2_hmac_ctx {
+ sha2_mech_type_t hc_mech_type; /* type of context */
+ uint32_t hc_digest_len; /* digest len in bytes */
+ SHA2_CTX hc_icontext; /* inner SHA2 context */
+ SHA2_CTX hc_ocontext; /* outer SHA2 context */
+} sha2_hmac_ctx_t;
+
+#endif
+
+extern int fips_sha2_post(void);
+extern int fips_sha2_hash(SHA2_CTX *, uchar_t *, ulong_t, uchar_t *);
+
+#ifndef _KERNEL
+/* SHA2 funtions */
+extern SHA2_CTX *fips_sha2_build_context(CK_MECHANISM_TYPE);
+
+/* SHA2 HMAC functions */
+extern soft_hmac_ctx_t *fips_sha2_hmac_build_context(CK_MECHANISM_TYPE,
+ uint8_t *, unsigned int);
+extern CK_RV fips_hmac_sha2_hash(unsigned char *, uint8_t *,
+ unsigned int, uint8_t *, unsigned int, CK_MECHANISM_TYPE);
+#else
+
+extern SHA2_CTX *fips_sha2_build_context(sha2_mech_t);
+extern sha2_hmac_ctx_t *fips_sha2_hmac_build_context(sha2_mech_t,
+ uint8_t *, unsigned int);
+extern void fips_hmac_sha2_hash(sha2_hmac_ctx_t *, uint8_t *, uint32_t,
+ uint8_t *, sha2_mech_t);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHA2_IMPL_H */
diff --git a/usr/src/lib/libcryptoutil/common/config_parsing.c b/usr/src/lib/libcryptoutil/common/config_parsing.c
index 92eccf35dd..14578975d9 100644
--- a/usr/src/lib/libcryptoutil/common/config_parsing.c
+++ b/usr/src/lib/libcryptoutil/common/config_parsing.c
@@ -19,11 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <errno.h>
@@ -234,9 +233,9 @@ parse_policylist(char *buf, uentry_t *pent)
sizeof (METASLOT_STATUS) - 1) == 0) {
if (value = strpbrk(buf, SEP_EQUAL)) {
value++; /* get rid of = */
- if (strcmp(value, METASLOT_DISABLED) == 0) {
+ if (strcmp(value, DISABLED_KEYWORD) == 0) {
pent->flag_metaslot_enabled = B_FALSE;
- } else if (strcmp(value, METASLOT_ENABLED) == 0) {
+ } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
pent->flag_metaslot_enabled = B_TRUE;
} else {
cryptoerror(LOG_ERR, "failed to parse %s.\n",
@@ -253,9 +252,9 @@ parse_policylist(char *buf, uentry_t *pent)
sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
if (value = strpbrk(buf, SEP_EQUAL)) {
value++; /* get rid of = */
- if (strcmp(value, METASLOT_DISABLED) == 0) {
+ if (strcmp(value, DISABLED_KEYWORD) == 0) {
pent->flag_metaslot_auto_key_migrate = B_FALSE;
- } else if (strcmp(value, METASLOT_ENABLED) == 0) {
+ } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
pent->flag_metaslot_auto_key_migrate = B_TRUE;
} else {
cryptoerror(LOG_ERR, "failed to parse %s.\n",
@@ -547,3 +546,98 @@ out:
return (rc);
}
+
+static CK_RV
+parse_fips_mode(char *buf, int *mode)
+{
+
+ char *value;
+
+ if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) {
+ if (value = strpbrk(buf, SEP_EQUAL)) {
+ value++; /* get rid of = */
+ if (strcmp(value, DISABLED_KEYWORD) == 0) {
+ *mode = CRYPTO_FIPS_MODE_DISABLED;
+ } else if (strcmp(value, ENABLED_KEYWORD) == 0) {
+ *mode = CRYPTO_FIPS_MODE_ENABLED;
+ } else {
+ cryptoerror(LOG_ERR,
+ "failed to parse kcf.conf file.\n");
+ return (CKR_FUNCTION_FAILED);
+ }
+ return (CKR_OK);
+ } else {
+ return (CKR_FUNCTION_FAILED);
+ }
+ } else {
+ /* should not come here */
+ return (CKR_FUNCTION_FAILED);
+ }
+
+}
+
+static boolean_t
+is_fips(char *name)
+{
+ if (strcmp(name, FIPS_KEYWORD) == 0) {
+ return (B_TRUE);
+ } else {
+ return (B_FALSE);
+ }
+}
+
+CK_RV
+get_fips_mode(int *mode)
+{
+ FILE *pfile = NULL;
+ char buffer[BUFSIZ];
+ int len;
+ CK_RV rc = CKR_OK;
+ int found = 0;
+ char *token1;
+
+ if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
+ cryptoerror(LOG_ERR,
+ "failed to open the kcf.conf file for read only.");
+ return (CKR_FUNCTION_FAILED);
+ }
+
+ while (fgets(buffer, BUFSIZ, pfile) != NULL) {
+ if (buffer[0] == '#' || buffer[0] == ' ' ||
+ buffer[0] == '\n'|| buffer[0] == '\t') {
+ continue; /* ignore comment lines */
+ }
+
+ len = strlen(buffer);
+ if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
+ len--;
+ }
+ buffer[len] = '\0';
+
+ /* Get provider name */
+ if ((token1 = strtok(buffer, SEP_COLON)) ==
+ NULL) { /* buf is NULL */
+ return (CKR_FUNCTION_FAILED);
+ };
+
+ if (is_fips(token1)) {
+ if ((rc = parse_fips_mode(buffer + strlen(token1) + 1,
+ mode)) != CKR_OK) {
+ goto out;
+ } else {
+ found++;
+ break;
+ }
+ } else {
+ continue;
+ }
+ }
+
+ if (!found) {
+ *mode = CRYPTO_FIPS_MODE_DISABLED;
+ }
+
+out:
+ (void) fclose(pfile);
+ return (rc);
+}
diff --git a/usr/src/lib/libcryptoutil/common/cryptoutil.h b/usr/src/lib/libcryptoutil/common/cryptoutil.h
index 6687417e29..191a335e5c 100644
--- a/usr/src/lib/libcryptoutil/common/cryptoutil.h
+++ b/usr/src/lib/libcryptoutil/common/cryptoutil.h
@@ -41,6 +41,7 @@ extern "C" {
#define MECH_ID_HEX_LEN 11 /* length of mechanism id in hex form */
#define _PATH_PKCS11_CONF "/etc/crypto/pkcs11.conf"
+#define _PATH_KCF_CONF "/etc/crypto/kcf.conf"
#define _PATH_KCFD_LOCK "/var/run/kcfd.lock"
/* $ISA substitution for parsing pkcs11.conf data */
@@ -57,19 +58,23 @@ extern "C" {
#define SEP_EQUAL "="
#define SEP_COMMA ","
#define METASLOT_KEYWORD "metaslot"
+#define FIPS_KEYWORD "fips-140"
#define EF_DISABLED "disabledlist="
#define EF_ENABLED "enabledlist="
#define EF_NORANDOM "NO_RANDOM"
#define METASLOT_TOKEN "metaslot_token="
#define METASLOT_SLOT "metaslot_slot="
#define METASLOT_STATUS "metaslot_status="
+#define EF_FIPS_STATUS "fips_status="
#define METASLOT_AUTO_KEY_MIGRATE "metaslot_auto_key_migrate="
-#define METASLOT_ENABLED "enabled"
-#define METASLOT_DISABLED "disabled"
+#define ENABLED_KEYWORD "enabled"
+#define DISABLED_KEYWORD "disabled"
#define SLOT_DESCRIPTION_SIZE 64
#define TOKEN_LABEL_SIZE 32
#define TOKEN_MANUFACTURER_SIZE 32
#define TOKEN_SERIAL_SIZE 16
+#define CRYPTO_FIPS_MODE_DISABLED 0
+#define CRYPTO_FIPS_MODE_ENABLED 1
/*
* Define the following softtoken values that are used by softtoken
@@ -156,6 +161,9 @@ extern int pkcs11_read_data(char *filename, void **dbuf, size_t *dlen);
extern int open_nointr(const char *path, int oflag, ...);
extern ssize_t readn_nointr(int fd, void *dbuf, size_t dlen);
extern ssize_t writen_nointr(int fd, void *dbuf, size_t dlen);
+extern int update_conf(char *conf_file, char *entry);
+
+extern CK_RV get_fips_mode(int *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libcryptoutil/common/mapfile-vers b/usr/src/lib/libcryptoutil/common/mapfile-vers
index 282d7c5f0b..7e2fe51536 100644
--- a/usr/src/lib/libcryptoutil/common/mapfile-vers
+++ b/usr/src/lib/libcryptoutil/common/mapfile-vers
@@ -49,6 +49,7 @@ SUNWprivate {
free_uentrylist;
free_umechlist;
getent_uef;
+ get_fips_mode;
get_fullpath;
get_metaslot_info;
get_pkcs11conf_info;
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com b/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com
index c3797e5cab..f97fcfe1ad 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# lib/pkcs11/pkcs11_softtoken/Makefile.com
@@ -64,7 +64,10 @@ LCL_OBJECTS = \
softSSL.o \
softASN1.o \
softBlowfishCrypt.o \
- softEC.o
+ softEC.o \
+ softFipsPost.o \
+ softFipsPostUtil.o \
+ softFipsDSAUtil.o
ASFLAGS = $(AS_PICFLAGS) -P -D__STDC__ -D_ASM $(CPPFLAGS)
@@ -77,16 +80,24 @@ ECC_COBJECTS = \
MPI_COBJECTS = mp_gf2m.o mpi.o mplogic.o mpmontg.o mpprime.o
RSA_COBJECTS = rsa_impl.o
+RNG_COBJECTS = fips_random.o
+FIPS_COBJECTS = fips_des_util.o \
+ fips_aes_util.o fips_sha1_util.o fips_sha2_util.o \
+ fips_rsa_util.o fips_ecc_util.o fips_random_util.o
ECC_OBJECTS = $(ECC_COBJECTS) $(ECC_PSR_OBJECTS)
MPI_OBJECTS = $(MPI_COBJECTS) $(MPI_PSR_OBJECTS)
RSA_OBJECTS = $(RSA_COBJECTS) $(RSA_PSR_OBJECTS)
+RNG_OBJECTS = $(RNG_COBJECTS)
+FIPS_OBJECTS = $(FIPS_COBJECTS)
BER_OBJECTS = bprint.o decode.o encode.o io.o
OBJECTS = \
$(LCL_OBJECTS) \
$(MPI_OBJECTS) \
$(RSA_OBJECTS) \
+ $(RNG_OBJECTS) \
+ $(FIPS_OBJECTS) \
$(BIGNUM_OBJECTS) \
$(BER_OBJECTS) \
$(ECC_OBJECTS)
@@ -98,6 +109,10 @@ DESDIR= $(SRC)/common/crypto/des
ECCDIR= $(SRC)/common/crypto/ecc
MPIDIR= $(SRC)/common/mpi
RSADIR= $(SRC)/common/crypto/rsa
+RNGDIR= $(SRC)/common/crypto/rng
+FIPSDIR= $(SRC)/common/crypto/fips
+SHA1DIR= $(SRC)/common/crypto/sha1
+SHA2DIR= $(SRC)/common/crypto/sha2
BIGNUMDIR= $(SRC)/common/bignum
BERDIR= ../../../libldap5/sources/ldap/ber
@@ -112,7 +127,9 @@ SRCS = \
$(LCL_OBJECTS:%.o=$(SRCDIR)/%.c) \
$(MPI_COBJECTS:%.o=$(MPIDIR)/%.c) \
$(RSA_COBJECTS:%.o=$(RSADIR)/%.c) \
- $(ECC_COBJECTS:%.o=$(ECCDIR)/%.c)
+ $(ECC_COBJECTS:%.o=$(ECCDIR)/%.c) \
+ $(RNG_COBJECTS:%.o=$(RNGDIR)/%.c) \
+ $(FIPS_COBJECTS:%.o=$(FIPSDIR)/%.c)
# libelfsign needs a static pkcs11_softtoken
LIBS = $(DYNLIB)
@@ -121,8 +138,9 @@ LDLIBS += -lc -lmd -lcryptoutil -lsoftcrypto
CFLAGS += $(CCVERBOSE)
CPPFLAGS += -I$(AESDIR) -I$(BLOWFISHDIR) -I$(ARCFOURDIR) -I$(DESDIR) \
- -I$(ECCDIR) -I$(SRC)/common/crypto -I$(MPIDIR) -I$(RSADIR) \
- -I$(SRCDIR) -I$(BIGNUMDIR) -D_POSIX_PTHREAD_SEMANTICS \
+ -I$(ECCDIR) -I$(SRC)/common/crypto -I$(MPIDIR) -I$(RSADIR) -I$(RNGDIR) \
+ -I$(FIPSDIR) -I$(SHA1DIR) -I$(SHA2DIR) -I$(SRCDIR) \
+ -I$(BIGNUMDIR) -D_POSIX_PTHREAD_SEMANTICS \
-DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B
LINTFLAGS64 += -errchk=longptr64
@@ -132,8 +150,9 @@ ROOTLIBDIR64= $(ROOT)/usr/lib/security/$(MACH64)
LINTSRC = \
$(LCL_OBJECTS:%.o=$(SRCDIR)/%.c) \
- $(RSA_COBJECTS:%.o=$(RSADIR)/%.c)
-
+ $(RSA_COBJECTS:%.o=$(RSADIR)/%.c) \
+ $(RNG_COBJECTS:%.o=$(RNGDIR)/%.c) \
+ $(FIPS_COBJECTS:%.o=$(FIPSDIR)/%.c)
.KEEP_STATE:
@@ -159,4 +178,12 @@ pics/%.o: $(RSADIR)/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
+pics/%.o: $(RNGDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/%.o: $(FIPSDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSA.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSA.h
new file mode 100644
index 0000000000..52cea0dcee
--- /dev/null
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSA.h
@@ -0,0 +1,68 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FIPS_DSA_H
+#define _FIPS_DSA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FIPS_DSA_DIGEST_LENGTH 20 /* 160-bits */
+#define FIPS_DSA_SEED_LENGTH 20 /* 160-bits */
+#define FIPS_DSA_SUBPRIME_LENGTH 20 /* 160-bits */
+#define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */
+#define FIPS_DSA_PRIME_LENGTH 128 /* 1024-bits */
+#define FIPS_DSA_BASE_LENGTH 128 /* 1024-bits */
+
+typedef struct DSAParams_s {
+ uint8_t *prime;
+ int prime_len;
+ uint8_t *subprime;
+ int subprime_len;
+ uint8_t *base;
+ int base_len;
+} DSAParams_t;
+
+typedef struct fips_key_s {
+ uint8_t *key;
+ int key_len;
+} fips_key_t;
+
+
+/* DSA functions */
+extern CK_RV fips_generate_dsa_key(DSAkey *, uint8_t *, int);
+extern CK_RV fips_dsa_genkey_pair(DSAParams_t *,
+ fips_key_t *, fips_key_t *, uint8_t *, int);
+extern CK_RV fips_dsa_digest_sign(DSAParams_t *,
+ fips_key_t *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, uint8_t *, int);
+extern CK_RV fips_dsa_verify(DSAParams_t *, fips_key_t *,
+ CK_BYTE_PTR, CK_BYTE_PTR);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FIPS_DSA_H */
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSAUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSAUtil.c
new file mode 100644
index 0000000000..8f492aee68
--- /dev/null
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsDSAUtil.c
@@ -0,0 +1,503 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sysmacros.h>
+#include <sys/sha1.h>
+#define _SHA2_IMPL
+#include <sys/sha2.h>
+#include <sys/crypto/common.h>
+#include <modes/modes.h>
+#include <bignum.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softCrypt.h"
+#include "softGlobal.h"
+#include "softRSA.h"
+#include "softDSA.h"
+#include "softRandom.h"
+#include "softOps.h"
+#include "softMAC.h"
+#include "softFipsDSA.h"
+#include <sha1_impl.h>
+
+CK_RV
+fips_generate_dsa_key(DSAkey *key, uint8_t *seed, int seed_len)
+{
+ BIG_ERR_CODE err;
+
+
+ bytestring2bignum(&key->x, seed, seed_len);
+
+ /* Compute public key y = g**x mod p */
+ if ((err = big_modexp(&(key->y), &(key->g), (&key->x),
+ (&key->p), NULL)) != BIG_OK)
+ return (convert_rv(err));
+
+ return (CKR_OK);
+}
+
+CK_RV
+fips_dsa_genkey_pair(DSAParams_t *dsa_params, fips_key_t *pubkey,
+ fips_key_t *prikey, uint8_t *seed, int seed_len)
+{
+ BIG_ERR_CODE brv;
+ CK_RV rv;
+ DSAkey dsakey = {0};
+
+ /*
+ * initialize the dsa key
+ * Note: big_extend takes length in words
+ */
+ if ((brv = DSA_key_init(&dsakey, dsa_params->prime_len * 8))
+ != BIG_OK) {
+ rv = convert_rv(brv);
+ goto cleanexit;
+ }
+
+ if ((brv = big_extend(&dsakey.p,
+ CHARLEN2BIGNUMLEN(dsa_params->prime_len))) != BIG_OK) {
+ rv = convert_rv(brv);
+ goto cleanexit;
+ }
+
+ bytestring2bignum(&dsakey.p, dsa_params->prime, dsa_params->prime_len);
+
+ if ((brv = big_extend(&dsakey.q,
+ CHARLEN2BIGNUMLEN(dsa_params->subprime_len))) != BIG_OK) {
+ rv = convert_rv(brv);
+ goto cleanexit;
+ }
+
+ bytestring2bignum(&dsakey.q, dsa_params->subprime,
+ dsa_params->subprime_len);
+
+ if ((brv = big_extend(&dsakey.g,
+ CHARLEN2BIGNUMLEN(dsa_params->base_len))) != BIG_OK) {
+ rv = convert_rv(brv);
+ goto cleanexit;
+ }
+
+ bytestring2bignum(&dsakey.g, dsa_params->base, dsa_params->base_len);
+
+ /*
+ * generate DSA key pair
+ * Note: bignum.len is length of value in words
+ */
+ if ((rv = fips_generate_dsa_key(&dsakey, seed, seed_len)) != CKR_OK) {
+ goto cleanexit;
+ }
+
+ /* pubkey->key_len = dsakey.y.len * (int)sizeof (uint32_t); */
+ pubkey->key_len = dsa_params->prime_len;
+ if ((pubkey->key = malloc(pubkey->key_len)) == NULL) {
+ rv = CKR_HOST_MEMORY;
+ goto cleanexit;
+ }
+ bignum2bytestring(pubkey->key, &dsakey.y, pubkey->key_len);
+
+ /* prikey->key_len = dsakey.x.len * (int)sizeof (uint32_t); */
+ prikey->key_len = DSA_SUBPRIME_BYTES;
+ if ((prikey->key = malloc(prikey->key_len)) == NULL) {
+ rv = CKR_HOST_MEMORY;
+ goto cleanexit;
+ }
+ bignum2bytestring(prikey->key, &dsakey.x, prikey->key_len);
+ DSA_key_finish(&dsakey);
+ return (CKR_OK);
+
+cleanexit:
+ DSA_key_finish(&dsakey);
+
+ if (pubkey->key != NULL) {
+ free(pubkey->key);
+ }
+
+ if (prikey->key != NULL) {
+ free(prikey->key);
+ }
+
+ return (rv);
+}
+
+CK_RV
+fips_dsa_digest_sign(DSAParams_t *dsa_params, fips_key_t *key,
+ CK_BYTE_PTR in, CK_ULONG inlen, CK_BYTE_PTR out,
+ uint8_t *seed, int seed_len)
+{
+
+
+ DSAkey dsakey;
+ BIGNUM msg, tmp, tmp1, tmp2;
+ BIG_ERR_CODE err;
+ CK_RV rv = CKR_OK;
+ SHA1_CTX *sha1_context = NULL;
+ uint8_t sha1_computed_digest[FIPS_DSA_DIGEST_LENGTH];
+
+ sha1_context = fips_sha1_build_context();
+ if (sha1_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha1_hash(sha1_context, in, inlen, sha1_computed_digest);
+
+ if ((err = DSA_key_init(&dsakey, dsa_params->prime_len * 8)) !=
+ BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ if ((err = big_init(&msg, BIG_CHUNKS_FOR_160BITS)) != BIG_OK) {
+ goto clean2;
+ }
+ if ((err = big_init(&tmp, CHARLEN2BIGNUMLEN(dsa_params->prime_len) +
+ 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) {
+ goto clean3;
+ }
+ if ((err = big_init(&tmp1, 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) {
+ goto clean4;
+ }
+ if ((err = big_init(&tmp2, BIG_CHUNKS_FOR_160BITS)) != BIG_OK) {
+ goto clean5;
+ }
+
+ bytestring2bignum(&(dsakey.g), dsa_params->base,
+ dsa_params->prime_len);
+ bytestring2bignum(&(dsakey.x), key->key, seed_len);
+ bytestring2bignum(&(dsakey.p), dsa_params->prime,
+ dsa_params->prime_len);
+ bytestring2bignum(&(dsakey.q), dsa_params->subprime,
+ DSA_SUBPRIME_BYTES);
+ bytestring2bignum(&msg, (uchar_t *)sha1_computed_digest,
+ FIPS_DSA_DIGEST_LENGTH);
+
+ bytestring2bignum(&(dsakey.k), seed, seed_len);
+
+ if ((err = big_div_pos(NULL, &(dsakey.k), &(dsakey.k),
+ &(dsakey.q))) != BIG_OK)
+ goto clean6;
+
+ if ((err = big_modexp(&tmp, &(dsakey.g), &(dsakey.k), &(dsakey.p),
+ NULL)) != BIG_OK)
+ goto clean6;
+
+ if ((err = big_div_pos(NULL, &(dsakey.r), &tmp, &(dsakey.q))) !=
+ BIG_OK)
+ goto clean6;
+
+ if ((err = big_ext_gcd_pos(NULL, NULL, &tmp, &(dsakey.q),
+ &(dsakey.k))) != BIG_OK)
+ goto clean6;
+
+ if (tmp.sign == -1)
+ if ((err = big_add(&tmp, &tmp, &(dsakey.q))) != BIG_OK)
+ goto clean6; /* tmp <- k^-1 */
+
+ if ((err = big_mul(&tmp1, &(dsakey.x), &(dsakey.r))) != BIG_OK)
+ goto clean6;
+
+ if ((err = big_add(&tmp1, &tmp1, &msg)) != BIG_OK)
+ goto clean6;
+
+ if ((err = big_mul(&tmp, &tmp1, &tmp)) != BIG_OK)
+ goto clean6;
+
+ if ((err = big_div_pos(NULL, &(dsakey.s), &tmp, &(dsakey.q))) !=
+ BIG_OK)
+ goto clean6;
+
+ bignum2bytestring((uchar_t *)out, &(dsakey.r), 20);
+ bignum2bytestring((uchar_t *)out + 20, &(dsakey.s), 20);
+
+ err = BIG_OK;
+
+clean6:
+ big_finish(&tmp2);
+clean5:
+ big_finish(&tmp1);
+clean4:
+ big_finish(&tmp);
+clean3:
+ big_finish(&msg);
+clean2:
+ DSA_key_finish(&dsakey);
+ if (err == BIG_OK)
+ rv = CKR_OK;
+ else if (err == BIG_NO_MEM)
+ rv = CKR_HOST_MEMORY;
+ else
+ rv = CKR_FUNCTION_FAILED;
+clean1:
+ return (rv);
+}
+
+CK_RV
+fips_dsa_verify(DSAParams_t *dsa_params, fips_key_t *key,
+ CK_BYTE_PTR data, CK_BYTE_PTR sig)
+{
+
+ DSAkey dsakey;
+ BIGNUM msg, tmp1, tmp2, tmp3;
+ CK_RV rv = CKR_OK;
+ SHA1_CTX *sha1_context = NULL;
+ uint8_t sha1_computed_digest[FIPS_DSA_DIGEST_LENGTH];
+
+ sha1_context = fips_sha1_build_context();
+ if (sha1_context == NULL)
+ return (CKR_HOST_MEMORY);
+
+ rv = fips_sha1_hash(sha1_context, data,
+ FIPS_DSA_DIGEST_LENGTH, sha1_computed_digest);
+
+ if (DSA_key_init(&dsakey, dsa_params->prime_len * 8) != BIG_OK) {
+ rv = CKR_HOST_MEMORY;
+ goto clean1;
+ }
+
+ rv = CKR_HOST_MEMORY;
+ if (big_init(&msg, BIG_CHUNKS_FOR_160BITS) != BIG_OK) {
+ goto clean6;
+ }
+ if (big_init(&tmp1, 2 * CHARLEN2BIGNUMLEN(dsa_params->prime_len)) !=
+ BIG_OK) {
+ goto clean7;
+ }
+ if (big_init(&tmp2, CHARLEN2BIGNUMLEN(dsa_params->prime_len)) !=
+ BIG_OK) {
+ goto clean8;
+ }
+ if (big_init(&tmp3, 2 * BIG_CHUNKS_FOR_160BITS) != BIG_OK) {
+ goto clean9;
+ }
+
+ bytestring2bignum(&(dsakey.g), dsa_params->base,
+ dsa_params->base_len);
+ bytestring2bignum(&(dsakey.y), key->key, key->key_len);
+ bytestring2bignum(&(dsakey.p), dsa_params->prime,
+ dsa_params->prime_len);
+ bytestring2bignum(&(dsakey.q), dsa_params->subprime,
+ DSA_SUBPRIME_BYTES);
+ bytestring2bignum(&(dsakey.r), (uchar_t *)sig, 20);
+ bytestring2bignum(&(dsakey.s), ((uchar_t *)sig) + 20, 20);
+ bytestring2bignum(&msg, (uchar_t *)sha1_computed_digest,
+ FIPS_DSA_DIGEST_LENGTH);
+
+ if (big_ext_gcd_pos(NULL, &tmp2, NULL, &(dsakey.s), &(dsakey.q)) !=
+ BIG_OK)
+ goto clean10;
+
+ if (tmp2.sign == -1)
+ if (big_add(&tmp2, &tmp2, &(dsakey.q)) != BIG_OK)
+ goto clean10; /* tmp2 <- w */
+
+ if (big_mul(&tmp1, &msg, &tmp2) != BIG_OK)
+ goto clean10;
+
+ if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK)
+ goto clean10; /* tmp1 <- u_1 */
+
+ if (big_mul(&tmp2, &tmp2, &(dsakey.r)) != BIG_OK)
+ goto clean10;
+
+ if (big_div_pos(NULL, &tmp2, &tmp2, &(dsakey.q)) != BIG_OK)
+ goto clean10; /* tmp2 <- u_2 */
+
+ if (big_modexp(&tmp1, &(dsakey.g), &tmp1, &(dsakey.p), NULL) !=
+ BIG_OK)
+ goto clean10;
+
+ if (big_modexp(&tmp2, &(dsakey.y), &tmp2, &(dsakey.p), NULL) !=
+ BIG_OK)
+ goto clean10;
+
+ if (big_mul(&tmp1, &tmp1, &tmp2) != BIG_OK)
+ goto clean10;
+
+ if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.p)) != BIG_OK)
+ goto clean10;
+
+ if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK)
+ goto clean10;
+
+ if (big_cmp_abs(&tmp1, &(dsakey.r)) == 0)
+ rv = CKR_OK;
+ else
+ rv = CKR_SIGNATURE_INVALID;
+
+clean10:
+ big_finish(&tmp3);
+clean9:
+ big_finish(&tmp2);
+clean8:
+ big_finish(&tmp1);
+clean7:
+ big_finish(&msg);
+clean6:
+ DSA_key_finish(&dsakey);
+clean1:
+ return (rv);
+}
+
+/*
+ * DSA Power-On SelfTest(s).
+ */
+CK_RV
+soft_fips_dsa_post(void)
+{
+ /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */
+ static uint8_t dsa_P[] = {
+ 0x80, 0xb0, 0xd1, 0x9d, 0x6e, 0xa4, 0xf3, 0x28,
+ 0x9f, 0x24, 0xa9, 0x8a, 0x49, 0xd0, 0x0c, 0x63,
+ 0xe8, 0x59, 0x04, 0xf9, 0x89, 0x4a, 0x5e, 0xc0,
+ 0x6d, 0xd2, 0x67, 0x6b, 0x37, 0x81, 0x83, 0x0c,
+ 0xfe, 0x3a, 0x8a, 0xfd, 0xa0, 0x3b, 0x08, 0x91,
+ 0x1c, 0xcb, 0xb5, 0x63, 0xb0, 0x1c, 0x70, 0xd0,
+ 0xae, 0xe1, 0x60, 0x2e, 0x12, 0xeb, 0x54, 0xc7,
+ 0xcf, 0xc6, 0xcc, 0xae, 0x97, 0x52, 0x32, 0x63,
+ 0xd3, 0xeb, 0x55, 0xea, 0x2f, 0x4c, 0xd5, 0xd7,
+ 0x3f, 0xda, 0xec, 0x49, 0x27, 0x0b, 0x14, 0x56,
+ 0xc5, 0x09, 0xbe, 0x4d, 0x09, 0x15, 0x75, 0x2b,
+ 0xa3, 0x42, 0x0d, 0x03, 0x71, 0xdf, 0x0f, 0xf4,
+ 0x0e, 0xe9, 0x0c, 0x46, 0x93, 0x3d, 0x3f, 0xa6,
+ 0x6c, 0xdb, 0xca, 0xe5, 0xac, 0x96, 0xc8, 0x64,
+ 0x5c, 0xec, 0x4b, 0x35, 0x65, 0xfc, 0xfb, 0x5a,
+ 0x1b, 0x04, 0x1b, 0xa1, 0x0e, 0xfd, 0x88, 0x15
+ };
+
+ static uint8_t dsa_Q[] = {
+ 0xad, 0x22, 0x59, 0xdf, 0xe5, 0xec, 0x4c, 0x6e,
+ 0xf9, 0x43, 0xf0, 0x4b, 0x2d, 0x50, 0x51, 0xc6,
+ 0x91, 0x99, 0x8b, 0xcf
+ };
+
+ static uint8_t dsa_G[] = {
+ 0x78, 0x6e, 0xa9, 0xd8, 0xcd, 0x4a, 0x85, 0xa4,
+ 0x45, 0xb6, 0x6e, 0x5d, 0x21, 0x50, 0x61, 0xf6,
+ 0x5f, 0xdf, 0x5c, 0x7a, 0xde, 0x0d, 0x19, 0xd3,
+ 0xc1, 0x3b, 0x14, 0xcc, 0x8e, 0xed, 0xdb, 0x17,
+ 0xb6, 0xca, 0xba, 0x86, 0xa9, 0xea, 0x51, 0x2d,
+ 0xc1, 0xa9, 0x16, 0xda, 0xf8, 0x7b, 0x59, 0x8a,
+ 0xdf, 0xcb, 0xa4, 0x67, 0x00, 0x44, 0xea, 0x24,
+ 0x73, 0xe5, 0xcb, 0x4b, 0xaf, 0x2a, 0x31, 0x25,
+ 0x22, 0x28, 0x3f, 0x16, 0x10, 0x82, 0xf7, 0xeb,
+ 0x94, 0x0d, 0xdd, 0x09, 0x22, 0x14, 0x08, 0x79,
+ 0xba, 0x11, 0x0b, 0xf1, 0xff, 0x2d, 0x67, 0xac,
+ 0xeb, 0xb6, 0x55, 0x51, 0x69, 0x97, 0xa7, 0x25,
+ 0x6b, 0x9c, 0xa0, 0x9b, 0xd5, 0x08, 0x9b, 0x27,
+ 0x42, 0x1c, 0x7a, 0x69, 0x57, 0xe6, 0x2e, 0xed,
+ 0xa9, 0x5b, 0x25, 0xe8, 0x1f, 0xd2, 0xed, 0x1f,
+ 0xdf, 0xe7, 0x80, 0x17, 0xba, 0x0d, 0x4d, 0x38
+ };
+
+ /*
+ * DSA Known Random Values (known random key block is 160-bits)
+ * and (known random signature block is 160-bits).
+ */
+ static uint8_t dsa_known_random_key_block[] = {
+ "This is DSA RNG key!"
+ };
+
+ static uint8_t dsa_known_random_signature_block[] = {
+ "Random DSA Signature"
+ };
+
+ /* DSA Known Digest (160-bits) */
+ static uint8_t dsa_known_digest[] = {
+ "DSA Signature Digest"
+ };
+
+ /* DSA Known Signature (320-bits). */
+ static uint8_t dsa_known_signature[] = {
+ 0x25, 0x7c, 0x3a, 0x79, 0x32, 0x45, 0xb7, 0x32,
+ 0x70, 0xca, 0x62, 0x63, 0x2b, 0xf6, 0x29, 0x2c,
+ 0x22, 0x2a, 0x03, 0xce, 0x65, 0x02, 0x72, 0x5a,
+ 0x66, 0x29, 0xcf, 0x56, 0xe6, 0xdf, 0xb0, 0xcc,
+ 0x53, 0x72, 0x56, 0x70, 0x92, 0xb5, 0x45, 0x75
+
+ };
+
+ /* DSA variables. */
+ DSAParams_t dsa_params;
+ CK_RV rv = CKR_OK;
+
+ fips_key_t dsa_private_key;
+ fips_key_t dsa_public_key;
+ uint8_t dsa_computed_signature[FIPS_DSA_SIGNATURE_LENGTH];
+
+ dsa_params.prime = dsa_P;
+ dsa_params.prime_len = FIPS_DSA_PRIME_LENGTH;
+ dsa_params.subprime = dsa_Q;
+ dsa_params.subprime_len = FIPS_DSA_SUBPRIME_LENGTH;
+ dsa_params.base = dsa_G;
+ dsa_params.base_len = FIPS_DSA_BASE_LENGTH;
+
+
+ /* Generate a DSA public/private key pair. */
+ rv = fips_dsa_genkey_pair(&dsa_params, &dsa_public_key,
+ &dsa_private_key, dsa_known_random_key_block,
+ FIPS_DSA_SEED_LENGTH);
+
+ if (rv != CKR_OK)
+ return (CKR_DEVICE_ERROR);
+
+ /*
+ * DSA Known Answer Signature Test
+ */
+
+ /* Perform DSA signature process. */
+ rv = fips_dsa_digest_sign(&dsa_params, &dsa_private_key,
+ dsa_known_digest, FIPS_DSA_DIGEST_LENGTH,
+ dsa_computed_signature, dsa_known_random_signature_block,
+ FIPS_DSA_SEED_LENGTH);
+
+ if ((rv != CKR_OK) ||
+ (memcmp(dsa_computed_signature, dsa_known_signature,
+ FIPS_DSA_SIGNATURE_LENGTH) != 0)) {
+ return (rv);
+ }
+
+ /*
+ * DSA Known Answer Verification Test
+ */
+
+ /* Perform DSA verification process. */
+ rv = fips_dsa_verify(&dsa_params, &dsa_public_key,
+ dsa_known_digest, dsa_computed_signature);
+
+ if (rv != CKR_OK)
+ return (CKR_DEVICE_ERROR);
+ else
+ return (CKR_OK);
+
+}
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPost.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPost.c
new file mode 100644
index 0000000000..e9bc272eee
--- /dev/null
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPost.c
@@ -0,0 +1,159 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <security/cryptoki.h>
+#include <sys/sha1.h>
+#include <sys/sha2.h>
+#include "softMAC.h"
+#define _AES_FIPS_POST
+#define _DES_FIPS_POST
+#include "softCrypt.h"
+#define _RSA_FIPS_POST
+#include <rsa_impl.h>
+#include <sha1_impl.h>
+#include <sha2_impl.h>
+#include <fips_random.h>
+
+
+extern int fips_ecdsa_post(void);
+extern CK_RV soft_fips_dsa_post(void);
+
+
+/*
+ * FIPS Power-on SelfTest for the supported FIPS ciphers and
+ * components.
+ */
+CK_RV
+soft_fips_post(void)
+{
+ CK_RV rv;
+
+ /*
+ * SHA-1 Power-On SelfTest.
+ *
+ * 1. SHA-1 POST
+ * 2. HMAC SHA-1 POST
+ */
+ rv = fips_sha1_post();
+ if (rv != CKR_OK)
+ return (rv);
+
+ /*
+ * SHA-2 Power-On SelfTest.
+ *
+ * 1. SHA-256 POST
+ * 2. SHA-384 POST
+ * 3. SHA-512 POST
+ * 4. HMAC SHA-256 POST
+ * 5. HMAC SHA-384 POST
+ * 6. HMAC SHA-512 POST
+ */
+ rv = fips_sha2_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+
+ /*
+ * Triple DES Power-On SelfTest.
+ *
+ * 1. DES3 ECB Encryption/Decryption
+ * 2. DES3 CBC Encryption/Decryption
+ */
+ rv = fips_des3_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /* AES Power-On SelfTest for 128-bit key. */
+ rv = fips_aes_post(FIPS_AES_128_KEY_SIZE);
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /* AES Power-On SelfTest for 192-bit key. */
+ rv = fips_aes_post(FIPS_AES_192_KEY_SIZE);
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /* AES Power-On SelfTest for 256-bit key. */
+ rv = fips_aes_post(FIPS_AES_256_KEY_SIZE);
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /*
+ * ECDSA Power-Up SelfTest
+ *
+ * 1. ECC Signature
+ * 2. ECC Verification
+ */
+ rv = fips_ecdsa_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /*
+ * RSA Power-On SelfTest
+ *
+ * 1. RSA Encryption
+ * 2. RSA Decryption
+ * 3. RSA SHA-1 Sign/Verify
+ * 4. RSA SHA-256 Sign/Verify
+ * 5. RSA SHA-384 Sign/Verify
+ * 6. RSA SHA-512 Sign/Verify
+ *
+ */
+ rv = fips_rsa_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /*
+ * DSA Power-On SelfTest
+ *
+ * 1. DSA Sign on SHA-1 digest
+ * 2. DSA Verification
+ */
+ rv = soft_fips_dsa_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /* RNG Power-On SelfTest. */
+ rv = fips_rng_post();
+
+ if (rv != CKR_OK)
+ return (rv);
+
+ /* Passed Power-On SelfTest. */
+ return (CKR_OK);
+}
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPostUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPostUtil.c
new file mode 100644
index 0000000000..5c9ab5c6d8
--- /dev/null
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softFipsPostUtil.c
@@ -0,0 +1,178 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/sysmacros.h>
+#include <sys/sha1.h>
+#define _SHA2_IMPL
+#include <sys/sha2.h>
+#include <sys/crypto/common.h>
+#include <modes/modes.h>
+#include <bignum.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <security/cryptoki.h>
+#include <cryptoutil.h>
+#include "softCrypt.h"
+#include "softGlobal.h"
+#include "softRSA.h"
+#include "softDSA.h"
+#include "softRandom.h"
+#include "softOps.h"
+#include "softMAC.h"
+#include <fips_post.h>
+
+#define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */
+#define MAX_ECKEY_LEN 72
+
+
+/*
+ * FIPS 140-2 pairwise consistency check utilized to validate key pair.
+ *
+ * This function returns
+ * CKR_OK if pairwise consistency check passed
+ * CKR_GENERAL_ERROR if pairwise consistency check failed
+ * other error codes if paiswise consistency check could not be
+ * performed, for example, CKR_HOST_MEMORY.
+ *
+ * Key type Mechanism type
+ * --------------------------------
+ *
+ * For sign/verify: CKK_RSA => CKM_SHA1_RSA_PKCS
+ * CKK_DSA => CKM_DSA_SHA1
+ * CKK_EC => CKM_ECDSA_SHA1
+ * others => CKM_INVALID_MECHANISM
+ *
+ * None of these mechanisms has a parameter.
+ */
+CK_RV
+fips_pairwise_check(soft_session_t *session_p,
+ soft_object_t *publicKey, soft_object_t *privateKey,
+ CK_KEY_TYPE keyType)
+{
+
+ CK_MECHANISM mech = {0, NULL, 0};
+ uchar_t modulus[MAX_KEY_ATTR_BUFLEN];
+ uint32_t modulus_len = sizeof (modulus);
+ boolean_t can_sign_verify = B_FALSE;
+ CK_RV rv;
+
+ /* Variables used for Signature/Verification functions. */
+ /* always uses SHA-1 digest */
+ unsigned char *known_digest = (unsigned char *)"OpenSolarisCommunity";
+ unsigned char *signature;
+ CK_ULONG signature_length;
+
+ if (keyType == CKK_RSA) {
+ /* Get modulus length of private key. */
+ rv = soft_get_private_value(privateKey, CKA_MODULUS,
+ modulus, &modulus_len);
+ if (rv != CKR_OK) {
+ return (CKR_DEVICE_ERROR);
+ }
+ }
+
+ /*
+ * Pairwise Consistency Check of Sign/Verify
+ */
+
+ /* Check to see if key object supports signature. */
+ can_sign_verify = (privateKey->bool_attr_mask & SIGN_BOOL_ON);
+
+ if (can_sign_verify) {
+ /* Determine length of signature. */
+ switch (keyType) {
+ case CKK_RSA:
+ signature_length = modulus_len;
+ mech.mechanism = CKM_SHA1_RSA_PKCS;
+ break;
+
+ case CKK_DSA:
+ signature_length = FIPS_DSA_SIGNATURE_LENGTH;
+ mech.mechanism = CKM_DSA_SHA1;
+ break;
+
+ case CKK_EC:
+ signature_length = MAX_ECKEY_LEN * 2;
+ mech.mechanism = CKM_ECDSA_SHA1;
+ break;
+
+ default:
+ return (CKR_DEVICE_ERROR);
+ }
+
+ /* Allocate space for signature data. */
+ signature = (unsigned char *) calloc(1, signature_length);
+ if (signature == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ /* Sign the known hash using the private key. */
+ rv = soft_sign_init(session_p, &mech, privateKey);
+ if (rv != CKR_OK) {
+ free(signature);
+ return (rv);
+ }
+
+ rv = soft_sign(session_p, known_digest, PAIRWISE_DIGEST_LENGTH,
+ signature, &signature_length);
+ if (rv != CKR_OK) {
+ free(signature);
+ return (rv);
+ }
+
+ /* Verify the known hash using the public key. */
+ rv = soft_verify_init(session_p, &mech, publicKey);
+ if (rv != CKR_OK) {
+ free(signature);
+ return (rv);
+ }
+
+ rv = soft_verify(session_p, known_digest,
+ PAIRWISE_DIGEST_LENGTH, signature,
+ signature_length);
+
+ /* Free signature data. */
+ free(signature);
+ if ((rv == CKR_SIGNATURE_LEN_RANGE) ||
+ (rv == CKR_SIGNATURE_INVALID)) {
+ return (CKR_GENERAL_ERROR);
+ }
+
+ if (rv != CKR_OK) {
+ return (rv);
+ }
+ }
+
+ return (CKR_OK);
+}
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c
index 0152827dbb..2df2a11926 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c
@@ -129,6 +129,9 @@ ses_to_be_freed_list_t ses_delay_freed;
/* protects softtoken_initialized and access to C_Initialize/C_Finalize */
pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER;
+/* fips mode setting */
+int softtoken_fips_mode = CRYPTO_FIPS_MODE_DISABLED;
+
static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved);
static void softtoken_init();
static void softtoken_fini();
@@ -275,6 +278,28 @@ C_Initialize(CK_VOID_PTR pInitArgs)
ses_delay_freed.first = NULL;
ses_delay_freed.last = NULL;
+ /*
+ * Perform POST when fips mode is enabled.
+ */
+ if ((rv = get_fips_mode(&softtoken_fips_mode)) == CKR_OK) {
+ if (softtoken_fips_mode == CRYPTO_FIPS_MODE_ENABLED) {
+ rv = soft_fips_post();
+ }
+ }
+
+ if (rv != CKR_OK) {
+ (void) pthread_mutex_destroy(
+ &ses_delay_freed.ses_to_be_free_mutex);
+ (void) pthread_mutex_destroy(
+ &obj_delay_freed.obj_to_be_free_mutex);
+ (void) pthread_mutex_destroy(&soft_slot.keystore_mutex);
+ (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
+ (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
+ (void) soft_destroy_token_session();
+ (void) pthread_mutex_unlock(&soft_giant_mutex);
+ return (CKR_FUNCTION_FAILED);
+ }
+
softtoken_pid = initialize_pid;
softtoken_initialized = B_TRUE;
(void) pthread_mutex_unlock(&soft_giant_mutex);
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGlobal.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGlobal.h
index bbb4d73152..a9cb8ab446 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGlobal.h
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGlobal.h
@@ -41,6 +41,7 @@ extern pthread_mutex_t soft_giant_mutex;
extern struct slot soft_slot;
extern struct obj_to_be_freed_list obj_delay_freed;
extern struct ses_to_be_freed_list ses_delay_freed;
+extern int softtoken_fips_mode;
#define SOFTTOKEN_SLOTID 1
@@ -70,6 +71,8 @@ extern struct ses_to_be_freed_list ses_delay_freed;
CKF_DUAL_CRYPTO_OPERATIONS|\
CKF_TOKEN_INITIALIZED
+extern CK_RV soft_fips_post(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c
index 0c2c005250..778f63d3e6 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c
@@ -52,6 +52,9 @@
#define local_min(a, b) ((a) < (b) ? (a) : (b))
+extern CK_RV fips_pairwise_check(soft_session_t *,
+ soft_object_t *, soft_object_t *, CK_KEY_TYPE);
+
static CK_RV
soft_pkcs12_pbe(soft_session_t *, CK_MECHANISM_PTR, soft_object_t *);
@@ -513,6 +516,33 @@ soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
soft_delete_object(session_p, private_key,
B_FALSE, B_FALSE);
}
+ return (rv);
+ }
+
+ /*
+ * FIPS 140-2 pairwise consistency check utilized to
+ * validate key pair
+ */
+ if ((key_type == CKK_RSA) || (key_type == CKK_DSA) ||
+ (key_type == CKK_EC)) {
+ if (softtoken_fips_mode == CRYPTO_FIPS_MODE_ENABLED) {
+ rv = fips_pairwise_check(session_p, public_key,
+ private_key, key_type);
+ if (rv != CKR_OK) {
+ if (IS_TOKEN_OBJECT(public_key)) {
+ soft_delete_token_object(public_key,
+ B_FALSE, B_FALSE);
+ soft_delete_token_object(private_key,
+ B_FALSE, B_FALSE);
+ } else {
+ soft_delete_object(session_p,
+ public_key, B_FALSE, B_FALSE);
+ soft_delete_object(session_p,
+ private_key, B_FALSE, B_FALSE);
+ }
+ return (rv);
+ }
+ }
}
if (IS_TOKEN_OBJECT(public_key)) {
@@ -524,6 +554,7 @@ soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
if (rv != CKR_OK) {
soft_delete_token_object(public_key, B_FALSE, B_FALSE);
soft_delete_token_object(private_key, B_FALSE, B_FALSE);
+ return (rv);
}
}
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 84c15a6db2..a4b094f824 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -481,9 +481,9 @@ MD4_OBJS += md4.o md4_mod.o
MD5_OBJS += md5.o md5_mod.o
-SHA1_OBJS += sha1.o sha1_mod.o
+SHA1_OBJS += sha1.o sha1_mod.o fips_sha1_util.o
-SHA2_OBJS += sha2.o sha2_mod.o
+SHA2_OBJS += sha2.o sha2_mod.o fips_sha2_util.o
IPGPC_OBJS += classifierddi.o classifier.o filters.o trie.o table.o \
ba_table.o
@@ -1467,7 +1467,7 @@ DPROV_OBJS += dprov.o
DCA_OBJS += dca.o dca_3des.o dca_debug.o dca_dsa.o dca_kstat.o dca_rng.o \
dca_rsa.o
-AESPROV_OBJS += aes.o aes_impl.o aes_modes.o
+AESPROV_OBJS += aes.o aes_impl.o aes_modes.o fips_aes_util.o
ARCFOURPROV_OBJS += arcfour.o arcfour_crypt.o
@@ -1478,11 +1478,11 @@ ECCPROV_OBJS += ecc.o ec.o ec2_163.o ec2_mont.o ecdecode.o ecl_mult.o \
ecp_jm.o ec2_233.o ecl_curve.o ecp_224.o ecp_aff.o \
ecp_mont.o ec2_aff.o ec_naf.o ecl_gf.o ecp_256.o mp_gf2m.o \
mpi.o mplogic.o mpmontg.o mpprime.o oid.o \
- secitem.o ec2_test.o ecp_test.o
+ secitem.o ec2_test.o ecp_test.o fips_ecc_util.o
-RSAPROV_OBJS += rsa.o rsa_impl.o
+RSAPROV_OBJS += rsa.o rsa_impl.o fips_rsa_util.o
-SWRANDPROV_OBJS += swrand.o
+SWRANDPROV_OBJS += swrand.o fips_random_util.o
#
# kernel SSL
@@ -1601,7 +1601,7 @@ KGSS_KRB5_OBJS += krb5mech.o \
$(CRYPTO_OLD) \
$(CRYPTO_RAW) $(K5_KRB) $(K5_OS)
-DES_OBJS += des_crypt.o des_impl.o des_ks.o des_soft.o
+DES_OBJS += des_crypt.o des_impl.o des_ks.o des_soft.o fips_des_util.o
DLBOOT_OBJS += bootparam_xdr.o nfs_dlinet.o scan.o
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index a5d08d30df..a3290cffa1 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -56,6 +56,10 @@ $(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/ecc/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/fips/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/modes/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1452,6 +1456,9 @@ $(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/blowfish/%.c
$(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/ecc/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/fips/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/modes/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/crypto/api/kcf_random.c b/usr/src/uts/common/crypto/api/kcf_random.c
index e24c28f171..ec0410a1fe 100644
--- a/usr/src/uts/common/crypto/api/kcf_random.c
+++ b/usr/src/uts/common/crypto/api/kcf_random.c
@@ -667,10 +667,13 @@ punt:
if (tempout[i] != rmp->rm_mag.rm_previous[i])
break;
}
- if (i == HASHSIZE/BYTES_IN_WORD)
+ if (i == HASHSIZE/BYTES_IN_WORD) {
cmn_err(CE_WARN, "kcf_random: The value of 160-bit "
"block random bytes are same as the previous "
"one.\n");
+ /* discard random bytes and return error */
+ return (EIO);
+ }
bcopy(tempout, rmp->rm_mag.rm_previous,
HASHSIZE);
diff --git a/usr/src/uts/common/crypto/core/kcf.c b/usr/src/uts/common/crypto/core/kcf.c
index a7e98ba0d3..9e11129786 100644
--- a/usr/src/uts/common/crypto/core/kcf.c
+++ b/usr/src/uts/common/crypto/core/kcf.c
@@ -61,6 +61,7 @@ int kcf_frmwrk_debug = 0;
kmutex_t kcf_dh_lock;
door_handle_t kcf_dh = NULL;
+uint32_t global_fips140_mode; /* FIPS140 enable/disable flag */
static struct modlmisc modlmisc = {
&mod_miscops, "Kernel Crypto Framework"
@@ -117,6 +118,17 @@ _fini(void)
}
/*
+ * Return the FIPS140 mode status:
+ * FIPS140_MODE_DISABLED (0)
+ * FIPS140_MODE_ENABLED (1)
+ */
+int
+kcf_get_fips140_mode(void)
+{
+ return (global_fips140_mode);
+}
+
+/*
* Return a pointer to the modctl structure of the
* provider's module.
*/
diff --git a/usr/src/uts/common/crypto/io/aes.c b/usr/src/uts/common/crypto/io/aes.c
index 5f0e8f4c75..c40a733327 100644
--- a/usr/src/uts/common/crypto/io/aes.c
+++ b/usr/src/uts/common/crypto/io/aes.c
@@ -38,6 +38,8 @@
#include <sys/sysmacros.h>
#include <sys/strsun.h>
#include <modes/modes.h>
+#define _AES_FIPS_POST
+#define _AES_IMPL
#include <aes/aes_impl.h>
extern struct mod_ops mod_cryptoops;
@@ -57,19 +59,6 @@ static struct modlinkage modlinkage = {
};
/*
- * CSPI information (entry points, provider info, etc.)
- */
-typedef enum aes_mech_type {
- AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */
- AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */
- AES_CBC_PAD_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC_PAD */
- AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */
- AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */
- AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */
- AES_GMAC_MECH_INFO_TYPE /* SUN_CKM_AES_GMAC */
-} aes_mech_type_t;
-
-/*
* The following definitions are to keep EXPORT_SRC happy.
*/
#ifndef AES_MIN_KEY_BYTES
@@ -1557,3 +1546,32 @@ aes_mac_verify_atomic(crypto_provider_handle_t provider,
return (aes_decrypt_atomic(provider, session_id, &gcm_mech,
key, mac, &null_crypto_data, template, req));
}
+
+/*
+ * AES Power-Up Self-Test
+ */
+void
+aes_POST(int *rc)
+{
+
+ int ret;
+
+ /* AES Power-Up Self-Test for 128-bit key. */
+ ret = fips_aes_post(FIPS_AES_128_KEY_SIZE);
+
+ if (ret != CRYPTO_SUCCESS)
+ goto out;
+
+ /* AES Power-Up Self-Test for 192-bit key. */
+ ret = fips_aes_post(FIPS_AES_192_KEY_SIZE);
+
+ if (ret != CRYPTO_SUCCESS)
+ goto out;
+
+ /* AES Power-Up Self-Test for 256-bit key. */
+ ret = fips_aes_post(FIPS_AES_256_KEY_SIZE);
+
+out:
+ *rc = ret;
+
+}
diff --git a/usr/src/uts/common/crypto/io/cryptoadm.c b/usr/src/uts/common/crypto/io/cryptoadm.c
index 9f895a173c..8789e01776 100644
--- a/usr/src/uts/common/crypto/io/cryptoadm.c
+++ b/usr/src/uts/common/crypto/io/cryptoadm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -61,6 +61,10 @@ static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t,
uint_t, uint32_t, int);
+
+kmutex_t fips140_mode_lock;
+extern uint32_t global_fips140_mode;
+
/*
* Module linkage.
*/
@@ -170,6 +174,7 @@ cryptoadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
return (DDI_FAILURE);
}
+ mutex_init(&fips140_mode_lock, NULL, MUTEX_DEFAULT, NULL);
cryptoadm_dip = dip;
return (DDI_SUCCESS);
@@ -802,6 +807,53 @@ out2:
return (error);
}
+/*
+ * This function enables/disables FIPS140 mode or gets the current
+ * FIPS140 mode status.
+ *
+ * Enable or disable FIPS140 ioctl operation name:
+ * FIPS140_ENABLE or FIPS140_DISABLE
+ *
+ * Global fips140 mode status in kernel:
+ * FIPS140_MODE_ENABLED or FIPS140_MODE_DISABLED
+ */
+/* ARGSUSED */
+static int
+fips140_actions(dev_t dev, caddr_t arg, int mode, int *rval, int cmd)
+{
+ crypto_fips140_t fips140_info;
+ uint32_t rv = CRYPTO_SUCCESS;
+ int error = 0;
+
+ if (copyin(arg, &fips140_info, sizeof (crypto_fips140_t)) != 0)
+ return (EFAULT);
+
+ switch (cmd) {
+ case CRYPTO_FIPS140_STATUS:
+ fips140_info.fips140_status = global_fips140_mode;
+ break;
+ case CRYPTO_FIPS140_SET:
+ mutex_enter(&fips140_mode_lock);
+ if (fips140_info.fips140_op == FIPS140_ENABLE)
+ global_fips140_mode = FIPS140_MODE_ENABLED;
+ else if (fips140_info.fips140_op == FIPS140_DISABLE)
+ global_fips140_mode = FIPS140_MODE_DISABLED;
+ else {
+ rv = CRYPTO_ARGUMENTS_BAD;
+ error = CRYPTO_FAILED;
+ }
+ mutex_exit(&fips140_mode_lock);
+ break;
+ }
+
+ fips140_info.fips140_return_value = rv;
+
+ if (copyout(&fips140_info, arg, sizeof (crypto_fips140_t)) != 0)
+ error = EFAULT;
+
+ return (error);
+}
+
static int
cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
int *rval)
@@ -818,6 +870,7 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
case CRYPTO_POOL_WAIT:
case CRYPTO_POOL_RUN:
case CRYPTO_LOAD_DOOR:
+ case CRYPTO_FIPS140_SET:
if ((error = drv_priv(c)) != 0)
return (error);
default:
@@ -886,6 +939,18 @@ cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
case CRYPTO_LOAD_DOOR:
return (load_door(dev, ARG, mode, rval));
+ case CRYPTO_FIPS140_STATUS:
+ return (fips140_actions(dev, ARG, mode, rval, cmd));
+ case CRYPTO_FIPS140_SET: {
+ int err;
+
+ err = fips140_actions(dev, ARG, mode, rval, cmd);
+ if (audit_active)
+ audit_cryptoadm(CRYPTO_FIPS140_SET, NULL, NULL,
+ 0, 0, 0, err);
+ return (err);
}
+ }
+
return (EINVAL);
}
diff --git a/usr/src/uts/common/crypto/io/ecc.c b/usr/src/uts/common/crypto/io/ecc.c
index 55d48db743..1a9211295d 100644
--- a/usr/src/uts/common/crypto/io/ecc.c
+++ b/usr/src/uts/common/crypto/io/ecc.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/param.h>
@@ -32,6 +30,7 @@
#include <sys/ddi.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/impl.h>
+#include <sys/crypto/ioctladmin.h>
#include <sys/sysmacros.h>
#include <sys/strsun.h>
#include <sys/sha1.h>
@@ -43,8 +42,8 @@
#include <sys/kmem.h>
#include <sys/kstat.h>
-#include "des_impl.h"
-#include "ecc_impl.h"
+#include <des/des_impl.h>
+#include <ecc/ecc_impl.h>
#define CKD_NULL 0x00000001
@@ -232,6 +231,10 @@ static void ecc_free_context(crypto_ctx_t *);
static void free_ecparams(ECParams *, boolean_t);
static void free_ecprivkey(ECPrivateKey *);
+static int fips_pairwise_check(ECPrivateKey *);
+extern int fips_ecdsa_post(void);
+
+
int
_init(void)
{
@@ -1180,6 +1183,13 @@ ecc_nostore_key_generate_pair(crypto_provider_handle_t provider,
bcopy(privKey->publicValue.data, point, xylen);
pub_out_template[point_idx].oa_value_len = xylen;
+ if ((rv = kcf_get_fips140_mode()) == FIPS140_MODE_ENABLED) {
+ /* Pair-wise consistency test */
+ if ((rv = fips_pairwise_check(privKey)) != CRYPTO_SUCCESS)
+ cmn_err(CE_WARN, "ecc: fips_pairwise_check() "
+ "failed (0x%x).", rv);
+ }
+
out:
free_ecprivkey(privKey);
free_ecparams(ecparams, B_TRUE);
@@ -1340,3 +1350,73 @@ free_ecprivkey(ECPrivateKey *key)
SECITEM_FreeItem(&key->version, B_FALSE);
kmem_free(key, sizeof (ECPrivateKey));
}
+
+/*
+ * Pair-wise Consistency Test
+ */
+static int
+fips_pairwise_check(ECPrivateKey *ecdsa_private_key)
+{
+
+ SECItem signature_item;
+ SECItem digest_item;
+ uchar_t signed_data[EC_MAX_SIG_LEN];
+ uchar_t sha1[SHA1_DIGEST_SIZE];
+ ECPublicKey ecdsa_public_key;
+ SHA1_CTX *sha1_context;
+ int rv;
+ static uint8_t msg[] = {
+ "OpenSolarisCommunity"
+ };
+
+ /* construct public key from private key. */
+ if ((EC_CopyParams(ecdsa_private_key->ecParams.arena,
+ &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams))
+ != SECSuccess)
+ return (CRYPTO_FAILED);
+
+ ecdsa_public_key.publicValue = ecdsa_private_key->publicValue;
+
+ if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
+ KM_SLEEP)) == NULL)
+ return (CRYPTO_HOST_MEMORY);
+
+ SHA1Init(sha1_context);
+ SHA1Update(sha1_context, msg, SHA1_DIGEST_SIZE);
+ SHA1Final(sha1, sha1_context);
+
+ digest_item.data = sha1;
+ digest_item.len = SHA1_DIGEST_SIZE;
+ signature_item.data = signed_data;
+ signature_item.len = sizeof (signed_data);
+
+ if ((ECDSA_SignDigest(ecdsa_private_key, &signature_item,
+ &digest_item, 0)) != SECSuccess) {
+ rv = CRYPTO_FAILED;
+ goto loser;
+ }
+
+ if (ECDSA_VerifyDigest(&ecdsa_public_key, &signature_item,
+ &digest_item, 0) != SECSuccess) {
+ rv = CRYPTO_SIGNATURE_INVALID;
+ } else {
+ rv = CRYPTO_SUCCESS;
+ }
+
+loser:
+ kmem_free(sha1_context, sizeof (SHA1_CTX));
+ return (rv);
+
+}
+
+
+/*
+ * ECC Power-Up Self-Test
+ */
+void
+ecc_POST(int *rc)
+{
+
+ *rc = fips_ecdsa_post();
+
+}
diff --git a/usr/src/uts/common/crypto/io/rsa.c b/usr/src/uts/common/crypto/io/rsa.c
index 83d2fbfef1..c762fea028 100644
--- a/usr/src/uts/common/crypto/io/rsa.c
+++ b/usr/src/uts/common/crypto/io/rsa.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* RSA provider for the Kernel Cryptographic Framework (KCF)
*/
@@ -39,10 +37,14 @@
#include <sys/strsun.h>
#include <sys/md5.h>
#include <sys/sha1.h>
+#define _SHA2_IMPL
#include <sys/sha2.h>
#include <sys/random.h>
#include <sys/crypto/impl.h>
-#include "rsa_impl.h"
+#include <sha1/sha1_impl.h>
+#include <sha2/sha2_impl.h>
+#define _RSA_FIPS_POST
+#include <rsa/rsa_impl.h>
extern struct mod_ops mod_cryptoops;
@@ -1708,3 +1710,14 @@ rsa_verify_recover_atomic(crypto_provider_handle_t provider,
return (rsa_verify_recover_common(mechanism->cm_type, key,
signature, data, crypto_kmflag(req)));
}
+
+/*
+ * RSA Power-Up Self-Test
+ */
+void
+rsa_POST(int *rc)
+{
+
+ *rc = fips_rsa_post();
+
+}
diff --git a/usr/src/uts/common/crypto/io/sha1_mod.c b/usr/src/uts/common/crypto/io/sha1_mod.c
index b6c8454901..bce4bc3d98 100644
--- a/usr/src/uts/common/crypto/io/sha1_mod.c
+++ b/usr/src/uts/common/crypto/io/sha1_mod.c
@@ -34,6 +34,7 @@
#include <sys/sysmacros.h>
#include <sys/sha1.h>
+#include <sha1/sha1_impl.h>
/*
* The sha1 module is created with two modlinkages:
@@ -58,39 +59,6 @@ static struct modlinkage modlinkage = {
MODREV_1, &modlmisc, &modlcrypto, NULL
};
-/*
- * CSPI information (entry points, provider info, etc.)
- */
-
-typedef enum sha1_mech_type {
- SHA1_MECH_INFO_TYPE, /* SUN_CKM_SHA1 */
- SHA1_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA1_HMAC */
- SHA1_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA1_HMAC_GENERAL */
-} sha1_mech_type_t;
-
-#define SHA1_DIGEST_LENGTH 20 /* SHA1 digest length in bytes */
-#define SHA1_HMAC_BLOCK_SIZE 64 /* SHA1-HMAC block size */
-#define SHA1_HMAC_MIN_KEY_LEN 1 /* SHA1-HMAC min key length in bytes */
-#define SHA1_HMAC_MAX_KEY_LEN INT_MAX /* SHA1-HMAC max key length in bytes */
-#define SHA1_HMAC_INTS_PER_BLOCK (SHA1_HMAC_BLOCK_SIZE/sizeof (uint32_t))
-
-/*
- * Context for SHA1 mechanism.
- */
-typedef struct sha1_ctx {
- sha1_mech_type_t sc_mech_type; /* type of context */
- SHA1_CTX sc_sha1_ctx; /* SHA1 context */
-} sha1_ctx_t;
-
-/*
- * Context for SHA1-HMAC and SHA1-HMAC-GENERAL mechanisms.
- */
-typedef struct sha1_hmac_ctx {
- sha1_mech_type_t hc_mech_type; /* type of context */
- uint32_t hc_digest_len; /* digest len in bytes */
- SHA1_CTX hc_icontext; /* inner SHA1 context */
- SHA1_CTX hc_ocontext; /* outer SHA1 context */
-} sha1_hmac_ctx_t;
/*
* Macros to access the SHA1 or SHA1-HMAC contexts from a context passed
@@ -1473,3 +1441,14 @@ sha1_free_context(crypto_ctx_t *ctx)
return (CRYPTO_SUCCESS);
}
+
+/*
+ * SHA-1 Power-Up Self-Test
+ */
+void
+sha1_POST(int *rc)
+{
+
+ *rc = fips_sha1_post();
+
+}
diff --git a/usr/src/uts/common/crypto/io/sha2_mod.c b/usr/src/uts/common/crypto/io/sha2_mod.c
index a6cff46faa..13e04719cf 100644
--- a/usr/src/uts/common/crypto/io/sha2_mod.c
+++ b/usr/src/uts/common/crypto/io/sha2_mod.c
@@ -33,6 +33,7 @@
#include <sys/sysmacros.h>
#define _SHA2_IMPL
#include <sys/sha2.h>
+#include <sha2/sha2_impl.h>
/*
* The sha2 module is created with two modlinkages:
@@ -58,28 +59,6 @@ static struct modlinkage modlinkage = {
};
/*
- * CSPI information (entry points, provider info, etc.)
- */
-
-/*
- * Context for SHA2 mechanism.
- */
-typedef struct sha2_ctx {
- sha2_mech_type_t sc_mech_type; /* type of context */
- SHA2_CTX sc_sha2_ctx; /* SHA2 context */
-} sha2_ctx_t;
-
-/*
- * Context for SHA2 HMAC and HMAC GENERAL mechanisms.
- */
-typedef struct sha2_hmac_ctx {
- sha2_mech_type_t hc_mech_type; /* type of context */
- uint32_t hc_digest_len; /* digest len in bytes */
- SHA2_CTX hc_icontext; /* inner SHA2 context */
- SHA2_CTX hc_ocontext; /* outer SHA2 context */
-} sha2_hmac_ctx_t;
-
-/*
* Macros to access the SHA2 or SHA2-HMAC contexts from a context passed
* by KCF to one of the entry points.
*/
@@ -1631,3 +1610,14 @@ sha2_free_context(crypto_ctx_t *ctx)
return (CRYPTO_SUCCESS);
}
+
+/*
+ * SHA-2 Power-Up Self-Test
+ */
+void
+sha2_POST(int *rc)
+{
+
+ *rc = fips_sha2_post();
+
+}
diff --git a/usr/src/uts/common/crypto/io/swrand.c b/usr/src/uts/common/crypto/io/swrand.c
index f519fe3dba..879ca709e6 100644
--- a/usr/src/uts/common/crypto/io/swrand.c
+++ b/usr/src/uts/common/crypto/io/swrand.c
@@ -335,7 +335,6 @@ swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t nonblock)
}
while (len > 0) {
-
/* Check if there is enough entropy */
while (entropy_bits < MINEXTRACTBITS) {
@@ -402,9 +401,13 @@ swrand_get_entropy(uint8_t *ptr, size_t len, boolean_t nonblock)
if (tempout[i] != previous_bytes[i])
break;
}
- if (i == HASHSIZE/BYTES_IN_WORD)
+
+ if (i == HASHSIZE/BYTES_IN_WORD) {
cmn_err(CE_WARN, "swrand: The value of 160-bit block "
"random bytes are same as the previous one.\n");
+ /* discard random bytes and return error */
+ return (EIO);
+ }
bcopy(tempout, previous_bytes, HASHSIZE);
@@ -904,3 +907,14 @@ rnd_handler(void *arg)
mutex_exit(&srndpool_lock);
}
+
+/*
+ * Swrand Power-Up Self-Test
+ */
+void
+swrand_POST(int *rc)
+{
+
+ *rc = fips_rng_post();
+
+}
diff --git a/usr/src/uts/common/des/des_crypt.c b/usr/src/uts/common/des/des_crypt.c
index a64aab7244..a474fd7bb7 100644
--- a/usr/src/uts/common/des/des_crypt.c
+++ b/usr/src/uts/common/des/des_crypt.c
@@ -48,6 +48,7 @@
#include <sys/strsun.h>
#include <sys/note.h>
#include <modes/modes.h>
+#define _DES_FIPS_POST
#include <des/des_impl.h>
/* EXPORT DELETE START */
@@ -96,18 +97,6 @@ static struct modlinkage modlinkage = {
NULL
};
-/*
- * CSPI information (entry points, provider info, etc.)
- */
-typedef enum des_mech_type {
- DES_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES_ECB */
- DES_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES_CBC */
- DES_CFB_MECH_INFO_TYPE, /* SUN_CKM_DES_CFB */
- DES3_ECB_MECH_INFO_TYPE, /* SUN_CKM_DES3_ECB */
- DES3_CBC_MECH_INFO_TYPE, /* SUN_CKM_DES3_CBC */
- DES3_CFB_MECH_INFO_TYPE /* SUN_CKM_DES3_CFB */
-} des_mech_type_t;
-
/* EXPORT DELETE START */
#define DES_MIN_KEY_LEN DES_MINBYTES
@@ -133,6 +122,7 @@ typedef enum des_mech_type {
#define DES3_MAX_KEY_LEN 0
#endif
+
/*
* Mechanism info structure passed to KCF during registration.
*/
@@ -1236,3 +1226,14 @@ des_common_init_ctx(des_ctx_t *des_ctx, crypto_spi_ctx_template_t *template,
return (rv);
}
+
+/*
+ * Triple DES Power-Up Self-Test
+ */
+void
+des_POST(int *rc)
+{
+
+ *rc = fips_des3_post();
+
+}
diff --git a/usr/src/uts/common/sys/crypto/impl.h b/usr/src/uts/common/sys/crypto/impl.h
index 4e04918169..f9d4908717 100644
--- a/usr/src/uts/common/sys/crypto/impl.h
+++ b/usr/src/uts/common/sys/crypto/impl.h
@@ -1396,6 +1396,7 @@ extern int kcf_policy_load_soft_disabled(char *, uint_t, crypto_mech_name_t *,
extern int kcf_policy_load_dev_disabled(char *, uint_t, uint_t,
crypto_mech_name_t *, uint_t *, crypto_mech_name_t **);
extern boolean_t in_soft_config_list(char *);
+extern int kcf_get_fips140_mode(void);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/crypto/ioctladmin.h b/usr/src/uts/common/sys/crypto/ioctladmin.h
index e44986296f..ea66732d3a 100644
--- a/usr/src/uts/common/sys/crypto/ioctladmin.h
+++ b/usr/src/uts/common/sys/crypto/ioctladmin.h
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_CRYPTO_IOCTLADMIN_H
#define _SYS_CRYPTO_IOCTLADMIN_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -104,6 +101,12 @@ typedef struct crypto_load_door {
uint_t ld_did;
} crypto_load_door_t;
+typedef struct crypto_fips140 {
+ uint_t fips140_return_value;
+ uint_t fips140_op;
+ uint_t fips140_status;
+} crypto_fips140_t;
+
#ifdef _KERNEL
#ifdef _SYSCALL32
@@ -117,6 +120,23 @@ typedef struct crypto_get_soft_list32 {
#endif /* _SYSCALL32 */
#endif /* _KERNEL */
+/*
+ * FIPS140 ioctl operations
+ */
+enum {
+ FIPS140_STATUS, /* get current fips140 mode */
+ FIPS140_ENABLE, /* enable fips140 mode */
+ FIPS140_DISABLE /* disable fips140 mode */
+};
+
+/*
+ * FIPS140 Mode Status
+ */
+enum {
+ FIPS140_MODE_DISABLED,
+ FIPS140_MODE_ENABLED
+};
+
#define CRYPTO_GET_VERSION CRYPTOADMIN(1)
#define CRYPTO_GET_DEV_LIST CRYPTOADMIN(2)
#define CRYPTO_GET_SOFT_LIST CRYPTOADMIN(3)
@@ -130,6 +150,8 @@ typedef struct crypto_get_soft_list32 {
#define CRYPTO_POOL_WAIT CRYPTOADMIN(13)
#define CRYPTO_POOL_RUN CRYPTOADMIN(14)
#define CRYPTO_LOAD_DOOR CRYPTOADMIN(15)
+#define CRYPTO_FIPS140_STATUS CRYPTOADMIN(16)
+#define CRYPTO_FIPS140_SET CRYPTOADMIN(17)
#ifdef __cplusplus
}
diff --git a/usr/src/uts/intel/ecc/Makefile b/usr/src/uts/intel/ecc/Makefile
index b263378e50..e7be8e1fdb 100644
--- a/usr/src/uts/intel/ecc/Makefile
+++ b/usr/src/uts/intel/ecc/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the ECc kef provider.
#
@@ -34,8 +33,7 @@
#
UTSBASE = ../..
COM1_DIR = $(COMMONBASE)/mpi
-COM2_DIR = $(COMMONBASE)/crypto/ecc
-COM3_DIR = $(COMMONBASE)/crypto/des
+COM2_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -65,11 +63,11 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
#
LDFLAGS += -dy -Nmisc/kcf
-CPPFLAGS += -I$(COM1_DIR) -I$(COM2_DIR) -I$(COM3_DIR)
+CPPFLAGS += -I$(COM1_DIR) -I$(COM2_DIR)
CFLAGS += -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B
-LINTFLAGS += -I$(COM1_DIR) -I$(COM2_DIR) -I$(COM3_DIR)
+LINTFLAGS += -I$(COM1_DIR) -I$(COM2_DIR)
#
# Default build targets.
diff --git a/usr/src/uts/intel/rsa/Makefile b/usr/src/uts/intel/rsa/Makefile
index c74d1f5202..1915aa7d8a 100644
--- a/usr/src/uts/intel/rsa/Makefile
+++ b/usr/src/uts/intel/rsa/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the RSA KEF provider.
#
@@ -34,7 +33,7 @@
#
UTSBASE = ../..
COM1_DIR = $(COMMONBASE)/bignum
-COM2_DIR = $(COMMONBASE)/crypto/rsa
+COM2_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
diff --git a/usr/src/uts/intel/sha1/Makefile b/usr/src/uts/intel/sha1/Makefile
index 67e5b92f8f..57237a7b5f 100644
--- a/usr/src/uts/intel/sha1/Makefile
+++ b/usr/src/uts/intel/sha1/Makefile
@@ -21,10 +21,9 @@
#
# uts/intel/sha1/Makefile
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the sha1 crypto kernel module.
#
@@ -35,7 +34,7 @@
# Path to the base of the uts directory tree (usually /usr/src/uts).
#
UTSBASE = ../..
-COMDIR = $(COMMONBASE)/crypto/sha1
+COMDIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -60,6 +59,14 @@ include $(UTSBASE)/intel/Makefile.intel
CLEANFILES += sha1-x86_64.s
#
+# Linkage dependencies
+#
+LDFLAGS += -dy -Nmisc/kcf
+
+CFLAGS += -I$(COMDIR)
+LINTFLAGS += -I$(COMDIR)
+
+#
# For now, disable these lint checks; maintainers should endeavor
# to investigate and remove these for maximum lint coverage.
# Please do not carry these forward to new Makefiles.
@@ -111,5 +118,5 @@ $(OBJS_DIR)/sha1-x86_64.o: sha1-x86_64.s
$(OBJS_DIR)/sha1-x86_64.ln: sha1-x86_64.s
@($(LHEAD) $(LINT.c) ${@F:.ln=.s} $(LTAIL))
-sha1-x86_64.s: $(COMDIR)/amd64/sha1-x86_64.pl
+sha1-x86_64.s: $(COMDIR)/sha1/amd64/sha1-x86_64.pl
$(PERL) $? $@
diff --git a/usr/src/uts/intel/sha2/Makefile b/usr/src/uts/intel/sha2/Makefile
index eb1fff8c37..e42eb3b1cb 100755..100644
--- a/usr/src/uts/intel/sha2/Makefile
+++ b/usr/src/uts/intel/sha2/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the sha2 crypto kernel module.
#
@@ -33,7 +32,7 @@
# Path to the base of the uts directory tree (usually /usr/src/uts).
#
UTSBASE = ../..
-COMDIR = $(COMMONBASE)/crypto/sha2
+COMDIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -65,6 +64,14 @@ LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
#
+# Linkage dependencies
+#
+LDFLAGS += -dy -Nmisc/kcf
+
+CFLAGS += -I$(COMDIR)
+LINTFLAGS += -I$(COMDIR)
+
+#
# For now, disable these lint checks; maintainers should endeavor
# to investigate and remove these for maximum lint coverage.
# Please do not carry these forward to new Makefiles.
@@ -110,8 +117,8 @@ $(OBJS_DIR)/%.o: %.s
$(OBJS_DIR)/%.ln: %.s
@($(LHEAD) $(LINT.c) ${@F:.ln=.s} $(LTAIL))
-sha512-x86_64.s: $(COMDIR)/amd64/sha512-x86_64.pl
+sha512-x86_64.s: $(COMDIR)/sha2/amd64/sha512-x86_64.pl
$(PERL) $? $@
-sha256-x86_64.s: $(COMDIR)/amd64/sha512-x86_64.pl
+sha256-x86_64.s: $(COMDIR)/sha2/amd64/sha512-x86_64.pl
$(PERL) $? $@
diff --git a/usr/src/uts/sparc/ecc/Makefile b/usr/src/uts/sparc/ecc/Makefile
index 55f4430188..06ac288821 100644
--- a/usr/src/uts/sparc/ecc/Makefile
+++ b/usr/src/uts/sparc/ecc/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the ECC KEF provider.
#
@@ -34,8 +33,7 @@
#
UTSBASE = ../..
COM1_DIR = $(COMMONBASE)/mpi
-COM2_DIR = $(COMMONBASE)/crypto/ecc
-COM3_DIR = $(COMMONBASE)/crypto/des
+COM2_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -68,9 +66,9 @@ LDFLAGS += -dy -Nmisc/kcf
#
# lint pass one enforcement
#
-CFLAGS += $(CCVERBOSE) -I$(COM1_DIR) -I$(COM2_DIR) -I$(COM3_DIR)
+CFLAGS += $(CCVERBOSE) -I$(COM1_DIR) -I$(COM2_DIR)
CFLAGS += -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B
-LINTFLAGS += -I$(COM1_DIR) -I$(COM2_DIR) -I$(COM3_DIR)
+LINTFLAGS += -I$(COM1_DIR) -I$(COM2_DIR)
#
# Default build targets.
diff --git a/usr/src/uts/sparc/rsa/Makefile b/usr/src/uts/sparc/rsa/Makefile
index 3d09f18fd9..6a14020bb6 100644
--- a/usr/src/uts/sparc/rsa/Makefile
+++ b/usr/src/uts/sparc/rsa/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the RSA KEF provider.
#
@@ -34,7 +33,7 @@
#
UTSBASE = ../..
COM1_DIR = $(COMMONBASE)/bignum
-COM2_DIR = $(COMMONBASE)/crypto/rsa
+COM2_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
diff --git a/usr/src/uts/sparc/sha1/Makefile b/usr/src/uts/sparc/sha1/Makefile
index b7bfb030d9..67d4c224aa 100644
--- a/usr/src/uts/sparc/sha1/Makefile
+++ b/usr/src/uts/sparc/sha1/Makefile
@@ -21,11 +21,10 @@
#
# uts/sparc/sha1/Makefile
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the sha1 crypto kernel module.
#
@@ -36,6 +35,7 @@
# Path to the base of the uts directory tree (usually /usr/src/uts).
#
UTSBASE = ../..
+COM_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -64,9 +64,15 @@ LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
#
+# Linkage dependencies
+#
+LDFLAGS += -dy -Nmisc/kcf
+
+#
# lint pass one enforcement
#
-CFLAGS += $(CCVERBOSE)
+CFLAGS += $(CCVERBOSE) -I$(COM_DIR)
+LINTFLAGS += -I$(COM_DIR)
#
# For now, disable these lint checks; maintainers should endeavor
diff --git a/usr/src/uts/sparc/sha2/Makefile b/usr/src/uts/sparc/sha2/Makefile
index f46b4ece55..013afff253 100644
--- a/usr/src/uts/sparc/sha2/Makefile
+++ b/usr/src/uts/sparc/sha2/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the sha2 crypto kernel module.
#
@@ -33,6 +32,7 @@
# Path to the base of the uts directory tree (usually /usr/src/uts).
#
UTSBASE = ../..
+COM_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -61,9 +61,15 @@ LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
#
+# Linkage dependencies
+#
+LDFLAGS += -dy -Nmisc/kcf
+
+#
# lint pass one enforcement
#
-CFLAGS += $(CCVERBOSE)
+CFLAGS += $(CCVERBOSE) -I$(COM_DIR)
+LINTFLAGS += -I$(COM_DIR)
#
# For now, disable these lint checks; maintainers should endeavor
diff --git a/usr/src/uts/sun4u/Makefile.files b/usr/src/uts/sun4u/Makefile.files
index 802789bec9..3c847fd614 100644
--- a/usr/src/uts/sun4u/Makefile.files
+++ b/usr/src/uts/sun4u/Makefile.files
@@ -148,7 +148,7 @@ MEM_CACHE_OBJS += mem_cache.o panther_asm.o
BIGNUM_PSR_OBJS += mont_mulf_kernel_v9.o
-AES_OBJS += aes.o aes_impl.o aes_modes.o aes_crypt_asm.o
+AES_OBJS += aes.o aes_impl.o aes_modes.o aes_crypt_asm.o fips_aes_util.o
DES_OBJS += des_crypt_asm.o
diff --git a/usr/src/uts/sun4u/sha1/Makefile b/usr/src/uts/sun4u/sha1/Makefile
index 95023bd191..19d69ac4b7 100644
--- a/usr/src/uts/sun4u/sha1/Makefile
+++ b/usr/src/uts/sun4u/sha1/Makefile
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
# This makefile drives the production of the SHA1 kernel module.
#
@@ -33,6 +32,7 @@
# Path to the base of the uts directory tree (usually /usr/src/uts).
#
UTSBASE = ../..
+COM_DIR = $(COMMONBASE)/crypto
#
# Define the module and object file sets.
@@ -55,11 +55,17 @@ ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+#
+# Linkage dependencies
+#
+LDFLAGS += -dy -Nmisc/kcf
+
#
# lint pass one enforcement
#
-CFLAGS += $(CCVERBOSE)
+CFLAGS += $(CCVERBOSE) -I$(COM_DIR)
CFLAGS += -DVIS_SHA1
+LINTFLAGS += -I$(COM_DIR)
#
# For now, disable these lint checks; maintainers should endeavor