Whamcloud - gitweb
LU-8602 gss: support OpenSSL 1.1
[fs/lustre-release.git] / lustre / utils / gss / lgss_sk.c
index 24752a5..d6d9959 100644 (file)
 /*
  * Copyright (C) 2015, Trustees of Indiana University
  *
+ * Copyright (c) 2016, Intel Corporation.
+ *
  * Author: Jeremy Filizetti <jfilizet@iu.edu>
  */
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
@@ -37,8 +40,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#include <lnet/nidstr.h>
-#include <lustre/lustre_idl.h>
+#include <linux/lustre/lustre_user.h>
 
 #include "sk_utils.h"
 #include "err_util.h"
 #define SK_DEFAULT_PRIME_BITS 2048
 #define SK_DEFAULT_NODEMAP "default"
 
-/* Names match up with openssl enc and dgst commands */
-char *sk_crypt2name[] = {
-       [SK_CRYPT_EMPTY] = "NONE",
-       [SK_CRYPT_AES256_CTR] = "AES-256-CTR",
-};
-
-char *sk_hmac2name[] = {
-       [SK_HMAC_EMPTY] = "NONE",
-       [SK_HMAC_SHA256] = "SHA256",
-       [SK_HMAC_SHA512] = "SHA512",
-};
-
-int sk_name2crypt(char *name)
-{
-       int i;
-
-       for (i = 0; i < SK_CRYPT_MAX; i++) {
-               if (strcasecmp(name, sk_crypt2name[i]) == 0)
-                       return i;
-       }
-
-       return SK_CRYPT_INVALID;
-}
-
-int sk_name2hmac(char *name)
-{
-       int i;
-
-       for (i = 0; i < SK_HMAC_MAX; i++) {
-               if (strcasecmp(name, sk_hmac2name[i]) == 0)
-                       return i;
-       }
-
-       return SK_HMAC_INVALID;
-}
-
-void usage(FILE *fp, char *program)
+static void usage(FILE *fp, char *program)
 {
        int i;
 
-       fprintf(fp, "Usage %s [OPTIONS] -l <file> | -m <file> | "
-               "-r <file> | -w <file>\n", program);
-       fprintf(fp, "-l|--load       <file>     Load key from file into user's "
+       fprintf(fp, "Usage %s [OPTIONS] {-l|-m|-r|-w} <keyfile>\n", program);
+       fprintf(fp, "-l|--load       <keyfile>  Load key from file into user's "
                "session keyring\n");
-       fprintf(fp, "-m|--modify     <file>     Modify a file's key "
-               "attributes\n");
-       fprintf(fp, "-r|--read       <file>     Show file's key attributes\n");
-       fprintf(fp, "-w|--write      <file>     Generate key file\n\n");
+       fprintf(fp, "-m|--modify     <keyfile>  Modify keyfile's attributes\n");
+       fprintf(fp, "-r|--read       <keyfile>  Show keyfile's attributes\n");
+       fprintf(fp, "-w|--write      <keyfile>  Generate keyfile\n\n");
        fprintf(fp, "Modify/Write Options:\n");
        fprintf(fp, "-c|--crypt      <num>      Cipher for encryption "
                "(Default: AES Counter mode)\n");
-       for (i = 1; i < SK_CRYPT_MAX; i++)
-               fprintf(fp, "                        %s\n", sk_crypt2name[i]);
-
+       for (i = 1; i < ARRAY_SIZE(sk_crypt_algs); i++)
+               fprintf(fp, "                        %s\n",
+                       sk_crypt_algs[i].sct_name);
        fprintf(fp, "-i|--hmac       <num>      Hash algorithm for integrity "
                "(Default: SHA256)\n");
-       for (i = 1; i < SK_HMAC_MAX; i++)
-               fprintf(fp, "                        %s\n", sk_hmac2name[i]);
-
+       for (i = 1; i < ARRAY_SIZE(sk_hmac_algs); i++)
+               fprintf(fp, "                        %s\n",
+                       sk_hmac_algs[i].sht_name);
        fprintf(fp, "-e|--expire     <num>      Seconds before contexts from "
-               "key expire (Default: %d seconds)\n", SK_DEFAULT_EXPIRE);
+               "key expire (Default: %d seconds (%.3g days))\n",
+               SK_DEFAULT_EXPIRE, (double)SK_DEFAULT_EXPIRE / 3600 / 24);
        fprintf(fp, "-f|--fsname     <name>     File system name for key\n");
        fprintf(fp, "-g|--mgsnids    <nids>     Comma seperated list of MGS "
-               "NIDs.  Only required when mgssec is used (Default: "
-               "\"\")\n");
+               "NIDs.  Only required when mgssec is used (Default: \"\")\n");
        fprintf(fp, "-n|--nodemap    <name>     Nodemap name for key "
                "(Default: \"%s\")\n", SK_DEFAULT_NODEMAP);
        fprintf(fp, "-p|--prime-bits <len>      Prime length (p) for DHKE in "
                "bits (Default: %d)\n", SK_DEFAULT_PRIME_BITS);
        fprintf(fp, "-t|--type       <type>     Key type (mgs, server, "
                "client)\n");
