[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r10632: added AES-CBC encryption/decryption and base32 decoding (tor/branches/114-dist-storage/src/common)
Author: kloesing
Date: 2007-06-17 07:07:22 -0400 (Sun, 17 Jun 2007)
New Revision: 10632
Modified:
tor/branches/114-dist-storage/src/common/crypto.c
tor/branches/114-dist-storage/src/common/crypto.h
Log:
added AES-CBC encryption/decryption and base32 decoding
Modified: tor/branches/114-dist-storage/src/common/crypto.c
===================================================================
--- tor/branches/114-dist-storage/src/common/crypto.c 2007-06-17 10:36:13 UTC (rev 10631)
+++ tor/branches/114-dist-storage/src/common/crypto.c 2007-06-17 11:07:22 UTC (rev 10632)
@@ -1144,6 +1144,117 @@
return 0;
}
+/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the symmetric key
+ * <b>key</b> of 16 bytes length to <b>to</b>. The length of <b>to</b> needs to
+ * be the length of <b>from</b> plus 32 (up to 16 bytes for padding and exactly
+ * 16 bytes for the initialization vector). On success, return the number of
+ * bytes written, on failure, return -1
+ */
+int
+crypto_cipher_encrypt_cbc(char *key, char *to, const char *from,
+ size_t fromlen)
+{
+
+ int outlen, tmplen;
+ unsigned char iv[16];
+ EVP_CIPHER_CTX ctx;
+
+ tor_assert(key);
+ tor_assert(to);
+ tor_assert(from);
+ tor_assert(fromlen);
+
+ /* generate random initialization vector and write it to the first 16 bytes
+ * of the result*/
+ crypto_rand((char *)iv, 16);
+
+ /* copy initialization vector to result */
+ memcpy((unsigned char *)to, iv, 16);
+
+ /* initialize cipher contex */
+ EVP_CIPHER_CTX_init(&ctx);
+
+ /* set up cipher context for encryption with cipher type AES-128 in CBC mode,
+ * default implementation, given key, and initialization vector */
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, (unsigned char *)key, iv);
+
+ /* encrypt fromlen bytes from buffer from and write the encrypted version to
+ * buffer to */
+ if(!EVP_EncryptUpdate(&ctx, ((unsigned char *)to) + 16, &outlen,
+ (const unsigned char *)from, (int)fromlen)) {
+ crypto_log_errors(LOG_WARN, "encrypting");
+ return -1;
+ }
+
+ /* encrypt the final data */
+ if(!EVP_EncryptFinal_ex(&ctx, ((unsigned char *)to) + 16 + outlen, &tmplen)) {
+ crypto_log_errors(LOG_WARN, "encrypting the final data");
+ return -1;
+ }
+ outlen += tmplen;
+
+ /* clear all information from cipher context and free up any allocated memory
+ * associate with it */
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ /* return number of written bytes */
+ return outlen + 16;
+}
+
+/** Decrypt <b>fromlen</b> bytes from <b>from</b> with the symmetric key
+ * <b>key</b> of 16 bytes length to <b>to</b>. The length of <b>to</b> may be
+ * the length of <b>from</b> minus 16 (up to 16 bytes for padding and exactly
+ * 16 bytes for the initialization vector). On success, return the number of
+ * bytes written, on failure, return -1
+ */
+int
+crypto_cipher_decrypt_cbc(char *key, char *to, const char *from,
+ size_t fromlen)
+{
+
+ int outlen, tmplen;
+ unsigned char iv[16];
+ EVP_CIPHER_CTX ctx;
+
+ tor_assert(key);
+ tor_assert(to);
+ tor_assert(from);
+ tor_assert(fromlen);
+
+ /* copy initialization vector from buffer */
+ memcpy(iv, (unsigned const char *)from, 16);
+
+ /* initialize cipher contex */
+ EVP_CIPHER_CTX_init(&ctx);
+
+ /* set up cipher context for decryption with cipher type AES-128 in CBC mode,
+ * default implementation, given key, and initialization vector */
+ EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, (unsigned char *)key, iv);
+
+ /* decrypt fromlen-16 bytes from buffer from and write the decrypted version
+ * to buffer to */
+ if(!EVP_DecryptUpdate(&ctx, (unsigned char *)to, &outlen,
+ ((const unsigned char *)from) + 16,
+ (int)fromlen - 16)) {
+ crypto_log_errors(LOG_WARN, "decrypting");
+ return -1;
+ }
+
+ /* encrypt the final data */
+ if(!EVP_DecryptFinal_ex(&ctx, ((unsigned char *)to) + outlen, &tmplen)) {
+ crypto_log_errors(LOG_WARN, "decrypting the final data");
+ return -1;
+ }
+ outlen += tmplen;
+
+ /* clear all information from cipher context and free up any allocated memory
+ * associate with it */
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ /* return number of written bytes */
+ return outlen;
+}
+
/* SHA-1 */
/** Compute the SHA1 digest of <b>len</b> bytes in data stored in
@@ -1793,7 +1904,7 @@
tor_assert(destlen < SIZE_T_CEILING);
for (i=0,bit=0; bit < nbits; ++i, bit+=5) {
- /* set v to the 16-bit value starting at src[bits/8], 0-padded. */
+ /* set v to the 16-bit value starting at src[bit/8], 0-padded. */
v = ((uint8_t)src[bit/8]) << 8;
if (bit+5<nbits) v += (uint8_t)src[(bit/8)+1];
/* set u to the 5-bit value at the bit'th bit of src. */
@@ -1803,6 +1914,66 @@
dest[i] = '\0';
}
+/** Implements base32 decoding as in rfc3548. Limitation: Requires
+ * that srclen*5 is a multiple of 8. Returns 0 if successful, -1 otherwise.
+ */
+int
+base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
+{
+ unsigned int nbits, i, j, bit;
+ char *tmp;
+ nbits = srclen * 5;
+
+ //log_warn(LD_DIR, "srclen is %d, nbits is %d", srclen, nbits);
+
+ 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);
+
+ /* convert base32 encoded chars by the 5-bit values that they represent */
+ tmp = tor_malloc_zero(srclen);
+ for (j = 0; j < srclen; ++j) {
+ if (src[j] > 0x60 && src[j] < 0x7B) tmp[j] = src[j] - 0x61;
+ else if (src[j] > 0x31 && src[j] < 0x38) tmp[j] = src[j] - 0x18;
+ else {
+ log_warn(LD_BUG, "illegal character in base32 encoded string");
+ return -1;
+ }
+ }
+
+ /* assemble result byte-wise by applying the five possible cases */
+ for (i = 0, bit = 0; bit < nbits; ++i, bit += 8) {
+ switch (bit % 40) {
+ case 0:
+ dest[i] = (((uint8_t)tmp[(bit/5)]) << 3) +
+ (((uint8_t)tmp[(bit/5)+1]) >> 2);
+ break;
+ case 8:
+ dest[i] = (((uint8_t)tmp[(bit/5)]) << 6) +
+ (((uint8_t)tmp[(bit/5)+1]) << 1) +
+ (((uint8_t)tmp[(bit/5)+2]) >> 4);
+ break;
+ case 16:
+ dest[i] = (((uint8_t)tmp[(bit/5)]) << 4) +
+ (((uint8_t)tmp[(bit/5)+1]) >> 1);
+ break;
+ case 24:
+ dest[i] = (((uint8_t)tmp[(bit/5)]) << 7) +
+ (((uint8_t)tmp[(bit/5)+1]) << 2) +
+ (((uint8_t)tmp[(bit/5)+2]) >> 3);
+ break;
+ case 32:
+ dest[i] = (((uint8_t)tmp[(bit/5)]) << 5) +
+ ((uint8_t)tmp[(bit/5)+1]);
+ break;
+ }
+ }
+
+ tor_free(tmp);
+ tmp = NULL;
+ return 0;
+}
+
/** 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
Modified: tor/branches/114-dist-storage/src/common/crypto.h
===================================================================
--- tor/branches/114-dist-storage/src/common/crypto.h 2007-06-17 10:36:13 UTC (rev 10631)
+++ tor/branches/114-dist-storage/src/common/crypto.h 2007-06-17 11:07:22 UTC (rev 10632)
@@ -123,6 +123,11 @@
const char *from, size_t fromlen);
int crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
const char *from, size_t fromlen);
+
+int crypto_cipher_encrypt_cbc(char *key, char *to, const char *from,
+ size_t fromlen);
+int crypto_cipher_decrypt_cbc(char *key, char *to, const char *from,
+ size_t fromlen);
/* SHA-1 */
int crypto_digest(char *digest, const char *m, size_t len);
@@ -164,6 +169,7 @@
/** Characters that can appear (case-insensitively) in a base-32 encoding. */
#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
+int base32_decode(char *dest, size_t destlen, const char *src, size_t srclen);
int digest_to_base64(char *d64, const char *digest);
int digest_from_base64(char *digest, const char *d64);