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.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 "crypto/aes.h"
  23#include "crypto/desrfb.h"
  24#include "crypto/xts.h"
  25#include "cipherpriv.h"
  26
  27typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
  28struct QCryptoCipherBuiltinAESContext {
  29    AES_KEY enc;
  30    AES_KEY dec;
  31};
  32typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
  33struct QCryptoCipherBuiltinAES {
  34    QCryptoCipherBuiltinAESContext key;
  35    QCryptoCipherBuiltinAESContext key_tweak;
  36    uint8_t iv[AES_BLOCK_SIZE];
  37};
  38typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
  39struct QCryptoCipherBuiltinDESRFB {
  40    uint8_t *key;
  41    size_t nkey;
  42};
  43
  44typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin;
  45struct QCryptoCipherBuiltin {
  46    union {
  47        QCryptoCipherBuiltinAES aes;
  48        QCryptoCipherBuiltinDESRFB desrfb;
  49    } state;
  50    size_t blocksize;
  51    void (*free)(QCryptoCipher *cipher);
  52    int (*setiv)(QCryptoCipher *cipher,
  53                 const uint8_t *iv, size_t niv,
  54                 Error **errp);
  55    int (*encrypt)(QCryptoCipher *cipher,
  56                   const void *in,
  57                   void *out,
  58                   size_t len,
  59                   Error **errp);
  60    int (*decrypt)(QCryptoCipher *cipher,
  61                   const void *in,
  62                   void *out,
  63                   size_t len,
  64                   Error **errp);
  65};
  66
  67
  68static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
  69{
  70    QCryptoCipherBuiltin *ctxt = cipher->opaque;
  71
  72    g_free(ctxt);
  73    cipher->opaque = NULL;
  74}
  75
  76
  77static void qcrypto_cipher_aes_ecb_encrypt(AES_KEY *key,
  78                                           const void *in,
  79                                           void *out,
  80                                           size_t len)
  81{
  82    const uint8_t *inptr = in;
  83    uint8_t *outptr = out;
  84    while (len) {
  85        if (len > AES_BLOCK_SIZE) {
  86            AES_encrypt(inptr, outptr, key);
  87            inptr += AES_BLOCK_SIZE;
  88            outptr += AES_BLOCK_SIZE;
  89            len -= AES_BLOCK_SIZE;
  90        } else {
  91            uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
  92            memcpy(tmp1, inptr, len);
  93            /* Fill with 0 to avoid valgrind uninitialized reads */
  94            memset(tmp1 + len, 0, sizeof(tmp1) - len);
  95            AES_encrypt(tmp1, tmp2, key);
  96            memcpy(outptr, tmp2, len);
  97            len = 0;
  98        }
  99    }
 100}
 101
 102
 103static void qcrypto_cipher_aes_ecb_decrypt(AES_KEY *key,
 104                                           const void *in,
 105                                           void *out,
 106                                           size_t len)
 107{
 108    const uint8_t *inptr = in;
 109    uint8_t *outptr = out;
 110    while (len) {
 111        if (len > AES_BLOCK_SIZE) {
 112            AES_decrypt(inptr, outptr, key);
 113            inptr += AES_BLOCK_SIZE;
 114            outptr += AES_BLOCK_SIZE;
 115            len -= AES_BLOCK_SIZE;
 116        } else {
 117            uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
 118            memcpy(tmp1, inptr, len);
 119            /* Fill with 0 to avoid valgrind uninitialized reads */
 120            memset(tmp1 + len, 0, sizeof(tmp1) - len);
 121            AES_decrypt(tmp1, tmp2, key);
 122            memcpy(outptr, tmp2, len);
 123            len = 0;
 124        }
 125    }
 126}
 127
 128
 129static void qcrypto_cipher_aes_xts_encrypt(const void *ctx,
 130                                           size_t length,
 131                                           uint8_t *dst,
 132                                           const uint8_t *src)
 133{
 134    const QCryptoCipherBuiltinAESContext *aesctx = ctx;
 135
 136    qcrypto_cipher_aes_ecb_encrypt((AES_KEY *)&aesctx->enc,
 137                                   src, dst, length);
 138}
 139
 140
 141static void qcrypto_cipher_aes_xts_decrypt(const void *ctx,
 142                                           size_t length,
 143                                           uint8_t *dst,
 144                                           const uint8_t *src)
 145{
 146    const QCryptoCipherBuiltinAESContext *aesctx = ctx;
 147
 148    qcrypto_cipher_aes_ecb_decrypt((AES_KEY *)&aesctx->dec,
 149                                   src, dst, length);
 150}
 151
 152
 153static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher,
 154                                      const void *in,
 155                                      void *out,
 156                                      size_t len,
 157                                      Error **errp)
 158{
 159    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 160
 161    switch (cipher->mode) {
 162    case QCRYPTO_CIPHER_MODE_ECB:
 163        qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc,
 164                                       in, out, len);
 165        break;
 166    case QCRYPTO_CIPHER_MODE_CBC:
 167        AES_cbc_encrypt(in, out, len,
 168                        &ctxt->state.aes.key.enc,
 169                        ctxt->state.aes.iv, 1);
 170        break;
 171    case QCRYPTO_CIPHER_MODE_XTS:
 172        xts_encrypt(&ctxt->state.aes.key,
 173                    &ctxt->state.aes.key_tweak,
 174                    qcrypto_cipher_aes_xts_encrypt,
 175                    qcrypto_cipher_aes_xts_decrypt,
 176                    ctxt->state.aes.iv,
 177                    len, out, in);
 178        break;
 179    default:
 180        g_assert_not_reached();
 181    }
 182
 183    return 0;
 184}
 185
 186
 187static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher,
 188                                      const void *in,
 189                                      void *out,
 190                                      size_t len,
 191                                      Error **errp)
 192{
 193    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 194
 195    switch (cipher->mode) {
 196    case QCRYPTO_CIPHER_MODE_ECB:
 197        qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec,
 198                                       in, out, len);
 199        break;
 200    case QCRYPTO_CIPHER_MODE_CBC:
 201        AES_cbc_encrypt(in, out, len,
 202                        &ctxt->state.aes.key.dec,
 203                        ctxt->state.aes.iv, 0);
 204        break;
 205    case QCRYPTO_CIPHER_MODE_XTS:
 206        xts_decrypt(&ctxt->state.aes.key,
 207                    &ctxt->state.aes.key_tweak,
 208                    qcrypto_cipher_aes_xts_encrypt,
 209                    qcrypto_cipher_aes_xts_decrypt,
 210                    ctxt->state.aes.iv,
 211                    len, out, in);
 212        break;
 213    default:
 214        g_assert_not_reached();
 215    }
 216
 217    return 0;
 218}
 219
 220static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
 221                                     const uint8_t *iv, size_t niv,
 222                                     Error **errp)
 223{
 224    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 225    if (niv != AES_BLOCK_SIZE) {
 226        error_setg(errp, "IV must be %d bytes not %zu",
 227                   AES_BLOCK_SIZE, niv);
 228        return -1;
 229    }
 230
 231    memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
 232
 233    return 0;
 234}
 235
 236
 237
 238
 239static QCryptoCipherBuiltin *
 240qcrypto_cipher_init_aes(QCryptoCipherMode mode,
 241                        const uint8_t *key, size_t nkey,
 242                        Error **errp)
 243{
 244    QCryptoCipherBuiltin *ctxt;
 245
 246    if (mode != QCRYPTO_CIPHER_MODE_CBC &&
 247        mode != QCRYPTO_CIPHER_MODE_ECB &&
 248        mode != QCRYPTO_CIPHER_MODE_XTS) {
 249        error_setg(errp, "Unsupported cipher mode %s",
 250                   QCryptoCipherMode_str(mode));
 251        return NULL;
 252    }
 253
 254    ctxt = g_new0(QCryptoCipherBuiltin, 1);
 255
 256    if (mode == QCRYPTO_CIPHER_MODE_XTS) {
 257        if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) {
 258            error_setg(errp, "Failed to set encryption key");
 259            goto error;
 260        }
 261
 262        if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) {
 263            error_setg(errp, "Failed to set decryption key");
 264            goto error;
 265        }
 266
 267        if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4,
 268                                &ctxt->state.aes.key_tweak.enc) != 0) {
 269            error_setg(errp, "Failed to set encryption key");
 270            goto error;
 271        }
 272
 273        if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4,
 274                                &ctxt->state.aes.key_tweak.dec) != 0) {
 275            error_setg(errp, "Failed to set decryption key");
 276            goto error;
 277        }
 278    } else {
 279        if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) {
 280            error_setg(errp, "Failed to set encryption key");
 281            goto error;
 282        }
 283
 284        if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) {
 285            error_setg(errp, "Failed to set decryption key");
 286            goto error;
 287        }
 288    }
 289
 290    ctxt->blocksize = AES_BLOCK_SIZE;
 291    ctxt->free = qcrypto_cipher_free_aes;
 292    ctxt->setiv = qcrypto_cipher_setiv_aes;
 293    ctxt->encrypt = qcrypto_cipher_encrypt_aes;
 294    ctxt->decrypt = qcrypto_cipher_decrypt_aes;
 295
 296    return ctxt;
 297
 298 error:
 299    g_free(ctxt);
 300    return NULL;
 301}
 302
 303
 304static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher)
 305{
 306    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 307
 308    g_free(ctxt->state.desrfb.key);
 309    g_free(ctxt);
 310    cipher->opaque = NULL;
 311}
 312
 313
 314static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
 315                                          const void *in,
 316                                          void *out,
 317                                          size_t len,
 318                                          Error **errp)
 319{
 320    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 321    size_t i;
 322
 323    if (len % 8) {
 324        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
 325                   len);
 326        return -1;
 327    }
 328
 329    deskey(ctxt->state.desrfb.key, EN0);
 330
 331    for (i = 0; i < len; i += 8) {
 332        des((void *)in + i, out + i);
 333    }
 334
 335    return 0;
 336}
 337
 338
 339static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
 340                                          const void *in,
 341                                          void *out,
 342                                          size_t len,
 343                                          Error **errp)
 344{
 345    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 346    size_t i;
 347
 348    if (len % 8) {
 349        error_setg(errp, "Buffer size must be multiple of 8 not %zu",
 350                   len);
 351        return -1;
 352    }
 353
 354    deskey(ctxt->state.desrfb.key, DE1);
 355
 356    for (i = 0; i < len; i += 8) {
 357        des((void *)in + i, out + i);
 358    }
 359
 360    return 0;
 361}
 362
 363
 364static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
 365                                        const uint8_t *iv, size_t niv,
 366                                        Error **errp)
 367{
 368    error_setg(errp, "Setting IV is not supported");
 369    return -1;
 370}
 371
 372
 373static QCryptoCipherBuiltin *
 374qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
 375                            const uint8_t *key, size_t nkey,
 376                            Error **errp)
 377{
 378    QCryptoCipherBuiltin *ctxt;
 379
 380    if (mode != QCRYPTO_CIPHER_MODE_ECB) {
 381        error_setg(errp, "Unsupported cipher mode %s",
 382                   QCryptoCipherMode_str(mode));
 383        return NULL;
 384    }
 385
 386    ctxt = g_new0(QCryptoCipherBuiltin, 1);
 387
 388    ctxt->state.desrfb.key = g_new0(uint8_t, nkey);
 389    memcpy(ctxt->state.desrfb.key, key, nkey);
 390    ctxt->state.desrfb.nkey = nkey;
 391
 392    ctxt->blocksize = 8;
 393    ctxt->free = qcrypto_cipher_free_des_rfb;
 394    ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
 395    ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
 396    ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
 397
 398    return ctxt;
 399}
 400
 401
 402bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
 403                             QCryptoCipherMode mode)
 404{
 405    switch (alg) {
 406    case QCRYPTO_CIPHER_ALG_DES_RFB:
 407    case QCRYPTO_CIPHER_ALG_AES_128:
 408    case QCRYPTO_CIPHER_ALG_AES_192:
 409    case QCRYPTO_CIPHER_ALG_AES_256:
 410        break;
 411    default:
 412        return false;
 413    }
 414
 415    switch (mode) {
 416    case QCRYPTO_CIPHER_MODE_ECB:
 417    case QCRYPTO_CIPHER_MODE_CBC:
 418    case QCRYPTO_CIPHER_MODE_XTS:
 419        return true;
 420    case QCRYPTO_CIPHER_MODE_CTR:
 421        return false;
 422    default:
 423        return false;
 424    }
 425}
 426
 427
 428static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
 429                                                    QCryptoCipherMode mode,
 430                                                    const uint8_t *key,
 431                                                    size_t nkey,
 432                                                    Error **errp)
 433{
 434    QCryptoCipherBuiltin *ctxt;
 435
 436    switch (mode) {
 437    case QCRYPTO_CIPHER_MODE_ECB:
 438    case QCRYPTO_CIPHER_MODE_CBC:
 439    case QCRYPTO_CIPHER_MODE_XTS:
 440        break;
 441    default:
 442        error_setg(errp, "Unsupported cipher mode %s",
 443                   QCryptoCipherMode_str(mode));
 444        return NULL;
 445    }
 446
 447    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
 448        return NULL;
 449    }
 450
 451    switch (alg) {
 452    case QCRYPTO_CIPHER_ALG_DES_RFB:
 453        ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
 454        break;
 455    case QCRYPTO_CIPHER_ALG_AES_128:
 456    case QCRYPTO_CIPHER_ALG_AES_192:
 457    case QCRYPTO_CIPHER_ALG_AES_256:
 458        ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
 459        break;
 460    default:
 461        error_setg(errp,
 462                   "Unsupported cipher algorithm %s",
 463                   QCryptoCipherAlgorithm_str(alg));
 464        return NULL;
 465    }
 466
 467    return ctxt;
 468}
 469
 470static void
 471qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher)
 472{
 473    QCryptoCipherBuiltin *ctxt;
 474
 475    ctxt = cipher->opaque;
 476    ctxt->free(cipher);
 477}
 478
 479
 480static int
 481qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
 482                               const void *in,
 483                               void *out,
 484                               size_t len,
 485                               Error **errp)
 486{
 487    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 488
 489    if (len % ctxt->blocksize) {
 490        error_setg(errp, "Length %zu must be a multiple of block size %zu",
 491                   len, ctxt->blocksize);
 492        return -1;
 493    }
 494
 495    return ctxt->encrypt(cipher, in, out, len, errp);
 496}
 497
 498
 499static int
 500qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
 501                               const void *in,
 502                               void *out,
 503                               size_t len,
 504                               Error **errp)
 505{
 506    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 507
 508    if (len % ctxt->blocksize) {
 509        error_setg(errp, "Length %zu must be a multiple of block size %zu",
 510                   len, ctxt->blocksize);
 511        return -1;
 512    }
 513
 514    return ctxt->decrypt(cipher, in, out, len, errp);
 515}
 516
 517
 518static int
 519qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher,
 520                             const uint8_t *iv, size_t niv,
 521                             Error **errp)
 522{
 523    QCryptoCipherBuiltin *ctxt = cipher->opaque;
 524
 525    return ctxt->setiv(cipher, iv, niv, errp);
 526}
 527
 528
 529static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
 530    .cipher_encrypt = qcrypto_builtin_cipher_encrypt,
 531    .cipher_decrypt = qcrypto_builtin_cipher_decrypt,
 532    .cipher_setiv = qcrypto_builtin_cipher_setiv,
 533    .cipher_free = qcrypto_builtin_cipher_ctx_free,
 534};
 535