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