EncryptedStream.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /* EncryptedStream.c
  2. *
  3. */
  4. #include "base64.h"
  5. #include "misc.h"
  6. #include <bdlib/src/String.h>
  7. #include <bdlib/src/base64.h>
  8. #include "EncryptedStream.h"
  9. #include <stdarg.h>
  10. #include "compat/compat.h"
  11. int EncryptedStream::loadFile (const int fd) {
  12. if (!key.length()) return bd::Stream::loadFile(fd);
  13. if (bd::Stream::loadFile(fd) == 1)
  14. return 1;
  15. bd::String in_buf;
  16. // When loading, we should never be told what format it is in, just determine it from the header.
  17. enc_flags = 0;
  18. /* Peak at the first few bytes to determine the algorithm used */
  19. if (str[0] == 0x7F && str[2] == 0x7F) {
  20. enc_flags = str[1];
  21. in_buf = str(3);
  22. } else {
  23. enc_flags |= ENC_NO_HEADER;
  24. // Old socksfile format?
  25. if (bd::String(str(0, 5)) == "+enc\n") {
  26. enc_flags |= (ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN);
  27. in_buf = str(5);
  28. } else {
  29. /* Peak at the first block to see if it matches a userfile or an old conf file */
  30. bd::String my_peek(decrypt_string(key, broken_base64Decode(str(0, 32))));
  31. if (my_peek(0, 4) == "#4v:" || my_peek(0, 2) == "! ")
  32. enc_flags |= (ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN);
  33. in_buf = str;
  34. }
  35. }
  36. bd::String IV;
  37. if (enc_flags & ENC_AES_256_CBC) {
  38. IV = in_buf(0, 16);
  39. in_buf += 16;
  40. }
  41. if (enc_flags & ENC_KEEP_NEWLINES) {
  42. bd::String buf(in_buf), line, out_buf;
  43. while (buf.length()) {
  44. line = newsplit(buf, '\n');
  45. unapply_filters(line, IV);
  46. line += '\n';
  47. out_buf += line;
  48. }
  49. in_buf = out_buf;
  50. } else {
  51. unapply_filters(in_buf, IV);
  52. }
  53. str = in_buf;
  54. return 0;
  55. }
  56. void EncryptedStream::apply_filters(bd::String& buf, const bd::String& IV) const {
  57. if (enc_flags & ENC_AES_256_CBC) {
  58. unsigned char* iv = (unsigned char*) strdup(IV.c_str());
  59. buf = encrypt_string_cbc(key, buf, iv);
  60. free(iv);
  61. } else if (enc_flags & ENC_AES_256_ECB)
  62. buf = encrypt_string(key, buf);
  63. if (enc_flags & ENC_BASE64_BROKEN)
  64. buf = broken_base64Encode(buf);
  65. if (enc_flags & ENC_BASE64)
  66. buf = bd::base64Encode(buf);
  67. }
  68. void EncryptedStream::unapply_filters(bd::String& buf, const bd::String& IV) const {
  69. if (enc_flags & ENC_BASE64_BROKEN)
  70. buf = broken_base64Decode(buf);
  71. if (enc_flags & ENC_BASE64)
  72. buf = bd::base64Decode(buf);
  73. if (enc_flags & ENC_AES_256_CBC) {
  74. unsigned char* iv = (unsigned char*) strdup(IV.c_str());
  75. buf = decrypt_string_cbc(key, buf, iv);
  76. free(iv);
  77. }
  78. else if (enc_flags & ENC_AES_256_ECB)
  79. buf = decrypt_string(key, buf);
  80. }
  81. int EncryptedStream::writeFile (const int fd) const {
  82. if (!key.length()) return bd::Stream::writeFile(fd);
  83. /* Encrypt the stream before writing it out */
  84. bd::String IV;
  85. if (enc_flags & ENC_AES_256_CBC) {
  86. char rand_string[17] = "";
  87. make_rand_str(rand_string, sizeof(rand_string) - 1);
  88. IV = bd::String(rand_string, 16);
  89. }
  90. bd::String out_buf;
  91. if (enc_flags & ENC_KEEP_NEWLINES) {
  92. bd::String buf(str), line;
  93. while (buf.length()) {
  94. line = newsplit(buf, '\n');
  95. apply_filters(line, IV);
  96. line += '\n';
  97. out_buf += line;
  98. }
  99. } else {
  100. out_buf = str;
  101. apply_filters(out_buf, IV);
  102. }
  103. if (enc_flags & ENC_NO_HEADER)
  104. return bd::Stream(out_buf).writeFile(fd);
  105. const char encoding[3] = {0x7F, enc_flags, 0x7F};
  106. bd::String encrypted(encoding, 3);
  107. if (enc_flags & ENC_AES_256_CBC)
  108. encrypted += IV;
  109. encrypted += out_buf;
  110. return bd::Stream(encrypted).writeFile(fd);
  111. }