crypto_pwbox.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "crypto.h"
  2. #include "crypto_s2k.h"
  3. #include "crypto_pwbox.h"
  4. #include "di_ops.h"
  5. #include "util.h"
  6. /* 7 bytes "TORBOX0"
  7. 1 byte: header len (H)
  8. H bytes: header, denoting secret key algorithm.
  9. Round up to multiple of 128 bytes, then encrypt:
  10. 4 bytes: data len
  11. data
  12. zeros
  13. 32 bytes: HMAC-SHA256 of all previous bytes.
  14. */
  15. #define MAX_OVERHEAD (S2K_MAXLEN + 8 + 32)
  16. /**
  17. * Make an authenticated passphrase-encrypted blob to encode the
  18. * <b>input_len</b> bytes in <b>input</b> using the passphrase
  19. * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory
  20. * to hold the encrypted data, and store a pointer to that memory in
  21. * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an
  22. * argument to the passphrase-hashing function.
  23. */
  24. int
  25. crypto_pwbox(uint8_t **out, size_t *outlen_out,
  26. const uint8_t *input, size_t input_len,
  27. const char *secret, size_t secret_len,
  28. unsigned s2k_flags)
  29. {
  30. uint8_t *result, *encrypted_portion, *hmac;
  31. size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
  32. size_t result_len = encrypted_len + MAX_OVERHEAD;
  33. int spec_len;
  34. uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
  35. crypto_cipher_t *cipher;
  36. int rv;
  37. /* Allocate a buffer and put things in the right place. */
  38. result = tor_malloc_zero(result_len);
  39. memcpy(result, "TORBOX0", 7);
  40. spec_len = secret_to_key_make_specifier(result + 8,
  41. result_len - 8,
  42. s2k_flags);
  43. if (spec_len < 0 || spec_len > 255)
  44. goto err;
  45. result[7] = (uint8_t) spec_len;
  46. tor_assert(8 + spec_len + encrypted_len <= result_len);
  47. encrypted_portion = result + 8 + spec_len;
  48. hmac = encrypted_portion + encrypted_len;
  49. set_uint32(encrypted_portion, htonl(input_len));
  50. memcpy(encrypted_portion+4, input, input_len);
  51. /* Now that all the data is in position, derive some keys, encrypt, and
  52. * digest */
  53. if (secret_to_key_derivekey(keys, sizeof(keys),
  54. result+8, spec_len,
  55. secret, secret_len) < 0)
  56. goto err;
  57. cipher = crypto_cipher_new((char*)keys);
  58. crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
  59. crypto_cipher_free(cipher);
  60. crypto_hmac_sha256((char*)hmac,
  61. (const char*)keys + CIPHER_KEY_LEN,
  62. sizeof(keys)-CIPHER_KEY_LEN,
  63. (const char*)result, 8 + spec_len + encrypted_len);
  64. *out = result;
  65. *outlen_out = 8 + spec_len + encrypted_len + DIGEST256_LEN;
  66. rv = 0;
  67. goto out;
  68. err:
  69. tor_free(result);
  70. rv = -1;
  71. out:
  72. memwipe(keys, 0, sizeof(keys));
  73. return rv;
  74. }
  75. /**
  76. * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in
  77. * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes.
  78. * On success, return 0 and allocate a new chunk of memory to hold the
  79. * decrypted data, and store a pointer to that memory in *<b>out</b>, and its
  80. * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if
  81. * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is
  82. * definitely corrupt.
  83. */
  84. int
  85. crypto_unpwbox(uint8_t **out, size_t *outlen_out,
  86. const uint8_t *inp, size_t input_len,
  87. const char *secret, size_t secret_len)
  88. {
  89. uint8_t *result = NULL;
  90. const uint8_t *encrypted;
  91. uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
  92. size_t spec_bytes;
  93. uint8_t hmac[DIGEST256_LEN];
  94. uint32_t result_len;
  95. crypto_cipher_t *cipher = NULL;
  96. int rv = UNPWBOX_CORRUPTED;
  97. if (input_len < 32)
  98. goto err;
  99. if (tor_memneq(inp, "TORBOX0", 7))
  100. goto err;
  101. spec_bytes = inp[7];
  102. if (input_len < 8 + spec_bytes)
  103. goto err;
  104. /* Now derive the keys and check the hmac. */
  105. if (secret_to_key_derivekey(keys, sizeof(keys),
  106. inp+8, spec_bytes,
  107. secret, secret_len) < 0)
  108. goto err;
  109. crypto_hmac_sha256((char *)hmac,
  110. (const char*)keys + CIPHER_KEY_LEN, sizeof(keys)-CIPHER_KEY_LEN,
  111. (const char*)inp, input_len - DIGEST256_LEN);
  112. if (tor_memneq(hmac, inp + input_len - DIGEST256_LEN, DIGEST256_LEN)) {
  113. rv = UNPWBOX_BAD_SECRET;
  114. goto err;
  115. }
  116. encrypted = inp + 8 + spec_bytes;
  117. /* How long is the plaintext? */
  118. cipher = crypto_cipher_new((char*)keys);
  119. crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
  120. result_len = ntohl(result_len);
  121. if (input_len < 8 + spec_bytes + 4 + result_len + 32)
  122. goto err;
  123. /* Allocate a buffer and decrypt */
  124. result = tor_malloc_zero(result_len);
  125. crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len);
  126. *out = result;
  127. *outlen_out = result_len;
  128. rv = UNPWBOX_OKAY;
  129. goto out;
  130. err:
  131. tor_free(result);
  132. out:
  133. crypto_cipher_free(cipher);
  134. memwipe(keys, 0, sizeof(keys));
  135. return rv;
  136. }