1 /********************************************************************** 2 Copyright(c) 2011-2024 Intel Corporation All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions 6 are met: 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in 11 the documentation and/or other materials provided with the 12 distribution. 13 * Neither the name of Intel Corporation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 **********************************************************************/ 29 30 #ifndef _MD5_MB_H_ 31 #define _MD5_MB_H_ 32 33 /** 34 * @file md5_mb.h 35 * @brief Multi-buffer CTX API MD5 function prototypes and structures 36 * @warning: MD5 is considered unsafe, so it is recommended to use SHA256 instead. 37 * 38 * Interface for multi-buffer MD5 functions 39 * 40 * <b> Multi-buffer MD5 Entire or First-Update..Update-Last </b> 41 * 42 * The interface to this multi-buffer hashing code is carried out through the 43 * context-level (CTX) init, submit and flush functions and the ISAL_MD5_HASH_CTX_MGR and 44 * ISAL_MD5_HASH_CTX objects. Numerous ISAL_MD5_HASH_CTX objects may be instantiated by the 45 * application for use with a single ISAL_MD5_HASH_CTX_MGR. 46 * 47 * The CTX interface functions carry out the initialization and padding of the jobs 48 * entered by the user and add them to the multi-buffer manager. The lower level "scheduler" 49 * layer then processes the jobs in an out-of-order manner. The scheduler layer functions 50 * are internal and are not intended to be invoked directly. Jobs can be submitted 51 * to a CTX as a complete buffer to be hashed, using the ISAL_HASH_ENTIRE flag, or as partial 52 * jobs which can be started using the ISAL_HASH_FIRST flag, and later resumed or finished 53 * using the ISAL_HASH_UPDATE and ISAL_HASH_LAST flags respectively. 54 * 55 * <b>Note:</b> The submit function does not require data buffers to be block sized. 56 * 57 * The MD5 CTX interface functions are available for 4 architectures: SSE, AVX, AVX2 and 58 * AVX512. In addition, a multibinary interface is provided, which selects the appropriate 59 * architecture-specific function at runtime. 60 * 61 * <b>Usage:</b> The application creates a ISAL_MD5_HASH_CTX_MGR object and initializes it 62 * with a call to md5_ctx_mgr_init*() function, where henceforth "*" stands for the 63 * relevant suffix for each architecture; _sse, _avx, _avx2, _avx512 (or no suffix for the 64 * multibinary version). The ISAL_MD5_HASH_CTX_MGR object will be used to schedule processor 65 * resources, with up to 8 ISAL_MD5_HASH_CTX objects (or 16 in AVX2 case, 32 in AVX512 case) 66 * being processed at a time. 67 * 68 * Each ISAL_MD5_HASH_CTX must be initialized before first use by the isal_hash_ctx_init macro 69 * defined in multi_buffer.h. After initialization, the application may begin computing 70 * a hash by giving the ISAL_MD5_HASH_CTX to a ISAL_MD5_HASH_CTX_MGR using the submit functions 71 * md5_ctx_mgr_submit*() with the ISAL_HASH_FIRST flag set. When the ISAL_MD5_HASH_CTX is 72 * returned to the application (via this or a later call to md5_ctx_mgr_submit*() or 73 * md5_ctx_mgr_flush*()), the application can then re-submit it with another call to 74 * md5_ctx_mgr_submit*(), but without the ISAL_HASH_FIRST flag set. 75 * 76 * Ideally, on the last buffer for that hash, md5_ctx_mgr_submit_sse is called with 77 * ISAL_HASH_LAST, although it is also possible to submit the hash with ISAL_HASH_LAST and a zero 78 * length if necessary. When a ISAL_MD5_HASH_CTX is returned after having been submitted with 79 * ISAL_HASH_LAST, it will contain a valid hash. The ISAL_MD5_HASH_CTX can be reused immediately 80 * by submitting with ISAL_HASH_FIRST. 81 * 82 * For example, you would submit hashes with the following flags for the following numbers 83 * of buffers: 84 * <ul> 85 * <li> one buffer: ISAL_HASH_FIRST | ISAL_HASH_LAST (or, equivalently, ISAL_HASH_ENTIRE) 86 * <li> two buffers: ISAL_HASH_FIRST, ISAL_HASH_LAST 87 * <li> three buffers: ISAL_HASH_FIRST, ISAL_HASH_UPDATE, ISAL_HASH_LAST 88 * etc. 89 * </ul> 90 * 91 * The order in which MD5_CTX objects are returned is in general different from the order 92 * in which they are submitted. 93 * 94 * A few possible error conditions exist: 95 * <ul> 96 * <li> Submitting flags other than the allowed entire/first/update/last values 97 * <li> Submitting a context that is currently being managed by a ISAL_MD5_HASH_CTX_MGR. 98 * <li> Submitting a context after ISAL_HASH_LAST is used but before ISAL_HASH_FIRST is set. 99 * </ul> 100 * 101 * These error conditions are reported by returning the ISAL_MD5_HASH_CTX immediately after 102 * a submit with its error member set to a non-zero error code (defined in 103 * multi_buffer.h). No changes are made to the ISAL_MD5_HASH_CTX_MGR in the case of an 104 * error; no processing is done for other hashes. 105 * 106 */ 107 108 #include <stdint.h> 109 #include <string.h> 110 #include "multi_buffer.h" 111 #include "types.h" 112 113 #ifdef __cplusplus 114 extern "C" { 115 #endif 116 117 /* 118 * Define enums from API v2.24, so applications that were using this version 119 * will still be compiled successfully. 120 * This list does not need to be extended for new definitions. 121 */ 122 #ifndef NO_COMPAT_ISAL_CRYPTO_API_2_24 123 /***** Previous hash constants and typedefs *****/ 124 #define MD5_DIGEST_NWORDS ISAL_MD5_DIGEST_NWORDS 125 #define MD5_MAX_LANES ISAL_MD5_MAX_LANES 126 #define MD5_MIN_LANES ISAL_MD5_MIN_LANES 127 #define MD5_BLOCK_SIZE ISAL_MD5_BLOCK_SIZE 128 #define MD5_PADLENGTHFIELD_SIZE ISAL_MD5_PADLENGTHFIELD_SIZE 129 130 #define MD5_HASH_CTX ISAL_MD5_HASH_CTX 131 #define md5_digest_array isal_md5_digest_array 132 133 #define MD5_HASH_CTX_MGR ISAL_MD5_HASH_CTX_MGR 134 #define MD5_JOB ISAL_MD5_JOB 135 #define MD5_WORD_T ISAL_MD5_WORD_T 136 #define MD5_MB_ARGS_X32 ISAL_MD5_MB_ARGS_X32 137 #define MD5_LANE_DATA ISAL_MD5_LANE_DATA 138 #define MD5_MB_JOB_MGR ISAL_MD5_MB_JOB_MGR 139 #endif /* !NO_COMPAT_ISAL_CRYPTO_API_2_24 */ 140 141 // Hash Constants and Typedefs 142 #define ISAL_MD5_DIGEST_NWORDS 4 143 #define ISAL_MD5_MAX_LANES 32 144 #define ISAL_MD5_MIN_LANES 8 145 #define ISAL_MD5_BLOCK_SIZE 64 146 #define ISAL_MD5_PADLENGTHFIELD_SIZE 8 147 148 typedef uint32_t isal_md5_digest_array[ISAL_MD5_DIGEST_NWORDS][ISAL_MD5_MAX_LANES]; 149 typedef uint32_t ISAL_MD5_WORD_T; 150 151 /** @brief Scheduler layer - Holds info describing a single MD5 job for the multi-buffer manager */ 152 153 typedef struct { 154 uint8_t *buffer; //!< pointer to data buffer for this job 155 uint32_t len; //!< length of buffer for this job in blocks. 156 DECLARE_ALIGNED(uint32_t result_digest[ISAL_MD5_DIGEST_NWORDS], 64); 157 //!< Digest output (in array of little-endian double words, different than SHA's). 158 ISAL_JOB_STS status; //!< output job status 159 void *user_data; //!< pointer for user's job-related data 160 } ISAL_MD5_JOB; 161 162 /** @brief Scheduler layer - Holds arguments for submitted MD5 job */ 163 164 typedef struct { 165 isal_md5_digest_array digest; 166 uint8_t *data_ptr[ISAL_MD5_MAX_LANES]; 167 } ISAL_MD5_MB_ARGS_X32; 168 169 /** @brief Scheduler layer - Lane data */ 170 171 typedef struct { 172 ISAL_MD5_JOB *job_in_lane; 173 } ISAL_MD5_LANE_DATA; 174 175 /** @brief Scheduler layer - Holds state for multi-buffer MD5 jobs */ 176 177 typedef struct { 178 ISAL_MD5_MB_ARGS_X32 args; 179 uint32_t lens[ISAL_MD5_MAX_LANES]; 180 uint64_t unused_lanes[4]; //!< each byte or nibble is index (0...31 or 15) of unused lanes. 181 ISAL_MD5_LANE_DATA ldata[ISAL_MD5_MAX_LANES]; 182 uint32_t num_lanes_inuse; 183 } ISAL_MD5_MB_JOB_MGR; 184 185 /** @brief Context layer - Holds state for multi-buffer MD5 jobs */ 186 187 typedef struct { 188 ISAL_MD5_MB_JOB_MGR mgr; 189 } ISAL_MD5_HASH_CTX_MGR; 190 191 /** @brief Context layer - Holds info describing a single MD5 job for the multi-buffer CTX manager 192 */ 193 194 typedef struct { 195 ISAL_MD5_JOB job; // Must be at struct offset 0. 196 ISAL_HASH_CTX_STS status; //!< Context status flag 197 ISAL_HASH_CTX_ERROR error; //!< Context error flag 198 uint64_t total_length; //!< Running counter of length processed for this CTX's job 199 const void *incoming_buffer; //!< pointer to data input buffer for this CTX's job 200 uint32_t incoming_buffer_length; //!< length of buffer for this job in bytes. 201 uint8_t partial_block_buffer[ISAL_MD5_BLOCK_SIZE * 2]; //!< CTX partial blocks 202 uint32_t partial_block_buffer_length; 203 void *user_data; //!< pointer for user to keep any job-related data 204 } ISAL_MD5_HASH_CTX; 205 206 /******************** multibinary function prototypes **********************/ 207 208 /** 209 * @brief Initialize the MD5 multi-buffer manager structure. 210 * @requires SSE4.1 or AVX or AVX2 or AVX512 211 * @deprecated Please use isal_md5_ctx_mgr_init() instead. 212 * 213 * @param mgr Structure holding context level state info 214 * @returns void 215 */ 216 ISAL_DEPRECATED("Please use isal_md5_ctx_mgr_init() instead") 217 void 218 md5_ctx_mgr_init(ISAL_MD5_HASH_CTX_MGR *mgr); 219 220 /** 221 * @brief Submit a new MD5 job to the multi-buffer manager. 222 * @requires SSE4.1 or AVX or AVX2 or AVX512 223 * @deprecated Please use isal_md5_ctx_mgr_submit() instead. 224 * 225 * @param mgr Structure holding context level state info 226 * @param ctx Structure holding ctx job info 227 * @param buffer Pointer to buffer to be processed 228 * @param len Length of buffer (in bytes) to be processed 229 * @param flags Input flag specifying job type (first, update, last or entire) 230 * @returns NULL if no jobs complete or pointer to jobs structure. 231 */ 232 ISAL_DEPRECATED("Please use isal_md5_ctx_mgr_submit() instead") 233 ISAL_MD5_HASH_CTX * 234 md5_ctx_mgr_submit(ISAL_MD5_HASH_CTX_MGR *mgr, ISAL_MD5_HASH_CTX *ctx, const void *buffer, 235 uint32_t len, ISAL_HASH_CTX_FLAG flags); 236 237 /** 238 * @brief Finish all submitted MD5 jobs and return when complete. 239 * @requires SSE4.1 or AVX or AVX2 or AVX512 240 * @deprecated Please use isal_md5_ctx_mgr_submit() instead. 241 * 242 * @param mgr Structure holding context level state info 243 * @returns NULL if no jobs to complete or pointer to jobs structure. 244 */ 245 ISAL_DEPRECATED("Please use isal_md5_ctx_mgr_submit() instead") 246 ISAL_MD5_HASH_CTX * 247 md5_ctx_mgr_flush(ISAL_MD5_HASH_CTX_MGR *mgr); 248 249 /** 250 * @brief Initialize the MD5 multi-buffer manager structure. 251 * @requires SSE4.1 for x86 or ASIMD for ARM 252 * 253 * @param[in] mgr Structure holding context level state info 254 * @return Operation status 255 * @retval 0 on success 256 * @retval Non-zero \a ISAL_CRYPTO_ERR on failure 257 */ 258 int 259 isal_md5_ctx_mgr_init(ISAL_MD5_HASH_CTX_MGR *mgr); 260 261 /** 262 * @brief Submit a new MD5 job to the multi-buffer manager. 263 * @requires SSE4.1 for x86 or ASIMD for ARM 264 * 265 * @param[in] mgr Structure holding context level state info 266 * @param[in] ctx_in Pointer to structure holding input job ctx info 267 * @param[out] ctx_out Pointer address to output job ctx info. 268 * Modified to point to completed job structure or 269 * NULL if no jobs completed. 270 * @param[in] buffer Pointer to buffer to be processed 271 * @param[in] len Length of buffer (in bytes) to be processed 272 * @param[in] flags Input flag specifying job type (first, update, last or entire) 273 * @return Operation status 274 * @retval 0 on success 275 * @retval Non-zero \a ISAL_CRYPTO_ERR on failure 276 */ 277 int 278 isal_md5_ctx_mgr_submit(ISAL_MD5_HASH_CTX_MGR *mgr, ISAL_MD5_HASH_CTX *ctx_in, 279 ISAL_MD5_HASH_CTX **ctx_out, const void *buffer, const uint32_t len, 280 const ISAL_HASH_CTX_FLAG flags); 281 282 /** 283 * @brief Finish all submitted MD5 jobs and return when complete. 284 * @requires SSE4.1 for x86 or ASIMD for ARM 285 * 286 * @param[in] mgr Structure holding context level state info 287 * @param[out] ctx_out Pointer address to output job ctx info. 288 * Modified to point to completed job structure or NULL 289 * if no jobs complete. 290 * @return Operation status 291 * @retval 0 on success 292 * @retval Non-zero \a ISAL_CRYPTO_ERR on failure 293 */ 294 int 295 isal_md5_ctx_mgr_flush(ISAL_MD5_HASH_CTX_MGR *mgr, ISAL_MD5_HASH_CTX **ctx_out); 296 #ifdef __cplusplus 297 } 298 #endif 299 300 #endif // _MD5_MB_H_ 301