diff options
author | Nick Mathewson <nickm@torproject.org> | 2014-08-28 12:04:22 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2014-08-28 12:04:22 -0400 |
commit | e72a5b3c070451e7762b1d22553cf077c50eb123 (patch) | |
tree | 9c8665d97fc0aa872db5f3a6058530ec7356d98f /src/common/crypto_s2k.c | |
parent | 9b2d8c4e20a57ce849395a2135ac4e720bf99c42 (diff) | |
download | tor-e72a5b3c070451e7762b1d22553cf077c50eb123.tar.gz tor-e72a5b3c070451e7762b1d22553cf077c50eb123.zip |
Move secret-to-key functionality into a separate module
I'm about to add more of these, so we might as well trudge forward.
Diffstat (limited to 'src/common/crypto_s2k.c')
-rw-r--r-- | src/common/crypto_s2k.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c new file mode 100644 index 0000000000..669ee5301b --- /dev/null +++ b/src/common/crypto_s2k.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2001, Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "crypto.h" +#include "util.h" +#include "compat.h" + +/** Implement RFC2440-style iterated-salted S2K conversion: convert the + * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte + * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier + * are a salt; the 9th byte describes how much iteration to do. + * Does not support <b>key_out_len</b> > DIGEST_LEN. + */ +void +secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret, + size_t secret_len, const char *s2k_specifier) +{ + crypto_digest_t *d; + uint8_t c; + size_t count, tmplen; + char *tmp; + tor_assert(key_out_len < SIZE_T_CEILING); + +#define EXPBIAS 6 + c = s2k_specifier[8]; + count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS); +#undef EXPBIAS + + tor_assert(key_out_len <= DIGEST_LEN); + + d = crypto_digest_new(); + tmplen = 8+secret_len; + tmp = tor_malloc(tmplen); + memcpy(tmp,s2k_specifier,8); + memcpy(tmp+8,secret,secret_len); + secret_len += 8; + while (count) { + if (count >= secret_len) { + crypto_digest_add_bytes(d, tmp, secret_len); + count -= secret_len; + } else { + crypto_digest_add_bytes(d, tmp, count); + count = 0; + } + } + crypto_digest_get_digest(d, key_out, key_out_len); + memwipe(tmp, 0, tmplen); + tor_free(tmp); + crypto_digest_free(d); +} |