1 /* Copyright (C) 2012 Phil Pennock.
2 * This is distributed as part of Exim and licensed under the GPL.
3 * See the file "NOTICE" for more details.
7 * c99 $(pkg-config --cflags openssl) gen_pkcs3.c $(pkg-config --libs openssl)
18 #include <openssl/bio.h>
19 #include <openssl/bn.h>
20 #include <openssl/dh.h>
21 #include <openssl/err.h>
22 #include <openssl/pem.h>
24 extern const char *__progname;
27 void __attribute__((__noreturn__)) __attribute__((__format__(printf, 1, 2)))
28 die(const char *fmt, ...)
33 fprintf(stderr, "%s: ", __progname);
35 vfprintf(stderr, fmt, ap);
37 fprintf(stderr, "\n");
43 void __attribute__((__noreturn__))
44 die_openssl_err(const char *msg)
49 ERR_error_string_n(ERR_get_error(), err_string, sizeof(err_string));
50 die("%s: %s", msg, err_string);
55 bn_from_text(const char *text)
64 spaceless = malloc(len);
66 die("malloc(%zu) failed: %s", len, strerror(errno));
68 for (p = spaceless, q = text, end = text + len;
76 rc = BN_hex2bn(&b, spaceless);
78 if (rc != p - spaceless)
79 die("BN_hex2bn did not convert entire input; took %d of %z bytes",
91 rc = DH_check(dh, &errflags);
92 if (!rc) die_openssl_err("DH_check() could not be performed");;
94 /* We ignore DH_UNABLE_TO_CHECK_GENERATOR because some of the invocations
95 * deliberately provide generators other than 2 or 5. */
97 if (errflags & DH_CHECK_P_NOT_SAFE_PRIME)
98 die("DH_check(): p not a safe prime");
99 if (errflags & DH_NOT_SUITABLE_GENERATOR)
100 die("DH_check(): g not suitable as generator");
105 emit_c_format_dh(FILE *stream, DH *dh)
109 char *data, *end, *p, *nl;
111 bio = BIO_new(BIO_s_mem());
112 PEM_write_bio_DHparams(bio, dh);
113 length = BIO_get_mem_data(bio, &data);
115 die("no data in memory BIO to format for printing");
117 die("grr, negative length memory not supported");
120 for (p = data; p < end; /**/) {
121 nl = strchr(p, '\n');
123 fprintf(stream, "\"%s\\n\"\n/* missing final newline */\n", p);
127 fprintf(stream, "\"%s\\n\"\n", p);
133 void __attribute__((__noreturn__))
134 usage(FILE *stream, int exitcode)
136 fprintf(stream, "Usage: %s [-CPcst] <dh_p> <dh_g>\n"
137 "Both dh_p and dh_g should be hex strings representing the numbers\n"
138 "They may contain whitespace.\n"
140 " -C show C string form of PEM result\n"
141 " -P do not show PEM\n"
142 " -c run OpenSSL DH_check() on the DH object\n"
143 " -s show the parsed p and g\n"
144 " -t show text form of certificate\n"
152 main(int argc, char *argv[])
157 bool perform_dh_check = false;
158 bool show_c_form = false;
159 bool show_numbers = false;
160 bool show_pem = true;
161 bool show_text = false;
163 while ((ch = getopt(argc, argv, "CPcsth")) != -1) {
172 perform_dh_check = true;
184 die("Unknown option or missing argument -%c", optopt);
186 die("Unhandled option -%c", ch);
195 fprintf(stderr, "argc: %d\n", argc);
199 p = bn_from_text(argv[1]);
200 g = bn_from_text(argv[2]);
204 BN_print_fp(stdout, p);
206 BN_print_fp(stdout, g);
214 if (perform_dh_check)
218 DHparams_print_fp(stdout, dh);
222 emit_c_format_dh(stdout, dh);
224 PEM_write_DHparams(stdout, dh);
227 DH_free(dh); /* should free p & g too */