qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cipher.c (5915B)


      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 #include "qemu/osdep.h"
     22 #include "qemu/host-utils.h"
     23 #include "qapi/error.h"
     24 #include "crypto/cipher.h"
     25 #include "cipherpriv.h"
     26 
     27 
     28 static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
     29     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     30     [QCRYPTO_CIPHER_ALG_AES_192] = 24,
     31     [QCRYPTO_CIPHER_ALG_AES_256] = 32,
     32     [QCRYPTO_CIPHER_ALG_DES] = 8,
     33     [QCRYPTO_CIPHER_ALG_3DES] = 24,
     34     [QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
     35     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
     36     [QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
     37     [QCRYPTO_CIPHER_ALG_SERPENT_256] = 32,
     38     [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
     39     [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24,
     40     [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32,
     41 };
     42 
     43 static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
     44     [QCRYPTO_CIPHER_ALG_AES_128] = 16,
     45     [QCRYPTO_CIPHER_ALG_AES_192] = 16,
     46     [QCRYPTO_CIPHER_ALG_AES_256] = 16,
     47     [QCRYPTO_CIPHER_ALG_DES] = 8,
     48     [QCRYPTO_CIPHER_ALG_3DES] = 8,
     49     [QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
     50     [QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
     51     [QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
     52     [QCRYPTO_CIPHER_ALG_SERPENT_256] = 16,
     53     [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16,
     54     [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16,
     55     [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16,
     56 };
     57 
     58 static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
     59     [QCRYPTO_CIPHER_MODE_ECB] = false,
     60     [QCRYPTO_CIPHER_MODE_CBC] = true,
     61     [QCRYPTO_CIPHER_MODE_XTS] = true,
     62     [QCRYPTO_CIPHER_MODE_CTR] = true,
     63 };
     64 
     65 
     66 size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg)
     67 {
     68     assert(alg < G_N_ELEMENTS(alg_key_len));
     69     return alg_block_len[alg];
     70 }
     71 
     72 
     73 size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg)
     74 {
     75     assert(alg < G_N_ELEMENTS(alg_key_len));
     76     return alg_key_len[alg];
     77 }
     78 
     79 
     80 size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg,
     81                                  QCryptoCipherMode mode)
     82 {
     83     if (alg >= G_N_ELEMENTS(alg_block_len)) {
     84         return 0;
     85     }
     86     if (mode >= G_N_ELEMENTS(mode_need_iv)) {
     87         return 0;
     88     }
     89 
     90     if (mode_need_iv[mode]) {
     91         return alg_block_len[alg];
     92     }
     93     return 0;
     94 }
     95 
     96 
     97 static bool
     98 qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
     99                                    QCryptoCipherMode mode,
    100                                    size_t nkey,
    101                                    Error **errp)
    102 {
    103     if ((unsigned)alg >= QCRYPTO_CIPHER_ALG__MAX) {
    104         error_setg(errp, "Cipher algorithm %d out of range",
    105                    alg);
    106         return false;
    107     }
    108 
    109     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
    110         if (alg == QCRYPTO_CIPHER_ALG_DES ||
    111             alg == QCRYPTO_CIPHER_ALG_3DES) {
    112             error_setg(errp, "XTS mode not compatible with DES/3DES");
    113             return false;
    114         }
    115         if (nkey % 2) {
    116             error_setg(errp, "XTS cipher key length should be a multiple of 2");
    117             return false;
    118         }
    119 
    120         if (alg_key_len[alg] != (nkey / 2)) {
    121             error_setg(errp, "Cipher key length %zu should be %zu",
    122                        nkey, alg_key_len[alg] * 2);
    123             return false;
    124         }
    125     } else {
    126         if (alg_key_len[alg] != nkey) {
    127             error_setg(errp, "Cipher key length %zu should be %zu",
    128                        nkey, alg_key_len[alg]);
    129             return false;
    130         }
    131     }
    132     return true;
    133 }
    134 
    135 #ifdef CONFIG_GCRYPT
    136 #include "cipher-gcrypt.c.inc"
    137 #elif defined CONFIG_NETTLE
    138 #include "cipher-nettle.c.inc"
    139 #elif defined CONFIG_GNUTLS_CRYPTO
    140 #include "cipher-gnutls.c.inc"
    141 #else
    142 #include "cipher-builtin.c.inc"
    143 #endif
    144 
    145 QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
    146                                   QCryptoCipherMode mode,
    147                                   const uint8_t *key, size_t nkey,
    148                                   Error **errp)
    149 {
    150     QCryptoCipher *cipher = NULL;
    151 
    152 #ifdef CONFIG_AF_ALG
    153     cipher = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL);
    154 #endif
    155 
    156     if (!cipher) {
    157         cipher = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp);
    158         if (!cipher) {
    159             return NULL;
    160         }
    161     }
    162 
    163     cipher->alg = alg;
    164     cipher->mode = mode;
    165 
    166     return cipher;
    167 }
    168 
    169 
    170 int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
    171                            const void *in,
    172                            void *out,
    173                            size_t len,
    174                            Error **errp)
    175 {
    176     const QCryptoCipherDriver *drv = cipher->driver;
    177     return drv->cipher_encrypt(cipher, in, out, len, errp);
    178 }
    179 
    180 
    181 int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
    182                            const void *in,
    183                            void *out,
    184                            size_t len,
    185                            Error **errp)
    186 {
    187     const QCryptoCipherDriver *drv = cipher->driver;
    188     return drv->cipher_decrypt(cipher, in, out, len, errp);
    189 }
    190 
    191 
    192 int qcrypto_cipher_setiv(QCryptoCipher *cipher,
    193                          const uint8_t *iv, size_t niv,
    194                          Error **errp)
    195 {
    196     const QCryptoCipherDriver *drv = cipher->driver;
    197     return drv->cipher_setiv(cipher, iv, niv, errp);
    198 }
    199 
    200 
    201 void qcrypto_cipher_free(QCryptoCipher *cipher)
    202 {
    203     if (cipher) {
    204         cipher->driver->cipher_free(cipher);
    205     }
    206 }