1 /* 2 * QEMU Cryptodev backend for QEMU cipher APIs 3 * 4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 * 6 * Authors: 7 * Gonglei <arei.gonglei@huawei.com> 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 21 * 22 */ 23 24 #include "qemu/osdep.h" 25 #include "sysemu/cryptodev.h" 26 #include "qapi/error.h" 27 #include "standard-headers/linux/virtio_crypto.h" 28 #include "crypto/cipher.h" 29 #include "crypto/akcipher.h" 30 #include "qom/object.h" 31 32 33 /** 34 * @TYPE_CRYPTODEV_BACKEND_BUILTIN: 35 * name of backend that uses QEMU cipher API 36 */ 37 #define TYPE_CRYPTODEV_BACKEND_BUILTIN "cryptodev-backend-builtin" 38 39 OBJECT_DECLARE_SIMPLE_TYPE(CryptoDevBackendBuiltin, CRYPTODEV_BACKEND_BUILTIN) 40 41 42 typedef struct CryptoDevBackendBuiltinSession { 43 QCryptoCipher *cipher; 44 uint8_t direction; /* encryption or decryption */ 45 uint8_t type; /* cipher? hash? aead? */ 46 QCryptoAkCipher *akcipher; 47 QTAILQ_ENTRY(CryptoDevBackendBuiltinSession) next; 48 } CryptoDevBackendBuiltinSession; 49 50 /* Max number of symmetric/asymmetric sessions */ 51 #define MAX_NUM_SESSIONS 256 52 53 #define CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN 512 54 #define CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN 64 55 56 struct CryptoDevBackendBuiltin { 57 CryptoDevBackend parent_obj; 58 59 CryptoDevBackendBuiltinSession *sessions[MAX_NUM_SESSIONS]; 60 }; 61 62 static void cryptodev_builtin_init_akcipher(CryptoDevBackend *backend) 63 { 64 QCryptoAkCipherOptions opts; 65 66 opts.alg = QCRYPTO_AKCIPHER_ALG_RSA; 67 opts.u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW; 68 if (qcrypto_akcipher_supports(&opts)) { 69 backend->conf.crypto_services |= 70 (1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER); 71 backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA; 72 } 73 } 74 75 static void cryptodev_builtin_init( 76 CryptoDevBackend *backend, Error **errp) 77 { 78 /* Only support one queue */ 79 int queues = backend->conf.peers.queues; 80 CryptoDevBackendClient *cc; 81 82 if (queues != 1) { 83 error_setg(errp, 84 "Only support one queue in cryptdov-builtin backend"); 85 return; 86 } 87 88 cc = cryptodev_backend_new_client(); 89 cc->info_str = g_strdup_printf("cryptodev-builtin0"); 90 cc->queue_index = 0; 91 cc->type = QCRYPTODEV_BACKEND_TYPE_BUILTIN; 92 backend->conf.peers.ccs[0] = cc; 93 94 backend->conf.crypto_services = 95 1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER | 96 1u << QCRYPTODEV_BACKEND_SERVICE_HASH | 97 1u << QCRYPTODEV_BACKEND_SERVICE_MAC; 98 backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC; 99 backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; 100 /* 101 * Set the Maximum length of crypto request. 102 * Why this value? Just avoid to overflow when 103 * memory allocation for each crypto request. 104 */ 105 backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendOpInfo); 106 backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN; 107 backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN; 108 cryptodev_builtin_init_akcipher(backend); 109 110 cryptodev_backend_set_ready(backend, true); 111 } 112 113 static int 114 cryptodev_builtin_get_unused_session_index( 115 CryptoDevBackendBuiltin *builtin) 116 { 117 size_t i; 118 119 for (i = 0; i < MAX_NUM_SESSIONS; i++) { 120 if (builtin->sessions[i] == NULL) { 121 return i; 122 } 123 } 124 125 return -1; 126 } 127 128 #define AES_KEYSIZE_128 16 129 #define AES_KEYSIZE_192 24 130 #define AES_KEYSIZE_256 32 131 #define AES_KEYSIZE_128_XTS AES_KEYSIZE_256 132 #define AES_KEYSIZE_256_XTS 64 133 134 static int 135 cryptodev_builtin_get_aes_algo(uint32_t key_len, int mode, Error **errp) 136 { 137 int algo; 138 139 if (key_len == AES_KEYSIZE_128) { 140 algo = QCRYPTO_CIPHER_ALG_AES_128; 141 } else if (key_len == AES_KEYSIZE_192) { 142 algo = QCRYPTO_CIPHER_ALG_AES_192; 143 } else if (key_len == AES_KEYSIZE_256) { /* equals AES_KEYSIZE_128_XTS */ 144 if (mode == QCRYPTO_CIPHER_MODE_XTS) { 145 algo = QCRYPTO_CIPHER_ALG_AES_128; 146 } else { 147 algo = QCRYPTO_CIPHER_ALG_AES_256; 148 } 149 } else if (key_len == AES_KEYSIZE_256_XTS) { 150 if (mode == QCRYPTO_CIPHER_MODE_XTS) { 151 algo = QCRYPTO_CIPHER_ALG_AES_256; 152 } else { 153 goto err; 154 } 155 } else { 156 goto err; 157 } 158 159 return algo; 160 161 err: 162 error_setg(errp, "Unsupported key length :%u", key_len); 163 return -1; 164 } 165 166 static int cryptodev_builtin_get_rsa_hash_algo( 167 int virtio_rsa_hash, Error **errp) 168 { 169 switch (virtio_rsa_hash) { 170 case VIRTIO_CRYPTO_RSA_MD5: 171 return QCRYPTO_HASH_ALG_MD5; 172 173 case VIRTIO_CRYPTO_RSA_SHA1: 174 return QCRYPTO_HASH_ALG_SHA1; 175 176 case VIRTIO_CRYPTO_RSA_SHA256: 177 return QCRYPTO_HASH_ALG_SHA256; 178 179 case VIRTIO_CRYPTO_RSA_SHA512: 180 return QCRYPTO_HASH_ALG_SHA512; 181 182 default: 183 error_setg(errp, "Unsupported rsa hash algo: %d", virtio_rsa_hash); 184 return -1; 185 } 186 } 187 188 static int cryptodev_builtin_set_rsa_options( 189 int virtio_padding_algo, 190 int virtio_hash_algo, 191 QCryptoAkCipherOptionsRSA *opt, 192 Error **errp) 193 { 194 if (virtio_padding_algo == VIRTIO_CRYPTO_RSA_PKCS1_PADDING) { 195 int hash_alg; 196 197 hash_alg = cryptodev_builtin_get_rsa_hash_algo(virtio_hash_algo, errp); 198 if (hash_alg < 0) { 199 return -1; 200 } 201 opt->hash_alg = hash_alg; 202 opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_PKCS1; 203 return 0; 204 } 205 206 if (virtio_padding_algo == VIRTIO_CRYPTO_RSA_RAW_PADDING) { 207 opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW; 208 return 0; 209 } 210 211 error_setg(errp, "Unsupported rsa padding algo: %d", virtio_padding_algo); 212 return -1; 213 } 214 215 static int cryptodev_builtin_create_cipher_session( 216 CryptoDevBackendBuiltin *builtin, 217 CryptoDevBackendSymSessionInfo *sess_info, 218 Error **errp) 219 { 220 int algo; 221 int mode; 222 QCryptoCipher *cipher; 223 int index; 224 CryptoDevBackendBuiltinSession *sess; 225 226 if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) { 227 error_setg(errp, "Unsupported optype :%u", sess_info->op_type); 228 return -1; 229 } 230 231 index = cryptodev_builtin_get_unused_session_index(builtin); 232 if (index < 0) { 233 error_setg(errp, "Total number of sessions created exceeds %u", 234 MAX_NUM_SESSIONS); 235 return -1; 236 } 237 238 switch (sess_info->cipher_alg) { 239 case VIRTIO_CRYPTO_CIPHER_AES_ECB: 240 mode = QCRYPTO_CIPHER_MODE_ECB; 241 algo = cryptodev_builtin_get_aes_algo(sess_info->key_len, 242 mode, errp); 243 if (algo < 0) { 244 return -1; 245 } 246 break; 247 case VIRTIO_CRYPTO_CIPHER_AES_CBC: 248 mode = QCRYPTO_CIPHER_MODE_CBC; 249 algo = cryptodev_builtin_get_aes_algo(sess_info->key_len, 250 mode, errp); 251 if (algo < 0) { 252 return -1; 253 } 254 break; 255 case VIRTIO_CRYPTO_CIPHER_AES_CTR: 256 mode = QCRYPTO_CIPHER_MODE_CTR; 257 algo = cryptodev_builtin_get_aes_algo(sess_info->key_len, 258 mode, errp); 259 if (algo < 0) { 260 return -1; 261 } 262 break; 263 case VIRTIO_CRYPTO_CIPHER_AES_XTS: 264 mode = QCRYPTO_CIPHER_MODE_XTS; 265 algo = cryptodev_builtin_get_aes_algo(sess_info->key_len, 266 mode, errp); 267 if (algo < 0) { 268 return -1; 269 } 270 break; 271 case VIRTIO_CRYPTO_CIPHER_3DES_ECB: 272 mode = QCRYPTO_CIPHER_MODE_ECB; 273 algo = QCRYPTO_CIPHER_ALG_3DES; 274 break; 275 case VIRTIO_CRYPTO_CIPHER_3DES_CBC: 276 mode = QCRYPTO_CIPHER_MODE_CBC; 277 algo = QCRYPTO_CIPHER_ALG_3DES; 278 break; 279 case VIRTIO_CRYPTO_CIPHER_3DES_CTR: 280 mode = QCRYPTO_CIPHER_MODE_CTR; 281 algo = QCRYPTO_CIPHER_ALG_3DES; 282 break; 283 default: 284 error_setg(errp, "Unsupported cipher alg :%u", 285 sess_info->cipher_alg); 286 return -1; 287 } 288 289 cipher = qcrypto_cipher_new(algo, mode, 290 sess_info->cipher_key, 291 sess_info->key_len, 292 errp); 293 if (!cipher) { 294 return -1; 295 } 296 297 sess = g_new0(CryptoDevBackendBuiltinSession, 1); 298 sess->cipher = cipher; 299 sess->direction = sess_info->direction; 300 sess->type = sess_info->op_type; 301 302 builtin->sessions[index] = sess; 303 304 return index; 305 } 306 307 static int cryptodev_builtin_create_akcipher_session( 308 CryptoDevBackendBuiltin *builtin, 309 CryptoDevBackendAsymSessionInfo *sess_info, 310 Error **errp) 311 { 312 CryptoDevBackendBuiltinSession *sess; 313 QCryptoAkCipher *akcipher; 314 int index; 315 QCryptoAkCipherKeyType type; 316 QCryptoAkCipherOptions opts; 317 318 switch (sess_info->algo) { 319 case VIRTIO_CRYPTO_AKCIPHER_RSA: 320 opts.alg = QCRYPTO_AKCIPHER_ALG_RSA; 321 if (cryptodev_builtin_set_rsa_options(sess_info->u.rsa.padding_algo, 322 sess_info->u.rsa.hash_algo, &opts.u.rsa, errp) != 0) { 323 return -1; 324 } 325 break; 326 327 /* TODO support DSA&ECDSA until qemu crypto framework support these */ 328 329 default: 330 error_setg(errp, "Unsupported akcipher alg %u", sess_info->algo); 331 return -1; 332 } 333 334 switch (sess_info->keytype) { 335 case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC: 336 type = QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC; 337 break; 338 339 case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE: 340 type = QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE; 341 break; 342 343 default: 344 error_setg(errp, "Unsupported akcipher keytype %u", sess_info->keytype); 345 return -1; 346 } 347 348 index = cryptodev_builtin_get_unused_session_index(builtin); 349 if (index < 0) { 350 error_setg(errp, "Total number of sessions created exceeds %u", 351 MAX_NUM_SESSIONS); 352 return -1; 353 } 354 355 akcipher = qcrypto_akcipher_new(&opts, type, sess_info->key, 356 sess_info->keylen, errp); 357 if (!akcipher) { 358 return -1; 359 } 360 361 sess = g_new0(CryptoDevBackendBuiltinSession, 1); 362 sess->akcipher = akcipher; 363 364 builtin->sessions[index] = sess; 365 366 return index; 367 } 368 369 static int cryptodev_builtin_create_session( 370 CryptoDevBackend *backend, 371 CryptoDevBackendSessionInfo *sess_info, 372 uint32_t queue_index, 373 CryptoDevCompletionFunc cb, 374 void *opaque) 375 { 376 CryptoDevBackendBuiltin *builtin = 377 CRYPTODEV_BACKEND_BUILTIN(backend); 378 CryptoDevBackendSymSessionInfo *sym_sess_info; 379 CryptoDevBackendAsymSessionInfo *asym_sess_info; 380 int ret, status; 381 Error *local_error = NULL; 382 383 switch (sess_info->op_code) { 384 case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION: 385 sym_sess_info = &sess_info->u.sym_sess_info; 386 ret = cryptodev_builtin_create_cipher_session( 387 builtin, sym_sess_info, &local_error); 388 break; 389 390 case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION: 391 asym_sess_info = &sess_info->u.asym_sess_info; 392 ret = cryptodev_builtin_create_akcipher_session( 393 builtin, asym_sess_info, &local_error); 394 break; 395 396 case VIRTIO_CRYPTO_HASH_CREATE_SESSION: 397 case VIRTIO_CRYPTO_MAC_CREATE_SESSION: 398 default: 399 error_setg(&local_error, "Unsupported opcode :%" PRIu32 "", 400 sess_info->op_code); 401 return -VIRTIO_CRYPTO_NOTSUPP; 402 } 403 404 if (local_error) { 405 error_report_err(local_error); 406 } 407 if (ret < 0) { 408 status = -VIRTIO_CRYPTO_ERR; 409 } else { 410 sess_info->session_id = ret; 411 status = VIRTIO_CRYPTO_OK; 412 } 413 if (cb) { 414 cb(opaque, status); 415 } 416 return 0; 417 } 418 419 static int cryptodev_builtin_close_session( 420 CryptoDevBackend *backend, 421 uint64_t session_id, 422 uint32_t queue_index, 423 CryptoDevCompletionFunc cb, 424 void *opaque) 425 { 426 CryptoDevBackendBuiltin *builtin = 427 CRYPTODEV_BACKEND_BUILTIN(backend); 428 CryptoDevBackendBuiltinSession *session; 429 430 if (session_id >= MAX_NUM_SESSIONS || !builtin->sessions[session_id]) { 431 return -VIRTIO_CRYPTO_INVSESS; 432 } 433 434 session = builtin->sessions[session_id]; 435 if (session->cipher) { 436 qcrypto_cipher_free(session->cipher); 437 } else if (session->akcipher) { 438 qcrypto_akcipher_free(session->akcipher); 439 } 440 441 g_free(session); 442 builtin->sessions[session_id] = NULL; 443 if (cb) { 444 cb(opaque, VIRTIO_CRYPTO_OK); 445 } 446 return 0; 447 } 448 449 static int cryptodev_builtin_sym_operation( 450 CryptoDevBackendBuiltinSession *sess, 451 CryptoDevBackendSymOpInfo *op_info, Error **errp) 452 { 453 int ret; 454 455 if (op_info->op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) { 456 error_setg(errp, 457 "Algorithm chain is unsupported for cryptdoev-builtin"); 458 return -VIRTIO_CRYPTO_NOTSUPP; 459 } 460 461 if (op_info->iv_len > 0) { 462 ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv, 463 op_info->iv_len, errp); 464 if (ret < 0) { 465 return -VIRTIO_CRYPTO_ERR; 466 } 467 } 468 469 if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) { 470 ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src, 471 op_info->dst, op_info->src_len, errp); 472 if (ret < 0) { 473 return -VIRTIO_CRYPTO_ERR; 474 } 475 } else { 476 ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src, 477 op_info->dst, op_info->src_len, errp); 478 if (ret < 0) { 479 return -VIRTIO_CRYPTO_ERR; 480 } 481 } 482 483 return VIRTIO_CRYPTO_OK; 484 } 485 486 static int cryptodev_builtin_asym_operation( 487 CryptoDevBackendBuiltinSession *sess, uint32_t op_code, 488 CryptoDevBackendAsymOpInfo *op_info, Error **errp) 489 { 490 int ret; 491 492 switch (op_code) { 493 case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT: 494 ret = qcrypto_akcipher_encrypt(sess->akcipher, 495 op_info->src, op_info->src_len, 496 op_info->dst, op_info->dst_len, errp); 497 break; 498 499 case VIRTIO_CRYPTO_AKCIPHER_DECRYPT: 500 ret = qcrypto_akcipher_decrypt(sess->akcipher, 501 op_info->src, op_info->src_len, 502 op_info->dst, op_info->dst_len, errp); 503 break; 504 505 case VIRTIO_CRYPTO_AKCIPHER_SIGN: 506 ret = qcrypto_akcipher_sign(sess->akcipher, 507 op_info->src, op_info->src_len, 508 op_info->dst, op_info->dst_len, errp); 509 break; 510 511 case VIRTIO_CRYPTO_AKCIPHER_VERIFY: 512 ret = qcrypto_akcipher_verify(sess->akcipher, 513 op_info->src, op_info->src_len, 514 op_info->dst, op_info->dst_len, errp); 515 break; 516 517 default: 518 return -VIRTIO_CRYPTO_ERR; 519 } 520 521 if (ret < 0) { 522 if (op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY) { 523 return -VIRTIO_CRYPTO_KEY_REJECTED; 524 } 525 return -VIRTIO_CRYPTO_ERR; 526 } 527 528 /* Buffer is too short, typically the driver should handle this case */ 529 if (unlikely(ret > op_info->dst_len)) { 530 if (errp && !*errp) { 531 error_setg(errp, "dst buffer too short"); 532 } 533 534 return -VIRTIO_CRYPTO_ERR; 535 } 536 537 op_info->dst_len = ret; 538 539 return VIRTIO_CRYPTO_OK; 540 } 541 542 static int cryptodev_builtin_operation( 543 CryptoDevBackend *backend, 544 CryptoDevBackendOpInfo *op_info) 545 { 546 CryptoDevBackendBuiltin *builtin = 547 CRYPTODEV_BACKEND_BUILTIN(backend); 548 CryptoDevBackendBuiltinSession *sess; 549 CryptoDevBackendSymOpInfo *sym_op_info; 550 CryptoDevBackendAsymOpInfo *asym_op_info; 551 QCryptodevBackendAlgType algtype = op_info->algtype; 552 int status = -VIRTIO_CRYPTO_ERR; 553 Error *local_error = NULL; 554 555 if (op_info->session_id >= MAX_NUM_SESSIONS || 556 builtin->sessions[op_info->session_id] == NULL) { 557 error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "", 558 op_info->session_id); 559 return -VIRTIO_CRYPTO_INVSESS; 560 } 561 562 sess = builtin->sessions[op_info->session_id]; 563 if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) { 564 sym_op_info = op_info->u.sym_op_info; 565 status = cryptodev_builtin_sym_operation(sess, sym_op_info, 566 &local_error); 567 } else if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) { 568 asym_op_info = op_info->u.asym_op_info; 569 status = cryptodev_builtin_asym_operation(sess, op_info->op_code, 570 asym_op_info, &local_error); 571 } 572 573 if (local_error) { 574 error_report_err(local_error); 575 } 576 if (op_info->cb) { 577 op_info->cb(op_info->opaque, status); 578 } 579 return 0; 580 } 581 582 static void cryptodev_builtin_cleanup( 583 CryptoDevBackend *backend, 584 Error **errp) 585 { 586 CryptoDevBackendBuiltin *builtin = 587 CRYPTODEV_BACKEND_BUILTIN(backend); 588 size_t i; 589 int queues = backend->conf.peers.queues; 590 CryptoDevBackendClient *cc; 591 592 for (i = 0; i < MAX_NUM_SESSIONS; i++) { 593 if (builtin->sessions[i] != NULL) { 594 cryptodev_builtin_close_session(backend, i, 0, NULL, NULL); 595 } 596 } 597 598 for (i = 0; i < queues; i++) { 599 cc = backend->conf.peers.ccs[i]; 600 if (cc) { 601 cryptodev_backend_free_client(cc); 602 backend->conf.peers.ccs[i] = NULL; 603 } 604 } 605 606 cryptodev_backend_set_ready(backend, false); 607 } 608 609 static void 610 cryptodev_builtin_class_init(ObjectClass *oc, void *data) 611 { 612 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_CLASS(oc); 613 614 bc->init = cryptodev_builtin_init; 615 bc->cleanup = cryptodev_builtin_cleanup; 616 bc->create_session = cryptodev_builtin_create_session; 617 bc->close_session = cryptodev_builtin_close_session; 618 bc->do_op = cryptodev_builtin_operation; 619 } 620 621 static const TypeInfo cryptodev_builtin_info = { 622 .name = TYPE_CRYPTODEV_BACKEND_BUILTIN, 623 .parent = TYPE_CRYPTODEV_BACKEND, 624 .class_init = cryptodev_builtin_class_init, 625 .instance_size = sizeof(CryptoDevBackendBuiltin), 626 }; 627 628 static void 629 cryptodev_builtin_register_types(void) 630 { 631 type_register_static(&cryptodev_builtin_info); 632 } 633 634 type_init(cryptodev_builtin_register_types); 635