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 assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]); 431 432 session = builtin->sessions[session_id]; 433 if (session->cipher) { 434 qcrypto_cipher_free(session->cipher); 435 } else if (session->akcipher) { 436 qcrypto_akcipher_free(session->akcipher); 437 } 438 439 g_free(session); 440 builtin->sessions[session_id] = NULL; 441 if (cb) { 442 cb(opaque, VIRTIO_CRYPTO_OK); 443 } 444 return 0; 445 } 446 447 static int cryptodev_builtin_sym_operation( 448 CryptoDevBackendBuiltinSession *sess, 449 CryptoDevBackendSymOpInfo *op_info, Error **errp) 450 { 451 int ret; 452 453 if (op_info->op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) { 454 error_setg(errp, 455 "Algorithm chain is unsupported for cryptdoev-builtin"); 456 return -VIRTIO_CRYPTO_NOTSUPP; 457 } 458 459 if (op_info->iv_len > 0) { 460 ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv, 461 op_info->iv_len, errp); 462 if (ret < 0) { 463 return -VIRTIO_CRYPTO_ERR; 464 } 465 } 466 467 if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) { 468 ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src, 469 op_info->dst, op_info->src_len, errp); 470 if (ret < 0) { 471 return -VIRTIO_CRYPTO_ERR; 472 } 473 } else { 474 ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src, 475 op_info->dst, op_info->src_len, errp); 476 if (ret < 0) { 477 return -VIRTIO_CRYPTO_ERR; 478 } 479 } 480 481 return VIRTIO_CRYPTO_OK; 482 } 483 484 static int cryptodev_builtin_asym_operation( 485 CryptoDevBackendBuiltinSession *sess, uint32_t op_code, 486 CryptoDevBackendAsymOpInfo *op_info, Error **errp) 487 { 488 int ret; 489 490 switch (op_code) { 491 case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT: 492 ret = qcrypto_akcipher_encrypt(sess->akcipher, 493 op_info->src, op_info->src_len, 494 op_info->dst, op_info->dst_len, errp); 495 break; 496 497 case VIRTIO_CRYPTO_AKCIPHER_DECRYPT: 498 ret = qcrypto_akcipher_decrypt(sess->akcipher, 499 op_info->src, op_info->src_len, 500 op_info->dst, op_info->dst_len, errp); 501 break; 502 503 case VIRTIO_CRYPTO_AKCIPHER_SIGN: 504 ret = qcrypto_akcipher_sign(sess->akcipher, 505 op_info->src, op_info->src_len, 506 op_info->dst, op_info->dst_len, errp); 507 break; 508 509 case VIRTIO_CRYPTO_AKCIPHER_VERIFY: 510 ret = qcrypto_akcipher_verify(sess->akcipher, 511 op_info->src, op_info->src_len, 512 op_info->dst, op_info->dst_len, errp); 513 break; 514 515 default: 516 return -VIRTIO_CRYPTO_ERR; 517 } 518 519 if (ret < 0) { 520 if (op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY) { 521 return -VIRTIO_CRYPTO_KEY_REJECTED; 522 } 523 return -VIRTIO_CRYPTO_ERR; 524 } 525 526 /* Buffer is too short, typically the driver should handle this case */ 527 if (unlikely(ret > op_info->dst_len)) { 528 if (errp && !*errp) { 529 error_setg(errp, "dst buffer too short"); 530 } 531 532 return -VIRTIO_CRYPTO_ERR; 533 } 534 535 op_info->dst_len = ret; 536 537 return VIRTIO_CRYPTO_OK; 538 } 539 540 static int cryptodev_builtin_operation( 541 CryptoDevBackend *backend, 542 CryptoDevBackendOpInfo *op_info) 543 { 544 CryptoDevBackendBuiltin *builtin = 545 CRYPTODEV_BACKEND_BUILTIN(backend); 546 CryptoDevBackendBuiltinSession *sess; 547 CryptoDevBackendSymOpInfo *sym_op_info; 548 CryptoDevBackendAsymOpInfo *asym_op_info; 549 QCryptodevBackendAlgType algtype = op_info->algtype; 550 int status = -VIRTIO_CRYPTO_ERR; 551 Error *local_error = NULL; 552 553 if (op_info->session_id >= MAX_NUM_SESSIONS || 554 builtin->sessions[op_info->session_id] == NULL) { 555 error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "", 556 op_info->session_id); 557 return -VIRTIO_CRYPTO_INVSESS; 558 } 559 560 sess = builtin->sessions[op_info->session_id]; 561 if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) { 562 sym_op_info = op_info->u.sym_op_info; 563 status = cryptodev_builtin_sym_operation(sess, sym_op_info, 564 &local_error); 565 } else if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) { 566 asym_op_info = op_info->u.asym_op_info; 567 status = cryptodev_builtin_asym_operation(sess, op_info->op_code, 568 asym_op_info, &local_error); 569 } 570 571 if (local_error) { 572 error_report_err(local_error); 573 } 574 if (op_info->cb) { 575 op_info->cb(op_info->opaque, status); 576 } 577 return 0; 578 } 579 580 static void cryptodev_builtin_cleanup( 581 CryptoDevBackend *backend, 582 Error **errp) 583 { 584 CryptoDevBackendBuiltin *builtin = 585 CRYPTODEV_BACKEND_BUILTIN(backend); 586 size_t i; 587 int queues = backend->conf.peers.queues; 588 CryptoDevBackendClient *cc; 589 590 for (i = 0; i < MAX_NUM_SESSIONS; i++) { 591 if (builtin->sessions[i] != NULL) { 592 cryptodev_builtin_close_session(backend, i, 0, NULL, NULL); 593 } 594 } 595 596 for (i = 0; i < queues; i++) { 597 cc = backend->conf.peers.ccs[i]; 598 if (cc) { 599 cryptodev_backend_free_client(cc); 600 backend->conf.peers.ccs[i] = NULL; 601 } 602 } 603 604 cryptodev_backend_set_ready(backend, false); 605 } 606 607 static void 608 cryptodev_builtin_class_init(ObjectClass *oc, void *data) 609 { 610 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_CLASS(oc); 611 612 bc->init = cryptodev_builtin_init; 613 bc->cleanup = cryptodev_builtin_cleanup; 614 bc->create_session = cryptodev_builtin_create_session; 615 bc->close_session = cryptodev_builtin_close_session; 616 bc->do_op = cryptodev_builtin_operation; 617 } 618 619 static const TypeInfo cryptodev_builtin_info = { 620 .name = TYPE_CRYPTODEV_BACKEND_BUILTIN, 621 .parent = TYPE_CRYPTODEV_BACKEND, 622 .class_init = cryptodev_builtin_class_init, 623 .instance_size = sizeof(CryptoDevBackendBuiltin), 624 }; 625 626 static void 627 cryptodev_builtin_register_types(void) 628 { 629 type_register_static(&cryptodev_builtin_info); 630 } 631 632 type_init(cryptodev_builtin_register_types); 633