crypto_s2k.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /* Copyright (c) 2001, Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2013, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. #include "crypto.h"
  7. #include "util.h"
  8. #include "compat.h"
  9. /** Implement RFC2440-style iterated-salted S2K conversion: convert the
  10. * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte
  11. * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier
  12. * are a salt; the 9th byte describes how much iteration to do.
  13. * Does not support <b>key_out_len</b> &gt; DIGEST_LEN.
  14. */
  15. void
  16. secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret,
  17. size_t secret_len, const char *s2k_specifier)
  18. {
  19. crypto_digest_t *d;
  20. uint8_t c;
  21. size_t count, tmplen;
  22. char *tmp;
  23. tor_assert(key_out_len < SIZE_T_CEILING);
  24. #define EXPBIAS 6
  25. c = s2k_specifier[8];
  26. count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
  27. #undef EXPBIAS
  28. tor_assert(key_out_len <= DIGEST_LEN);
  29. d = crypto_digest_new();
  30. tmplen = 8+secret_len;
  31. tmp = tor_malloc(tmplen);
  32. memcpy(tmp,s2k_specifier,8);
  33. memcpy(tmp+8,secret,secret_len);
  34. secret_len += 8;
  35. while (count) {
  36. if (count >= secret_len) {
  37. crypto_digest_add_bytes(d, tmp, secret_len);
  38. count -= secret_len;
  39. } else {
  40. crypto_digest_add_bytes(d, tmp, count);
  41. count = 0;
  42. }
  43. }
  44. crypto_digest_get_digest(d, key_out, key_out_len);
  45. memwipe(tmp, 0, tmplen);
  46. tor_free(tmp);
  47. crypto_digest_free(d);
  48. }