gen_key.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * Key generation application
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  8. * not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. #include "mbedtls/build_info.h"
  20. #include "mbedtls/platform.h"
  21. #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) && \
  22. defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
  23. #include "mbedtls/error.h"
  24. #include "mbedtls/pk.h"
  25. #include "mbedtls/ecdsa.h"
  26. #include "mbedtls/rsa.h"
  27. #include "mbedtls/error.h"
  28. #include "mbedtls/entropy.h"
  29. #include "mbedtls/ctr_drbg.h"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #if !defined(_WIN32)
  34. #include <unistd.h>
  35. #define DEV_RANDOM_THRESHOLD 32
  36. int dev_random_entropy_poll(void *data, unsigned char *output,
  37. size_t len, size_t *olen)
  38. {
  39. FILE *file;
  40. size_t ret, left = len;
  41. unsigned char *p = output;
  42. ((void) data);
  43. *olen = 0;
  44. file = fopen("/dev/random", "rb");
  45. if (file == NULL) {
  46. return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  47. }
  48. while (left > 0) {
  49. /* /dev/random can return much less than requested. If so, try again */
  50. ret = fread(p, 1, left, file);
  51. if (ret == 0 && ferror(file)) {
  52. fclose(file);
  53. return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  54. }
  55. p += ret;
  56. left -= ret;
  57. sleep(1);
  58. }
  59. fclose(file);
  60. *olen = len;
  61. return 0;
  62. }
  63. #endif /* !_WIN32 */
  64. #endif
  65. #if defined(MBEDTLS_ECP_C)
  66. #define DFL_EC_CURVE mbedtls_ecp_curve_list()->grp_id
  67. #else
  68. #define DFL_EC_CURVE 0
  69. #endif
  70. #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
  71. #define USAGE_DEV_RANDOM \
  72. " use_dev_random=0|1 default: 0\n"
  73. #else
  74. #define USAGE_DEV_RANDOM ""
  75. #endif /* !_WIN32 && MBEDTLS_FS_IO */
  76. #define FORMAT_PEM 0
  77. #define FORMAT_DER 1
  78. #define DFL_TYPE MBEDTLS_PK_RSA
  79. #define DFL_RSA_KEYSIZE 4096
  80. #define DFL_FILENAME "keyfile.key"
  81. #define DFL_FORMAT FORMAT_PEM
  82. #define DFL_USE_DEV_RANDOM 0
  83. #define USAGE \
  84. "\n usage: gen_key param=<>...\n" \
  85. "\n acceptable parameters:\n" \
  86. " type=rsa|ec default: rsa\n" \
  87. " rsa_keysize=%%d default: 4096\n" \
  88. " ec_curve=%%s see below\n" \
  89. " filename=%%s default: keyfile.key\n" \
  90. " format=pem|der default: pem\n" \
  91. USAGE_DEV_RANDOM \
  92. "\n"
  93. #if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_PEM_WRITE_C) || \
  94. !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \
  95. !defined(MBEDTLS_CTR_DRBG_C)
  96. int main(void)
  97. {
  98. mbedtls_printf("MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO and/or "
  99. "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
  100. "MBEDTLS_PEM_WRITE_C"
  101. "not defined.\n");
  102. mbedtls_exit(0);
  103. }
  104. #else
  105. /*
  106. * global options
  107. */
  108. struct options {
  109. int type; /* the type of key to generate */
  110. int rsa_keysize; /* length of key in bits */
  111. int ec_curve; /* curve identifier for EC keys */
  112. const char *filename; /* filename of the key file */
  113. int format; /* the output format to use */
  114. int use_dev_random; /* use /dev/random as entropy source */
  115. } opt;
  116. static int write_private_key(mbedtls_pk_context *key, const char *output_file)
  117. {
  118. int ret;
  119. FILE *f;
  120. unsigned char output_buf[16000];
  121. unsigned char *c = output_buf;
  122. size_t len = 0;
  123. memset(output_buf, 0, 16000);
  124. if (opt.format == FORMAT_PEM) {
  125. if ((ret = mbedtls_pk_write_key_pem(key, output_buf, 16000)) != 0) {
  126. return ret;
  127. }
  128. len = strlen((char *) output_buf);
  129. } else {
  130. if ((ret = mbedtls_pk_write_key_der(key, output_buf, 16000)) < 0) {
  131. return ret;
  132. }
  133. len = ret;
  134. c = output_buf + sizeof(output_buf) - len;
  135. }
  136. if ((f = fopen(output_file, "wb")) == NULL) {
  137. return -1;
  138. }
  139. if (fwrite(c, 1, len, f) != len) {
  140. fclose(f);
  141. return -1;
  142. }
  143. fclose(f);
  144. return 0;
  145. }
  146. int main(int argc, char *argv[])
  147. {
  148. int ret = 1;
  149. int exit_code = MBEDTLS_EXIT_FAILURE;
  150. mbedtls_pk_context key;
  151. char buf[1024];
  152. int i;
  153. char *p, *q;
  154. mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
  155. mbedtls_entropy_context entropy;
  156. mbedtls_ctr_drbg_context ctr_drbg;
  157. const char *pers = "gen_key";
  158. #if defined(MBEDTLS_ECP_C)
  159. const mbedtls_ecp_curve_info *curve_info;
  160. #endif
  161. /*
  162. * Set to sane values
  163. */
  164. mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
  165. mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
  166. mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
  167. mbedtls_pk_init(&key);
  168. mbedtls_ctr_drbg_init(&ctr_drbg);
  169. memset(buf, 0, sizeof(buf));
  170. if (argc < 2) {
  171. usage:
  172. mbedtls_printf(USAGE);
  173. #if defined(MBEDTLS_ECP_C)
  174. mbedtls_printf(" available ec_curve values:\n");
  175. curve_info = mbedtls_ecp_curve_list();
  176. mbedtls_printf(" %s (default)\n", curve_info->name);
  177. while ((++curve_info)->name != NULL) {
  178. mbedtls_printf(" %s\n", curve_info->name);
  179. }
  180. #endif /* MBEDTLS_ECP_C */
  181. goto exit;
  182. }
  183. opt.type = DFL_TYPE;
  184. opt.rsa_keysize = DFL_RSA_KEYSIZE;
  185. opt.ec_curve = DFL_EC_CURVE;
  186. opt.filename = DFL_FILENAME;
  187. opt.format = DFL_FORMAT;
  188. opt.use_dev_random = DFL_USE_DEV_RANDOM;
  189. for (i = 1; i < argc; i++) {
  190. p = argv[i];
  191. if ((q = strchr(p, '=')) == NULL) {
  192. goto usage;
  193. }
  194. *q++ = '\0';
  195. if (strcmp(p, "type") == 0) {
  196. if (strcmp(q, "rsa") == 0) {
  197. opt.type = MBEDTLS_PK_RSA;
  198. } else if (strcmp(q, "ec") == 0) {
  199. opt.type = MBEDTLS_PK_ECKEY;
  200. } else {
  201. goto usage;
  202. }
  203. } else if (strcmp(p, "format") == 0) {
  204. if (strcmp(q, "pem") == 0) {
  205. opt.format = FORMAT_PEM;
  206. } else if (strcmp(q, "der") == 0) {
  207. opt.format = FORMAT_DER;
  208. } else {
  209. goto usage;
  210. }
  211. } else if (strcmp(p, "rsa_keysize") == 0) {
  212. opt.rsa_keysize = atoi(q);
  213. if (opt.rsa_keysize < 1024 ||
  214. opt.rsa_keysize > MBEDTLS_MPI_MAX_BITS) {
  215. goto usage;
  216. }
  217. }
  218. #if defined(MBEDTLS_ECP_C)
  219. else if (strcmp(p, "ec_curve") == 0) {
  220. if ((curve_info = mbedtls_ecp_curve_info_from_name(q)) == NULL) {
  221. goto usage;
  222. }
  223. opt.ec_curve = curve_info->grp_id;
  224. }
  225. #endif
  226. else if (strcmp(p, "filename") == 0) {
  227. opt.filename = q;
  228. } else if (strcmp(p, "use_dev_random") == 0) {
  229. opt.use_dev_random = atoi(q);
  230. if (opt.use_dev_random < 0 || opt.use_dev_random > 1) {
  231. goto usage;
  232. }
  233. } else {
  234. goto usage;
  235. }
  236. }
  237. mbedtls_printf("\n . Seeding the random number generator...");
  238. fflush(stdout);
  239. mbedtls_entropy_init(&entropy);
  240. #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
  241. if (opt.use_dev_random) {
  242. if ((ret = mbedtls_entropy_add_source(&entropy, dev_random_entropy_poll,
  243. NULL, DEV_RANDOM_THRESHOLD,
  244. MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0) {
  245. mbedtls_printf(" failed\n ! mbedtls_entropy_add_source returned -0x%04x\n",
  246. (unsigned int) -ret);
  247. goto exit;
  248. }
  249. mbedtls_printf("\n Using /dev/random, so can take a long time! ");
  250. fflush(stdout);
  251. }
  252. #endif /* !_WIN32 && MBEDTLS_FS_IO */
  253. if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
  254. (const unsigned char *) pers,
  255. strlen(pers))) != 0) {
  256. mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
  257. (unsigned int) -ret);
  258. goto exit;
  259. }
  260. /*
  261. * 1.1. Generate the key
  262. */
  263. mbedtls_printf("\n . Generating the private key ...");
  264. fflush(stdout);
  265. if ((ret = mbedtls_pk_setup(&key,
  266. mbedtls_pk_info_from_type((mbedtls_pk_type_t) opt.type))) != 0) {
  267. mbedtls_printf(" failed\n ! mbedtls_pk_setup returned -0x%04x", (unsigned int) -ret);
  268. goto exit;
  269. }
  270. #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
  271. if (opt.type == MBEDTLS_PK_RSA) {
  272. ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(key), mbedtls_ctr_drbg_random, &ctr_drbg,
  273. opt.rsa_keysize, 65537);
  274. if (ret != 0) {
  275. mbedtls_printf(" failed\n ! mbedtls_rsa_gen_key returned -0x%04x",
  276. (unsigned int) -ret);
  277. goto exit;
  278. }
  279. } else
  280. #endif /* MBEDTLS_RSA_C */
  281. #if defined(MBEDTLS_ECP_C)
  282. if (opt.type == MBEDTLS_PK_ECKEY) {
  283. ret = mbedtls_ecp_gen_key((mbedtls_ecp_group_id) opt.ec_curve,
  284. mbedtls_pk_ec(key),
  285. mbedtls_ctr_drbg_random, &ctr_drbg);
  286. if (ret != 0) {
  287. mbedtls_printf(" failed\n ! mbedtls_ecp_gen_key returned -0x%04x",
  288. (unsigned int) -ret);
  289. goto exit;
  290. }
  291. } else
  292. #endif /* MBEDTLS_ECP_C */
  293. {
  294. mbedtls_printf(" failed\n ! key type not supported\n");
  295. goto exit;
  296. }
  297. /*
  298. * 1.2 Print the key
  299. */
  300. mbedtls_printf(" ok\n . Key information:\n");
  301. #if defined(MBEDTLS_RSA_C)
  302. if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
  303. mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
  304. if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
  305. (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP)) != 0) {
  306. mbedtls_printf(" failed\n ! could not export RSA parameters\n\n");
  307. goto exit;
  308. }
  309. mbedtls_mpi_write_file("N: ", &N, 16, NULL);
  310. mbedtls_mpi_write_file("E: ", &E, 16, NULL);
  311. mbedtls_mpi_write_file("D: ", &D, 16, NULL);
  312. mbedtls_mpi_write_file("P: ", &P, 16, NULL);
  313. mbedtls_mpi_write_file("Q: ", &Q, 16, NULL);
  314. mbedtls_mpi_write_file("DP: ", &DP, 16, NULL);
  315. mbedtls_mpi_write_file("DQ: ", &DQ, 16, NULL);
  316. mbedtls_mpi_write_file("QP: ", &QP, 16, NULL);
  317. } else
  318. #endif
  319. #if defined(MBEDTLS_ECP_C)
  320. if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
  321. mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(key);
  322. mbedtls_printf("curve: %s\n",
  323. mbedtls_ecp_curve_info_from_grp_id(ecp->MBEDTLS_PRIVATE(grp).id)->name);
  324. mbedtls_mpi_write_file("X_Q: ", &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, NULL);
  325. mbedtls_mpi_write_file("Y_Q: ", &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16, NULL);
  326. mbedtls_mpi_write_file("D: ", &ecp->MBEDTLS_PRIVATE(d), 16, NULL);
  327. } else
  328. #endif
  329. mbedtls_printf(" ! key type not supported\n");
  330. /*
  331. * 1.3 Export key
  332. */
  333. mbedtls_printf(" . Writing key to file...");
  334. if ((ret = write_private_key(&key, opt.filename)) != 0) {
  335. mbedtls_printf(" failed\n");
  336. goto exit;
  337. }
  338. mbedtls_printf(" ok\n");
  339. exit_code = MBEDTLS_EXIT_SUCCESS;
  340. exit:
  341. if (exit_code != MBEDTLS_EXIT_SUCCESS) {
  342. #ifdef MBEDTLS_ERROR_C
  343. mbedtls_strerror(ret, buf, sizeof(buf));
  344. mbedtls_printf(" - %s\n", buf);
  345. #else
  346. mbedtls_printf("\n");
  347. #endif
  348. }
  349. mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
  350. mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
  351. mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
  352. mbedtls_pk_free(&key);
  353. mbedtls_ctr_drbg_free(&ctr_drbg);
  354. mbedtls_entropy_free(&entropy);
  355. mbedtls_exit(exit_code);
  356. }
  357. #endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
  358. * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */