main.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*-
  2. * Copyright 2009 Colin Percival
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. */
  26. #include "scrypt_platform.h"
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include "getopt.h"
  32. #include "humansize.h"
  33. #include "insecure_memzero.h"
  34. #include "readpass.h"
  35. #include "scryptenc.h"
  36. #include "warnp.h"
  37. static void
  38. usage(void)
  39. {
  40. fprintf(stderr,
  41. "usage: scrypt {enc | dec} [-f] [-M maxmem]"
  42. " [-m maxmemfrac]\n"
  43. " [-t maxtime] [-v] [-P] infile [outfile]\n"
  44. " scrypt --version\n");
  45. exit(1);
  46. }
  47. int
  48. main(int argc, char *argv[])
  49. {
  50. FILE * infile;
  51. FILE * outfile;
  52. int devtty = 1;
  53. int dec = 0;
  54. size_t maxmem = 0;
  55. int force_resources = 0;
  56. uint64_t maxmem64;
  57. double maxmemfrac = 0.5;
  58. double maxtime = 300.0;
  59. const char * ch;
  60. char * passwd;
  61. int rc;
  62. int verbose = 0;
  63. WARNP_INIT;
  64. /* We should have "enc" or "dec" first. */
  65. if (argc < 2)
  66. usage();
  67. if (strcmp(argv[1], "enc") == 0) {
  68. maxmem = 0;
  69. maxmemfrac = 0.125;
  70. maxtime = 5.0;
  71. } else if (strcmp(argv[1], "dec") == 0) {
  72. dec = 1;
  73. } else if (strcmp(argv[1], "--version") == 0) {
  74. fprintf(stdout, "scrypt %s\n", PACKAGE_VERSION);
  75. exit(0);
  76. } else {
  77. warn0("First argument must be 'enc' or 'dec'.\n");
  78. usage();
  79. }
  80. argc--;
  81. argv++;
  82. /* Parse arguments. */
  83. while ((ch = GETOPT(argc, argv)) != NULL) {
  84. GETOPT_SWITCH(ch) {
  85. GETOPT_OPT("-f"):
  86. force_resources = 1;
  87. break;
  88. GETOPT_OPTARG("-M"):
  89. if (humansize_parse(optarg, &maxmem64)) {
  90. warn0("Could not parse the parameter to -M.");
  91. exit(1);
  92. }
  93. if (maxmem64 > SIZE_MAX) {
  94. warn0("The parameter to -M is too large.");
  95. exit(1);
  96. }
  97. maxmem = (size_t)maxmem64;
  98. break;
  99. GETOPT_OPTARG("-m"):
  100. maxmemfrac = strtod(optarg, NULL);
  101. break;
  102. GETOPT_OPTARG("-t"):
  103. maxtime = strtod(optarg, NULL);
  104. break;
  105. GETOPT_OPT("-v"):
  106. verbose = 1;
  107. break;
  108. GETOPT_OPT("-P"):
  109. devtty = 0;
  110. break;
  111. GETOPT_MISSING_ARG:
  112. warn0("Missing argument to %s\n", ch);
  113. usage();
  114. GETOPT_DEFAULT:
  115. warn0("illegal option -- %s\n", ch);
  116. usage();
  117. }
  118. }
  119. argc -= optind;
  120. argv += optind;
  121. /* We must have one or two parameters left. */
  122. if ((argc < 1) || (argc > 2))
  123. usage();
  124. /* If the input isn't stdin, open the file. */
  125. if (strcmp(argv[0], "-")) {
  126. if ((infile = fopen(argv[0], "rb")) == NULL) {
  127. warnp("Cannot open input file: %s", argv[0]);
  128. exit(1);
  129. }
  130. } else {
  131. infile = stdin;
  132. }
  133. /* If we have an output file, open it. */
  134. if (argc > 1) {
  135. if ((outfile = fopen(argv[1], "wb")) == NULL) {
  136. warnp("Cannot open output file: %s", argv[1]);
  137. exit(1);
  138. }
  139. } else {
  140. outfile = stdout;
  141. }
  142. /* Prompt for a password. */
  143. if (readpass(&passwd, "Please enter passphrase",
  144. (dec || !devtty) ? NULL : "Please confirm passphrase", devtty))
  145. exit(1);
  146. /* Encrypt or decrypt. */
  147. if (dec)
  148. rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
  149. strlen(passwd), maxmem, maxmemfrac, maxtime, verbose,
  150. force_resources);
  151. else
  152. rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
  153. strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);
  154. /* Zero and free the password. */
  155. insecure_memzero(passwd, strlen(passwd));
  156. free(passwd);
  157. /* Close any files we opened. */
  158. if (infile != stdin)
  159. fclose(infile);
  160. if (outfile != stdout)
  161. fclose(outfile);
  162. /* If we failed, print the right error message and exit. */
  163. if (rc != 0) {
  164. switch (rc) {
  165. case 1:
  166. warnp("Error determining amount of available memory");
  167. break;
  168. case 2:
  169. warnp("Error reading clocks");
  170. break;
  171. case 3:
  172. warnp("Error computing derived key");
  173. break;
  174. case 4:
  175. warnp("Error reading salt");
  176. break;
  177. case 5:
  178. warnp("OpenSSL error");
  179. break;
  180. case 6:
  181. warnp("Error allocating memory");
  182. break;
  183. case 7:
  184. warn0("Input is not valid scrypt-encrypted block");
  185. break;
  186. case 8:
  187. warn0("Unrecognized scrypt format version");
  188. break;
  189. case 9:
  190. warn0("Decrypting file would require too much memory");
  191. break;
  192. case 10:
  193. warn0("Decrypting file would take too much CPU time");
  194. break;
  195. case 11:
  196. warn0("Passphrase is incorrect");
  197. break;
  198. case 12:
  199. warnp("Error writing file: %s",
  200. (argc > 1) ? argv[1] : "standard output");
  201. break;
  202. case 13:
  203. warnp("Error reading file: %s", argv[0]);
  204. break;
  205. }
  206. exit(1);
  207. }
  208. return (0);
  209. }