reqgen.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the License); you may
  5. * not use this file except in compliance with the License.
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. */
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <gmssl/mem.h>
  14. #include <gmssl/hex.h>
  15. #include <gmssl/rand.h>
  16. #include <gmssl/pkcs8.h>
  17. #include <gmssl/x509.h>
  18. #include <gmssl/x509_req.h>
  19. static const char *options =
  20. "[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str"
  21. " -key pem -pass pass"
  22. " [-sm2_id str | -sm2_id_hex hex]"
  23. " [-out pem]";
  24. static char *usage =
  25. "Options\n"
  26. "\n"
  27. " -key file Private key file in PEM format\n"
  28. " -pass pass Password for decrypting private key file\n"
  29. " -sm2_id str Signer's ID in SM2 signature algorithm\n"
  30. " -sm2_id_hex hex Signer's ID in hex format\n"
  31. " When `-sm2_id` or `-sm2_id_hex` is specified,\n"
  32. " must use the same ID in other commands explicitly.\n"
  33. " If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n"
  34. " the default string '1234567812345678' is used\n"
  35. " -out file Output Certificate Request (CSR) file in PEM format\n"
  36. "\n"
  37. " Subject options\n"
  38. "\n"
  39. " -C str Country\n"
  40. " -ST str State or province name\n"
  41. " -L str Locality\n"
  42. " -O str Organization\n"
  43. " -OU str Organizational unit\n"
  44. " -CN str Common name\n"
  45. "\n"
  46. "Examples\n"
  47. "\n"
  48. " gmssl sm2keygen -pass P@ssw0rd -out key.pem\n"
  49. " gmssl reqgen -CN www.gmssl.org -key key.pem -pass P@ssw0rd -out req.pem\n"
  50. "\n";
  51. int reqgen_main(int argc, char **argv)
  52. {
  53. int ret = 1;
  54. char *prog = argv[0];
  55. char *str;
  56. // Subject
  57. uint8_t name[256];
  58. size_t namelen = 0;
  59. char *country = NULL;
  60. char *state = NULL;
  61. char *locality = NULL;
  62. char *org = NULL;
  63. char *org_unit = NULL;
  64. char *common_name = NULL;
  65. // Attributs
  66. uint8_t attrs[512];
  67. size_t attrs_len = 0;
  68. // Private Key
  69. FILE *keyfp = NULL;
  70. char *pass = NULL;
  71. SM2_KEY sm2_key;
  72. char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
  73. size_t signer_id_len = 0;
  74. // Output
  75. char *outfile = NULL;
  76. FILE *outfp = stdout;
  77. uint8_t req[1024];
  78. uint8_t *p = req;
  79. size_t reqlen = 0;
  80. argc--;
  81. argv++;
  82. if (argc < 1) {
  83. fprintf(stderr, "usage: %s %s\n", prog, options);
  84. return 1;
  85. }
  86. while (argc > 0) {
  87. if (!strcmp(*argv, "-help")) {
  88. printf("usage: gmssl %s %s\n\n", prog, options);
  89. printf("%s\n", usage);
  90. ret = 0;
  91. goto end;
  92. } else if (!strcmp(*argv, "-C")) {
  93. if (--argc < 1) goto bad;
  94. country = *(++argv);
  95. } else if (!strcmp(*argv, "-ST")) {
  96. if (--argc < 1) goto bad;
  97. state = *(++argv);
  98. } else if (!strcmp(*argv, "-L")) {
  99. if (--argc < 1) goto bad;
  100. locality = *(++argv);
  101. } else if (!strcmp(*argv, "-O")) {
  102. if (--argc < 1) goto bad;
  103. org = *(++argv);
  104. } else if (!strcmp(*argv, "-OU")) {
  105. if (--argc < 1) goto bad;
  106. org_unit = *(++argv);
  107. } else if (!strcmp(*argv, "-CN")) {
  108. if (--argc < 1) goto bad;
  109. common_name = *(++argv);
  110. } else if (!strcmp(*argv, "-key")) {
  111. if (--argc < 1) goto bad;
  112. str = *(++argv);
  113. if (!(keyfp = fopen(str, "rb"))) {
  114. fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno));
  115. goto end;
  116. }
  117. } else if (!strcmp(*argv, "-pass")) {
  118. if (--argc < 1) goto bad;
  119. pass = *(++argv);
  120. } else if (!strcmp(*argv, "-sm2_id")) {
  121. if (--argc < 1) goto bad;
  122. str = *(++argv);
  123. if (strlen(str) > sizeof(signer_id) - 1) {
  124. fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog);
  125. goto end;
  126. }
  127. strncpy(signer_id, str, sizeof(signer_id));
  128. signer_id_len = strlen(str);
  129. } else if (!strcmp(*argv, "-sm2_id_hex")) {
  130. if (--argc < 1) goto bad;
  131. str = *(++argv);
  132. if (strlen(str) > (sizeof(signer_id) - 1) * 2) {
  133. fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog);
  134. goto end;
  135. }
  136. if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) {
  137. fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog);
  138. goto end;
  139. }
  140. } else if (!strcmp(*argv, "-out")) {
  141. if (--argc < 1) goto bad;
  142. outfile = *(++argv);
  143. if (!(outfp = fopen(outfile, "wb"))) {
  144. fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
  145. goto end;
  146. }
  147. } else {
  148. fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
  149. goto end;
  150. bad:
  151. fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
  152. goto end;
  153. }
  154. argc--;
  155. argv++;
  156. }
  157. if (!common_name) {
  158. fprintf(stderr, "%s: `-CN` option required\n", prog);
  159. printf("usage: gmssl %s %s\n\n", prog, options);
  160. goto end;
  161. }
  162. if (!keyfp) {
  163. fprintf(stderr, "%s: `-key` option required\n", prog);
  164. printf("usage: gmssl %s %s\n\n", prog, options);
  165. goto end;
  166. }
  167. if (!pass) {
  168. fprintf(stderr, "%s: `-pass` option required\n", prog);
  169. printf("usage: gmssl %s %s\n\n", prog, options);
  170. goto end;
  171. }
  172. if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
  173. fprintf(stderr, "%s: load private key failed\n", prog);
  174. goto end;
  175. }
  176. if (!signer_id_len) {
  177. strcpy(signer_id, SM2_DEFAULT_ID);
  178. signer_id_len = strlen(SM2_DEFAULT_ID);
  179. }
  180. if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) {
  181. fprintf(stderr, "%s: set Subject Name error\n", prog);
  182. goto end;
  183. }
  184. if (x509_req_sign_to_der(
  185. X509_version_v1,
  186. name, namelen,
  187. &sm2_key,
  188. attrs, attrs_len,
  189. OID_sm2sign_with_sm3,
  190. &sm2_key, signer_id, signer_id_len,
  191. &p, &reqlen) != 1) {
  192. fprintf(stderr, "%s: inner error\n", prog);
  193. goto end;
  194. }
  195. if (x509_req_to_pem(req, reqlen, outfp) != 1) {
  196. fprintf(stderr, "%s: output CSR failed\n", prog);
  197. goto end;
  198. }
  199. ret = 0;
  200. end:
  201. gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
  202. if (keyfp) fclose(keyfp);
  203. if (outfile && outfp) fclose(outfp);
  204. return ret;
  205. }