|  | @@ -1144,6 +1144,170 @@ crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#define AES_CIPHER_BLOCK_SIZE (16)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define AES_IV_SIZE (16)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the
 | 
	
		
			
				|  |  | + * symmetric key <b>key</b> of 16 bytes length to <b>to</b> of length
 | 
	
		
			
				|  |  | + * <b>tolen</b> which needs to be <b>fromlen</b>, padded to the next 16
 | 
	
		
			
				|  |  | + * bytes, plus exactly 16 bytes for the initialization vector. On success,
 | 
	
		
			
				|  |  | + * return the number of bytes written, on failure, return -1.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +crypto_cipher_encrypt_cbc(const char *key, char *to, size_t tolen,
 | 
	
		
			
				|  |  | +                          const char *from, size_t fromlen)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
 | 
	
		
			
				|  |  | +  unsigned char iv[AES_IV_SIZE]; /* initialization vector */
 | 
	
		
			
				|  |  | +  int outlen, tmplen; /* length of encrypted strings (w/ and wo/ final data) */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  tor_assert(key);
 | 
	
		
			
				|  |  | +  tor_assert(to);
 | 
	
		
			
				|  |  | +  tor_assert(tolen >= fromlen + AES_IV_SIZE +
 | 
	
		
			
				|  |  | +                    (AES_CIPHER_BLOCK_SIZE - fromlen % AES_CIPHER_BLOCK_SIZE));
 | 
	
		
			
				|  |  | +  tor_assert(from);
 | 
	
		
			
				|  |  | +  tor_assert(fromlen > 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* generate random initialization vector */
 | 
	
		
			
				|  |  | +  crypto_rand((char *)iv, AES_IV_SIZE);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* initialize cipher context for the initialization vector */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_init(&ctx_iv);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* disable padding for encryption of initialization vector */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_set_padding(&ctx_iv, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* set up cipher context for the initialization vector for encryption with
 | 
	
		
			
				|  |  | +   * cipher type AES-128 in ECB mode, default implementation, given key, and
 | 
	
		
			
				|  |  | +   * no initialization vector */
 | 
	
		
			
				|  |  | +  EVP_EncryptInit_ex(&ctx_iv, EVP_aes_128_ecb(), NULL, (unsigned char *)key,
 | 
	
		
			
				|  |  | +                     NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* encrypt initialization vector (no padding necessary) and write it to the
 | 
	
		
			
				|  |  | +   * first 16 bytes of the result */
 | 
	
		
			
				|  |  | +  if (!EVP_EncryptUpdate(&ctx_iv, (unsigned char *)to, &outlen, iv,
 | 
	
		
			
				|  |  | +                         AES_IV_SIZE)) {
 | 
	
		
			
				|  |  | +    crypto_log_errors(LOG_WARN, "encrypting initialization vector");
 | 
	
		
			
				|  |  | +    return -1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* clear all information from cipher context for the initialization vector
 | 
	
		
			
				|  |  | +   * and free up any allocated memory associate with it */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_cleanup(&ctx_iv);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* initialize cipher context for the message */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_init(&ctx_msg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* 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_msg, 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_msg,
 | 
	
		
			
				|  |  | +                        ((unsigned char *)to) + AES_IV_SIZE, &outlen,
 | 
	
		
			
				|  |  | +                        (const unsigned char *)from, (int)fromlen)) {
 | 
	
		
			
				|  |  | +    crypto_log_errors(LOG_WARN, "encrypting");
 | 
	
		
			
				|  |  | +    return -1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* encrypt the final data */
 | 
	
		
			
				|  |  | +  if (!EVP_EncryptFinal_ex(&ctx_msg,
 | 
	
		
			
				|  |  | +                        ((unsigned char *)to) + AES_IV_SIZE + 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_msg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* return number of written bytes */
 | 
	
		
			
				|  |  | +  return outlen + AES_IV_SIZE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** Decrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the
 | 
	
		
			
				|  |  | + * symmetric key <b>key</b> of 16 bytes length to <b>to</b> of length
 | 
	
		
			
				|  |  | + * <b>tolen</b> which may be <b>fromlen</b> minus 16 for the initialization
 | 
	
		
			
				|  |  | + * vector (the size of padding cannot be determined in advance). On success,
 | 
	
		
			
				|  |  | + * return the number of bytes written, on failure (NOT including providing
 | 
	
		
			
				|  |  | + * the wrong key, which occasionally returns the correct length!), return -1.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +crypto_cipher_decrypt_cbc(const char *key, char *to, size_t tolen,
 | 
	
		
			
				|  |  | +                          const char *from, size_t fromlen)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
 | 
	
		
			
				|  |  | +  unsigned char iv[AES_IV_SIZE]; /* initialization vector */
 | 
	
		
			
				|  |  | +  int outlen, tmplen; /* length of decrypted strings (w/ and wo/ final data) */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  tor_assert(key);
 | 
	
		
			
				|  |  | +  tor_assert(to);
 | 
	
		
			
				|  |  | +  tor_assert(tolen >= fromlen - AES_IV_SIZE);
 | 
	
		
			
				|  |  | +  tor_assert(from);
 | 
	
		
			
				|  |  | +  tor_assert(fromlen > 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* initialize cipher context for the initialization vector */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_init(&ctx_iv);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* disable padding for decryption of initialization vector */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_set_padding(&ctx_iv, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* set up cipher context for the initialization vector for decryption with
 | 
	
		
			
				|  |  | +   * cipher type AES-128 in ECB mode, default implementation, given key, and
 | 
	
		
			
				|  |  | +   * no initialization vector */
 | 
	
		
			
				|  |  | +  EVP_DecryptInit_ex(&ctx_iv, EVP_aes_128_ecb(), NULL, (unsigned char *)key,
 | 
	
		
			
				|  |  | +                     NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* decrypt initialization vector (is not padded) */
 | 
	
		
			
				|  |  | +  if (!EVP_DecryptUpdate(&ctx_iv, iv, &outlen, (const unsigned char *)from,
 | 
	
		
			
				|  |  | +                         AES_IV_SIZE)) {
 | 
	
		
			
				|  |  | +    crypto_log_errors(LOG_WARN, "decrypting initialization vector");
 | 
	
		
			
				|  |  | +    return -1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* clear all information from cipher context for the initialization vector
 | 
	
		
			
				|  |  | +   * and free up any allocated memory associate with it */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_cleanup(&ctx_iv);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* initialize cipher context for the message */
 | 
	
		
			
				|  |  | +  EVP_CIPHER_CTX_init(&ctx_msg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* 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_msg, 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_msg, (unsigned char *)to, &outlen,
 | 
	
		
			
				|  |  | +                        ((const unsigned char *)from) + AES_IV_SIZE,
 | 
	
		
			
				|  |  | +                        (int)fromlen - AES_IV_SIZE)) {
 | 
	
		
			
				|  |  | +    crypto_log_errors(LOG_INFO, "decrypting");
 | 
	
		
			
				|  |  | +    return -1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* decrypt the final data */
 | 
	
		
			
				|  |  | +  if (!EVP_DecryptFinal_ex(&ctx_msg, ((unsigned char *)to) + outlen,
 | 
	
		
			
				|  |  | +                           &tmplen)) {
 | 
	
		
			
				|  |  | +    crypto_log_errors(LOG_INFO, "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_msg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /* return number of written bytes */
 | 
	
		
			
				|  |  | +  return outlen;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* SHA-1 */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Compute the SHA1 digest of <b>len</b> bytes in data stored in
 | 
	
	
		
			
				|  | @@ -1803,6 +1967,64 @@ base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
 | 
	
		
			
				|  |  |    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;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  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 to 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 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
 |