Implement data decryption as well.
[bluesky.git] / bluesky / crypto.c
index 6eec464..defe1b3 100644 (file)
@@ -74,8 +74,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 +85,45 @@ 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)
+{
+    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);
+}