CFLAGS="$saved_flags"
]) # LC_OPENSSL_HMAC
+# LC_OPENSSL_FIPS
+#
+# OpenSSL 1.0+ can be built with or without FIPS support
+AC_DEFUN([LC_OPENSSL_FIPS], [
+has_fips_support="no"
+saved_flags="$CFLAGS"
+CFLAGS="-Werror"
+AC_MSG_CHECKING([whether OpenSSL has FIPS_mode])
+AS_IF([test "x$enable_ssk" != xno], [
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ #include <openssl/dh.h>
+ #include <openssl/dsa.h>
+ #include <openssl/evp.h>
+ #include <openssl/hmac.h>
+ #include <openssl/fips.h>
+
+ int main(void) {
+ int rc;
+ rc = FIPS_mode();
+ return rc;
+ }
+])],[
+ AC_DEFINE(HAVE_OPENSSL_FIPS, 1, [OpenSSL FIPS_mode])
+ has_fips_support="yes"
+])
+])
+AC_MSG_RESULT([$has_fips_support])
+CFLAGS="$saved_flags"
+]) # LC_OPENSSL_FIPS
+
# LC_OPENSSL_EVP_PKEY
#
# OpenSSL 3.0 introduces EVP_PKEY_get_params
AC_DEFUN([LC_OPENSSL_SSK], [
AS_IF([test "x$enable_ssk" != xno], [
LC_OPENSSL_HMAC
+ LC_OPENSSL_FIPS
LC_OPENSSL_EVP_PKEY
])
AS_IF([test "x$has_hmac_functions" = xyes -o "x$has_evp_pkey" = xyes], [
/* One week default expiration */
#define SK_DEFAULT_EXPIRE 604800
+/* But only one day in FIPS mode */
+#define SK_DEFAULT_EXPIRE_FIPS 86400
#define SK_DEFAULT_SK_KEYLEN 256
#define SK_DEFAULT_PRIME_BITS 2048
#define SK_DEFAULT_NODEMAP "default"
+static int fips_mode;
+
static void usage(FILE *fp, char *program)
{
int i;
return rc;
}
+#if !defined(HAVE_OPENSSL_EVP_PKEY) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+static inline int __fetch_ssk_prime(struct sk_keyfile_config *config)
+{
+ const BIGNUM *p;
+ DH *dh = NULL;
+ int primenid;
+ int rc = -1;
+
+ primenid = sk_primebits2primenid(config->skc_prime_bits);
+ dh = DH_new_by_nid(primenid);
+ if (!dh) {
+ fprintf(stderr, "error: dh cannot be init\n");
+ goto prime_end;
+ }
+
+ p = DH_get0_p(dh);
+ if (!p) {
+ fprintf(stderr, "error: cannot get p from dh\n");
+ goto prime_end;
+ }
+
+ if (BN_num_bytes(p) > SK_MAX_P_BYTES) {
+ fprintf(stderr,
+ "error: requested length %d exceeds maximum %d\n",
+ BN_num_bytes(p), SK_MAX_P_BYTES * 8);
+ goto prime_end;
+ }
+
+ if (BN_bn2bin(p, config->skc_p) != BN_num_bytes(p)) {
+ fprintf(stderr, "error: convert BIGNUM p to binary failed\n");
+ goto prime_end;
+ }
+
+ rc = 0;
+
+prime_end:
+ if (rc)
+ fprintf(stderr,
+ "error: fetching SSK prime failed: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ DH_free(dh);
+ return rc;
+}
+#endif
+
static inline int __gen_ssk_prime(struct sk_keyfile_config *config)
{
int rc = -1;
+ const char *primename;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *dh = NULL;
BIGNUM *p;
+ if (fips_mode) {
+ primename = sk_primebits2name(config->skc_prime_bits);
+ if (!primename) {
+ fprintf(stderr,
+ "error: prime len %d not supported in FIPS mode\n",
+ config->skc_prime_bits);
+ return rc;
+ }
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ fprintf(stdout,
+ "FIPS mode, using well-known prime %s\n", primename);
+#ifndef HAVE_OPENSSL_EVP_PKEY
+ return __fetch_ssk_prime(config);
+#endif
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+ }
+
ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
if (!ctx || EVP_PKEY_paramgen_init(ctx) != 1) {
fprintf(stderr, "error: ctx cannot be init\n");
rc = 0;
prime_end:
+ if (rc)
+ fprintf(stderr,
+ "error: generating SSK prime failed: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(dh);
EVP_PKEY_CTX_free(ctx);
return rc;
/* init gss logger for foreground (no syslog) which prints to stderr */
initerr(NULL, verbose, 1);
+ fips_mode = FIPS_mode();
+
if (input)
return print_config(input);
/* Set the defaults for new key */
config->skc_version = SK_CONF_VERSION;
- config->skc_expire = SK_DEFAULT_EXPIRE;
+ config->skc_expire = fips_mode ?
+ SK_DEFAULT_EXPIRE_FIPS : SK_DEFAULT_EXPIRE;
config->skc_shared_keylen = SK_DEFAULT_SK_KEYLEN;
config->skc_prime_bits = SK_DEFAULT_PRIME_BITS;
config->skc_crypt_alg = SK_CRYPT_AES256_CTR;
config->skc_hmac_alg = hmac;
if (expire != -1)
config->skc_expire = expire;
+ if (fips_mode && config->skc_expire > SK_DEFAULT_EXPIRE_FIPS)
+ fprintf(stderr,
+ "warning: using a %us key expiration greater than %us is not recommended in FIPS mode\n",
+ config->skc_expire, SK_DEFAULT_EXPIRE_FIPS);
if (shared_keylen != -1)
config->skc_shared_keylen = shared_keylen;
if (prime_bits != -1) {
#include <linux/lustre/lustre_idl.h>
#include <linux/lustre/lustre_disk.h>
#include <openssl/dh.h>
+#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#ifdef HAVE_OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
#ifdef HAVE_OPENSSL_EVP_PKEY
#include <openssl/core_names.h>
#endif
}
#endif
+#ifndef HAVE_OPENSSL_FIPS
+#define FIPS_mode() 0
+#endif
+
/* Some limits and defaults */
#define SK_CONF_VERSION 1
#define SK_MSG_VERSION 1
return NULL;
}
+#ifndef NID_ffdhe2048
+#define NID_ffdhe2048 1126
+#define NID_ffdhe3072 1127
+#define NID_ffdhe4096 1128
+#define NID_ffdhe6144 1129
+#define NID_ffdhe8192 1130
+#endif
+
+static const struct sk_prime_type sk_prime_nids[] = {
+ {
+ .spt_name = "null",
+ .spt_type = 0,
+ .spt_primebits = 0
+ },
+ {
+ .spt_name = "ffdhe2048",
+ .spt_type = NID_ffdhe2048,
+ .spt_primebits = 2048
+ },
+ {
+ .spt_name = "ffdhe3072",
+ .spt_type = NID_ffdhe3072,
+ .spt_primebits = 3072
+ },
+ {
+ .spt_name = "ffdhe4096",
+ .spt_type = NID_ffdhe4096,
+ .spt_primebits = 4096
+ },
+ {
+ .spt_name = "ffdhe6144",
+ .spt_type = NID_ffdhe6144,
+ .spt_primebits = 6144
+ },
+ {
+ .spt_name = "ffdhe8192",
+ .spt_type = NID_ffdhe8192,
+ .spt_primebits = 8192
+ },
+};
+
+static inline int sk_primebits2primenid(int primebits)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sk_prime_nids); i++) {
+ if (primebits == sk_prime_nids[i].spt_primebits)
+ return sk_prime_nids[i].spt_type;
+ }
+
+ return -1;
+}
+
+static inline const char *sk_primebits2name(int primebits)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sk_prime_nids); i++) {
+ if (primebits == sk_prime_nids[i].spt_primebits)
+ return sk_prime_nids[i].spt_name;
+ }
+
+ return NULL;
+}
+
void sk_init_logging(char *program, int verbose, int fg);
struct sk_keyfile_config *sk_read_file(char *filename);
int sk_load_keyfile(char *path);