diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-12-30 03:30:09 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-12-30 14:33:54 +1100 |
commit | 3e60d18fba1b502c21d64fc7e81d80bcd08a2092 (patch) | |
tree | 0ec5f0bd3e34d1290a6c1a068234d39d8d367b35 /ssh-keygen.c | |
parent | 1e645fe767f27725dc7fd7864526de34683f7daf (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.c | 249 |
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 */ |
163 | static char *openssh_format_cipher = NULL; | 163 | static 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 | */ | ||
169 | static int rounds = 0; | 166 | static int rounds = 0; |
170 | 167 | ||
171 | /* argv0 */ | 168 | /* argv0 */ |
@@ -2759,6 +2756,122 @@ done: | |||
2759 | } | 2756 | } |
2760 | 2757 | ||
2761 | static void | 2758 | static void |
2759 | do_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 | |||
2811 | static void | ||
2812 | do_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 | |||
2874 | static void | ||
2762 | usage(void) | 2875 | usage(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); |