s2n_npn.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include "tls/extensions/s2n_npn.h"
  16. #include "tls/extensions/s2n_client_alpn.h"
  17. #include "tls/extensions/s2n_server_alpn.h"
  18. #include "tls/s2n_protocol_preferences.h"
  19. #include "tls/s2n_tls.h"
  20. #include "tls/s2n_tls_parameters.h"
  21. #include "utils/s2n_safety.h"
  22. bool s2n_npn_should_send(struct s2n_connection *conn)
  23. {
  24. /*
  25. *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-3
  26. *# For the same reasons, after a handshake has been performed for a
  27. *# given connection, renegotiations on the same connection MUST NOT
  28. *# include the "next_protocol_negotiation" extension.
  29. */
  30. return s2n_client_alpn_should_send(conn) && conn->config->npn_supported && !s2n_handshake_is_renegotiation(conn);
  31. }
  32. int s2n_client_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
  33. {
  34. /* Only use the NPN extension to negotiate a protocol if we don't have
  35. * an option to use the ALPN extension.
  36. */
  37. if (s2n_npn_should_send(conn) && !s2n_server_alpn_should_send(conn)) {
  38. conn->npn_negotiated = true;
  39. }
  40. return S2N_SUCCESS;
  41. }
  42. const s2n_extension_type s2n_client_npn_extension = {
  43. .iana_value = TLS_EXTENSION_NPN,
  44. .is_response = false,
  45. .send = s2n_extension_send_noop,
  46. .recv = s2n_client_npn_recv,
  47. .should_send = s2n_npn_should_send,
  48. .if_missing = s2n_extension_noop_if_missing,
  49. };
  50. bool s2n_server_npn_should_send(struct s2n_connection *conn)
  51. {
  52. return conn->npn_negotiated;
  53. }
  54. int s2n_server_npn_send(struct s2n_connection *conn, struct s2n_stuffer *out)
  55. {
  56. struct s2n_blob *app_protocols = NULL;
  57. POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &app_protocols));
  58. POSIX_ENSURE_REF(app_protocols);
  59. POSIX_GUARD(s2n_stuffer_write(out, app_protocols));
  60. return S2N_SUCCESS;
  61. }
  62. int s2n_server_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
  63. {
  64. struct s2n_blob *supported_protocols = NULL;
  65. POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &supported_protocols));
  66. POSIX_ENSURE_REF(supported_protocols);
  67. if (supported_protocols->size == 0) {
  68. /* No protocols configured */
  69. return S2N_SUCCESS;
  70. }
  71. /*
  72. *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-3
  73. *# The "extension_data" field of a "next_protocol_negotiation" extension
  74. *# in a "ServerHello" contains an optional list of protocols advertised
  75. *# by the server.
  76. */
  77. if (s2n_stuffer_data_available(extension)) {
  78. POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, extension, supported_protocols));
  79. }
  80. /*
  81. *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-4
  82. *# In the event that the client doesn't support any of server's protocols, or
  83. *# the server doesn't advertise any, it SHOULD select the first protocol
  84. *# that it supports.
  85. */
  86. if (s2n_get_application_protocol(conn) == NULL) {
  87. struct s2n_stuffer stuffer = { 0 };
  88. POSIX_GUARD(s2n_stuffer_init(&stuffer, supported_protocols));
  89. POSIX_GUARD(s2n_stuffer_skip_write(&stuffer, supported_protocols->size));
  90. struct s2n_blob protocol = { 0 };
  91. POSIX_GUARD_RESULT(s2n_protocol_preferences_read(&stuffer, &protocol));
  92. POSIX_ENSURE_LT(protocol.size, sizeof(conn->application_protocol));
  93. POSIX_CHECKED_MEMCPY(conn->application_protocol, protocol.data, protocol.size);
  94. conn->application_protocol[protocol.size] = '\0';
  95. }
  96. conn->npn_negotiated = true;
  97. return S2N_SUCCESS;
  98. }
  99. const s2n_extension_type s2n_server_npn_extension = {
  100. .iana_value = TLS_EXTENSION_NPN,
  101. .is_response = true,
  102. .send = s2n_server_npn_send,
  103. .recv = s2n_server_npn_recv,
  104. .should_send = s2n_server_npn_should_send,
  105. .if_missing = s2n_extension_noop_if_missing,
  106. };