[or-cvs] r10632: added AES-CBC encryption/decryption and base32 decoding (tor/branches/114-dist-storage/src/common)

kloesing at seul.org kloesing at seul.org
Sun Jun 17 11:07:22 UTC 2007


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);



More information about the tor-commits mailing list