1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <pkcs11_ta.h> 8 #include <string.h> 9 #include <tee_api_defines.h> 10 #include <tee_internal_api.h> 11 #include <tee_internal_api_extensions.h> 12 #include <util.h> 13 14 #include "attributes.h" 15 #include "object.h" 16 #include "pkcs11_attributes.h" 17 #include "pkcs11_helpers.h" 18 #include "pkcs11_token.h" 19 #include "processing.h" 20 #include "serializer.h" 21 22 static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) 23 { 24 if (session_is_active(session)) 25 return PKCS11_CKR_OPERATION_ACTIVE; 26 27 return PKCS11_CKR_OK; 28 } 29 30 static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd) 31 { 32 switch (cmd) { 33 case PKCS11_CMD_ENCRYPT_UPDATE: 34 case PKCS11_CMD_ENCRYPT_ONESHOT: 35 case PKCS11_CMD_ENCRYPT_FINAL: 36 return PKCS11_FUNCTION_ENCRYPT; 37 case PKCS11_CMD_DECRYPT_UPDATE: 38 case PKCS11_CMD_DECRYPT_ONESHOT: 39 case PKCS11_CMD_DECRYPT_FINAL: 40 return PKCS11_FUNCTION_DECRYPT; 41 case PKCS11_CMD_SIGN_ONESHOT: 42 case PKCS11_CMD_SIGN_UPDATE: 43 case PKCS11_CMD_SIGN_FINAL: 44 return PKCS11_FUNCTION_SIGN; 45 case PKCS11_CMD_VERIFY_ONESHOT: 46 case PKCS11_CMD_VERIFY_UPDATE: 47 case PKCS11_CMD_VERIFY_FINAL: 48 return PKCS11_FUNCTION_VERIFY; 49 default: 50 return PKCS11_FUNCTION_UNKNOWN; 51 } 52 } 53 54 static bool func_matches_state(enum processing_func function, 55 enum pkcs11_proc_state state) 56 { 57 switch (function) { 58 case PKCS11_FUNCTION_ENCRYPT: 59 return state == PKCS11_SESSION_ENCRYPTING || 60 state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 61 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 62 case PKCS11_FUNCTION_DECRYPT: 63 return state == PKCS11_SESSION_DECRYPTING || 64 state == PKCS11_SESSION_DECRYPTING_DIGESTING || 65 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 66 case PKCS11_FUNCTION_DIGEST: 67 return state == PKCS11_SESSION_DIGESTING || 68 state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 69 case PKCS11_FUNCTION_SIGN: 70 return state == PKCS11_SESSION_SIGNING || 71 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 72 case PKCS11_FUNCTION_VERIFY: 73 return state == PKCS11_SESSION_VERIFYING || 74 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 75 case PKCS11_FUNCTION_SIGN_RECOVER: 76 return state == PKCS11_SESSION_SIGNING_RECOVER; 77 case PKCS11_FUNCTION_VERIFY_RECOVER: 78 return state == PKCS11_SESSION_SIGNING_RECOVER; 79 default: 80 TEE_Panic(function); 81 return false; 82 } 83 } 84 85 static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 86 enum processing_func function) 87 { 88 enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 89 90 if (session->processing && 91 func_matches_state(function, session->processing->state)) 92 rc = PKCS11_CKR_OK; 93 94 return rc; 95 } 96 97 void release_active_processing(struct pkcs11_session *session) 98 { 99 if (!session->processing) 100 return; 101 102 if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 103 TEE_FreeOperation(session->processing->tee_op_handle); 104 session->processing->tee_op_handle = TEE_HANDLE_NULL; 105 } 106 107 TEE_Free(session->processing->extra_ctx); 108 109 TEE_Free(session->processing); 110 session->processing = NULL; 111 } 112 113 size_t get_object_key_bit_size(struct pkcs11_object *obj) 114 { 115 uint32_t a_size = 0; 116 struct obj_attrs *attrs = obj->attributes; 117 118 switch (get_key_type(attrs)) { 119 case PKCS11_CKK_AES: 120 case PKCS11_CKK_GENERIC_SECRET: 121 case PKCS11_CKK_MD5_HMAC: 122 case PKCS11_CKK_SHA_1_HMAC: 123 case PKCS11_CKK_SHA224_HMAC: 124 case PKCS11_CKK_SHA256_HMAC: 125 case PKCS11_CKK_SHA384_HMAC: 126 case PKCS11_CKK_SHA512_HMAC: 127 if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 128 return 0; 129 130 return a_size * 8; 131 default: 132 TEE_Panic(0); 133 return 0; 134 } 135 } 136 137 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 138 { 139 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 140 void *data = NULL; 141 uint32_t data_size = 0; 142 uint32_t value_len = 0; 143 void *value = NULL; 144 145 if (!*head) 146 return PKCS11_CKR_TEMPLATE_INCONSISTENT; 147 148 rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 149 if (rc || data_size != sizeof(uint32_t)) { 150 DMSG("%s", rc ? "No attribute value_len found" : 151 "Invalid size for attribute VALUE_LEN"); 152 153 return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 154 } 155 TEE_MemMove(&value_len, data, data_size); 156 157 /* Remove the default empty value attribute if found */ 158 rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 159 if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 160 return PKCS11_CKR_GENERAL_ERROR; 161 162 value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 163 if (!value) 164 return PKCS11_CKR_DEVICE_MEMORY; 165 166 TEE_GenerateRandom(value, value_len); 167 168 rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 169 170 TEE_Free(value); 171 172 return rc; 173 } 174 175 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 176 uint32_t ptypes, TEE_Param *params) 177 { 178 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 179 TEE_PARAM_TYPE_NONE, 180 TEE_PARAM_TYPE_MEMREF_OUTPUT, 181 TEE_PARAM_TYPE_NONE); 182 TEE_Param *ctrl = params; 183 TEE_Param *out = params + 2; 184 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 185 struct serialargs ctrlargs = { }; 186 struct pkcs11_session *session = NULL; 187 struct pkcs11_attribute_head *proc_params = NULL; 188 struct obj_attrs *head = NULL; 189 struct pkcs11_object_head *template = NULL; 190 size_t template_size = 0; 191 uint32_t obj_handle = 0; 192 193 if (!client || ptypes != exp_pt || 194 out->memref.size != sizeof(obj_handle)) 195 return PKCS11_CKR_ARGUMENTS_BAD; 196 197 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 198 199 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 200 if (rc) 201 return rc; 202 203 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 204 if (rc) 205 goto out; 206 207 rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 208 if (rc) 209 goto out; 210 211 if (serialargs_remaining_bytes(&ctrlargs)) { 212 rc = PKCS11_CKR_ARGUMENTS_BAD; 213 goto out; 214 } 215 216 rc = get_ready_session(session); 217 if (rc) 218 goto out; 219 220 template_size = sizeof(*template) + template->attrs_size; 221 222 rc = check_mechanism_against_processing(session, proc_params->id, 223 PKCS11_FUNCTION_GENERATE, 224 PKCS11_FUNC_STEP_INIT); 225 if (rc) { 226 DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 227 goto out; 228 } 229 230 /* 231 * Prepare a clean initial state for the requested object attributes. 232 * Free temporary template once done. 233 */ 234 rc = create_attributes_from_template(&head, template, template_size, 235 NULL, PKCS11_FUNCTION_GENERATE, 236 proc_params->id, 237 PKCS11_CKO_UNDEFINED_ID); 238 if (rc) 239 goto out; 240 241 TEE_Free(template); 242 template = NULL; 243 244 rc = check_created_attrs(head, NULL); 245 if (rc) 246 goto out; 247 248 rc = check_created_attrs_against_processing(proc_params->id, head); 249 if (rc) 250 goto out; 251 252 rc = check_created_attrs_against_token(session, head); 253 if (rc) 254 goto out; 255 256 /* 257 * Execute target processing and add value as attribute 258 * PKCS11_CKA_VALUE. Symm key generation: depends on target 259 * processing to be used. 260 */ 261 switch (proc_params->id) { 262 case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 263 case PKCS11_CKM_AES_KEY_GEN: 264 /* Generate random of size specified by attribute VALUE_LEN */ 265 rc = generate_random_key_value(&head); 266 if (rc) 267 goto out; 268 break; 269 270 default: 271 rc = PKCS11_CKR_MECHANISM_INVALID; 272 goto out; 273 } 274 275 TEE_Free(proc_params); 276 proc_params = NULL; 277 278 /* 279 * Object is ready, register it and return a handle. 280 */ 281 rc = create_object(session, head, &obj_handle); 282 if (rc) 283 goto out; 284 285 /* 286 * Now obj_handle (through the related struct pkcs11_object instance) 287 * owns the serialized buffer that holds the object attributes. 288 * We reset head to NULL as it is no more the buffer owner and would 289 * be freed at function out. 290 */ 291 head = NULL; 292 293 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 294 out->memref.size = sizeof(obj_handle); 295 296 DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 297 session->handle, obj_handle); 298 299 out: 300 TEE_Free(proc_params); 301 TEE_Free(template); 302 TEE_Free(head); 303 304 return rc; 305 } 306 307 /* 308 * entry_processing_init - Generic entry for initializing a processing 309 * 310 * @client = client reference 311 * @ptype = Invocation parameter types 312 * @params = Invocation parameters reference 313 * @function - encrypt, decrypt, sign, verify, digest, ... 314 */ 315 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 316 uint32_t ptypes, TEE_Param *params, 317 enum processing_func function) 318 { 319 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 320 TEE_PARAM_TYPE_NONE, 321 TEE_PARAM_TYPE_NONE, 322 TEE_PARAM_TYPE_NONE); 323 TEE_Param *ctrl = params; 324 enum pkcs11_rc rc = PKCS11_CKR_OK; 325 struct serialargs ctrlargs = { }; 326 struct pkcs11_session *session = NULL; 327 struct pkcs11_attribute_head *proc_params = NULL; 328 uint32_t key_handle = 0; 329 struct pkcs11_object *obj = NULL; 330 331 if (!client || ptypes != exp_pt) 332 return PKCS11_CKR_ARGUMENTS_BAD; 333 334 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 335 336 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 337 if (rc) 338 return rc; 339 340 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 341 if (rc) 342 return rc; 343 344 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 345 if (rc) 346 return rc; 347 348 if (serialargs_remaining_bytes(&ctrlargs)) { 349 rc = PKCS11_CKR_ARGUMENTS_BAD; 350 goto out; 351 } 352 353 rc = get_ready_session(session); 354 if (rc) 355 goto out; 356 357 obj = pkcs11_handle2object(key_handle, session); 358 if (!obj) { 359 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 360 goto out; 361 } 362 363 rc = set_processing_state(session, function, obj, NULL); 364 if (rc) 365 goto out; 366 367 rc = check_mechanism_against_processing(session, proc_params->id, 368 function, 369 PKCS11_FUNC_STEP_INIT); 370 if (rc) 371 goto out; 372 373 rc = check_parent_attrs_against_processing(proc_params->id, function, 374 obj->attributes); 375 if (rc) 376 goto out; 377 378 rc = check_access_attrs_against_token(session, obj->attributes); 379 if (rc) 380 goto out; 381 382 if (processing_is_tee_symm(proc_params->id)) 383 rc = init_symm_operation(session, function, proc_params, obj); 384 else 385 rc = PKCS11_CKR_MECHANISM_INVALID; 386 387 if (rc == PKCS11_CKR_OK) { 388 session->processing->mecha_type = proc_params->id; 389 DMSG("PKCS11 session %"PRIu32": init processing %s %s", 390 session->handle, id2str_proc(proc_params->id), 391 id2str_function(function)); 392 } 393 394 out: 395 if (rc && session) 396 release_active_processing(session); 397 398 TEE_Free(proc_params); 399 400 return rc; 401 } 402 403 /* 404 * entry_processing_step - Generic entry on active processing 405 * 406 * @client = client reference 407 * @ptype = Invocation parameter types 408 * @params = Invocation parameters reference 409 * @function - encrypt, decrypt, sign, verify, digest, ... 410 * @step - update, oneshot, final 411 */ 412 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 413 uint32_t ptypes, TEE_Param *params, 414 enum processing_func function, 415 enum processing_step step) 416 { 417 TEE_Param *ctrl = params; 418 enum pkcs11_rc rc = PKCS11_CKR_OK; 419 struct serialargs ctrlargs = { }; 420 struct pkcs11_session *session = NULL; 421 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 422 423 if (!client || 424 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 425 return PKCS11_CKR_ARGUMENTS_BAD; 426 427 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 428 429 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 430 if (rc) 431 return rc; 432 433 if (serialargs_remaining_bytes(&ctrlargs)) 434 return PKCS11_CKR_ARGUMENTS_BAD; 435 436 rc = get_active_session(session, function); 437 if (rc) 438 return rc; 439 440 mecha_type = session->processing->mecha_type; 441 rc = check_mechanism_against_processing(session, mecha_type, 442 function, step); 443 if (rc) 444 goto out; 445 446 if (processing_is_tee_symm(mecha_type)) 447 rc = step_symm_operation(session, function, step, 448 ptypes, params); 449 else 450 rc = PKCS11_CKR_MECHANISM_INVALID; 451 452 if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) { 453 session->processing->updated = true; 454 DMSG("PKCS11 session%"PRIu32": processing %s %s", 455 session->handle, id2str_proc(mecha_type), 456 id2str_function(function)); 457 } 458 459 out: 460 switch (step) { 461 case PKCS11_FUNC_STEP_UPDATE: 462 if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 463 release_active_processing(session); 464 break; 465 default: 466 /* ONESHOT and FINAL terminates processing on success */ 467 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 468 release_active_processing(session); 469 break; 470 } 471 472 return rc; 473 } 474 475 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 476 uint32_t ptypes, TEE_Param *params, 477 enum processing_func function) 478 { 479 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 480 TEE_PARAM_TYPE_NONE, 481 TEE_PARAM_TYPE_MEMREF_OUTPUT, 482 TEE_PARAM_TYPE_NONE); 483 TEE_Param *ctrl = params; 484 TEE_Param *out = params + 2; 485 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 486 struct serialargs ctrlargs = { }; 487 struct pkcs11_session *session = NULL; 488 struct pkcs11_attribute_head *proc_params = NULL; 489 struct pkcs11_object_head *template = NULL; 490 uint32_t parent_handle = 0; 491 uint32_t obj_handle = 0; 492 struct pkcs11_object *parent = NULL; 493 struct obj_attrs *head = NULL; 494 size_t template_size = 0; 495 void *out_buf = NULL; 496 uint32_t out_size = 0; 497 498 if (!client || ptypes != exp_pt || 499 out->memref.size != sizeof(obj_handle)) 500 return PKCS11_CKR_ARGUMENTS_BAD; 501 502 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 503 504 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 505 if (rc) 506 return rc; 507 508 rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 509 if (rc) 510 return rc; 511 512 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 513 if (rc) 514 goto out_free; 515 516 rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 517 if (rc) 518 goto out_free; 519 520 if (serialargs_remaining_bytes(&ctrlargs)) { 521 rc = PKCS11_CKR_ARGUMENTS_BAD; 522 goto out_free; 523 } 524 525 /* Return error if processing already active */ 526 rc = get_ready_session(session); 527 if (rc) 528 goto out_free; 529 530 /* Check parent handle */ 531 parent = pkcs11_handle2object(parent_handle, session); 532 if (!parent) { 533 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 534 goto out_free; 535 } 536 537 /* Check if mechanism can be used for derivation function */ 538 rc = check_mechanism_against_processing(session, proc_params->id, 539 function, 540 PKCS11_FUNC_STEP_INIT); 541 if (rc) 542 goto out_free; 543 544 /* Set the processing state to active */ 545 rc = set_processing_state(session, function, parent, NULL); 546 if (rc) 547 goto out_free; 548 549 /* 550 * Check if base/parent key has CKA_DERIVE set and its key type is 551 * compatible with the mechanism passed 552 */ 553 rc = check_parent_attrs_against_processing(proc_params->id, function, 554 parent->attributes); 555 if (rc) { 556 /* 557 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 558 * specified with C_Derive/Unwrap() in the specification. So 559 * return the next most appropriate error. 560 */ 561 if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 562 rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 563 goto out; 564 } 565 566 /* Check access of base/parent key */ 567 rc = check_access_attrs_against_token(session, parent->attributes); 568 if (rc) 569 goto out; 570 571 template_size = sizeof(*template) + template->attrs_size; 572 /* 573 * Prepare a clean initial state for the requested object attributes 574 * using base/parent key attributes. Free temporary template once done. 575 */ 576 rc = create_attributes_from_template(&head, template, template_size, 577 parent->attributes, 578 function, 579 proc_params->id, 580 PKCS11_CKO_UNDEFINED_ID); 581 if (rc) 582 goto out; 583 584 TEE_Free(template); 585 template = NULL; 586 587 /* check_created_attrs() is called later once key size is known */ 588 589 rc = check_created_attrs_against_processing(proc_params->id, head); 590 if (rc) 591 goto out; 592 593 rc = check_created_attrs_against_token(session, head); 594 if (rc) 595 goto out; 596 597 if (processing_is_tee_symm(proc_params->id)) { 598 /* 599 * These derivation mechanism require encryption to be 600 * performed on the data passed in proc_params by parent 601 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 602 * to init_symm_operation() 603 */ 604 rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 605 proc_params, parent); 606 if (rc) 607 goto out; 608 609 session->processing->mecha_type = proc_params->id; 610 611 rc = derive_key_by_symm_enc(session, &out_buf, &out_size); 612 if (rc) 613 goto out; 614 } else { 615 rc = PKCS11_CKR_MECHANISM_INVALID; 616 goto out; 617 } 618 619 rc = set_key_data(&head, out_buf, out_size); 620 if (rc) 621 goto out; 622 623 TEE_Free(out_buf); 624 out_buf = NULL; 625 626 TEE_Free(proc_params); 627 proc_params = NULL; 628 629 /* 630 * Object is ready, register it and return a handle. 631 */ 632 rc = create_object(session, head, &obj_handle); 633 if (rc) 634 goto out; 635 636 /* 637 * Now obj_handle (through the related struct pkcs11_object instance) 638 * owns the serialized buffer that holds the object attributes. 639 * We reset head to NULL as it is no more the buffer owner and would 640 * be freed at function out. 641 */ 642 head = NULL; 643 644 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 645 out->memref.size = sizeof(obj_handle); 646 647 DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 648 session->handle, obj_handle); 649 650 out: 651 release_active_processing(session); 652 out_free: 653 TEE_Free(proc_params); 654 TEE_Free(template); 655 TEE_Free(head); 656 TEE_Free(out_buf); 657 658 return rc; 659 } 660 661 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 662 uint32_t ptypes, 663 TEE_Param *params) 664 { 665 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 666 TEE_PARAM_TYPE_NONE, 667 TEE_PARAM_TYPE_NONE, 668 TEE_PARAM_TYPE_NONE); 669 TEE_Param *ctrl = params; 670 enum pkcs11_rc rc = PKCS11_CKR_OK; 671 struct serialargs ctrlargs = { }; 672 struct pkcs11_session *session = NULL; 673 enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 674 uint32_t cmd = 0; 675 676 if (!client || ptypes != exp_pt) 677 return PKCS11_CKR_ARGUMENTS_BAD; 678 679 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 680 681 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 682 if (rc) 683 return rc; 684 685 rc = serialargs_get_u32(&ctrlargs, &cmd); 686 687 if (serialargs_remaining_bytes(&ctrlargs)) 688 return PKCS11_CKR_ARGUMENTS_BAD; 689 690 function = func_for_cmd(cmd); 691 if (function == PKCS11_FUNCTION_UNKNOWN) 692 return PKCS11_CKR_ARGUMENTS_BAD; 693 694 rc = get_active_session(session, function); 695 if (rc) 696 return rc; 697 698 release_active_processing(session); 699 700 DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 701 702 return PKCS11_CKR_OK; 703 } 704