TlsOptions.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/crt/io/TlsOptions.h>
  6. #include <aws/crt/io/Pkcs11.h>
  7. #include <aws/crt/Api.h>
  8. #include <aws/io/logging.h>
  9. #include <aws/io/tls_channel_handler.h>
  10. namespace Aws
  11. {
  12. namespace Crt
  13. {
  14. namespace Io
  15. {
  16. TlsContextOptions::~TlsContextOptions()
  17. {
  18. if (m_isInit)
  19. {
  20. aws_tls_ctx_options_clean_up(&m_options);
  21. }
  22. }
  23. TlsContextOptions::TlsContextOptions() noexcept : m_isInit(false) { AWS_ZERO_STRUCT(m_options); }
  24. TlsContextOptions::TlsContextOptions(TlsContextOptions &&other) noexcept
  25. {
  26. m_options = other.m_options;
  27. m_isInit = other.m_isInit;
  28. AWS_ZERO_STRUCT(other.m_options);
  29. other.m_isInit = false;
  30. }
  31. TlsContextOptions &TlsContextOptions::operator=(TlsContextOptions &&other) noexcept
  32. {
  33. if (&other != this)
  34. {
  35. if (m_isInit)
  36. {
  37. aws_tls_ctx_options_clean_up(&m_options);
  38. }
  39. m_options = other.m_options;
  40. m_isInit = other.m_isInit;
  41. AWS_ZERO_STRUCT(other.m_options);
  42. other.m_isInit = false;
  43. }
  44. return *this;
  45. }
  46. TlsContextOptions TlsContextOptions::InitDefaultClient(Allocator *allocator) noexcept
  47. {
  48. TlsContextOptions ctxOptions;
  49. aws_tls_ctx_options_init_default_client(&ctxOptions.m_options, allocator);
  50. ctxOptions.m_isInit = true;
  51. return ctxOptions;
  52. }
  53. TlsContextOptions TlsContextOptions::InitClientWithMtls(
  54. const char *certPath,
  55. const char *pKeyPath,
  56. Allocator *allocator) noexcept
  57. {
  58. TlsContextOptions ctxOptions;
  59. if (!aws_tls_ctx_options_init_client_mtls_from_path(
  60. &ctxOptions.m_options, allocator, certPath, pKeyPath))
  61. {
  62. ctxOptions.m_isInit = true;
  63. }
  64. return ctxOptions;
  65. }
  66. TlsContextOptions TlsContextOptions::InitClientWithMtls(
  67. const ByteCursor &cert,
  68. const ByteCursor &pkey,
  69. Allocator *allocator) noexcept
  70. {
  71. TlsContextOptions ctxOptions;
  72. if (!aws_tls_ctx_options_init_client_mtls(
  73. &ctxOptions.m_options,
  74. allocator,
  75. const_cast<ByteCursor *>(&cert),
  76. const_cast<ByteCursor *>(&pkey)))
  77. {
  78. ctxOptions.m_isInit = true;
  79. }
  80. return ctxOptions;
  81. }
  82. TlsContextOptions TlsContextOptions::InitClientWithMtlsPkcs11(
  83. const TlsContextPkcs11Options &pkcs11Options,
  84. Allocator *allocator) noexcept
  85. {
  86. TlsContextOptions ctxOptions;
  87. aws_tls_ctx_pkcs11_options nativePkcs11Options = pkcs11Options.GetUnderlyingHandle();
  88. if (!aws_tls_ctx_options_init_client_mtls_with_pkcs11(
  89. &ctxOptions.m_options, allocator, &nativePkcs11Options))
  90. {
  91. ctxOptions.m_isInit = true;
  92. }
  93. return ctxOptions;
  94. }
  95. TlsContextOptions TlsContextOptions::InitClientWithMtlsPkcs12(
  96. const char *pkcs12Path,
  97. const char *pkcs12Pwd,
  98. Allocator *allocator) noexcept
  99. {
  100. TlsContextOptions ctxOptions;
  101. struct aws_byte_cursor password = aws_byte_cursor_from_c_str(pkcs12Pwd);
  102. if (!aws_tls_ctx_options_init_client_mtls_pkcs12_from_path(
  103. &ctxOptions.m_options, allocator, pkcs12Path, &password))
  104. {
  105. ctxOptions.m_isInit = true;
  106. }
  107. return ctxOptions;
  108. }
  109. bool TlsContextOptions::SetKeychainPath(ByteCursor &keychain_path) noexcept
  110. {
  111. AWS_ASSERT(m_isInit);
  112. return aws_tls_ctx_options_set_keychain_path(&m_options, &keychain_path) == 0;
  113. }
  114. TlsContextOptions TlsContextOptions::InitClientWithMtlsSystemPath(
  115. const char *windowsCertStorePath,
  116. Allocator *allocator) noexcept
  117. {
  118. TlsContextOptions ctxOptions;
  119. if (!aws_tls_ctx_options_init_client_mtls_from_system_path(
  120. &ctxOptions.m_options, allocator, windowsCertStorePath))
  121. {
  122. ctxOptions.m_isInit = true;
  123. }
  124. return ctxOptions;
  125. }
  126. int TlsContextOptions::LastError() const noexcept { return LastErrorOrUnknown(); }
  127. bool TlsContextOptions::IsAlpnSupported() noexcept { return aws_tls_is_alpn_available(); }
  128. bool TlsContextOptions::SetAlpnList(const char *alpn_list) noexcept
  129. {
  130. AWS_ASSERT(m_isInit);
  131. return aws_tls_ctx_options_set_alpn_list(&m_options, alpn_list) == 0;
  132. }
  133. void TlsContextOptions::SetVerifyPeer(bool verify_peer) noexcept
  134. {
  135. AWS_ASSERT(m_isInit);
  136. aws_tls_ctx_options_set_verify_peer(&m_options, verify_peer);
  137. }
  138. void TlsContextOptions::SetMinimumTlsVersion(aws_tls_versions minimumTlsVersion)
  139. {
  140. AWS_ASSERT(m_isInit);
  141. aws_tls_ctx_options_set_minimum_tls_version(&m_options, minimumTlsVersion);
  142. }
  143. void TlsContextOptions::SetTlsCipherPreference(aws_tls_cipher_pref cipher_pref)
  144. {
  145. AWS_ASSERT(m_isInit);
  146. aws_tls_ctx_options_set_tls_cipher_preference(&m_options, cipher_pref);
  147. }
  148. bool TlsContextOptions::OverrideDefaultTrustStore(const char *caPath, const char *caFile) noexcept
  149. {
  150. AWS_ASSERT(m_isInit);
  151. return aws_tls_ctx_options_override_default_trust_store_from_path(&m_options, caPath, caFile) == 0;
  152. }
  153. bool TlsContextOptions::OverrideDefaultTrustStore(const ByteCursor &ca) noexcept
  154. {
  155. AWS_ASSERT(m_isInit);
  156. return aws_tls_ctx_options_override_default_trust_store(&m_options, const_cast<ByteCursor *>(&ca)) == 0;
  157. }
  158. TlsContextPkcs11Options::TlsContextPkcs11Options(
  159. const std::shared_ptr<Pkcs11Lib> &pkcs11Lib,
  160. Allocator *) noexcept
  161. : m_pkcs11Lib{pkcs11Lib}
  162. {
  163. }
  164. void TlsContextPkcs11Options::SetUserPin(const String &pin) noexcept { m_userPin = pin; }
  165. void TlsContextPkcs11Options::SetSlotId(const uint64_t id) noexcept { m_slotId = id; }
  166. void TlsContextPkcs11Options::SetTokenLabel(const String &label) noexcept { m_tokenLabel = label; }
  167. void TlsContextPkcs11Options::SetPrivateKeyObjectLabel(const String &label) noexcept
  168. {
  169. m_privateKeyObjectLabel = label;
  170. }
  171. void TlsContextPkcs11Options::SetCertificateFilePath(const String &path) noexcept
  172. {
  173. m_certificateFilePath = path;
  174. }
  175. void TlsContextPkcs11Options::SetCertificateFileContents(const String &contents) noexcept
  176. {
  177. m_certificateFileContents = contents;
  178. }
  179. aws_tls_ctx_pkcs11_options TlsContextPkcs11Options::GetUnderlyingHandle() const noexcept
  180. {
  181. aws_tls_ctx_pkcs11_options options;
  182. AWS_ZERO_STRUCT(options);
  183. if (m_pkcs11Lib)
  184. {
  185. options.pkcs11_lib = m_pkcs11Lib->GetNativeHandle();
  186. }
  187. if (m_slotId)
  188. {
  189. options.slot_id = &(*m_slotId);
  190. }
  191. if (m_userPin)
  192. {
  193. options.user_pin = ByteCursorFromString(*m_userPin);
  194. }
  195. if (m_tokenLabel)
  196. {
  197. options.token_label = ByteCursorFromString(*m_tokenLabel);
  198. }
  199. if (m_privateKeyObjectLabel)
  200. {
  201. options.private_key_object_label = ByteCursorFromString(*m_privateKeyObjectLabel);
  202. }
  203. if (m_certificateFilePath)
  204. {
  205. options.cert_file_path = ByteCursorFromString(*m_certificateFilePath);
  206. }
  207. if (m_certificateFileContents)
  208. {
  209. options.cert_file_contents = ByteCursorFromString(*m_certificateFileContents);
  210. }
  211. return options;
  212. }
  213. TlsConnectionOptions::TlsConnectionOptions() noexcept : m_lastError(AWS_ERROR_SUCCESS), m_isInit(false) {}
  214. TlsConnectionOptions::TlsConnectionOptions(aws_tls_ctx *ctx, Allocator *allocator) noexcept
  215. : m_allocator(allocator), m_lastError(AWS_ERROR_SUCCESS), m_isInit(true)
  216. {
  217. aws_tls_connection_options_init_from_ctx(&m_tls_connection_options, ctx);
  218. }
  219. TlsConnectionOptions::~TlsConnectionOptions()
  220. {
  221. if (m_isInit)
  222. {
  223. aws_tls_connection_options_clean_up(&m_tls_connection_options);
  224. m_isInit = false;
  225. }
  226. }
  227. TlsConnectionOptions::TlsConnectionOptions(const TlsConnectionOptions &options) noexcept
  228. {
  229. m_isInit = false;
  230. AWS_ZERO_STRUCT(m_tls_connection_options);
  231. if (options.m_isInit)
  232. {
  233. m_allocator = options.m_allocator;
  234. if (!aws_tls_connection_options_copy(&m_tls_connection_options, &options.m_tls_connection_options))
  235. {
  236. m_isInit = true;
  237. }
  238. else
  239. {
  240. m_lastError = LastErrorOrUnknown();
  241. }
  242. }
  243. }
  244. TlsConnectionOptions &TlsConnectionOptions::operator=(const TlsConnectionOptions &options) noexcept
  245. {
  246. if (this != &options)
  247. {
  248. if (m_isInit)
  249. {
  250. aws_tls_connection_options_clean_up(&m_tls_connection_options);
  251. }
  252. m_isInit = false;
  253. AWS_ZERO_STRUCT(m_tls_connection_options);
  254. if (options.m_isInit)
  255. {
  256. m_allocator = options.m_allocator;
  257. if (!aws_tls_connection_options_copy(
  258. &m_tls_connection_options, &options.m_tls_connection_options))
  259. {
  260. m_isInit = true;
  261. }
  262. else
  263. {
  264. m_lastError = LastErrorOrUnknown();
  265. }
  266. }
  267. }
  268. return *this;
  269. }
  270. TlsConnectionOptions::TlsConnectionOptions(TlsConnectionOptions &&options) noexcept
  271. : m_isInit(options.m_isInit)
  272. {
  273. if (options.m_isInit)
  274. {
  275. m_tls_connection_options = options.m_tls_connection_options;
  276. m_allocator = options.m_allocator;
  277. AWS_ZERO_STRUCT(options.m_tls_connection_options);
  278. options.m_isInit = false;
  279. }
  280. }
  281. TlsConnectionOptions &TlsConnectionOptions::operator=(TlsConnectionOptions &&options) noexcept
  282. {
  283. if (this != &options)
  284. {
  285. if (m_isInit)
  286. {
  287. aws_tls_connection_options_clean_up(&m_tls_connection_options);
  288. }
  289. m_isInit = false;
  290. if (options.m_isInit)
  291. {
  292. m_tls_connection_options = options.m_tls_connection_options;
  293. AWS_ZERO_STRUCT(options.m_tls_connection_options);
  294. options.m_isInit = false;
  295. m_isInit = true;
  296. m_allocator = options.m_allocator;
  297. }
  298. }
  299. return *this;
  300. }
  301. bool TlsConnectionOptions::SetServerName(ByteCursor &serverName) noexcept
  302. {
  303. if (!isValid())
  304. {
  305. m_lastError = LastErrorOrUnknown();
  306. return false;
  307. }
  308. if (aws_tls_connection_options_set_server_name(&m_tls_connection_options, m_allocator, &serverName))
  309. {
  310. m_lastError = LastErrorOrUnknown();
  311. return false;
  312. }
  313. return true;
  314. }
  315. bool TlsConnectionOptions::SetAlpnList(const char *alpnList) noexcept
  316. {
  317. if (!isValid())
  318. {
  319. m_lastError = LastErrorOrUnknown();
  320. return false;
  321. }
  322. if (aws_tls_connection_options_set_alpn_list(&m_tls_connection_options, m_allocator, alpnList))
  323. {
  324. m_lastError = LastErrorOrUnknown();
  325. return false;
  326. }
  327. return true;
  328. }
  329. TlsContext::TlsContext() noexcept : m_ctx(nullptr), m_initializationError(AWS_ERROR_SUCCESS) {}
  330. TlsContext::TlsContext(TlsContextOptions &options, TlsMode mode, Allocator *allocator) noexcept
  331. : m_ctx(nullptr), m_initializationError(AWS_ERROR_SUCCESS)
  332. {
  333. #if BYO_CRYPTO
  334. if (!ApiHandle::GetBYOCryptoNewTlsContextImplCallback() ||
  335. !ApiHandle::GetBYOCryptoDeleteTlsContextImplCallback())
  336. {
  337. AWS_LOGF_ERROR(
  338. AWS_LS_IO_TLS,
  339. "Must call ApiHandle::SetBYOCryptoTlsContextCallbacks() before TlsContext can be created");
  340. m_initializationError = AWS_IO_TLS_CTX_ERROR;
  341. return;
  342. }
  343. void *impl = ApiHandle::GetBYOCryptoNewTlsContextImplCallback()(options, mode, allocator);
  344. if (!impl)
  345. {
  346. AWS_LOGF_ERROR(
  347. AWS_LS_IO_TLS, "Creation callback from ApiHandle::SetBYOCryptoTlsContextCallbacks() failed");
  348. m_initializationError = AWS_IO_TLS_CTX_ERROR;
  349. return;
  350. }
  351. auto underlying_tls_ctx = static_cast<aws_tls_ctx *>(aws_mem_calloc(allocator, 1, sizeof(aws_tls_ctx)));
  352. underlying_tls_ctx->alloc = allocator;
  353. underlying_tls_ctx->impl = impl;
  354. aws_ref_count_init(&underlying_tls_ctx->ref_count, underlying_tls_ctx, [](void *userdata) {
  355. auto dying_ctx = static_cast<aws_tls_ctx *>(userdata);
  356. ApiHandle::GetBYOCryptoDeleteTlsContextImplCallback()(dying_ctx->impl);
  357. aws_mem_release(dying_ctx->alloc, dying_ctx);
  358. });
  359. m_ctx.reset(underlying_tls_ctx, aws_tls_ctx_release);
  360. #else
  361. if (mode == TlsMode::CLIENT)
  362. {
  363. aws_tls_ctx *underlying_tls_ctx = aws_tls_client_ctx_new(allocator, &options.m_options);
  364. if (underlying_tls_ctx != nullptr)
  365. {
  366. m_ctx.reset(underlying_tls_ctx, aws_tls_ctx_release);
  367. }
  368. }
  369. else
  370. {
  371. aws_tls_ctx *underlying_tls_ctx = aws_tls_server_ctx_new(allocator, &options.m_options);
  372. if (underlying_tls_ctx != nullptr)
  373. {
  374. m_ctx.reset(underlying_tls_ctx, aws_tls_ctx_release);
  375. }
  376. }
  377. if (!m_ctx)
  378. {
  379. m_initializationError = Aws::Crt::LastErrorOrUnknown();
  380. }
  381. #endif // BYO_CRYPTO
  382. }
  383. TlsConnectionOptions TlsContext::NewConnectionOptions() const noexcept
  384. {
  385. if (!isValid())
  386. {
  387. AWS_LOGF_ERROR(
  388. AWS_LS_IO_TLS, "Trying to call TlsContext::NewConnectionOptions from an invalid TlsContext.");
  389. return TlsConnectionOptions();
  390. }
  391. return TlsConnectionOptions(m_ctx.get(), m_ctx->alloc);
  392. }
  393. TlsChannelHandler::TlsChannelHandler(
  394. struct aws_channel_slot *,
  395. const struct aws_tls_connection_options &options,
  396. Allocator *allocator)
  397. : ChannelHandler(allocator)
  398. {
  399. m_OnNegotiationResult = options.on_negotiation_result;
  400. m_userData = options.user_data;
  401. aws_byte_buf_init(&m_protocolByteBuf, allocator, 16);
  402. }
  403. TlsChannelHandler::~TlsChannelHandler() { aws_byte_buf_clean_up(&m_protocolByteBuf); }
  404. void TlsChannelHandler::CompleteTlsNegotiation(int errorCode)
  405. {
  406. m_OnNegotiationResult(&this->m_handler, GetSlot(), errorCode, m_userData);
  407. }
  408. ClientTlsChannelHandler::ClientTlsChannelHandler(
  409. struct aws_channel_slot *slot,
  410. const struct aws_tls_connection_options &options,
  411. Allocator *allocator)
  412. : TlsChannelHandler(slot, options, allocator)
  413. {
  414. }
  415. } // namespace Io
  416. } // namespace Crt
  417. } // namespace Aws
  418. #if BYO_CRYPTO
  419. AWS_EXTERN_C_BEGIN
  420. bool aws_tls_is_alpn_available(void)
  421. {
  422. const auto &callback = Aws::Crt::ApiHandle::GetBYOCryptoIsTlsAlpnSupportedCallback();
  423. if (!callback)
  424. {
  425. AWS_LOGF_ERROR(
  426. AWS_LS_IO_TLS, "Must call ApiHandle::SetBYOCryptoTlsContextCallbacks() before ALPN can be queried");
  427. return false;
  428. }
  429. return callback();
  430. }
  431. struct aws_byte_buf aws_tls_handler_protocol(struct aws_channel_handler *handler)
  432. {
  433. auto *channelHandler = reinterpret_cast<Aws::Crt::Io::ChannelHandler *>(handler->impl);
  434. auto *tlsHandler = static_cast<Aws::Crt::Io::TlsChannelHandler *>(channelHandler);
  435. Aws::Crt::String protocolString = const_cast<const Aws::Crt::Io::TlsChannelHandler *>(tlsHandler)->GetProtocol();
  436. tlsHandler->m_protocolByteBuf.len = 0;
  437. aws_byte_cursor protocolCursor = Aws::Crt::ByteCursorFromString(protocolString);
  438. aws_byte_buf_append_dynamic(&tlsHandler->m_protocolByteBuf, &protocolCursor);
  439. return tlsHandler->m_protocolByteBuf;
  440. }
  441. AWS_EXTERN_C_END
  442. #endif /* BYO_CRYPTO */