cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

cipher-builtin.c.inc (9213B)


      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
     23typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
     24struct QCryptoCipherBuiltinAESContext {
     25    AES_KEY enc;
     26    AES_KEY dec;
     27};
     28
     29typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
     30struct QCryptoCipherBuiltinAES {
     31    QCryptoCipher base;
     32    QCryptoCipherBuiltinAESContext key;
     33    uint8_t iv[AES_BLOCK_SIZE];
     34};
     35
     36
     37static inline bool qcrypto_length_check(size_t len, size_t blocksize,
     38                                        Error **errp)
     39{
     40    if (unlikely(len & (blocksize - 1))) {
     41        error_setg(errp, "Length %zu must be a multiple of block size %zu",
     42                   len, blocksize);
     43        return false;
     44    }
     45    return true;
     46}
     47
     48static void qcrypto_cipher_ctx_free(QCryptoCipher *cipher)
     49{
     50    g_free(cipher);
     51}
     52
     53static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher,
     54                                   const uint8_t *iv, size_t niv,
     55                                   Error **errp)
     56{
     57    error_setg(errp, "Setting IV is not supported");
     58    return -1;
     59}
     60
     61static void do_aes_encrypt_ecb(const void *vctx,
     62                               size_t len,
     63                               uint8_t *out,
     64                               const uint8_t *in)
     65{
     66    const QCryptoCipherBuiltinAESContext *ctx = vctx;
     67
     68    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
     69    while (len) {
     70        AES_encrypt(in, out, &ctx->enc);
     71        in += AES_BLOCK_SIZE;
     72        out += AES_BLOCK_SIZE;
     73        len -= AES_BLOCK_SIZE;
     74    }
     75}
     76
     77static void do_aes_decrypt_ecb(const void *vctx,
     78                               size_t len,
     79                               uint8_t *out,
     80                               const uint8_t *in)
     81{
     82    const QCryptoCipherBuiltinAESContext *ctx = vctx;
     83
     84    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
     85    while (len) {
     86        AES_decrypt(in, out, &ctx->dec);
     87        in += AES_BLOCK_SIZE;
     88        out += AES_BLOCK_SIZE;
     89        len -= AES_BLOCK_SIZE;
     90    }
     91}
     92
     93static void do_aes_encrypt_cbc(const AES_KEY *key,
     94                               size_t len,
     95                               uint8_t *out,
     96                               const uint8_t *in,
     97                               uint8_t *ivec)
     98{
     99    uint8_t tmp[AES_BLOCK_SIZE];
    100    size_t n;
    101
    102    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
    103    while (len) {
    104        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
    105            tmp[n] = in[n] ^ ivec[n];
    106        }
    107        AES_encrypt(tmp, out, key);
    108        memcpy(ivec, out, AES_BLOCK_SIZE);
    109        len -= AES_BLOCK_SIZE;
    110        in += AES_BLOCK_SIZE;
    111        out += AES_BLOCK_SIZE;
    112    }
    113}
    114
    115static void do_aes_decrypt_cbc(const AES_KEY *key,
    116                               size_t len,
    117                               uint8_t *out,
    118                               const uint8_t *in,
    119                               uint8_t *ivec)
    120{
    121    uint8_t tmp[AES_BLOCK_SIZE];
    122    size_t n;
    123
    124    /* We have already verified that len % AES_BLOCK_SIZE == 0. */
    125    while (len) {
    126        memcpy(tmp, in, AES_BLOCK_SIZE);
    127        AES_decrypt(in, out, key);
    128        for (n = 0; n < AES_BLOCK_SIZE; ++n) {
    129            out[n] ^= ivec[n];
    130        }
    131        memcpy(ivec, tmp, AES_BLOCK_SIZE);
    132        len -= AES_BLOCK_SIZE;
    133        in += AES_BLOCK_SIZE;
    134        out += AES_BLOCK_SIZE;
    135    }
    136}
    137
    138static int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher,
    139                                          const void *in, void *out,
    140                                          size_t len, Error **errp)
    141{
    142    QCryptoCipherBuiltinAES *ctx
    143        = container_of(cipher, QCryptoCipherBuiltinAES, base);
    144
    145    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
    146        return -1;
    147    }
    148    do_aes_encrypt_ecb(&ctx->key, len, out, in);
    149    return 0;
    150}
    151
    152static int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher,
    153                                          const void *in, void *out,
    154                                          size_t len, Error **errp)
    155{
    156    QCryptoCipherBuiltinAES *ctx
    157        = container_of(cipher, QCryptoCipherBuiltinAES, base);
    158
    159    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
    160        return -1;
    161    }
    162    do_aes_decrypt_ecb(&ctx->key, len, out, in);
    163    return 0;
    164}
    165
    166static int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher,
    167                                          const void *in, void *out,
    168                                          size_t len, Error **errp)
    169{
    170    QCryptoCipherBuiltinAES *ctx
    171        = container_of(cipher, QCryptoCipherBuiltinAES, base);
    172
    173    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
    174        return -1;
    175    }
    176    do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv);
    177    return 0;
    178}
    179
    180static int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher,
    181                                          const void *in, void *out,
    182                                          size_t len, Error **errp)
    183{
    184    QCryptoCipherBuiltinAES *ctx
    185        = container_of(cipher, QCryptoCipherBuiltinAES, base);
    186
    187    if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
    188        return -1;
    189    }
    190    do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv);
    191    return 0;
    192}
    193
    194static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv,
    195                             size_t niv, Error **errp)
    196{
    197    QCryptoCipherBuiltinAES *ctx
    198        = container_of(cipher, QCryptoCipherBuiltinAES, base);
    199
    200    if (niv != AES_BLOCK_SIZE) {
    201        error_setg(errp, "IV must be %d bytes not %zu",
    202                   AES_BLOCK_SIZE, niv);
    203        return -1;
    204    }
    205
    206    memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
    207    return 0;
    208}
    209
    210static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = {
    211    .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb,
    212    .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb,
    213    .cipher_setiv = qcrypto_cipher_no_setiv,
    214    .cipher_free = qcrypto_cipher_ctx_free,
    215};
    216
    217static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = {
    218    .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc,
    219    .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc,
    220    .cipher_setiv = qcrypto_cipher_aes_setiv,
    221    .cipher_free = qcrypto_cipher_ctx_free,
    222};
    223
    224bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
    225                             QCryptoCipherMode mode)
    226{
    227    switch (alg) {
    228    case QCRYPTO_CIPHER_ALG_AES_128:
    229    case QCRYPTO_CIPHER_ALG_AES_192:
    230    case QCRYPTO_CIPHER_ALG_AES_256:
    231        switch (mode) {
    232        case QCRYPTO_CIPHER_MODE_ECB:
    233        case QCRYPTO_CIPHER_MODE_CBC:
    234            return true;
    235        default:
    236            return false;
    237        }
    238        break;
    239    default:
    240        return false;
    241    }
    242}
    243
    244static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
    245                                             QCryptoCipherMode mode,
    246                                             const uint8_t *key,
    247                                             size_t nkey,
    248                                             Error **errp)
    249{
    250    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
    251        return NULL;
    252    }
    253
    254    switch (alg) {
    255    case QCRYPTO_CIPHER_ALG_AES_128:
    256    case QCRYPTO_CIPHER_ALG_AES_192:
    257    case QCRYPTO_CIPHER_ALG_AES_256:
    258        {
    259            QCryptoCipherBuiltinAES *ctx;
    260            const QCryptoCipherDriver *drv;
    261
    262            switch (mode) {
    263            case QCRYPTO_CIPHER_MODE_ECB:
    264                drv = &qcrypto_cipher_aes_driver_ecb;
    265                break;
    266            case QCRYPTO_CIPHER_MODE_CBC:
    267                drv = &qcrypto_cipher_aes_driver_cbc;
    268                break;
    269            default:
    270                goto bad_mode;
    271            }
    272
    273            ctx = g_new0(QCryptoCipherBuiltinAES, 1);
    274            ctx->base.driver = drv;
    275
    276            if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) {
    277                error_setg(errp, "Failed to set encryption key");
    278                goto error;
    279            }
    280            if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) {
    281                error_setg(errp, "Failed to set decryption key");
    282                goto error;
    283            }
    284
    285            return &ctx->base;
    286
    287        error:
    288            g_free(ctx);
    289            return NULL;
    290        }
    291
    292    default:
    293        error_setg(errp,
    294                   "Unsupported cipher algorithm %s",
    295                   QCryptoCipherAlgorithm_str(alg));
    296        return NULL;
    297    }
    298
    299 bad_mode:
    300    error_setg(errp, "Unsupported cipher mode %s",
    301               QCryptoCipherMode_str(mode));
    302    return NULL;
    303}