diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 44aaba3060..06b4d26e9a 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -701,7 +701,7 @@ UT_046: UT_047: extends: .unit_test_esp32s2_template - parallel: 7 + parallel: 8 tags: - ESP32S2_IDF - UT_T1_1 diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/port/include/sha1_alt.h index f97c0e49b8..ce6391445c 100644 --- a/components/mbedtls/port/include/sha1_alt.h +++ b/components/mbedtls/port/include/sha1_alt.h @@ -50,6 +50,24 @@ typedef struct { esp_mbedtls_sha1_mode mode; } mbedtls_sha1_context; +/** + * \brief Set the SHA-1 mode for a mbedtls_sha1_context. + * + * \param ctx The SHA-1 context structure. + * \param mode The SHA-1 mode to be set. It can be one of the following: + * - ESP_MBEDTLS_SHA1_UNUSED: Indicates that the first block hasn't been processed yet. + * - ESP_MBEDTLS_SHA1_HARDWARE: Specifies the use of hardware SHA engine for SHA-1 calculations. + * - ESP_MBEDTLS_SHA1_SOFTWARE: Specifies the use of software-based SHA-1 calculations. + * + * \return None. + */ +static inline void esp_mbedtls_set_sha1_mode(mbedtls_sha1_context *ctx, esp_mbedtls_sha1_mode mode) +{ + if (ctx) { + ctx->mode = mode; + } +} + #elif SOC_SHA_SUPPORT_DMA typedef enum { diff --git a/components/mbedtls/port/sha/dma/esp_sha1.c b/components/mbedtls/port/sha/dma/esp_sha1.c index 91b011f386..d6082bf449 100644 --- a/components/mbedtls/port/sha/dma/esp_sha1.c +++ b/components/mbedtls/port/sha/dma/esp_sha1.c @@ -110,6 +110,17 @@ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) } #endif +static void esp_internal_sha_update_state(mbedtls_sha1_context *ctx) +{ + if (ctx->sha_state == ESP_SHA1_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA1_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA1_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + static int esp_internal_sha1_dma_process(mbedtls_sha1_context *ctx, const uint8_t *data, size_t len, uint8_t *buf, size_t buf_len) @@ -119,9 +130,17 @@ static int esp_internal_sha1_dma_process(mbedtls_sha1_context *ctx, int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { - int ret; + int ret = -1; esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); esp_sha_release_hardware(); return ret; } @@ -136,7 +155,6 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) { - int ret; size_t fill; uint32_t left, len, local_len = 0; @@ -167,25 +185,19 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *inp if ( len || local_len) { esp_sha_acquire_hardware(); - if (ctx->sha_state == ESP_SHA1_STATE_INIT) { - ctx->first_block = true; - ctx->sha_state = ESP_SHA1_STATE_IN_PROCESS; - } else if (ctx->sha_state == ESP_SHA1_STATE_IN_PROCESS) { - ctx->first_block = false; - esp_sha_write_digest_state(SHA1, ctx->state); + esp_internal_sha_update_state(ctx); + + int ret = esp_internal_sha1_dma_process(ctx, input, len, ctx->buffer, local_len); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; } - ret = esp_internal_sha1_dma_process(ctx, input, len, ctx->buffer, local_len); - esp_sha_read_digest_state(SHA1, ctx->state); esp_sha_release_hardware(); - if (ret != 0) { - return ret; - } - } if ( ilen > 0 ) { @@ -216,7 +228,7 @@ static const unsigned char sha1_padding[64] = { */ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ) { - int ret; + int ret = -1; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; diff --git a/components/mbedtls/port/sha/dma/esp_sha256.c b/components/mbedtls/port/sha/dma/esp_sha256.c index 307b338498..12bf5223ae 100644 --- a/components/mbedtls/port/sha/dma/esp_sha256.c +++ b/components/mbedtls/port/sha/dma/esp_sha256.c @@ -125,11 +125,30 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, #endif +static void esp_internal_sha_update_state(mbedtls_sha256_context *ctx) +{ + if (ctx->sha_state == ESP_SHA256_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) { - int ret; + int ret = -1; esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); esp_sha_release_hardware(); return ret; @@ -149,7 +168,6 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ) { - int ret = 0; size_t fill; uint32_t left, len, local_len = 0; @@ -181,24 +199,18 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char if ( len || local_len) { esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); - if (ctx->sha_state == ESP_SHA256_STATE_INIT) { - ctx->first_block = true; - ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS; - } else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) { - ctx->first_block = false; - esp_sha_write_digest_state(ctx->mode, ctx->state); + int ret = esp_sha_dma(ctx->mode, input, len, ctx->buffer, local_len, ctx->first_block); + + if (ret != 0) { + esp_sha_release_hardware(); + return ret; } - ret = esp_sha_dma(ctx->mode, input, len, ctx->buffer, local_len, ctx->first_block); - esp_sha_read_digest_state(ctx->mode, ctx->state); esp_sha_release_hardware(); - - if (ret != 0) { - return ret; - } } if ( ilen > 0 ) { @@ -229,7 +241,7 @@ static const unsigned char sha256_padding[64] = { */ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ) { - int ret; + int ret = -1; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; diff --git a/components/mbedtls/port/sha/dma/esp_sha512.c b/components/mbedtls/port/sha/dma/esp_sha512.c index fa4465d0f8..b8d5eda119 100644 --- a/components/mbedtls/port/sha/dma/esp_sha512.c +++ b/components/mbedtls/port/sha/dma/esp_sha512.c @@ -146,6 +146,26 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, } #endif +static int esp_internal_sha_update_state(mbedtls_sha512_context *ctx) +{ + if (ctx->sha_state == ESP_SHA512_STATE_INIT) { + if (ctx->mode == SHA2_512T) { + int ret = -1; + if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) { + return ret; + } + ctx->first_block = false; + } else { + ctx->first_block = true; + } + ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } + return 0; +} + static int esp_internal_sha512_dma_process(mbedtls_sha512_context *ctx, const uint8_t *data, size_t len, uint8_t *buf, size_t buf_len) @@ -159,9 +179,22 @@ static int esp_internal_sha512_dma_process(mbedtls_sha512_context *ctx, int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) { - int ret; + int ret = -1; esp_sha_acquire_hardware(); + + ret = esp_internal_sha_update_state(ctx); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + ret = esp_internal_sha512_dma_process(ctx, data, 128, 0, 0); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); esp_sha_release_hardware(); return ret; @@ -182,7 +215,6 @@ void mbedtls_sha512_process( mbedtls_sha512_context *ctx, int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen ) { - int ret; size_t fill; unsigned int left, len, local_len = 0; @@ -214,31 +246,24 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char esp_sha_acquire_hardware(); - if (ctx->sha_state == ESP_SHA512_STATE_INIT) { + int ret = esp_internal_sha_update_state(ctx); - if (ctx->mode == SHA2_512T) { - esp_sha_512_t_init_hash(ctx->t_val); - ctx->first_block = false; - } else { - ctx->first_block = true; - } - ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS; - - } else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) { - ctx->first_block = false; - esp_sha_write_digest_state(ctx->mode, ctx->state); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; } ret = esp_internal_sha512_dma_process(ctx, input, len, ctx->buffer, local_len); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + esp_sha_read_digest_state(ctx->mode, ctx->state); esp_sha_release_hardware(); - if (ret != 0) { - return ret; - } - } @@ -275,7 +300,7 @@ static const unsigned char sha512_padding[128] = { */ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ) { - int ret; + int ret = -1; size_t last, padn; uint64_t high, low; unsigned char msglen[16]; diff --git a/components/mbedtls/port/sha/parallel_engine/esp_sha1.c b/components/mbedtls/port/sha/parallel_engine/esp_sha1.c index 4700daf553..edd9211c5f 100644 --- a/components/mbedtls/port/sha/parallel_engine/esp_sha1.c +++ b/components/mbedtls/port/sha/parallel_engine/esp_sha1.c @@ -142,39 +142,6 @@ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) } #endif -static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); - -int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) -{ - bool first_block = false; - if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) { - /* try to use hardware for this digest */ - if (esp_sha_try_lock_engine(SHA1)) { - ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE; - first_block = true; - } else { - ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; - } - } - - if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { - esp_sha_block(SHA1, data, first_block); - } else { - mbedtls_sha1_software_process(ctx, data); - } - - return 0; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, - const unsigned char data[64] ) -{ - mbedtls_internal_sha1_process( ctx, data ); -} -#endif - - static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { uint32_t temp, W[16], A, B, C, D, E; @@ -331,12 +298,46 @@ static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsi ctx->state[4] += E; } + +static int esp_internal_sha1_parallel_engine_process( mbedtls_sha1_context *ctx, const unsigned char data[64], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(SHA1)) { + ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_block(SHA1, data, first_block); + if (read_digest) { + esp_sha_read_digest_state(SHA1, ctx->state); + } + } else { + mbedtls_sha1_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + return esp_internal_sha1_parallel_engine_process(ctx, data, true); +} + + /* * SHA-1 process buffer */ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) { - int ret; + int ret = -1; size_t fill; uint32_t left; @@ -357,7 +358,7 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *inp if ( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - if ( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) { + if ( ( ret = esp_internal_sha1_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { return ret; } @@ -367,7 +368,7 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *inp } while ( ilen >= 64 ) { - if ( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) { + if ( ( ret = esp_internal_sha1_parallel_engine_process( ctx, input, false ) ) != 0 ) { return ret; } @@ -375,6 +376,10 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *inp ilen -= 64; } + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_read_digest_state(SHA1, ctx->state); + } + if ( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), input, ilen ); } @@ -403,7 +408,7 @@ static const unsigned char sha1_padding[64] = { */ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ) { - int ret; + int ret = -1; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; diff --git a/components/mbedtls/port/sha/parallel_engine/esp_sha256.c b/components/mbedtls/port/sha/parallel_engine/esp_sha256.c index c29ffebb7d..5043f8b8ce 100644 --- a/components/mbedtls/port/sha/parallel_engine/esp_sha256.c +++ b/components/mbedtls/port/sha/parallel_engine/esp_sha256.c @@ -203,30 +203,6 @@ static const uint32_t K[] = { d += temp1; h = temp1 + temp2; \ } -static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); - -int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) -{ - bool first_block = false; - - if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) { - /* try to use hardware for this digest */ - if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) { - ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE; - first_block = true; - } else { - ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; - } - } - - if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { - esp_sha_block(SHA2_256, data, first_block); - } else { - mbedtls_sha256_software_process(ctx, data); - } - - return 0; -} #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_sha256_process( mbedtls_sha256_context *ctx, @@ -292,13 +268,47 @@ static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const } } + +static int esp_internal_sha256_parallel_engine_process( mbedtls_sha256_context *ctx, const unsigned char data[64], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) { + /* try to use hardware for this digest */ + if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) { + ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_block(SHA2_256, data, first_block); + if (read_digest) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + } + } else { + mbedtls_sha256_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + return esp_internal_sha256_parallel_engine_process(ctx, data, true); +} + + /* * SHA-256 process buffer */ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ) { - int ret; + int ret = -1; size_t fill; uint32_t left; @@ -319,7 +329,7 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char if ( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - if ( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) { + if ( ( ret = esp_internal_sha256_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { return ret; } @@ -329,7 +339,7 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char } while ( ilen >= 64 ) { - if ( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) { + if ( ( ret = esp_internal_sha256_parallel_engine_process( ctx, input, false ) ) != 0 ) { return ret; } @@ -337,6 +347,10 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char ilen -= 64; } + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + } + if ( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), input, ilen ); } @@ -365,7 +379,7 @@ static const unsigned char sha256_padding[64] = { */ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ) { - int ret; + int ret = -1; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; diff --git a/components/mbedtls/port/sha/parallel_engine/esp_sha512.c b/components/mbedtls/port/sha/parallel_engine/esp_sha512.c index fd9c354d15..e13eddda42 100644 --- a/components/mbedtls/port/sha/parallel_engine/esp_sha512.c +++ b/components/mbedtls/port/sha/parallel_engine/esp_sha512.c @@ -230,30 +230,6 @@ static const uint64_t K[80] = { UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) }; -static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); - -int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) -{ - bool first_block = false; - - if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) { - /* try to use hardware for this digest */ - if (esp_sha_try_lock_engine(sha_type(ctx))) { - ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE; - first_block = true; - } else { - ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; - } - } - - if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { - esp_sha_block(sha_type(ctx), data, first_block); - } else { - mbedtls_sha512_software_process(ctx, data); - } - - return 0; -} #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_sha512_process( mbedtls_sha512_context *ctx, @@ -329,13 +305,47 @@ static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const ctx->state[7] += H; } + +static int esp_internal_sha512_parallel_engine_process( mbedtls_sha512_context *ctx, const unsigned char data[128], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(sha_type(ctx))) { + ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_block(sha_type(ctx), data, first_block); + if (read_digest) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + } + } else { + mbedtls_sha512_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + return esp_internal_sha512_parallel_engine_process(ctx, data, true); +} + + /* * SHA-512 process buffer */ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen ) { - int ret; + int ret = -1; size_t fill; unsigned int left; @@ -354,7 +364,7 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char if ( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - if ( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) { + if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { return ret; } @@ -364,7 +374,7 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char } while ( ilen >= 128 ) { - if ( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) { + if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, input, false ) ) != 0 ) { return ret; } @@ -372,6 +382,10 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char ilen -= 128; } + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + } + if ( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), input, ilen ); } @@ -405,7 +419,7 @@ static const unsigned char sha512_padding[128] = { */ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ) { - int ret; + int ret = -1; size_t last, padn; uint64_t high, low; unsigned char msglen[16]; diff --git a/components/mbedtls/test/test_sha.c b/components/mbedtls/test/test_sha.c index 063cdcf0a6..df157344d9 100644 --- a/components/mbedtls/test/test_sha.c +++ b/components/mbedtls/test/test_sha.c @@ -142,3 +142,92 @@ TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]") TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_espsha, sha512_mbedtls, sizeof(sha512_espsha), "SHA512 results should match"); #endif } + +#if CONFIG_MBEDTLS_HARDWARE_SHA + +TEST_CASE("Test mbedtls_internal_sha_process()", "[hw_crypto]") +{ + const size_t BUFFER_SZ = 128; + int ret; + unsigned char output[64] = { 0 }; + void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buffer); + memset(buffer, 0xEE, BUFFER_SZ); + + mbedtls_sha1_context sha1_ctx; + + const uint8_t sha1_expected[20] = { 0x41, 0x63, 0x12, 0x5b, 0x9c, 0x68, 0x85, 0xc8, + 0x01, 0x40, 0xf4, 0x03, 0x5d, 0x0d, 0x84, 0x0e, + 0xa4, 0xae, 0x4d, 0xe9 }; + + mbedtls_sha1_init(&sha1_ctx); + ret = mbedtls_sha1_starts_ret(&sha1_ctx); + TEST_ASSERT_EQUAL(0, ret); + + ret = mbedtls_internal_sha1_process(&sha1_ctx, buffer); + TEST_ASSERT_EQUAL(0, ret); + + ret = mbedtls_internal_sha1_process(&sha1_ctx, buffer); + TEST_ASSERT_EQUAL(0, ret); + +#if SOC_SHA_ENDIANNESS_BE + for (int i = 0; i < sizeof(sha1_ctx.state)/sizeof(sha1_ctx.state[0]); i++) + { + *(uint32_t *)(output + i*4) = __builtin_bswap32(sha1_ctx.state[i]); + } +#else + memcpy(output, sha1_ctx.state, 20); +#endif + + // Check if the intermediate states are correct + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, output, sizeof(sha1_expected)); + + ret = mbedtls_sha1_finish_ret(&sha1_ctx, output); + TEST_ASSERT_EQUAL(0, ret); + + mbedtls_sha1_free(&sha1_ctx); + +#if SOC_SHA_SUPPORT_SHA512 + mbedtls_sha512_context sha512_ctx; + + const uint8_t sha512_expected[64] = { 0x3c, 0x77, 0x5f, 0xb0, 0x3b, 0x25, 0x8d, 0x3b, + 0xa9, 0x28, 0xa2, 0x29, 0xf2, 0x14, 0x7d, 0xb3, + 0x64, 0x1e, 0x76, 0xd5, 0x0b, 0xbc, 0xdf, 0xb4, + 0x75, 0x1d, 0xe7, 0x7f, 0x62, 0x83, 0xdd, 0x78, + 0x6b, 0x0e, 0xa4, 0xd2, 0xbe, 0x51, 0x56, 0xd4, + 0xfe, 0x3b, 0xa3, 0x3a, 0xd7, 0xf6, 0xd3, 0xb3, + 0xe7, 0x9d, 0xb5, 0xe6, 0x76, 0x35, 0x2a, 0xae, + 0x07, 0x0a, 0x3a, 0x03, 0x44, 0xf0, 0xb8, 0xfe }; + + mbedtls_sha512_init(&sha512_ctx); + ret = mbedtls_sha512_starts_ret(&sha512_ctx, 0); + TEST_ASSERT_EQUAL(0, ret); + + ret = mbedtls_internal_sha512_process(&sha512_ctx, buffer); + TEST_ASSERT_EQUAL(0, ret); + + ret = mbedtls_internal_sha512_process(&sha512_ctx, buffer); + TEST_ASSERT_EQUAL(0, ret); + +#if SOC_SHA_ENDIANNESS_BE + for (int i = 0; i < sizeof(sha512_ctx.state)/sizeof(sha512_ctx.state[0]); i++) + { + *(uint64_t *)(output + i*8) = __builtin_bswap64(sha512_ctx.state[i]); + } +#else + memcpy(output, sha512_ctx.state, 64); +#endif + + // Check if the intermediate states are correct + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha512_expected, output, sizeof(sha512_expected)); + + ret = mbedtls_sha512_finish_ret(&sha512_ctx, output); + TEST_ASSERT_EQUAL(0, ret); + + mbedtls_sha512_free(&sha512_ctx); + +#endif + free(buffer); + +} +#endif diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 76222b0e31..1ed022077e 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -276,6 +276,9 @@ /* ESP32 style SHA engine, where multiple states can be stored in parallel */ #define SOC_SHA_SUPPORT_PARALLEL_ENG (1) +/* ESP32's SHA peripheral processes and stores data in big-endian format */ +#define SOC_SHA_ENDIANNESS_BE (1) + /* Supported HW algorithms */ #define SOC_SHA_SUPPORT_SHA1 (1) #define SOC_SHA_SUPPORT_SHA256 (1) diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 505b89ba42..7b4c45f240 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -91,6 +91,7 @@ endif() if(CONFIG_WPA_MBEDTLS_CRYPTO) set(crypto_src + "src/crypto/fastpbkdf2.c" "src/crypto/crypto_mbedtls.c" "src/crypto/crypto_mbedtls-bignum.c" "src/crypto/crypto_mbedtls-ec.c") @@ -202,6 +203,7 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211W CONFIG_SHA256 CONFIG_WNM + CONFIG_FAST_PBKDF2 ) if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE) diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/src/crypto/crypto_mbedtls.c index cf37343cfa..544213e0a4 100644 --- a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c +++ b/components/wpa_supplicant/src/crypto/crypto_mbedtls.c @@ -37,6 +37,10 @@ #include "crypto.h" #include "mbedtls/esp_config.h" +#ifdef CONFIG_FAST_PBKDF2 +#include "fastpbkdf2.h" +#endif + static int digest_vector(mbedtls_md_type_t md_type, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { @@ -658,6 +662,12 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen) { +#ifdef CONFIG_FAST_PBKDF2 + fastpbkdf2_hmac_sha1((const u8 *) passphrase, os_strlen(passphrase), + ssid, ssid_len, iterations, buf, buflen); + return 0; +#else + mbedtls_md_context_t sha1_ctx; const mbedtls_md_info_t *info_sha1; int ret; @@ -677,7 +687,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const u8 *) passphrase, os_strlen(passphrase) , ssid, - ssid_len, iterations, 32, buf); + ssid_len, iterations, buflen, buf); if (ret != 0) { ret = -1; goto cleanup; @@ -686,6 +696,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, cleanup: mbedtls_md_free(&sha1_ctx); return ret; +#endif } #ifdef MBEDTLS_DES_C diff --git a/components/wpa_supplicant/src/crypto/fastpbkdf2.c b/components/wpa_supplicant/src/crypto/fastpbkdf2.c new file mode 100644 index 0000000000..9084eef09c --- /dev/null +++ b/components/wpa_supplicant/src/crypto/fastpbkdf2.c @@ -0,0 +1,394 @@ +/* + * SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/* + * fast-pbkdf2 - Optimal PBKDF2-HMAC calculation + * Written in 2015 by Joseph Birr-Pixton + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * . + */ +#include "utils/common.h" +#include "fastpbkdf2.h" + +#include +#include +#if defined(__GNUC__) +#include +#endif + +#include +#include "mbedtls/esp_config.h" +#include "utils/wpa_debug.h" + +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) +#ifndef MBEDTLS_PRIVATE +#define MBEDTLS_PRIVATE(member) member +#endif +#endif + +/* --- MSVC doesn't support C99 --- */ +#ifdef _MSC_VER +#define restrict +#define _Pragma __pragma +#endif + +/* --- Common useful things --- */ +#ifndef MIN +#define MIN(a, b) ((a) > (b)) ? (b) : (a) +#endif + +static inline void write32_be(uint32_t n, uint8_t out[4]) +{ +#if defined(__GNUC__) && __GNUC__ >= 4 && __BYTE_ORDER == __LITTLE_ENDIAN + *(uint32_t *)(out) = __builtin_bswap32(n); +#else + out[0] = (n >> 24) & 0xff; + out[1] = (n >> 16) & 0xff; + out[2] = (n >> 8) & 0xff; + out[3] = n & 0xff; +#endif +} + +/* Prepare block (of blocksz bytes) to contain md padding denoting a msg-size + * message (in bytes). block has a prefix of used bytes. + * + * Message length is expressed in 32 bits (so suitable for sha1, sha256, sha512). */ +static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t msg) +{ + memset(block + used, 0, blocksz - used - 4); + block[used] = 0x80; + block += blocksz - 4; + write32_be((uint32_t) (msg * 8), block); +} + +/* Internal function/type names for hash-specific things. */ +#define HMAC_CTX(_name) HMAC_ ## _name ## _ctx +#define HMAC_INIT(_name) HMAC_ ## _name ## _init +#define HMAC_UPDATE(_name) HMAC_ ## _name ## _update +#define HMAC_FINAL(_name) HMAC_ ## _name ## _final + +#define PBKDF2_F(_name) pbkdf2_f_ ## _name +#define PBKDF2(_name) pbkdf2_ ## _name + +/* This macro expands to decls for the whole implementation for a given + * hash function. Arguments are: + * + * _name like 'sha1', added to symbol names + * _blocksz block size, in bytes + * _hashsz digest output, in bytes + * _ctx hash context type + * _init hash context initialisation function + * args: (_ctx *c) + * _update hash context update function + * args: (_ctx *c, const void *data, size_t ndata) + * _final hash context finish function + * args: (_ctx *c, void *out) + * _xform hash context raw block update function + * args: (_ctx *c, const void *data) + * _xcpy hash context raw copy function (only need copy hash state) + * args: (_ctx * restrict out, const _ctx *restrict in) + * _xtract hash context state extraction + * args: args (_ctx *restrict c, uint8_t *restrict out) + * _xxor hash context xor function (only need xor hash state) + * args: (_ctx *restrict out, const _ctx *restrict in) + * + * The resulting function is named PBKDF2(_name). + */ +#define DECL_PBKDF2(_name, _blocksz, _hashsz, _ctx, \ + _init, _update, _xform, _final, _xcpy, _xtract, _xxor) \ + typedef struct { \ + _ctx inner; \ + _ctx outer; \ + } HMAC_CTX(_name); \ + \ + static inline void HMAC_INIT(_name)(HMAC_CTX(_name) *ctx, \ + const uint8_t *key, size_t nkey) \ + { \ + /* Prepare key: */ \ + uint8_t k[_blocksz]; \ + \ + /* Shorten long keys. */ \ + if (nkey > _blocksz) \ + { \ + _init(&ctx->inner); \ + _update(&ctx->inner, key, nkey); \ + _final(&ctx->inner, k); \ + \ + key = k; \ + nkey = _hashsz; \ + } \ + \ + /* Standard doesn't cover case where blocksz < hashsz. */ \ + assert(nkey <= _blocksz); \ + \ + /* Right zero-pad short keys. */ \ + if (k != key) \ + memcpy(k, key, nkey); \ + if (_blocksz > nkey) \ + memset(k + nkey, 0, _blocksz - nkey); \ + \ + /* Start inner hash computation */ \ + uint8_t blk_inner[_blocksz]; \ + uint8_t blk_outer[_blocksz]; \ + \ + for (size_t i = 0; i < _blocksz; i++) \ + { \ + blk_inner[i] = 0x36 ^ k[i]; \ + blk_outer[i] = 0x5c ^ k[i]; \ + } \ + \ + _init(&ctx->inner); \ + _update(&ctx->inner, blk_inner, sizeof blk_inner); \ + \ + /* And outer. */ \ + _init(&ctx->outer); \ + _update(&ctx->outer, blk_outer, sizeof blk_outer); \ + } \ + \ + static inline void HMAC_UPDATE(_name)(HMAC_CTX(_name) *ctx, \ + const void *data, size_t ndata) \ + { \ + _update(&ctx->inner, data, ndata); \ + } \ + \ + static inline void HMAC_FINAL(_name)(HMAC_CTX(_name) *ctx, \ + uint8_t out[_hashsz]) \ + { \ + _final(&ctx->inner, out); \ + _update(&ctx->outer, out, _hashsz); \ + _final(&ctx->outer, out); \ + } \ + \ + \ + /* --- PBKDF2 --- */ \ + static inline void PBKDF2_F(_name)(const HMAC_CTX(_name) *startctx, \ + uint32_t counter, \ + const uint8_t *salt, size_t nsalt, \ + uint32_t iterations, \ + uint8_t *out) \ + { \ + uint8_t countbuf[4]; \ + write32_be(counter, countbuf); \ + \ + /* Prepare loop-invariant padding block. */ \ + uint8_t Ublock[_blocksz]; \ + md_pad(Ublock, _blocksz, _hashsz, _blocksz + _hashsz); \ + \ + /* First iteration: \ + * U_1 = PRF(P, S || INT_32_BE(i)) \ + */ \ + HMAC_CTX(_name) ctx = *startctx; \ + HMAC_UPDATE(_name)(&ctx, salt, nsalt); \ + HMAC_UPDATE(_name)(&ctx, countbuf, sizeof countbuf); \ + HMAC_FINAL(_name)(&ctx, Ublock); \ + _ctx result = ctx.outer; \ + \ + /* Subsequent iterations: \ + * U_c = PRF(P, U_{c-1}) \ + */ \ + for (uint32_t i = 1; i < iterations; i++) \ + { \ + /* Complete inner hash with previous U */ \ + _xcpy(&ctx.inner, &startctx->inner); \ + _xform(&ctx.inner, Ublock); \ + _xtract(&ctx.inner, Ublock); \ + /* Complete outer hash with inner output */ \ + _xcpy(&ctx.outer, &startctx->outer); \ + _xform(&ctx.outer, Ublock); \ + _xtract(&ctx.outer, Ublock); \ + _xxor(&result, &ctx.outer); \ + } \ + \ + /* Reform result into output buffer. */ \ + _xtract(&result, out); \ + } \ + \ + static inline void PBKDF2(_name)(const uint8_t *pw, size_t npw, \ + const uint8_t *salt, size_t nsalt, \ + uint32_t iterations, \ + uint8_t *out, size_t nout) \ + { \ + assert(iterations); \ + assert(out && nout); \ + \ + /* Starting point for inner loop. */ \ + HMAC_CTX(_name) ctx; \ + HMAC_INIT(_name)(&ctx, pw, npw); \ + \ + /* How many blocks do we need? */ \ + uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz; \ + \ + for (uint32_t counter = 1; counter <= blocks_needed; counter++) \ + { \ + uint8_t block[_hashsz]; \ + PBKDF2_F(_name)(&ctx, counter, salt, nsalt, iterations, block); \ + \ + size_t offset = (counter - 1) * _hashsz; \ + size_t taken = MIN(nout - offset, _hashsz); \ + memcpy(out + offset, block, taken); \ + } \ + } + +static inline void sha1_extract(mbedtls_sha1_context *restrict ctx, uint8_t *restrict out) +{ +#if defined(MBEDTLS_SHA1_ALT) +#if CONFIG_IDF_TARGET_ESP32 + /* ESP32 stores internal SHA state in BE format similar to software */ + write32_be(ctx->state[0], out); + write32_be(ctx->state[1], out + 4); + write32_be(ctx->state[2], out + 8); + write32_be(ctx->state[3], out + 12); + write32_be(ctx->state[4], out + 16); +#else + *(uint32_t *)(out) = ctx->state[0]; + *(uint32_t *)(out + 4) = ctx->state[1]; + *(uint32_t *)(out + 8) = ctx->state[2]; + *(uint32_t *)(out + 12) = ctx->state[3]; + *(uint32_t *)(out + 16) = ctx->state[4]; +#endif +#else + write32_be(ctx->MBEDTLS_PRIVATE(state)[0], out); + write32_be(ctx->MBEDTLS_PRIVATE(state)[1], out + 4); + write32_be(ctx->MBEDTLS_PRIVATE(state)[2], out + 8); + write32_be(ctx->MBEDTLS_PRIVATE(state)[3], out + 12); + write32_be(ctx->MBEDTLS_PRIVATE(state)[4], out + 16); +#endif +} + +static inline void sha1_cpy(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in) +{ +#if defined(MBEDTLS_SHA1_ALT) + out->state[0] = in->state[0]; + out->state[1] = in->state[1]; + out->state[2] = in->state[2]; + out->state[3] = in->state[3]; + out->state[4] = in->state[4]; +#else + out->MBEDTLS_PRIVATE(state)[0] = in->MBEDTLS_PRIVATE(state)[0]; + out->MBEDTLS_PRIVATE(state)[1] = in->MBEDTLS_PRIVATE(state)[1]; + out->MBEDTLS_PRIVATE(state)[2] = in->MBEDTLS_PRIVATE(state)[2]; + out->MBEDTLS_PRIVATE(state)[3] = in->MBEDTLS_PRIVATE(state)[3]; + out->MBEDTLS_PRIVATE(state)[4] = in->MBEDTLS_PRIVATE(state)[4]; +#endif +} + +static inline void sha1_xor(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in) +{ +#if defined(MBEDTLS_SHA1_ALT) + out->state[0] ^= in->state[0]; + out->state[1] ^= in->state[1]; + out->state[2] ^= in->state[2]; + out->state[3] ^= in->state[3]; + out->state[4] ^= in->state[4]; +#else + out->MBEDTLS_PRIVATE(state)[0] ^= in->MBEDTLS_PRIVATE(state)[0]; + out->MBEDTLS_PRIVATE(state)[1] ^= in->MBEDTLS_PRIVATE(state)[1]; + out->MBEDTLS_PRIVATE(state)[2] ^= in->MBEDTLS_PRIVATE(state)[2]; + out->MBEDTLS_PRIVATE(state)[3] ^= in->MBEDTLS_PRIVATE(state)[3]; + out->MBEDTLS_PRIVATE(state)[4] ^= in->MBEDTLS_PRIVATE(state)[4]; +#endif +} + +static int mbedtls_sha1_init_start(mbedtls_sha1_context *ctx) +{ + mbedtls_sha1_init(ctx); + mbedtls_sha1_starts_ret(ctx); +#if defined(CONFIG_IDF_TARGET_ESP32) && defined(MBEDTLS_SHA1_ALT) + /* Use software mode for esp32 since hardware can't give output more than 20 */ + esp_mbedtls_set_sha1_mode(ctx, ESP_MBEDTLS_SHA1_SOFTWARE); +#endif + return 0; +} + +#ifndef MBEDTLS_SHA1_ALT +static int sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]) +{ + int ret = -1; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->MBEDTLS_PRIVATE(total)[0] & 0x3F; + + ctx->MBEDTLS_PRIVATE(buffer)[used++] = 0x80; + + if (used <= 56) { + /* Enough room for padding + length in current block */ + memset(ctx->MBEDTLS_PRIVATE(buffer) + used, 0, 56 - used); + } else { + /* We'll need an extra block */ + memset(ctx->MBEDTLS_PRIVATE(buffer) + used, 0, 64 - used); + + if ((ret = mbedtls_internal_sha1_process(ctx, ctx->MBEDTLS_PRIVATE(buffer))) != 0) { + goto exit; + } + + memset(ctx->MBEDTLS_PRIVATE(buffer), 0, 56); + } + + /* + * Add message length + */ + high = (ctx->MBEDTLS_PRIVATE(total)[0] >> 29) + | (ctx->MBEDTLS_PRIVATE(total)[1] << 3); + low = (ctx->MBEDTLS_PRIVATE(total)[0] << 3); + + write32_be(high, ctx->MBEDTLS_PRIVATE(buffer) + 56); + write32_be(low, ctx->MBEDTLS_PRIVATE(buffer) + 60); + + if ((ret = mbedtls_internal_sha1_process(ctx, ctx->MBEDTLS_PRIVATE(buffer))) != 0) { + goto exit; + } + + /* + * Output final state + */ + write32_be(ctx->MBEDTLS_PRIVATE(state)[0], output); + write32_be(ctx->MBEDTLS_PRIVATE(state)[1], output + 4); + write32_be(ctx->MBEDTLS_PRIVATE(state)[2], output + 8); + write32_be(ctx->MBEDTLS_PRIVATE(state)[3], output + 12); + write32_be(ctx->MBEDTLS_PRIVATE(state)[4], output + 16); + + ret = 0; + +exit: + return ret; +} +#endif + +DECL_PBKDF2(sha1, // _name + 64, // _blocksz + 20, // _hashsz + mbedtls_sha1_context, // _ctx + mbedtls_sha1_init_start, // _init + mbedtls_sha1_update_ret, // _update + mbedtls_internal_sha1_process, // _xform +#if defined(MBEDTLS_SHA1_ALT) + mbedtls_sha1_finish_ret, // _final +#else + sha1_finish, // _final +#endif + sha1_cpy, // _xcpy + sha1_extract, // _xtract + sha1_xor) // _xxor + +void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, + const uint8_t *salt, size_t nsalt, + uint32_t iterations, + uint8_t *out, size_t nout) +{ + PBKDF2(sha1)(pw, npw, salt, nsalt, iterations, out, nout); +} diff --git a/components/wpa_supplicant/src/crypto/fastpbkdf2.h b/components/wpa_supplicant/src/crypto/fastpbkdf2.h new file mode 100644 index 0000000000..60838942dd --- /dev/null +++ b/components/wpa_supplicant/src/crypto/fastpbkdf2.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton + * + * SPDX-License-Identifier: CC0-1.0 + */ + +/* + * fastpbkdf2 - Faster PBKDF2-HMAC calculation + * Written in 2015 by Joseph Birr-Pixton + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * . + */ + +#ifndef FASTPBKDF2_H +#define FASTPBKDF2_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Calculates PBKDF2-HMAC-SHA1. + * + * @p npw bytes at @p pw are the password input. + * @p nsalt bytes at @p salt are the salt input. + * @p iterations is the PBKDF2 iteration count and must be non-zero. + * @p nout bytes of output are written to @p out. @p nout must be non-zero. + * + * This function cannot fail; it does not report errors. + */ +void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, + const uint8_t *salt, size_t nsalt, + uint32_t iterations, + uint8_t *out, size_t nout); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/wpa_supplicant/test/test_fast_pbkdf2.c b/components/wpa_supplicant/test/test_fast_pbkdf2.c new file mode 100644 index 0000000000..ec08525d36 --- /dev/null +++ b/components/wpa_supplicant/test/test_fast_pbkdf2.c @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "string.h" +#include +#include "unity.h" +#include "utils/common.h" +#include "mbedtls/pkcs5.h" +#include "crypto/sha1.h" + +#define MAX_PASSPHRASE_LEN 64 +#define MAX_SSID_LEN 32 +#define PMK_LEN 32 + +TEST_CASE("Test pbkdf2", "[crypto-pbkdf2]") +{ + uint8_t PMK[PMK_LEN]; + uint8_t ssid_len; + uint8_t passphrase_len; + uint8_t ssid[MAX_SSID_LEN]; + uint8_t passphrase[MAX_PASSPHRASE_LEN]; + uint8_t expected_pmk1[PMK_LEN] = + {0xe7, 0x90, 0xd0, 0x65, 0x67, 0xf0, 0xbf, 0xca, 0xca, 0x10, 0x88, 0x0b, 0x85, 0xb2, 0x33, 0xe5, + 0xe1, 0xd5, 0xe5, 0xb8, 0xd0, 0xfd, 0x94, 0x60, 0x56, 0x95, 0x5e, 0x41, 0x5a, 0x7f, 0xfa, 0xfa}; + + uint8_t expected_pmk[PMK_LEN]; + + /* Compare Fast PBKDF output with expected output*/ + pbkdf2_sha1("espressif", (uint8_t *)"espressif", strlen("espressif"), 4096, PMK, PMK_LEN); + TEST_ASSERT(memcmp(PMK, expected_pmk1, PMK_LEN) == 0); + ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk1, PMK_LEN, ESP_LOG_INFO); + + /* Compare fast PBKDF output with mbedtls pbkdf2 function's output */ + pbkdf2_sha1("espressif2", (uint8_t *)"espressif2", strlen("espressif2"), 4096, PMK, PMK_LEN); + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + mbedtls_md_init(&sha1_ctx); + info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + mbedtls_md_setup(&sha1_ctx, info_sha1, 1); + mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *) "espressif2", + strlen("espressif2"), (const unsigned char *)"espressif2", strlen("espressif2"), + 4096, PMK_LEN , expected_pmk); + + TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0); + ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk, PMK_LEN, ESP_LOG_INFO); + /* Calculate PMK using random ssid and passphrase and compare */ + os_memset(ssid, 0, MAX_SSID_LEN); + os_memset(passphrase, 0, MAX_PASSPHRASE_LEN); + ssid_len = os_random(); + ssid_len %= MAX_SSID_LEN; + + os_get_random(ssid, ssid_len); + + passphrase_len = os_random(); + passphrase_len %= MAX_PASSPHRASE_LEN; + + os_get_random(passphrase, passphrase_len); + pbkdf2_sha1((char *)passphrase, ssid, ssid_len, 4096, PMK, PMK_LEN); + mbedtls_md_context_t sha1_ctx_1; + const mbedtls_md_info_t *info_sha1_1; + mbedtls_md_init(&sha1_ctx_1); + info_sha1_1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + mbedtls_md_setup(&sha1_ctx_1, info_sha1_1, 1); + mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx_1, (const unsigned char *) passphrase, + strlen((char *)passphrase), (const unsigned char *)ssid, ssid_len, + 4096, PMK_LEN, expected_pmk1); + ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk1, PMK_LEN, ESP_LOG_INFO); + TEST_ASSERT(memcmp(PMK, expected_pmk1, PMK_LEN) == 0); +} diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 1c6b8d584e..871cc197ed 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -25,6 +25,8 @@ These third party libraries can be included into the application (firmware) prod * `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license. +* :component_file:`Fast PBKDF2 ` Copyright (c) 2015 Joseph Birr-Pixton and licensed under CC0 Public Domain Dedication license. + * `FreeBSD net80211`_ Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license. * `JSMN`_ JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT license.