/*
* QEMU Crypto cipher algorithms
*
* Copyright (c) 2015 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see .
*
*/
#ifndef QCRYPTO_CIPHER_H__
#define QCRYPTO_CIPHER_H__
#include "qemu-common.h"
#include "qapi/error.h"
typedef struct QCryptoCipher QCryptoCipher;
typedef enum {
QCRYPTO_CIPHER_ALG_AES_128,
QCRYPTO_CIPHER_ALG_AES_192,
QCRYPTO_CIPHER_ALG_AES_256,
QCRYPTO_CIPHER_ALG_DES_RFB, /* A stupid variant on DES for VNC */
QCRYPTO_CIPHER_ALG_LAST
} QCryptoCipherAlgorithm;
typedef enum {
QCRYPTO_CIPHER_MODE_ECB,
QCRYPTO_CIPHER_MODE_CBC,
QCRYPTO_CIPHER_MODE_LAST
} QCryptoCipherMode;
/**
* QCryptoCipher:
*
* The QCryptoCipher object provides a way to perform encryption
* and decryption of data, with a standard API, regardless of the
* algorithm used. It further isolates the calling code from the
* details of the specific underlying implementation, whether
* built-in, libgcrypt or nettle.
*
* Each QCryptoCipher object is capable of performing both
* encryption and decryption, and can operate in a number
* or modes including ECB, CBC.
*
*
* Encrypting data with AES-128 in CBC mode
*
* QCryptoCipher *cipher;
* uint8_t key = ....;
* size_t keylen = 16;
* uint8_t iv = ....;
*
* if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128)) {
* error_report(errp, "Feature requires AES cipher support");
* return -1;
* }
*
* cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128,
* QCRYPTO_CIPHER_MODE_CBC,
* key, keylen,
* errp);
* if (!cipher) {
* return -1;
* }
*
* if (qcrypto_cipher_set_iv(cipher, iv, keylen, errp) < 0) {
* return -1;
* }
*
* if (qcrypto_cipher_encrypt(cipher, rawdata, encdata, datalen, errp) < 0) {
* return -1;
* }
*
* qcrypto_cipher_free(cipher);
*
*
*
*/
struct QCryptoCipher {
QCryptoCipherAlgorithm alg;
QCryptoCipherMode mode;
void *opaque;
};
/**
* qcrypto_cipher_supports:
* @alg: the cipher algorithm
*
* Determine if @alg cipher algorithm is supported by the
* current configured build
*
* Returns: true if the algorithm is supported, false otherwise
*/
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg);
/**
* qcrypto_cipher_get_block_len:
* @alg: the cipher algorithm
*
* Get the required data block size in bytes. When
* encrypting data, it must be a multiple of the
* block size.
*
* Returns: the block size in bytes
*/
size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg);
/**
* qcrypto_cipher_get_key_len:
* @alg: the cipher algorithm
*
* Get the required key size in bytes.
*
* Returns: the key size in bytes
*/
size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg);
/**
* qcrypto_cipher_get_iv_len:
* @alg: the cipher algorithm
* @mode: the cipher mode
*
* Get the required initialization vector size
* in bytes, if one is required.
*
* Returns: the IV size in bytes, or 0 if no IV is permitted
*/
size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode);
/**
* qcrypto_cipher_new:
* @alg: the cipher algorithm
* @mode: the cipher usage mode
* @key: the private key bytes
* @nkey: the length of @key
* @errp: pointer to an uninitialized error object
*
* Creates a new cipher object for encrypting/decrypting
* data with the algorithm @alg in the usage mode @mode.
*
* The @key parameter provides the bytes representing
* the encryption/decryption key to use. The @nkey parameter
* specifies the length of @key in bytes. Each algorithm has
* one or more valid key lengths, and it is an error to provide
* a key of the incorrect length.
*
* The returned cipher object must be released with
* qcrypto_cipher_free() when no longer required
*
* Returns: a new cipher object, or NULL on error
*/
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp);
/**
* qcrypto_cipher_free:
* @cipher: the cipher object
*
* Release the memory associated with @cipher that
* was previously allocated by qcrypto_cipher_new()
*/
void qcrypto_cipher_free(QCryptoCipher *cipher);
/**
* qcrypto_cipher_encrypt:
* @cipher: the cipher object
* @in: buffer holding the plain text input data
* @out: buffer to fill with the cipher text output data
* @len: the length of @in and @out buffers
* @errp: pointer to an uninitialized error object
*
* Encrypts the plain text stored in @in, filling
* @out with the resulting ciphered text. Both the
* @in and @out buffers must have the same size,
* given by @len.
*
* Returns: 0 on success, or -1 on error
*/
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
/**
* qcrypto_cipher_decrypt:
* @cipher: the cipher object
* @in: buffer holding the cipher text input data
* @out: buffer to fill with the plain text output data
* @len: the length of @in and @out buffers
* @errp: pointer to an uninitialized error object
*
* Decrypts the cipher text stored in @in, filling
* @out with the resulting plain text. Both the
* @in and @out buffers must have the same size,
* given by @len.
*
* Returns: 0 on success, or -1 on error
*/
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
/**
* qcrypto_cipher_setiv:
* @cipher: the cipher object
* @iv: the initialization vector bytes
* @niv: the length of @iv
* @errpr: pointer to an uninitialized error object
*
* If the @cipher object is setup to use a mode that requires
* initialization vectors, this sets the initialization vector
* bytes. The @iv data should have the same length as the
* cipher key used when originally constructing the cipher
* object. It is an error to set an initialization vector
* if the cipher mode does not require one.
*
* Returns: 0 on success, -1 on error
*/
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp);
#endif /* QCRYPTO_CIPHER_H__ */