crypto_pwbox.c 5.5 KB

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