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 GCRY_THREAD_OPTION_PTHREAD_IMPL;
25 void bluesky_crypt_init()
27 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
29 if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
32 if (!gcry_check_version(GCRYPT_VERSION))
33 g_error("libgcrypt version mismatch\n");
35 gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
36 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
39 /* Return cryptographically-strong random data. */
40 void bluesky_crypt_random_bytes(guchar *buf, gint len)
42 gcry_randomize(buf, len, GCRY_STRONG_RANDOM);
45 /* Hash a string down to an encryption key. */
46 void bluesky_crypt_hash_key(const char *keystr, uint8_t *out)
49 gsize csum_len = sizeof(raw_csum);
51 assert(CRYPTO_KEY_SIZE == 16);
53 GChecksum *csum = g_checksum_new(G_CHECKSUM_SHA256);
54 g_checksum_update(csum, keystr, strlen(keystr));
55 g_checksum_get_digest(csum, raw_csum, &csum_len);
56 g_checksum_free(csum);
58 memcpy(out, raw_csum, CRYPTO_KEY_SIZE);
61 /* Encrypt a data block. */
62 BlueSkyRCStr *bluesky_crypt_encrypt(BlueSkyRCStr *in, const uint8_t *key)
65 gcry_cipher_hd_t handle;
67 status = gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC,
70 g_error("gcrypt error setting up encryption: %s\n",
71 gcry_strerror(status));
74 uint8_t *out = g_malloc0(in->len + CRYPTO_BLOCK_SIZE);
76 gcry_cipher_setkey(handle, key, CRYPTO_KEY_SIZE);
78 g_error("gcrypt error setting key: %s\n",
79 gcry_strerror(status));
82 bluesky_crypt_random_bytes(out, CRYPTO_BLOCK_SIZE);
83 status = gcry_cipher_setiv(handle, out, CRYPTO_BLOCK_SIZE);
85 g_error("gcrypt error setting IV: %s\n",
86 gcry_strerror(status));
89 status = gcry_cipher_encrypt(handle, out + CRYPTO_BLOCK_SIZE, in->len,
92 g_error("gcrypt error encrypting: %s\n",
93 gcry_strerror(status));
96 gcry_cipher_close(handle);
98 return bluesky_string_new(out, in->len + CRYPTO_BLOCK_SIZE);
101 /* Decrypt a data block. */
102 BlueSkyRCStr *bluesky_crypt_decrypt(BlueSkyRCStr *in, const uint8_t *key)
105 gcry_cipher_hd_t handle;
107 g_return_val_if_fail(in->len > CRYPTO_BLOCK_SIZE, NULL);
109 status = gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC,
110 GCRY_CIPHER_CBC_CTS);
112 g_error("gcrypt error setting up encryption: %s\n",
113 gcry_strerror(status));
116 uint8_t *out = g_malloc0(in->len - CRYPTO_BLOCK_SIZE);
118 gcry_cipher_setkey(handle, key, CRYPTO_KEY_SIZE);
120 g_error("gcrypt error setting key: %s\n",
121 gcry_strerror(status));
124 status = gcry_cipher_setiv(handle, in->data, CRYPTO_BLOCK_SIZE);
126 g_error("gcrypt error setting IV: %s\n",
127 gcry_strerror(status));
130 status = gcry_cipher_decrypt(handle, out, in->len - CRYPTO_BLOCK_SIZE,
131 in->data + CRYPTO_BLOCK_SIZE,
132 in->len - CRYPTO_BLOCK_SIZE);
134 g_error("gcrypt error decrypting: %s\n",
135 gcry_strerror(status));
138 gcry_cipher_close(handle);
140 return bluesky_string_new(out, in->len + CRYPTO_BLOCK_SIZE);