diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/crypto.c | 53 | ||||
-rw-r--r-- | src/common/crypto.h | 12 |
2 files changed, 49 insertions, 16 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index e47fa5602..15b58188e 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -807,9 +807,12 @@ crypto_pk_copy_full(crypto_pk_env_t *env) * in <b>env</b>, using the padding method <b>padding</b>. On success, * write the result to <b>to</b>, and return the number of bytes * written. On failure, return -1. + * + * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be + * at least the length of the modulus of <b>env</b>. */ int -crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, +crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding) { int r; @@ -817,6 +820,7 @@ crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, tor_assert(from); tor_assert(to); tor_assert(fromlen<INT_MAX); + tor_assert(tolen >= crypto_pk_keysize(env)); r = RSA_public_encrypt((int)fromlen, (unsigned char*)from, (unsigned char*)to, @@ -832,9 +836,13 @@ crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, * in <b>env</b>, using the padding method <b>padding</b>. On success, * write the result to <b>to</b>, and return the number of bytes * written. On failure, return -1. + * + * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be + * at least the length of the modulus of <b>env</b>. */ int crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to, + size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure) { @@ -844,6 +852,7 @@ crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to, tor_assert(to); tor_assert(env->key); tor_assert(fromlen<INT_MAX); + tor_assert(tolen >= crypto_pk_keysize(env)); if (!env->key->p) /* Not a private key */ return -1; @@ -864,9 +873,13 @@ crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to, * public key in <b>env</b>, using PKCS1 padding. On success, write the * signed data to <b>to</b>, and return the number of bytes written. * On failure, return -1. + * + * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be + * at least the length of the modulus of <b>env</b>. */ int crypto_pk_public_checksig(crypto_pk_env_t *env, char *to, + size_t tolen, const char *from, size_t fromlen) { int r; @@ -874,6 +887,7 @@ crypto_pk_public_checksig(crypto_pk_env_t *env, char *to, tor_assert(from); tor_assert(to); tor_assert(fromlen < INT_MAX); + tor_assert(tolen >= crypto_pk_keysize(env)); r = RSA_public_decrypt((int)fromlen, (unsigned char*)from, (unsigned char*)to, env->key, RSA_PKCS1_PADDING); @@ -896,6 +910,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, { char digest[DIGEST_LEN]; char *buf; + size_t buflen; int r; tor_assert(env); @@ -908,8 +923,9 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, log_warn(LD_BUG, "couldn't compute digest"); return -1; } - buf = tor_malloc(crypto_pk_keysize(env)+1); - r = crypto_pk_public_checksig(env,buf,sig,siglen); + buflen = crypto_pk_keysize(env)+1; + buf = tor_malloc(buflen); + r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen); if (r != DIGEST_LEN) { log_warn(LD_CRYPTO, "Invalid signature"); tor_free(buf); @@ -929,9 +945,12 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, * <b>env</b>, using PKCS1 padding. On success, write the signature to * <b>to</b>, and return the number of bytes written. On failure, return * -1. + * + * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be + * at least the length of the modulus of <b>env</b>. */ int -crypto_pk_private_sign(crypto_pk_env_t *env, char *to, +crypto_pk_private_sign(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen) { int r; @@ -939,6 +958,7 @@ crypto_pk_private_sign(crypto_pk_env_t *env, char *to, tor_assert(from); tor_assert(to); tor_assert(fromlen < INT_MAX); + tor_assert(tolen >= crypto_pk_keysize(env)); if (!env->key->p) /* Not a private key */ return -1; @@ -957,16 +977,19 @@ crypto_pk_private_sign(crypto_pk_env_t *env, char *to, * <b>from</b>; sign the data with the private key in <b>env</b>, and * store it in <b>to</b>. Return the number of bytes written on * success, and -1 on failure. + * + * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be + * at least the length of the modulus of <b>env</b>. */ int -crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to, +crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen) { int r; char digest[DIGEST_LEN]; if (crypto_digest(digest,from,fromlen)<0) return -1; - r = crypto_pk_private_sign(env,to,digest,DIGEST_LEN); + r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN); memset(digest, 0, sizeof(digest)); return r; } @@ -990,7 +1013,7 @@ crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to, */ int crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env, - char *to, + char *to, size_t tolen, const char *from, size_t fromlen, int padding, int force) @@ -1013,8 +1036,13 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env, if (!force && fromlen+overhead <= pkeylen) { /* It all fits in a single encrypt. */ - return crypto_pk_public_encrypt(env,to,from,fromlen,padding); + return crypto_pk_public_encrypt(env,to, + tolen, + from,fromlen,padding); } + tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN); + tor_assert(tolen >= pkeylen); + cipher = crypto_new_cipher_env(); if (!cipher) return -1; if (crypto_cipher_generate_key(cipher)<0) @@ -1036,7 +1064,7 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env, /* Length of symmetrically encrypted data. */ symlen = fromlen-(pkeylen-overhead-CIPHER_KEY_LEN); - outlen = crypto_pk_public_encrypt(env,to,buf,pkeylen-overhead,padding); + outlen = crypto_pk_public_encrypt(env,to,tolen,buf,pkeylen-overhead,padding); if (outlen!=(int)pkeylen) { goto err; } @@ -1062,6 +1090,7 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env, int crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, char *to, + size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure) @@ -1075,11 +1104,12 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, pkeylen = crypto_pk_keysize(env); if (fromlen <= pkeylen) { - return crypto_pk_private_decrypt(env,to,from,fromlen,padding, + return crypto_pk_private_decrypt(env,to,tolen,from,fromlen,padding, warnOnFailure); } + buf = tor_malloc(pkeylen+1); - outlen = crypto_pk_private_decrypt(env,buf,from,pkeylen,padding, + outlen = crypto_pk_private_decrypt(env,buf,pkeylen+1,from,pkeylen,padding, warnOnFailure); if (outlen<0) { log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO, @@ -1097,6 +1127,7 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, } memcpy(to,buf+CIPHER_KEY_LEN,outlen-CIPHER_KEY_LEN); outlen -= CIPHER_KEY_LEN; + tor_assert(tolen - outlen >= fromlen - pkeylen); r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen); if (r<0) goto err; diff --git a/src/common/crypto.h b/src/common/crypto.h index 080172828..29ba36cdf 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -123,23 +123,25 @@ crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig); crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig); int crypto_pk_key_is_private(const crypto_pk_env_t *key); -int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, +int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding); -int crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to, +int crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure); -int crypto_pk_public_checksig(crypto_pk_env_t *env, char *to, +int crypto_pk_public_checksig(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen); int crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, size_t datalen, const char *sig, size_t siglen); -int crypto_pk_private_sign(crypto_pk_env_t *env, char *to, +int crypto_pk_private_sign(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen); -int crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to, +int crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to, size_t tolen, const char *from, size_t fromlen); int crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env, char *to, + size_t tolen, const char *from, size_t fromlen, int padding, int force); int crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, char *to, + size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure); |