summaryrefslogtreecommitdiff
path: root/src/common/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/crypto.c')
-rw-r--r--src/common/crypto.c370
1 files changed, 311 insertions, 59 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 29137a834d..e847d8c033 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -27,6 +27,7 @@
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
+#include <openssl/engine.h>
#include <openssl/rand.h>
#include <openssl/opensslv.h>
#include <openssl/bn.h>
@@ -49,9 +50,9 @@
#define CRYPTO_PRIVATE
#include "crypto.h"
-#include "log.h"
+#include "../common/torlog.h"
#include "aes.h"
-#include "util.h"
+#include "../common/util.h"
#include "container.h"
#include "compat.h"
@@ -61,6 +62,33 @@
#include <openssl/engine.h>
+#ifdef ANDROID
+/* Android's OpenSSL seems to have removed all of its Engine support. */
+#define DISABLE_ENGINES
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x00908000l
+/* On OpenSSL versions before 0.9.8, there is no working SHA256
+ * implementation, so we use Tom St Denis's nice speedy one, slightly adapted
+ * to our needs */
+#define SHA256_CTX sha256_state
+#define SHA256_Init sha256_init
+#define SHA256_Update sha256_process
+#define LTC_ARGCHK(x) tor_assert(x)
+#include "sha256.c"
+#define SHA256_Final(a,b) sha256_done(b,a)
+
+static unsigned char *
+SHA256(const unsigned char *m, size_t len, unsigned char *d)
+{
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, m, len);
+ SHA256_Final(d, &ctx);
+ return d;
+}
+#endif
+
/** Macro: is k a valid RSA public or private key? */
#define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n)
/** Macro: is k a valid RSA private key? */
@@ -94,7 +122,7 @@ struct crypto_dh_env_t {
};
static int setup_openssl_threading(void);
-static int tor_check_dh_key(BIGNUM *bn);
+static int tor_check_dh_key(int severity, BIGNUM *bn);
/** Return the number of bytes added by padding method <b>padding</b>.
*/
@@ -151,6 +179,7 @@ crypto_log_errors(int severity, const char *doing)
}
}
+#ifndef DISABLE_ENGINES
/** Log any OpenSSL engines we're using at NOTICE. */
static void
log_engine(const char *fn, ENGINE *e)
@@ -165,37 +194,82 @@ log_engine(const char *fn, ENGINE *e)
log(LOG_INFO, LD_CRYPTO, "Using default implementation for %s", fn);
}
}
+#endif
+
+#ifndef DISABLE_ENGINES
+/** Try to load an engine in a shared library via fully qualified path.
+ */
+static ENGINE *
+try_load_engine(const char *path, const char *engine)
+{
+ ENGINE *e = ENGINE_by_id("dynamic");
+ if (e) {
+ if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
+ !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
+ !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
+ !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+ ENGINE_free(e);
+ e = NULL;
+ }
+ }
+ return e;
+}
+#endif
/** Initialize the crypto library. Return 0 on success, -1 on failure.
*/
int
-crypto_global_init(int useAccel)
+crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
{
if (!_crypto_global_initialized) {
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
_crypto_global_initialized = 1;
setup_openssl_threading();
- /* XXX the below is a bug, since we can't know if we're supposed
- * to be using hardware acceleration or not. we should arrange
- * for this function to be called before init_keys. But make it
- * not complain loudly, at least until we make acceleration work. */
- if (useAccel < 0) {
- log_info(LD_CRYPTO, "Initializing OpenSSL via tor_tls_init().");
- }
if (useAccel > 0) {
+#ifdef DISABLE_ENGINES
+ (void)accelName;
+ (void)accelDir;
+ log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
+#else
+ ENGINE *e = NULL;
+
log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
ENGINE_load_builtin_engines();
- if (!ENGINE_register_all_complete())
- return -1;
-
- /* XXXX make sure this isn't leaking. */
+ ENGINE_register_all_complete();
+
+ if (accelName) {
+ if (accelDir) {
+ log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
+ " via path \"%s\".", accelName, accelDir);
+ e = try_load_engine(accelName, accelDir);
+ } else {
+ log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
+ " acceleration support.", accelName);
+ e = ENGINE_by_id(accelName);
+ }
+ if (!e) {
+ log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
+ accelName);
+ } else {
+ log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
+ accelName);
+ }
+ }
+ if (e) {
+ log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
+ " setting default ciphers.");
+ ENGINE_set_default(e, ENGINE_METHOD_ALL);
+ }
log_engine("RSA", ENGINE_get_default_RSA());
log_engine("DH", ENGINE_get_default_DH());
log_engine("RAND", ENGINE_get_default_RAND());
log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
log_engine("3DES", ENGINE_get_cipher_engine(NID_des_ede3_ecb));
log_engine("AES", ENGINE_get_cipher_engine(NID_aes_128_ecb));
+#endif
+ } else {
+ log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
}
return crypto_seed_rng(1);
}
@@ -217,7 +291,11 @@ crypto_global_cleanup(void)
EVP_cleanup();
ERR_remove_state(0);
ERR_free_strings();
+
+#ifndef DISABLE_ENGINES
ENGINE_cleanup();
+#endif
+
CONF_modules_unload(1);
CRYPTO_cleanup_all_ex_data();
#ifdef TOR_IS_MULTITHREADED
@@ -259,7 +337,8 @@ _crypto_new_pk_env_evp_pkey(EVP_PKEY *pkey)
return _crypto_new_pk_env_rsa(rsa);
}
-/** Helper, used by tor-checkkey.c. Return the RSA from a crypto_pk_env_t. */
+/** Helper, used by tor-checkkey.c and tor-gencert.c. Return the RSA from a
+ * crypto_pk_env_t. */
RSA *
_crypto_pk_env_get_rsa(crypto_pk_env_t *env)
{
@@ -321,10 +400,12 @@ crypto_new_pk_env(void)
void
crypto_free_pk_env(crypto_pk_env_t *env)
{
- tor_assert(env);
+ if (!env)
+ return;
if (--env->refs > 0)
return;
+ tor_assert(env->refs == 0);
if (env->key)
RSA_free(env->key);
@@ -347,10 +428,7 @@ crypto_create_init_cipher(const char *key, int encrypt_mode)
return NULL;
}
- if (crypto_cipher_set_key(crypto, key)) {
- crypto_log_errors(LOG_WARN, "setting symmetric key");
- goto error;
- }
+ crypto_cipher_set_key(crypto, key);
if (encrypt_mode)
r = crypto_cipher_encrypt_init_cipher(crypto);
@@ -384,7 +462,8 @@ crypto_new_cipher_env(void)
void
crypto_free_cipher_env(crypto_cipher_env_t *env)
{
- tor_assert(env);
+ if (!env)
+ return;
tor_assert(env->cipher);
aes_free_cipher(env->cipher);
@@ -394,11 +473,11 @@ crypto_free_cipher_env(crypto_cipher_env_t *env)
/* public key crypto */
-/** Generate a new public/private keypair in <b>env</b>. Return 0 on
- * success, -1 on failure.
+/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
+ * Return 0 on success, -1 on failure.
*/
int
-crypto_pk_generate_key(crypto_pk_env_t *env)
+crypto_pk_generate_key_with_bits(crypto_pk_env_t *env, int bits)
{
tor_assert(env);
@@ -406,7 +485,7 @@ crypto_pk_generate_key(crypto_pk_env_t *env)
RSA_free(env->key);
#if OPENSSL_VERSION_NUMBER < 0x00908000l
/* In OpenSSL 0.9.7, RSA_generate_key is all we have. */
- env->key = RSA_generate_key(PK_BYTES*8,65537, NULL, NULL);
+ env->key = RSA_generate_key(bits, 65537, NULL, NULL);
#else
/* In OpenSSL 0.9.8, RSA_generate_key is deprecated. */
{
@@ -419,7 +498,7 @@ crypto_pk_generate_key(crypto_pk_env_t *env)
r = RSA_new();
if (!r)
goto done;
- if (RSA_generate_key_ex(r, PK_BYTES*8, e, NULL) == -1)
+ if (RSA_generate_key_ex(r, bits, e, NULL) == -1)
goto done;
env->key = r;
@@ -705,14 +784,25 @@ crypto_pk_env_t *
crypto_pk_copy_full(crypto_pk_env_t *env)
{
RSA *new_key;
+ int privatekey = 0;
tor_assert(env);
tor_assert(env->key);
if (PRIVATE_KEY_OK(env)) {
new_key = RSAPrivateKey_dup(env->key);
+ privatekey = 1;
} else {
new_key = RSAPublicKey_dup(env->key);
}
+ if (!new_key) {
+ log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.",
+ privatekey?"private":"public");
+ crypto_log_errors(LOG_ERR,
+ privatekey ? "Duplicating a private key" :
+ "Duplicating a public key");
+ tor_fragile_assert();
+ return NULL;
+ }
return _crypto_new_pk_env_rsa(new_key);
}
@@ -1213,19 +1303,14 @@ crypto_cipher_generate_key(crypto_cipher_env_t *env)
/** Set the symmetric key for the cipher in <b>env</b> to the first
* CIPHER_KEY_LEN bytes of <b>key</b>. Does not initialize the cipher.
- * Return 0 on success, -1 on failure.
*/
-int
+void
crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key)
{
tor_assert(env);
tor_assert(key);
- if (!env->key)
- return -1;
-
memcpy(env->key, key, CIPHER_KEY_LEN);
- return 0;
}
/** Generate an initialization vector for our AES-CTR cipher; store it
@@ -1402,9 +1487,69 @@ crypto_digest(char *digest, const char *m, size_t len)
return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
}
+int
+crypto_digest256(char *digest, const char *m, size_t len,
+ digest_algorithm_t algorithm)
+{
+ tor_assert(m);
+ tor_assert(digest);
+ tor_assert(algorithm == DIGEST_SHA256);
+ return (SHA256((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
+}
+
+/** Set the digests_t in <b>ds_out</b> to contain every digest on the
+ * <b>len</b> bytes in <b>m</b> that we know how to compute. Return 0 on
+ * success, -1 on failure. */
+int
+crypto_digest_all(digests_t *ds_out, const char *m, size_t len)
+{
+ digest_algorithm_t i;
+ tor_assert(ds_out);
+ memset(ds_out, 0, sizeof(*ds_out));
+ if (crypto_digest(ds_out->d[DIGEST_SHA1], m, len) < 0)
+ return -1;
+ for (i = DIGEST_SHA256; i < N_DIGEST_ALGORITHMS; ++i) {
+ if (crypto_digest256(ds_out->d[i], m, len, i) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/** Return the name of an algorithm, as used in directory documents. */
+const char *
+crypto_digest_algorithm_get_name(digest_algorithm_t alg)
+{
+ switch (alg) {
+ case DIGEST_SHA1:
+ return "sha1";
+ case DIGEST_SHA256:
+ return "sha256";
+ default:
+ tor_fragile_assert();
+ return "??unknown_digest??";
+ }
+}
+
+/** Given the name of a digest algorithm, return its integer value, or -1 if
+ * the name is not recognized. */
+int
+crypto_digest_algorithm_parse_name(const char *name)
+{
+ if (!strcmp(name, "sha1"))
+ return DIGEST_SHA1;
+ else if (!strcmp(name, "sha256"))
+ return DIGEST_SHA256;
+ else
+ return -1;
+}
+
/** Intermediate information about the digest of a stream of data. */
struct crypto_digest_env_t {
- SHA_CTX d;
+ union {
+ SHA_CTX sha1;
+ SHA256_CTX sha2;
+ } d;
+ digest_algorithm_t algorithm : 8;
};
/** Allocate and return a new digest object.
@@ -1414,7 +1559,19 @@ crypto_new_digest_env(void)
{
crypto_digest_env_t *r;
r = tor_malloc(sizeof(crypto_digest_env_t));
- SHA1_Init(&r->d);
+ SHA1_Init(&r->d.sha1);
+ r->algorithm = DIGEST_SHA1;
+ return r;
+}
+
+crypto_digest_env_t *
+crypto_new_digest256_env(digest_algorithm_t algorithm)
+{
+ crypto_digest_env_t *r;
+ tor_assert(algorithm == DIGEST_SHA256);
+ r = tor_malloc(sizeof(crypto_digest_env_t));
+ SHA256_Init(&r->d.sha2);
+ r->algorithm = algorithm;
return r;
}
@@ -1423,6 +1580,8 @@ crypto_new_digest_env(void)
void
crypto_free_digest_env(crypto_digest_env_t *digest)
{
+ if (!digest)
+ return;
memset(digest, 0, sizeof(crypto_digest_env_t));
tor_free(digest);
}
@@ -1435,30 +1594,51 @@ crypto_digest_add_bytes(crypto_digest_env_t *digest, const char *data,
{
tor_assert(digest);
tor_assert(data);
- /* Using the SHA1_*() calls directly means we don't support doing
- * SHA1 in hardware. But so far the delay of getting the question
+ /* Using the SHA*_*() calls directly means we don't support doing
+ * SHA in hardware. But so far the delay of getting the question
* to the hardware, and hearing the answer, is likely higher than
* just doing it ourselves. Hashes are fast.
*/
- SHA1_Update(&digest->d, (void*)data, len);
+ switch (digest->algorithm) {
+ case DIGEST_SHA1:
+ SHA1_Update(&digest->d.sha1, (void*)data, len);
+ break;
+ case DIGEST_SHA256:
+ SHA256_Update(&digest->d.sha2, (void*)data, len);
+ break;
+ default:
+ tor_fragile_assert();
+ break;
+ }
}
/** Compute the hash of the data that has been passed to the digest
* object; write the first out_len bytes of the result to <b>out</b>.
- * <b>out_len</b> must be \<= DIGEST_LEN.
+ * <b>out_len</b> must be \<= DIGEST256_LEN.
*/
void
crypto_digest_get_digest(crypto_digest_env_t *digest,
char *out, size_t out_len)
{
- unsigned char r[DIGEST_LEN];
- SHA_CTX tmpctx;
+ unsigned char r[DIGEST256_LEN];
+ crypto_digest_env_t tmpenv;
tor_assert(digest);
tor_assert(out);
- tor_assert(out_len <= DIGEST_LEN);
- /* memcpy into a temporary ctx, since SHA1_Final clears the context */
- memcpy(&tmpctx, &digest->d, sizeof(SHA_CTX));
- SHA1_Final(r, &tmpctx);
+ /* memcpy into a temporary ctx, since SHA*_Final clears the context */
+ memcpy(&tmpenv, digest, sizeof(crypto_digest_env_t));
+ switch (digest->algorithm) {
+ case DIGEST_SHA1:
+ tor_assert(out_len <= DIGEST_LEN);
+ SHA1_Final(r, &tmpenv.d.sha1);
+ break;
+ case DIGEST_SHA256:
+ tor_assert(out_len <= DIGEST256_LEN);
+ SHA256_Final(r, &tmpenv.d.sha2);
+ break;
+ default:
+ tor_fragile_assert();
+ break;
+ }
memcpy(out, r, out_len);
memset(r, 0, sizeof(r));
}
@@ -1594,7 +1774,7 @@ crypto_dh_generate_public(crypto_dh_env_t *dh)
crypto_log_errors(LOG_WARN, "generating DH key");
return -1;
}
- if (tor_check_dh_key(dh->dh->pub_key)<0) {
+ if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) {
log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-"
"the-universe chances really do happen. Trying again.");
/* Free and clear the keys, so OpenSSL will actually try again. */
@@ -1641,7 +1821,7 @@ crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey, size_t pubkey_len)
* See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips.
*/
static int
-tor_check_dh_key(BIGNUM *bn)
+tor_check_dh_key(int severity, BIGNUM *bn)
{
BIGNUM *x;
char *s;
@@ -1652,13 +1832,13 @@ tor_check_dh_key(BIGNUM *bn)
init_dh_param();
BN_set_word(x, 1);
if (BN_cmp(bn,x)<=0) {
- log_warn(LD_CRYPTO, "DH key must be at least 2.");
+ log_fn(severity, LD_CRYPTO, "DH key must be at least 2.");
goto err;
}
BN_copy(x,dh_param_p);
BN_sub_word(x, 1);
if (BN_cmp(bn,x)>=0) {
- log_warn(LD_CRYPTO, "DH key must be at most p-2.");
+ log_fn(severity, LD_CRYPTO, "DH key must be at most p-2.");
goto err;
}
BN_free(x);
@@ -1666,7 +1846,7 @@ tor_check_dh_key(BIGNUM *bn)
err:
BN_free(x);
s = BN_bn2hex(bn);
- log_warn(LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
+ log_fn(severity, LD_CRYPTO, "Rejecting insecure DH key [%s]", s);
OPENSSL_free(s);
return -1;
}
@@ -1684,7 +1864,7 @@ tor_check_dh_key(BIGNUM *bn)
* where || is concatenation.)
*/
ssize_t
-crypto_dh_compute_secret(crypto_dh_env_t *dh,
+crypto_dh_compute_secret(int severity, crypto_dh_env_t *dh,
const char *pubkey, size_t pubkey_len,
char *secret_out, size_t secret_bytes_out)
{
@@ -1699,9 +1879,9 @@ crypto_dh_compute_secret(crypto_dh_env_t *dh,
if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
(int)pubkey_len, NULL)))
goto error;
- if (tor_check_dh_key(pubkey_bn)<0) {
+ if (tor_check_dh_key(severity, pubkey_bn)<0) {
/* Check for invalid public keys. */
- log_warn(LD_CRYPTO,"Rejected invalid g^x");
+ log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
goto error;
}
secret_tmp_len = crypto_dh_get_bytes(dh);
@@ -1777,7 +1957,8 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len,
void
crypto_dh_free(crypto_dh_env_t *dh)
{
- tor_assert(dh);
+ if (!dh)
+ return;
tor_assert(dh->dh);
DH_free(dh->dh);
tor_free(dh);
@@ -1802,6 +1983,14 @@ crypto_dh_free(crypto_dh_env_t *dh)
OPENSSL_VERSION_NUMBER <= 0x00907fffl) || \
(OPENSSL_VERSION_NUMBER >= 0x0090803fl))
+static void
+seed_weak_rng(void)
+{
+ unsigned seed;
+ crypto_rand((void*)&seed, sizeof(seed));
+ tor_init_weak_random(seed);
+}
+
/** Seed OpenSSL's random number generator with bytes from the operating
* system. <b>startup</b> should be true iff we have just started Tor and
* have not yet allocated a bunch of fds. Return 0 on success, -1 on failure.
@@ -1809,14 +1998,15 @@ crypto_dh_free(crypto_dh_env_t *dh)
int
crypto_seed_rng(int startup)
{
- char buf[ADD_ENTROPY];
int rand_poll_status = 0;
/* local variables */
#ifdef MS_WINDOWS
+ unsigned char buf[ADD_ENTROPY];
static int provider_set = 0;
static HCRYPTPROV provider;
#else
+ char buf[ADD_ENTROPY];
static const char *filenames[] = {
"/dev/srandom", "/dev/urandom", "/dev/random", NULL
};
@@ -1852,6 +2042,7 @@ crypto_seed_rng(int startup)
}
RAND_seed(buf, sizeof(buf));
memset(buf, 0, sizeof(buf));
+ seed_weak_rng();
return 0;
#else
for (i = 0; filenames[i]; ++i) {
@@ -1868,6 +2059,7 @@ crypto_seed_rng(int startup)
}
RAND_seed(buf, (int)sizeof(buf));
memset(buf, 0, sizeof(buf));
+ seed_weak_rng();
return 0;
}
@@ -1935,6 +2127,26 @@ crypto_rand_uint64(uint64_t max)
}
}
+/** Return a pseudorandom double d, chosen uniformly from the range
+ * 0.0 <= d < 1.0.
+ */
+double
+crypto_rand_double(void)
+{
+ /* We just use an unsigned int here; we don't really care about getting
+ * more than 32 bits of resolution */
+ unsigned int uint;
+ crypto_rand((char*)&uint, sizeof(uint));
+#if SIZEOF_INT == 4
+#define UINT_MAX_AS_DOUBLE 4294967296.0
+#elif SIZEOF_INT == 8
+#define UINT_MAX_AS_DOUBLE 1.8446744073709552e+19
+#else
+#error SIZEOF_INT is neither 4 nor 8
+#endif
+ return ((double)uint) / UINT_MAX_AS_DOUBLE;
+}
+
/** Generate and return a new random hostname starting with <b>prefix</b>,
* ending with <b>suffix</b>, and containing no less than
* <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
@@ -2195,15 +2407,54 @@ digest_from_base64(char *digest, const char *d64)
#endif
}
+/** Base-64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the
+ * trailing = and newline characters, and store the nul-terminated result in
+ * the first BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
+int
+digest256_to_base64(char *d64, const char *digest)
+{
+ char buf[256];
+ base64_encode(buf, sizeof(buf), digest, DIGEST256_LEN);
+ buf[BASE64_DIGEST256_LEN] = '\0';
+ memcpy(d64, buf, BASE64_DIGEST256_LEN+1);
+ return 0;
+}
+
+/** Given a base-64 encoded, nul-terminated digest in <b>d64</b> (without
+ * trailing newline or = characters), decode it and store the result in the
+ * first DIGEST256_LEN bytes at <b>digest</b>. */
+int
+digest256_from_base64(char *digest, const char *d64)
+{
+#ifdef USE_OPENSSL_BASE64
+ char buf_in[BASE64_DIGEST256_LEN+3];
+ char buf[256];
+ if (strlen(d64) != BASE64_DIGEST256_LEN)
+ return -1;
+ memcpy(buf_in, d64, BASE64_DIGEST256_LEN);
+ memcpy(buf_in+BASE64_DIGEST256_LEN, "=\n\0", 3);
+ if (base64_decode(buf, sizeof(buf), buf_in, strlen(buf_in)) != DIGEST256_LEN)
+ return -1;
+ memcpy(digest, buf, DIGEST256_LEN);
+ return 0;
+#else
+ if (base64_decode(digest, DIGEST256_LEN, d64, strlen(d64)) == DIGEST256_LEN)
+ return 0;
+ else
+ return -1;
+#endif
+}
+
/** Implements base32 encoding as in rfc3548. Limitation: Requires
* that srclen*8 is a multiple of 5.
*/
void
base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
{
- unsigned int i, bit, v, u;
- size_t nbits = srclen * 8;
+ unsigned int i, v, u;
+ size_t nbits = srclen * 8, bit;
+ tor_assert(srclen < SIZE_T_CEILING/8);
tor_assert((nbits%5) == 0); /* We need an even multiple of 5 bits. */
tor_assert((nbits/5)+1 <= destlen); /* We need enough space. */
tor_assert(destlen < SIZE_T_CEILING);
@@ -2227,11 +2478,12 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
{
/* XXXX we might want to rewrite this along the lines of base64_decode, if
* it ever shows up in the profile. */
- unsigned int i, j, bit;
- size_t nbits;
+ unsigned int i;
+ size_t nbits, j, bit;
char *tmp;
nbits = srclen * 5;
+ tor_assert(srclen < SIZE_T_CEILING / 5);
tor_assert((nbits%8) == 0); /* We need an even multiple of 8 bits. */
tor_assert((nbits/8) <= destlen); /* We need enough space. */
tor_assert(destlen < SIZE_T_CEILING);