ssl_misc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /* ssl_misc.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. #include <wolfssl/wolfcrypt/types.h>
  26. #include <wolfssl/wolfcrypt/error-crypt.h>
  27. #if !defined(WOLFSSL_SSL_MISC_INCLUDED)
  28. #ifndef WOLFSSL_IGNORE_FILE_WARN
  29. #warning ssl_misc.c does not need to be compiled separately from ssl.c
  30. #endif
  31. #else
  32. #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
  33. #ifndef NO_BIO
  34. #ifdef WOLFSSL_NO_FSEEK
  35. /* Amount of memory to allocate/add. */
  36. #define READ_BIO_FILE_CHUNK 128
  37. /* Read a file in chunks.
  38. *
  39. * Allocates a chunk and reads into it until it is full.
  40. *
  41. * @param [in, out] bio BIO object to read with.
  42. * @param [out] data Read data in a new buffer.
  43. * @return Negative on error.
  44. * @return Number of bytes read on success.
  45. */
  46. static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data)
  47. {
  48. int ret = 0;
  49. char* mem;
  50. char* p;
  51. /* Allocate buffer to hold a chunk of data. */
  52. mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  53. if (mem == NULL) {
  54. WOLFSSL_ERROR_MSG("Memory allocation error");
  55. ret = MEMORY_E;
  56. }
  57. if (ret == 0) {
  58. int sz;
  59. /* ret is the number of bytes read and is zero. */
  60. /* p is where to read in next chunk. */
  61. p = mem;
  62. /* Memory available to read into is one chunk. */
  63. sz = READ_BIO_FILE_CHUNK;
  64. /* Keep reading in chunks until no more or an error. */
  65. while ((sz = wolfSSL_BIO_read(bio, p, sz)) > 0) {
  66. int remaining;
  67. /* Update total read. */
  68. ret += sz;
  69. /* Calculate remaining unused memory. */
  70. remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
  71. /* Check for space remaining. */
  72. if (remaining != READ_BIO_FILE_CHUNK) {
  73. /* Update where data is read into. */
  74. p += sz;
  75. /* Maximum possible size is the remaining buffer size. */
  76. sz = remaining;
  77. }
  78. else {
  79. /* No space left for more data to be read - add a chunk. */
  80. p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL,
  81. DYNAMIC_TYPE_TMP_BUFFER);
  82. if (p == NULL) {
  83. sz = MEMORY_E;
  84. break;
  85. }
  86. /* Set mem to new pointer. */
  87. mem = p;
  88. /* Set p to where to read in next chunk. */
  89. p += ret;
  90. /* Read in a new chunk. */
  91. sz = READ_BIO_FILE_CHUNK;
  92. }
  93. }
  94. if ((sz < 0) || (ret == 0)) {
  95. /* Dispose of memory on error or no data read. */
  96. XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  97. mem = NULL;
  98. /* Return error. */
  99. ret = sz;
  100. }
  101. }
  102. *data = mem;
  103. return ret;
  104. }
  105. #endif
  106. /* Read exactly the required amount into a newly allocated buffer.
  107. *
  108. * @param [in, out] bio BIO object to read with.
  109. * @param [in sz Amount of data to read.
  110. * @param [out] data Read data in a new buffer.
  111. * @return Negative on error.
  112. * @return Number of bytes read on success.
  113. */
  114. static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data)
  115. {
  116. int ret = 0;
  117. char* mem;
  118. /* Allocate buffer to hold data. */
  119. mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  120. if (mem == NULL) {
  121. WOLFSSL_ERROR_MSG("Memory allocation error");
  122. ret = MEMORY_E;
  123. }
  124. else if ((ret = wolfSSL_BIO_read(bio, mem, sz)) != sz) {
  125. /* Pending data not read. */
  126. XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  127. mem = NULL;
  128. ret = MEMORY_E;
  129. }
  130. *data = mem;
  131. return ret;
  132. }
  133. /* Read all the data from a BIO.
  134. *
  135. * @param [in, out] bio BIO object to read with.
  136. * @param [out] data Read data in a buffer.
  137. * @param [out] dataSz Amount of data read in bytes.
  138. * @param [out] memAlloced Indicates whether return buffer was allocated.
  139. * @return Negative on error.
  140. * @return 0 on success.
  141. */
  142. static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz,
  143. int* memAlloced)
  144. {
  145. int ret;
  146. int sz;
  147. if (bio->type == WOLFSSL_BIO_MEMORY) {
  148. ret = wolfSSL_BIO_get_mem_data(bio, data);
  149. if (ret > 0) {
  150. bio->rdIdx += ret;
  151. }
  152. *memAlloced = 0;
  153. }
  154. #ifndef WOLFSSL_NO_FSEEK
  155. /* Get pending or, when a file BIO, get length of file. */
  156. else if ((sz = wolfSSL_BIO_get_len(bio)) > 0) {
  157. ret = wolfssl_read_bio_len(bio, sz, data);
  158. if (ret > 0) {
  159. *memAlloced = 1;
  160. }
  161. }
  162. #else
  163. else if ((sz = wolfSSL_BIO_pending(bio)) > 0) {
  164. ret = wolfssl_read_bio_len(bio, sz, data);
  165. if (ret > 0) {
  166. *memAlloced = 1;
  167. }
  168. }
  169. else if (bio->type == WOLFSSL_BIO_FILE) {
  170. ret = wolfssl_read_bio_file(bio, data);
  171. if (ret > 0) {
  172. *memAlloced = 1;
  173. }
  174. }
  175. #endif
  176. else {
  177. WOLFSSL_ERROR_MSG("No data read from bio");
  178. *memAlloced = 0;
  179. ret = NOT_COMPILED_IN;
  180. }
  181. if (ret >= 0) {
  182. *dataSz = ret;
  183. ret = 0;
  184. }
  185. return ret;
  186. }
  187. #endif /* !NO_BIO */
  188. #endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */
  189. #if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \
  190. (!defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
  191. !defined(WOLFSSL_NO_CLIENT_AUTH)))) && !defined(WOLFCRYPT_ONLY) && \
  192. !defined(NO_FILESYSTEM)
  193. /* Read all the data from a file.
  194. *
  195. * @param [in] fp File pointer to read with.
  196. * @param [out] fileSz Amount of data remaining in file in bytes.
  197. * @return WOLFSSL_BAD_FILE on error.
  198. * @return 0 on success.
  199. */
  200. static int wolfssl_file_len(XFILE fp, long* fileSz)
  201. {
  202. int ret = 0;
  203. long sz = 0;
  204. long curr = 0;
  205. if (fp == XBADFILE) {
  206. ret = WOLFSSL_BAD_FILE;
  207. }
  208. if (ret == 0) {
  209. /* Get file offset at end of file. */
  210. curr = (long)XFTELL(fp);
  211. if (curr < 0) {
  212. ret = WOLFSSL_BAD_FILE;
  213. }
  214. }
  215. /* Move to end of file. */
  216. if ((ret == 0) && (XFSEEK(fp, 0, SEEK_END) != 0)) {
  217. ret = WOLFSSL_BAD_FILE;
  218. }
  219. if (ret == 0) {
  220. /* Get file offset at end of file and subtract current offset. */
  221. sz = (long)XFTELL(fp) - curr;
  222. if (sz < 0) {
  223. ret = WOLFSSL_BAD_FILE;
  224. }
  225. }
  226. /* Go back to original offset in file. */
  227. if ((ret == 0) && (XFSEEK(fp, curr, SEEK_SET) != 0)) {
  228. ret = WOLFSSL_BAD_FILE;
  229. }
  230. /* Validate size. */
  231. if ((ret == 0) && ((sz > MAX_WOLFSSL_FILE_SIZE) || (sz <= 0L))) {
  232. ret = WOLFSSL_BAD_FILE;
  233. }
  234. if (ret == 0) {
  235. *fileSz = sz;
  236. }
  237. return ret;
  238. }
  239. #endif
  240. #if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE)) && \
  241. !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
  242. /* Read all the data from a file.
  243. *
  244. * @param [in] fp File pointer to read with.
  245. * @param [out] data Read data in an allocated buffer.
  246. * @param [out] dataSz Amount of data read in bytes.
  247. * @return WOLFSSL_BAD_FILE when reading fails.
  248. * @return MEMORY_E when memory allocation fails.
  249. * @return 0 on success.
  250. */
  251. static int wolfssl_read_file(XFILE fp, char** data, int* dataSz)
  252. {
  253. int ret = 0;
  254. long sz = 0;
  255. char* mem = NULL;
  256. ret = wolfssl_file_len(fp, &sz);
  257. if (ret == 0) {
  258. /* Allocate memory big enough to hold whole file. */
  259. mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  260. if (mem == NULL) {
  261. ret = MEMORY_E;
  262. }
  263. }
  264. /* Read whole file into new buffer. */
  265. if ((ret == 0) && ((int)XFREAD(mem, 1, (size_t)sz, fp) != sz)) {
  266. ret = WOLFSSL_BAD_FILE;
  267. }
  268. if (ret == 0) {
  269. *dataSz = (int)sz;
  270. *data = mem;
  271. mem = NULL;
  272. }
  273. XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  274. return ret;
  275. }
  276. #endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY &&
  277. * !NO_FILESYSTEM */
  278. #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
  279. #ifdef WOLFSSL_SMALL_STACK
  280. /* Buffer and size with no stack buffer. */
  281. typedef struct {
  282. /* Dynamically allocated buffer. */
  283. byte* buffer;
  284. /* Size of buffer in bytes. */
  285. word32 sz;
  286. } StaticBuffer;
  287. /* Initialize static buffer.
  288. *
  289. * @param [in, out] sb Static buffer.
  290. */
  291. static void static_buffer_init(StaticBuffer* sb)
  292. {
  293. sb->buffer = NULL;
  294. sb->sz = 0;
  295. }
  296. /* Set the size of the buffer.
  297. *
  298. * Can only set size once.
  299. *
  300. * @param [in] sb Static buffer.
  301. * @param [in] len Length required.
  302. * @param [in] heap Dynamic memory allocation hint.
  303. * @param [in] type Type of dynamic memory.
  304. * @return 0 on success.
  305. * @return MEMORY_E when dynamic memory allocation fails.
  306. */
  307. static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
  308. int type)
  309. {
  310. int ret = 0;
  311. (void)heap;
  312. (void)type;
  313. sb->buffer = (byte*)XMALLOC(len, heap, type);
  314. if (sb->buffer == NULL) {
  315. ret = MEMORY_E;
  316. }
  317. else {
  318. sb->sz = len;
  319. }
  320. return ret;
  321. }
  322. /* Dispose of dynamically allocated buffer.
  323. *
  324. * @param [in] sb Static buffer.
  325. * @param [in] heap Dynamic memory allocation hint.
  326. * @param [in] type Type of dynamic memory.
  327. */
  328. static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
  329. {
  330. (void)heap;
  331. (void)type;
  332. XFREE(sb->buffer, heap, type);
  333. }
  334. #else
  335. /* Buffer and size with stack buffer set and option to dynamically allocate. */
  336. typedef struct {
  337. /* Stack or heap buffer. */
  338. byte* buffer;
  339. /* Size of buffer in bytes. */
  340. word32 sz;
  341. /* Indicates whether the buffer was dynamically allocated. */
  342. int dyn;
  343. } StaticBuffer;
  344. /* Initialize static buffer.
  345. *
  346. * @param [in, out] sb Static buffer.
  347. * @param [in] stackBuffer Buffer allocated on the stack.
  348. * @param [in] len Length of stack buffer.
  349. */
  350. static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len)
  351. {
  352. sb->buffer = stackBuffer;
  353. sb->sz = len;
  354. sb->dyn = 0;
  355. }
  356. /* Set the size of the buffer.
  357. *
  358. * Pre: Buffer on the stack set with its size.
  359. * Can only set size once.
  360. *
  361. * @param [in] sb Static buffer.
  362. * @param [in] len Length required.
  363. * @param [in] heap Dynamic memory allocation hint.
  364. * @param [in] type Type of dynamic memory.
  365. * @return 0 on success.
  366. * @return MEMORY_E when dynamic memory allocation fails.
  367. */
  368. static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap,
  369. int type)
  370. {
  371. int ret = 0;
  372. (void)heap;
  373. (void)type;
  374. if (len > sb->sz) {
  375. byte* buff = (byte*)XMALLOC(len, heap, type);
  376. if (buff == NULL) {
  377. ret = MEMORY_E;
  378. }
  379. else {
  380. sb->buffer = buff;
  381. sb->sz = len;
  382. sb->dyn = 1;
  383. }
  384. }
  385. return ret;
  386. }
  387. /* Dispose of dynamically allocated buffer.
  388. *
  389. * @param [in] sb Static buffer.
  390. * @param [in] heap Dynamic memory allocation hint.
  391. * @param [in] type Type of dynamic memory.
  392. */
  393. static void static_buffer_free(StaticBuffer* sb, void* heap, int type)
  394. {
  395. (void)heap;
  396. (void)type;
  397. if (sb->dyn) {
  398. XFREE(sb->buffer, heap, type);
  399. }
  400. }
  401. #endif /* WOLFSSL_SMALL_STACK */
  402. #ifndef NO_FILESYSTEM
  403. /* Read all the data from a file into content.
  404. *
  405. * @param [in] fname File pointer to read with.
  406. * @param [in, out] content Read data in an allocated buffer.
  407. * @param [in] heap Dynamic memory allocation hint.
  408. * @param [in] type Type of dynamic memory.
  409. * @param [out] size Amount of data read in bytes.
  410. * @return 0 on success.
  411. * @return WOLFSSL_BAD_FILE when reading fails.
  412. * @return MEMORY_E when memory allocation fails.
  413. */
  414. static int wolfssl_read_file_static(const char* fname, StaticBuffer* content,
  415. void* heap, int type, long* size)
  416. {
  417. int ret = 0;
  418. XFILE file = XBADFILE;
  419. long sz = 0;
  420. /* Check filename is usable. */
  421. if (fname == NULL) {
  422. ret = WOLFSSL_BAD_FILE;
  423. }
  424. /* Open file for reading. */
  425. if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
  426. ret = WOLFSSL_BAD_FILE;
  427. }
  428. if (ret == 0) {
  429. /* Get length of file. */
  430. ret = wolfssl_file_len(file, &sz);
  431. }
  432. if (ret == 0) {
  433. /* Set the buffer to be big enough to hold all data. */
  434. ret = static_buffer_set_size(content, (word32)sz, heap, type);
  435. }
  436. /* Read data from file. */
  437. if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, sz, file) !=
  438. (size_t)sz)) {
  439. ret = WOLFSSL_BAD_FILE;
  440. }
  441. /* Close file if opened. */
  442. if (file != XBADFILE) {
  443. XFCLOSE(file);
  444. }
  445. /* Return size read. */
  446. *size = sz;
  447. return ret;
  448. }
  449. #endif /* !NO_FILESYSTEM */
  450. #endif /* !WOLFCRYPT_ONLY && !NO_CERTS */
  451. #endif /* !WOLFSSL_SSL_MISC_INCLUDED */