-       fprintf(fp, "-k|--shared     <len>      Shared key length in bits "
+       fprintf(fp, "-k|--key-bits   <len>      Shared key length in bits "
                "(Default: %d)\n", SK_DEFAULT_SK_KEYLEN);
-       fprintf(fp, "-d|--data       <file>     Shared key data source "
-               "(Default: /dev/random)\n\n");
+       fprintf(fp, "-d|--data       <file>     Key data source for new keys "
+               "(Default: /dev/random)\n");
+       fprintf(fp, "                        Not a seed value. "
+               "This is the actual key value.\n\n");
        fprintf(fp, "Other Options:\n");
-       fprintf(fp, "-v|--verbose           Increase verbosity for "
-               "errors\n");
+       fprintf(fp, "-v|--verbose           Increase verbosity for errors\n");
        exit(EXIT_FAILURE);
 }
 
-ssize_t get_key_data(char *src, void *buffer, size_t bits)
+static ssize_t get_key_data(char *src, void *buffer, size_t bits)
 {
        char *ptr = buffer;
        size_t remain;
@@ -144,10 +109,10 @@ ssize_t get_key_data(char *src, void *buffer, size_t bits)
        /* convert bits to minimum number of bytes */
        remain = (bits + 7) / 8;
 
-       printf("Reading data for shared key from %s\n", src);
+       printf("Reading random data for shared key from '%s'\n", src);
        fd = open(src, O_RDONLY);
        if (fd < 0) {
-               fprintf(stderr, "Failed to open %s: %s\n", src,
+               fprintf(stderr, "error: opening '%s': %s\n", src,
                        strerror(errno));
                return -errno;
        }
@@ -157,13 +122,15 @@ ssize_t get_key_data(char *src, void *buffer, size_t bits)
                if (rc < 0) {
                        if (errno == EINTR)
                                continue;
-                       fprintf(stderr, "Error reading from %s: %s\n", src,
+                       fprintf(stderr, "error: reading from '%s': %s\n", src,
                                strerror(errno));
                        rc = -errno;
                        goto out;
 
                } else if (rc == 0) {
-                       fprintf(stderr, "Key source too short for key size\n");
+                       fprintf(stderr,
+                               "error: key source too short for %zd-bit key\n",
+                               bits);
                        rc = -ENODATA;
                        goto out;
                }
@@ -177,8 +144,8 @@ out:
        return rc;
 }
 
-int write_config_file(char *output_file, struct sk_keyfile_config *config,
-                     bool overwrite)
+static int write_config_file(char *output_file,
+                            struct sk_keyfile_config *config, bool overwrite)
 {
        size_t rc;
        int fd;
@@ -191,19 +158,18 @@ int write_config_file(char *output_file, struct sk_keyfile_config *config,
 
        fd = open(output_file, flags, 0400);
        if (fd < 0) {
-               fprintf(stderr, "Failed to open %s: %s\n", output_file,
+               fprintf(stderr, "error: opening '%s': %s\n", output_file,
                        strerror(errno));
                return -errno;
        }
 
        rc = write(fd, config, sizeof(*config));
        if (rc < 0) {
-               fprintf(stderr, "Error writing to %s: %s\n", output_file,
+               fprintf(stderr, "error: writing to '%s': %s\n", output_file,
                        strerror(errno));
                rc = -errno;
-
        } else if (rc != sizeof(*config)) {
-               fprintf(stderr, "Short write to %s\n", output_file);
+               fprintf(stderr, "error: short write to '%s'\n", output_file);
                rc = -ENOSPC;
 
        } else {
@@ -214,7 +180,7 @@ int write_config_file(char *output_file, struct sk_keyfile_config *config,
        return rc;
 }
 
-int print_config(char *filename)
+static int print_config(char *filename)
 {
        struct sk_keyfile_config *config;
        int i;
@@ -224,51 +190,52 @@ int print_config(char *filename)
                return EXIT_FAILURE;
 
        if (sk_validate_config(config)) {
-               fprintf(stderr, "Key configuration failed validation\n");
+               fprintf(stderr, "error: key configuration failed validation\n");
                free(config);
                return EXIT_FAILURE;
        }
 
        printf("Version:        %u\n", config->skc_version);
-       printf("Type:           ");
+       printf("Type:          ");
        if (config->skc_type & SK_TYPE_MGS)
-               printf("mgs ");
+               printf(" mgs");
        if (config->skc_type & SK_TYPE_SERVER)
-               printf("server ");
+               printf(" server");
        if (config->skc_type & SK_TYPE_CLIENT)
-               printf("client ");
+               printf(" client");
        printf("\n");
-       printf("HMAC alg:       %s\n", sk_hmac2name[config->skc_hmac_alg]);
-       printf("Crypt alg:      %s\n", sk_crypt2name[config->skc_crypt_alg]);
+       printf("HMAC alg:       %s\n", sk_hmac2name(config->skc_hmac_alg));
+       printf("Crypto alg:     %s\n", sk_crypt2name(config->skc_crypt_alg));
        printf("Ctx Expiration: %u seconds\n", config->skc_expire);
        printf("Shared keylen:  %u bits\n", config->skc_shared_keylen);
        printf("Prime length:   %u bits\n", config->skc_prime_bits);
        printf("File system:    %s\n", config->skc_fsname);
-       printf("MGS NIDs:       ");
+       printf("MGS NIDs:      ");
        for (i = 0; i < MAX_MGSNIDS; i++) {
                if (config->skc_mgsnids[i] == LNET_NID_ANY)
                        continue;
-               printf("%s ", libcfs_nid2str(config->skc_mgsnids[i]));
+               printf(" %s", libcfs_nid2str(config->skc_mgsnids[i]));
        }
        printf("\n");
        printf("Nodemap name:   %s\n", config->skc_nodemap);
        printf("Shared key:\n");
        print_hex(0, config->skc_shared_key, config->skc_shared_keylen / 8);
-       printf("Prime (p) :\n");
 
        /* Don't print empty keys */
        for (i = 0; i < SK_MAX_P_BYTES; i++)
                if (config->skc_p[i] != 0)
                        break;
 
-       if (i != SK_MAX_P_BYTES)
+       if (i != SK_MAX_P_BYTES) {
+               printf("Prime (p):\n");
                print_hex(0, config->skc_p, config->skc_prime_bits / 8);
+       }
 
        free(config);
        return EXIT_SUCCESS;
 }
 
-int parse_mgsnids(char *mgsnids, struct sk_keyfile_config *config)
+static int parse_mgsnids(char *mgsnids, struct sk_keyfile_config *config)
 {
        lnet_nid_t nid;
        char *ptr;
@@ -291,7 +258,7 @@ int parse_mgsnids(char *mgsnids, struct sk_keyfile_config *config)
 
                nid = libcfs_str2nid(ptr);
                if (nid == LNET_NID_ANY) {
-                       fprintf(stderr, "Invalid MGS NID: %s\n", ptr);
+                       fprintf(stderr, "error: invalid MGS NID: %s\n", ptr);
                        rc = -EINVAL;
                        break;
                }
@@ -301,7 +268,7 @@ int parse_mgsnids(char *mgsnids, struct sk_keyfile_config *config)
        }
 
        if (i == MAX_MGSNIDS) {
-               fprintf(stderr, "Too many MGS NIDs provided\n");
+               fprintf(stderr, "error: more than %u MGS NIDs provided\n", i);
                rc = -E2BIG;
        }
 
@@ -311,7 +278,7 @@ int parse_mgsnids(char *mgsnids, struct sk_keyfile_config *config)
 int main(int argc, char **argv)
 {
        struct sk_keyfile_config *config;
-       char *data = NULL;
+       char *datafile = NULL;
        char *input = NULL;
        char *load = NULL;
        char *modify = NULL;
@@ -329,51 +296,54 @@ int main(int argc, char **argv)
        int verbose = 0;
        int i;
        int opt;
-       enum sk_key_type  type = SK_TYPE_INVALID;
+       enum sk_key_type type = SK_TYPE_INVALID;
        bool generate_prime = false;
-       DH *dh;
-
-       static struct option long_opt[] = {
-               {"crypt", 1, 0, 'c'},
-               {"data", 1, 0, 'd'},
-               {"expire", 1, 0, 'e'},
-               {"fsname", 1, 0, 'f'},
-               {"mgsnids", 1, 0, 'g'},
-               {"help", 0, 0, 'h'},
-               {"hmac", 1, 0, 'i'},
-               {"shared", 1, 0, 'k'},
-               {"load", 1, 0, 'l'},
-               {"modify", 1, 0, 'm'},
-               {"nodemap", 1, 0, 'n'},
-               {"prime-bits", 1, 0, 'p'},
-               {"read", 1, 0, 'r'},
-               {"type", 1, 0, 't'},
-               {"verbose", 0, 0, 'v'},
-               {"write", 1, 0, 'w'},
-               {0, 0, 0, 0},
-       };
+       DH *dh = NULL;
+
+       static struct option long_opts[] = {
+       { .name = "crypt",      .has_arg = required_argument, .val = 'c'},
+       { .name = "data",       .has_arg = required_argument, .val = 'd'},
+       { .name = "expire",     .has_arg = required_argument, .val = 'e'},
+       { .name = "fsname",     .has_arg = required_argument, .val = 'f'},
+       { .name = "mgsnids",    .has_arg = required_argument, .val = 'g'},
+       { .name = "help",       .has_arg = no_argument,       .val = 'h'},
+       { .name = "hmac",       .has_arg = required_argument, .val = 'i'},
+       { .name = "integrity",  .has_arg = required_argument, .val = 'i'},
+       { .name = "key-bits",   .has_arg = required_argument, .val = 'k'},
+       { .name = "shared",     .has_arg = required_argument, .val = 'k'},
+       { .name = "load",       .has_arg = required_argument, .val = 'l'},
+       { .name = "modify",     .has_arg = required_argument, .val = 'm'},
+       { .name = "nodemap",    .has_arg = required_argument, .val = 'n'},
+       { .name = "prime-bits", .has_arg = required_argument, .val = 'p'},
+       { .name = "read",       .has_arg = required_argument, .val = 'r'},
+       { .name = "type",       .has_arg = required_argument, .val = 't'},
+       { .name = "verbose",    .has_arg = no_argument,       .val = 'v'},
+       { .name = "write",      .has_arg = required_argument, .val = 'w'},
+       { .name = NULL, } };
 
        while ((opt = getopt_long(argc, argv,
-                                 "c:d:e:f:g:hi:l:m:n:p:r:s:k:t:w:v", long_opt,
+                                 "c:d:e:f:g:hi:l:m:n:p:r:s:k:t:w:v", long_opts,
                                  NULL)) != EOF) {
                switch (opt) {
                case 'c':
                        crypt = sk_name2crypt(optarg);
                        break;
                case 'd':
-                       data = optarg;
+                       datafile = optarg;
                        break;
                case 'e':
                        expire = atoi(optarg);
                        if (expire < 60)
-                               fprintf(stderr, "WARNING: Using a short key "
+                               fprintf(stderr, "warning: using a %us key "
                                        "expiration may cause issues during "
-                                       "key renegotiation\n");
+                                       "key renegotiation\n", expire);
                        break;
                case 'f':
                        fsname = optarg;
                        if (strlen(fsname) > MTI_NAME_MAXLEN) {
-                               fprintf(stderr, "File system name too long\n");
+                               fprintf(stderr,
+                                       "error: file system name longer than "
+                                       "%u characters\n", MTI_NAME_MAXLEN);
                                return EXIT_FAILURE;
                        }
                        break;
@@ -398,14 +368,18 @@ int main(int argc, char **argv)
                case 'n':
                        nodemap = optarg;
                        if (strlen(nodemap) > LUSTRE_NODEMAP_NAME_LENGTH) {
-                               fprintf(stderr, "Nodemap name too long\n");
+                               fprintf(stderr,
+                                       "error: nodemap name longer than "
+                                       "%u characters\n",
+                                       LUSTRE_NODEMAP_NAME_LENGTH);
                                return EXIT_FAILURE;
                        }
                        break;
                case 'p':
                        prime_bits = atoi(optarg);
                        if (prime_bits <= 0) {
-                               fprintf(stderr, "Invalid prime length: %s\n",
+                               fprintf(stderr,
+                                       "error: invalid prime length: '%s'\n",
                                        optarg);
                                return EXIT_FAILURE;
                        }
@@ -416,8 +390,8 @@ int main(int argc, char **argv)
                case 't':
                        tmp2 = strdup(optarg);
                        if (!tmp2) {
-                               fprintf(stderr, "Failed to allocated memory "
-                                       "for type argument\n");
+                               fprintf(stderr,
+                                       "error: failed to allocate type\n");
                                return EXIT_FAILURE;
                        }
                        tmp = strsep(&tmp2, ",");
@@ -429,9 +403,10 @@ int main(int argc, char **argv)
                                } else if (strcasecmp(tmp, "client") == 0) {
                                        type |= SK_TYPE_CLIENT;
                                } else {
-                                       fprintf(stderr, "Invalid type must be "
-                                               "mgs, server, or  client: "
-                                               "%s\n", optarg);
+                                       fprintf(stderr,
+                                               "error: invalid type '%s', "
+                                               "must be mgs, server, or client"
+                                               "\n", optarg);
                                        return EXIT_FAILURE;
                                }
                                tmp = strsep(&tmp2, ",");
@@ -445,14 +420,15 @@ int main(int argc, char **argv)
                        output = optarg;
                        break;
                default:
-                       fprintf(stderr, "Unknown option: %c\n", opt);
+                       fprintf(stderr, "error: unknown option: '%c'\n", opt);
                        return EXIT_FAILURE;
                        break;
                }
        }
 
        if (optind != argc) {
-               fprintf(stderr, "Extraneous arguments provided, check usage\n");
+               fprintf(stderr,
+                       "error: extraneous arguments provided, check usage\n");
                return EXIT_FAILURE;
        }
 
@@ -474,11 +450,17 @@ int main(int argc, char **argv)
        }
 
        if (crypt == SK_CRYPT_INVALID) {
-               fprintf(stderr, "Invalid crypt algorithm specified\n");
+               fprintf(stderr, "error: invalid crypt algorithm specified\n");
                return EXIT_FAILURE;
        }
        if (hmac == SK_HMAC_INVALID) {
-               fprintf(stderr, "Invalid HMAC algorithm specified\n");
+               fprintf(stderr, "error: invalid HMAC algorithm specified\n");
+               return EXIT_FAILURE;
+       }
+
+       if (modify && datafile) {
+               fprintf(stderr,
+                       "error: data file option not valid in key modify\n");
                return EXIT_FAILURE;
        }
 
@@ -487,14 +469,6 @@ int main(int argc, char **argv)
                if (!config)
                        return EXIT_FAILURE;
 
-               if (crypt != SK_CRYPT_EMPTY)
-                       config->skc_crypt_alg = crypt;
-               if (hmac != SK_HMAC_EMPTY)
-                       config->skc_hmac_alg = hmac;
-               if (expire != -1)
-                       config->skc_expire = expire;
-               if (shared_keylen != -1)
-                       config->skc_shared_keylen = shared_keylen;
                if (type != SK_TYPE_INVALID) {
                        /* generate key when adding client type */
                        if (!(config->skc_type & SK_TYPE_CLIENT) &&
@@ -510,74 +484,43 @@ int main(int argc, char **argv)
                        if (config->skc_prime_bits != prime_bits &&
                            config->skc_type & SK_TYPE_CLIENT)
                                generate_prime = true;
-                       config->skc_prime_bits = prime_bits;
                }
-               if (fsname)
-                       strncpy(config->skc_fsname, fsname, strlen(fsname));
-               if (nodemap)
-                       strncpy(config->skc_nodemap, nodemap, strlen(nodemap));
-               if (mgsnids && parse_mgsnids(mgsnids, config))
-                       goto error;
-               if (sk_validate_config(config)) {
+       } else {
+               /* write mode for a new key */
+               if (!fsname && !mgsnids) {
                        fprintf(stderr,
-                               "Key configuration failed validation\n");
-                       goto error;
-               }
-
-               if (data && get_key_data(data, config->skc_shared_key,
-                   config->skc_shared_keylen)) {
-                       fprintf(stderr, "Failure getting data for key\n");
-                       goto error;
+                               "error: missing --fsname or --mgsnids\n");
+                       return EXIT_FAILURE;
                }
 
-               if (generate_prime) {
-                       printf("Generating DH parameters this can take a "
-                              "while...\n");
-                       dh = DH_generate_parameters(config->skc_prime_bits,
-                                                   SK_GENERATOR, NULL, NULL);
-                       if (BN_num_bytes(dh->p) > SK_MAX_P_BYTES) {
-                               fprintf(stderr, "Cannot generate DH parameters:"
-                                       " requested length %d exceeds maximum: "
-                                       "%d\n", config->skc_prime_bits,
-                                       SK_MAX_P_BYTES * 8);
-                               goto error;
-                       }
-                       if (BN_bn2bin(dh->p, config->skc_p) !=
-                           BN_num_bytes(dh->p)) {
-                               fprintf(stderr, "Failed conversion of BIGNUM p"
-                                       " to binary\n");
-                               goto error;
-                       }
-               }
+               config = calloc(1, sizeof(*config));
+               if (!config)
+                       return EXIT_FAILURE;
 
-               if (write_config_file(modify, config, true))
+               /* Set the defaults for new key */
+               config->skc_version = SK_CONF_VERSION;
+               config->skc_expire = 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 = SK_HMAC_SHA256;
+               for (i = 0; i < MAX_MGSNIDS; i++)
+                       config->skc_mgsnids[i] = LNET_NID_ANY;
+
+               if (type == SK_TYPE_INVALID) {
+                       fprintf(stderr, "error: no type specified for key\n");
                        goto error;
+               }
+               config->skc_type = type;
+               generate_prime = type & SK_TYPE_CLIENT;
 
-               return EXIT_SUCCESS;
-       }
+               /* SK_DEFAULT_NODEMAP is made to fit in skc_nodemap */
+               strcpy(config->skc_nodemap, SK_DEFAULT_NODEMAP);
 
-       /* write mode for a new key */
-       if (!fsname && !mgsnids) {
-               fprintf(stderr, "Must provide --fsname, "
-                       "--mgsnids, or both\n");
-               return EXIT_FAILURE;
+               if (!datafile)
+                       datafile = "/dev/random";
        }
 
-       config = malloc(sizeof(*config));
-       if (!config)
-               return EXIT_FAILURE;
-
-       /* Set the defaults */
-       memset(config, 0, sizeof(*config));
-       config->skc_version = SK_CONF_VERSION;
-       config->skc_expire = 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 = SK_HMAC_SHA256;
-       for (i = 0; i < MAX_MGSNIDS; i++)
-               config->skc_mgsnids[i] = LNET_NID_ANY;
-
        if (crypt != SK_CRYPT_EMPTY)
                config->skc_crypt_alg = crypt;
        if (hmac != SK_HMAC_EMPTY)
@@ -589,58 +532,71 @@ int main(int argc, char **argv)
        if (prime_bits != -1)
                config->skc_prime_bits = prime_bits;
        if (fsname)
-               strncpy(config->skc_fsname, fsname, strlen(fsname));
+               /* fsname string length was checked when parsing
+                * command-line options
+                */
+               strcpy(config->skc_fsname, fsname);
        if (nodemap)
-               strncpy(config->skc_nodemap, nodemap, strlen(nodemap));
-       else
-               strncpy(config->skc_nodemap, SK_DEFAULT_NODEMAP,
-                       strlen(SK_DEFAULT_NODEMAP));
-
+               /* nodemap string length was checked when parsing
+                * command-line options
+                */
+               strcpy(config->skc_nodemap, nodemap);
        if (mgsnids && parse_mgsnids(mgsnids, config))
                goto error;
-       if (type == SK_TYPE_INVALID) {
-               fprintf(stderr, "No type specified for key\n");
-               goto error;
-       }
-       config->skc_type = type;
-
        if (sk_validate_config(config)) {
-               fprintf(stderr, "Key configuration failed validation\n");
+               fprintf(stderr, "error: key configuration failed validation\n");
                goto error;
        }
 
-       if (!data)
-               data = "/dev/random";
-       if (get_key_data(data, config->skc_shared_key,
-           config->skc_shared_keylen)) {
-               fprintf(stderr, "Failure getting data for key\n");
+       if (datafile && get_key_data(datafile, config->skc_shared_key,
+                                    config->skc_shared_keylen)) {
+               fprintf(stderr, "error: failure getting key data from '%s'\n",
+                       datafile);
                goto error;
        }
 
-       if (type & SK_TYPE_CLIENT) {
-               printf("Generating DH parameters this can take a while...\n");
-               dh = DH_generate_parameters(config->skc_prime_bits,
-                                           SK_GENERATOR, NULL, NULL);
-               if (BN_num_bytes(dh->p) > SK_MAX_P_BYTES) {
-                       fprintf(stderr, "Cannot generate DH parameters: "
-                               "requested length %d exceeds maximum: %d\n",
+       if (generate_prime) {
+               const BIGNUM *p;
+               int rc;
+
+               printf("Generating DH parameters, this can take a while...\n");
+               dh = DH_new();
+               if (!dh) {
+                       fprintf(stderr, "error: dh cannot be allocated\n");
+                       goto error;
+               }
+
+               rc = DH_generate_parameters_ex(dh, config->skc_prime_bits,
+                                              SK_GENERATOR, NULL);
+               if (rc != 1) {
+                       fprintf(stderr, "error generating DH parameters\n");
+                       goto error;
+               }
+
+               DH_get0_pqg(dh, &p, NULL, NULL);
+
+               if (BN_num_bytes(p) > SK_MAX_P_BYTES) {
+                       fprintf(stderr, "error: cannot generate DH parameters: "
+                               "requested length %d exceeds maximum %d\n",
                                config->skc_prime_bits, SK_MAX_P_BYTES * 8);
                        goto error;
                }
-               if (BN_bn2bin(dh->p, config->skc_p) != BN_num_bytes(dh->p)) {
-                       fprintf(stderr, "Failed conversion of BIGNUM p to "
-                               "binary\n");
+               if (BN_bn2bin(p, config->skc_p) != BN_num_bytes(p)) {
+                       fprintf(stderr,
+                               "error: convert BIGNUM p to binary failed\n");
                        goto error;
                }
+
+               DH_free(dh);
        }
 
-       if (write_config_file(output, config, false))
+       if (write_config_file(modify ?: output, config, modify))
                goto error;
 
        return EXIT_SUCCESS;
 
 error:
-       if (config)
-               free(config);
+       DH_free(dh);
+       free(config);
        return EXIT_FAILURE;
 }