diff options
author | Hai-May Chao <Hai-May.Chao@Sun.COM> | 2009-09-11 09:04:22 -0700 |
---|---|---|
committer | Hai-May Chao <Hai-May.Chao@Sun.COM> | 2009-09-11 09:04:22 -0700 |
commit | b5a2d8455dfa3190fc977c4bec53e91c99012767 (patch) | |
tree | bff1e4f897b4291273be1f3f4c90125be60353b7 /usr/src | |
parent | 44da779fd55c337eb9877e490e494037fc1ddf06 (diff) | |
download | illumos-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')
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 |