xref: /openbmc/qemu/crypto/cipher-builtin.c.inc (revision a68694cd)
1/*
2 * QEMU Crypto cipher built-in 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#include "crypto/aes.h"
22#include "crypto/desrfb.h"
23#include "crypto/xts.h"
24
25typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
26struct QCryptoCipherBuiltinAESContext {
27    AES_KEY enc;
28    AES_KEY dec;
29};
30
31typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
32struct QCryptoCipherBuiltinAES {
33    QCryptoCipher base;
34    QCryptoCipherBuiltinAESContext key;
35    QCryptoCipherBuiltinAESContext key_tweak;
36    uint8_t iv[AES_BLOCK_SIZE];
37};
38
39
40static inline bool qcrypto_length_check(size_t len, size_t blocksize,
41                                        Error **errp)
42{
43    if (unlikely(len & (blocksize - 1))) {
44        error_setg(errp, "Length %zu must be a multiple of block size %zu",
45                   len, blocksize);
46        return false;
47    }
48    return true;
49}
50
51static void qcrypto_cipher_ctx_free(QCryptoCipher *cipher)
52{
53    g_free(cipher);
54}
55
56static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher,
57                                   const uint8_t *iv, size_t niv,
58                                   Error **errp)
59{
60    error_setg(errp, "Setting IV is not supported");
61    return -1;
62}
63
64static void do_aes_encrypt_ecb(const void *vctx,
65                               size_t len,
66                               uint8_t *out,
67                               const uint8_t *in)
68{
69    const QCryptoCipherBuiltinAESContext *ctx = vctx;
70
71    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
72    while (len) {
73        AES_encrypt(in, out, &ctx->enc);
74        in += AES_BLOCK_SIZE;
75        out += AES_BLOCK_SIZE;
76        len -= AES_BLOCK_SIZE;
77    }
78}
79
80static void do_aes_decrypt_ecb(const void *vctx,
81                               size_t len,
82                               uint8_t *out,
83                               const uint8_t *in)
84{
85    const QCryptoCipherBuiltinAESContext *ctx = vctx;
86
87    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
88    while (len) {
89        AES_decrypt(in, out, &ctx->dec);
90        in += AES_BLOCK_SIZE;
91        out += AES_BLOCK_SIZE;
92        len -= AES_BLOCK_SIZE;
93    }
94}
95
96static void do_aes_encrypt_cbc(const AES_KEY *key,
97                               size_t len,
98                               uint8_t *out,
99                               const uint8_t *in,
100                               uint8_t *ivec)
101{
102    uint8_t tmp[AES_BLOCK_SIZE];
103    size_t n;
104
105    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
106    while (len) {
107        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
108            tmp[n] = in[n] ^ ivec[n];
109        }
110        AES_encrypt(tmp, out, key);
111        memcpy(ivec, out, AES_BLOCK_SIZE);
112        len -= AES_BLOCK_SIZE;
113        in += AES_BLOCK_SIZE;
114        out += AES_BLOCK_SIZE;
115    }
116}
117
118static void do_aes_decrypt_cbc(const AES_KEY *key,
119                               size_t len,
120                               uint8_t *out,
121                               const uint8_t *in,
122                               uint8_t *ivec)
123{
124    uint8_t tmp[AES_BLOCK_SIZE];
125    size_t n;
126
127    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
128    while (len) {
129        memcpy(tmp, in, AES_BLOCK_SIZE);
130        AES_decrypt(in, out, key);
131        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
132            out[n] ^= ivec[n];
133        }
134        memcpy(ivec, tmp, AES_BLOCK_SIZE);
135        len -= AES_BLOCK_SIZE;
136        in += AES_BLOCK_SIZE;
137        out += AES_BLOCK_SIZE;
138    }
139}
140
141static int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher,
142                                          const void *in, void *out,
143                                          size_t len, Error **errp)
144{
145    QCryptoCipherBuiltinAES *ctx
146        = container_of(cipher, QCryptoCipherBuiltinAES, base);
147
148    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
149        return -1;
150    }
151    do_aes_encrypt_ecb(&ctx->key, len, out, in);
152    return 0;
153}
154
155static int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher,
156                                          const void *in, void *out,
157                                          size_t len, Error **errp)
158{
159    QCryptoCipherBuiltinAES *ctx
160        = container_of(cipher, QCryptoCipherBuiltinAES, base);
161
162    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
163        return -1;
164    }
165    do_aes_decrypt_ecb(&ctx->key, len, out, in);
166    return 0;
167}
168
169static int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher,
170                                          const void *in, void *out,
171                                          size_t len, Error **errp)
172{
173    QCryptoCipherBuiltinAES *ctx
174        = container_of(cipher, QCryptoCipherBuiltinAES, base);
175
176    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
177        return -1;
178    }
179    do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv);
180    return 0;
181}
182
183static int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher,
184                                          const void *in, void *out,
185                                          size_t len, Error **errp)
186{
187    QCryptoCipherBuiltinAES *ctx
188        = container_of(cipher, QCryptoCipherBuiltinAES, base);
189
190    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
191        return -1;
192    }
193    do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv);
194    return 0;
195}
196
197static int qcrypto_cipher_aes_encrypt_xts(QCryptoCipher *cipher,
198                                          const void *in, void *out,
199                                          size_t len, Error **errp)
200{
201    QCryptoCipherBuiltinAES *ctx
202        = container_of(cipher, QCryptoCipherBuiltinAES, base);
203
204    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
205        return -1;
206    }
207    xts_encrypt(&ctx->key, &ctx->key_tweak,
208                do_aes_encrypt_ecb, do_aes_decrypt_ecb,
209                ctx->iv, len, out, in);
210    return 0;
211}
212
213static int qcrypto_cipher_aes_decrypt_xts(QCryptoCipher *cipher,
214                                          const void *in, void *out,
215                                          size_t len, Error **errp)
216{
217    QCryptoCipherBuiltinAES *ctx
218        = container_of(cipher, QCryptoCipherBuiltinAES, base);
219
220    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
221        return -1;
222    }
223    xts_decrypt(&ctx->key, &ctx->key_tweak,
224                do_aes_encrypt_ecb, do_aes_decrypt_ecb,
225                ctx->iv, len, out, in);
226    return 0;
227}
228
229
230static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv,
231                             size_t niv, Error **errp)
232{
233    QCryptoCipherBuiltinAES *ctx
234        = container_of(cipher, QCryptoCipherBuiltinAES, base);
235
236    if (niv != AES_BLOCK_SIZE) {
237        error_setg(errp, "IV must be %d bytes not %zu",
238                   AES_BLOCK_SIZE, niv);
239        return -1;
240    }
241
242    memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
243    return 0;
244}
245
246static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = {
247    .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb,
248    .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb,
249    .cipher_setiv = qcrypto_cipher_no_setiv,
250    .cipher_free = qcrypto_cipher_ctx_free,
251};
252
253static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = {
254    .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc,
255    .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc,
256    .cipher_setiv = qcrypto_cipher_aes_setiv,
257    .cipher_free = qcrypto_cipher_ctx_free,
258};
259
260static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_xts = {
261    .cipher_encrypt = qcrypto_cipher_aes_encrypt_xts,
262    .cipher_decrypt = qcrypto_cipher_aes_decrypt_xts,
263    .cipher_setiv = qcrypto_cipher_aes_setiv,
264    .cipher_free = qcrypto_cipher_ctx_free,
265};
266
267
268typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
269struct QCryptoCipherBuiltinDESRFB {
270    QCryptoCipher base;
271
272    /* C.f. alg_key_len[QCRYPTO_CIPHER_ALG_DES_RFB] */
273    uint8_t key[8];
274};
275
276static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
277                                          const void *in, void *out,
278                                          size_t len, Error **errp)
279{
280    QCryptoCipherBuiltinDESRFB *ctx
281        = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
282    size_t i;
283
284    if (!qcrypto_length_check(len, 8, errp)) {
285        return -1;
286    }
287
288    deskey(ctx->key, EN0);
289
290    for (i = 0; i < len; i += 8) {
291        des((void *)in + i, out + i);
292    }
293
294    return 0;
295}
296
297static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
298                                          const void *in, void *out,
299                                          size_t len, Error **errp)
300{
301    QCryptoCipherBuiltinDESRFB *ctx
302        = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
303    size_t i;
304
305    if (!qcrypto_length_check(len, 8, errp)) {
306        return -1;
307    }
308
309    deskey(ctx->key, DE1);
310
311    for (i = 0; i < len; i += 8) {
312        des((void *)in + i, out + i);
313    }
314
315    return 0;
316}
317
318static const struct QCryptoCipherDriver qcrypto_cipher_des_rfb_driver = {
319    .cipher_encrypt = qcrypto_cipher_encrypt_des_rfb,
320    .cipher_decrypt = qcrypto_cipher_decrypt_des_rfb,
321    .cipher_setiv = qcrypto_cipher_no_setiv,
322    .cipher_free = qcrypto_cipher_ctx_free,
323};
324
325bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
326                             QCryptoCipherMode mode)
327{
328    switch (alg) {
329    case QCRYPTO_CIPHER_ALG_DES_RFB:
330        return mode == QCRYPTO_CIPHER_MODE_ECB;
331    case QCRYPTO_CIPHER_ALG_AES_128:
332    case QCRYPTO_CIPHER_ALG_AES_192:
333    case QCRYPTO_CIPHER_ALG_AES_256:
334        switch (mode) {
335        case QCRYPTO_CIPHER_MODE_ECB:
336        case QCRYPTO_CIPHER_MODE_CBC:
337        case QCRYPTO_CIPHER_MODE_XTS:
338            return true;
339        default:
340            return false;
341        }
342        break;
343    default:
344        return false;
345    }
346}
347
348static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
349                                             QCryptoCipherMode mode,
350                                             const uint8_t *key,
351                                             size_t nkey,
352                                             Error **errp)
353{
354    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
355        return NULL;
356    }
357
358    switch (alg) {
359    case QCRYPTO_CIPHER_ALG_DES_RFB:
360        if (mode == QCRYPTO_CIPHER_MODE_ECB) {
361            QCryptoCipherBuiltinDESRFB *ctx;
362
363            ctx = g_new0(QCryptoCipherBuiltinDESRFB, 1);
364            ctx->base.driver = &qcrypto_cipher_des_rfb_driver;
365            memcpy(ctx->key, key, sizeof(ctx->key));
366
367            return &ctx->base;
368        }
369        goto bad_mode;
370
371    case QCRYPTO_CIPHER_ALG_AES_128:
372    case QCRYPTO_CIPHER_ALG_AES_192:
373    case QCRYPTO_CIPHER_ALG_AES_256:
374        {
375            QCryptoCipherBuiltinAES *ctx;
376            const QCryptoCipherDriver *drv;
377
378            switch (mode) {
379            case QCRYPTO_CIPHER_MODE_ECB:
380                drv = &qcrypto_cipher_aes_driver_ecb;
381                break;
382            case QCRYPTO_CIPHER_MODE_CBC:
383                drv = &qcrypto_cipher_aes_driver_cbc;
384                break;
385            case QCRYPTO_CIPHER_MODE_XTS:
386                drv = &qcrypto_cipher_aes_driver_xts;
387                break;
388            default:
389                goto bad_mode;
390            }
391
392            ctx = g_new0(QCryptoCipherBuiltinAES, 1);
393            ctx->base.driver = drv;
394
395            if (mode == QCRYPTO_CIPHER_MODE_XTS) {
396                nkey /= 2;
397                if (AES_set_encrypt_key(key + nkey, nkey * 8,
398                                        &ctx->key_tweak.enc)) {
399                    error_setg(errp, "Failed to set encryption key");
400                    goto error;
401                }
402                if (AES_set_decrypt_key(key + nkey, nkey * 8,
403                                        &ctx->key_tweak.dec)) {
404                    error_setg(errp, "Failed to set decryption key");
405                    goto error;
406                }
407            }
408            if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) {
409                error_setg(errp, "Failed to set encryption key");
410                goto error;
411            }
412            if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) {
413                error_setg(errp, "Failed to set decryption key");
414                goto error;
415            }
416
417            return &ctx->base;
418
419        error:
420            g_free(ctx);
421            return NULL;
422        }
423
424    default:
425        error_setg(errp,
426                   "Unsupported cipher algorithm %s",
427                   QCryptoCipherAlgorithm_str(alg));
428        return NULL;
429    }
430
431 bad_mode:
432    error_setg(errp, "Unsupported cipher mode %s",
433               QCryptoCipherMode_str(mode));
434    return NULL;
435}
436