Ejemplo n.º 1
0
static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
				   const char *key, char *buf)
{
	int bs = alg->iv_size;
	char iv[bs], iv_old[bs];
	struct crypt_cipher *cipher = NULL;
	int i, j, r;

	assert(bs == 2*sizeof(uint32_t));

	r = crypt_cipher_init(&cipher, "blowfish", "ecb",
			      &key[alg->key_offset], alg->key_size);
	if (r < 0)
		return r;

	memcpy(iv, &key[alg->iv_offset], alg->iv_size);
	for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
		memcpy(iv_old, &buf[i], bs);
		TCRYPT_swab_le(&buf[i]);
		r = crypt_cipher_decrypt(cipher, &buf[i], &buf[i],
					  bs, NULL, 0);
		TCRYPT_swab_le(&buf[i]);
		if (r < 0)
			break;
		for (j = 0; j < bs; j++)
			buf[i + j] ^= iv[j];
		memcpy(iv, iv_old, bs);
	}

	crypt_cipher_destroy(cipher);
	crypt_memzero(iv, bs);
	crypt_memzero(iv_old, bs);
	return r;
}
Ejemplo n.º 2
0
/*
 * For chanined ciphers and CBC mode we need "outer" decryption.
 * Backend doesn't provide this, so implement it here directly using ECB.
 */
static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers,
				const char *key, struct tcrypt_phdr *hdr)
{
	struct crypt_cipher *cipher[ciphers->chain_count];
	unsigned int bs = ciphers->cipher[0].iv_size;
	char *buf = (char*)&hdr->e, iv[bs], iv_old[bs];
	unsigned int i, j;
	int r = -EINVAL;

	TCRYPT_remove_whitening(buf, &key[8]);

	memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs);

	/* Initialize all ciphers in chain in ECB mode */
	for (j = 0; j < ciphers->chain_count; j++)
		cipher[j] = NULL;
	for (j = 0; j < ciphers->chain_count; j++) {
		r = crypt_cipher_init(&cipher[j], ciphers->cipher[j].name, "ecb",
				      &key[ciphers->cipher[j].key_offset],
				      ciphers->cipher[j].key_size);
		if (r < 0)
			goto out;
	}

	/* Implements CBC with chained ciphers in loop inside */
	for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
		memcpy(iv_old, &buf[i], bs);
		for (j = ciphers->chain_count; j > 0; j--) {
			r = crypt_cipher_decrypt(cipher[j - 1], &buf[i], &buf[i],
						  bs, NULL, 0);
			if (r < 0)
				goto out;
		}
		for (j = 0; j < bs; j++)
			buf[i + j] ^= iv[j];
		memcpy(iv, iv_old, bs);
	}
out:
	for (j = 0; j < ciphers->chain_count; j++)
		if (cipher[j])
			crypt_cipher_destroy(cipher[j]);

	crypt_memzero(iv, bs);
	crypt_memzero(iv_old, bs);
	return r;
}
Ejemplo n.º 3
0
static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
				   const char *key,struct tcrypt_phdr *hdr)
{
	char backend_key[TCRYPT_HDR_KEY_LEN];
	char iv[TCRYPT_HDR_IV_LEN] = {};
	char mode_name[MAX_CIPHER_LEN];
	struct crypt_cipher *cipher;
	char *c, *buf = (char*)&hdr->e;
	int r;

	/* Remove IV if present */
	strncpy(mode_name, mode, MAX_CIPHER_LEN);
	c = strchr(mode_name, '-');
	if (c)
		*c = '\0';

	if (!strncmp(mode, "lrw", 3))
		iv[alg->iv_size - 1] = 1;
	else if (!strncmp(mode, "cbc", 3)) {
		TCRYPT_remove_whitening(buf, &key[8]);
		if (!strcmp(alg->name, "blowfish_le"))
			return decrypt_blowfish_le_cbc(alg, key, buf);
		memcpy(iv, &key[alg->iv_offset], alg->iv_size);
	}

	TCRYPT_copy_key(alg, mode, backend_key, key);
	r = crypt_cipher_init(&cipher, alg->name, mode_name,
			      backend_key, alg->key_size);
	if (!r) {
		r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN,
					 iv, alg->iv_size);
		crypt_cipher_destroy(cipher);
	}

	crypt_memzero(backend_key, sizeof(backend_key));
	crypt_memzero(iv, TCRYPT_HDR_IV_LEN);
	return r;
}
Ejemplo n.º 4
0
static int cipher_perf_one(struct cipher_perf *cp, char *buf,
			   size_t buf_size, int enc)
{
	struct crypt_cipher *cipher = NULL;
	size_t done = 0, block = CIPHER_BLOCK_BYTES;
	int r;

	if (buf_size < block)
		block = buf_size;

	r = crypt_cipher_init(&cipher, cp->name, cp->mode, cp->key, cp->key_length);
	if (r < 0) {
		log_dbg("Cannot initialise cipher %s, mode %s.", cp->name, cp->mode);
		return r;
	}

	while (done < buf_size) {
		if ((done + block) > buf_size)
			block = buf_size - done;

		if (enc)
			r = crypt_cipher_encrypt(cipher, &buf[done], &buf[done],
						 block, cp->iv, cp->iv_length);
		else
			r = crypt_cipher_decrypt(cipher, &buf[done], &buf[done],
						 block, cp->iv, cp->iv_length);
		if (r < 0)
			break;

		done += block;
	}

	crypt_cipher_destroy(cipher);

	return r;
}