pkcs11_tls_op_handler.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/io/pkcs11.h>
  6. #include "pkcs11_private.h"
  7. #include <aws/common/mutex.h>
  8. #include <aws/common/string.h>
  9. #include <aws/io/logging.h>
  10. struct aws_pkcs11_tls_op_handler {
  11. /* The custom key operation handler needed for the callbacks */
  12. struct aws_custom_key_op_handler base;
  13. struct aws_allocator *alloc;
  14. struct aws_pkcs11_lib *lib;
  15. /* Use a single PKCS#11 session for all TLS connections on an aws_tls_ctx.
  16. * We do this because PKCS#11 tokens may only support a
  17. * limited number of sessions (PKCS11-UG-v2.40 section 2.6.7).
  18. * If this one shared session turns out to be a severe bottleneck,
  19. * we could look into other setups (ex: put session on its own thread,
  20. * 1 session per event-loop, 1 session per connection, etc).
  21. *
  22. * The lock must be held while performing session operations.
  23. * Otherwise, it would not be safe for multiple threads to share a
  24. * session (PKCS11-UG-v2.40 section 2.6.7). The lock isn't needed for
  25. * setup and teardown though, since we ensure nothing parallel is going
  26. * on at these times */
  27. struct aws_mutex session_lock;
  28. CK_SESSION_HANDLE session_handle;
  29. CK_OBJECT_HANDLE private_key_handle;
  30. CK_KEY_TYPE private_key_type;
  31. };
  32. static void s_aws_custom_key_op_handler_destroy(struct aws_custom_key_op_handler *key_op_handler) {
  33. struct aws_pkcs11_tls_op_handler *handler = (struct aws_pkcs11_tls_op_handler *)key_op_handler->impl;
  34. if (handler->session_handle != 0) {
  35. aws_pkcs11_lib_close_session(handler->lib, handler->session_handle);
  36. }
  37. aws_mutex_clean_up(&handler->session_lock);
  38. aws_pkcs11_lib_release(handler->lib);
  39. aws_mem_release(handler->alloc, handler);
  40. }
  41. /**
  42. * Performs the PKCS11 TLS private key operation. This is called automatically when performing a mutual TLS handshake.
  43. */
  44. void s_aws_pkcs11_tls_op_handler_do_operation(
  45. struct aws_custom_key_op_handler *handler,
  46. struct aws_tls_key_operation *operation) {
  47. struct aws_pkcs11_tls_op_handler *pkcs11_handler = (struct aws_pkcs11_tls_op_handler *)handler->impl;
  48. struct aws_byte_buf output_buf; /* initialized later */
  49. AWS_ZERO_STRUCT(output_buf);
  50. /*********** BEGIN CRITICAL SECTION ***********/
  51. aws_mutex_lock(&pkcs11_handler->session_lock);
  52. bool success_while_locked = false;
  53. switch (aws_tls_key_operation_get_type(operation)) {
  54. case AWS_TLS_KEY_OPERATION_DECRYPT:
  55. if (aws_pkcs11_lib_decrypt(
  56. pkcs11_handler->lib,
  57. pkcs11_handler->session_handle,
  58. pkcs11_handler->private_key_handle,
  59. pkcs11_handler->private_key_type,
  60. aws_tls_key_operation_get_input(operation),
  61. pkcs11_handler->alloc,
  62. &output_buf)) {
  63. goto unlock;
  64. }
  65. break;
  66. case AWS_TLS_KEY_OPERATION_SIGN:
  67. if (aws_pkcs11_lib_sign(
  68. pkcs11_handler->lib,
  69. pkcs11_handler->session_handle,
  70. pkcs11_handler->private_key_handle,
  71. pkcs11_handler->private_key_type,
  72. aws_tls_key_operation_get_input(operation),
  73. pkcs11_handler->alloc,
  74. aws_tls_key_operation_get_digest_algorithm(operation),
  75. aws_tls_key_operation_get_signature_algorithm(operation),
  76. &output_buf)) {
  77. goto unlock;
  78. }
  79. break;
  80. default:
  81. AWS_LOGF_ERROR(
  82. AWS_LS_IO_PKCS11,
  83. "PKCS11 Handler %p: Unknown TLS key operation with value of %u",
  84. (void *)handler,
  85. aws_tls_key_operation_get_type(operation));
  86. aws_raise_error(AWS_ERROR_INVALID_STATE);
  87. goto unlock;
  88. }
  89. success_while_locked = true;
  90. unlock:
  91. aws_mutex_unlock(&pkcs11_handler->session_lock);
  92. /*********** END CRITICAL SECTION ***********/
  93. if (success_while_locked) {
  94. aws_tls_key_operation_complete(operation, aws_byte_cursor_from_buf(&output_buf));
  95. } else {
  96. aws_tls_key_operation_complete_with_error(operation, aws_last_error());
  97. }
  98. aws_byte_buf_clean_up(&output_buf);
  99. }
  100. static struct aws_custom_key_op_handler_vtable s_aws_custom_key_op_handler_vtable = {
  101. .on_key_operation = s_aws_pkcs11_tls_op_handler_do_operation,
  102. };
  103. struct aws_custom_key_op_handler *aws_pkcs11_tls_op_handler_new(
  104. struct aws_allocator *allocator,
  105. struct aws_pkcs11_lib *pkcs11_lib,
  106. const struct aws_byte_cursor *user_pin,
  107. const struct aws_byte_cursor *match_token_label,
  108. const struct aws_byte_cursor *match_private_key_label,
  109. const uint64_t *match_slot_id) {
  110. bool success = false;
  111. struct aws_pkcs11_tls_op_handler *pkcs11_handler =
  112. aws_mem_calloc(allocator, 1, sizeof(struct aws_pkcs11_tls_op_handler));
  113. // Optional data
  114. struct aws_string *pkcs_user_pin = NULL;
  115. struct aws_string *pkcs_token_label = NULL;
  116. struct aws_string *pkcs_private_key_object_label = NULL;
  117. aws_ref_count_init(
  118. &pkcs11_handler->base.ref_count,
  119. &pkcs11_handler->base,
  120. (aws_simple_completion_callback *)s_aws_custom_key_op_handler_destroy);
  121. pkcs11_handler->base.impl = (void *)pkcs11_handler;
  122. pkcs11_handler->base.vtable = &s_aws_custom_key_op_handler_vtable;
  123. pkcs11_handler->alloc = allocator;
  124. /* pkcs11_lib is required */
  125. if (pkcs11_lib == NULL) {
  126. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  127. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "PKCS11 Handler %p new: PKCS11 library is null", (void *)pkcs11_handler);
  128. goto done;
  129. }
  130. pkcs11_handler->lib = aws_pkcs11_lib_acquire(pkcs11_lib); /* cannot fail */
  131. aws_mutex_init(&pkcs11_handler->session_lock);
  132. /* user_pin is optional */
  133. if (user_pin->ptr != NULL) {
  134. pkcs_user_pin = aws_string_new_from_cursor(allocator, user_pin);
  135. }
  136. /* token_label is optional */
  137. if (match_token_label->ptr != NULL) {
  138. pkcs_token_label = aws_string_new_from_cursor(allocator, match_token_label);
  139. }
  140. /* private_key_object_label is optional */
  141. if (match_private_key_label->ptr != NULL) {
  142. pkcs_private_key_object_label = aws_string_new_from_cursor(allocator, match_private_key_label);
  143. }
  144. CK_SLOT_ID slot_id;
  145. if (aws_pkcs11_lib_find_slot_with_token(pkcs11_handler->lib, match_slot_id, pkcs_token_label, &slot_id /*out*/)) {
  146. goto done;
  147. }
  148. if (aws_pkcs11_lib_open_session(pkcs11_handler->lib, slot_id, &pkcs11_handler->session_handle)) {
  149. goto done;
  150. }
  151. if (pkcs_user_pin != NULL) {
  152. if (aws_pkcs11_lib_login_user(pkcs11_handler->lib, pkcs11_handler->session_handle, pkcs_user_pin)) {
  153. goto done;
  154. }
  155. }
  156. if (aws_pkcs11_lib_find_private_key(
  157. pkcs11_handler->lib,
  158. pkcs11_handler->session_handle,
  159. pkcs_private_key_object_label,
  160. &pkcs11_handler->private_key_handle /*out*/,
  161. &pkcs11_handler->private_key_type /*out*/)) {
  162. goto done;
  163. }
  164. success = true;
  165. done:
  166. /* CLEANUP */
  167. if (pkcs_user_pin != NULL) {
  168. aws_string_destroy_secure(pkcs_user_pin);
  169. }
  170. if (pkcs_token_label != NULL) {
  171. aws_string_destroy(pkcs_token_label);
  172. }
  173. if (pkcs_private_key_object_label != NULL) {
  174. aws_string_destroy(pkcs_private_key_object_label);
  175. }
  176. if (success) {
  177. return &pkcs11_handler->base;
  178. } else {
  179. aws_custom_key_op_handler_release(&pkcs11_handler->base);
  180. return NULL;
  181. }
  182. }