Merge pull request #10 from hmalpani/feature/add_esp_encrypted_img_component
Add esp_encrypted_img to component manager
This commit is contained in:
commit
5362db237b
|
@ -15,6 +15,6 @@ jobs:
|
|||
- name: Upload components to component service
|
||||
uses: espressif/github-actions/upload_components@master
|
||||
with:
|
||||
directories: "cbor;jsmn;libsodium;pid_ctrl;qrcode;nghttp;sh2lib;expat"
|
||||
directories: "cbor;jsmn;libsodium;pid_ctrl;qrcode;nghttp;sh2lib;expat;esp_encrypted_img"
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
idf_component_register(SRCS "src/esp_encrypted_img.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES mbedtls)
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,40 @@
|
|||
# ESP Encrypted Image Abstraction Layer
|
||||
|
||||
This component provides an API interface to decrypt data defined in "ESP Encrypted Image" format. This format is as specified at [Image Format](#image-format)
|
||||
|
||||
This component can help in integrating pre encrypted firmware in over-the-air updates. Additionally, this component can also be used for other use-cases which requires addition of encryption layer for custom data.
|
||||
|
||||
|
||||
## Image Format
|
||||
|
||||
![Image Format](image_format.png)
|
||||
|
||||
typedef struct {
|
||||
char magic[4];
|
||||
char enc_gcm[384];
|
||||
char iv[16];
|
||||
char bin_size[4];
|
||||
char auth[16];
|
||||
char extra_header[88];
|
||||
} pre_enc_bin_header;
|
||||
|
||||
The above struct represents encrypted image header.
|
||||
|
||||
Note:
|
||||
* RSA-3072 key is provided to the tool externally. You can generate RSA key pair using following command:
|
||||
|
||||
`openssl genrsa -out rsa_key/private.pem 3072`
|
||||
|
||||
* AES-GCM key and IV are generated by the tool itself.
|
||||
|
||||
## Tool Info
|
||||
|
||||
This component also contains tool ([esp_enc_img_gen.py](tools/esp_enc_img_gen.py)) to generate encrypted images using RSA3072 public key.
|
||||
|
||||
To know more about the tool, use command:
|
||||
`python esp_enc_img-gen.py --help`
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
To learn more about how to use this component, please check API Documentation from header file [esp_encrypted_img.h](include/esp_encrypted_img.h)
|
|
@ -0,0 +1,6 @@
|
|||
version: "1.0.0"
|
||||
description: ESP Encrypted Image Abstraction Layer
|
||||
url: https://github.com/espressif/idf-extra-components/tree/master/esp_encrypted_img
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=4.4"
|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
|
||||
#if 0 //High level layout for state machine
|
||||
|
||||
@startuml
|
||||
[*] --> READ_MAGIC
|
||||
READ_MAGIC --> READ_MAGIC : READ LEN < 4
|
||||
READ_MAGIC --> DECODE_MAGIC : READ LEN = 4
|
||||
|
||||
DECODE_MAGIC --> READ_GCM : MAGIC VERIFIED
|
||||
DECODE_MAGIC --> ESP_FAIL : MAGIC VERIFICATION FAILED
|
||||
PROCESS_BINARY --> ESP_FAIL : DECRYPTION FAILED
|
||||
|
||||
READ_GCM --> READ_GCM : READ_LEN < 384
|
||||
READ_GCM --> DECRYPT_GCM : READ_LEN = 384
|
||||
DECRYPT_GCM --> ESP_FAIL : DECRYPTION FAILED
|
||||
DECRYPT_GCM --> READ_IV : DECRYPTION SUCCESSFUL
|
||||
READ_IV --> READ_IV : READ LEN < 16
|
||||
READ_IV --> READ_BIN_SIZE
|
||||
READ_BIN_SIZE --> READ_BIN_SIZE : READ LEN < 5
|
||||
READ_BIN_SIZE --> READ_AUTH
|
||||
READ_AUTH --> READ_AUTH : READ LEN < 16
|
||||
READ_AUTH --> PROCESS_BINARY
|
||||
PROCESS_BINARY --> PROCESS_BINARY : READ LEN < BIN_SIZE
|
||||
|
||||
PROCESS_BINARY --> ESP_OK : READ LEN = BIN_SIZE
|
||||
ESP_OK --> [*]
|
||||
ESP_FAIL --> [*]
|
||||
@enduml
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *esp_decrypt_handle_t;
|
||||
|
||||
typedef struct {
|
||||
const char *rsa_pub_key; /*!< 3072 bit RSA key in PEM format */
|
||||
size_t rsa_pub_key_len; /*!< Length of the buffer pointed to by rsa_pub_key*/
|
||||
} esp_decrypt_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
char *data_in; /*!< Pointer to data to be decrypted */
|
||||
size_t data_in_len; /*!< Input data length */
|
||||
char *data_out; /*!< Pointer to decrypted data */
|
||||
size_t data_out_len; /*!< Output data length */
|
||||
} pre_enc_decrypt_arg_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function returns esp_decrypt_handle_t handle.
|
||||
*
|
||||
* @param[in] cfg pointer to esp_decrypt_cfg_t structure
|
||||
*
|
||||
* @return
|
||||
* - NULL On failure
|
||||
* - esp_decrypt_handle_t handle
|
||||
*/
|
||||
esp_decrypt_handle_t esp_encrypted_img_decrypt_start(const esp_decrypt_cfg_t *cfg);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function performs decryption on input data.
|
||||
*
|
||||
* This function must be called only if esp_encrypted_img_decrypt_start() returns successfully.
|
||||
* This function must be called in a loop since since input data might not contain whole binary at once.
|
||||
* This function must be called till it return ESP_OK.
|
||||
*
|
||||
* @note args->data_out must be freed after use provided args->data_out_len is greater than 0
|
||||
*
|
||||
* @param[in] ctx pointer to esp_decrypt_handle_t
|
||||
* @param[in/out] args pointer to pre_enc_decrypt_arg_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL On failure
|
||||
* - ESP_ERR_DECRYPT_IN_PROGRESS Decryption is in process
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t esp_encrypted_img_decrypt_data(esp_decrypt_handle_t *ctx, pre_enc_decrypt_arg_t *args);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clean-up decryption process.
|
||||
*
|
||||
* @param[in] ctx pointer to esp_decrypt_handle_t structure
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL On failure
|
||||
* - ESP_OK
|
||||
*/
|
||||
esp_err_t esp_encrypted_img_decrypt_end(esp_decrypt_handle_t *ctx);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
set(ESP_IMG_GEN_TOOL_PATH ${CMAKE_CURRENT_LIST_DIR}/tools/esp_enc_img_gen.py)
|
||||
|
||||
function(create_esp_enc_img input_file rsa_key_file output_file app)
|
||||
cmake_parse_arguments(arg "${options}" "" "${multi}" "${ARGN}")
|
||||
idf_build_get_property(python PYTHON)
|
||||
|
||||
add_custom_command(OUTPUT ${output_file}
|
||||
POST_BUILD
|
||||
COMMAND ${python} ${ESP_IMG_GEN_TOOL_PATH} encrypt
|
||||
${input_file}
|
||||
${rsa_key_file} ${output_file}
|
||||
DEPENDS gen_project_binary
|
||||
COMMENT "Generating pre-encrypted binary"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(encrypt_bin_target DEPENDS ${output_file})
|
||||
add_dependencies(${app} encrypt_bin_target)
|
||||
endfunction()
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_encrypted_img.h"
|
||||
#include <errno.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/gcm.h"
|
||||
#include "sys/param.h"
|
||||
|
||||
static const char *TAG = "esp_encrypted_img";
|
||||
|
||||
typedef enum {
|
||||
ESP_PRE_ENC_IMG_READ_MAGIC,
|
||||
ESP_PRE_ENC_IMG_READ_GCM,
|
||||
ESP_PRE_ENC_IMG_READ_IV,
|
||||
ESP_PRE_ENC_IMG_READ_BINSIZE,
|
||||
ESP_PRE_ENC_IMG_READ_AUTH,
|
||||
ESP_PRE_ENC_IMG_READ_EXTRA_HEADER,
|
||||
ESP_PRE_ENC_DATA_DECODE_STATE,
|
||||
} esp_encrypted_img_state;
|
||||
|
||||
struct esp_encrypted_img_handle {
|
||||
const char *rsa_pem;
|
||||
size_t rsa_len;
|
||||
uint32_t binary_file_len;
|
||||
uint32_t binary_file_read;
|
||||
char *gcm_key;
|
||||
char *iv;
|
||||
char auth_tag[16];
|
||||
esp_encrypted_img_state state;
|
||||
mbedtls_gcm_context gcm_ctx;
|
||||
size_t cache_buf_len;
|
||||
char *cache_buf;
|
||||
};
|
||||
|
||||
#define GCM_KEY_SIZE 32
|
||||
#define MAGIC_SIZE 4
|
||||
#define ENC_GCM_KEY_SIZE 384
|
||||
#define IV_SIZE 16
|
||||
#define BIN_SIZE_DATA 4
|
||||
#define AUTH_SIZE 16
|
||||
#define RESERVED_HEADER 88
|
||||
|
||||
typedef struct {
|
||||
char magic[MAGIC_SIZE];
|
||||
char enc_gcm[ENC_GCM_KEY_SIZE];
|
||||
char iv[IV_SIZE];
|
||||
char bin_size[BIN_SIZE_DATA];
|
||||
char auth[AUTH_SIZE];
|
||||
char extra_header[RESERVED_HEADER];
|
||||
} pre_enc_bin_header;
|
||||
#define HEADER_DATA_SIZE sizeof(pre_enc_bin_header)
|
||||
|
||||
// Magic Byte is created using command: echo -n "esp_encrypted_img" | sha256sum
|
||||
static uint32_t esp_enc_img_magic = 0x0788b6cf;
|
||||
|
||||
typedef struct esp_encrypted_img_handle esp_encrypted_img_t;
|
||||
|
||||
static int decipher_gcm_key(char *enc_gcm, esp_encrypted_img_t *handle)
|
||||
{
|
||||
int ret = 1;
|
||||
handle->gcm_key = calloc(1, GCM_KEY_SIZE);
|
||||
if (!handle->gcm_key) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
size_t olen = 0;
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
const char *pers = "mbedtls_pk_encrypt";
|
||||
|
||||
mbedtls_ctr_drbg_init( &ctr_drbg );
|
||||
mbedtls_entropy_init( &entropy );
|
||||
mbedtls_pk_init( &pk );
|
||||
|
||||
if ((ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
|
||||
&entropy, (const unsigned char *) pers,
|
||||
strlen(pers))) != 0) {
|
||||
ESP_LOGE(TAG, "failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", (unsigned int) - ret);
|
||||
free(handle->gcm_key);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Reading RSA private key");
|
||||
|
||||
if ( (ret = mbedtls_pk_parse_key(&pk, (const unsigned char *) handle->rsa_pem, handle->rsa_len, NULL, 0)) != 0) {
|
||||
ESP_LOGE(TAG, "failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", (unsigned int) - ret );
|
||||
free(handle->gcm_key);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (( ret = mbedtls_pk_decrypt( &pk, (const unsigned char *)enc_gcm, ENC_GCM_KEY_SIZE, (unsigned char *)handle->gcm_key, &olen, GCM_KEY_SIZE,
|
||||
mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) {
|
||||
ESP_LOGE(TAG, "failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", (unsigned int) - ret );
|
||||
free(handle->gcm_key);
|
||||
goto exit;
|
||||
}
|
||||
handle->cache_buf = realloc(handle->cache_buf, 16);
|
||||
if (!handle->cache_buf) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_IV;
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
handle->iv = calloc(1, IV_SIZE);
|
||||
if (!handle->iv) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_pk_free( &pk );
|
||||
mbedtls_entropy_free( &entropy );
|
||||
mbedtls_ctr_drbg_free( &ctr_drbg );
|
||||
free((void *)handle->rsa_pem);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
esp_decrypt_handle_t esp_encrypted_img_decrypt_start(const esp_decrypt_cfg_t *cfg)
|
||||
{
|
||||
if (cfg == NULL || cfg->rsa_pub_key == NULL) {
|
||||
ESP_LOGE(TAG, "esp_encrypted_img_decrypt_start : Invalid argument");
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Starting Decryption Process");
|
||||
|
||||
esp_encrypted_img_t *handle = calloc(1, sizeof(esp_encrypted_img_t));
|
||||
if (!handle) {
|
||||
ESP_LOGE(TAG, "Couldn't allocate memory to handle");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
handle->rsa_pem = calloc(1, cfg->rsa_pub_key_len);
|
||||
if (!handle->rsa_pem) {
|
||||
ESP_LOGE(TAG, "Couldn't allocate memory to handle->rsa_pem");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
handle->cache_buf = calloc(1, ENC_GCM_KEY_SIZE);
|
||||
if (!handle->cache_buf) {
|
||||
ESP_LOGE(TAG, "Couldn't allocate memory to handle->cache_buf");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
memcpy((void *)handle->rsa_pem, cfg->rsa_pub_key, cfg->rsa_pub_key_len);
|
||||
handle->rsa_len = cfg->rsa_pub_key_len;
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_MAGIC;
|
||||
|
||||
esp_decrypt_handle_t *ctx = (esp_decrypt_handle_t *)handle;
|
||||
return ctx;
|
||||
|
||||
failure:
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
if (handle->rsa_pem) {
|
||||
free((void *)handle->rsa_pem);
|
||||
}
|
||||
if (handle) {
|
||||
free(handle);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t process_bin(esp_encrypted_img_t *handle, pre_enc_decrypt_arg_t *args, int curr_index)
|
||||
{
|
||||
size_t data_len = args->data_in_len;
|
||||
|
||||
handle->binary_file_read += data_len - curr_index;
|
||||
int dec_len = 0;
|
||||
if (handle->binary_file_read != handle->binary_file_len) {
|
||||
size_t copy_len = 0;
|
||||
|
||||
if ((handle->cache_buf_len + (data_len - curr_index)) - (handle->cache_buf_len + (data_len - curr_index)) % 16 > 0) {
|
||||
args->data_out = realloc(args->data_out, (handle->cache_buf_len + (data_len - curr_index)) - (handle->cache_buf_len + (data_len - curr_index)) % 16);
|
||||
if (!args->data_out) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
if (handle->cache_buf_len != 0) {
|
||||
copy_len = MIN(16 - handle->cache_buf_len, data_len - curr_index);
|
||||
memcpy(handle->cache_buf + handle->cache_buf_len, args->data_in + curr_index, copy_len);
|
||||
handle->cache_buf_len += copy_len;
|
||||
if (handle->cache_buf_len != 16) {
|
||||
args->data_out_len = 0;
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
if (mbedtls_gcm_update(&handle->gcm_ctx, 16, (const unsigned char *)handle->cache_buf, (unsigned char *) args->data_out) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
dec_len = 16;
|
||||
}
|
||||
handle->cache_buf_len = (data_len - curr_index - copy_len) % 16;
|
||||
if (handle->cache_buf_len != 0) {
|
||||
data_len -= handle->cache_buf_len;
|
||||
memcpy(handle->cache_buf, args->data_in + (data_len), handle->cache_buf_len);
|
||||
}
|
||||
|
||||
if (data_len - copy_len - curr_index > 0) {
|
||||
if (mbedtls_gcm_update(&handle->gcm_ctx, data_len - copy_len - curr_index, (const unsigned char *)args->data_in + curr_index + copy_len, (unsigned char *)args->data_out + dec_len) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
args->data_out_len = dec_len + data_len - curr_index - copy_len;
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
|
||||
args->data_out = realloc(args->data_out, handle->cache_buf_len + data_len - curr_index);
|
||||
if (!args->data_out) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
size_t copy_len = 0;
|
||||
|
||||
copy_len = MIN(16 - handle->cache_buf_len, data_len - curr_index);
|
||||
memcpy(handle->cache_buf + handle->cache_buf_len, args->data_in + curr_index, copy_len);
|
||||
handle->cache_buf_len += copy_len;
|
||||
if (mbedtls_gcm_update(&handle->gcm_ctx, handle->cache_buf_len, (const unsigned char *)handle->cache_buf, (unsigned char *)args->data_out) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (data_len - curr_index - copy_len > 0) {
|
||||
if (mbedtls_gcm_update(&handle->gcm_ctx, data_len - curr_index - copy_len, (const unsigned char *)(args->data_in + curr_index + copy_len), (unsigned char *)(args->data_out + 16)) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
args->data_out_len = handle->cache_buf_len + data_len - copy_len - curr_index;
|
||||
handle->cache_buf_len = 0;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void read_and_cache_data(esp_encrypted_img_t *handle, pre_enc_decrypt_arg_t *args, int *curr_index, int data_size)
|
||||
{
|
||||
const int data_left = data_size - handle->binary_file_read;
|
||||
const int data_recv = args->data_in_len - *curr_index;
|
||||
if (handle->state == ESP_PRE_ENC_IMG_READ_IV && handle->iv) {
|
||||
memcpy(handle->iv + handle->cache_buf_len, args->data_in + *curr_index, MIN(data_recv, data_left));
|
||||
} else if (handle->state == ESP_PRE_ENC_IMG_READ_AUTH) {
|
||||
memcpy(handle->auth_tag + handle->cache_buf_len, args->data_in + *curr_index, MIN(data_recv, data_left));
|
||||
} else {
|
||||
memcpy(handle->cache_buf + handle->cache_buf_len, args->data_in + *curr_index, MIN(data_recv, data_left));
|
||||
}
|
||||
handle->cache_buf_len += MIN(data_recv, data_left);
|
||||
int temp = *curr_index;
|
||||
*curr_index += MIN(data_recv, data_left);
|
||||
handle->binary_file_read += MIN(args->data_in_len - temp, data_left);
|
||||
}
|
||||
|
||||
esp_err_t esp_encrypted_img_decrypt_data(esp_decrypt_handle_t *ctx, pre_enc_decrypt_arg_t *args)
|
||||
{
|
||||
if (ctx == NULL || args == NULL || args->data_in == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_encrypted_img_t *handle = (esp_encrypted_img_t *)ctx;
|
||||
if (handle == NULL) {
|
||||
ESP_LOGE(TAG, "esp_encrypted_img_decrypt_data: Invalid argument");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t err;
|
||||
int curr_index = 0;
|
||||
|
||||
switch (handle->state) {
|
||||
case ESP_PRE_ENC_IMG_READ_MAGIC:
|
||||
if (handle->cache_buf_len == 0 && (args->data_in_len - curr_index) >= MAGIC_SIZE) {
|
||||
uint32_t recv_magic = *(uint32_t *)args->data_in;
|
||||
|
||||
if (recv_magic != esp_enc_img_magic) {
|
||||
ESP_LOGE(TAG, "Magic Verification failed");
|
||||
free((void *)handle->rsa_pem);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
curr_index += MAGIC_SIZE;
|
||||
} else {
|
||||
read_and_cache_data(handle, args, &curr_index, MAGIC_SIZE);
|
||||
if (handle->binary_file_read == MAGIC_SIZE) {
|
||||
uint32_t recv_magic = *(uint32_t *)handle->cache_buf;
|
||||
|
||||
if (recv_magic != esp_enc_img_magic) {
|
||||
ESP_LOGE(TAG, "Magic Verification failed");
|
||||
free((void *)handle->rsa_pem);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Magic Verified");
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_GCM;
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_IMG_READ_GCM:
|
||||
if (handle->cache_buf_len == 0 && args->data_in_len - curr_index >= ENC_GCM_KEY_SIZE) {
|
||||
if (decipher_gcm_key(args->data_in + curr_index, handle) != 0) {
|
||||
ESP_LOGE(TAG, "Unable to decipher GCM key");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
curr_index += ENC_GCM_KEY_SIZE;
|
||||
} else {
|
||||
read_and_cache_data(handle, args, &curr_index, ENC_GCM_KEY_SIZE);
|
||||
if (handle->cache_buf_len == ENC_GCM_KEY_SIZE) {
|
||||
if (decipher_gcm_key(handle->cache_buf, handle) != 0) {
|
||||
ESP_LOGE(TAG, "Unable to decipher GCM key");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_IMG_READ_IV:
|
||||
if (handle->cache_buf_len == 0 && args->data_in_len - curr_index >= IV_SIZE) {
|
||||
memcpy(handle->iv, args->data_in + curr_index, IV_SIZE);
|
||||
handle->binary_file_read = IV_SIZE;
|
||||
curr_index += IV_SIZE;
|
||||
} else {
|
||||
read_and_cache_data(handle, args, &curr_index, IV_SIZE);
|
||||
}
|
||||
if (handle->binary_file_read == IV_SIZE) {
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_BINSIZE;
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
mbedtls_gcm_init(&handle->gcm_ctx);
|
||||
if ((err = mbedtls_gcm_setkey(&handle->gcm_ctx, MBEDTLS_CIPHER_ID_AES, (const unsigned char *)handle->gcm_key, GCM_KEY_SIZE * 8)) != 0) {
|
||||
ESP_LOGE(TAG, "Error: mbedtls_gcm_set_key: -0x%04x\n", (unsigned int) - err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
free(handle->gcm_key);
|
||||
if (mbedtls_gcm_starts(&handle->gcm_ctx, MBEDTLS_GCM_DECRYPT, (const unsigned char *)handle->iv, IV_SIZE, NULL, 0) != 0) {
|
||||
ESP_LOGE(TAG, "Error: mbedtls_gcm_starts: -0x%04x\n", (unsigned int) - err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
free(handle->iv);
|
||||
handle->iv = NULL;
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_IMG_READ_BINSIZE:
|
||||
if (handle->cache_buf_len == 0 && (args->data_in_len - curr_index) >= BIN_SIZE_DATA) {
|
||||
handle->binary_file_len = *(uint32_t *)(args->data_in + curr_index);
|
||||
curr_index += BIN_SIZE_DATA;
|
||||
} else {
|
||||
read_and_cache_data(handle, args, &curr_index, BIN_SIZE_DATA);
|
||||
if (handle->binary_file_read == BIN_SIZE_DATA) {
|
||||
handle->binary_file_len = *(uint32_t *)handle->cache_buf;
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_AUTH;
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_IMG_READ_AUTH:
|
||||
if (handle->cache_buf_len == 0 && args->data_in_len - curr_index >= AUTH_SIZE) {
|
||||
memcpy(handle->auth_tag, args->data_in + curr_index, AUTH_SIZE);
|
||||
handle->binary_file_read = AUTH_SIZE;
|
||||
curr_index += AUTH_SIZE;
|
||||
} else {
|
||||
read_and_cache_data(handle, args, &curr_index, AUTH_SIZE);
|
||||
}
|
||||
if (handle->binary_file_read == AUTH_SIZE) {
|
||||
handle->state = ESP_PRE_ENC_IMG_READ_EXTRA_HEADER;
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_IMG_READ_EXTRA_HEADER:
|
||||
{
|
||||
int temp = curr_index;
|
||||
curr_index += MIN(args->data_in_len - curr_index, RESERVED_HEADER - handle->binary_file_read);
|
||||
handle->binary_file_read += MIN(args->data_in_len - temp, RESERVED_HEADER - handle->binary_file_read);
|
||||
if (handle->binary_file_read == RESERVED_HEADER) {
|
||||
handle->state = ESP_PRE_ENC_DATA_DECODE_STATE;
|
||||
handle->binary_file_read = 0;
|
||||
handle->cache_buf_len = 0;
|
||||
} else {
|
||||
return ESP_ERR_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
/* falls through */
|
||||
case ESP_PRE_ENC_DATA_DECODE_STATE:
|
||||
err = process_bin(handle, args, curr_index);
|
||||
return err;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_encrypted_img_decrypt_end(esp_decrypt_handle_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_encrypted_img_t *handle = (esp_encrypted_img_t *)ctx;
|
||||
esp_err_t err = ESP_OK;
|
||||
if (handle == NULL) {
|
||||
ESP_LOGE(TAG, "esp_encrypted_img_decrypt_data: Invalid argument");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (handle->state == ESP_PRE_ENC_DATA_DECODE_STATE) {
|
||||
if (handle->cache_buf_len != 0 || handle->binary_file_read != handle->binary_file_len) {
|
||||
ESP_LOGE(TAG, "Invalid operation");
|
||||
err = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
char *got_auth = calloc(1, AUTH_SIZE);
|
||||
if (!got_auth) {
|
||||
ESP_LOGE(TAG, "Unable to allocate memory");
|
||||
err = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
err = mbedtls_gcm_finish(&handle->gcm_ctx, (unsigned char *)got_auth, AUTH_SIZE);
|
||||
if (err != 0) {
|
||||
ESP_LOGE(TAG, "Error: %d", err);
|
||||
free(got_auth);
|
||||
err = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
if (memcmp(got_auth, handle->auth_tag, AUTH_SIZE) != 0) {
|
||||
ESP_LOGE(TAG, "Invalid Auth");
|
||||
free(got_auth);
|
||||
err = ESP_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
free(got_auth);
|
||||
}
|
||||
err = ESP_OK;
|
||||
exit:
|
||||
mbedtls_gcm_free(&handle->gcm_ctx);
|
||||
free(handle->cache_buf);
|
||||
free(handle);
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
REQUIRES unity
|
||||
PRIV_REQUIRES cmock esp_encrypted_img
|
||||
EMBED_TXTFILES certs/test_rsa_private_key.pem
|
||||
EMBED_FILES image.bin)
|
|
@ -0,0 +1,39 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
Binary file not shown.
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_encrypted_img.h"
|
||||
|
||||
extern const uint8_t rsa_private_pem_start[] asm("_binary_test_rsa_private_key_pem_start");
|
||||
extern const uint8_t rsa_private_pem_end[] asm("_binary_test_rsa_private_key_pem_end");
|
||||
|
||||
extern const uint8_t bin_start[] asm("_binary_image_bin_start");
|
||||
extern const uint8_t bin_end[] asm("_binary_image_bin_end");
|
||||
|
||||
TEST_CASE("Sending all data at once", "[encrypted_img]")
|
||||
{
|
||||
esp_decrypt_cfg_t cfg = {
|
||||
.rsa_pub_key = (char *)rsa_private_pem_start,
|
||||
.rsa_pub_key_len = rsa_private_pem_end - rsa_private_pem_start,
|
||||
};
|
||||
esp_decrypt_handle_t *ctx = esp_encrypted_img_decrypt_start(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(ctx);
|
||||
|
||||
pre_enc_decrypt_arg_t *args = calloc(1, sizeof(pre_enc_decrypt_arg_t));
|
||||
TEST_ASSERT_NOT_NULL(args);
|
||||
|
||||
args->data_in = (char *)bin_start;
|
||||
args->data_in_len = bin_end - bin_start;
|
||||
|
||||
esp_err_t err;
|
||||
err = esp_encrypted_img_decrypt_data(ctx, args);
|
||||
|
||||
TEST_ESP_OK(err);
|
||||
printf("Successful\n");
|
||||
printf("\n");
|
||||
|
||||
err = esp_encrypted_img_decrypt_end(ctx);
|
||||
TEST_ESP_OK(err);
|
||||
if (args->data_out) {
|
||||
free(args->data_out);
|
||||
}
|
||||
free(args);
|
||||
}
|
||||
|
||||
TEST_CASE("Sending 1 byte data at once", "[encrypted_img]")
|
||||
{
|
||||
esp_decrypt_cfg_t cfg = {
|
||||
.rsa_pub_key = (char *)rsa_private_pem_start,
|
||||
.rsa_pub_key_len = rsa_private_pem_end - rsa_private_pem_start,
|
||||
};
|
||||
esp_decrypt_handle_t *ctx = esp_encrypted_img_decrypt_start(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(ctx);
|
||||
|
||||
pre_enc_decrypt_arg_t *args = calloc(1, sizeof(pre_enc_decrypt_arg_t));
|
||||
TEST_ASSERT_NOT_NULL(args);
|
||||
|
||||
esp_err_t err;
|
||||
int i = 0;
|
||||
do {
|
||||
args->data_in = (char *)(bin_start + i);
|
||||
i++;
|
||||
args->data_in_len = 1;
|
||||
err = esp_encrypted_img_decrypt_data(ctx, args);
|
||||
if (err == ESP_FAIL) {
|
||||
printf("ESP_FAIL ERROR\n");
|
||||
break;
|
||||
}
|
||||
} while (err != ESP_OK);
|
||||
TEST_ESP_OK(err);
|
||||
|
||||
err = esp_encrypted_img_decrypt_end(ctx);
|
||||
TEST_ESP_OK(err);
|
||||
if (args->data_out) {
|
||||
free(args->data_out);
|
||||
}
|
||||
free(args);
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid Magic", "[encrypted_img]")
|
||||
{
|
||||
uint8_t cipher[] = {
|
||||
0x34, 0x12, 0xbc, 0xec,
|
||||
0xf5, 0x3a, 0x72, 0x55, 0x36, 0x0f, 0x4a, 0x92,
|
||||
0x5f, 0x15, 0xef, 0xbb, 0xe8, 0x9c, 0x7e, 0x43,
|
||||
0x7c, 0x87, 0x3d, 0x00, 0xb4, 0x22, 0xcc, 0x35,
|
||||
0x77, 0x92, 0x6a, 0x44, 0x80, 0x83, 0x9d, 0x0d,
|
||||
0x4c, 0x28, 0x5b, 0x7d, 0xbd, 0xef, 0x59, 0x56,
|
||||
0xba, 0x0f, 0x9d, 0xab, 0x3b, 0x09, 0x26, 0x77,
|
||||
0x82, 0x28, 0x24, 0x6e, 0xb8, 0x35, 0x96, 0x87,
|
||||
0xd6, 0x35, 0x03, 0x9b, 0x4e, 0x60, 0xaf, 0x11,
|
||||
0x14, 0x74, 0x13, 0x75, 0xb1, 0xf6, 0x5b, 0xe5,
|
||||
0xb9, 0xf0, 0x2b, 0x37, 0x02, 0xaf, 0x76, 0x8f,
|
||||
0xe1, 0x08, 0xfa, 0x46, 0xa1, 0xb0, 0x8d, 0x04,
|
||||
0xb6, 0x09, 0x8b, 0x0f, 0x8c, 0x54, 0xab, 0x9d,
|
||||
0xe9, 0x32, 0xb7, 0xae, 0xc5, 0x6d, 0x5d, 0x85,
|
||||
0x54, 0x2b, 0x1e, 0x8c, 0xbe, 0x4c, 0xee, 0x89,
|
||||
0xc4, 0x16, 0x97, 0x6c, 0x48, 0xaf, 0x3c, 0xef,
|
||||
0x90, 0x01, 0x12, 0xd6, 0x72, 0xf4, 0xca, 0xc5,
|
||||
0xa1, 0xec, 0x8d, 0xe0, 0x4b, 0xc8, 0xb2, 0xb4,
|
||||
0x66, 0x92, 0xd8, 0x0f, 0x65, 0x4d, 0x16, 0x30,
|
||||
0x6d, 0x2e, 0x3b, 0x64, 0x22, 0x36, 0x02, 0x43,
|
||||
0x10, 0xa8, 0x77, 0xb1, 0xf2, 0x8c, 0x29, 0x8d,
|
||||
0x23, 0xf2, 0xc6, 0xd4, 0x5b, 0x2e, 0x78, 0x15,
|
||||
0x8b, 0x5e, 0x0a, 0x2b, 0xd8, 0x76, 0x83, 0xe6,
|
||||
0xf9, 0x2a, 0xad, 0xf7, 0xf1, 0x06, 0x18, 0xbf,
|
||||
0xe1, 0x50, 0x89, 0xbf, 0x92, 0xfd, 0xe8, 0xcf,
|
||||
0x06, 0x5b, 0xf3, 0xa0, 0x3b, 0xa2, 0x60, 0x0e,
|
||||
0x04, 0xc8, 0x80, 0xb7, 0x97, 0xce, 0xdc, 0xc6,
|
||||
0x7c, 0xdb, 0x82, 0x77, 0xa7, 0x84, 0xf3, 0xf3,
|
||||
0x4a, 0xfa, 0xce, 0x9a, 0x1e, 0x4b, 0x81, 0x45,
|
||||
0xed, 0xfc, 0xd7, 0xe3, 0x4d, 0x40, 0x03, 0x8f,
|
||||
0x17, 0x30, 0x8f, 0x35, 0x62, 0xc3, 0x9e, 0x1d,
|
||||
0x11, 0xee, 0x3c, 0x5a, 0xbd, 0x3b, 0x32, 0x6c,
|
||||
0x16, 0xef, 0xab, 0x67, 0xe7, 0x57, 0x89, 0x61,
|
||||
0xbd, 0x1c, 0xb0, 0x28, 0x58, 0x3b, 0x70, 0xd7,
|
||||
0x4a, 0x8e, 0x08, 0x0b, 0x3b, 0x14, 0x15, 0x7c,
|
||||
0x0e, 0x97, 0xcc, 0xa6, 0x00, 0xf7, 0x0c, 0xa0,
|
||||
0x3a, 0xd0, 0xc7, 0x97, 0xbe, 0xf6, 0xc6, 0xe7,
|
||||
0xc4, 0xc4, 0x90, 0x3d, 0x94, 0xf8, 0xd3, 0x71,
|
||||
0x85, 0x6c, 0x40, 0x97, 0xae, 0x52, 0x0e, 0xe0,
|
||||
0x70, 0x15, 0x13, 0xe4, 0xcd, 0xbb, 0xf0, 0x80,
|
||||
0x11, 0x56, 0x08, 0xff, 0x71, 0xa3, 0xca, 0x00,
|
||||
0x43, 0x0d, 0xde, 0xa1, 0x81, 0xaa, 0x52, 0x9a,
|
||||
0xfd, 0x64, 0x58, 0x6c, 0x99, 0x37, 0x9b, 0x04,
|
||||
0x46, 0x33, 0x22, 0x88, 0x53, 0x1a, 0x99, 0x54,
|
||||
0xf2, 0x77, 0x00, 0x23, 0xf0, 0xf3, 0x24, 0x02,
|
||||
0x7d, 0x2a, 0x93, 0x98, 0x25, 0x5f, 0x55, 0xaf,
|
||||
0x99, 0xf6, 0x69, 0x4e, 0x3a, 0xdf, 0x8f, 0xed,
|
||||
0x59, 0x91, 0xaa, 0xff, 0x0b, 0xaa, 0x70, 0x8e,
|
||||
0x08, 0xfe, 0xa1, 0x32, 0xa9, 0xa7, 0xc6, 0xf9,
|
||||
0x1d, 0xfa, 0x52, 0x32, 0xc5, 0x5b, 0x64, 0x1e,
|
||||
0x75, 0x67, 0xe0, 0xac, 0xe0, 0x35, 0x9d, 0x4a,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x9a, 0xf1,
|
||||
0xe2, 0x4a, 0xe8, 0xea, 0xed, 0x68, 0x15, 0xf4,
|
||||
0x04, 0x36, 0x96, 0x60, 0x48, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5a, 0x2f, 0x2a, 0x16,
|
||||
0x6c, 0x8b, 0x34, 0x4e, 0xc0
|
||||
};
|
||||
|
||||
esp_decrypt_cfg_t cfg = {
|
||||
.rsa_pub_key = (char *)rsa_private_pem_start,
|
||||
.rsa_pub_key_len = rsa_private_pem_end - rsa_private_pem_start,
|
||||
};
|
||||
esp_decrypt_handle_t *ctx = esp_encrypted_img_decrypt_start(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(ctx);
|
||||
|
||||
pre_enc_decrypt_arg_t *args = calloc(1, sizeof(pre_enc_decrypt_arg_t));
|
||||
TEST_ASSERT_NOT_NULL(args);
|
||||
|
||||
args->data_in = (char *)cipher;
|
||||
args->data_in_len = 521;
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
err = esp_encrypted_img_decrypt_data(ctx, args);
|
||||
|
||||
TEST_ESP_ERR(ESP_FAIL, err);
|
||||
|
||||
err = esp_encrypted_img_decrypt_end(ctx);
|
||||
free(args);
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid Image", "[encrypted_img]")
|
||||
{
|
||||
//"Espressif" is encoded using GCM key. After successful decoding, "Espressif" will be printed.
|
||||
uint8_t cipher[] = {
|
||||
0xcf, 0xb6, 0x88, 0x07,
|
||||
0xf5, 0x3a, 0x72, 0x55, 0x36, 0x0f, 0x4a, 0x92,
|
||||
0x5f, 0x15, 0xef, 0xbb, 0xe8, 0x9c, 0x7e, 0x43,
|
||||
0x7c, 0x87, 0x3d, 0x00, 0xb4, 0x22, 0xcc, 0x35,
|
||||
0x77, 0x92, 0x6a, 0x44, 0x80, 0x83, 0x9d, 0x0d,
|
||||
0x4c, 0x28, 0x5b, 0x7d, 0xbd, 0xef, 0x59, 0x56,
|
||||
0xba, 0x0f, 0x9d, 0xab, 0x3b, 0x09, 0x26, 0x77,
|
||||
0x82, 0x28, 0x24, 0x6e, 0xb8, 0x35, 0x96, 0x87,
|
||||
0xd6, 0x35, 0x03, 0x9b, 0x4e, 0x60, 0xaf, 0x11,
|
||||
0x14, 0x74, 0x13, 0x75, 0xb1, 0xf6, 0x5b, 0xe5,
|
||||
0xb9, 0xf0, 0x2b, 0x37, 0x02, 0xaf, 0x76, 0x8f,
|
||||
0xe1, 0x08, 0xfa, 0x46, 0xa1, 0xb0, 0x8d, 0x04,
|
||||
0xb6, 0x09, 0x8b, 0x0f, 0x8c, 0x54, 0xab, 0x9d,
|
||||
0xe9, 0x32, 0xb7, 0xae, 0xc5, 0x6d, 0x5d, 0x85,
|
||||
0x54, 0x2b, 0x1e, 0x8c, 0xbe, 0x4c, 0xee, 0x89,
|
||||
0xc4, 0x16, 0x97, 0x6c, 0x48, 0xaf, 0x3c, 0xef,
|
||||
0x90, 0x01, 0x12, 0xd6, 0x72, 0xf4, 0xca, 0xc5,
|
||||
0xa1, 0xec, 0x8d, 0xe0, 0x4b, 0xc8, 0xb2, 0xb4,
|
||||
0x66, 0x92, 0xd8, 0x0f, 0x65, 0x4d, 0x16, 0x30,
|
||||
0x6d, 0x2e, 0x3b, 0x64, 0x22, 0x36, 0x02, 0x43,
|
||||
0x10, 0xa8, 0x77, 0xb1, 0xf2, 0x8c, 0x29, 0x8d,
|
||||
0x23, 0xf2, 0xc6, 0xd4, 0x5b, 0x2e, 0x78, 0x15,
|
||||
0x8b, 0x5e, 0x0a, 0x2b, 0xd8, 0x76, 0x83, 0xe6,
|
||||
0xf9, 0x2a, 0xad, 0xf7, 0xf1, 0x06, 0x18, 0xbf,
|
||||
0xe1, 0x50, 0x89, 0xbf, 0x92, 0xfd, 0xe8, 0xcf,
|
||||
0x06, 0x5b, 0xf3, 0xa0, 0x3b, 0xa2, 0x60, 0x0e,
|
||||
0x04, 0xc8, 0x80, 0xb7, 0x97, 0xce, 0xdc, 0xc6,
|
||||
0x7c, 0xdb, 0x82, 0x77, 0xa7, 0x84, 0xf3, 0xf3,
|
||||
0x4a, 0xfa, 0xce, 0x9a, 0x1e, 0x4b, 0x81, 0x45,
|
||||
0xed, 0xfc, 0xd7, 0xe3, 0x4d, 0x40, 0x03, 0x8f,
|
||||
0x17, 0x30, 0x8f, 0x35, 0x62, 0xc3, 0x9e, 0x1d,
|
||||
0x11, 0xee, 0x3c, 0x5a, 0xbd, 0x3b, 0x32, 0x6c,
|
||||
0x16, 0xef, 0xab, 0x67, 0xe7, 0x57, 0x89, 0x61,
|
||||
0xbd, 0x1c, 0xb0, 0x28, 0x58, 0x3b, 0x70, 0xd7,
|
||||
0x4a, 0x8e, 0x08, 0x0b, 0x3b, 0x14, 0x15, 0x7c,
|
||||
0x0e, 0x97, 0xcc, 0xa6, 0x00, 0xf7, 0x0c, 0xa0,
|
||||
0x3a, 0xd0, 0xc7, 0x97, 0xbe, 0xf6, 0xc6, 0xe7,
|
||||
0xc4, 0xc4, 0x90, 0x3d, 0x94, 0xf8, 0xd3, 0x71,
|
||||
0x85, 0x6c, 0x40, 0x97, 0xae, 0x52, 0x0e, 0xe0,
|
||||
0x70, 0x15, 0x13, 0xe4, 0xcd, 0xbb, 0xf0, 0x80,
|
||||
0x11, 0x56, 0x08, 0xff, 0x71, 0xa3, 0xca, 0x00,
|
||||
0x43, 0x0d, 0xde, 0xa1, 0x81, 0xaa, 0x52, 0x9a,
|
||||
0xfd, 0x64, 0x58, 0x6c, 0x99, 0x37, 0x9b, 0x04,
|
||||
0x46, 0x33, 0x22, 0x88, 0x53, 0x1a, 0x99, 0x54,
|
||||
0xf2, 0x77, 0x00, 0x23, 0xf0, 0xf3, 0x24, 0x02,
|
||||
0x7d, 0x2a, 0x93, 0x98, 0x25, 0x5f, 0x55, 0xaf,
|
||||
0x99, 0xf6, 0x69, 0x4e, 0x3a, 0xdf, 0x8f, 0xed,
|
||||
0x59, 0x91, 0xaa, 0xff, 0x0b, 0xaa, 0x70, 0x8e,
|
||||
0x08, 0xfe, 0xa1, 0x32, 0xa9, 0xa7, 0xc6, 0xf9,
|
||||
0x1d, 0xfa, 0x52, 0x32, 0xc5, 0x5b, 0x64, 0x1e,
|
||||
0x75, 0x67, 0xe0, 0xac, 0xe0, 0x35, 0x9d, 0x4a,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x9a, 0xf1,
|
||||
0xe2, 0x4a, 0xe8, 0xea, 0xed, 0x68, 0x15, 0xf4,
|
||||
0x04, 0x36, 0x96, 0x60, 0x48, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5a, 0x2f, 0x2a, 0x16,
|
||||
0x6c, 0x8b, 0x34, 0x4e, 0xd0
|
||||
};
|
||||
|
||||
esp_decrypt_cfg_t cfg = {
|
||||
.rsa_pub_key = (char *)rsa_private_pem_start,
|
||||
.rsa_pub_key_len = rsa_private_pem_end - rsa_private_pem_start,
|
||||
};
|
||||
esp_decrypt_handle_t *ctx = esp_encrypted_img_decrypt_start(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(ctx);
|
||||
|
||||
pre_enc_decrypt_arg_t *args = calloc(1, sizeof(pre_enc_decrypt_arg_t));
|
||||
TEST_ASSERT_NOT_NULL(args);
|
||||
|
||||
args->data_in = (char *)cipher;
|
||||
args->data_in_len = 521;
|
||||
|
||||
esp_err_t err;
|
||||
err = esp_encrypted_img_decrypt_data(ctx, args);
|
||||
|
||||
TEST_ESP_OK(err);
|
||||
|
||||
err = esp_encrypted_img_decrypt_end(ctx);
|
||||
TEST_ESP_ERR(ESP_FAIL, err);
|
||||
if (args->data_out) {
|
||||
free(args->data_out);
|
||||
}
|
||||
free(args);
|
||||
}
|
||||
|
||||
TEST_CASE("Sending random size data at once", "[encrypted_img]")
|
||||
{
|
||||
esp_decrypt_cfg_t cfg = {
|
||||
.rsa_pub_key = (char *)rsa_private_pem_start,
|
||||
.rsa_pub_key_len = rsa_private_pem_end - rsa_private_pem_start,
|
||||
};
|
||||
esp_decrypt_handle_t *ctx = esp_encrypted_img_decrypt_start(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(ctx);
|
||||
|
||||
pre_enc_decrypt_arg_t *args = calloc(1, sizeof(pre_enc_decrypt_arg_t));
|
||||
TEST_ASSERT_NOT_NULL(args);
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
uint32_t y = esp_random();
|
||||
y = (y % 16) + 1;
|
||||
uint32_t x = y < ((bin_end - bin_start) - i) ? y : ((bin_end - bin_start) - i);
|
||||
args->data_in = (char *)(bin_start + i);
|
||||
i += x;
|
||||
args->data_in_len = x;
|
||||
err = esp_encrypted_img_decrypt_data(ctx, args);
|
||||
if (err == ESP_FAIL) {
|
||||
printf("ESP_FAIL ERROR\n");
|
||||
break;
|
||||
}
|
||||
} while (err != ESP_OK);
|
||||
|
||||
TEST_ESP_OK(err);
|
||||
|
||||
err = esp_encrypted_img_decrypt_end(ctx);
|
||||
TEST_ESP_OK(err);
|
||||
if (args->data_out) {
|
||||
free(args->data_out);
|
||||
}
|
||||
free(args);
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Encrypted image generation tool. This tool helps in generating encrypted binary image
|
||||
# in pre-defined format with assistance of RSA-3072 bit key.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
|
||||
# Magic Byte is created using command: echo -n "esp_encrypted_img" | sha256sum
|
||||
esp_enc_img_magic = 0x0788b6cf
|
||||
|
||||
GCM_KEY_SIZE = 32
|
||||
MAGIC_SIZE = 4
|
||||
ENC_GCM_KEY_SIZE = 384
|
||||
IV_SIZE = 16
|
||||
BIN_SIZE_DATA = 4
|
||||
AUTH_SIZE = 16
|
||||
RESERVED_HEADER = (512 - (MAGIC_SIZE + ENC_GCM_KEY_SIZE + IV_SIZE + BIN_SIZE_DATA + AUTH_SIZE))
|
||||
|
||||
|
||||
def generate_key_GCM(size: int) -> bytes:
|
||||
return os.urandom(int(size))
|
||||
|
||||
|
||||
def generate_IV_GCM() -> bytes:
|
||||
return os.urandom(IV_SIZE)
|
||||
|
||||
|
||||
def encrypt_binary(plaintext: bytes, key: bytes, IV: bytes) -> tuple:
|
||||
encobj = AESGCM(key)
|
||||
ct = encobj.encrypt(IV, plaintext, None)
|
||||
return ct[:len(plaintext)], ct[len(plaintext):]
|
||||
|
||||
|
||||
def encrypt(input_file: str, rsa_key_file_name: str, output_file: str) -> None:
|
||||
print('Encrypting image ...')
|
||||
with open(input_file, 'rb') as image:
|
||||
data = image.read()
|
||||
|
||||
with open(rsa_key_file_name, 'rb') as key_file:
|
||||
private_key = serialization.load_pem_private_key(key_file.read(), password=None)
|
||||
|
||||
public_key = private_key.public_key()
|
||||
|
||||
gcm_key = generate_key_GCM(GCM_KEY_SIZE)
|
||||
iv = generate_IV_GCM()
|
||||
|
||||
encrypted_gcm_key = public_key.encrypt(gcm_key, padding.PKCS1v15())
|
||||
ciphertext, authtag = encrypt_binary(data, gcm_key, iv)
|
||||
|
||||
with open(output_file, 'ab') as image:
|
||||
image.write(esp_enc_img_magic.to_bytes(MAGIC_SIZE, 'little'))
|
||||
image.write((encrypted_gcm_key))
|
||||
image.write((iv))
|
||||
image.write(len(ciphertext).to_bytes(BIN_SIZE_DATA, 'little'))
|
||||
image.write(authtag)
|
||||
image.write(bytearray(RESERVED_HEADER))
|
||||
image.write(ciphertext)
|
||||
|
||||
print('Done')
|
||||
|
||||
|
||||
def decrypt_binary(ciphertext: bytes, authTag: bytes, key: bytes, IV: bytes) -> bytes:
|
||||
encobj = AESGCM(key)
|
||||
plaintext = encobj.decrypt(IV, ciphertext + authTag, None)
|
||||
return plaintext
|
||||
|
||||
|
||||
def decrypt(input_file: str, rsa_key: str, output_file: str) -> None:
|
||||
print('Decrypting image ...')
|
||||
with open(rsa_key, 'rb') as key_file:
|
||||
private_key = serialization.load_pem_private_key(key_file.read(), password=None)
|
||||
|
||||
with open(input_file, 'rb') as file:
|
||||
recv_magic = file.read(MAGIC_SIZE)
|
||||
if(int.from_bytes(recv_magic, 'little') != esp_enc_img_magic):
|
||||
print('Error: Magic Verification Failed', file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
print('Magic verified successfully')
|
||||
|
||||
encrypted_gcm_key = file.read(ENC_GCM_KEY_SIZE)
|
||||
gcm_key = private_key.decrypt(encrypted_gcm_key, padding.PKCS1v15())
|
||||
|
||||
iv = file.read(IV_SIZE)
|
||||
bin_size = int.from_bytes(file.read(BIN_SIZE_DATA), 'little')
|
||||
auth = file.read(AUTH_SIZE)
|
||||
|
||||
file.read(RESERVED_HEADER)
|
||||
enc_bin = file.read(bin_size)
|
||||
|
||||
decrypted_binary = decrypt_binary(enc_bin, auth, gcm_key, iv)
|
||||
|
||||
with open(output_file, 'ab') as file:
|
||||
file.write(decrypted_binary)
|
||||
print('Done')
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser('Encrypted Image Tool')
|
||||
subparsers = parser.add_subparsers(dest='operation', help='run enc_image -h for additional help')
|
||||
subparsers.add_parser('encrypt', help='Encrypt an binary')
|
||||
subparsers.add_parser('decrypt', help='Decrypt an encrypted image')
|
||||
parser.add_argument('input_file')
|
||||
parser.add_argument('RSA_key')
|
||||
parser.add_argument('output_file_name')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if(args.operation == 'encrypt'):
|
||||
encrypt(args.input_file, args.RSA_key, args.output_file_name)
|
||||
if(args.operation == 'decrypt'):
|
||||
decrypt(args.input_file, args.RSA_key, args.output_file_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -2,10 +2,15 @@
|
|||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS ../libsodium ../expat)
|
||||
set(EXTRA_COMPONENT_DIRS ../libsodium ../expat ../esp_encrypted_img)
|
||||
|
||||
# Set the components to include the tests for.
|
||||
set(TEST_COMPONENTS libsodium expat CACHE STRING "List of components to test")
|
||||
set(TEST_COMPONENTS libsodium expat esp_encrypted_img CACHE STRING "List of components to test")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/version.cmake) # $ENV{IDF_VERSION} was added after v4.3...
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_LESS "4.4")
|
||||
set(EXCLUDE_COMPONENTS esp_encrypted_img)
|
||||
endif()
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(idf_extra_test_app)
|
||||
|
|
Loading…
Reference in New Issue