tls_multib.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "../../ssl_local.h"
  10. #include "../record_local.h"
  11. #include "recmethod_local.h"
  12. #if defined(OPENSSL_SMALL_FOOTPRINT) \
  13. || !(defined(AES_ASM) && (defined(__x86_64) \
  14. || defined(__x86_64__) \
  15. || defined(_M_AMD64) \
  16. || defined(_M_X64)))
  17. # undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
  18. # define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
  19. #endif
  20. static int tls_is_multiblock_capable(OSSL_RECORD_LAYER *rl, uint8_t type,
  21. size_t len, size_t fraglen)
  22. {
  23. #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
  24. if (type == SSL3_RT_APPLICATION_DATA
  25. && len >= 4 * fraglen
  26. && rl->compctx == NULL
  27. && rl->msg_callback == NULL
  28. && !rl->use_etm
  29. && RLAYER_USE_EXPLICIT_IV(rl)
  30. && !BIO_get_ktls_send(rl->bio)
  31. && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(rl->enc_ctx))
  32. & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0)
  33. return 1;
  34. #endif
  35. return 0;
  36. }
  37. size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, uint8_t type,
  38. size_t len, size_t maxfrag,
  39. size_t *preffrag)
  40. {
  41. if (tls_is_multiblock_capable(rl, type, len, *preffrag)) {
  42. /* minimize address aliasing conflicts */
  43. if ((*preffrag & 0xfff) == 0)
  44. *preffrag -= 512;
  45. if (len >= 8 * (*preffrag))
  46. return 8;
  47. return 4;
  48. }
  49. return tls_get_max_records_default(rl, type, len, maxfrag, preffrag);
  50. }
  51. /*
  52. * Write records using the multiblock method.
  53. *
  54. * Returns 1 on success, 0 if multiblock isn't suitable (non-fatal error), or
  55. * -1 on fatal error.
  56. */
  57. static int tls_write_records_multiblock_int(OSSL_RECORD_LAYER *rl,
  58. OSSL_RECORD_TEMPLATE *templates,
  59. size_t numtempl)
  60. {
  61. #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
  62. size_t i;
  63. size_t totlen;
  64. TLS_BUFFER *wb;
  65. unsigned char aad[13];
  66. EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
  67. size_t packlen;
  68. int packleni;
  69. if (numtempl != 4 && numtempl != 8)
  70. return 0;
  71. /*
  72. * Check templates have contiguous buffers and are all the same type and
  73. * length
  74. */
  75. for (i = 1; i < numtempl; i++) {
  76. if (templates[i - 1].type != templates[i].type
  77. || templates[i - 1].buflen != templates[i].buflen
  78. || templates[i - 1].buf + templates[i - 1].buflen
  79. != templates[i].buf)
  80. return 0;
  81. }
  82. totlen = templates[0].buflen * numtempl;
  83. if (!tls_is_multiblock_capable(rl, templates[0].type, totlen,
  84. templates[0].buflen))
  85. return 0;
  86. /*
  87. * If we get this far, then multiblock is suitable
  88. * Depending on platform multi-block can deliver several *times*
  89. * better performance. Downside is that it has to allocate
  90. * jumbo buffer to accommodate up to 8 records, but the
  91. * compromise is considered worthy.
  92. */
  93. /*
  94. * Allocate jumbo buffer. This will get freed next time we do a non
  95. * multiblock write in the call to tls_setup_write_buffer() - the different
  96. * buffer sizes will be spotted and the buffer reallocated.
  97. */
  98. packlen = EVP_CIPHER_CTX_ctrl(rl->enc_ctx,
  99. EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
  100. (int)templates[0].buflen, NULL);
  101. packlen *= numtempl;
  102. if (!tls_setup_write_buffer(rl, 1, packlen, packlen)) {
  103. /* RLAYERfatal() already called */
  104. return -1;
  105. }
  106. wb = &rl->wbuf[0];
  107. mb_param.interleave = numtempl;
  108. memcpy(aad, rl->sequence, 8);
  109. aad[8] = templates[0].type;
  110. aad[9] = (unsigned char)(templates[0].version >> 8);
  111. aad[10] = (unsigned char)(templates[0].version);
  112. aad[11] = 0;
  113. aad[12] = 0;
  114. mb_param.out = NULL;
  115. mb_param.inp = aad;
  116. mb_param.len = totlen;
  117. packleni = EVP_CIPHER_CTX_ctrl(rl->enc_ctx,
  118. EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
  119. sizeof(mb_param), &mb_param);
  120. packlen = (size_t)packleni;
  121. if (packleni <= 0 || packlen > wb->len) { /* never happens */
  122. RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
  123. return -1;
  124. }
  125. mb_param.out = wb->buf;
  126. mb_param.inp = templates[0].buf;
  127. mb_param.len = totlen;
  128. if (EVP_CIPHER_CTX_ctrl(rl->enc_ctx,
  129. EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
  130. sizeof(mb_param), &mb_param) <= 0) {
  131. RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
  132. return -1;
  133. }
  134. rl->sequence[7] += mb_param.interleave;
  135. if (rl->sequence[7] < mb_param.interleave) {
  136. int j = 6;
  137. while (j >= 0 && (++rl->sequence[j--]) == 0) ;
  138. }
  139. wb->offset = 0;
  140. wb->left = packlen;
  141. return 1;
  142. #else /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
  143. return 0;
  144. #endif
  145. }
  146. int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl,
  147. OSSL_RECORD_TEMPLATE *templates,
  148. size_t numtempl)
  149. {
  150. int ret;
  151. ret = tls_write_records_multiblock_int(rl, templates, numtempl);
  152. if (ret < 0) {
  153. /* RLAYERfatal already called */
  154. return 0;
  155. }
  156. if (ret == 0) {
  157. /* Multiblock wasn't suitable so just do a standard write */
  158. if (!tls_write_records_default(rl, templates, numtempl)) {
  159. /* RLAYERfatal already called */
  160. return 0;
  161. }
  162. }
  163. return 1;
  164. }