ssl_cache.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * SSL session cache implementation
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  8. * not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. /*
  20. * These session callbacks use a simple chained list
  21. * to store and retrieve the session information.
  22. */
  23. #include "common.h"
  24. #if defined(MBEDTLS_SSL_CACHE_C)
  25. #include "mbedtls/platform.h"
  26. #include "mbedtls/ssl_cache.h"
  27. #include "mbedtls/ssl_internal.h"
  28. #include <string.h>
  29. void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache)
  30. {
  31. memset(cache, 0, sizeof(mbedtls_ssl_cache_context));
  32. cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
  33. cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
  34. #if defined(MBEDTLS_THREADING_C)
  35. mbedtls_mutex_init(&cache->mutex);
  36. #endif
  37. }
  38. int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session)
  39. {
  40. int ret = 1;
  41. #if defined(MBEDTLS_HAVE_TIME)
  42. mbedtls_time_t t = mbedtls_time(NULL);
  43. #endif
  44. mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
  45. mbedtls_ssl_cache_entry *cur, *entry;
  46. #if defined(MBEDTLS_THREADING_C)
  47. if (mbedtls_mutex_lock(&cache->mutex) != 0) {
  48. return 1;
  49. }
  50. #endif
  51. cur = cache->chain;
  52. entry = NULL;
  53. while (cur != NULL) {
  54. entry = cur;
  55. cur = cur->next;
  56. #if defined(MBEDTLS_HAVE_TIME)
  57. if (cache->timeout != 0 &&
  58. (int) (t - entry->timestamp) > cache->timeout) {
  59. continue;
  60. }
  61. #endif
  62. if (session->id_len != entry->session.id_len ||
  63. memcmp(session->id, entry->session.id,
  64. entry->session.id_len) != 0) {
  65. continue;
  66. }
  67. ret = mbedtls_ssl_session_copy(session, &entry->session);
  68. if (ret != 0) {
  69. ret = 1;
  70. goto exit;
  71. }
  72. #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
  73. defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
  74. /*
  75. * Restore peer certificate (without rest of the original chain)
  76. */
  77. if (entry->peer_cert.p != NULL) {
  78. /* `session->peer_cert` is NULL after the call to
  79. * mbedtls_ssl_session_copy(), because cache entries
  80. * have the `peer_cert` field set to NULL. */
  81. if ((session->peer_cert = mbedtls_calloc(1,
  82. sizeof(mbedtls_x509_crt))) == NULL) {
  83. ret = 1;
  84. goto exit;
  85. }
  86. mbedtls_x509_crt_init(session->peer_cert);
  87. if (mbedtls_x509_crt_parse(session->peer_cert, entry->peer_cert.p,
  88. entry->peer_cert.len) != 0) {
  89. mbedtls_free(session->peer_cert);
  90. session->peer_cert = NULL;
  91. ret = 1;
  92. goto exit;
  93. }
  94. }
  95. #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
  96. ret = 0;
  97. goto exit;
  98. }
  99. exit:
  100. #if defined(MBEDTLS_THREADING_C)
  101. if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
  102. ret = 1;
  103. }
  104. #endif
  105. return ret;
  106. }
  107. int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session)
  108. {
  109. int ret = 1;
  110. #if defined(MBEDTLS_HAVE_TIME)
  111. mbedtls_time_t t = mbedtls_time(NULL), oldest = 0;
  112. mbedtls_ssl_cache_entry *old = NULL;
  113. #endif
  114. mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
  115. mbedtls_ssl_cache_entry *cur, *prv;
  116. int count = 0;
  117. #if defined(MBEDTLS_THREADING_C)
  118. if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
  119. return ret;
  120. }
  121. #endif
  122. cur = cache->chain;
  123. prv = NULL;
  124. while (cur != NULL) {
  125. count++;
  126. #if defined(MBEDTLS_HAVE_TIME)
  127. if (cache->timeout != 0 &&
  128. (int) (t - cur->timestamp) > cache->timeout) {
  129. cur->timestamp = t;
  130. break; /* expired, reuse this slot, update timestamp */
  131. }
  132. #endif
  133. if (memcmp(session->id, cur->session.id, cur->session.id_len) == 0) {
  134. break; /* client reconnected, keep timestamp for session id */
  135. }
  136. #if defined(MBEDTLS_HAVE_TIME)
  137. if (oldest == 0 || cur->timestamp < oldest) {
  138. oldest = cur->timestamp;
  139. old = cur;
  140. }
  141. #endif
  142. prv = cur;
  143. cur = cur->next;
  144. }
  145. if (cur == NULL) {
  146. #if defined(MBEDTLS_HAVE_TIME)
  147. /*
  148. * Reuse oldest entry if max_entries reached
  149. */
  150. if (count >= cache->max_entries) {
  151. if (old == NULL) {
  152. ret = 1;
  153. goto exit;
  154. }
  155. cur = old;
  156. }
  157. #else /* MBEDTLS_HAVE_TIME */
  158. /*
  159. * Reuse first entry in chain if max_entries reached,
  160. * but move to last place
  161. */
  162. if (count >= cache->max_entries) {
  163. if (cache->chain == NULL) {
  164. ret = 1;
  165. goto exit;
  166. }
  167. cur = cache->chain;
  168. cache->chain = cur->next;
  169. cur->next = NULL;
  170. prv->next = cur;
  171. }
  172. #endif /* MBEDTLS_HAVE_TIME */
  173. else {
  174. /*
  175. * max_entries not reached, create new entry
  176. */
  177. cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));
  178. if (cur == NULL) {
  179. ret = 1;
  180. goto exit;
  181. }
  182. if (prv == NULL) {
  183. cache->chain = cur;
  184. } else {
  185. prv->next = cur;
  186. }
  187. }
  188. #if defined(MBEDTLS_HAVE_TIME)
  189. cur->timestamp = t;
  190. #endif
  191. }
  192. #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
  193. defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
  194. /*
  195. * If we're reusing an entry, free its certificate first
  196. */
  197. if (cur->peer_cert.p != NULL) {
  198. mbedtls_free(cur->peer_cert.p);
  199. memset(&cur->peer_cert, 0, sizeof(mbedtls_x509_buf));
  200. }
  201. #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
  202. /* Copy the entire session; this temporarily makes a copy of the
  203. * X.509 CRT structure even though we only want to store the raw CRT.
  204. * This inefficiency will go away as soon as we implement on-demand
  205. * parsing of CRTs, in which case there's no need for the `peer_cert`
  206. * field anymore in the first place, and we're done after this call. */
  207. ret = mbedtls_ssl_session_copy(&cur->session, session);
  208. if (ret != 0) {
  209. ret = 1;
  210. goto exit;
  211. }
  212. #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
  213. defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
  214. /* If present, free the X.509 structure and only store the raw CRT data. */
  215. if (cur->session.peer_cert != NULL) {
  216. cur->peer_cert.p =
  217. mbedtls_calloc(1, cur->session.peer_cert->raw.len);
  218. if (cur->peer_cert.p == NULL) {
  219. ret = 1;
  220. goto exit;
  221. }
  222. memcpy(cur->peer_cert.p,
  223. cur->session.peer_cert->raw.p,
  224. cur->session.peer_cert->raw.len);
  225. cur->peer_cert.len = session->peer_cert->raw.len;
  226. mbedtls_x509_crt_free(cur->session.peer_cert);
  227. mbedtls_free(cur->session.peer_cert);
  228. cur->session.peer_cert = NULL;
  229. }
  230. #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
  231. ret = 0;
  232. exit:
  233. #if defined(MBEDTLS_THREADING_C)
  234. if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
  235. ret = 1;
  236. }
  237. #endif
  238. return ret;
  239. }
  240. #if defined(MBEDTLS_HAVE_TIME)
  241. void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout)
  242. {
  243. if (timeout < 0) {
  244. timeout = 0;
  245. }
  246. cache->timeout = timeout;
  247. }
  248. #endif /* MBEDTLS_HAVE_TIME */
  249. void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)
  250. {
  251. if (max < 0) {
  252. max = 0;
  253. }
  254. cache->max_entries = max;
  255. }
  256. void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache)
  257. {
  258. mbedtls_ssl_cache_entry *cur, *prv;
  259. cur = cache->chain;
  260. while (cur != NULL) {
  261. prv = cur;
  262. cur = cur->next;
  263. mbedtls_ssl_session_free(&prv->session);
  264. #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
  265. defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
  266. mbedtls_free(prv->peer_cert.p);
  267. #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
  268. mbedtls_free(prv);
  269. }
  270. #if defined(MBEDTLS_THREADING_C)
  271. mbedtls_mutex_free(&cache->mutex);
  272. #endif
  273. cache->chain = NULL;
  274. }
  275. #endif /* MBEDTLS_SSL_CACHE_C */