aboutsummaryrefslogtreecommitdiff
path: root/src/common/crypto_s2k.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2014-08-28 12:04:22 -0400
committerNick Mathewson <nickm@torproject.org>2014-08-28 12:04:22 -0400
commite72a5b3c070451e7762b1d22553cf077c50eb123 (patch)
tree9c8665d97fc0aa872db5f3a6058530ec7356d98f /src/common/crypto_s2k.c
parent9b2d8c4e20a57ce849395a2135ac4e720bf99c42 (diff)
downloadtor-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.c53
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> &gt; 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);
+}