qemu/crypto/cipher-builtin.c
<<
>>
Prefs
   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 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
  24typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
  25struct QCryptoCipherBuiltinAES {
  26    AES_KEY encrypt_key;
  27    AES_KEY decrypt_key;
  28    uint8_t *iv;
  29    size_t niv;
  30};
  31typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
  32struct QCryptoCipherBuiltinDESRFB {
  33    uint8_t *key;
  34    size_t nkey;
  35};
  36
  37typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
  38struct QCryptoCipherBuiltin {
  39    union {
  40        QCryptoCipherBuiltinAES aes;
  41        QCryptoCipherBuiltinDESRFB desrfb;
  42    } state;
  43    void (*free)(QCryptoCipher *cipher);
  44    int (*setiv)(QCryptoCipher *cipher,
  45                 const uint8_t *iv, size_t niv,
  46                 Error **errp);
  47    int (*encrypt)(QCryptoCipher *cipher,
  48                   const void *in,
  49                   void *out,
  50                   size_t len,
  51                   Error **errp);
  52    int (*decrypt)(QCryptoCipher *cipher,
  53                   const void *in,
  54                   void *out,
  55                   size_t len,
  56                   Error **errp);
  57};
  58
  59
  60static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
  61{
  62    QCryptoCipherBuiltin *ctxt = cipher->opaque;
  63
  64    g_free(ctxt->state.aes.iv);
  65    g_free(ctxt);
  66    cipher->opaque = NULL;
  67}
  68
  69
  70static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
  71                                      const void *in,
  72                                      void *out,
  73                                      size_t len,
  74                                      Error **errp)
  75{
  76    QCryptoCipherBuiltin *ctxt = cipher->opaque;
  77
  78    if (cipher->mode == QCRYPTO_CIPHER_MODE_ECB) {
  79        const uint8_t *inptr = in;
  80        uint8_t *outptr = out;
  81        while (len) {
  82            if (len > AES_BLOCK_SIZE) {
  83                AES_encrypt(inptr, outptr, &ctxt->state.aes.encrypt_key);
  84                inptr += AES_BLOCK_SIZE;
  85                outptr += AES_BLOCK_SIZE;
  86                len -= AES_BLOCK_SIZE;
  87            } else {
  88                uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
  89                memcpy(tmp1, inptr, len);
  90                /* Fill with 0 to avoid valgrind uninitialized reads */
  91                memset(tmp1 + len, 0, sizeof(tmp1) - len);
  92                AES_encrypt(tmp1, tmp2, &ctxt->state.aes.encrypt_key);
  93                memcpy(outptr, tmp2, len);
  94                len = 0;
  95            }
  96        }
  97    } else {
  98        AES_cbc_encrypt(in, out, len,
  99                        &ctxt->state.aes.encrypt_key,
 100                        ctxt->state.aes.iv, 1);
 101    }
 102
 103    return 0;
 104}
 105
 106
 107static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
 108                                      const void *in,
 109                                      void *out,
 110                                      size_t len,
 111                                      Error **errp)
 112{
 113    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 114
 115    if (cipher->mode == QCRYPTO_CIPHER_MODE_ECB) {
 116        const uint8_t *inptr = in;
 117        uint8_t *outptr = out;
 118        while (len) {
 119            if (len > AES_BLOCK_SIZE) {
 120                AES_decrypt(inptr, outptr, &ctxt->state.aes.decrypt_key);
 121                inptr += AES_BLOCK_SIZE;
 122                outptr += AES_BLOCK_SIZE;
 123                len -= AES_BLOCK_SIZE;
 124            } else {
 125                uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
 126                memcpy(tmp1, inptr, len);
 127                /* Fill with 0 to avoid valgrind uninitialized reads */
 128                memset(tmp1 + len, 0, sizeof(tmp1) - len);
 129                AES_decrypt(tmp1, tmp2, &ctxt->state.aes.decrypt_key);
 130                memcpy(outptr, tmp2, len);
 131                len = 0;
 132            }
 133        }
 134    } else {
 135        AES_cbc_encrypt(in, out, len,
 136                        &ctxt->state.aes.decrypt_key,
 137                        ctxt->state.aes.iv, 0);
 138    }
 139
 140    return 0;
 141}
 142
 143static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
 144                                     const uint8_t *iv, size_t niv,
 145                                     Error **errp)
 146{
 147    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 148    if (niv != 16) {
 149        error_setg(errp, "IV must be 16 bytes not %zu", niv);
 150        return -1;
 151    }
 152
 153    g_free(ctxt->state.aes.iv);
 154    ctxt->state.aes.iv = g_new0(uint8_t, niv);
 155    memcpy(ctxt->state.aes.iv, iv, niv);
 156    ctxt->state.aes.niv = niv;
 157
 158    return 0;
 159}
 160
 161
 162
 163
 164static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
 165                                   const uint8_t *key, size_t nkey,
 166                                   Error **errp)
 167{
 168    QCryptoCipherBuiltin *ctxt;
 169
 170    if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
 171        cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
 172        error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
 173        return -1;
 174    }
 175
 176    ctxt = g_new0(QCryptoCipherBuiltin, 1);
 177
 178    if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.encrypt_key) != 0) {
 179        error_setg(errp, "Failed to set encryption key");
 180        goto error;
 181    }
 182
 183    if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.decrypt_key) != 0) {
 184        error_setg(errp, "Failed to set decryption key");
 185        goto error;
 186    }
 187
 188    ctxt->free = qcrypto_cipher_free_aes;
 189    ctxt->setiv = qcrypto_cipher_setiv_aes;
 190    ctxt->encrypt = qcrypto_cipher_encrypt_aes;
 191    ctxt->decrypt = qcrypto_cipher_decrypt_aes;
 192
 193    cipher->opaque = ctxt;
 194
 195    return 0;
 196
 197 error:
 198    g_free(ctxt);
 199    return -1;
 200}
 201
 202
 203static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
 204{
 205    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 206
 207    g_free(ctxt->state.desrfb.key);
 208    g_free(ctxt);
 209    cipher->opaque = NULL;
 210}
 211
 212
 213static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
 214                                          const void *in,
 215                                          void *out,
 216                                          size_t len,
 217                                          Error **errp)
 218{
 219    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 220    size_t i;
 221
 222    if (len % 8) {
 223        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
 224                   len);
 225        return -1;
 226    }
 227
 228    deskey(ctxt->state.desrfb.key, EN0);
 229
 230    for (i = 0; i < len; i += 8) {
 231        des((void *)in + i, out + i);
 232    }
 233
 234    return 0;
 235}
 236
 237
 238static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
 239                                          const void *in,
 240                                          void *out,
 241                                          size_t len,
 242                                          Error **errp)
 243{
 244    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 245    size_t i;
 246
 247    if (len % 8) {
 248        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
 249                   len);
 250        return -1;
 251    }
 252
 253    deskey(ctxt->state.desrfb.key, DE1);
 254
 255    for (i = 0; i < len; i += 8) {
 256        des((void *)in + i, out + i);
 257    }
 258
 259    return 0;
 260}
 261
 262
 263static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
 264                                        const uint8_t *iv, size_t niv,
 265                                        Error **errp)
 266{
 267    error_setg(errp, "Setting IV is not supported");
 268    return -1;
 269}
 270
 271
 272static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
 273                                       const uint8_t *key, size_t nkey,
 274                                       Error **errp)
 275{
 276    QCryptoCipherBuiltin *ctxt;
 277
 278    if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
 279        error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
 280        return -1;
 281    }
 282
 283    ctxt = g_new0(QCryptoCipherBuiltin, 1);
 284
 285    ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
 286    memcpy(ctxt->state.desrfb.key, key, nkey);
 287    ctxt->state.desrfb.nkey = nkey;
 288
 289    ctxt->free = qcrypto_cipher_free_des_rfb;
 290    ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
 291    ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
 292    ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
 293
 294    cipher->opaque = ctxt;
 295
 296    return 0;
 297}
 298
 299
 300bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
 301{
 302    switch (alg) {
 303    case QCRYPTO_CIPHER_ALG_DES_RFB:
 304    case QCRYPTO_CIPHER_ALG_AES_128:
 305    case QCRYPTO_CIPHER_ALG_AES_192:
 306    case QCRYPTO_CIPHER_ALG_AES_256:
 307        return true;
 308    default:
 309        return false;
 310    }
 311}
 312
 313
 314QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
 315                                  QCryptoCipherMode mode,
 316                                  const uint8_t *key, size_t nkey,
 317                                  Error **errp)
 318{
 319    QCryptoCipher *cipher;
 320
 321    cipher = g_new0(QCryptoCipher, 1);
 322    cipher->alg = alg;
 323    cipher->mode = mode;
 324
 325    if (!qcrypto_cipher_validate_key_length(alg, nkey, errp)) {
 326        goto error;
 327    }
 328
 329    switch (cipher->alg) {
 330    case QCRYPTO_CIPHER_ALG_DES_RFB:
 331        if (qcrypto_cipher_init_des_rfb(cipher, key, nkey, errp) < 0) {
 332            goto error;
 333        }
 334        break;
 335    case QCRYPTO_CIPHER_ALG_AES_128:
 336    case QCRYPTO_CIPHER_ALG_AES_192:
 337    case QCRYPTO_CIPHER_ALG_AES_256:
 338        if (qcrypto_cipher_init_aes(cipher, key, nkey, errp) < 0) {
 339            goto error;
 340        }
 341        break;
 342    default:
 343        error_setg(errp,
 344                   "Unsupported cipher algorithm %d", cipher->alg);
 345        goto error;
 346    }
 347
 348    return cipher;
 349
 350 error:
 351    g_free(cipher);
 352    return NULL;
 353}
 354
 355void qcrypto_cipher_free(QCryptoCipher *cipher)
 356{
 357    QCryptoCipherBuiltin *ctxt;
 358
 359    if (!cipher) {
 360        return;
 361    }
 362
 363    ctxt = cipher->opaque;
 364    ctxt->free(cipher);
 365    g_free(cipher);
 366}
 367
 368
 369int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
 370                           const void *in,
 371                           void *out,
 372                           size_t len,
 373                           Error **errp)
 374{
 375    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 376
 377    return ctxt->encrypt(cipher, in, out, len, errp);
 378}
 379
 380
 381int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
 382                           const void *in,
 383                           void *out,
 384                           size_t len,
 385                           Error **errp)
 386{
 387    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 388
 389    return ctxt->decrypt(cipher, in, out, len, errp);
 390}
 391
 392
 393int qcrypto_cipher_setiv(QCryptoCipher *cipher,
 394                         const uint8_t *iv, size_t niv,
 395                         Error **errp)
 396{
 397    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 398
 399    return ctxt->setiv(cipher, iv, niv, errp);
 400}
 401