main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*############################################################################
  2. # Copyright 2016 Intel Corporation
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################*/
  16. /*!
  17. * \file
  18. *
  19. * \brief Signmsg example implementation.
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "util/argutil.h"
  26. #include "util/buffutil.h"
  27. #include "util/convutil.h"
  28. #include "util/envutil.h"
  29. #include "util/stdtypes.h"
  30. #include "src/signmsg.h"
  31. // Defaults
  32. #define PROGRAM_NAME ("signmsg")
  33. #define MPRIVKEYFILE_DEFAULT ("mprivkey.dat")
  34. #define PUBKEYFILE_DEFAULT ("pubkey.bin")
  35. #define SIGRL_DEFAULT (NULL)
  36. #define SIG_DEFAULT ("sig.dat")
  37. #define CACERT_DEFAULT ("cacert.bin")
  38. #define HASHALG_DEFAULT ("SHA-512")
  39. #define MPRECMPI_DEFAULT NULL
  40. #define MPRECMPO_DEFAULT NULL
  41. /// Print usage message
  42. void PrintUsage() {
  43. log_fmt(
  44. "Usage: %s [OPTION]...\n"
  45. "Create Intel(R) EPID signature of message\n"
  46. "\n"
  47. "Options:\n"
  48. "\n"
  49. "--sig=FILE write signature to FILE (default: %s)\n"
  50. "--msg=MESSAGE MESSAGE to sign\n"
  51. "--bsn=BASENAME BASENAME to sign with (default: random)\n"
  52. "--sigrl=FILE load signature based revocation list from FILE\n"
  53. "--gpubkey=FILE load group public key from FILE\n"
  54. " (default: %s)\n"
  55. "--mprivkey=FILE load member private key from FILE\n"
  56. " (default: %s)\n"
  57. "--mprecmpi=FILE load pre-computed member data from FILE\n"
  58. "--mprecmpo=FILE write pre-computed member data to FILE\n"
  59. "--hashalg=NAME SHA-256 | SHA-384 | SHA-512 (default: %s)\n"
  60. "--capubkey=FILE load IoT Issuing CA public key from FILE\n"
  61. " (default: %s)\n"
  62. "-h,--help display this help and exit\n"
  63. "-v,--verbose print status messages to stdout\n"
  64. "\n",
  65. PROGRAM_NAME, SIG_DEFAULT, PUBKEYFILE_DEFAULT, MPRIVKEYFILE_DEFAULT,
  66. HASHALG_DEFAULT, CACERT_DEFAULT);
  67. }
  68. /// Main entrypoint
  69. int main(int argc, char* argv[]) {
  70. // intermediate return value for C style functions
  71. int ret_value = EXIT_SUCCESS;
  72. // intermediate return value for EPID functions
  73. EpidStatus result = kEpidErr;
  74. // Temp option pointer
  75. char const* opt_str = 0;
  76. // User Settings
  77. // Signature file name parameter
  78. char const* sig_file = SIG_DEFAULT;
  79. // Message string parameter
  80. char const* msg_str = NULL;
  81. size_t msg_size = 0;
  82. // Basename string parameter
  83. char const* basename_str = NULL;
  84. size_t basename_size = 0;
  85. // SigRl file name parameter
  86. char const* sigrl_file = SIGRL_DEFAULT;
  87. // Group public key file name parameter
  88. char const* pubkey_file = PUBKEYFILE_DEFAULT;
  89. // Member private key file name parameter
  90. char const* mprivkey_file = MPRIVKEYFILE_DEFAULT;
  91. // Member pre-computed settings input file name parameter
  92. char const* mprecmpi_file = MPRECMPI_DEFAULT;
  93. // Member pre-computed settings output file name parameter
  94. char const* mprecmpo_file = MPRECMPO_DEFAULT;
  95. // Hash algorithm name parameter
  96. char const* hashalg_str = HASHALG_DEFAULT;
  97. // CA certificate file name parameter
  98. char const* cacert_file = CACERT_DEFAULT;
  99. // Verbose flag parameter
  100. bool verbose = false;
  101. // Buffers and computed values
  102. // Signature buffer
  103. EpidSignature* sig = NULL;
  104. size_t sig_size = 0;
  105. // SigRl file
  106. unsigned char* signed_sig_rl = NULL;
  107. size_t signed_sig_rl_size = 0;
  108. // Group public key file
  109. unsigned char* signed_pubkey = NULL;
  110. size_t signed_pubkey_size = 0;
  111. // CA certificate
  112. EpidCaCertificate cacert = {0};
  113. // Member private key buffer
  114. unsigned char* mprivkey = NULL;
  115. size_t mprivkey_size = 0;
  116. // Member pre-computed settings
  117. MemberPrecomp member_precmp = {0};
  118. // Flag that Member pre-computed settings input is valid
  119. bool use_precmp_in;
  120. // Hash algorithm
  121. HashAlg hashalg;
  122. // set program name for logging
  123. set_prog_name(PROGRAM_NAME);
  124. do {
  125. // Read command line args
  126. if (argc < 1) {
  127. PrintUsage();
  128. ret_value = EXIT_FAILURE;
  129. break;
  130. }
  131. if (CmdOptionExists(argc, argv, "--help") ||
  132. CmdOptionExists(argc, argv, "-h")) {
  133. PrintUsage();
  134. ret_value = EXIT_SUCCESS;
  135. break;
  136. }
  137. if (CmdOptionExists(argc, argv, "--verbose") ||
  138. CmdOptionExists(argc, argv, "-v")) {
  139. verbose = ToggleVerbosity();
  140. }
  141. if (0 != (opt_str = GetCmdOption(argc, argv, "--sig"))) {
  142. sig_file = opt_str;
  143. }
  144. if (0 != (opt_str = GetCmdOption(argc, argv, "--msg"))) {
  145. msg_str = opt_str;
  146. msg_size = strlen(msg_str);
  147. }
  148. if (0 != (opt_str = GetCmdOption(argc, argv, "--bsn"))) {
  149. basename_str = opt_str;
  150. basename_size = strlen(basename_str);
  151. }
  152. if (0 != (opt_str = GetCmdOption(argc, argv, "--sigrl"))) {
  153. sigrl_file = opt_str;
  154. }
  155. if (0 != (opt_str = GetCmdOption(argc, argv, "--gpubkey"))) {
  156. pubkey_file = opt_str;
  157. }
  158. if (0 != (opt_str = GetCmdOption(argc, argv, "--mprivkey"))) {
  159. mprivkey_file = opt_str;
  160. }
  161. if (0 != (opt_str = GetCmdOption(argc, argv, "--mprecmpi"))) {
  162. mprecmpi_file = opt_str;
  163. }
  164. if (0 != (opt_str = GetCmdOption(argc, argv, "--mprecmpo"))) {
  165. mprecmpo_file = opt_str;
  166. }
  167. if (0 != (opt_str = GetCmdOption(argc, argv, "--hashalg"))) {
  168. hashalg_str = opt_str;
  169. }
  170. if (0 != (opt_str = GetCmdOption(argc, argv, "--capubkey"))) {
  171. cacert_file = opt_str;
  172. }
  173. // convert command line args to usable formats
  174. // CA certificate
  175. if (0 != ReadLoud(cacert_file, &cacert, sizeof(cacert))) {
  176. ret_value = EXIT_FAILURE;
  177. break;
  178. }
  179. // Security note:
  180. // Application must confirm that IoT EPID Issuing CA certificate is
  181. // authorized by IoT EPID Root CA, e.g., signed by IoT EPID Root CA.
  182. if (!IsCaCertAuthorizedByRootCa(&cacert, sizeof(cacert))) {
  183. log_error("CA certificate is not authorized");
  184. ret_value = EXIT_FAILURE;
  185. break;
  186. }
  187. // SigRl
  188. if (FileExists(sigrl_file)) {
  189. signed_sig_rl = NewBufferFromFile(sigrl_file, &signed_sig_rl_size);
  190. if (!signed_sig_rl) {
  191. ret_value = EXIT_FAILURE;
  192. break;
  193. }
  194. if (0 != ReadLoud(sigrl_file, signed_sig_rl, signed_sig_rl_size)) {
  195. ret_value = EXIT_FAILURE;
  196. break;
  197. }
  198. }
  199. // Group public key file
  200. signed_pubkey = NewBufferFromFile(pubkey_file, &signed_pubkey_size);
  201. if (!signed_pubkey) {
  202. ret_value = EXIT_FAILURE;
  203. break;
  204. }
  205. if (0 != ReadLoud(pubkey_file, signed_pubkey, signed_pubkey_size)) {
  206. ret_value = EXIT_FAILURE;
  207. break;
  208. }
  209. // Member private key
  210. mprivkey = NewBufferFromFile(mprivkey_file, &mprivkey_size);
  211. if (!mprivkey) {
  212. ret_value = EXIT_FAILURE;
  213. break;
  214. }
  215. if (mprivkey_size != sizeof(PrivKey) &&
  216. mprivkey_size != sizeof(CompressedPrivKey)) {
  217. log_error("Private Key file size is inconsistent");
  218. ret_value = EXIT_FAILURE;
  219. break;
  220. }
  221. if (0 != ReadLoud(mprivkey_file, mprivkey, mprivkey_size)) {
  222. ret_value = EXIT_FAILURE;
  223. break;
  224. }
  225. // Load Member pre-computed settings
  226. use_precmp_in = false;
  227. if (mprecmpi_file) {
  228. if (sizeof(MemberPrecomp) != GetFileSize(mprecmpi_file)) {
  229. log_error("incorrect input precomp size");
  230. ret_value = EXIT_FAILURE;
  231. break;
  232. }
  233. use_precmp_in = true;
  234. if (0 != ReadLoud(mprecmpi_file, &member_precmp, sizeof(MemberPrecomp))) {
  235. ret_value = EXIT_FAILURE;
  236. break;
  237. }
  238. }
  239. // Hash algorithm
  240. if (!StringToHashAlg(hashalg_str, &hashalg)) {
  241. ret_value = EXIT_FAILURE;
  242. break;
  243. }
  244. if (hashalg != kSha256 && hashalg != kSha384 && hashalg != kSha512) {
  245. log_error("unsupported hash algorithm %s", HashAlgToString(hashalg));
  246. ret_value = EXIT_FAILURE;
  247. break;
  248. }
  249. // Report Settings
  250. if (verbose) {
  251. log_msg("==============================================");
  252. log_msg("Signing Message:");
  253. log_msg("");
  254. log_msg(" [in] Message Len: %d", (int)msg_size);
  255. log_msg(" [in] Message: ");
  256. PrintBuffer(msg_str, msg_size);
  257. log_msg("");
  258. log_msg(" [in] BaseName Len: %d", (int)basename_size);
  259. log_msg(" [in] BaseName: ");
  260. PrintBuffer(basename_str, basename_size);
  261. log_msg("");
  262. log_msg(" [in] SigRl Len: %d", (int)signed_sig_rl_size);
  263. log_msg(" [in] SigRl: ");
  264. PrintBuffer(signed_sig_rl, signed_sig_rl_size);
  265. log_msg("");
  266. log_msg(" [in] Group Public Key: ");
  267. PrintBuffer(signed_pubkey, signed_pubkey_size);
  268. log_msg("");
  269. log_msg(" [in] Member Private Key: ");
  270. PrintBuffer(&mprivkey, sizeof(mprivkey));
  271. log_msg("");
  272. log_msg(" [in] Hash Algorithm: %s", HashAlgToString(hashalg));
  273. log_msg("");
  274. log_msg(" [in] IoT EPID Issuing CA Certificate: ");
  275. PrintBuffer(&cacert, sizeof(cacert));
  276. if (use_precmp_in) {
  277. log_msg("");
  278. log_msg(" [in] Member PreComp: ");
  279. PrintBuffer(&member_precmp, sizeof(member_precmp));
  280. }
  281. log_msg("==============================================");
  282. }
  283. // Sign
  284. result = SignMsg(msg_str, msg_size, basename_str, basename_size,
  285. signed_sig_rl, signed_sig_rl_size, signed_pubkey,
  286. signed_pubkey_size, mprivkey, mprivkey_size, hashalg,
  287. &member_precmp, use_precmp_in, &sig, &sig_size, &cacert);
  288. // Report Result
  289. if (kEpidNoErr != result) {
  290. if (kEpidSigRevokedinSigRl == result) {
  291. log_error("signature revoked in SigRL");
  292. } else {
  293. log_error("function SignMsg returned %s", EpidStatusToString(result));
  294. ret_value = EXIT_FAILURE;
  295. break;
  296. }
  297. }
  298. if (sig && sig_size != 0) {
  299. // Store signature
  300. if (0 != WriteLoud(sig, sig_size, sig_file)) {
  301. ret_value = EXIT_FAILURE;
  302. break;
  303. }
  304. }
  305. // Store Member pre-computed settings
  306. if (mprecmpo_file) {
  307. if (0 !=
  308. WriteLoud(&member_precmp, sizeof(member_precmp), mprecmpo_file)) {
  309. ret_value = EXIT_FAILURE;
  310. break;
  311. }
  312. }
  313. // Success
  314. ret_value = EXIT_SUCCESS;
  315. } while (0);
  316. // Free allocated buffers
  317. if (sig) free(sig);
  318. if (signed_sig_rl) free(signed_sig_rl);
  319. if (signed_pubkey) free(signed_pubkey);
  320. if (mprivkey) free(mprivkey);
  321. return ret_value;
  322. }