pkcs11_lib.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  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/ref_count.h>
  9. #include <aws/common/string.h>
  10. #include <aws/io/logging.h>
  11. #include <aws/io/shared_library.h>
  12. #include <inttypes.h>
  13. /* NOTE 1: even though we currently include the v2.40 headers, they're compatible with any v2.x library.
  14. * NOTE 2: v3.x is backwards compatible with 2.x, and even claims to be 2.40 if you check its version the 2.x way */
  15. #define AWS_SUPPORTED_CRYPTOKI_VERSION_MAJOR 2
  16. #define AWS_MIN_SUPPORTED_CRYPTOKI_VERSION_MINOR 20
  17. /* clang-format off */
  18. /*
  19. * DER encoded DigestInfo value to be prefixed to the hash, used for RSA signing
  20. * See https://tools.ietf.org/html/rfc3447#page-43
  21. * (Notes to help understand what's going on here with DER encoding)
  22. * 0x30 nn - Sequence of tags, nn bytes, including hash, nn = mm+jj+4 (PKCS11 DigestInfo)
  23. * 0x30 mm - Subsequence of tags, mm bytes (ii+4) (PKCS11
  24. * 0x06 ii - OID encoding, ii bytes, see X.680 - this identifies the hash algorithm
  25. * 0x05 00 - NULL
  26. * 0x04 jj - OCTET, nn = mm + jj + 4
  27. * Digest (nn - mm - 4 bytes)
  28. */
  29. static const uint8_t SHA1_PREFIX_TO_RSA_SIG[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
  30. static const uint8_t SHA256_PREFIX_TO_RSA_SIG[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
  31. static const uint8_t SHA384_PREFIX_TO_RSA_SIG[] = { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 };
  32. static const uint8_t SHA512_PREFIX_TO_RSA_SIG[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
  33. static const uint8_t SHA224_PREFIX_TO_RSA_SIG[] = { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c };
  34. /* clang-format on */
  35. /* Return c-string for PKCS#11 CKR_* contants. */
  36. const char *aws_pkcs11_ckr_str(CK_RV rv) {
  37. /* clang-format off */
  38. switch (rv) {
  39. case (CKR_OK): return "CKR_OK";
  40. case (CKR_CANCEL): return "CKR_CANCEL";
  41. case (CKR_HOST_MEMORY): return "CKR_HOST_MEMORY";
  42. case (CKR_SLOT_ID_INVALID): return "CKR_SLOT_ID_INVALID";
  43. case (CKR_GENERAL_ERROR): return "CKR_GENERAL_ERROR";
  44. case (CKR_FUNCTION_FAILED): return "CKR_FUNCTION_FAILED";
  45. case (CKR_ARGUMENTS_BAD): return "CKR_ARGUMENTS_BAD";
  46. case (CKR_NO_EVENT): return "CKR_NO_EVENT";
  47. case (CKR_NEED_TO_CREATE_THREADS): return "CKR_NEED_TO_CREATE_THREADS";
  48. case (CKR_CANT_LOCK): return "CKR_CANT_LOCK";
  49. case (CKR_ATTRIBUTE_READ_ONLY): return "CKR_ATTRIBUTE_READ_ONLY";
  50. case (CKR_ATTRIBUTE_SENSITIVE): return "CKR_ATTRIBUTE_SENSITIVE";
  51. case (CKR_ATTRIBUTE_TYPE_INVALID): return "CKR_ATTRIBUTE_TYPE_INVALID";
  52. case (CKR_ATTRIBUTE_VALUE_INVALID): return "CKR_ATTRIBUTE_VALUE_INVALID";
  53. case (CKR_ACTION_PROHIBITED): return "CKR_ACTION_PROHIBITED";
  54. case (CKR_DATA_INVALID): return "CKR_DATA_INVALID";
  55. case (CKR_DATA_LEN_RANGE): return "CKR_DATA_LEN_RANGE";
  56. case (CKR_DEVICE_ERROR): return "CKR_DEVICE_ERROR";
  57. case (CKR_DEVICE_MEMORY): return "CKR_DEVICE_MEMORY";
  58. case (CKR_DEVICE_REMOVED): return "CKR_DEVICE_REMOVED";
  59. case (CKR_ENCRYPTED_DATA_INVALID): return "CKR_ENCRYPTED_DATA_INVALID";
  60. case (CKR_ENCRYPTED_DATA_LEN_RANGE): return "CKR_ENCRYPTED_DATA_LEN_RANGE";
  61. case (CKR_FUNCTION_CANCELED): return "CKR_FUNCTION_CANCELED";
  62. case (CKR_FUNCTION_NOT_PARALLEL): return "CKR_FUNCTION_NOT_PARALLEL";
  63. case (CKR_FUNCTION_NOT_SUPPORTED): return "CKR_FUNCTION_NOT_SUPPORTED";
  64. case (CKR_KEY_HANDLE_INVALID): return "CKR_KEY_HANDLE_INVALID";
  65. case (CKR_KEY_SIZE_RANGE): return "CKR_KEY_SIZE_RANGE";
  66. case (CKR_KEY_TYPE_INCONSISTENT): return "CKR_KEY_TYPE_INCONSISTENT";
  67. case (CKR_KEY_NOT_NEEDED): return "CKR_KEY_NOT_NEEDED";
  68. case (CKR_KEY_CHANGED): return "CKR_KEY_CHANGED";
  69. case (CKR_KEY_NEEDED): return "CKR_KEY_NEEDED";
  70. case (CKR_KEY_INDIGESTIBLE): return "CKR_KEY_INDIGESTIBLE";
  71. case (CKR_KEY_FUNCTION_NOT_PERMITTED): return "CKR_KEY_FUNCTION_NOT_PERMITTED";
  72. case (CKR_KEY_NOT_WRAPPABLE): return "CKR_KEY_NOT_WRAPPABLE";
  73. case (CKR_KEY_UNEXTRACTABLE): return "CKR_KEY_UNEXTRACTABLE";
  74. case (CKR_MECHANISM_INVALID): return "CKR_MECHANISM_INVALID";
  75. case (CKR_MECHANISM_PARAM_INVALID): return "CKR_MECHANISM_PARAM_INVALID";
  76. case (CKR_OBJECT_HANDLE_INVALID): return "CKR_OBJECT_HANDLE_INVALID";
  77. case (CKR_OPERATION_ACTIVE): return "CKR_OPERATION_ACTIVE";
  78. case (CKR_OPERATION_NOT_INITIALIZED): return "CKR_OPERATION_NOT_INITIALIZED";
  79. case (CKR_PIN_INCORRECT): return "CKR_PIN_INCORRECT";
  80. case (CKR_PIN_INVALID): return "CKR_PIN_INVALID";
  81. case (CKR_PIN_LEN_RANGE): return "CKR_PIN_LEN_RANGE";
  82. case (CKR_PIN_EXPIRED): return "CKR_PIN_EXPIRED";
  83. case (CKR_PIN_LOCKED): return "CKR_PIN_LOCKED";
  84. case (CKR_SESSION_CLOSED): return "CKR_SESSION_CLOSED";
  85. case (CKR_SESSION_COUNT): return "CKR_SESSION_COUNT";
  86. case (CKR_SESSION_HANDLE_INVALID): return "CKR_SESSION_HANDLE_INVALID";
  87. case (CKR_SESSION_PARALLEL_NOT_SUPPORTED): return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
  88. case (CKR_SESSION_READ_ONLY): return "CKR_SESSION_READ_ONLY";
  89. case (CKR_SESSION_EXISTS): return "CKR_SESSION_EXISTS";
  90. case (CKR_SESSION_READ_ONLY_EXISTS): return "CKR_SESSION_READ_ONLY_EXISTS";
  91. case (CKR_SESSION_READ_WRITE_SO_EXISTS): return "CKR_SESSION_READ_WRITE_SO_EXISTS";
  92. case (CKR_SIGNATURE_INVALID): return "CKR_SIGNATURE_INVALID";
  93. case (CKR_SIGNATURE_LEN_RANGE): return "CKR_SIGNATURE_LEN_RANGE";
  94. case (CKR_TEMPLATE_INCOMPLETE): return "CKR_TEMPLATE_INCOMPLETE";
  95. case (CKR_TEMPLATE_INCONSISTENT): return "CKR_TEMPLATE_INCONSISTENT";
  96. case (CKR_TOKEN_NOT_PRESENT): return "CKR_TOKEN_NOT_PRESENT";
  97. case (CKR_TOKEN_NOT_RECOGNIZED): return "CKR_TOKEN_NOT_RECOGNIZED";
  98. case (CKR_TOKEN_WRITE_PROTECTED): return "CKR_TOKEN_WRITE_PROTECTED";
  99. case (CKR_UNWRAPPING_KEY_HANDLE_INVALID): return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
  100. case (CKR_UNWRAPPING_KEY_SIZE_RANGE): return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
  101. case (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT): return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
  102. case (CKR_USER_ALREADY_LOGGED_IN): return "CKR_USER_ALREADY_LOGGED_IN";
  103. case (CKR_USER_NOT_LOGGED_IN): return "CKR_USER_NOT_LOGGED_IN";
  104. case (CKR_USER_PIN_NOT_INITIALIZED): return "CKR_USER_PIN_NOT_INITIALIZED";
  105. case (CKR_USER_TYPE_INVALID): return "CKR_USER_TYPE_INVALID";
  106. case (CKR_USER_ANOTHER_ALREADY_LOGGED_IN): return "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
  107. case (CKR_USER_TOO_MANY_TYPES): return "CKR_USER_TOO_MANY_TYPES";
  108. case (CKR_WRAPPED_KEY_INVALID): return "CKR_WRAPPED_KEY_INVALID";
  109. case (CKR_WRAPPED_KEY_LEN_RANGE): return "CKR_WRAPPED_KEY_LEN_RANGE";
  110. case (CKR_WRAPPING_KEY_HANDLE_INVALID): return "CKR_WRAPPING_KEY_HANDLE_INVALID";
  111. case (CKR_WRAPPING_KEY_SIZE_RANGE): return "CKR_WRAPPING_KEY_SIZE_RANGE";
  112. case (CKR_WRAPPING_KEY_TYPE_INCONSISTENT): return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
  113. case (CKR_RANDOM_SEED_NOT_SUPPORTED): return "CKR_RANDOM_SEED_NOT_SUPPORTED";
  114. case (CKR_RANDOM_NO_RNG): return "CKR_RANDOM_NO_RNG";
  115. case (CKR_DOMAIN_PARAMS_INVALID): return "CKR_DOMAIN_PARAMS_INVALID";
  116. case (CKR_CURVE_NOT_SUPPORTED): return "CKR_CURVE_NOT_SUPPORTED";
  117. case (CKR_BUFFER_TOO_SMALL): return "CKR_BUFFER_TOO_SMALL";
  118. case (CKR_SAVED_STATE_INVALID): return "CKR_SAVED_STATE_INVALID";
  119. case (CKR_INFORMATION_SENSITIVE): return "CKR_INFORMATION_SENSITIVE";
  120. case (CKR_STATE_UNSAVEABLE): return "CKR_STATE_UNSAVEABLE";
  121. case (CKR_CRYPTOKI_NOT_INITIALIZED): return "CKR_CRYPTOKI_NOT_INITIALIZED";
  122. case (CKR_CRYPTOKI_ALREADY_INITIALIZED): return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
  123. case (CKR_MUTEX_BAD): return "CKR_MUTEX_BAD";
  124. case (CKR_MUTEX_NOT_LOCKED): return "CKR_MUTEX_NOT_LOCKED";
  125. case (CKR_NEW_PIN_MODE): return "CKR_NEW_PIN_MODE";
  126. case (CKR_NEXT_OTP): return "CKR_NEXT_OTP";
  127. case (CKR_EXCEEDED_MAX_ITERATIONS): return "CKR_EXCEEDED_MAX_ITERATIONS";
  128. case (CKR_FIPS_SELF_TEST_FAILED): return "CKR_FIPS_SELF_TEST_FAILED";
  129. case (CKR_LIBRARY_LOAD_FAILED): return "CKR_LIBRARY_LOAD_FAILED";
  130. case (CKR_PIN_TOO_WEAK): return "CKR_PIN_TOO_WEAK";
  131. case (CKR_PUBLIC_KEY_INVALID): return "CKR_PUBLIC_KEY_INVALID";
  132. case (CKR_FUNCTION_REJECTED): return "CKR_FUNCTION_REJECTED";
  133. default: return "<UNKNOWN RETURN VALUE>";
  134. }
  135. /* clang-format on */
  136. }
  137. /* Translate from a CK_RV to an AWS error code */
  138. static int s_ck_to_aws_error(CK_RV rv) {
  139. AWS_ASSERT(rv != CKR_OK);
  140. /* clang-format off */
  141. switch (rv) {
  142. case (CKR_CANCEL): return AWS_ERROR_PKCS11_CKR_CANCEL;
  143. case (CKR_HOST_MEMORY): return AWS_ERROR_PKCS11_CKR_HOST_MEMORY;
  144. case (CKR_SLOT_ID_INVALID): return AWS_ERROR_PKCS11_CKR_SLOT_ID_INVALID;
  145. case (CKR_GENERAL_ERROR): return AWS_ERROR_PKCS11_CKR_GENERAL_ERROR;
  146. case (CKR_FUNCTION_FAILED): return AWS_ERROR_PKCS11_CKR_FUNCTION_FAILED;
  147. case (CKR_ARGUMENTS_BAD): return AWS_ERROR_PKCS11_CKR_ARGUMENTS_BAD;
  148. case (CKR_NO_EVENT): return AWS_ERROR_PKCS11_CKR_NO_EVENT;
  149. case (CKR_NEED_TO_CREATE_THREADS): return AWS_ERROR_PKCS11_CKR_NEED_TO_CREATE_THREADS;
  150. case (CKR_CANT_LOCK): return AWS_ERROR_PKCS11_CKR_CANT_LOCK;
  151. case (CKR_ATTRIBUTE_READ_ONLY): return AWS_ERROR_PKCS11_CKR_ATTRIBUTE_READ_ONLY;
  152. case (CKR_ATTRIBUTE_SENSITIVE): return AWS_ERROR_PKCS11_CKR_ATTRIBUTE_SENSITIVE;
  153. case (CKR_ATTRIBUTE_TYPE_INVALID): return AWS_ERROR_PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
  154. case (CKR_ATTRIBUTE_VALUE_INVALID): return AWS_ERROR_PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
  155. case (CKR_ACTION_PROHIBITED): return AWS_ERROR_PKCS11_CKR_ACTION_PROHIBITED;
  156. case (CKR_DATA_INVALID): return AWS_ERROR_PKCS11_CKR_DATA_INVALID;
  157. case (CKR_DATA_LEN_RANGE): return AWS_ERROR_PKCS11_CKR_DATA_LEN_RANGE;
  158. case (CKR_DEVICE_ERROR): return AWS_ERROR_PKCS11_CKR_DEVICE_ERROR;
  159. case (CKR_DEVICE_MEMORY): return AWS_ERROR_PKCS11_CKR_DEVICE_MEMORY;
  160. case (CKR_DEVICE_REMOVED): return AWS_ERROR_PKCS11_CKR_DEVICE_REMOVED;
  161. case (CKR_ENCRYPTED_DATA_INVALID): return AWS_ERROR_PKCS11_CKR_ENCRYPTED_DATA_INVALID;
  162. case (CKR_ENCRYPTED_DATA_LEN_RANGE): return AWS_ERROR_PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
  163. case (CKR_FUNCTION_CANCELED): return AWS_ERROR_PKCS11_CKR_FUNCTION_CANCELED;
  164. case (CKR_FUNCTION_NOT_PARALLEL): return AWS_ERROR_PKCS11_CKR_FUNCTION_NOT_PARALLEL;
  165. case (CKR_FUNCTION_NOT_SUPPORTED): return AWS_ERROR_PKCS11_CKR_FUNCTION_NOT_SUPPORTED;
  166. case (CKR_KEY_HANDLE_INVALID): return AWS_ERROR_PKCS11_CKR_KEY_HANDLE_INVALID;
  167. case (CKR_KEY_SIZE_RANGE): return AWS_ERROR_PKCS11_CKR_KEY_SIZE_RANGE;
  168. case (CKR_KEY_TYPE_INCONSISTENT): return AWS_ERROR_PKCS11_CKR_KEY_TYPE_INCONSISTENT;
  169. case (CKR_KEY_NOT_NEEDED): return AWS_ERROR_PKCS11_CKR_KEY_NOT_NEEDED;
  170. case (CKR_KEY_CHANGED): return AWS_ERROR_PKCS11_CKR_KEY_CHANGED;
  171. case (CKR_KEY_NEEDED): return AWS_ERROR_PKCS11_CKR_KEY_NEEDED;
  172. case (CKR_KEY_INDIGESTIBLE): return AWS_ERROR_PKCS11_CKR_KEY_INDIGESTIBLE;
  173. case (CKR_KEY_FUNCTION_NOT_PERMITTED): return AWS_ERROR_PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
  174. case (CKR_KEY_NOT_WRAPPABLE): return AWS_ERROR_PKCS11_CKR_KEY_NOT_WRAPPABLE;
  175. case (CKR_KEY_UNEXTRACTABLE): return AWS_ERROR_PKCS11_CKR_KEY_UNEXTRACTABLE;
  176. case (CKR_MECHANISM_INVALID): return AWS_ERROR_PKCS11_CKR_MECHANISM_INVALID;
  177. case (CKR_MECHANISM_PARAM_INVALID): return AWS_ERROR_PKCS11_CKR_MECHANISM_PARAM_INVALID;
  178. case (CKR_OBJECT_HANDLE_INVALID): return AWS_ERROR_PKCS11_CKR_OBJECT_HANDLE_INVALID;
  179. case (CKR_OPERATION_ACTIVE): return AWS_ERROR_PKCS11_CKR_OPERATION_ACTIVE;
  180. case (CKR_OPERATION_NOT_INITIALIZED): return AWS_ERROR_PKCS11_CKR_OPERATION_NOT_INITIALIZED;
  181. case (CKR_PIN_INCORRECT): return AWS_ERROR_PKCS11_CKR_PIN_INCORRECT;
  182. case (CKR_PIN_INVALID): return AWS_ERROR_PKCS11_CKR_PIN_INVALID;
  183. case (CKR_PIN_LEN_RANGE): return AWS_ERROR_PKCS11_CKR_PIN_LEN_RANGE;
  184. case (CKR_PIN_EXPIRED): return AWS_ERROR_PKCS11_CKR_PIN_EXPIRED;
  185. case (CKR_PIN_LOCKED): return AWS_ERROR_PKCS11_CKR_PIN_LOCKED;
  186. case (CKR_SESSION_CLOSED): return AWS_ERROR_PKCS11_CKR_SESSION_CLOSED;
  187. case (CKR_SESSION_COUNT): return AWS_ERROR_PKCS11_CKR_SESSION_COUNT;
  188. case (CKR_SESSION_HANDLE_INVALID): return AWS_ERROR_PKCS11_CKR_SESSION_HANDLE_INVALID;
  189. case (CKR_SESSION_PARALLEL_NOT_SUPPORTED): return AWS_ERROR_PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED;
  190. case (CKR_SESSION_READ_ONLY): return AWS_ERROR_PKCS11_CKR_SESSION_READ_ONLY;
  191. case (CKR_SESSION_EXISTS): return AWS_ERROR_PKCS11_CKR_SESSION_EXISTS;
  192. case (CKR_SESSION_READ_ONLY_EXISTS): return AWS_ERROR_PKCS11_CKR_SESSION_READ_ONLY_EXISTS;
  193. case (CKR_SESSION_READ_WRITE_SO_EXISTS): return AWS_ERROR_PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS;
  194. case (CKR_SIGNATURE_INVALID): return AWS_ERROR_PKCS11_CKR_SIGNATURE_INVALID;
  195. case (CKR_SIGNATURE_LEN_RANGE): return AWS_ERROR_PKCS11_CKR_SIGNATURE_LEN_RANGE;
  196. case (CKR_TEMPLATE_INCOMPLETE): return AWS_ERROR_PKCS11_CKR_TEMPLATE_INCOMPLETE;
  197. case (CKR_TEMPLATE_INCONSISTENT): return AWS_ERROR_PKCS11_CKR_TEMPLATE_INCONSISTENT;
  198. case (CKR_TOKEN_NOT_PRESENT): return AWS_ERROR_PKCS11_CKR_TOKEN_NOT_PRESENT;
  199. case (CKR_TOKEN_NOT_RECOGNIZED): return AWS_ERROR_PKCS11_CKR_TOKEN_NOT_RECOGNIZED;
  200. case (CKR_TOKEN_WRITE_PROTECTED): return AWS_ERROR_PKCS11_CKR_TOKEN_WRITE_PROTECTED;
  201. case (CKR_UNWRAPPING_KEY_HANDLE_INVALID): return AWS_ERROR_PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID;
  202. case (CKR_UNWRAPPING_KEY_SIZE_RANGE): return AWS_ERROR_PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE;
  203. case (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT): return AWS_ERROR_PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
  204. case (CKR_USER_ALREADY_LOGGED_IN): return AWS_ERROR_PKCS11_CKR_USER_ALREADY_LOGGED_IN;
  205. case (CKR_USER_NOT_LOGGED_IN): return AWS_ERROR_PKCS11_CKR_USER_NOT_LOGGED_IN;
  206. case (CKR_USER_PIN_NOT_INITIALIZED): return AWS_ERROR_PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
  207. case (CKR_USER_TYPE_INVALID): return AWS_ERROR_PKCS11_CKR_USER_TYPE_INVALID;
  208. case (CKR_USER_ANOTHER_ALREADY_LOGGED_IN): return AWS_ERROR_PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
  209. case (CKR_USER_TOO_MANY_TYPES): return AWS_ERROR_PKCS11_CKR_USER_TOO_MANY_TYPES;
  210. case (CKR_WRAPPED_KEY_INVALID): return AWS_ERROR_PKCS11_CKR_WRAPPED_KEY_INVALID;
  211. case (CKR_WRAPPED_KEY_LEN_RANGE): return AWS_ERROR_PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
  212. case (CKR_WRAPPING_KEY_HANDLE_INVALID): return AWS_ERROR_PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
  213. case (CKR_WRAPPING_KEY_SIZE_RANGE): return AWS_ERROR_PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE;
  214. case (CKR_WRAPPING_KEY_TYPE_INCONSISTENT): return AWS_ERROR_PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
  215. case (CKR_RANDOM_SEED_NOT_SUPPORTED): return AWS_ERROR_PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED;
  216. case (CKR_RANDOM_NO_RNG): return AWS_ERROR_PKCS11_CKR_RANDOM_NO_RNG;
  217. case (CKR_DOMAIN_PARAMS_INVALID): return AWS_ERROR_PKCS11_CKR_DOMAIN_PARAMS_INVALID;
  218. case (CKR_CURVE_NOT_SUPPORTED): return AWS_ERROR_PKCS11_CKR_CURVE_NOT_SUPPORTED;
  219. case (CKR_BUFFER_TOO_SMALL): return AWS_ERROR_PKCS11_CKR_BUFFER_TOO_SMALL;
  220. case (CKR_SAVED_STATE_INVALID): return AWS_ERROR_PKCS11_CKR_SAVED_STATE_INVALID;
  221. case (CKR_INFORMATION_SENSITIVE): return AWS_ERROR_PKCS11_CKR_INFORMATION_SENSITIVE;
  222. case (CKR_STATE_UNSAVEABLE): return AWS_ERROR_PKCS11_CKR_STATE_UNSAVEABLE;
  223. case (CKR_CRYPTOKI_NOT_INITIALIZED): return AWS_ERROR_PKCS11_CKR_CRYPTOKI_NOT_INITIALIZED;
  224. case (CKR_CRYPTOKI_ALREADY_INITIALIZED): return AWS_ERROR_PKCS11_CKR_CRYPTOKI_ALREADY_INITIALIZED;
  225. case (CKR_MUTEX_BAD): return AWS_ERROR_PKCS11_CKR_MUTEX_BAD;
  226. case (CKR_MUTEX_NOT_LOCKED): return AWS_ERROR_PKCS11_CKR_MUTEX_NOT_LOCKED;
  227. case (CKR_NEW_PIN_MODE): return AWS_ERROR_PKCS11_CKR_NEW_PIN_MODE;
  228. case (CKR_NEXT_OTP): return AWS_ERROR_PKCS11_CKR_NEXT_OTP;
  229. case (CKR_EXCEEDED_MAX_ITERATIONS): return AWS_ERROR_PKCS11_CKR_EXCEEDED_MAX_ITERATIONS;
  230. case (CKR_FIPS_SELF_TEST_FAILED): return AWS_ERROR_PKCS11_CKR_FIPS_SELF_TEST_FAILED;
  231. case (CKR_LIBRARY_LOAD_FAILED): return AWS_ERROR_PKCS11_CKR_LIBRARY_LOAD_FAILED;
  232. case (CKR_PIN_TOO_WEAK): return AWS_ERROR_PKCS11_CKR_PIN_TOO_WEAK;
  233. case (CKR_PUBLIC_KEY_INVALID): return AWS_ERROR_PKCS11_CKR_PUBLIC_KEY_INVALID;
  234. case (CKR_FUNCTION_REJECTED): return AWS_ERROR_PKCS11_CKR_FUNCTION_REJECTED;
  235. default: return AWS_ERROR_PKCS11_UNKNOWN_CRYPTOKI_RETURN_VALUE;
  236. }
  237. /* clang-format on */
  238. }
  239. /* Return c-string for PKCS#11 CKK_* contants. */
  240. static const char *s_ckk_str(CK_KEY_TYPE key_type) {
  241. /* clang-format off */
  242. switch(key_type) {
  243. case (CKK_RSA): return "CKK_RSA";
  244. case (CKK_DSA): return "CKK_DSA";
  245. case (CKK_DH): return "CKK_DH";
  246. case (CKK_EC): return "CKK_EC";
  247. case (CKK_X9_42_DH): return "CKK_X9_42_DH";
  248. case (CKK_KEA): return "CKK_KEA";
  249. case (CKK_GENERIC_SECRET): return "CKK_GENERIC_SECRET";
  250. case (CKK_RC2): return "CKK_RC2";
  251. case (CKK_RC4): return "CKK_RC4";
  252. case (CKK_DES): return "CKK_DES";
  253. case (CKK_DES2): return "CKK_DES2";
  254. case (CKK_DES3): return "CKK_DES3";
  255. case (CKK_CAST): return "CKK_CAST";
  256. case (CKK_CAST3): return "CKK_CAST3";
  257. case (CKK_CAST128): return "CKK_CAST128";
  258. case (CKK_RC5): return "CKK_RC5";
  259. case (CKK_IDEA): return "CKK_IDEA";
  260. case (CKK_SKIPJACK): return "CKK_SKIPJACK";
  261. case (CKK_BATON): return "CKK_BATON";
  262. case (CKK_JUNIPER): return "CKK_JUNIPER";
  263. case (CKK_CDMF): return "CKK_CDMF";
  264. case (CKK_AES): return "CKK_AES";
  265. case (CKK_BLOWFISH): return "CKK_BLOWFISH";
  266. case (CKK_TWOFISH): return "CKK_TWOFISH";
  267. case (CKK_SECURID): return "CKK_SECURID";
  268. case (CKK_HOTP): return "CKK_HOTP";
  269. case (CKK_ACTI): return "CKK_ACTI";
  270. case (CKK_CAMELLIA): return "CKK_CAMELLIA";
  271. case (CKK_ARIA): return "CKK_ARIA";
  272. case (CKK_MD5_HMAC): return "CKK_MD5_HMAC";
  273. case (CKK_SHA_1_HMAC): return "CKK_SHA_1_HMAC";
  274. case (CKK_RIPEMD128_HMAC): return "CKK_RIPEMD128_HMAC";
  275. case (CKK_RIPEMD160_HMAC): return "CKK_RIPEMD160_HMAC";
  276. case (CKK_SHA256_HMAC): return "CKK_SHA256_HMAC";
  277. case (CKK_SHA384_HMAC): return "CKK_SHA384_HMAC";
  278. case (CKK_SHA512_HMAC): return "CKK_SHA512_HMAC";
  279. case (CKK_SHA224_HMAC): return "CKK_SHA224_HMAC";
  280. case (CKK_SEED): return "CKK_SEED";
  281. case (CKK_GOSTR3410): return "CKK_GOSTR3410";
  282. case (CKK_GOSTR3411): return "CKK_GOSTR3411";
  283. case (CKK_GOST28147): return "CKK_GOST28147";
  284. default: return "<UNKNOWN KEY TYPE>";
  285. }
  286. /* clang-format on */
  287. }
  288. /* Log the failure of a PKCS#11 function, and call aws_raise_error() with the appropriate AWS error code */
  289. static int s_raise_ck_error(const struct aws_pkcs11_lib *pkcs11_lib, const char *fn_name, CK_RV rv) {
  290. int aws_err = s_ck_to_aws_error(rv);
  291. AWS_LOGF_ERROR(
  292. AWS_LS_IO_PKCS11,
  293. "id=%p: %s() failed. PKCS#11 error: %s (0x%08lX). AWS error: %s",
  294. (void *)pkcs11_lib,
  295. fn_name,
  296. aws_pkcs11_ckr_str(rv),
  297. rv,
  298. aws_error_name(aws_err));
  299. return aws_raise_error(aws_err);
  300. }
  301. /* Log the failure of a PKCS#11 session-handle function and call aws_raise_error() with the appropriate error code */
  302. static int s_raise_ck_session_error(
  303. const struct aws_pkcs11_lib *pkcs11_lib,
  304. const char *fn_name,
  305. CK_SESSION_HANDLE session,
  306. CK_RV rv) {
  307. int aws_err = s_ck_to_aws_error(rv);
  308. AWS_LOGF_ERROR(
  309. AWS_LS_IO_PKCS11,
  310. "id=%p session=%lu: %s() failed. PKCS#11 error: %s (0x%08lX). AWS error: %s",
  311. (void *)pkcs11_lib,
  312. session,
  313. fn_name,
  314. aws_pkcs11_ckr_str(rv),
  315. rv,
  316. aws_error_name(aws_err));
  317. return aws_raise_error(aws_err);
  318. }
  319. /* PKCS#11 often pads strings with ' ' */
  320. static bool s_is_padding(uint8_t c) {
  321. return c == ' ';
  322. }
  323. /* Return byte-cursor to string with ' ' padding trimmed off.
  324. * PKCS#11 structs commonly stores strings in fixed-width arrays, padded by ' ' instead of null-terminator */
  325. static struct aws_byte_cursor s_trim_padding(const uint8_t *str, size_t len) {
  326. const struct aws_byte_cursor src = aws_byte_cursor_from_array(str, len);
  327. return aws_byte_cursor_right_trim_pred(&src, s_is_padding);
  328. }
  329. /* Callback for PKCS#11 library to create a mutex.
  330. * Described in PKCS11-base-v2.40 section 3.7 */
  331. static CK_RV s_pkcs11_create_mutex(CK_VOID_PTR_PTR mutex_out) {
  332. if (mutex_out == NULL) {
  333. return CKR_GENERAL_ERROR;
  334. }
  335. /* Using the default allocator because there's no way to know which PKCS#11 instance is invoking this callback */
  336. struct aws_allocator *allocator = aws_default_allocator();
  337. struct aws_mutex *mutex = aws_mem_calloc(allocator, 1, sizeof(struct aws_mutex));
  338. if (aws_mutex_init(mutex)) {
  339. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "PKCS#11 CreateMutex() failed, error %s", aws_error_name(aws_last_error()));
  340. aws_mem_release(allocator, mutex);
  341. *mutex_out = NULL;
  342. return CKR_GENERAL_ERROR;
  343. }
  344. *mutex_out = mutex;
  345. return CKR_OK;
  346. }
  347. /* Callback for PKCS#11 library to destroy a mutex.
  348. * Described in PKCS11-base-v2.40 section 3.7 */
  349. static CK_RV s_pkcs11_destroy_mutex(CK_VOID_PTR mutex_ptr) {
  350. if (mutex_ptr == NULL) {
  351. return CKR_GENERAL_ERROR;
  352. }
  353. struct aws_mutex *mutex = mutex_ptr;
  354. aws_mutex_clean_up(mutex);
  355. aws_mem_release(aws_default_allocator(), mutex);
  356. return CKR_OK;
  357. }
  358. /* Callback for PKCS#11 library to lock a mutex.
  359. * Described in PKCS11-base-v2.40 section 3.7 */
  360. static CK_RV s_pkcs11_lock_mutex(CK_VOID_PTR mutex_ptr) {
  361. if (mutex_ptr == NULL) {
  362. return CKR_GENERAL_ERROR;
  363. }
  364. struct aws_mutex *mutex = mutex_ptr;
  365. if (aws_mutex_lock(mutex)) {
  366. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "PKCS#11 LockMutex() failed, error %s", aws_error_name(aws_last_error()));
  367. return CKR_GENERAL_ERROR;
  368. }
  369. return CKR_OK;
  370. }
  371. /* Callback for PKCS#11 library to unlock a mutex.
  372. * Described in PKCS11-base-v2.40 section 3.7 */
  373. static CK_RV s_pkcs11_unlock_mutex(CK_VOID_PTR mutex_ptr) {
  374. if (mutex_ptr == NULL) {
  375. return CKR_GENERAL_ERROR;
  376. }
  377. struct aws_mutex *mutex = mutex_ptr;
  378. if (aws_mutex_unlock(mutex)) {
  379. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "PKCS#11 LockMutex() failed, error %s", aws_error_name(aws_last_error()));
  380. /* NOTE: Cryptoki has a CKR_MUTEX_NOT_LOCKED error code.
  381. * But posix doesn't treat this as an error and neither does windows so ¯\_(ツ)_/¯
  382. * If aws_mutex_unlock() failed here, it was something else. */
  383. return CKR_GENERAL_ERROR;
  384. }
  385. return CKR_OK;
  386. }
  387. struct aws_pkcs11_lib {
  388. struct aws_ref_count ref_count;
  389. struct aws_allocator *allocator;
  390. struct aws_shared_library shared_lib;
  391. CK_FUNCTION_LIST_PTR function_list;
  392. /* If true, C_Finalize() should be called when last ref-count is released */
  393. bool finalize_on_cleanup;
  394. };
  395. /* Invoked when last ref-count is released. Free all resources.
  396. * Note that this is also called if initialization fails half-way through */
  397. static void s_pkcs11_lib_destroy(void *user_data) {
  398. struct aws_pkcs11_lib *pkcs11_lib = user_data;
  399. AWS_LOGF_DEBUG(
  400. AWS_LS_IO_PKCS11,
  401. "id=%p: Unloading PKCS#11. C_Finalize:%s",
  402. (void *)pkcs11_lib,
  403. pkcs11_lib->finalize_on_cleanup ? "yes" : "omit");
  404. if (pkcs11_lib->finalize_on_cleanup) {
  405. CK_RV rv = pkcs11_lib->function_list->C_Finalize(NULL);
  406. if (rv != CKR_OK) {
  407. /* Log about it, but continue cleaning up */
  408. s_raise_ck_error(pkcs11_lib, "C_Finalize", rv);
  409. }
  410. }
  411. aws_shared_library_clean_up(&pkcs11_lib->shared_lib);
  412. aws_mem_release(pkcs11_lib->allocator, pkcs11_lib);
  413. }
  414. struct aws_pkcs11_lib *aws_pkcs11_lib_new(
  415. struct aws_allocator *allocator,
  416. const struct aws_pkcs11_lib_options *options) {
  417. /* Validate options */
  418. switch (options->initialize_finalize_behavior) {
  419. case AWS_PKCS11_LIB_DEFAULT_BEHAVIOR:
  420. case AWS_PKCS11_LIB_OMIT_INITIALIZE:
  421. case AWS_PKCS11_LIB_STRICT_INITIALIZE_FINALIZE:
  422. break;
  423. default:
  424. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "Invalid PKCS#11 behavior arg: %d", options->initialize_finalize_behavior);
  425. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  426. return NULL;
  427. }
  428. /* Create the struct */
  429. struct aws_pkcs11_lib *pkcs11_lib = aws_mem_calloc(allocator, 1, sizeof(struct aws_pkcs11_lib));
  430. aws_ref_count_init(&pkcs11_lib->ref_count, pkcs11_lib, s_pkcs11_lib_destroy);
  431. pkcs11_lib->allocator = allocator;
  432. /* Load the library. */
  433. /* need a null-terminated string to call next function,
  434. * or NULL if going to search the current application for PKCS#11 symbols. */
  435. struct aws_string *filename_storage = NULL;
  436. const char *filename = NULL;
  437. if (options->filename.ptr != NULL) {
  438. filename_storage = aws_string_new_from_cursor(allocator, &options->filename);
  439. filename = aws_string_c_str(filename_storage);
  440. }
  441. AWS_LOGF_DEBUG(
  442. AWS_LS_IO_PKCS11,
  443. "Loading PKCS#11. file:'%s' C_Initialize:%s",
  444. filename ? filename : "<MAIN PROGRAM>",
  445. (options->initialize_finalize_behavior == AWS_PKCS11_LIB_OMIT_INITIALIZE) ? "omit" : "yes");
  446. if (aws_shared_library_init(&pkcs11_lib->shared_lib, filename)) {
  447. goto error;
  448. }
  449. /* Find C_GetFunctionList() and call it to get the list of pointers to all the other functions */
  450. CK_C_GetFunctionList get_function_list = NULL;
  451. if (aws_shared_library_find_function(
  452. &pkcs11_lib->shared_lib, "C_GetFunctionList", (aws_generic_function *)&get_function_list)) {
  453. goto error;
  454. }
  455. CK_RV rv = get_function_list(&pkcs11_lib->function_list);
  456. if (rv != CKR_OK) {
  457. s_raise_ck_error(pkcs11_lib, "C_GetFunctionList", rv);
  458. goto error;
  459. }
  460. /* Check function list's API version */
  461. CK_VERSION version = pkcs11_lib->function_list->version;
  462. if ((version.major != AWS_SUPPORTED_CRYPTOKI_VERSION_MAJOR) ||
  463. (version.minor < AWS_MIN_SUPPORTED_CRYPTOKI_VERSION_MINOR)) {
  464. AWS_LOGF_ERROR(
  465. AWS_LS_IO_PKCS11,
  466. "id=%p: Library implements PKCS#11 version %" PRIu8 ".%" PRIu8 " but %d.%d compatibility is required",
  467. (void *)pkcs11_lib,
  468. version.major,
  469. version.minor,
  470. AWS_SUPPORTED_CRYPTOKI_VERSION_MAJOR,
  471. AWS_MIN_SUPPORTED_CRYPTOKI_VERSION_MINOR);
  472. aws_raise_error(AWS_ERROR_PKCS11_VERSION_UNSUPPORTED);
  473. goto error;
  474. }
  475. /* Call C_Initialize() */
  476. const char *init_logging_str = "omit";
  477. if (options->initialize_finalize_behavior != AWS_PKCS11_LIB_OMIT_INITIALIZE) {
  478. CK_C_INITIALIZE_ARGS init_args = {
  479. /* encourage lib to use our locks */
  480. .CreateMutex = s_pkcs11_create_mutex,
  481. .DestroyMutex = s_pkcs11_destroy_mutex,
  482. .LockMutex = s_pkcs11_lock_mutex,
  483. .UnlockMutex = s_pkcs11_unlock_mutex,
  484. /* but if it needs to use OS locks instead, sure whatever you do you */
  485. .flags = CKF_OS_LOCKING_OK,
  486. };
  487. rv = pkcs11_lib->function_list->C_Initialize(&init_args);
  488. if (rv != CKR_OK) {
  489. /* Ignore already-initialized errors (unless user wants STRICT behavior) */
  490. if (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED ||
  491. options->initialize_finalize_behavior == AWS_PKCS11_LIB_STRICT_INITIALIZE_FINALIZE) {
  492. s_raise_ck_error(pkcs11_lib, "C_Initialize", rv);
  493. goto error;
  494. }
  495. }
  496. init_logging_str = aws_pkcs11_ckr_str(rv);
  497. if (options->initialize_finalize_behavior == AWS_PKCS11_LIB_STRICT_INITIALIZE_FINALIZE) {
  498. pkcs11_lib->finalize_on_cleanup = true;
  499. }
  500. }
  501. /* Get info about the library and log it.
  502. * This will be VERY useful for diagnosing user issues. */
  503. CK_INFO info;
  504. AWS_ZERO_STRUCT(info);
  505. rv = pkcs11_lib->function_list->C_GetInfo(&info);
  506. if (rv != CKR_OK) {
  507. s_raise_ck_error(pkcs11_lib, "C_GetInfo", rv);
  508. goto error;
  509. }
  510. AWS_LOGF_INFO(
  511. AWS_LS_IO_PKCS11,
  512. "id=%p: PKCS#11 loaded. file:'%s' cryptokiVersion:%" PRIu8 ".%" PRIu8 " manufacturerID:'" PRInSTR
  513. "' flags:0x%08lX libraryDescription:'" PRInSTR "' libraryVersion:%" PRIu8 ".%" PRIu8 " C_Initialize:%s",
  514. (void *)pkcs11_lib,
  515. filename ? filename : "<MAIN PROGRAM>",
  516. info.cryptokiVersion.major,
  517. info.cryptokiVersion.minor,
  518. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.manufacturerID, sizeof(info.manufacturerID))),
  519. info.flags,
  520. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.libraryDescription, sizeof(info.libraryDescription))),
  521. info.libraryVersion.major,
  522. info.libraryVersion.minor,
  523. init_logging_str);
  524. /* Success! */
  525. goto clean_up;
  526. error:
  527. AWS_LOGF_ERROR(
  528. AWS_LS_IO_PKCS11,
  529. "id=%p: Failed to initialize PKCS#11 library from '%s'",
  530. (void *)pkcs11_lib,
  531. filename ? filename : "<MAIN_PROGRAM>");
  532. aws_pkcs11_lib_release(pkcs11_lib);
  533. pkcs11_lib = NULL;
  534. clean_up:
  535. aws_string_destroy(filename_storage);
  536. return pkcs11_lib;
  537. }
  538. struct aws_pkcs11_lib *aws_pkcs11_lib_acquire(struct aws_pkcs11_lib *pkcs11_lib) {
  539. aws_ref_count_acquire(&pkcs11_lib->ref_count);
  540. return pkcs11_lib;
  541. }
  542. void aws_pkcs11_lib_release(struct aws_pkcs11_lib *pkcs11_lib) {
  543. if (pkcs11_lib) {
  544. aws_ref_count_release(&pkcs11_lib->ref_count);
  545. }
  546. }
  547. /**
  548. * Find the slot that meets all criteria:
  549. * - has a token
  550. * - if match_slot_id is non-null, then slot IDs must match
  551. * - if match_token_label is non-null, then labels must match
  552. * The function fails unless it finds exactly one slot meeting all criteria.
  553. */
  554. int aws_pkcs11_lib_find_slot_with_token(
  555. struct aws_pkcs11_lib *pkcs11_lib,
  556. const uint64_t *match_slot_id,
  557. const struct aws_string *match_token_label,
  558. CK_SLOT_ID *out_slot_id) {
  559. CK_SLOT_ID *slot_id_array = NULL; /* array of IDs */
  560. CK_SLOT_ID *candidate = NULL; /* points to ID in slot_id_array */
  561. CK_TOKEN_INFO info;
  562. AWS_ZERO_STRUCT(info);
  563. bool success = false;
  564. /* query number of slots with tokens */
  565. CK_ULONG num_slots = 0;
  566. CK_RV rv = pkcs11_lib->function_list->C_GetSlotList(CK_TRUE /*tokenPresent*/, NULL /*pSlotList*/, &num_slots);
  567. if (rv != CKR_OK) {
  568. s_raise_ck_error(pkcs11_lib, "C_GetSlotList", rv);
  569. goto clean_up;
  570. }
  571. if (num_slots == 0) {
  572. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "id=%p: No PKCS#11 tokens present in any slot", (void *)pkcs11_lib);
  573. aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
  574. goto clean_up;
  575. }
  576. AWS_LOGF_TRACE(
  577. AWS_LS_IO_PKCS11, "id=%p: Found %lu slots with tokens. Picking one...", (void *)pkcs11_lib, num_slots);
  578. /* allocate space for slot IDs */
  579. slot_id_array = aws_mem_calloc(pkcs11_lib->allocator, num_slots, sizeof(CK_SLOT_ID));
  580. /* query all slot IDs */
  581. rv = pkcs11_lib->function_list->C_GetSlotList(CK_TRUE /*tokenPresent*/, slot_id_array, &num_slots);
  582. if (rv != CKR_OK) {
  583. s_raise_ck_error(pkcs11_lib, "C_GetSlotList", rv);
  584. goto clean_up;
  585. }
  586. for (size_t i = 0; i < num_slots; ++i) {
  587. CK_SLOT_ID slot_id_i = slot_id_array[i];
  588. /* if specific slot_id requested, and this isn't it, then skip */
  589. if ((match_slot_id != NULL) && (*match_slot_id != slot_id_i)) {
  590. AWS_LOGF_TRACE(
  591. AWS_LS_IO_PKCS11,
  592. "id=%p: Ignoring PKCS#11 token because slot %lu doesn't match %" PRIu64,
  593. (void *)pkcs11_lib,
  594. slot_id_i,
  595. *match_slot_id);
  596. continue;
  597. }
  598. /* query token info */
  599. CK_TOKEN_INFO token_info_i;
  600. AWS_ZERO_STRUCT(token_info_i);
  601. rv = pkcs11_lib->function_list->C_GetTokenInfo(slot_id_i, &token_info_i);
  602. if (rv != CKR_OK) {
  603. s_raise_ck_error(pkcs11_lib, "C_GetTokenInfo", rv);
  604. goto clean_up;
  605. }
  606. /* if specific token label requested, and this isn't it, then skip */
  607. if (match_token_label != NULL) {
  608. struct aws_byte_cursor label_i = s_trim_padding(token_info_i.label, sizeof(token_info_i.label));
  609. if (aws_string_eq_byte_cursor(match_token_label, &label_i) == false) {
  610. AWS_LOGF_TRACE(
  611. AWS_LS_IO_PKCS11,
  612. "id=%p: Ignoring PKCS#11 token in slot %lu because label '" PRInSTR "' doesn't match '%s'",
  613. (void *)pkcs11_lib,
  614. slot_id_i,
  615. AWS_BYTE_CURSOR_PRI(label_i),
  616. aws_string_c_str(match_token_label));
  617. continue;
  618. }
  619. }
  620. /* this slot is a candidate! */
  621. /* be sure there's only one candidate */
  622. if (candidate != NULL) {
  623. AWS_LOGF_ERROR(
  624. AWS_LS_IO_PKCS11,
  625. "id=%p: Failed to choose PKCS#11 token, multiple tokens match search criteria",
  626. (void *)pkcs11_lib);
  627. aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
  628. goto clean_up;
  629. }
  630. /* the new candidate! */
  631. candidate = &slot_id_array[i];
  632. memcpy(&info, &token_info_i, sizeof(CK_TOKEN_INFO));
  633. }
  634. if (candidate == NULL) {
  635. AWS_LOGF_ERROR(
  636. AWS_LS_IO_PKCS11, "id=%p: Failed to find PKCS#11 token which matches search criteria", (void *)pkcs11_lib);
  637. aws_raise_error(AWS_ERROR_PKCS11_TOKEN_NOT_FOUND);
  638. goto clean_up;
  639. }
  640. /* success! */
  641. AWS_LOGF_DEBUG(
  642. AWS_LS_IO_PKCS11,
  643. "id=%p: Selected PKCS#11 token. slot:%lu label:'" PRInSTR "' manufacturerID:'" PRInSTR "' model:'" PRInSTR
  644. "' serialNumber:'" PRInSTR "' flags:0x%08lX sessionCount:%lu/%lu rwSessionCount:%lu/%lu"
  645. " freePublicMemory:%lu/%lu freePrivateMemory:%lu/%lu"
  646. " hardwareVersion:%" PRIu8 ".%" PRIu8 " firmwareVersion:%" PRIu8 ".%" PRIu8,
  647. (void *)pkcs11_lib,
  648. *candidate,
  649. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.label, sizeof(info.label))),
  650. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.manufacturerID, sizeof(info.manufacturerID))),
  651. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.model, sizeof(info.model))),
  652. AWS_BYTE_CURSOR_PRI(s_trim_padding(info.serialNumber, sizeof(info.serialNumber))),
  653. info.flags,
  654. info.ulSessionCount,
  655. info.ulMaxSessionCount,
  656. info.ulRwSessionCount,
  657. info.ulMaxRwSessionCount,
  658. info.ulFreePublicMemory,
  659. info.ulTotalPublicMemory,
  660. info.ulFreePrivateMemory,
  661. info.ulTotalPrivateMemory,
  662. info.hardwareVersion.major,
  663. info.hardwareVersion.minor,
  664. info.firmwareVersion.major,
  665. info.firmwareVersion.minor);
  666. *out_slot_id = *candidate;
  667. success = true;
  668. clean_up:
  669. aws_mem_release(pkcs11_lib->allocator, slot_id_array);
  670. return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
  671. }
  672. CK_FUNCTION_LIST *aws_pkcs11_lib_get_function_list(struct aws_pkcs11_lib *pkcs11_lib) {
  673. return pkcs11_lib->function_list;
  674. }
  675. int aws_pkcs11_lib_open_session(
  676. struct aws_pkcs11_lib *pkcs11_lib,
  677. CK_SLOT_ID slot_id,
  678. CK_SESSION_HANDLE *out_session_handle) {
  679. CK_SESSION_HANDLE session_handle = CK_INVALID_HANDLE;
  680. CK_RV rv = pkcs11_lib->function_list->C_OpenSession(
  681. slot_id, CKF_SERIAL_SESSION /*flags*/, NULL /*pApplication*/, NULL /*notify*/, &session_handle);
  682. if (rv != CKR_OK) {
  683. return s_raise_ck_error(pkcs11_lib, "C_OpenSession", rv);
  684. }
  685. /* success! */
  686. AWS_LOGF_DEBUG(
  687. AWS_LS_IO_PKCS11, "id=%p session=%lu: Session opened on slot %lu", (void *)pkcs11_lib, session_handle, slot_id);
  688. *out_session_handle = session_handle;
  689. return AWS_OP_SUCCESS;
  690. }
  691. void aws_pkcs11_lib_close_session(struct aws_pkcs11_lib *pkcs11_lib, CK_SESSION_HANDLE session_handle) {
  692. CK_RV rv = pkcs11_lib->function_list->C_CloseSession(session_handle);
  693. if (rv == CKR_OK) {
  694. AWS_LOGF_DEBUG(AWS_LS_IO_PKCS11, "id=%p session=%lu: Session closed", (void *)pkcs11_lib, session_handle);
  695. } else {
  696. /* Log the error, but we can't really do anything about it */
  697. AWS_LOGF_WARN(
  698. AWS_LS_IO_PKCS11,
  699. "id=%p session=%lu: Ignoring C_CloseSession() failure. PKCS#11 error: %s (0x%08lX)",
  700. (void *)pkcs11_lib,
  701. session_handle,
  702. aws_pkcs11_ckr_str(rv),
  703. rv);
  704. }
  705. }
  706. int aws_pkcs11_lib_login_user(
  707. struct aws_pkcs11_lib *pkcs11_lib,
  708. CK_SESSION_HANDLE session_handle,
  709. const struct aws_string *optional_user_pin) {
  710. CK_UTF8CHAR_PTR pin = NULL;
  711. CK_ULONG pin_len = 0;
  712. if (optional_user_pin) {
  713. if (optional_user_pin->len > ULONG_MAX) {
  714. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "id=%p session=%lu: PIN is too long", (void *)pkcs11_lib, session_handle);
  715. return aws_raise_error(AWS_ERROR_PKCS11_CKR_PIN_INCORRECT);
  716. }
  717. pin_len = (CK_ULONG)optional_user_pin->len;
  718. pin = (CK_UTF8CHAR_PTR)optional_user_pin->bytes;
  719. }
  720. CK_RV rv = pkcs11_lib->function_list->C_Login(session_handle, CKU_USER, pin, pin_len);
  721. /* Ignore if we are already logged in, this could happen if application using device sdk also logs in to pkcs11 */
  722. if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
  723. return s_raise_ck_session_error(pkcs11_lib, "C_Login", session_handle, rv);
  724. }
  725. /* Success! */
  726. if (rv == CKR_USER_ALREADY_LOGGED_IN) {
  727. AWS_LOGF_DEBUG(
  728. AWS_LS_IO_PKCS11, "id=%p session=%lu: User was already logged in", (void *)pkcs11_lib, session_handle);
  729. } else {
  730. AWS_LOGF_DEBUG(AWS_LS_IO_PKCS11, "id=%p session=%lu: User logged in", (void *)pkcs11_lib, session_handle);
  731. }
  732. return AWS_OP_SUCCESS;
  733. }
  734. /**
  735. * Find the object that meets all criteria:
  736. * - is private key
  737. * - if match_label is non-null, then labels must match
  738. * The function fails unless it finds exactly one object meeting all criteria.
  739. */
  740. int aws_pkcs11_lib_find_private_key(
  741. struct aws_pkcs11_lib *pkcs11_lib,
  742. CK_SESSION_HANDLE session_handle,
  743. const struct aws_string *match_label,
  744. CK_OBJECT_HANDLE *out_key_handle,
  745. CK_KEY_TYPE *out_key_type) {
  746. /* gets set true after everything succeeds */
  747. bool success = false;
  748. /* gets set true after search initialized.
  749. * indicates that C_FindObjectsFinal() must be run before function ends */
  750. bool must_finalize_search = false;
  751. /* set up search attributes */
  752. CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
  753. CK_ULONG num_attributes = 1;
  754. CK_ATTRIBUTE attributes[2] = {
  755. {
  756. .type = CKA_CLASS,
  757. .pValue = &key_class,
  758. .ulValueLen = sizeof(key_class),
  759. },
  760. };
  761. if (match_label != NULL) {
  762. if (match_label->len > ULONG_MAX) {
  763. AWS_LOGF_ERROR(
  764. AWS_LS_IO_PKCS11,
  765. "id=%p session=%lu: private key label is too long",
  766. (void *)pkcs11_lib,
  767. session_handle);
  768. aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
  769. goto clean_up;
  770. }
  771. CK_ATTRIBUTE *attr = &attributes[num_attributes++];
  772. attr->type = CKA_LABEL;
  773. attr->pValue = (void *)match_label->bytes;
  774. attr->ulValueLen = (CK_ULONG)match_label->len;
  775. }
  776. /* initialize search */
  777. CK_RV rv = pkcs11_lib->function_list->C_FindObjectsInit(session_handle, attributes, num_attributes);
  778. if (rv != CKR_OK) {
  779. s_raise_ck_session_error(pkcs11_lib, "C_FindObjectsInit", session_handle, rv);
  780. goto clean_up;
  781. }
  782. must_finalize_search = true;
  783. /* get search results.
  784. * note that we're asking for 2 objects max, so we can fail if we find more than one */
  785. CK_OBJECT_HANDLE found_objects[2] = {0};
  786. CK_ULONG num_found = 0;
  787. rv = pkcs11_lib->function_list->C_FindObjects(session_handle, found_objects, 2 /*max*/, &num_found);
  788. if (rv != CKR_OK) {
  789. s_raise_ck_session_error(pkcs11_lib, "C_FindObjects", session_handle, rv);
  790. goto clean_up;
  791. }
  792. if ((num_found == 0) || (found_objects[0] == CK_INVALID_HANDLE)) {
  793. AWS_LOGF_ERROR(
  794. AWS_LS_IO_PKCS11,
  795. "id=%p session=%lu: Failed to find private key on PKCS#11 token which matches search criteria",
  796. (void *)pkcs11_lib,
  797. session_handle);
  798. aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
  799. goto clean_up;
  800. }
  801. if (num_found > 1) {
  802. AWS_LOGF_ERROR(
  803. AWS_LS_IO_PKCS11,
  804. "id=%p session=%lu: Failed to choose private key, multiple objects on PKCS#11 token match search criteria",
  805. (void *)pkcs11_lib,
  806. session_handle);
  807. aws_raise_error(AWS_ERROR_PKCS11_KEY_NOT_FOUND);
  808. goto clean_up;
  809. }
  810. /* key found */
  811. CK_OBJECT_HANDLE key_handle = found_objects[0];
  812. /* query key-type */
  813. CK_KEY_TYPE key_type = 0;
  814. CK_ATTRIBUTE key_attributes[] = {
  815. {
  816. .type = CKA_KEY_TYPE,
  817. .pValue = &key_type,
  818. .ulValueLen = sizeof(key_type),
  819. },
  820. };
  821. rv = pkcs11_lib->function_list->C_GetAttributeValue(
  822. session_handle, key_handle, key_attributes, AWS_ARRAY_SIZE(key_attributes));
  823. if (rv != CKR_OK) {
  824. s_raise_ck_session_error(pkcs11_lib, "C_GetAttributeValue", session_handle, rv);
  825. goto clean_up;
  826. }
  827. switch (key_type) {
  828. case CKK_RSA:
  829. case CKK_EC:
  830. break;
  831. default:
  832. AWS_LOGF_ERROR(
  833. AWS_LS_IO_PKCS11,
  834. "id=%p session=%lu: PKCS#11 private key type %s (0x%08lX) is currently unsupported",
  835. (void *)pkcs11_lib,
  836. session_handle,
  837. s_ckk_str(key_type),
  838. key_type);
  839. aws_raise_error(AWS_ERROR_PKCS11_KEY_TYPE_UNSUPPORTED);
  840. goto clean_up;
  841. }
  842. /* Success! */
  843. AWS_LOGF_TRACE(
  844. AWS_LS_IO_PKCS11,
  845. "id=%p session=%lu: Found private key. type=%s",
  846. (void *)pkcs11_lib,
  847. session_handle,
  848. s_ckk_str(key_type));
  849. *out_key_handle = key_handle;
  850. *out_key_type = key_type;
  851. success = true;
  852. clean_up:
  853. if (must_finalize_search) {
  854. rv = pkcs11_lib->function_list->C_FindObjectsFinal(session_handle);
  855. /* don't bother reporting error if we were already failing */
  856. if ((rv != CKR_OK) && (success == true)) {
  857. s_raise_ck_session_error(pkcs11_lib, "C_FindObjectsFinal", session_handle, rv);
  858. success = false;
  859. }
  860. }
  861. return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
  862. }
  863. int aws_pkcs11_lib_decrypt(
  864. struct aws_pkcs11_lib *pkcs11_lib,
  865. CK_SESSION_HANDLE session_handle,
  866. CK_OBJECT_HANDLE key_handle,
  867. CK_KEY_TYPE key_type,
  868. struct aws_byte_cursor encrypted_data,
  869. struct aws_allocator *allocator,
  870. struct aws_byte_buf *out_data) {
  871. AWS_ASSERT(encrypted_data.len <= ULONG_MAX); /* do real error checking if this becomes a public API */
  872. AWS_ASSERT(out_data->allocator == NULL);
  873. CK_MECHANISM mechanism;
  874. AWS_ZERO_STRUCT(mechanism);
  875. /* Note, CKK_EC is not expected to enter into this code path */
  876. switch (key_type) {
  877. case CKK_RSA:
  878. mechanism.mechanism = CKM_RSA_PKCS;
  879. break;
  880. default:
  881. aws_raise_error(AWS_ERROR_PKCS11_KEY_TYPE_UNSUPPORTED);
  882. goto error;
  883. }
  884. /* initialize the decryption operation */
  885. CK_RV rv = pkcs11_lib->function_list->C_DecryptInit(session_handle, &mechanism, key_handle);
  886. if (rv != CKR_OK) {
  887. s_raise_ck_session_error(pkcs11_lib, "C_DecryptInit", session_handle, rv);
  888. goto error;
  889. }
  890. /* query needed capacity (finalizes decryption operation if it fails) */
  891. CK_ULONG data_len = 0;
  892. rv = pkcs11_lib->function_list->C_Decrypt(
  893. session_handle, encrypted_data.ptr, (CK_ULONG)encrypted_data.len, NULL /*pData*/, &data_len);
  894. if (rv != CKR_OK) {
  895. s_raise_ck_session_error(pkcs11_lib, "C_Decrypt", session_handle, rv);
  896. goto error;
  897. }
  898. aws_byte_buf_init(out_data, allocator, data_len); /* cannot fail */
  899. /* do actual decrypt (finalizes decryption operation, whether it succeeds or fails)*/
  900. rv = pkcs11_lib->function_list->C_Decrypt(
  901. session_handle, encrypted_data.ptr, (CK_ULONG)encrypted_data.len, out_data->buffer, &data_len);
  902. if (rv != CKR_OK) {
  903. s_raise_ck_session_error(pkcs11_lib, "C_Decrypt", session_handle, rv);
  904. goto error;
  905. }
  906. out_data->len = data_len;
  907. return AWS_OP_SUCCESS;
  908. error:
  909. aws_byte_buf_clean_up(out_data);
  910. return AWS_OP_ERR;
  911. }
  912. /* runs C_Sign(), putting encrypted message into out_signature */
  913. static int s_pkcs11_sign_helper(
  914. struct aws_pkcs11_lib *pkcs11_lib,
  915. CK_SESSION_HANDLE session_handle,
  916. CK_OBJECT_HANDLE key_handle,
  917. CK_MECHANISM mechanism,
  918. struct aws_byte_cursor input_data,
  919. struct aws_allocator *allocator,
  920. struct aws_byte_buf *out_signature) {
  921. /* initialize signing operation */
  922. CK_RV rv = pkcs11_lib->function_list->C_SignInit(session_handle, &mechanism, key_handle);
  923. if (rv != CKR_OK) {
  924. s_raise_ck_session_error(pkcs11_lib, "C_SignInit", session_handle, rv);
  925. goto error;
  926. }
  927. /* query needed capacity (finalizes signing operation if it fails) */
  928. CK_ULONG signature_len = 0;
  929. rv = pkcs11_lib->function_list->C_Sign(
  930. session_handle, input_data.ptr, (CK_ULONG)input_data.len, NULL /*pSignature*/, &signature_len);
  931. if (rv != CKR_OK) {
  932. s_raise_ck_session_error(pkcs11_lib, "C_Sign", session_handle, rv);
  933. goto error;
  934. }
  935. aws_byte_buf_init(out_signature, allocator, signature_len); /* cannot fail */
  936. /* do actual signing (finalizes signing operation, whether it succeeds or fails) */
  937. rv = pkcs11_lib->function_list->C_Sign(
  938. session_handle, input_data.ptr, (CK_ULONG)input_data.len, out_signature->buffer, &signature_len);
  939. if (rv != CKR_OK) {
  940. s_raise_ck_session_error(pkcs11_lib, "C_Sign", session_handle, rv);
  941. goto error;
  942. }
  943. out_signature->len = signature_len;
  944. return AWS_OP_SUCCESS;
  945. error:
  946. aws_byte_buf_clean_up(out_signature);
  947. return AWS_OP_ERR;
  948. }
  949. int aws_get_prefix_to_rsa_sig(enum aws_tls_hash_algorithm digest_alg, struct aws_byte_cursor *out_prefix) {
  950. switch (digest_alg) {
  951. case AWS_TLS_HASH_SHA1:
  952. *out_prefix = aws_byte_cursor_from_array(SHA1_PREFIX_TO_RSA_SIG, sizeof(SHA1_PREFIX_TO_RSA_SIG));
  953. break;
  954. case AWS_TLS_HASH_SHA224:
  955. *out_prefix = aws_byte_cursor_from_array(SHA224_PREFIX_TO_RSA_SIG, sizeof(SHA224_PREFIX_TO_RSA_SIG));
  956. break;
  957. case AWS_TLS_HASH_SHA256:
  958. *out_prefix = aws_byte_cursor_from_array(SHA256_PREFIX_TO_RSA_SIG, sizeof(SHA256_PREFIX_TO_RSA_SIG));
  959. break;
  960. case AWS_TLS_HASH_SHA384:
  961. *out_prefix = aws_byte_cursor_from_array(SHA384_PREFIX_TO_RSA_SIG, sizeof(SHA384_PREFIX_TO_RSA_SIG));
  962. break;
  963. case AWS_TLS_HASH_SHA512:
  964. *out_prefix = aws_byte_cursor_from_array(SHA512_PREFIX_TO_RSA_SIG, sizeof(SHA512_PREFIX_TO_RSA_SIG));
  965. break;
  966. default:
  967. return aws_raise_error(AWS_IO_TLS_DIGEST_ALGORITHM_UNSUPPORTED);
  968. }
  969. return AWS_OP_SUCCESS;
  970. }
  971. static int s_pkcs11_sign_rsa(
  972. struct aws_pkcs11_lib *pkcs11_lib,
  973. CK_SESSION_HANDLE session_handle,
  974. CK_OBJECT_HANDLE key_handle,
  975. struct aws_byte_cursor digest_data,
  976. struct aws_allocator *allocator,
  977. enum aws_tls_hash_algorithm digest_alg,
  978. enum aws_tls_signature_algorithm signature_alg,
  979. struct aws_byte_buf *out_signature) {
  980. if (signature_alg != AWS_TLS_SIGNATURE_RSA) {
  981. AWS_LOGF_ERROR(
  982. AWS_LS_IO_PKCS11,
  983. "id=%p session=%lu: Signature algorithm '%s' is currently unsupported for PKCS#11 RSA keys. "
  984. "Supported algorithms are: RSA",
  985. (void *)pkcs11_lib,
  986. session_handle,
  987. aws_tls_signature_algorithm_str(signature_alg));
  988. return aws_raise_error(AWS_IO_TLS_SIGNATURE_ALGORITHM_UNSUPPORTED);
  989. }
  990. struct aws_byte_cursor prefix;
  991. if (aws_get_prefix_to_rsa_sig(digest_alg, &prefix)) {
  992. AWS_LOGF_ERROR(
  993. AWS_LS_IO_PKCS11,
  994. "id=%p session=%lu: Unsupported digest '%s' for PKCS#11 RSA signing. "
  995. "Supported digests are: SHA1, SHA256, SHA384 and SHA512. AWS error: %s",
  996. (void *)pkcs11_lib,
  997. session_handle,
  998. aws_tls_hash_algorithm_str(digest_alg),
  999. aws_error_name(aws_last_error()));
  1000. return AWS_OP_ERR;
  1001. }
  1002. bool success = false;
  1003. struct aws_byte_buf prefixed_input;
  1004. aws_byte_buf_init(&prefixed_input, allocator, digest_data.len + prefix.len); /* cannot fail */
  1005. aws_byte_buf_write_from_whole_cursor(&prefixed_input, prefix);
  1006. aws_byte_buf_write_from_whole_cursor(&prefixed_input, digest_data);
  1007. /* We could get the original input and not the digest to sign and leverage CKM_SHA*_RSA_PKCS mechanisms
  1008. * but the original input is too large (all the TLS handshake messages until clientCertVerify) and
  1009. * we do not want to perform the digest inside the TPM for performance reasons, therefore we only
  1010. * leverage CKM_RSA_PKCS mechanism and *only* sign the digest using TPM. Only signing requires
  1011. * additional prefix to the input to complete the digest part for RSA signing. */
  1012. CK_MECHANISM mechanism = {.mechanism = CKM_RSA_PKCS};
  1013. if (s_pkcs11_sign_helper(
  1014. pkcs11_lib,
  1015. session_handle,
  1016. key_handle,
  1017. mechanism,
  1018. aws_byte_cursor_from_buf(&prefixed_input),
  1019. allocator,
  1020. out_signature)) {
  1021. goto error;
  1022. }
  1023. success = true;
  1024. goto clean_up;
  1025. error:
  1026. aws_byte_buf_clean_up(out_signature);
  1027. clean_up:
  1028. aws_byte_buf_clean_up(&prefixed_input);
  1029. return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
  1030. }
  1031. /*
  1032. * Basic ASN.1 (DER) encoding of header -- sufficient for ECDSA
  1033. */
  1034. static int s_asn1_enc_prefix(struct aws_byte_buf *buffer, uint8_t identifier, size_t length) {
  1035. if (((identifier & 0x1f) == 0x1f) || (length > 0x7f)) {
  1036. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "Unable to encode ASN.1 (DER) header 0x%02x %zu", identifier, length);
  1037. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1038. }
  1039. uint8_t head[2];
  1040. head[0] = identifier;
  1041. head[1] = (uint8_t)length;
  1042. if (!aws_byte_buf_write(buffer, head, sizeof(head))) {
  1043. AWS_LOGF_ERROR(
  1044. AWS_LS_IO_PKCS11, "Insufficient buffer to encode ASN.1 (DER) header 0x%02x %zu", identifier, length);
  1045. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1046. }
  1047. return AWS_OP_SUCCESS;
  1048. }
  1049. /*
  1050. * Basic ASN.1 (DER) encoding of an unsigned big number -- sufficient for ECDSA. Note that this implementation
  1051. * may reduce the number of integer bytes down to 1 (removing leading zero bytes), or conversely increase by
  1052. * one extra byte to ensure the unsigned integer is unambiguously encoded.
  1053. */
  1054. int aws_pkcs11_asn1_enc_ubigint(struct aws_byte_buf *const buffer, struct aws_byte_cursor bigint) {
  1055. // trim out all leading zero's
  1056. while (bigint.len > 0 && bigint.ptr[0] == 0) {
  1057. aws_byte_cursor_advance(&bigint, 1);
  1058. }
  1059. // If the most significant bit is a '1', prefix with a zero-byte to prevent misinterpreting number as negative.
  1060. // If the big integer value was zero, length will be zero, replace with zero-byte using the same approach.
  1061. bool add_leading_zero = bigint.len == 0 || (bigint.ptr[0] & 0x80) != 0;
  1062. size_t actual_len = bigint.len + (add_leading_zero ? 1 : 0);
  1063. // header - indicate integer of given length (including any prefix zero)
  1064. bool success = s_asn1_enc_prefix(buffer, 0x02, actual_len) == AWS_OP_SUCCESS;
  1065. if (add_leading_zero) {
  1066. success = success && aws_byte_buf_write_u8(buffer, 0);
  1067. }
  1068. // write rest of number
  1069. success = success && aws_byte_buf_write_from_whole_cursor(buffer, bigint);
  1070. if (success) {
  1071. return AWS_OP_SUCCESS;
  1072. } else {
  1073. AWS_LOGF_ERROR(
  1074. AWS_LS_IO_PKCS11, "Insufficient buffer to ASN.1 (DER) encode big integer of length %zu", actual_len);
  1075. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1076. }
  1077. }
  1078. static int s_pkcs11_sign_ecdsa(
  1079. struct aws_pkcs11_lib *pkcs11_lib,
  1080. CK_SESSION_HANDLE session_handle,
  1081. CK_OBJECT_HANDLE key_handle,
  1082. struct aws_byte_cursor digest_data,
  1083. struct aws_allocator *allocator,
  1084. enum aws_tls_signature_algorithm signature_alg,
  1085. struct aws_byte_buf *out_signature) {
  1086. struct aws_byte_buf part_signature;
  1087. struct aws_byte_buf r_part;
  1088. struct aws_byte_buf s_part;
  1089. AWS_ZERO_STRUCT(part_signature);
  1090. AWS_ZERO_STRUCT(r_part);
  1091. AWS_ZERO_STRUCT(s_part);
  1092. if (signature_alg != AWS_TLS_SIGNATURE_ECDSA) {
  1093. AWS_LOGF_ERROR(
  1094. AWS_LS_IO_PKCS11,
  1095. "id=%p session=%lu: Signature algorithm '%s' is currently unsupported for PKCS#11 EC keys. "
  1096. "Supported algorithms are: ECDSA",
  1097. (void *)pkcs11_lib,
  1098. session_handle,
  1099. aws_tls_signature_algorithm_str(signature_alg));
  1100. return aws_raise_error(AWS_IO_TLS_SIGNATURE_ALGORITHM_UNSUPPORTED);
  1101. }
  1102. bool success = false;
  1103. /* ECDSA signing consists of DER-encoding of "r" and "s" parameters. C_Sign returns the two
  1104. * integers as big numbers in big-endian format, so translation is required.
  1105. */
  1106. CK_MECHANISM mechanism = {.mechanism = CKM_ECDSA};
  1107. if (s_pkcs11_sign_helper(
  1108. pkcs11_lib, session_handle, key_handle, mechanism, digest_data, allocator, &part_signature) !=
  1109. AWS_OP_SUCCESS) {
  1110. goto error;
  1111. }
  1112. /* PKCS11 library returns these parameters as two big unsigned integer numbers of exactly the same length. The
  1113. * numbers need to be ASN.1/DER encoded (variable length). In addition to the header, space is needed to allow for
  1114. * an occasional extra 0x00 prefix byte to ensure integer is encoded and interpreted as unsigned.
  1115. */
  1116. if (part_signature.len == 0 || (part_signature.len & 1) != 0) {
  1117. /* This should never happen, we would fail anyway, but making it explicit and fail early */
  1118. AWS_LOGF_ERROR(
  1119. AWS_LS_IO_PKCS11,
  1120. "PKCS11 library returned an invalid length, unable to interpret ECDSA signature to encode correctly.");
  1121. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1122. goto error;
  1123. }
  1124. size_t num_bytes = part_signature.len / 2;
  1125. aws_byte_buf_init(&r_part, allocator, num_bytes + 4);
  1126. aws_byte_buf_init(&s_part, allocator, num_bytes + 4);
  1127. if (aws_pkcs11_asn1_enc_ubigint(&r_part, aws_byte_cursor_from_array(part_signature.buffer, num_bytes)) !=
  1128. AWS_OP_SUCCESS) {
  1129. goto error;
  1130. }
  1131. if (aws_pkcs11_asn1_enc_ubigint(
  1132. &s_part, aws_byte_cursor_from_array(part_signature.buffer + num_bytes, num_bytes)) != AWS_OP_SUCCESS) {
  1133. goto error;
  1134. }
  1135. size_t pair_len = r_part.len + s_part.len;
  1136. aws_byte_buf_init(out_signature, allocator, pair_len + 2); // inc header
  1137. if (s_asn1_enc_prefix(out_signature, 0x30, pair_len) != AWS_OP_SUCCESS) {
  1138. goto error;
  1139. }
  1140. if (!aws_byte_buf_write_from_whole_buffer(out_signature, r_part)) {
  1141. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "Insufficient buffer to ASN.1 (DER) encode ECDSA signature R-part.");
  1142. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1143. goto error;
  1144. }
  1145. if (!aws_byte_buf_write_from_whole_buffer(out_signature, s_part)) {
  1146. AWS_LOGF_ERROR(AWS_LS_IO_PKCS11, "Insufficient buffer to ASN.1 (DER) encode ECDSA signature S-part.");
  1147. return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
  1148. goto error;
  1149. }
  1150. success = true;
  1151. goto clean_up;
  1152. error:
  1153. aws_byte_buf_clean_up(out_signature);
  1154. clean_up:
  1155. aws_byte_buf_clean_up(&part_signature);
  1156. aws_byte_buf_clean_up(&r_part);
  1157. aws_byte_buf_clean_up(&s_part);
  1158. return success ? AWS_OP_SUCCESS : AWS_OP_ERR;
  1159. }
  1160. int aws_pkcs11_lib_sign(
  1161. struct aws_pkcs11_lib *pkcs11_lib,
  1162. CK_SESSION_HANDLE session_handle,
  1163. CK_OBJECT_HANDLE key_handle,
  1164. CK_KEY_TYPE key_type,
  1165. struct aws_byte_cursor digest_data,
  1166. struct aws_allocator *allocator,
  1167. enum aws_tls_hash_algorithm digest_alg,
  1168. enum aws_tls_signature_algorithm signature_alg,
  1169. struct aws_byte_buf *out_signature) {
  1170. AWS_ASSERT(digest_data.len <= ULONG_MAX); /* do real error checking if this becomes a public API */
  1171. AWS_ASSERT(out_signature->allocator == NULL);
  1172. switch (key_type) {
  1173. case CKK_RSA:
  1174. return s_pkcs11_sign_rsa(
  1175. pkcs11_lib,
  1176. session_handle,
  1177. key_handle,
  1178. digest_data,
  1179. allocator,
  1180. digest_alg,
  1181. signature_alg,
  1182. out_signature);
  1183. case CKK_ECDSA:
  1184. return s_pkcs11_sign_ecdsa(
  1185. pkcs11_lib,
  1186. session_handle,
  1187. key_handle,
  1188. digest_data,
  1189. allocator,
  1190. // not digest_alg -- need to check this
  1191. signature_alg,
  1192. out_signature);
  1193. default:
  1194. return aws_raise_error(AWS_ERROR_PKCS11_KEY_TYPE_UNSUPPORTED);
  1195. }
  1196. }