aesgcm.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
  2. /* SPDX-License-Identifier: Unlicense */
  3. /**
  4. @file aesgcm.c
  5. AES128-GCM demo - file en-&decryption, Steffen Jaeckel
  6. Uses the format: |ciphertext|tag-16-bytes|
  7. */
  8. #define _GNU_SOURCE
  9. #include <tomcrypt.h>
  10. #include <stdio.h>
  11. #include <stdint.h>
  12. #include <sys/stat.h>
  13. #include <sys/types.h>
  14. #include <dirent.h>
  15. #include <string.h>
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #include "gcm-file/gcm_filehandle.c"
  20. #include "gcm-file/gcm_file.c"
  21. static off_t fsize(const char *filename)
  22. {
  23. struct stat st;
  24. if (stat(filename, &st) == 0) return st.st_size;
  25. return -1;
  26. }
  27. #if defined(__linux__) && defined(__GLIBC_PREREQ)
  28. #if __GLIBC_PREREQ(2, 14)
  29. #define HAS_SYNCFS
  30. #endif
  31. #endif
  32. static int mv(const char *old_name, const char *new_name)
  33. {
  34. int fd;
  35. if (rename(old_name, new_name) == -1) return -1;
  36. fd = open(new_name, 0);
  37. if (fd == -1) return -1;
  38. #if !defined(_WIN32)
  39. if (fsync(fd) != 0) goto OUT;
  40. #if defined(HAS_SYNCFS)
  41. syncfs(fd);
  42. #else
  43. sync();
  44. #endif
  45. OUT:
  46. #endif
  47. close(fd);
  48. return 0;
  49. }
  50. /* https://stackoverflow.com/a/23898449 */
  51. static void scan_hex(const char* str, uint8_t* bytes, size_t blen)
  52. {
  53. uint8_t pos;
  54. uint8_t idx0;
  55. uint8_t idx1;
  56. const uint8_t hashmap[] =
  57. {
  58. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
  59. 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
  60. 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */
  61. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */
  62. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */
  63. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */
  64. 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */
  65. };
  66. for (pos = 0; ((pos < (blen*2)) && (pos < XSTRLEN(str))); pos += 2)
  67. {
  68. idx0 = (uint8_t)(str[pos+0] & 0x1F) ^ 0x10;
  69. idx1 = (uint8_t)(str[pos+1] & 0x1F) ^ 0x10;
  70. bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1];
  71. }
  72. }
  73. static void die(int ret)
  74. {
  75. fprintf(stderr, "Usage: aesgcm <-e|-d> <infile> <outfile> <88|96 char hex-string 'IV | key'>\n");
  76. exit(ret);
  77. }
  78. int main(int argc, char **argv)
  79. {
  80. int ret = 0, err, arg, direction, res, tmp;
  81. size_t keylen;
  82. uint8_t keybuf[48] = {0};
  83. char *out = NULL;
  84. const char *mode, *in_file, *out_file, *key_string;
  85. unsigned long ivlen;
  86. if (argc < 5) die(__LINE__);
  87. arg = 1;
  88. mode = argv[arg++];
  89. in_file = argv[arg++];
  90. out_file = argv[arg++];
  91. key_string = argv[arg++];
  92. if(strcmp(mode, "-d") == 0) direction = GCM_DECRYPT;
  93. else if(strcmp(mode, "-e") == 0) direction = GCM_ENCRYPT;
  94. else die(__LINE__);
  95. if (fsize(in_file) <= 0) die(__LINE__);
  96. keylen = XSTRLEN(key_string);
  97. if (keylen != 88 && keylen != 96) die(__LINE__);
  98. scan_hex(key_string, keybuf, keylen/2);
  99. register_all_ciphers();
  100. if(asprintf(&out, "%s-XXXXXX", out_file) < 0) die(__LINE__);
  101. if((tmp = mkstemp(out)) == -1) {
  102. ret = __LINE__;
  103. goto cleanup;
  104. }
  105. close(tmp);
  106. ivlen = keylen/2 - 32;
  107. if((err = gcm_file(find_cipher("aes"), &keybuf[ivlen], 32, keybuf, ivlen, NULL, 0, in_file, out, 16, direction, &res)) != CRYPT_OK) {
  108. fprintf(stderr, "boooh %s\n", error_to_string(err));
  109. ret = __LINE__;
  110. goto cleanup;
  111. }
  112. if(res != 1) {
  113. ret = __LINE__;
  114. }
  115. else
  116. {
  117. if (mv(out, out_file) != 0) ret = __LINE__;
  118. }
  119. cleanup:
  120. if(ret != 0) unlink(out);
  121. free(out);
  122. return ret;
  123. }