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