| 1 | /* |
| 2 | * QEMU Crypto cipher algorithms |
| 3 | * |
| 4 | * Copyright (c) 2015 Red Hat, Inc. |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| 18 | * |
| 19 | */ |
| 20 | |
| 21 | #ifndef QCRYPTO_CIPHER_H |
| 22 | #define QCRYPTO_CIPHER_H |
| 23 | |
| 24 | #include "qapi/qapi-types-crypto.h" |
| 25 | |
| 26 | typedef struct QCryptoCipher QCryptoCipher; |
| 27 | typedef struct QCryptoCipherDriver QCryptoCipherDriver; |
| 28 | |
| 29 | /* See also "QCryptoCipherAlgo" and "QCryptoCipherMode" |
| 30 | * enums defined in qapi/crypto.json */ |
| 31 | |
| 32 | /** |
| 33 | * QCryptoCipher: |
| 34 | * |
| 35 | * The QCryptoCipher object provides a way to perform encryption |
| 36 | * and decryption of data, with a standard API, regardless of the |
| 37 | * algorithm used. It further isolates the calling code from the |
| 38 | * details of the specific underlying implementation, whether |
| 39 | * built-in, libgcrypt or nettle. |
| 40 | * |
| 41 | * Each QCryptoCipher object is capable of performing both |
| 42 | * encryption and decryption, and can operate in a number |
| 43 | * or modes including ECB, CBC. |
| 44 | * |
| 45 | * <example> |
| 46 | * <title>Encrypting data with AES-128 in CBC mode</title> |
| 47 | * <programlisting> |
| 48 | * QCryptoCipher *cipher; |
| 49 | * uint8_t key = ....; |
| 50 | * size_t keylen = 16; |
| 51 | * uint8_t iv = ....; |
| 52 | * |
| 53 | * if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALGO_AES_128)) { |
| 54 | * error_report(errp, "Feature <blah> requires AES cipher support"); |
| 55 | * return -1; |
| 56 | * } |
| 57 | * |
| 58 | * cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128, |
| 59 | * QCRYPTO_CIPHER_MODE_CBC, |
| 60 | * key, keylen, |
| 61 | * errp); |
| 62 | * if (!cipher) { |
| 63 | * return -1; |
| 64 | * } |
| 65 | * |
| 66 | * if (qcrypto_cipher_set_iv(cipher, iv, keylen, errp) < 0) { |
| 67 | * return -1; |
| 68 | * } |
| 69 | * |
| 70 | * if (qcrypto_cipher_encrypt(cipher, rawdata, encdata, datalen, errp) < 0) { |
| 71 | * return -1; |
| 72 | * } |
| 73 | * |
| 74 | * qcrypto_cipher_free(cipher); |
| 75 | * </programlisting> |
| 76 | * </example> |
| 77 | * |
| 78 | */ |
| 79 | |
| 80 | struct QCryptoCipher { |
| 81 | QCryptoCipherAlgo alg; |
| 82 | QCryptoCipherMode mode; |
| 83 | const QCryptoCipherDriver *driver; |
| 84 | }; |
| 85 | |
| 86 | /** |
| 87 | * qcrypto_cipher_supports: |
| 88 | * @alg: the cipher algorithm |
| 89 | * @mode: the cipher mode |
| 90 | * |
| 91 | * Determine if @alg cipher algorithm in @mode is supported by the |
| 92 | * current configured build |
| 93 | * |
| 94 | * Returns: true if the algorithm is supported, false otherwise |
| 95 | */ |
| 96 | bool qcrypto_cipher_supports(QCryptoCipherAlgo alg, |
| 97 | QCryptoCipherMode mode); |
| 98 | |
| 99 | /** |
| 100 | * qcrypto_cipher_get_block_len: |
| 101 | * @alg: the cipher algorithm |
| 102 | * |
| 103 | * Get the required data block size in bytes. When |
| 104 | * encrypting data, it must be a multiple of the |
| 105 | * block size. |
| 106 | * |
| 107 | * Returns: the block size in bytes |
| 108 | */ |
| 109 | size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgo alg); |
| 110 | |
| 111 | |
| 112 | /** |
| 113 | * qcrypto_cipher_get_key_len: |
| 114 | * @alg: the cipher algorithm |
| 115 | * |
| 116 | * Get the required key size in bytes. |
| 117 | * |
| 118 | * Returns: the key size in bytes |
| 119 | */ |
| 120 | size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgo alg); |
| 121 | |
| 122 | |
| 123 | /** |
| 124 | * qcrypto_cipher_get_iv_len: |
| 125 | * @alg: the cipher algorithm |
| 126 | * @mode: the cipher mode |
| 127 | * |
| 128 | * Get the required initialization vector size |
| 129 | * in bytes, if one is required. |
| 130 | * |
| 131 | * Returns: the IV size in bytes, or 0 if no IV is permitted |
| 132 | */ |
| 133 | size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgo alg, |
| 134 | QCryptoCipherMode mode); |
| 135 | |
| 136 | |
| 137 | /** |
| 138 | * qcrypto_cipher_new: |
| 139 | * @alg: the cipher algorithm |
| 140 | * @mode: the cipher usage mode |
| 141 | * @key: the private key bytes |
| 142 | * @nkey: the length of @key |
| 143 | * @errp: pointer to a NULL-initialized error object |
| 144 | * |
| 145 | * Creates a new cipher object for encrypting/decrypting |
| 146 | * data with the algorithm @alg in the usage mode @mode. |
| 147 | * |
| 148 | * The @key parameter provides the bytes representing |
| 149 | * the encryption/decryption key to use. The @nkey parameter |
| 150 | * specifies the length of @key in bytes. Each algorithm has |
| 151 | * one or more valid key lengths, and it is an error to provide |
| 152 | * a key of the incorrect length. |
| 153 | * |
| 154 | * The returned cipher object must be released with |
| 155 | * qcrypto_cipher_free() when no longer required |
| 156 | * |
| 157 | * Returns: a new cipher object, or NULL on error |
| 158 | */ |
| 159 | QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgo alg, |
| 160 | QCryptoCipherMode mode, |
| 161 | const uint8_t *key, size_t nkey, |
| 162 | Error **errp); |
| 163 | |
| 164 | /** |
| 165 | * qcrypto_cipher_free: |
| 166 | * @cipher: the cipher object |
| 167 | * |
| 168 | * Release the memory associated with @cipher that |
| 169 | * was previously allocated by qcrypto_cipher_new() |
| 170 | */ |
| 171 | void qcrypto_cipher_free(QCryptoCipher *cipher); |
| 172 | |
| 173 | G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoCipher, qcrypto_cipher_free) |
| 174 | |
| 175 | /** |
| 176 | * qcrypto_cipher_encrypt: |
| 177 | * @cipher: the cipher object |
| 178 | * @in: buffer holding the plain text input data |
| 179 | * @out: buffer to fill with the cipher text output data |
| 180 | * @len: the length of @in and @out buffers |
| 181 | * @errp: pointer to a NULL-initialized error object |
| 182 | * |
| 183 | * Encrypts the plain text stored in @in, filling |
| 184 | * @out with the resulting ciphered text. Both the |
| 185 | * @in and @out buffers must have the same size, |
| 186 | * given by @len. |
| 187 | * |
| 188 | * Returns: 0 on success, or -1 on error |
| 189 | */ |
| 190 | int qcrypto_cipher_encrypt(QCryptoCipher *cipher, |
| 191 | const void *in, |
| 192 | void *out, |
| 193 | size_t len, |
| 194 | Error **errp); |
| 195 | |
| 196 | |
| 197 | /** |
| 198 | * qcrypto_cipher_decrypt: |
| 199 | * @cipher: the cipher object |
| 200 | * @in: buffer holding the cipher text input data |
| 201 | * @out: buffer to fill with the plain text output data |
| 202 | * @len: the length of @in and @out buffers |
| 203 | * @errp: pointer to a NULL-initialized error object |
| 204 | * |
| 205 | * Decrypts the cipher text stored in @in, filling |
| 206 | * @out with the resulting plain text. Both the |
| 207 | * @in and @out buffers must have the same size, |
| 208 | * given by @len. |
| 209 | * |
| 210 | * Returns: 0 on success, or -1 on error |
| 211 | */ |
| 212 | int qcrypto_cipher_decrypt(QCryptoCipher *cipher, |
| 213 | const void *in, |
| 214 | void *out, |
| 215 | size_t len, |
| 216 | Error **errp); |
| 217 | |
| 218 | /** |
| 219 | * qcrypto_cipher_setiv: |
| 220 | * @cipher: the cipher object |
| 221 | * @iv: the initialization vector or counter (CTR mode) bytes |
| 222 | * @niv: the length of @iv |
| 223 | * @errpr: pointer to a NULL-initialized error object |
| 224 | * |
| 225 | * If the @cipher object is setup to use a mode that requires |
| 226 | * initialization vectors or counter, this sets the @niv |
| 227 | * bytes. The @iv data should have the same length as the |
| 228 | * cipher key used when originally constructing the cipher |
| 229 | * object. It is an error to set an initialization vector |
| 230 | * or counter if the cipher mode does not require one. |
| 231 | * |
| 232 | * Returns: 0 on success, -1 on error |
| 233 | */ |
| 234 | int qcrypto_cipher_setiv(QCryptoCipher *cipher, |
| 235 | const uint8_t *iv, size_t niv, |
| 236 | Error **errp); |
| 237 | |
| 238 | /** |
| 239 | * qcrypto_cipher_setaad: |
| 240 | * @cipher: the cipher object |
| 241 | * @aad: the associated data to authenticate |
| 242 | * @len: the length of @aad |
| 243 | * @errp: pointer to a NULL-initialized error object |
| 244 | * |
| 245 | * For AEAD modes such as GCM, feed the associated data (AAD) that is |
| 246 | * authenticated but not encrypted. It must be called after |
| 247 | * qcrypto_cipher_setiv() and before the first encrypt/decrypt call. It is |
| 248 | * an error to call this on a mode that is not an AEAD mode. |
| 249 | * |
| 250 | * Returns: 0 on success, -1 on error |
| 251 | */ |
| 252 | int qcrypto_cipher_setaad(QCryptoCipher *cipher, |
| 253 | const uint8_t *aad, size_t len, |
| 254 | Error **errp); |
| 255 | |
| 256 | /** |
| 257 | * qcrypto_cipher_gettag: |
| 258 | * @cipher: the cipher object |
| 259 | * @tag: buffer to receive the authentication tag |
| 260 | * @len: the length of @tag |
| 261 | * @errp: pointer to a NULL-initialized error object |
| 262 | * |
| 263 | * For AEAD modes such as GCM, read back the authentication tag computed |
| 264 | * over the associated data and the message. It must be called after the |
| 265 | * encrypt/decrypt operation. It is an error to call this on a mode that is |
| 266 | * not an AEAD mode. |
| 267 | * |
| 268 | * Returns: 0 on success, -1 on error |
| 269 | */ |
| 270 | int qcrypto_cipher_gettag(QCryptoCipher *cipher, |
| 271 | uint8_t *tag, size_t len, |
| 272 | Error **errp); |
| 273 | |
| 274 | #endif /* QCRYPTO_CIPHER_H */ |