size_t Cipher::put(const unsigned char *data, size_t size) { if(size % keys.iosize() || !bufaddr) return 0; size_t count = 0; while(bufsize && size + bufpos > bufsize) { size_t diff = bufsize - bufpos; count += put(data, diff); data += diff; size -= diff; } switch(bufmode) { case Cipher::ENCRYPT: gnutls_cipher_encrypt2((CIPHER_CTX)context, (void *)data, size, bufaddr + bufpos, size); break; case Cipher::DECRYPT: gnutls_cipher_decrypt2((CIPHER_CTX)context, data, size, bufaddr + bufpos, size); } count += size; if(!count) { release(); return 0; } bufpos += size; if(bufsize && bufpos >= bufsize) { push(bufaddr, bufsize); bufpos = 0; } return count; }
static void cipher_bench(int algo, int size, int aead) { int ret; gnutls_cipher_hd_t ctx; void *_key, *_iv; gnutls_datum_t key, iv; int ivsize = gnutls_cipher_get_iv_size(algo); int keysize = gnutls_cipher_get_key_size(algo); int step = size * 1024; struct benchmark_st st; _key = malloc(keysize); if (_key == NULL) return; memset(_key, 0xf0, keysize); _iv = malloc(ivsize); if (_iv == NULL) return; memset(_iv, 0xf0, ivsize); iv.data = _iv; if (aead) iv.size = 12; else iv.size = ivsize; key.data = _key; key.size = keysize; printf("%16s ", gnutls_cipher_get_name(algo)); fflush(stdout); start_benchmark(&st); ret = gnutls_cipher_init(&ctx, algo, &key, &iv); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); goto leave; } if (aead) gnutls_cipher_add_auth(ctx, data, 1024); do { gnutls_cipher_encrypt2(ctx, data, step, data, step + 64); st.size += step; } while (benchmark_must_finish == 0); gnutls_cipher_deinit(ctx); stop_benchmark(&st, NULL, 1); leave: free(_key); free(_iv); }
static int dcrypt_gnutls_ctx_sym_update(struct dcrypt_context_symmetric *ctx, const unsigned char *data, size_t data_len, buffer_t *result, const char **error_r) { int ec; size_t outl = gnutls_cipher_get_block_size(ctx->cipher); unsigned char buf[outl]; ec = gnutls_cipher_encrypt2(ctx->ctx, data, data_len, buf, outl); if(ec < 0) return dcrypt_gnutls_error(ec, error_r); buffer_append(result, buf, outl); return ec; }
static gboolean purple_aes_cipher_gnutls_encrypt(const guchar *input, guchar *output, size_t len, guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, PurpleCipherBatchMode batch_mode) { gnutls_cipher_hd_t handle; int ret; /* We have to simulate ECB mode, which is not supported by GnuTLS. */ if (batch_mode == PURPLE_CIPHER_BATCH_MODE_ECB) { size_t i; for (i = 0; i < len / PURPLE_AES_BLOCK_SIZE; i++) { int offset = i * PURPLE_AES_BLOCK_SIZE; guchar iv_local[PURPLE_AES_BLOCK_SIZE]; gboolean succ; memcpy(iv_local, iv, sizeof(iv_local)); succ = purple_aes_cipher_gnutls_encrypt( input + offset, output + offset, PURPLE_AES_BLOCK_SIZE, iv_local, key, key_size, PURPLE_CIPHER_BATCH_MODE_CBC); if (!succ) return FALSE; } return TRUE; } handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); if (handle == NULL) return FALSE; ret = gnutls_cipher_encrypt2(handle, (guchar *)input, len, output, len); gnutls_cipher_deinit(handle); if (ret != 0) { purple_debug_error("cipher-aes", "gnutls_cipher_encrypt2 failed: %d\n", ret); return FALSE; } return TRUE; }
static gboolean purple_aes_cipher_gnutls_encrypt(const guchar *input, guchar *output, size_t len, guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) { gnutls_cipher_hd_t handle; int ret; handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); if (handle == NULL) return FALSE; ret = gnutls_cipher_encrypt2(handle, (guchar *)input, len, output, len); gnutls_cipher_deinit(handle); if (ret != 0) { purple_debug_error("cipher-aes", "gnutls_cipher_encrypt2 failed: %d\n", ret); return FALSE; } return TRUE; }
static void cipher_mac_bench(int algo, int mac_algo, int size) { int ret; gnutls_cipher_hd_t ctx; gnutls_hmac_hd_t mac_ctx; void *_key, *_iv; gnutls_datum_t key, iv; int ivsize = gnutls_cipher_get_iv_size(algo); int keysize = gnutls_cipher_get_key_size(algo); int step = size * 1024; struct benchmark_st st; void *output, *input; unsigned char c, *i; _key = malloc(keysize); if (_key == NULL) return; memset(_key, 0xf0, keysize); _iv = malloc(ivsize); if (_iv == NULL) { free(_key); return; } memset(_iv, 0xf0, ivsize); iv.data = _iv; iv.size = ivsize; key.data = _key; key.size = keysize; assert(gnutls_rnd(GNUTLS_RND_NONCE, &c, 1) >= 0); printf("%19s-%s ", gnutls_cipher_get_name(algo), gnutls_mac_get_name(mac_algo)); fflush(stdout); ALLOCM(input, MAX_MEM); ALLOC(output); i = input; start_benchmark(&st); ret = gnutls_hmac_init(&mac_ctx, mac_algo, key.data, key.size); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); goto leave; } ret = gnutls_cipher_init(&ctx, algo, &key, &iv); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); goto leave; } do { gnutls_hmac(mac_ctx, i, step); gnutls_cipher_encrypt2(ctx, i, step, output, step + 64); st.size += step; INC(input, i, step); } while (benchmark_must_finish == 0); gnutls_cipher_deinit(ctx); gnutls_hmac_deinit(mac_ctx, NULL); stop_benchmark(&st, NULL, 1); leave: FREE(input); FREE(output); free(_key); free(_iv); }
static void cipher_bench(int algo, int size, int aead) { int ret; gnutls_cipher_hd_t ctx; void *_key, *_iv; gnutls_aead_cipher_hd_t actx; gnutls_datum_t key, iv; int ivsize = gnutls_cipher_get_iv_size(algo); int keysize = gnutls_cipher_get_key_size(algo); int step = size * 1024; void *input, *output; struct benchmark_st st; unsigned char c, *i; _key = malloc(keysize); if (_key == NULL) return; memset(_key, 0xf0, keysize); _iv = malloc(ivsize); if (_iv == NULL) { free(_key); return; } memset(_iv, 0xf0, ivsize); iv.data = _iv; iv.size = ivsize; key.data = _key; key.size = keysize; printf("%24s ", gnutls_cipher_get_name(algo)); fflush(stdout); assert(gnutls_rnd(GNUTLS_RND_NONCE, &c, 1) >= 0); ALLOCM(input, MAX_MEM); ALLOCM(output, step+64); i = input; start_benchmark(&st); if (algo == GNUTLS_CIPHER_NULL) { do { force_memcpy(output, i, step); st.size += step; INC(input, i, step); } while (benchmark_must_finish == 0); } else if (aead != 0) { unsigned tag_size = gnutls_cipher_get_tag_size(algo); size_t out_size; ret = gnutls_aead_cipher_init(&actx, algo, &key); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); goto leave; } do { out_size = step+64; assert(gnutls_aead_cipher_encrypt(actx, iv.data, iv.size, NULL, 0, tag_size, i, step, output, &out_size) >= 0); st.size += step; INC(input, i, step); } while (benchmark_must_finish == 0); gnutls_aead_cipher_deinit(actx); } else { ret = gnutls_cipher_init(&ctx, algo, &key, &iv); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); goto leave; } do { gnutls_cipher_encrypt2(ctx, i, step, output, step + 64); st.size += step; INC(input, i, step); } while (benchmark_must_finish == 0); gnutls_cipher_deinit(ctx); } stop_benchmark(&st, NULL, 1); FREE(input); FREE(output); leave: free(_key); free(_iv); }
gchar *password_encrypt_gnutls(const gchar *password, const gchar *encryption_passphrase) { /* Another, slightly inferior combination is AES-128-CBC + SHA-256. * Any block cipher in CBC mode with keysize N and a hash algo with * digest length 2*N would do. */ gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_256_CBC; gnutls_cipher_hd_t handle; gnutls_datum_t key, iv; int keylen, blocklen, ret; unsigned char *buf, *encbuf, *base, *output; guint rounds = prefs_common_get_prefs()->master_passphrase_pbkdf2_rounds; g_return_val_if_fail(password != NULL, NULL); g_return_val_if_fail(encryption_passphrase != NULL, NULL); /* ivlen = gnutls_cipher_get_iv_size(algo);*/ keylen = gnutls_cipher_get_key_size(algo); blocklen = gnutls_cipher_get_block_size(algo); /* digestlen = gnutls_hash_get_len(digest); */ /* Take the passphrase and compute a key derivation of suitable * length to be used as encryption key for our block cipher. */ key.data = _make_key_deriv(encryption_passphrase, rounds, keylen); key.size = keylen; /* Prepare random IV for cipher */ iv.data = malloc(IVLEN); iv.size = IVLEN; if (!get_random_bytes(iv.data, IVLEN)) { g_free(key.data); g_free(iv.data); return NULL; } /* Initialize the encryption */ ret = gnutls_cipher_init(&handle, algo, &key, &iv); if (ret < 0) { g_free(key.data); g_free(iv.data); return NULL; } /* Fill buf with one block of random data, our password, pad the * rest with zero bytes. */ buf = malloc(BUFSIZE + blocklen); memset(buf, 0, BUFSIZE); if (!get_random_bytes(buf, blocklen)) { g_free(buf); g_free(key.data); g_free(iv.data); gnutls_cipher_deinit(handle); return NULL; } memcpy(buf + blocklen, password, strlen(password)); /* Encrypt into encbuf */ encbuf = malloc(BUFSIZE + blocklen); memset(encbuf, 0, BUFSIZE + blocklen); ret = gnutls_cipher_encrypt2(handle, buf, BUFSIZE + blocklen, encbuf, BUFSIZE + blocklen); if (ret < 0) { g_free(key.data); g_free(iv.data); g_free(buf); g_free(encbuf); gnutls_cipher_deinit(handle); return NULL; } /* Cleanup */ gnutls_cipher_deinit(handle); g_free(key.data); g_free(iv.data); g_free(buf); /* And finally prepare the resulting string: * "{algorithm,rounds}base64encodedciphertext" */ base = g_base64_encode(encbuf, BUFSIZE); g_free(encbuf); output = g_strdup_printf("{%s,%d}%s", gnutls_cipher_get_name(algo), rounds, base); g_free(base); return output; }
char * crypto_encrypt (const char *cipher, const GByteArray *data, const char *iv, const gsize iv_len, const char *key, gsize key_len, gsize *out_len, GError **error) { gnutls_cipher_hd_t ctx; gnutls_datum_t key_dt, iv_dt; int err; int cipher_mech; char *output = NULL; gboolean success = FALSE; gsize padded_buf_len, pad_len, output_len; char *padded_buf = NULL; guint32 i; gsize salt_len; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { cipher_mech = GNUTLS_CIPHER_3DES_CBC; salt_len = SALT_LEN; } else if (!strcmp (cipher, CIPHER_AES_CBC)) { cipher_mech = GNUTLS_CIPHER_AES_128_CBC; salt_len = iv_len; } else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } /* If data->len % ivlen == 0, then we add another complete block * onto the end so that the decrypter knows there's padding. */ pad_len = iv_len - (data->len % iv_len); output_len = padded_buf_len = data->len + pad_len; padded_buf = g_malloc0 (padded_buf_len); memcpy (padded_buf, data->data, data->len); for (i = 0; i < pad_len; i++) padded_buf[data->len + i] = (guint8) (pad_len & 0xFF); output = g_malloc0 (output_len); key_dt.data = (unsigned char *) key; key_dt.size = key_len; iv_dt.data = (unsigned char *) iv; iv_dt.size = iv_len; err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt); if (err < 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_INIT_FAILED, _("Failed to initialize the encryption cipher context: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); goto out; } err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len); if (err < 0) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, _("Failed to encrypt the data: %s (%s)"), gnutls_strerror_name (err), gnutls_strerror (err)); goto out; } *out_len = output_len; success = TRUE; out: if (padded_buf) { memset (padded_buf, 0, padded_buf_len); g_free (padded_buf); padded_buf = NULL; } if (!success) { if (output) { /* Don't expose key material */ memset (output, 0, output_len); g_free (output); output = NULL; } } gnutls_cipher_deinit (ctx); return output; }