Miscellaneous fixes.
[bluesky.git] / bluesky / crypto.c
index 6eec464..fff4e0d 100644 (file)
 
 #include "bluesky.h"
 
+static int DISABLE_CRYPTO = 1;
+
 /* Cryptographic operations.  The rest of the BlueSky code merely calls into
  * the functions in this file, so this is the only point where we interface
  * with an external cryptographic library. */
 
-#define CRYPTO_BLOCK_SIZE 16        /* 128-bit AES */
-#define CRYPTO_KEY_SIZE   16
-
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
 
 void bluesky_crypt_init()
@@ -31,8 +30,6 @@ void bluesky_crypt_init()
     if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
         return;
 
-    g_print("libgcrypt not yet initialized, initializing...\n");
-
     if (!gcry_check_version(GCRYPT_VERSION))
         g_error("libgcrypt version mismatch\n");
 
@@ -49,6 +46,11 @@ void bluesky_crypt_random_bytes(guchar *buf, gint len)
 /* Encrypt a data block. */
 BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key)
 {
+    if (DISABLE_CRYPTO) {
+        bluesky_string_ref(in);
+        return in;
+    }
+
     gcry_error_t status;
     gcry_cipher_hd_t handle;
 
@@ -74,8 +76,8 @@ BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key)
                 gcry_strerror(status));
     }
 
-    gcry_cipher_encrypt(handle, out + CRYPTO_BLOCK_SIZE, in->len,
-                        in->data, in->len);
+    status = gcry_cipher_encrypt(handle, out + CRYPTO_BLOCK_SIZE, in->len,
+                                 in->data, in->len);
     if (status) {
         g_error("gcrypt error encrypting: %s\n",
                 gcry_strerror(status));
@@ -85,3 +87,50 @@ BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key)
 
     return bluesky_string_new(out, in->len + CRYPTO_BLOCK_SIZE);
 }
+
+/* Decrypt a data block. */
+BlueSkyRCStr *bluesky_crypt_decrypt(BlueSkyRCStr *in, const uint8_t *key)
+{
+    if (DISABLE_CRYPTO) {
+        bluesky_string_ref(in);
+        return in;
+    }
+
+    gcry_error_t status;
+    gcry_cipher_hd_t handle;
+
+    g_return_val_if_fail(in->len > CRYPTO_BLOCK_SIZE, NULL);
+
+    status = gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC,
+                              GCRY_CIPHER_CBC_CTS);
+    if (status) {
+        g_error("gcrypt error setting up encryption: %s\n",
+                gcry_strerror(status));
+    }
+
+    uint8_t *out = g_malloc0(in->len - CRYPTO_BLOCK_SIZE);
+
+    gcry_cipher_setkey(handle, key, CRYPTO_KEY_SIZE);
+    if (status) {
+        g_error("gcrypt error setting key: %s\n",
+                gcry_strerror(status));
+    }
+
+    status = gcry_cipher_setiv(handle, in->data, CRYPTO_BLOCK_SIZE);
+    if (status) {
+        g_error("gcrypt error setting IV: %s\n",
+                gcry_strerror(status));
+    }
+
+    status = gcry_cipher_decrypt(handle, out, in->len - CRYPTO_BLOCK_SIZE,
+                                 in->data + CRYPTO_BLOCK_SIZE,
+                                 in->len - CRYPTO_BLOCK_SIZE);
+    if (status) {
+        g_error("gcrypt error decrypting: %s\n",
+                gcry_strerror(status));
+    }
+
+    gcry_cipher_close(handle);
+
+    return bluesky_string_new(out, in->len + CRYPTO_BLOCK_SIZE);
+}