summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-30 03:30:09 +0000
committerDamien Miller <djm@mindrot.org>2019-12-30 14:33:54 +1100
commit3e60d18fba1b502c21d64fc7e81d80bcd08a2092 (patch)
tree0ec5f0bd3e34d1290a6c1a068234d39d8d367b35 /ssh-keygen.c
parent1e645fe767f27725dc7fd7864526de34683f7daf (diff)
upstream: remove single-letter flags for moduli options
Move all moduli generation options to live under the -O flag. Frees up seven single-letter flags. NB. this change break existing ssh-keygen commandline syntax for moduli- related operations. Very few people use these fortunately. feedback and ok markus@ OpenBSD-Commit-ID: d498f3eaf28128484826a4fcb343612764927935
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c249
1 files changed, 150 insertions, 99 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 43f2e1e82..447810fb1 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.375 2019/12/30 03:28:41 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.376 2019/12/30 03:30:09 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -162,10 +162,7 @@ static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
162/* Cipher for new-format private keys */ 162/* Cipher for new-format private keys */
163static char *openssh_format_cipher = NULL; 163static char *openssh_format_cipher = NULL;
164 164
165/* 165/* Number of KDF rounds to derive new format keys. */
166 * Number of KDF rounds to derive new format keys /
167 * number of primality trials when screening moduli.
168 */
169static int rounds = 0; 166static int rounds = 0;
170 167
171/* argv0 */ 168/* argv0 */
@@ -2759,6 +2756,122 @@ done:
2759} 2756}
2760 2757
2761static void 2758static void
2759do_moduli_gen(const char *out_file, char **opts, size_t nopts)
2760{
2761#ifdef WITH_OPENSSL
2762 /* Moduli generation/screening */
2763 u_int32_t memory = 0;
2764 BIGNUM *start = NULL;
2765 int moduli_bits = 0;
2766 FILE *out;
2767 size_t i;
2768 const char *errstr;
2769
2770 /* Parse options */
2771 for (i = 0; i < nopts; i++) {
2772 if (strncmp(opts[i], "memory=", 7) == 0) {
2773 memory = (u_int32_t)strtonum(opts[i]+7, 1,
2774 UINT_MAX, &errstr);
2775 if (errstr) {
2776 fatal("Memory limit is %s: %s",
2777 errstr, opts[i]+7);
2778 }
2779 } else if (strncmp(opts[i], "start=", 6) == 0) {
2780 /* XXX - also compare length against bits */
2781 if (BN_hex2bn(&start, opts[i]+6) == 0)
2782 fatal("Invalid start point.");
2783 } else if (strncmp(opts[i], "bits=", 5) == 0) {
2784 moduli_bits = (int)strtonum(opts[i]+5, 1,
2785 INT_MAX, &errstr);
2786 if (errstr) {
2787 fatal("Invalid number: %s (%s)",
2788 opts[i]+12, errstr);
2789 }
2790 } else {
2791 fatal("Option \"%s\" is unsupported for moduli "
2792 "generation", opts[i]);
2793 }
2794 }
2795
2796 if ((out = fopen(out_file, "w")) == NULL) {
2797 fatal("Couldn't open modulus candidate file \"%s\": %s",
2798 out_file, strerror(errno));
2799 }
2800 setvbuf(out, NULL, _IOLBF, 0);
2801
2802 if (moduli_bits == 0)
2803 moduli_bits = DEFAULT_BITS;
2804 if (gen_candidates(out, memory, moduli_bits, start) != 0)
2805 fatal("modulus candidate generation failed");
2806#else /* WITH_OPENSSL */
2807 fatal("Moduli generation is not supported");
2808#endif /* WITH_OPENSSL */
2809}
2810
2811static void
2812do_moduli_screen(const char *out_file, char **opts, size_t nopts)
2813{
2814#ifdef WITH_OPENSSL
2815 /* Moduli generation/screening */
2816 char *checkpoint = NULL;
2817 u_int32_t generator_wanted = 0;
2818 unsigned long start_lineno = 0, lines_to_process = 0;
2819 int prime_tests = 0;
2820 FILE *out, *in = stdin;
2821 size_t i;
2822 const char *errstr;
2823
2824 /* Parse options */
2825 for (i = 0; i < nopts; i++) {
2826 if (strncmp(opts[i], "lines=", 6) == 0) {
2827 lines_to_process = strtoul(opts[i]+6, NULL, 10);
2828 } else if (strncmp(opts[i], "start-line=", 11) == 0) {
2829 start_lineno = strtoul(opts[i]+11, NULL, 10);
2830 } else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
2831 checkpoint = xstrdup(opts[i]+11);
2832 } else if (strncmp(opts[i], "generator=", 10) == 0) {
2833 generator_wanted = (u_int32_t)strtonum(
2834 opts[i]+10, 1, UINT_MAX, &errstr);
2835 if (errstr != NULL) {
2836 fatal("Generator invalid: %s (%s)",
2837 opts[i]+10, errstr);
2838 }
2839 } else if (strncmp(opts[i], "prime-tests=", 12) == 0) {
2840 prime_tests = (int)strtonum(opts[i]+12, 1,
2841 INT_MAX, &errstr);
2842 if (errstr) {
2843 fatal("Invalid number: %s (%s)",
2844 opts[i]+12, errstr);
2845 }
2846 } else {
2847 fatal("Option \"%s\" is unsupported for moduli "
2848 "screening", opts[i]);
2849 }
2850 }
2851
2852 if (have_identity && strcmp(identity_file, "-") != 0) {
2853 if ((in = fopen(identity_file, "r")) == NULL) {
2854 fatal("Couldn't open modulus candidate "
2855 "file \"%s\": %s", identity_file,
2856 strerror(errno));
2857 }
2858 }
2859
2860 if ((out = fopen(out_file, "a")) == NULL) {
2861 fatal("Couldn't open moduli file \"%s\": %s",
2862 out_file, strerror(errno));
2863 }
2864 setvbuf(out, NULL, _IOLBF, 0);
2865 if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
2866 generator_wanted, checkpoint,
2867 start_lineno, lines_to_process) != 0)
2868 fatal("modulus screening failed");
2869#else /* WITH_OPENSSL */
2870 fatal("Moduli screening is not supported");
2871#endif /* WITH_OPENSSL */
2872}
2873
2874static void
2762usage(void) 2875usage(void)
2763{ 2876{
2764 fprintf(stderr, 2877 fprintf(stderr,
@@ -2783,9 +2896,8 @@ usage(void)
2783 " ssh-keygen -R hostname [-f known_hosts_file]\n" 2896 " ssh-keygen -R hostname [-f known_hosts_file]\n"
2784 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n" 2897 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
2785#ifdef WITH_OPENSSL 2898#ifdef WITH_OPENSSL
2786 " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n" 2899 " ssh-keygen -M generate [-O option] output\n"
2787 " ssh-keygen -f input_file -T output_file [-v] [-a rounds] [-J num_lines]\n" 2900 " ssh-keygen -M screen [-f input_file] [-O option] [-a rounds] output_file\n"
2788 " [-j start_line] [-K checkpt] [-W generator]\n"
2789#endif 2901#endif
2790 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n" 2902 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
2791 " [-n principals] [-O option] [-V validity_interval]\n" 2903 " [-n principals] [-O option] [-V validity_interval]\n"
@@ -2819,6 +2931,7 @@ main(int argc, char **argv)
2819 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; 2931 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
2820 int prefer_agent = 0, convert_to = 0, convert_from = 0; 2932 int prefer_agent = 0, convert_to = 0, convert_from = 0;
2821 int print_public = 0, print_generic = 0, cert_serial_autoinc = 0; 2933 int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
2934 int do_gen_candidates = 0, do_screen_candidates = 0;
2822 unsigned long long ull, cert_serial = 0; 2935 unsigned long long ull, cert_serial = 0;
2823 char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; 2936 char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
2824 size_t i, nopts = 0; 2937 size_t i, nopts = 0;
@@ -2828,14 +2941,6 @@ main(int argc, char **argv)
2828 const char *errstr; 2941 const char *errstr;
2829 int log_level = SYSLOG_LEVEL_INFO; 2942 int log_level = SYSLOG_LEVEL_INFO;
2830 char *sign_op = NULL; 2943 char *sign_op = NULL;
2831#ifdef WITH_OPENSSL
2832 /* Moduli generation/screening */
2833 char out_file[PATH_MAX], *checkpoint = NULL;
2834 u_int32_t memory = 0, generator_wanted = 0;
2835 int do_gen_candidates = 0, do_screen_candidates = 0;
2836 unsigned long start_lineno = 0, lines_to_process = 0;
2837 BIGNUM *start = NULL;
2838#endif
2839 2944
2840 extern int optind; 2945 extern int optind;
2841 extern char *optarg; 2946 extern char *optarg;
@@ -2860,10 +2965,10 @@ main(int argc, char **argv)
2860 2965
2861 sk_provider = getenv("SSH_SK_PROVIDER"); 2966 sk_provider = getenv("SSH_SK_PROVIDER");
2862 2967
2863 /* Remaining character: d */ 2968 /* Remaining characters: dGjJKSTW */
2864 while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvy" 2969 while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvy"
2865 "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Y:Z:" 2970 "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
2866 "a:b:f:g:j:m:n:r:s:t:w:x:z:")) != -1) { 2971 "a:b:f:g:m:n:r:s:t:w:x:z:")) != -1) {
2867 switch (opt) { 2972 switch (opt) {
2868 case 'A': 2973 case 'A':
2869 gen_all_hostkeys = 1; 2974 gen_all_hostkeys = 1;
@@ -3053,50 +3158,14 @@ main(int argc, char **argv)
3053 (errno == ERANGE && cert_serial == ULLONG_MAX)) 3158 (errno == ERANGE && cert_serial == ULLONG_MAX))
3054 fatal("Invalid serial number \"%s\"", optarg); 3159 fatal("Invalid serial number \"%s\"", optarg);
3055 break; 3160 break;
3056#ifdef WITH_OPENSSL
3057 /* Moduli generation/screening */
3058 case 'G':
3059 do_gen_candidates = 1;
3060 if (strlcpy(out_file, optarg, sizeof(out_file)) >=
3061 sizeof(out_file))
3062 fatal("Output filename too long");
3063 break;
3064 case 'J':
3065 lines_to_process = strtoul(optarg, NULL, 10);
3066 break;
3067 case 'j':
3068 start_lineno = strtoul(optarg, NULL, 10);
3069 break;
3070 case 'K':
3071 if (strlen(optarg) >= PATH_MAX)
3072 fatal("Checkpoint filename too long");
3073 checkpoint = xstrdup(optarg);
3074 break;
3075 case 'M': 3161 case 'M':
3076 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, 3162 if (strcmp(optarg, "generate") == 0)
3077 &errstr); 3163 do_gen_candidates = 1;
3078 if (errstr) 3164 else if (strcmp(optarg, "screen") == 0)
3079 fatal("Memory limit is %s: %s", errstr, optarg); 3165 do_screen_candidates = 1;
3080 break; 3166 else
3081 case 'S': 3167 fatal("Unsupported moduli option %s", optarg);
3082 /* XXX - also compare length against bits */
3083 if (BN_hex2bn(&start, optarg) == 0)
3084 fatal("Invalid start point.");
3085 break;
3086 case 'T':
3087 do_screen_candidates = 1;
3088 if (strlcpy(out_file, optarg, sizeof(out_file)) >=
3089 sizeof(out_file))
3090 fatal("Output filename too long");
3091 break;
3092 case 'W':
3093 generator_wanted = (u_int32_t)strtonum(optarg, 1,
3094 UINT_MAX, &errstr);
3095 if (errstr != NULL)
3096 fatal("Desired generator invalid: %s (%s)",
3097 optarg, errstr);
3098 break; 3168 break;
3099#endif /* WITH_OPENSSL */
3100 case '?': 3169 case '?':
3101 default: 3170 default:
3102 usage(); 3171 usage();
@@ -3163,7 +3232,8 @@ main(int argc, char **argv)
3163 error("Too few arguments."); 3232 error("Too few arguments.");
3164 usage(); 3233 usage();
3165 } 3234 }
3166 } else if (argc > 0 && !gen_krl && !check_krl) { 3235 } else if (argc > 0 && !gen_krl && !check_krl &&
3236 !do_gen_candidates && !do_screen_candidates) {
3167 error("Too many arguments."); 3237 error("Too many arguments.");
3168 usage(); 3238 usage();
3169 } 3239 }
@@ -3176,13 +3246,21 @@ main(int argc, char **argv)
3176 usage(); 3246 usage();
3177 } 3247 }
3178 if (gen_krl) { 3248 if (gen_krl) {
3249#ifdef WITH_OPENSSL
3179 do_gen_krl(pw, update_krl, ca_key_path, 3250 do_gen_krl(pw, update_krl, ca_key_path,
3180 cert_serial, identity_comment, argc, argv); 3251 cert_serial, identity_comment, argc, argv);
3181 return (0); 3252 return (0);
3253#else
3254 fatal("KRL generation not supported");
3255#endif
3182 } 3256 }
3183 if (check_krl) { 3257 if (check_krl) {
3258#ifdef WITH_OPENSSL
3184 do_check_krl(pw, argc, argv); 3259 do_check_krl(pw, argc, argv);
3185 return (0); 3260 return (0);
3261#else
3262 fatal("KRL checking not supported");
3263#endif
3186 } 3264 }
3187 if (ca_key_path != NULL) { 3265 if (ca_key_path != NULL) {
3188 if (cert_key_id == NULL) 3266 if (cert_key_id == NULL)
@@ -3249,47 +3327,20 @@ main(int argc, char **argv)
3249 } 3327 }
3250 } 3328 }
3251 3329
3252#ifdef WITH_OPENSSL 3330 if (do_gen_candidates || do_screen_candidates) {
3331 if (argc <= 0)
3332 fatal("No output file specified");
3333 else if (argc > 1)
3334 fatal("Too many output files specified");
3335 }
3253 if (do_gen_candidates) { 3336 if (do_gen_candidates) {
3254 FILE *out = fopen(out_file, "w"); 3337 do_moduli_gen(argv[0], opts, nopts);
3255 3338 return 0;
3256 if (out == NULL) {
3257 error("Couldn't open modulus candidate file \"%s\": %s",
3258 out_file, strerror(errno));
3259 return (1);
3260 }
3261 if (bits == 0)
3262 bits = DEFAULT_BITS;
3263 if (gen_candidates(out, memory, bits, start) != 0)
3264 fatal("modulus candidate generation failed");
3265
3266 return (0);
3267 } 3339 }
3268
3269 if (do_screen_candidates) { 3340 if (do_screen_candidates) {
3270 FILE *in; 3341 do_moduli_screen(argv[0], opts, nopts);
3271 FILE *out = fopen(out_file, "a"); 3342 return 0;
3272
3273 if (have_identity && strcmp(identity_file, "-") != 0) {
3274 if ((in = fopen(identity_file, "r")) == NULL) {
3275 fatal("Couldn't open modulus candidate "
3276 "file \"%s\": %s", identity_file,
3277 strerror(errno));
3278 }
3279 } else
3280 in = stdin;
3281
3282 if (out == NULL) {
3283 fatal("Couldn't open moduli file \"%s\": %s",
3284 out_file, strerror(errno));
3285 }
3286 if (prime_test(in, out, rounds == 0 ? 100 : rounds,
3287 generator_wanted, checkpoint,
3288 start_lineno, lines_to_process) != 0)
3289 fatal("modulus screening failed");
3290 return (0);
3291 } 3343 }
3292#endif
3293 3344
3294 if (gen_all_hostkeys) { 3345 if (gen_all_hostkeys) {
3295 do_gen_all_hostkeys(pw); 3346 do_gen_all_hostkeys(pw);