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 case PKCS11_CMD_DIGEST_UPDATE: 50 case PKCS11_CMD_DIGEST_KEY: 51 case PKCS11_CMD_DIGEST_ONESHOT: 52 case PKCS11_CMD_DIGEST_FINAL: 53 return PKCS11_FUNCTION_DIGEST; 54 default: 55 return PKCS11_FUNCTION_UNKNOWN; 56 } 57 } 58 59 static bool func_matches_state(enum processing_func function, 60 enum pkcs11_proc_state state) 61 { 62 switch (function) { 63 case PKCS11_FUNCTION_ENCRYPT: 64 return state == PKCS11_SESSION_ENCRYPTING || 65 state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 66 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 67 case PKCS11_FUNCTION_DECRYPT: 68 return state == PKCS11_SESSION_DECRYPTING || 69 state == PKCS11_SESSION_DECRYPTING_DIGESTING || 70 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 71 case PKCS11_FUNCTION_DIGEST: 72 return state == PKCS11_SESSION_DIGESTING || 73 state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 74 case PKCS11_FUNCTION_SIGN: 75 return state == PKCS11_SESSION_SIGNING || 76 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 77 case PKCS11_FUNCTION_VERIFY: 78 return state == PKCS11_SESSION_VERIFYING || 79 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 80 case PKCS11_FUNCTION_SIGN_RECOVER: 81 return state == PKCS11_SESSION_SIGNING_RECOVER; 82 case PKCS11_FUNCTION_VERIFY_RECOVER: 83 return state == PKCS11_SESSION_SIGNING_RECOVER; 84 default: 85 TEE_Panic(function); 86 return false; 87 } 88 } 89 90 static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 91 enum processing_func function) 92 { 93 enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 94 95 if (session->processing && 96 func_matches_state(function, session->processing->state)) 97 rc = PKCS11_CKR_OK; 98 99 return rc; 100 } 101 102 void release_active_processing(struct pkcs11_session *session) 103 { 104 if (!session->processing) 105 return; 106 107 if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) { 108 TEE_FreeOperation(session->processing->tee_hash_op_handle); 109 session->processing->tee_hash_op_handle = TEE_HANDLE_NULL; 110 session->processing->tee_hash_algo = 0; 111 } 112 113 if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 114 TEE_FreeOperation(session->processing->tee_op_handle); 115 session->processing->tee_op_handle = TEE_HANDLE_NULL; 116 } 117 118 TEE_Free(session->processing->extra_ctx); 119 120 TEE_Free(session->processing); 121 session->processing = NULL; 122 } 123 124 size_t get_object_key_bit_size(struct pkcs11_object *obj) 125 { 126 void *a_ptr = NULL; 127 uint32_t a_size = 0; 128 struct obj_attrs *attrs = obj->attributes; 129 130 switch (get_key_type(attrs)) { 131 case PKCS11_CKK_AES: 132 case PKCS11_CKK_GENERIC_SECRET: 133 case PKCS11_CKK_MD5_HMAC: 134 case PKCS11_CKK_SHA_1_HMAC: 135 case PKCS11_CKK_SHA224_HMAC: 136 case PKCS11_CKK_SHA256_HMAC: 137 case PKCS11_CKK_SHA384_HMAC: 138 case PKCS11_CKK_SHA512_HMAC: 139 if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 140 return 0; 141 142 return a_size * 8; 143 case PKCS11_CKK_EC: 144 if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS, 145 &a_ptr, &a_size) || !a_ptr) 146 return 0; 147 148 return ec_params2tee_keysize(a_ptr, a_size); 149 default: 150 TEE_Panic(0); 151 return 0; 152 } 153 } 154 155 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 156 { 157 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 158 void *data = NULL; 159 uint32_t data_size = 0; 160 uint32_t value_len = 0; 161 void *value = NULL; 162 163 if (!*head) 164 return PKCS11_CKR_TEMPLATE_INCONSISTENT; 165 166 rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 167 if (rc || data_size != sizeof(uint32_t)) { 168 DMSG("%s", rc ? "No attribute value_len found" : 169 "Invalid size for attribute VALUE_LEN"); 170 171 return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 172 } 173 TEE_MemMove(&value_len, data, data_size); 174 175 /* Remove the default empty value attribute if found */ 176 rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 177 if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 178 return PKCS11_CKR_GENERAL_ERROR; 179 180 value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 181 if (!value) 182 return PKCS11_CKR_DEVICE_MEMORY; 183 184 TEE_GenerateRandom(value, value_len); 185 186 rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 187 188 TEE_Free(value); 189 190 return rc; 191 } 192 193 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 194 uint32_t ptypes, TEE_Param *params) 195 { 196 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 197 TEE_PARAM_TYPE_NONE, 198 TEE_PARAM_TYPE_MEMREF_OUTPUT, 199 TEE_PARAM_TYPE_NONE); 200 TEE_Param *ctrl = params; 201 TEE_Param *out = params + 2; 202 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 203 struct serialargs ctrlargs = { }; 204 struct pkcs11_session *session = NULL; 205 struct pkcs11_attribute_head *proc_params = NULL; 206 struct obj_attrs *head = NULL; 207 struct pkcs11_object_head *template = NULL; 208 size_t template_size = 0; 209 uint32_t obj_handle = 0; 210 211 if (!client || ptypes != exp_pt || 212 out->memref.size != sizeof(obj_handle)) 213 return PKCS11_CKR_ARGUMENTS_BAD; 214 215 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 216 217 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 218 if (rc) 219 return rc; 220 221 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 222 if (rc) 223 goto out; 224 225 rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 226 if (rc) 227 goto out; 228 229 if (serialargs_remaining_bytes(&ctrlargs)) { 230 rc = PKCS11_CKR_ARGUMENTS_BAD; 231 goto out; 232 } 233 234 rc = get_ready_session(session); 235 if (rc) 236 goto out; 237 238 template_size = sizeof(*template) + template->attrs_size; 239 240 rc = check_mechanism_against_processing(session, proc_params->id, 241 PKCS11_FUNCTION_GENERATE, 242 PKCS11_FUNC_STEP_INIT); 243 if (rc) { 244 DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 245 goto out; 246 } 247 248 /* 249 * Prepare a clean initial state for the requested object attributes. 250 * Free temporary template once done. 251 */ 252 rc = create_attributes_from_template(&head, template, template_size, 253 NULL, PKCS11_FUNCTION_GENERATE, 254 proc_params->id, 255 PKCS11_CKO_UNDEFINED_ID); 256 if (rc) 257 goto out; 258 259 TEE_Free(template); 260 template = NULL; 261 262 rc = check_created_attrs(head, NULL); 263 if (rc) 264 goto out; 265 266 rc = check_created_attrs_against_processing(proc_params->id, head); 267 if (rc) 268 goto out; 269 270 rc = check_created_attrs_against_token(session, head); 271 if (rc) 272 goto out; 273 274 /* 275 * Execute target processing and add value as attribute 276 * PKCS11_CKA_VALUE. Symm key generation: depends on target 277 * processing to be used. 278 */ 279 switch (proc_params->id) { 280 case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 281 case PKCS11_CKM_AES_KEY_GEN: 282 /* Generate random of size specified by attribute VALUE_LEN */ 283 rc = generate_random_key_value(&head); 284 if (rc) 285 goto out; 286 break; 287 288 default: 289 rc = PKCS11_CKR_MECHANISM_INVALID; 290 goto out; 291 } 292 293 TEE_Free(proc_params); 294 proc_params = NULL; 295 296 /* 297 * Object is ready, register it and return a handle. 298 */ 299 rc = create_object(session, head, &obj_handle); 300 if (rc) 301 goto out; 302 303 /* 304 * Now obj_handle (through the related struct pkcs11_object instance) 305 * owns the serialized buffer that holds the object attributes. 306 * We reset head to NULL as it is no more the buffer owner and would 307 * be freed at function out. 308 */ 309 head = NULL; 310 311 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 312 out->memref.size = sizeof(obj_handle); 313 314 DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 315 session->handle, obj_handle); 316 317 out: 318 TEE_Free(proc_params); 319 TEE_Free(template); 320 TEE_Free(head); 321 322 return rc; 323 } 324 325 enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, 326 uint32_t attribute, 327 void **data, size_t *size) 328 { 329 TEE_Result res = TEE_ERROR_GENERIC; 330 void *ptr = NULL; 331 uint32_t sz = 0; 332 333 res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz); 334 if (res != TEE_ERROR_SHORT_BUFFER) 335 return PKCS11_CKR_FUNCTION_FAILED; 336 337 ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); 338 if (!ptr) 339 return PKCS11_CKR_DEVICE_MEMORY; 340 341 res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz); 342 if (res) { 343 TEE_Free(ptr); 344 } else { 345 *data = ptr; 346 *size = sz; 347 } 348 349 return tee2pkcs_error(res); 350 } 351 352 enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, 353 uint32_t pkcs11_id, 354 TEE_ObjectHandle tee_obj, 355 uint32_t tee_id) 356 { 357 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 358 void *a_ptr = NULL; 359 size_t a_size = 0; 360 361 rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size); 362 if (rc) 363 goto out; 364 365 rc = add_attribute(head, pkcs11_id, a_ptr, a_size); 366 367 TEE_Free(a_ptr); 368 369 out: 370 if (rc) 371 EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s", 372 tee_id, pkcs11_id, id2str_attr(pkcs11_id)); 373 return rc; 374 } 375 376 enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, 377 uint32_t ptypes, TEE_Param *params) 378 { 379 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 380 TEE_PARAM_TYPE_NONE, 381 TEE_PARAM_TYPE_MEMREF_OUTPUT, 382 TEE_PARAM_TYPE_NONE); 383 TEE_Param *ctrl = params; 384 TEE_Param *out = params + 2; 385 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 386 struct serialargs ctrlargs = { }; 387 struct pkcs11_session *session = NULL; 388 struct pkcs11_attribute_head *proc_params = NULL; 389 struct obj_attrs *pub_head = NULL; 390 struct obj_attrs *priv_head = NULL; 391 struct pkcs11_object_head *pub_template = NULL; 392 struct pkcs11_object_head *priv_template = NULL; 393 struct pkcs11_object *object = NULL; 394 size_t pub_template_size = 0; 395 size_t priv_template_size = 0; 396 uint32_t pubkey_handle = 0; 397 uint32_t privkey_handle = 0; 398 uint32_t *hdl_ptr = NULL; 399 size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle); 400 401 if (!client || ptypes != exp_pt || out->memref.size != out_ref_size) 402 return PKCS11_CKR_ARGUMENTS_BAD; 403 404 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 405 406 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 407 if (rc) 408 return rc; 409 410 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 411 if (rc) 412 goto out; 413 414 rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template); 415 if (rc) 416 goto out; 417 418 rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template); 419 if (rc) 420 goto out; 421 422 if (serialargs_remaining_bytes(&ctrlargs)) { 423 rc = PKCS11_CKR_ARGUMENTS_BAD; 424 goto out; 425 } 426 427 rc = get_ready_session(session); 428 if (rc) 429 goto out; 430 431 rc = check_mechanism_against_processing(session, proc_params->id, 432 PKCS11_FUNCTION_GENERATE_PAIR, 433 PKCS11_FUNC_STEP_INIT); 434 if (rc) 435 goto out; 436 437 pub_template_size = sizeof(*pub_template) + pub_template->attrs_size; 438 439 rc = create_attributes_from_template(&pub_head, pub_template, 440 pub_template_size, NULL, 441 PKCS11_FUNCTION_GENERATE_PAIR, 442 proc_params->id, 443 PKCS11_CKO_PUBLIC_KEY); 444 if (rc) 445 goto out; 446 447 TEE_Free(pub_template); 448 pub_template = NULL; 449 450 priv_template_size = sizeof(*priv_template) + 451 priv_template->attrs_size; 452 453 rc = create_attributes_from_template(&priv_head, priv_template, 454 priv_template_size, NULL, 455 PKCS11_FUNCTION_GENERATE_PAIR, 456 proc_params->id, 457 PKCS11_CKO_PRIVATE_KEY); 458 if (rc) 459 goto out; 460 461 TEE_Free(priv_template); 462 priv_template = NULL; 463 464 /* Generate CKA_ID for keys if not specified by the templates */ 465 rc = add_missing_attribute_id(&pub_head, &priv_head); 466 if (rc) 467 goto out; 468 469 /* Check created object against processing and token state */ 470 rc = check_created_attrs(pub_head, priv_head); 471 if (rc) 472 goto out; 473 474 rc = check_created_attrs_against_processing(proc_params->id, pub_head); 475 if (rc) 476 goto out; 477 478 rc = check_created_attrs_against_processing(proc_params->id, 479 priv_head); 480 if (rc) 481 goto out; 482 483 rc = check_created_attrs_against_token(session, pub_head); 484 if (rc) 485 goto out; 486 487 rc = check_access_attrs_against_token(session, pub_head); 488 if (rc) 489 goto out; 490 491 rc = check_created_attrs_against_token(session, priv_head); 492 if (rc) 493 goto out; 494 495 rc = check_access_attrs_against_token(session, priv_head); 496 if (rc) 497 goto out; 498 499 /* Generate key pair */ 500 switch (proc_params->id) { 501 case PKCS11_CKM_EC_KEY_PAIR_GEN: 502 rc = generate_ec_keys(proc_params, &pub_head, &priv_head); 503 break; 504 default: 505 rc = PKCS11_CKR_MECHANISM_INVALID; 506 break; 507 } 508 if (rc) 509 goto out; 510 511 TEE_Free(proc_params); 512 proc_params = NULL; 513 514 /* 515 * Object is ready, register it and return a handle. 516 */ 517 rc = create_object(session, pub_head, &pubkey_handle); 518 if (rc) 519 goto out; 520 521 /* 522 * Now obj_handle (through the related struct pkcs11_object instance) 523 * owns the serialized buffer that holds the object attributes. 524 * We reset local pub_head to NULL to mark that ownership has been 525 * transferred. 526 */ 527 pub_head = NULL; 528 529 rc = create_object(session, priv_head, &privkey_handle); 530 if (rc) 531 goto out; 532 533 /* Ownership has been transferred so mark it with NULL */ 534 priv_head = NULL; 535 536 hdl_ptr = (uint32_t *)out->memref.buffer; 537 538 TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle)); 539 TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle)); 540 541 pubkey_handle = 0; 542 privkey_handle = 0; 543 544 DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32, 545 session->handle, privkey_handle, pubkey_handle); 546 547 out: 548 if (pubkey_handle) { 549 object = pkcs11_handle2object(pubkey_handle, session); 550 if (!object) 551 TEE_Panic(0); 552 destroy_object(session, object, false); 553 } 554 TEE_Free(priv_head); 555 TEE_Free(pub_head); 556 TEE_Free(priv_template); 557 TEE_Free(pub_template); 558 TEE_Free(proc_params); 559 560 return rc; 561 } 562 563 /* 564 * entry_processing_init - Generic entry for initializing a processing 565 * 566 * @client = client reference 567 * @ptype = Invocation parameter types 568 * @params = Invocation parameters reference 569 * @function - encrypt, decrypt, sign, verify, digest, ... 570 */ 571 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 572 uint32_t ptypes, TEE_Param *params, 573 enum processing_func function) 574 { 575 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 576 TEE_PARAM_TYPE_NONE, 577 TEE_PARAM_TYPE_NONE, 578 TEE_PARAM_TYPE_NONE); 579 TEE_Param *ctrl = params; 580 enum pkcs11_rc rc = PKCS11_CKR_OK; 581 struct serialargs ctrlargs = { }; 582 struct pkcs11_session *session = NULL; 583 struct pkcs11_attribute_head *proc_params = NULL; 584 uint32_t key_handle = 0; 585 struct pkcs11_object *obj = NULL; 586 587 if (!client || ptypes != exp_pt) 588 return PKCS11_CKR_ARGUMENTS_BAD; 589 590 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 591 592 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 593 if (rc) 594 return rc; 595 596 if (function != PKCS11_FUNCTION_DIGEST) { 597 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 598 if (rc) 599 return rc; 600 } 601 602 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 603 if (rc) 604 return rc; 605 606 if (serialargs_remaining_bytes(&ctrlargs)) { 607 rc = PKCS11_CKR_ARGUMENTS_BAD; 608 goto out; 609 } 610 611 rc = get_ready_session(session); 612 if (rc) 613 goto out; 614 615 if (function != PKCS11_FUNCTION_DIGEST) { 616 obj = pkcs11_handle2object(key_handle, session); 617 if (!obj) { 618 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 619 goto out; 620 } 621 } 622 623 rc = set_processing_state(session, function, obj, NULL); 624 if (rc) 625 goto out; 626 627 rc = check_mechanism_against_processing(session, proc_params->id, 628 function, 629 PKCS11_FUNC_STEP_INIT); 630 if (rc) 631 goto out; 632 633 if (obj) { 634 rc = check_parent_attrs_against_processing(proc_params->id, 635 function, 636 obj->attributes); 637 if (rc) 638 goto out; 639 640 rc = check_access_attrs_against_token(session, 641 obj->attributes); 642 if (rc) 643 goto out; 644 } 645 646 if (processing_is_tee_symm(proc_params->id)) 647 rc = init_symm_operation(session, function, proc_params, obj); 648 else if (processing_is_tee_asymm(proc_params->id)) 649 rc = init_asymm_operation(session, function, proc_params, obj); 650 else if (processing_is_tee_digest(proc_params->id)) 651 rc = init_digest_operation(session, proc_params); 652 else 653 rc = PKCS11_CKR_MECHANISM_INVALID; 654 655 if (rc == PKCS11_CKR_OK) { 656 session->processing->mecha_type = proc_params->id; 657 DMSG("PKCS11 session %"PRIu32": init processing %s %s", 658 session->handle, id2str_proc(proc_params->id), 659 id2str_function(function)); 660 } 661 662 out: 663 if (rc && session) 664 release_active_processing(session); 665 666 TEE_Free(proc_params); 667 668 return rc; 669 } 670 671 /* 672 * entry_processing_step - Generic entry on active processing 673 * 674 * @client = client reference 675 * @ptype = Invocation parameter types 676 * @params = Invocation parameters reference 677 * @function - encrypt, decrypt, sign, verify, digest, ... 678 * @step - update, oneshot, final 679 */ 680 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 681 uint32_t ptypes, TEE_Param *params, 682 enum processing_func function, 683 enum processing_step step) 684 { 685 TEE_Param *ctrl = params; 686 enum pkcs11_rc rc = PKCS11_CKR_OK; 687 struct serialargs ctrlargs = { }; 688 struct pkcs11_session *session = NULL; 689 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 690 uint32_t key_handle = 0; 691 struct pkcs11_object *obj = NULL; 692 693 if (!client || 694 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 695 return PKCS11_CKR_ARGUMENTS_BAD; 696 697 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 698 699 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 700 if (rc) 701 return rc; 702 703 if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 704 assert(function == PKCS11_FUNCTION_DIGEST); 705 706 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 707 if (rc) 708 return rc; 709 } 710 711 if (serialargs_remaining_bytes(&ctrlargs)) 712 return PKCS11_CKR_ARGUMENTS_BAD; 713 714 rc = get_active_session(session, function); 715 if (rc) 716 return rc; 717 718 if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 719 assert(function == PKCS11_FUNCTION_DIGEST); 720 721 obj = pkcs11_handle2object(key_handle, session); 722 if (!obj) { 723 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 724 goto out; 725 } 726 727 rc = check_access_attrs_against_token(session, 728 obj->attributes); 729 if (rc) { 730 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 731 goto out; 732 } 733 } 734 735 mecha_type = session->processing->mecha_type; 736 rc = check_mechanism_against_processing(session, mecha_type, 737 function, step); 738 if (rc) 739 goto out; 740 741 if (processing_is_tee_symm(mecha_type)) 742 rc = step_symm_operation(session, function, step, 743 ptypes, params); 744 else if (processing_is_tee_asymm(mecha_type)) 745 rc = step_asymm_operation(session, function, step, 746 ptypes, params); 747 else if (processing_is_tee_digest(mecha_type)) 748 rc = step_digest_operation(session, step, obj, ptypes, params); 749 else 750 rc = PKCS11_CKR_MECHANISM_INVALID; 751 752 if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || 753 step == PKCS11_FUNC_STEP_UPDATE_KEY)) { 754 session->processing->updated = true; 755 DMSG("PKCS11 session%"PRIu32": processing %s %s", 756 session->handle, id2str_proc(mecha_type), 757 id2str_function(function)); 758 } 759 760 out: 761 switch (step) { 762 case PKCS11_FUNC_STEP_UPDATE: 763 case PKCS11_FUNC_STEP_UPDATE_KEY: 764 if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 765 release_active_processing(session); 766 break; 767 default: 768 /* ONESHOT and FINAL terminates processing on success */ 769 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 770 release_active_processing(session); 771 break; 772 } 773 774 return rc; 775 } 776 777 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 778 uint32_t ptypes, TEE_Param *params, 779 enum processing_func function) 780 { 781 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 782 TEE_PARAM_TYPE_NONE, 783 TEE_PARAM_TYPE_MEMREF_OUTPUT, 784 TEE_PARAM_TYPE_NONE); 785 TEE_Param *ctrl = params; 786 TEE_Param *out = params + 2; 787 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 788 struct serialargs ctrlargs = { }; 789 struct pkcs11_session *session = NULL; 790 struct pkcs11_attribute_head *proc_params = NULL; 791 struct pkcs11_object_head *template = NULL; 792 uint32_t parent_handle = 0; 793 uint32_t obj_handle = 0; 794 struct pkcs11_object *parent = NULL; 795 struct obj_attrs *head = NULL; 796 size_t template_size = 0; 797 void *out_buf = NULL; 798 uint32_t out_size = 0; 799 800 if (!client || ptypes != exp_pt || 801 out->memref.size != sizeof(obj_handle)) 802 return PKCS11_CKR_ARGUMENTS_BAD; 803 804 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 805 806 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 807 if (rc) 808 return rc; 809 810 rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 811 if (rc) 812 return rc; 813 814 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 815 if (rc) 816 goto out_free; 817 818 rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 819 if (rc) 820 goto out_free; 821 822 if (serialargs_remaining_bytes(&ctrlargs)) { 823 rc = PKCS11_CKR_ARGUMENTS_BAD; 824 goto out_free; 825 } 826 827 /* Return error if processing already active */ 828 rc = get_ready_session(session); 829 if (rc) 830 goto out_free; 831 832 /* Check parent handle */ 833 parent = pkcs11_handle2object(parent_handle, session); 834 if (!parent) { 835 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 836 goto out_free; 837 } 838 839 /* Check if mechanism can be used for derivation function */ 840 rc = check_mechanism_against_processing(session, proc_params->id, 841 function, 842 PKCS11_FUNC_STEP_INIT); 843 if (rc) 844 goto out_free; 845 846 /* Set the processing state to active */ 847 rc = set_processing_state(session, function, parent, NULL); 848 if (rc) 849 goto out_free; 850 851 /* 852 * Check if base/parent key has CKA_DERIVE set and its key type is 853 * compatible with the mechanism passed 854 */ 855 rc = check_parent_attrs_against_processing(proc_params->id, function, 856 parent->attributes); 857 if (rc) { 858 /* 859 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 860 * specified with C_Derive/Unwrap() in the specification. So 861 * return the next most appropriate error. 862 */ 863 if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 864 rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 865 goto out; 866 } 867 868 /* Check access of base/parent key */ 869 rc = check_access_attrs_against_token(session, parent->attributes); 870 if (rc) 871 goto out; 872 873 template_size = sizeof(*template) + template->attrs_size; 874 /* 875 * Prepare a clean initial state for the requested object attributes 876 * using base/parent key attributes. Free temporary template once done. 877 */ 878 rc = create_attributes_from_template(&head, template, template_size, 879 parent->attributes, 880 function, 881 proc_params->id, 882 PKCS11_CKO_UNDEFINED_ID); 883 if (rc) 884 goto out; 885 886 TEE_Free(template); 887 template = NULL; 888 889 /* check_created_attrs() is called later once key size is known */ 890 891 rc = check_created_attrs_against_processing(proc_params->id, head); 892 if (rc) 893 goto out; 894 895 rc = check_created_attrs_against_token(session, head); 896 if (rc) 897 goto out; 898 899 if (processing_is_tee_symm(proc_params->id)) { 900 /* 901 * These derivation mechanism require encryption to be 902 * performed on the data passed in proc_params by parent 903 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 904 * to init_symm_operation() 905 */ 906 rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 907 proc_params, parent); 908 if (rc) 909 goto out; 910 911 session->processing->mecha_type = proc_params->id; 912 913 rc = derive_key_by_symm_enc(session, &out_buf, &out_size); 914 if (rc) 915 goto out; 916 } else { 917 rc = PKCS11_CKR_MECHANISM_INVALID; 918 goto out; 919 } 920 921 rc = set_key_data(&head, out_buf, out_size); 922 if (rc) 923 goto out; 924 925 TEE_Free(out_buf); 926 out_buf = NULL; 927 928 TEE_Free(proc_params); 929 proc_params = NULL; 930 931 /* 932 * Object is ready, register it and return a handle. 933 */ 934 rc = create_object(session, head, &obj_handle); 935 if (rc) 936 goto out; 937 938 /* 939 * Now obj_handle (through the related struct pkcs11_object instance) 940 * owns the serialized buffer that holds the object attributes. 941 * We reset head to NULL as it is no more the buffer owner and would 942 * be freed at function out. 943 */ 944 head = NULL; 945 946 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 947 out->memref.size = sizeof(obj_handle); 948 949 DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 950 session->handle, obj_handle); 951 952 out: 953 release_active_processing(session); 954 out_free: 955 TEE_Free(proc_params); 956 TEE_Free(template); 957 TEE_Free(head); 958 TEE_Free(out_buf); 959 960 return rc; 961 } 962 963 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 964 uint32_t ptypes, 965 TEE_Param *params) 966 { 967 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 968 TEE_PARAM_TYPE_NONE, 969 TEE_PARAM_TYPE_NONE, 970 TEE_PARAM_TYPE_NONE); 971 TEE_Param *ctrl = params; 972 enum pkcs11_rc rc = PKCS11_CKR_OK; 973 struct serialargs ctrlargs = { }; 974 struct pkcs11_session *session = NULL; 975 enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 976 uint32_t cmd = 0; 977 978 if (!client || ptypes != exp_pt) 979 return PKCS11_CKR_ARGUMENTS_BAD; 980 981 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 982 983 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 984 if (rc) 985 return rc; 986 987 rc = serialargs_get_u32(&ctrlargs, &cmd); 988 989 if (serialargs_remaining_bytes(&ctrlargs)) 990 return PKCS11_CKR_ARGUMENTS_BAD; 991 992 function = func_for_cmd(cmd); 993 if (function == PKCS11_FUNCTION_UNKNOWN) 994 return PKCS11_CKR_ARGUMENTS_BAD; 995 996 rc = get_active_session(session, function); 997 if (rc) 998 return rc; 999 1000 release_active_processing(session); 1001 1002 DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 1003 1004 return PKCS11_CKR_OK; 1005 } 1006