1 /* Blue Sky: File Systems in the Cloud
3 * Copyright (C) 2009 The Regents of the University of California
4 * Written by Michael Vrable <mvrable@cs.ucsd.edu>
17 #include "bluesky-private.h"
19 /* Cryptographic operations. The rest of the BlueSky code merely calls into
20 * the functions in this file, so this is the only point where we interface
21 * with an external cryptographic library. */
23 /* TODO: We ought to switch to an authenticated encryption mode like EAX. */
25 GCRY_THREAD_OPTION_PTHREAD_IMPL;
27 void bluesky_crypt_init()
29 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
31 if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
34 if (!gcry_check_version(GCRYPT_VERSION))
35 g_error("libgcrypt version mismatch\n");
37 gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
38 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
41 /* Return cryptographically-strong random data. */
42 void bluesky_crypt_random_bytes(guchar *buf, gint len)
44 gcry_randomize(buf, len, GCRY_STRONG_RANDOM);
47 /* Hash a string down to an encryption key. */
48 void bluesky_crypt_hash_key(const char *keystr, uint8_t *out)
51 gsize csum_len = sizeof(raw_csum);
53 assert(CRYPTO_KEY_SIZE == 16);
55 GChecksum *csum = g_checksum_new(G_CHECKSUM_SHA256);
56 g_checksum_update(csum, (const guchar *)keystr, strlen(keystr));
57 g_checksum_get_digest(csum, raw_csum, &csum_len);
58 g_checksum_free(csum);
60 memcpy(out, raw_csum, CRYPTO_KEY_SIZE);
63 /* Encrypt a data block. */
64 BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key)
67 gcry_cipher_hd_t handle;
69 status = gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
72 g_error("gcrypt error setting up encryption: %s\n",
73 gcry_strerror(status));
76 uint8_t *out = g_malloc0(in->len + CRYPTO_BLOCK_SIZE);
78 gcry_cipher_setkey(handle, key, CRYPTO_KEY_SIZE);
80 g_error("gcrypt error setting key: %s\n",
81 gcry_strerror(status));
84 bluesky_crypt_random_bytes(out, CRYPTO_BLOCK_SIZE);
85 status = gcry_cipher_setctr(handle, out, CRYPTO_BLOCK_SIZE);
87 g_error("gcrypt error setting IV: %s\n",
88 gcry_strerror(status));
91 status = gcry_cipher_encrypt(handle, out + CRYPTO_BLOCK_SIZE, in->len,
94 g_error("gcrypt error encrypting: %s\n",
95 gcry_strerror(status));
98 gcry_cipher_close(handle);
100 return bluesky_string_new(out, in->len + CRYPTO_BLOCK_SIZE);
103 /* Decrypt a data block. */
104 BlueSkyRCStr *bluesky_crypt_decrypt(BlueSkyRCStr *in, const uint8_t *key)
107 gcry_cipher_hd_t handle;
109 g_return_val_if_fail(in->len > CRYPTO_BLOCK_SIZE, NULL);
111 status = gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
114 g_error("gcrypt error setting up encryption: %s\n",
115 gcry_strerror(status));
118 uint8_t *out = g_malloc0(in->len - CRYPTO_BLOCK_SIZE);
120 gcry_cipher_setkey(handle, key, CRYPTO_KEY_SIZE);
122 g_error("gcrypt error setting key: %s\n",
123 gcry_strerror(status));
126 status = gcry_cipher_setctr(handle, in->data, CRYPTO_BLOCK_SIZE);
128 g_error("gcrypt error setting IV: %s\n",
129 gcry_strerror(status));
132 status = gcry_cipher_decrypt(handle, out, in->len - CRYPTO_BLOCK_SIZE,
133 in->data + CRYPTO_BLOCK_SIZE,
134 in->len - CRYPTO_BLOCK_SIZE);
136 g_error("gcrypt error decrypting: %s\n",
137 gcry_strerror(status));
140 gcry_cipher_close(handle);
142 return bluesky_string_new(out, in->len - CRYPTO_BLOCK_SIZE);