cert_write.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /*
  2. * Certificate generation and signing
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. *
  7. * This file is provided under the Apache License 2.0, or the
  8. * GNU General Public License v2.0 or later.
  9. *
  10. * **********
  11. * Apache License 2.0:
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  14. * not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  21. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *
  25. * **********
  26. *
  27. * **********
  28. * GNU General Public License v2.0 or later:
  29. *
  30. * This program is free software; you can redistribute it and/or modify
  31. * it under the terms of the GNU General Public License as published by
  32. * the Free Software Foundation; either version 2 of the License, or
  33. * (at your option) any later version.
  34. *
  35. * This program is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  38. * GNU General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU General Public License along
  41. * with this program; if not, write to the Free Software Foundation, Inc.,
  42. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  43. *
  44. * **********
  45. */
  46. #if !defined(MBEDTLS_CONFIG_FILE)
  47. #include "mbedtls/config.h"
  48. #else
  49. #include MBEDTLS_CONFIG_FILE
  50. #endif
  51. #if defined(MBEDTLS_PLATFORM_C)
  52. #include "mbedtls/platform.h"
  53. #else
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #define mbedtls_printf printf
  57. #define mbedtls_exit exit
  58. #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
  59. #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
  60. #endif /* MBEDTLS_PLATFORM_C */
  61. #if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
  62. !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
  63. !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
  64. !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C) || \
  65. !defined(MBEDTLS_PEM_WRITE_C)
  66. int main( void )
  67. {
  68. mbedtls_printf( "MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
  69. "MBEDTLS_FS_IO and/or MBEDTLS_SHA256_C and/or "
  70. "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
  71. "MBEDTLS_ERROR_C not defined.\n");
  72. mbedtls_exit( 0 );
  73. }
  74. #else
  75. #include "mbedtls/x509_crt.h"
  76. #include "mbedtls/x509_csr.h"
  77. #include "mbedtls/entropy.h"
  78. #include "mbedtls/ctr_drbg.h"
  79. #include "mbedtls/md.h"
  80. #include "mbedtls/error.h"
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <string.h>
  84. #if defined(MBEDTLS_X509_CSR_PARSE_C)
  85. #define USAGE_CSR \
  86. " request_file=%%s default: (empty)\n" \
  87. " If request_file is specified, subject_key,\n" \
  88. " subject_pwd and subject_name are ignored!\n"
  89. #else
  90. #define USAGE_CSR ""
  91. #endif /* MBEDTLS_X509_CSR_PARSE_C */
  92. #define DFL_ISSUER_CRT ""
  93. #define DFL_REQUEST_FILE ""
  94. #define DFL_SUBJECT_KEY "subject.key"
  95. #define DFL_ISSUER_KEY "ca.key"
  96. #define DFL_SUBJECT_PWD ""
  97. #define DFL_ISSUER_PWD ""
  98. #define DFL_OUTPUT_FILENAME "cert.crt"
  99. #define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK"
  100. #define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK"
  101. #define DFL_NOT_BEFORE "20010101000000"
  102. #define DFL_NOT_AFTER "20301231235959"
  103. #define DFL_SERIAL "1"
  104. #define DFL_SELFSIGN 0
  105. #define DFL_IS_CA 0
  106. #define DFL_MAX_PATHLEN -1
  107. #define DFL_KEY_USAGE 0
  108. #define DFL_NS_CERT_TYPE 0
  109. #define DFL_VERSION 3
  110. #define DFL_AUTH_IDENT 1
  111. #define DFL_SUBJ_IDENT 1
  112. #define DFL_CONSTRAINTS 1
  113. #define DFL_DIGEST MBEDTLS_MD_SHA256
  114. #define USAGE \
  115. "\n usage: cert_write param=<>...\n" \
  116. "\n acceptable parameters:\n" \
  117. USAGE_CSR \
  118. " subject_key=%%s default: subject.key\n" \
  119. " subject_pwd=%%s default: (empty)\n" \
  120. " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
  121. "\n" \
  122. " issuer_crt=%%s default: (empty)\n" \
  123. " If issuer_crt is specified, issuer_name is\n" \
  124. " ignored!\n" \
  125. " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \
  126. "\n" \
  127. " selfsign=%%d default: 0 (false)\n" \
  128. " If selfsign is enabled, issuer_name and\n" \
  129. " issuer_key are required (issuer_crt and\n" \
  130. " subject_* are ignored\n" \
  131. " issuer_key=%%s default: ca.key\n" \
  132. " issuer_pwd=%%s default: (empty)\n" \
  133. " output_file=%%s default: cert.crt\n" \
  134. " serial=%%s default: 1\n" \
  135. " not_before=%%s default: 20010101000000\n"\
  136. " not_after=%%s default: 20301231235959\n"\
  137. " is_ca=%%d default: 0 (disabled)\n" \
  138. " max_pathlen=%%d default: -1 (none)\n" \
  139. " md=%%s default: SHA256\n" \
  140. " Supported values (if enabled):\n" \
  141. " MD2, MD4, MD5, RIPEMD160, SHA1,\n" \
  142. " SHA224, SHA256, SHA384, SHA512\n" \
  143. " version=%%d default: 3\n" \
  144. " Possible values: 1, 2, 3\n"\
  145. " subject_identifier=%%s default: 1\n" \
  146. " Possible values: 0, 1\n" \
  147. " (Considered for v3 only)\n"\
  148. " authority_identifier=%%s default: 1\n" \
  149. " Possible values: 0, 1\n" \
  150. " (Considered for v3 only)\n"\
  151. " basic_constraints=%%d default: 1\n" \
  152. " Possible values: 0, 1\n" \
  153. " (Considered for v3 only)\n"\
  154. " key_usage=%%s default: (empty)\n" \
  155. " Comma-separated-list of values:\n" \
  156. " digital_signature\n" \
  157. " non_repudiation\n" \
  158. " key_encipherment\n" \
  159. " data_encipherment\n" \
  160. " key_agreement\n" \
  161. " key_cert_sign\n" \
  162. " crl_sign\n" \
  163. " (Considered for v3 only)\n"\
  164. " ns_cert_type=%%s default: (empty)\n" \
  165. " Comma-separated-list of values:\n" \
  166. " ssl_client\n" \
  167. " ssl_server\n" \
  168. " email\n" \
  169. " object_signing\n" \
  170. " ssl_ca\n" \
  171. " email_ca\n" \
  172. " object_signing_ca\n" \
  173. "\n"
  174. /*
  175. * global options
  176. */
  177. struct options
  178. {
  179. const char *issuer_crt; /* filename of the issuer certificate */
  180. const char *request_file; /* filename of the certificate request */
  181. const char *subject_key; /* filename of the subject key file */
  182. const char *issuer_key; /* filename of the issuer key file */
  183. const char *subject_pwd; /* password for the subject key file */
  184. const char *issuer_pwd; /* password for the issuer key file */
  185. const char *output_file; /* where to store the constructed CRT */
  186. const char *subject_name; /* subject name for certificate */
  187. const char *issuer_name; /* issuer name for certificate */
  188. const char *not_before; /* validity period not before */
  189. const char *not_after; /* validity period not after */
  190. const char *serial; /* serial number string */
  191. int selfsign; /* selfsign the certificate */
  192. int is_ca; /* is a CA certificate */
  193. int max_pathlen; /* maximum CA path length */
  194. int authority_identifier; /* add authority identifier to CRT */
  195. int subject_identifier; /* add subject identifier to CRT */
  196. int basic_constraints; /* add basic constraints ext to CRT */
  197. int version; /* CRT version */
  198. mbedtls_md_type_t md; /* Hash used for signing */
  199. unsigned char key_usage; /* key usage flags */
  200. unsigned char ns_cert_type; /* NS cert type */
  201. } opt;
  202. int write_certificate( mbedtls_x509write_cert *crt, const char *output_file,
  203. int (*f_rng)(void *, unsigned char *, size_t),
  204. void *p_rng )
  205. {
  206. int ret;
  207. FILE *f;
  208. unsigned char output_buf[4096];
  209. size_t len = 0;
  210. memset( output_buf, 0, 4096 );
  211. if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096,
  212. f_rng, p_rng ) ) < 0 )
  213. return( ret );
  214. len = strlen( (char *) output_buf );
  215. if( ( f = fopen( output_file, "w" ) ) == NULL )
  216. return( -1 );
  217. if( fwrite( output_buf, 1, len, f ) != len )
  218. {
  219. fclose( f );
  220. return( -1 );
  221. }
  222. fclose( f );
  223. return( 0 );
  224. }
  225. int main( int argc, char *argv[] )
  226. {
  227. int ret = 1;
  228. int exit_code = MBEDTLS_EXIT_FAILURE;
  229. mbedtls_x509_crt issuer_crt;
  230. mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
  231. mbedtls_pk_context *issuer_key = &loaded_issuer_key,
  232. *subject_key = &loaded_subject_key;
  233. char buf[1024];
  234. char issuer_name[256];
  235. int i;
  236. char *p, *q, *r;
  237. #if defined(MBEDTLS_X509_CSR_PARSE_C)
  238. char subject_name[256];
  239. mbedtls_x509_csr csr;
  240. #endif
  241. mbedtls_x509write_cert crt;
  242. mbedtls_mpi serial;
  243. mbedtls_entropy_context entropy;
  244. mbedtls_ctr_drbg_context ctr_drbg;
  245. const char *pers = "crt example app";
  246. /*
  247. * Set to sane values
  248. */
  249. mbedtls_x509write_crt_init( &crt );
  250. mbedtls_pk_init( &loaded_issuer_key );
  251. mbedtls_pk_init( &loaded_subject_key );
  252. mbedtls_mpi_init( &serial );
  253. mbedtls_ctr_drbg_init( &ctr_drbg );
  254. mbedtls_entropy_init( &entropy );
  255. #if defined(MBEDTLS_X509_CSR_PARSE_C)
  256. mbedtls_x509_csr_init( &csr );
  257. #endif
  258. mbedtls_x509_crt_init( &issuer_crt );
  259. memset( buf, 0, 1024 );
  260. if( argc == 0 )
  261. {
  262. usage:
  263. mbedtls_printf( USAGE );
  264. goto exit;
  265. }
  266. opt.issuer_crt = DFL_ISSUER_CRT;
  267. opt.request_file = DFL_REQUEST_FILE;
  268. opt.subject_key = DFL_SUBJECT_KEY;
  269. opt.issuer_key = DFL_ISSUER_KEY;
  270. opt.subject_pwd = DFL_SUBJECT_PWD;
  271. opt.issuer_pwd = DFL_ISSUER_PWD;
  272. opt.output_file = DFL_OUTPUT_FILENAME;
  273. opt.subject_name = DFL_SUBJECT_NAME;
  274. opt.issuer_name = DFL_ISSUER_NAME;
  275. opt.not_before = DFL_NOT_BEFORE;
  276. opt.not_after = DFL_NOT_AFTER;
  277. opt.serial = DFL_SERIAL;
  278. opt.selfsign = DFL_SELFSIGN;
  279. opt.is_ca = DFL_IS_CA;
  280. opt.max_pathlen = DFL_MAX_PATHLEN;
  281. opt.key_usage = DFL_KEY_USAGE;
  282. opt.ns_cert_type = DFL_NS_CERT_TYPE;
  283. opt.version = DFL_VERSION - 1;
  284. opt.md = DFL_DIGEST;
  285. opt.subject_identifier = DFL_SUBJ_IDENT;
  286. opt.authority_identifier = DFL_AUTH_IDENT;
  287. opt.basic_constraints = DFL_CONSTRAINTS;
  288. for( i = 1; i < argc; i++ )
  289. {
  290. p = argv[i];
  291. if( ( q = strchr( p, '=' ) ) == NULL )
  292. goto usage;
  293. *q++ = '\0';
  294. if( strcmp( p, "request_file" ) == 0 )
  295. opt.request_file = q;
  296. else if( strcmp( p, "subject_key" ) == 0 )
  297. opt.subject_key = q;
  298. else if( strcmp( p, "issuer_key" ) == 0 )
  299. opt.issuer_key = q;
  300. else if( strcmp( p, "subject_pwd" ) == 0 )
  301. opt.subject_pwd = q;
  302. else if( strcmp( p, "issuer_pwd" ) == 0 )
  303. opt.issuer_pwd = q;
  304. else if( strcmp( p, "issuer_crt" ) == 0 )
  305. opt.issuer_crt = q;
  306. else if( strcmp( p, "output_file" ) == 0 )
  307. opt.output_file = q;
  308. else if( strcmp( p, "subject_name" ) == 0 )
  309. {
  310. opt.subject_name = q;
  311. }
  312. else if( strcmp( p, "issuer_name" ) == 0 )
  313. {
  314. opt.issuer_name = q;
  315. }
  316. else if( strcmp( p, "not_before" ) == 0 )
  317. {
  318. opt.not_before = q;
  319. }
  320. else if( strcmp( p, "not_after" ) == 0 )
  321. {
  322. opt.not_after = q;
  323. }
  324. else if( strcmp( p, "serial" ) == 0 )
  325. {
  326. opt.serial = q;
  327. }
  328. else if( strcmp( p, "authority_identifier" ) == 0 )
  329. {
  330. opt.authority_identifier = atoi( q );
  331. if( opt.authority_identifier != 0 &&
  332. opt.authority_identifier != 1 )
  333. {
  334. mbedtls_printf( "Invalid argument for option %s\n", p );
  335. goto usage;
  336. }
  337. }
  338. else if( strcmp( p, "subject_identifier" ) == 0 )
  339. {
  340. opt.subject_identifier = atoi( q );
  341. if( opt.subject_identifier != 0 &&
  342. opt.subject_identifier != 1 )
  343. {
  344. mbedtls_printf( "Invalid argument for option %s\n", p );
  345. goto usage;
  346. }
  347. }
  348. else if( strcmp( p, "basic_constraints" ) == 0 )
  349. {
  350. opt.basic_constraints = atoi( q );
  351. if( opt.basic_constraints != 0 &&
  352. opt.basic_constraints != 1 )
  353. {
  354. mbedtls_printf( "Invalid argument for option %s\n", p );
  355. goto usage;
  356. }
  357. }
  358. else if( strcmp( p, "md" ) == 0 )
  359. {
  360. const mbedtls_md_info_t *md_info =
  361. mbedtls_md_info_from_string( q );
  362. if( md_info == NULL )
  363. {
  364. mbedtls_printf( "Invalid argument for option %s\n", p );
  365. goto usage;
  366. }
  367. opt.md = mbedtls_md_get_type( md_info );
  368. }
  369. else if( strcmp( p, "version" ) == 0 )
  370. {
  371. opt.version = atoi( q );
  372. if( opt.version < 1 || opt.version > 3 )
  373. {
  374. mbedtls_printf( "Invalid argument for option %s\n", p );
  375. goto usage;
  376. }
  377. opt.version--;
  378. }
  379. else if( strcmp( p, "selfsign" ) == 0 )
  380. {
  381. opt.selfsign = atoi( q );
  382. if( opt.selfsign < 0 || opt.selfsign > 1 )
  383. {
  384. mbedtls_printf( "Invalid argument for option %s\n", p );
  385. goto usage;
  386. }
  387. }
  388. else if( strcmp( p, "is_ca" ) == 0 )
  389. {
  390. opt.is_ca = atoi( q );
  391. if( opt.is_ca < 0 || opt.is_ca > 1 )
  392. {
  393. mbedtls_printf( "Invalid argument for option %s\n", p );
  394. goto usage;
  395. }
  396. }
  397. else if( strcmp( p, "max_pathlen" ) == 0 )
  398. {
  399. opt.max_pathlen = atoi( q );
  400. if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
  401. {
  402. mbedtls_printf( "Invalid argument for option %s\n", p );
  403. goto usage;
  404. }
  405. }
  406. else if( strcmp( p, "key_usage" ) == 0 )
  407. {
  408. while( q != NULL )
  409. {
  410. if( ( r = strchr( q, ',' ) ) != NULL )
  411. *r++ = '\0';
  412. if( strcmp( q, "digital_signature" ) == 0 )
  413. opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
  414. else if( strcmp( q, "non_repudiation" ) == 0 )
  415. opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
  416. else if( strcmp( q, "key_encipherment" ) == 0 )
  417. opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
  418. else if( strcmp( q, "data_encipherment" ) == 0 )
  419. opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
  420. else if( strcmp( q, "key_agreement" ) == 0 )
  421. opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
  422. else if( strcmp( q, "key_cert_sign" ) == 0 )
  423. opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
  424. else if( strcmp( q, "crl_sign" ) == 0 )
  425. opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
  426. else
  427. {
  428. mbedtls_printf( "Invalid argument for option %s\n", p );
  429. goto usage;
  430. }
  431. q = r;
  432. }
  433. }
  434. else if( strcmp( p, "ns_cert_type" ) == 0 )
  435. {
  436. while( q != NULL )
  437. {
  438. if( ( r = strchr( q, ',' ) ) != NULL )
  439. *r++ = '\0';
  440. if( strcmp( q, "ssl_client" ) == 0 )
  441. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
  442. else if( strcmp( q, "ssl_server" ) == 0 )
  443. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
  444. else if( strcmp( q, "email" ) == 0 )
  445. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
  446. else if( strcmp( q, "object_signing" ) == 0 )
  447. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
  448. else if( strcmp( q, "ssl_ca" ) == 0 )
  449. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
  450. else if( strcmp( q, "email_ca" ) == 0 )
  451. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
  452. else if( strcmp( q, "object_signing_ca" ) == 0 )
  453. opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
  454. else
  455. {
  456. mbedtls_printf( "Invalid argument for option %s\n", p );
  457. goto usage;
  458. }
  459. q = r;
  460. }
  461. }
  462. else
  463. goto usage;
  464. }
  465. mbedtls_printf("\n");
  466. /*
  467. * 0. Seed the PRNG
  468. */
  469. mbedtls_printf( " . Seeding the random number generator..." );
  470. fflush( stdout );
  471. if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
  472. (const unsigned char *) pers,
  473. strlen( pers ) ) ) != 0 )
  474. {
  475. mbedtls_strerror( ret, buf, 1024 );
  476. mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n",
  477. ret, buf );
  478. goto exit;
  479. }
  480. mbedtls_printf( " ok\n" );
  481. // Parse serial to MPI
  482. //
  483. mbedtls_printf( " . Reading serial number..." );
  484. fflush( stdout );
  485. if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
  486. {
  487. mbedtls_strerror( ret, buf, 1024 );
  488. mbedtls_printf( " failed\n ! mbedtls_mpi_read_string "
  489. "returned -0x%04x - %s\n\n", -ret, buf );
  490. goto exit;
  491. }
  492. mbedtls_printf( " ok\n" );
  493. // Parse issuer certificate if present
  494. //
  495. if( !opt.selfsign && strlen( opt.issuer_crt ) )
  496. {
  497. /*
  498. * 1.0.a. Load the certificates
  499. */
  500. mbedtls_printf( " . Loading the issuer certificate ..." );
  501. fflush( stdout );
  502. if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
  503. {
  504. mbedtls_strerror( ret, buf, 1024 );
  505. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file "
  506. "returned -0x%04x - %s\n\n", -ret, buf );
  507. goto exit;
  508. }
  509. ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
  510. &issuer_crt.subject );
  511. if( ret < 0 )
  512. {
  513. mbedtls_strerror( ret, buf, 1024 );
  514. mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
  515. "returned -0x%04x - %s\n\n", -ret, buf );
  516. goto exit;
  517. }
  518. opt.issuer_name = issuer_name;
  519. mbedtls_printf( " ok\n" );
  520. }
  521. #if defined(MBEDTLS_X509_CSR_PARSE_C)
  522. // Parse certificate request if present
  523. //
  524. if( !opt.selfsign && strlen( opt.request_file ) )
  525. {
  526. /*
  527. * 1.0.b. Load the CSR
  528. */
  529. mbedtls_printf( " . Loading the certificate request ..." );
  530. fflush( stdout );
  531. if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
  532. {
  533. mbedtls_strerror( ret, buf, 1024 );
  534. mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file "
  535. "returned -0x%04x - %s\n\n", -ret, buf );
  536. goto exit;
  537. }
  538. ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name),
  539. &csr.subject );
  540. if( ret < 0 )
  541. {
  542. mbedtls_strerror( ret, buf, 1024 );
  543. mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
  544. "returned -0x%04x - %s\n\n", -ret, buf );
  545. goto exit;
  546. }
  547. opt.subject_name = subject_name;
  548. subject_key = &csr.pk;
  549. mbedtls_printf( " ok\n" );
  550. }
  551. #endif /* MBEDTLS_X509_CSR_PARSE_C */
  552. /*
  553. * 1.1. Load the keys
  554. */
  555. if( !opt.selfsign && !strlen( opt.request_file ) )
  556. {
  557. mbedtls_printf( " . Loading the subject key ..." );
  558. fflush( stdout );
  559. ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
  560. opt.subject_pwd );
  561. if( ret != 0 )
  562. {
  563. mbedtls_strerror( ret, buf, 1024 );
  564. mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
  565. "returned -0x%04x - %s\n\n", -ret, buf );
  566. goto exit;
  567. }
  568. mbedtls_printf( " ok\n" );
  569. }
  570. mbedtls_printf( " . Loading the issuer key ..." );
  571. fflush( stdout );
  572. ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
  573. opt.issuer_pwd );
  574. if( ret != 0 )
  575. {
  576. mbedtls_strerror( ret, buf, 1024 );
  577. mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
  578. "returned -x%02x - %s\n\n", -ret, buf );
  579. goto exit;
  580. }
  581. // Check if key and issuer certificate match
  582. //
  583. if( strlen( opt.issuer_crt ) )
  584. {
  585. if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key ) != 0 )
  586. {
  587. mbedtls_printf( " failed\n ! issuer_key does not match "
  588. "issuer certificate\n\n" );
  589. goto exit;
  590. }
  591. }
  592. mbedtls_printf( " ok\n" );
  593. if( opt.selfsign )
  594. {
  595. opt.subject_name = opt.issuer_name;
  596. subject_key = issuer_key;
  597. }
  598. mbedtls_x509write_crt_set_subject_key( &crt, subject_key );
  599. mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key );
  600. /*
  601. * 1.0. Check the names for validity
  602. */
  603. if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
  604. {
  605. mbedtls_strerror( ret, buf, 1024 );
  606. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name "
  607. "returned -0x%04x - %s\n\n", -ret, buf );
  608. goto exit;
  609. }
  610. if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
  611. {
  612. mbedtls_strerror( ret, buf, 1024 );
  613. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name "
  614. "returned -0x%04x - %s\n\n", -ret, buf );
  615. goto exit;
  616. }
  617. mbedtls_printf( " . Setting certificate values ..." );
  618. fflush( stdout );
  619. mbedtls_x509write_crt_set_version( &crt, opt.version );
  620. mbedtls_x509write_crt_set_md_alg( &crt, opt.md );
  621. ret = mbedtls_x509write_crt_set_serial( &crt, &serial );
  622. if( ret != 0 )
  623. {
  624. mbedtls_strerror( ret, buf, 1024 );
  625. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial "
  626. "returned -0x%04x - %s\n\n", -ret, buf );
  627. goto exit;
  628. }
  629. ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
  630. if( ret != 0 )
  631. {
  632. mbedtls_strerror( ret, buf, 1024 );
  633. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity "
  634. "returned -0x%04x - %s\n\n", -ret, buf );
  635. goto exit;
  636. }
  637. mbedtls_printf( " ok\n" );
  638. if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
  639. opt.basic_constraints != 0 )
  640. {
  641. mbedtls_printf( " . Adding the Basic Constraints extension ..." );
  642. fflush( stdout );
  643. ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca,
  644. opt.max_pathlen );
  645. if( ret != 0 )
  646. {
  647. mbedtls_strerror( ret, buf, 1024 );
  648. mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints "
  649. "returned -0x%04x - %s\n\n", -ret, buf );
  650. goto exit;
  651. }
  652. mbedtls_printf( " ok\n" );
  653. }
  654. #if defined(MBEDTLS_SHA1_C)
  655. if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
  656. opt.subject_identifier != 0 )
  657. {
  658. mbedtls_printf( " . Adding the Subject Key Identifier ..." );
  659. fflush( stdout );
  660. ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt );
  661. if( ret != 0 )
  662. {
  663. mbedtls_strerror( ret, buf, 1024 );
  664. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject"
  665. "_key_identifier returned -0x%04x - %s\n\n",
  666. -ret, buf );
  667. goto exit;
  668. }
  669. mbedtls_printf( " ok\n" );
  670. }
  671. if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
  672. opt.authority_identifier != 0 )
  673. {
  674. mbedtls_printf( " . Adding the Authority Key Identifier ..." );
  675. fflush( stdout );
  676. ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt );
  677. if( ret != 0 )
  678. {
  679. mbedtls_strerror( ret, buf, 1024 );
  680. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_"
  681. "key_identifier returned -0x%04x - %s\n\n",
  682. -ret, buf );
  683. goto exit;
  684. }
  685. mbedtls_printf( " ok\n" );
  686. }
  687. #endif /* MBEDTLS_SHA1_C */
  688. if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
  689. opt.key_usage != 0 )
  690. {
  691. mbedtls_printf( " . Adding the Key Usage extension ..." );
  692. fflush( stdout );
  693. ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage );
  694. if( ret != 0 )
  695. {
  696. mbedtls_strerror( ret, buf, 1024 );
  697. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage "
  698. "returned -0x%04x - %s\n\n", -ret, buf );
  699. goto exit;
  700. }
  701. mbedtls_printf( " ok\n" );
  702. }
  703. if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
  704. opt.ns_cert_type != 0 )
  705. {
  706. mbedtls_printf( " . Adding the NS Cert Type extension ..." );
  707. fflush( stdout );
  708. ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
  709. if( ret != 0 )
  710. {
  711. mbedtls_strerror( ret, buf, 1024 );
  712. mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type "
  713. "returned -0x%04x - %s\n\n", -ret, buf );
  714. goto exit;
  715. }
  716. mbedtls_printf( " ok\n" );
  717. }
  718. /*
  719. * 1.2. Writing the certificate
  720. */
  721. mbedtls_printf( " . Writing the certificate..." );
  722. fflush( stdout );
  723. if( ( ret = write_certificate( &crt, opt.output_file,
  724. mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  725. {
  726. mbedtls_strerror( ret, buf, 1024 );
  727. mbedtls_printf( " failed\n ! write_certificate -0x%04x - %s\n\n",
  728. -ret, buf );
  729. goto exit;
  730. }
  731. mbedtls_printf( " ok\n" );
  732. exit_code = MBEDTLS_EXIT_SUCCESS;
  733. exit:
  734. #if defined(MBEDTLS_X509_CSR_PARSE_C)
  735. mbedtls_x509_csr_free( &csr );
  736. #endif /* MBEDTLS_X509_CSR_PARSE_C */
  737. mbedtls_x509_crt_free( &issuer_crt );
  738. mbedtls_x509write_crt_free( &crt );
  739. mbedtls_pk_free( &loaded_subject_key );
  740. mbedtls_pk_free( &loaded_issuer_key );
  741. mbedtls_mpi_free( &serial );
  742. mbedtls_ctr_drbg_free( &ctr_drbg );
  743. mbedtls_entropy_free( &entropy );
  744. #if defined(_WIN32)
  745. mbedtls_printf( " + Press Enter to exit this program.\n" );
  746. fflush( stdout ); getchar();
  747. #endif
  748. mbedtls_exit( exit_code );
  749. }
  750. #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
  751. MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
  752. MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */