diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 5b43d32b6..9207a4f42 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -471,6 +471,42 @@ struct mbedtls_ssl_transform
 #endif
 };
 
+/*
+ * Internal representation of record frames
+ *
+ * The header layout is chosen to facilitate the computation of
+ * authentication tags which often use the header bytes laid out
+ * exactly as in the struct; note that it does not match what's
+ * transferred on the wire.
+ *
+ * Instances come in two flavors:
+ * (1) Encrypted
+ *     These always have data_offset = 0
+ * (2) Unencrypted
+ *     These have data_offset set to the length of the
+ *     fixed part of the IV used for encryption.
+ *
+ * The reason for the data_offset in the unencrypted case
+ * is to allow for in-place conversion of an unencrypted to
+ * an encrypted record. If the offset wasn't included, the
+ * encrypted content would need to be shifted afterwards to
+ * make space for the fixed IV.
+ *
+ */
+typedef struct
+{
+    uint8_t ctr[8];         /*!< Record sequence number        */
+    uint8_t type;           /*!< Record type                   */
+    uint8_t ver[2];         /*!< SSL/TLS version               */
+    uint8_t len[2];         /*!< Content length, little endian */
+
+    unsigned char *buf;     /*!< Memory buffer enclosing the record content */
+    size_t buf_len;         /*!< Buffer length */
+    size_t data_offset;     /*!< Offset of record content */
+    size_t data_len;        /*!< Length of record content */
+
+} mbedtls_record;
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /*
  * List of certificate + private key pairs