/*
- * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2025 Huawei Device Co., Ltd.
* 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
*/
#include "mbedtls_pkcs7.h"
-
-#include <stdio.h>
-#include <stdlib.h>
+#include <ctype.h>
#include <string.h>
-#include <stdbool.h>
-
-#include "mbedtls/platform.h" // for mbedtls_calloc
+#include <time.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include "app_common.h"
#include "securec.h"
-
-#include "verify_util_log.h"
-
-#define VERIFY_BUF_LEN 512
-#define MAX_SIG_SIZE 1024
-#define MAX_HASH_SIZE 64
+#include "mbedtls/platform.h"
+#include <mbedtls/md.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/pk.h>
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include <mbedtls/ecdh.h>
+#include <mbedtls/cipher.h>
+#include <mbedtls/error.h>
+#include "log.h"
+#include "nv.h"
/*
* below pkcs-7 and pkcs-9 oid definition is not defined in mbedtls now
#define DER_FORMAT_SINGED_DATA 2
#define PKCS7_ERR_GOTO_OUT(rc) \
- do { \
- if ((rc) != PKCS7_SUCC) \
- { \
- goto OUT; \
- } \
+ do { \
+ if ((rc) != PKCS7_SUCC) \
+ { \
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "%s:%u, error occurred, ret:%d", __FUNCTION__, __LINE__, (rc)); \
+ return rc; \
+ } \
} while (0)
-/*
- * for now, there's only one root ca
- * so we do not duplicate load root ca for every signer
- * but just let the signer's rootca point to this.
- */
static mbedtls_x509_crt g_rootCaG2Cert;
static bool g_rootCertLoaded;
static const unsigned char g_rootCaG2CertInPem[] =
"-----BEGIN CERTIFICATE-----\r\n"
- "MIICRDCCAcmgAwIBAgIED+E4izAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\r\n"
- "MRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\r\n"
- "bTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\r\n"
- "MTAyMDIxMjE0MThaFw00OTEyMzExMjE0MThaMGgxCzAJBgNVBAYTAkNOMRQwEgYD\r\n"
- "VQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEoMCYG\r\n"
- "A1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTB2MBAGByqGSM49\r\n"
- "AgEGBSuBBAAiA2IABE023XmRaw2DnO8NSsb+KG/uY0FtS3u5LQucdr3qWVnRW5ui\r\n"
- "QIL6ttNZBEeLTUeYcJZCpayg9Llf+1SmDA7dY4iP2EcRo4UN3rilovtfFfsmH4ty\r\n"
- "3SApHVFzWUl+NwdH8KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\r\n"
- "AQYwHQYDVR0OBBYEFBc6EKGrGXzlAE+s0Zgnsphadw7NMAwGCCqGSM49BAMDBQAD\r\n"
- "ZwAwZAIwd1p3JzHN93eoPped1li0j64npgqNzwy4OrkehYAqNXpcpaEcLZ7UxW8E\r\n"
- "I2lZJ3SbAjAkqySHb12sIwdSFKSN9KCMMEo/eUT5dUXlcKR2nZz0MJdxT5F51qcX\r\n"
- "1CumzkcYhgU=\r\n"
+ "MIICGjCCAaGgAwIBAgIIShhpn519jNAwCgYIKoZIzj0EAwMwUzELMAkGA1UEBhMC\r\n"
+ "Q04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UECwwKSHVhd2VpIENCRzEeMBwGA1UE\r\n"
+ "AwwVSHVhd2VpIENCRyBSb290IENBIEcyMB4XDTIwMDMxNjAzMDQzOVoXDTQ5MDMx\r\n"
+ "NjAzMDQzOVowUzELMAkGA1UEBhMCQ04xDzANBgNVBAoMBkh1YXdlaTETMBEGA1UE\r\n"
+ "CwwKSHVhd2VpIENCRzEeMBwGA1UEAwwVSHVhd2VpIENCRyBSb290IENBIEcyMHYw\r\n"
+ "EAYHKoZIzj0CAQYFK4EEACIDYgAEWidkGnDSOw3/HE2y2GHl+fpWBIa5S+IlnNrs\r\n"
+ "GUvwC1I2QWvtqCHWmwFlFK95zKXiM8s9yV3VVXh7ivN8ZJO3SC5N1TCrvB2lpHMB\r\n"
+ "wcz4DA0kgHCMm/wDec6kOHx1xvCRo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\r\n"
+ "AQH/BAUwAwEB/zAdBgNVHQ4EFgQUo45a9Vq8cYwqaiVyfkiS4pLcIAAwCgYIKoZI\r\n"
+ "zj0EAwMDZwAwZAIwMypeB7P0IbY7c6gpWcClhRznOJFj8uavrNu2PIoz9KIqr3jn\r\n"
+ "BlBHJs0myI7ntYpEAjBbm8eDMZY5zq5iMZUC6H7UzYSix4Uy1YlsLVV738PtKP9h\r\n"
+ "FTjgDHctXJlC5L7+ZDY=\r\n"
"-----END CERTIFICATE-----\r\n";
static mbedtls_x509_crt g_debugModeRootCert;
"7XL/vJcp3HeHjiXu7XZmYQ+QAvHPhU0CMCiwWFbDl8ETw4VK25QbwhL/QiUfiRfC\r\n"
"J6LzteOvjLTEV5iebQMz/nS1j7/oj3Rsqg==\r\n"
"-----END CERTIFICATE-----\r\n";
+static mbedtls_x509_crt g_ohosRootCert;
+static const unsigned char OHOS_ROOT_CERT_IN_PEM[] =
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIICRDCCAcmgAwIBAgIED+E4izAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\r\n"
+ "MRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\r\n"
+ "bTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\r\n"
+ "MTAyMDIxMjE0MThaFw00OTEyMzExMjE0MThaMGgxCzAJBgNVBAYTAkNOMRQwEgYD\r\n"
+ "VQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEoMCYG\r\n"
+ "A1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTB2MBAGByqGSM49\r\n"
+ "AgEGBSuBBAAiA2IABE023XmRaw2DnO8NSsb+KG/uY0FtS3u5LQucdr3qWVnRW5ui\r\n"
+ "QIL6ttNZBEeLTUeYcJZCpayg9Llf+1SmDA7dY4iP2EcRo4UN3rilovtfFfsmH4ty\r\n"
+ "3SApHVFzWUl+NwdH8KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\r\n"
+ "AQYwHQYDVR0OBBYEFBc6EKGrGXzlAE+s0Zgnsphadw7NMAwGCCqGSM49BAMDBQAD\r\n"
+ "ZwAwZAIwd1p3JzHN93eoPped1li0j64npgqNzwy4OrkehYAqNXpcpaEcLZ7UxW8E\r\n"
+ "I2lZJ3SbAjAkqySHb12sIwdSFKSN9KCMMEo/eUT5dUXlcKR2nZz0MJdxT5F51qcX\r\n"
+ "1CumzkcYhgU=\r\n"
+ "-----END CERTIFICATE-----\r\n";
+
+#define VERIFY_BUF_LEN 512
+#define MAX_CERTPATH_LEN 256
+#define OEM_CERT_PATH "/user/app/user/certcfg/"
+
+static void *Pkcs7Calloc(size_t nmemb, size_t size)
+{
+#if (RUNNING_BOARD == LITE_WEARABLE)
+ void *ptr = PSRAM_Malloc(nmemb * size);
+ if (ptr == NULL) {
+ return NULL;
+ }
+ (void)memset_s(ptr, nmemb * size, 0, nmemb * size);
+ return ptr;
+#else
+ return calloc(nmemb, size);
+#endif
+}
+
+static void Pkcs7Free(void *ptr)
+{
+#if (RUNNING_BOARD == LITE_WEARABLE)
+ PSRAM_Free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+#ifdef MARKET_ENABLE
+#define DIALMARKET_PUBKEY_PATH "/user/dialpubkey"
+/* hardcoded public key */
+static const char ROOT_CA_OEM_PUBKEY_IN_PEM[] =
+ "-----BEGIN PUBLIC KEY-----\r\n"
+ "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvnjlpcsSvEOhMfYwrW/Y\r\n"
+ "ExDmXL47SkbomiorGtdF63J2Vkgs2/HTxhUKBkIvSPbGRTR+io8rAo2J3oz1U48m\r\n"
+ "+M/+yIszIYC2s+tW64v8NuxLwMFFeg7+cud07/FwfJYYIRvyDQVduwV0VwvkTQy+\r\n"
+ "4/n5m+zJEHNheCakEEmFXn7vXUzxlSVSji5cHbGZ2ZzdmettLMc88tv/Kq8X3rgM\r\n"
+ "KQkngVylO4p93UvzY9hIAh9heL5VWMVOj241p3RojavIofODIeF7Vti2DjJjvbPW\r\n"
+ "igV0M9C0wLlZzMTQwoZbZT8mKsHkXW3XdTgc8ccD7RioeQa9MOlLKFbnJQLYNKr+\r\n"
+ "WsGDTFO2iHQmRAIGGuvWnxZIGS5Ho+ZUntdIYAvH8ww+36eFOwNp5cb1/ZjZmQ4c\r\n"
+ "p0zTw3zF8mSEieToMgIgz19wc9hvYgMPLlZpzFZklg8tJenJvcNpk5/3saEmpV6R\r\n"
+ "gGZ0IrmT/5h3Z/49W86Dv3b2ro4zb/sqtLufDqGoF3IDAgMBAAE=\r\n"
+ "-----END PUBLIC KEY-----\r\n";
+
+static const unsigned char g_dialRootCertInPem[] =
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIEsTCCAxmgAwIBAgIUdJ4u/0ct0XJHZphCzmBQQddboC4wDQYJKoZIhvcNAQEL\r\n"
+ "BQAwaDELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoZW56aGVuMREwDwYDVQQHDAhT\r\n"
+ "aGVuemhlbjEPMA0GA1UECgwGSFRMaW5rMQ8wDQYDVQQLDAZIVExpbmsxETAPBgNV\r\n"
+ "BAMMCEhUTGlua0NBMB4XDTI1MDQyNzA2NDkwN1oXDTM1MDQyNTA2NDkwN1owaDEL\r\n"
+ "MAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoZW56aGVuMREwDwYDVQQHDAhTaGVuemhl\r\n"
+ "bjEPMA0GA1UECgwGSFRMaW5rMQ8wDQYDVQQLDAZIVExpbmsxETAPBgNVBAMMCEhU\r\n"
+ "TGlua0NBMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAytceDkYIIn2P\r\n"
+ "340TG6+3yI4NhauO7IoXDI74w3CXpqFG40F2h42IKnDLsDznGKMyaRglsab09K1m\r\n"
+ "/yrVomrH2/e1EpMaATiKIJFkEijSjo0/EGqYeT1q59tyXdkgl/VLV04Yh8ra5lU8\r\n"
+ "nVog/Lk02GLhoTVttMQOA2dn3muaLzjuBHEjfAisfubP+mxE1e7/P6E2ZD5D8J2i\r\n"
+ "XoMSDTO6FwZwNBtTnrTu11z1h5bRQ6jPU3fAWxcfThjR/InocTtS4OlpKNuPlnOt\r\n"
+ "PpS+j0DVD+UJKR3wPEXSpxwBVveSJB7NsCMIuAM9urTmhzJzcSu9pKKzb6r22xBx\r\n"
+ "HaNQ6g+rX6vCCHnT/vUlqscyrKxnC3DwEqzK2PByvAGaMDfB6co/nyncYmQ0eIz+\r\n"
+ "8Px+xoLcFQ6qfyHBlj81FHvkM5R/TprruGUUvWkTySQJnLuRY7aEqmFWQAKXYppK\r\n"
+ "G6ZmgnDYiV2vwpsdR6TbVomdmpIV7r0Vp8hs1vVRaZHOJoJdNrynAgMBAAGjUzBR\r\n"
+ "MB0GA1UdDgQWBBR6KC9wRu9J6A1Fa86FoLNVgSvYMzAfBgNVHSMEGDAWgBR6KC9w\r\n"
+ "Ru9J6A1Fa86FoLNVgSvYMzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA\r\n"
+ "A4IBgQDB/QGEdrz/bGpmHBca32oWYmeI4OSGZSjoBdzg54tI0TzncrQTduzSYTLM\r\n"
+ "8bl3HExDlZXR/wqMlfqftNctlHKRUpX3K0A78M3j2xdBu5AoeDI4Xis7AkWTeo4U\r\n"
+ "6EQYtZU1rY6RgX95GsMPyMtbEwB+xiUM8w2gf8rhTLt6iotDU6ErUh6qLS7zqQOJ\r\n"
+ "0ulmF9g9/bLcyfaVeXdxVL1+Ggw2jIpxkqO4XjeuUNj/1FrMmiZdKQAdny5aNEf4\r\n"
+ "MZ9IWd1WNgSOtbg/Csf7m55yOCJjUr3QteE1pRJoMAw0mw9GXEZkndRX27Sl6wvW\r\n"
+ "xeD9niKvD5dG7vg/dzSJNUBqL7dOyNezyWXJIlxXMG24MuWMe7GbBBbxdatEXs1E\r\n"
+ "fT/P6O9ffghZbd7q5Cm3pC/xfMtpPl1sV4OeDzIzs2j5Fvc7LXTePT60bbFLe5WB\r\n"
+ "yPLVWeOJrMxWjrppi8O7cVBo/uhWopV14vbawJ970flrgRH6/dm50P/VHQ7ktAZe\r\n"
+ "ZVFOoMU=\r\n"
+ "-----END CERTIFICATE-----\r\n";
+
+#define PUB_KEY_SIZE 65
+#define SHARED_SECRET_SIZE 32
+#define UT_NV_MAX_LENGTH 4060
+#define CHUNK_SIZE (1024 * 4) // Each HASH update processes 4KB
+#define SHA256_HASH_SIZE 32
+#define RSA3072_SIG_SIZE 384
+#define PUB_KEY_FILE_FULL_NAME_LEN 256
+#define ECC_PEN_KEY_LEN 256
+#define TARGET_PEM ".pem"
+
+typedef struct {
+ mbedtls_ecp_group grp; // Elliptic curve group (including curve parameters)
+ mbedtls_mpi d; // ECC private key
+ mbedtls_ecp_point Q; // ECC public key
+ unsigned char pubKey[PUB_KEY_SIZE];
+ size_t pubKeyLen;
+ unsigned char workKey[SHARED_SECRET_SIZE];
+ unsigned char noise[NOISE_SIZE];
+} EcdhEntity;
+
+typedef struct {
+ mbedtls_cipher_context_t *ctx;
+ const unsigned char *key;
+ const unsigned char *iv;
+ const unsigned char *input;
+ size_t ilen;
+ unsigned char *output;
+ size_t *olen;
+ int32_t paddingMode;
+} AesParams;
+
+const uint16_t NV_KEY_ID = NV_ID_SECURE_DIAL;
+
+int32_t PKCS7_SaveKeyToNv(unsigned char *pem_buffer, uint32_t pem_bufferLen, uint16_t keyId)
+{
+ int32_t ret = 0;
+ nv_key_attr_t attr = {0, 1, 0, 0};
+ ret = uapi_nv_write_with_attr(keyId, pem_buffer, pem_bufferLen, &attr, NULL);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to write key to nv.");
+ return PKCS7_SAVE_PUB_KEY_FAIL;
+ }
+ return ret;
+}
+
+int32_t PKCS7_GetKeyFromNv(uint16_t keyId, uint8_t *data)
+{
+ int32_t ret = 0;
+ uint16_t k_length = 0;
+ nv_key_attr_t attr = {0, 1, 0, 0};
+ ret = uapi_nv_read_with_attr(keyId, UT_NV_MAX_LENGTH, &k_length, data, &attr);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to read key from nv.");
+ return PKCS7_GET_PUB_KEY_FAIL;
+ }
+ return ret;
+}
+
+int32_t InitDrbg(mbedtls_ctr_drbg_context *drbg, mbedtls_entropy_context *entropy)
+{
+ const char *pers = "ECDH_Negotiation";
+ mbedtls_entropy_init(entropy);
+ mbedtls_ctr_drbg_init(drbg);
+ if (mbedtls_ctr_drbg_seed(drbg, mbedtls_entropy_func, entropy, (const uint8_t *)pers, strlen(pers)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ctr_drbg_seed failed");
+ return PKCS7_INVALID_PARAM;
+ }
+ return 0;
+}
+
+int32_t InitEcdhEntity(EcdhEntity *entity, mbedtls_ctr_drbg_context *drbg)
+{
+ int32_t ret = 0;
+
+ // Initialize all cryptographic objects
+ mbedtls_ecp_group_init(&entity->grp);
+ mbedtls_mpi_init(&entity->d);
+ mbedtls_ecp_point_init(&entity->Q);
+ entity->pubKeyLen = 0;
+
+ // 1. Loading curve MBEDTLS-EPC_SP_BP256R1
+ ret = mbedtls_ecp_group_load(&entity->grp, MBEDTLS_ECP_DP_BP256R1);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecp_group_load failed: -0x%04X\n", -ret);
+ return ret;
+ }
+
+ // 2. Generate key pairs
+ ret = mbedtls_ecdh_gen_public(
+ &entity->grp, &entity->d, &entity->Q,
+ mbedtls_ctr_drbg_random, drbg);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecdh_gen_public failed: -0x%04X\n", -ret);
+ return ret;
+ }
+ return 0;
+}
+
+// Triple HKDF derived function (using synchronized salt values)
+int32_t TripleHkdfDerive(const unsigned char *sharedSecret, size_t secretLen,
+ const unsigned char sals[SALT_INFO_POOL_ROWS * NOISE_SIZE], unsigned char *finalKey, size_t keyLen)
+{
+ int32_t ret;
+ const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ unsigned char intermediate_key[AES_KEY_LEN];
+
+ // First round of HKDF: salt1
+ if ((ret = mbedtls_hkdf(md, sals, NOISE_SIZE, sharedSecret, secretLen,
+ NULL, 0, intermediate_key, AES_KEY_LEN)) != 0) {
+ return ret;
+ }
+
+ // Second round HKDF: salt2, Attach protocol identifier to info2
+ const char *info2 = "HKDF-Round2";
+ // IKM is the output of the previous round, Covering the intermediate key
+ if ((ret = mbedtls_hkdf(md, sals + NOISE_SIZE, NOISE_SIZE, intermediate_key, AES_KEY_LEN,
+ (const unsigned char *)info2, strlen(info2), intermediate_key, AES_KEY_LEN)) != 0) {
+ return ret;
+ }
+
+ // Third round HKDF: salt3, Fixed protocol identification
+ const char *info3 = "AES128-CBC-Key";
+ if ((ret = mbedtls_hkdf(md, sals + NOISE_SIZE + NOISE_SIZE, NOISE_SIZE, intermediate_key, AES_KEY_LEN,
+ (const unsigned char *)info3, strlen(info3), finalKey, keyLen)) != 0) {
+ return ret;
+ }
+ memset_s(intermediate_key, AES_KEY_LEN, 0, AES_KEY_LEN);
+ return 0;
+}
+
+int32_t ComputeSharedSecret(EcdhEntity *local, EcdhEntity *peer, mbedtls_ctr_drbg_context *drbg,
+ unsigned char pubKeyFileName[PUBLIC_KEY_FILE_LEN], mbedtls_entropy_context *entropy)
+{
+ int32_t ret;
+ mbedtls_mpi z;
+ mbedtls_mpi_init(&z);
+ unsigned char sharedSecret[SHARED_SECRET_SIZE] = {0};
+ // 1. Analyze the public key of the opposite end
+ mbedtls_ecp_point peer_Q;
+ mbedtls_ecp_point_init(&peer_Q);
+ ret = mbedtls_ecp_point_read_binary(&local->grp, &peer_Q, peer->pubKey, peer->pubKeyLen);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecp_point_read_binary failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+ // 2. Calculate shared key
+ ret = mbedtls_ecdh_compute_shared(&local->grp, &z, &peer_Q, &local->d, mbedtls_ctr_drbg_random, drbg);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecdh_compute_shared failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+ unsigned char saltInfoPool[SALT_INFO_POOL_ROWS * NOISE_SIZE] = {0};
+ mbedtls_ctr_drbg_random(drbg, saltInfoPool, NOISE_SIZE * SALT_INFO_POOL_ROWS);
+ /*
+ * Optimizing the performance of converting each byte into two hexadecimal characters
+ * using the lookup table method.
+ */
+ const char hexTable[] = "0123456789ABCDEF";
+ for (int i = 0; i < SALT_INFO_POOL_ROWS * NOISE_SIZE; i++) {
+ pubKeyFileName[i * 2] = hexTable[saltInfoPool[i] >> 4]; // Move 4 positions to the right
+ pubKeyFileName[i * 2 + 1] = hexTable[saltInfoPool[i] & 0x0F];
+ }
+ ret = memcpy_s(pubKeyFileName + SALT_INFO_POOL_ROWS * NOISE_SIZE * 2, strlen(TARGET_PEM), TARGET_PEM,
+ strlen(TARGET_PEM));
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "memcpy_s failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+ pubKeyFileName[PUBLIC_KEY_FILE_LEN - 1] = '\0';
+ // 3. Convert to byte stream
+ ret = mbedtls_mpi_write_binary(&z, sharedSecret, SHARED_SECRET_SIZE);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_mpi_write_binary failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+ // HKDF derived working key (parameters must be consistent with the counterpart)
+ if ((ret = TripleHkdfDerive(sharedSecret, sizeof(sharedSecret), saltInfoPool,
+ local->workKey, sizeof(local->workKey))) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Three failed HKDF attempts: -0x%04x\n", -ret);
+ goto cleanup;
+ }
+cleanup:
+ mbedtls_mpi_free(&z);
+ mbedtls_ecp_point_free(&peer_Q);
+ memset_s(sharedSecret, sizeof(sharedSecret), 0, sizeof(sharedSecret));
+ return ret;
+}
+
+// Extract private key as byte array
+int32_t GetPrivateKey(EcdhEntity *entity, unsigned char *eccPrivKey, size_t *eccPrivKeyLen)
+{
+ if (mbedtls_mpi_size(&entity->d) > *eccPrivKeyLen) {
+ return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+ }
+
+ *eccPrivKeyLen = mbedtls_mpi_size(&entity->d);
+ return mbedtls_mpi_write_binary(&entity->d, eccPrivKey, *eccPrivKeyLen);
+}
+
+int32_t CreateCubdirAndFile(const char *subdir, const char *filename, const void *data, size_t size)
+{
+ // 1. Create the client's public key directory and file for the first boot, and grant the file 0755 permission
+ if (mkdir(subdir, 0755) != 0) {
+ if (errno != EEXIST) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to create subdirectories!");
+ return PKCS7_FILE_OPERATION_FAIL;
+ }
+ }
+
+ // 2. Build a complete file path
+ char fullpath[PUB_KEY_FILE_FULL_NAME_LEN];
+ int32_t ret = snprintf_s(fullpath, sizeof(fullpath), sizeof(fullpath) - 1, "%s/%s", subdir, filename);
+ if (ret < 0 || ret >= sizeof(fullpath)) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Path truncated!");
+ return PKCS7_INVALID_PARAM;
+ }
+ // 3. Create and write files
+ FILE *fp = fopen(fullpath, "wb");
+ if (!fp) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to create file");
+ return PKCS7_FILE_OPERATION_FAIL;
+ }
+
+ if (data && size > 0) {
+ if (fwrite(data, 1, size, fp) != size) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Fail to write to file!");
+ fclose(fp);
+ return PKCS7_FILE_OPERATION_FAIL;
+ }
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+// Check if there is a. pem file in the directory
+bool CheckPemExists(const char *dirPath)
+{
+ DIR *dir = opendir(dirPath);
+ if (!dir) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Fail to open dir:%s!", dirPath);
+ return false;
+ }
+
+ struct dirent *entry;
+ bool hasPem = false;
+ while ((entry = readdir(dir)) != NULL) {
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+ continue;
+ }
+ // Check file extension
+ const char *ext = strrchr(entry->d_name, '.');
+ if (ext && strcmp(ext, TARGET_PEM) == 0) {
+ hasPem = true;
+ break;
+ }
+ }
+
+ closedir(dir);
+ return hasPem;
+}
+
+static int32_t GetClientECCPubKey(EcdhEntity *entity, unsigned char *clientPubKey)
+{
+ // Convert the public key to PEM format and write it to a file
+ mbedtls_pk_context pk;
+ mbedtls_pk_init(&pk);
+
+ // Bind ECC key context
+ int32_t ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_pk_setup failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+
+ // Copy curve parameters and public key to pk context
+ mbedtls_ecp_keypair *ec_key = mbedtls_pk_ec(pk);
+ ret = mbedtls_ecp_group_copy(&ec_key->MBEDTLS_PRIVATE(grp), &entity->grp);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecp_group_copy failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+
+ ret = mbedtls_ecp_copy(&ec_key->MBEDTLS_PRIVATE(Q), &entity->Q);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_ecp_copy failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+
+ // Generate PEM format public key
+ ret = mbedtls_pk_write_pubkey_pem(&pk, clientPubKey, ECC_PEN_KEY_LEN);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_pk_write_pubkey_pem failed: -0x%04X\n", -ret);
+ goto cleanup;
+ }
+cleanup:
+ mbedtls_pk_free(&pk);
+ return ret;
+}
+
+int32_t PKCS7_GenerateECCKeypair()
+{
+ unsigned char clientPubKey[ECC_PEN_KEY_LEN];
+ EcdhEntity client = {0};
+ EcdhEntity peer = {0};
+ if (CheckPemExists(DIALMARKET_PUBKEY_PATH)) {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "The public key already exists!");
+ return 0;
+ }
+ unsigned char pubKeyFileName[PUBLIC_KEY_FILE_LEN] = {0};
+ // ECDH negotiation
+ mbedtls_ctr_drbg_context drbg;
+ mbedtls_entropy_context entropy;
+ int32_t ret = InitDrbg(&drbg, &entropy);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to InitDrbg!\n");
+ return ret;
+ }
+ // 1. Generate client key pairs
+ ret = InitEcdhEntity(&client, &drbg);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to init ecdh entity!\n");
+ return ret;
+ }
+ // Server public key
+ const uint8_t server_pub_key[PUB_KEY_SIZE] = {
+ 0x04, 0x67, 0x6E, 0xFF, 0x58, 0x0E, 0xB2, 0x64, 0x79, 0x40, 0x29, 0x9C, 0xBB, 0x1A, 0xE6,
+ 0x22, 0xA2, 0x62, 0x8F, 0x06, 0xDA, 0x74, 0x0C, 0xAC, 0x88, 0x1D, 0x8D, 0x40, 0xBE, 0xB8,
+ 0xC9, 0xE3, 0x79, 0x9F, 0x32, 0x66, 0x5D, 0xEC, 0xF1, 0xBA, 0xCF, 0x03, 0x10, 0x1B, 0x80,
+ 0xD0, 0x8B, 0xF8, 0xF0, 0x56, 0x01, 0x74, 0x30, 0xC3, 0x20, 0x18, 0x5B, 0x83, 0x5F, 0xA4,
+ 0xA0, 0x90, 0x6E, 0x53, 0x89
+ };
+ ret = memcpy_s(peer.pubKey, PUB_KEY_SIZE, server_pub_key, PUB_KEY_SIZE);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to init ecdh entity!\n");
+ return ret;
+ }
+ peer.pubKeyLen = PUB_KEY_SIZE;
+ ret = ComputeSharedSecret(&client, &peer, &drbg, pubKeyFileName, &entropy);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to compute shared secret!\n");
+ goto cleanup;
+ }
+ ret = PKCS7_SaveKeyToNv(client.workKey, AES_KEY_LEN, NV_KEY_ID);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to PKCS7_SaveKeyToNv!\n");
+ goto cleanup;
+ }
+ ret = GetClientECCPubKey(&client, clientPubKey);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to GetClientECCPubKey!\n");
+ goto cleanup;
+ }
+ if (CreateCubdirAndFile(DIALMARKET_PUBKEY_PATH, pubKeyFileName, clientPubKey, strlen(clientPubKey)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Public key write failed!");
+ ret = MBEDTLS_ERR_PK_FILE_IO_ERROR;
+ goto cleanup;
+ }
+
+cleanup:
+ mbedtls_ecp_group_free(&client.grp);
+ mbedtls_mpi_free(&client.d);
+ mbedtls_ecp_point_free(&client.Q);
+ memset_s(&client, sizeof(client), 0, sizeof(client));
+ mbedtls_ctr_drbg_free(&drbg);
+ mbedtls_entropy_free(&entropy);
+ return ret;
+}
+
+static int32_t verifyCertChain(FILE *fp, const MetadataStruct *meta, mbedtls_x509_crt *certChain)
+{
+ int32_t ret = 0;
+ uint32_t flags = 0;
+ unsigned char *appCert = NULL;
+ mbedtls_x509_crt rootCert;
+ mbedtls_x509_crt_init(&rootCert);
+ if ((ret = mbedtls_x509_crt_parse(&rootCert, g_dialRootCertInPem, sizeof(g_dialRootCertInPem))) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Root certificate parsing failed: -0x%04X!", -ret);
+ goto cleanup;
+ }
+
+ // Read and parse application certificates
+ appCert = Pkcs7Calloc(meta->appCertLen + 1, sizeof(char));
+ if (appCert == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "malloc failed!");
+ ret = PKCS7_MEMORY_EXHAUST;
+ goto cleanup;
+ }
+ fseek(fp, meta->sigOffset + meta->sigLen, SEEK_SET);
+ if (fread(appCert, 1, meta->appCertLen, fp) != meta->appCertLen) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Read app cert failed!");
+ ret = PKCS7_FILE_OPERATION_FAIL;
+ goto cleanup;
+ }
+ appCert[meta->appCertLen] = '\0';
+ if ((ret = mbedtls_x509_crt_parse(certChain, appCert, meta->appCertLen + 1)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Application certificate parsing failed: -0x%04X!", -ret);
+ goto cleanup;
+ }
+ // Read and parse intermediate certificates
+ unsigned char *interCert = Pkcs7Calloc(meta->intermediateCertLen + 1, sizeof(char));
+ if (interCert == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "malloc for intermediate cert failed!");
+ ret = PKCS7_MEMORY_EXHAUST;
+ goto cleanup;
+ }
+ fseek(fp, meta->sigOffset + meta->sigLen + meta->appCertLen, SEEK_SET);
+ if (fread(interCert, 1, meta->intermediateCertLen, fp) != meta->intermediateCertLen) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Intermediate certificate read failed!");
+ ret = PKCS7_FILE_OPERATION_FAIL;
+ goto cleanup;
+ }
+ interCert[meta->intermediateCertLen] = '\0';
+ if ((ret = mbedtls_x509_crt_parse(certChain, interCert, meta->intermediateCertLen + 1)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Intermediate certificate parsing failed: -0x%04X!", -ret);
+ goto cleanup;
+ }
+ // Verify certificate chain
+ if ((ret = mbedtls_x509_crt_verify(certChain, &rootCert, NULL, NULL, &flags, NULL, NULL)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Certificate chain verification failed: -0x%04X!", -ret);
+ }
+
+cleanup:
+ if (appCert) {
+ Pkcs7Free(appCert);
+ appCert = NULL;
+ }
+ if (interCert) {
+ Pkcs7Free(interCert);
+ interCert = NULL;
+ }
+ mbedtls_x509_crt_free(&rootCert);
+ return ret;
+}
+
+int32_t AesCrypt(const AesParams *params)
+{
+ if (params == NULL || params->ctx == NULL || params->key == NULL || params->iv == NULL || params->input == NULL ||
+ params->output == NULL || params->olen == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Invalid AES parameters");
+ return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+ }
+
+ int32_t ret = 0;
+ if ((ret = mbedtls_cipher_reset(params->ctx)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Cipher reset failed: -0x%04X", -ret);
+ return ret;
+ }
+ // 128 is the length of key for AES128
+ if ((ret = mbedtls_cipher_setkey(params->ctx, params->key, 128, MBEDTLS_DECRYPT)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Set key failed: -0x%04X", -ret);
+ return ret;
+ }
+
+ if ((ret = mbedtls_cipher_set_padding_mode(params->ctx, params->paddingMode)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Set padding failed: -0x%04X", -ret);
+ return ret;
+ }
+
+ if ((ret = mbedtls_cipher_crypt(params->ctx, params->iv, AES_KEY_LEN, params->input, params->ilen,
+ params->output, params->olen)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Cryption failed: -0x%04X", -ret);
+ }
+ return ret;
+}
+
+static int32_t VerifySignature(FILE *fp, const MetadataStruct *meta, mbedtls_x509_crt *certChain, unsigned char *hash)
+{
+ int32_t ret = 0;
+ unsigned char *sigBuf = Pkcs7Calloc(meta->sigLen, sizeof(char));
+ if (sigBuf == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "memory allocation failed!");
+ return PKCS7_MEMORY_EXHAUST;
+ }
+
+ // Read signature data
+ fseek(fp, meta->sigOffset, SEEK_SET);
+ if (fread(sigBuf, 1, meta->sigLen, fp) != meta->sigLen) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Signature reading failed!");
+ ret = PKCS7_FILE_OPERATION_FAIL;
+ goto exit;
+ }
+ // verify signature
+ mbedtls_pk_rsassa_pss_options pss_options = {
+ .mgf1_hash_id = MBEDTLS_MD_SHA256,
+ .expected_salt_len = SHA256_HASH_SIZE // Must be consistent with the SaltLength on the Java side
+ };
+ // Pass PSS parameters when calling the verification interface
+ ret = mbedtls_pk_verify_ext(MBEDTLS_PK_RSASSA_PSS, &pss_options, &certChain->pk, MBEDTLS_MD_SHA256,
+ hash, SHA256_HASH_SIZE, sigBuf, meta->sigLen);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Verification of dial signature failed!, ret:%d", ret);
+ }
+exit:
+ if (sigBuf != NULL) {
+ Pkcs7Free(sigBuf);
+ sigBuf = NULL;
+ }
+ return ret;
+}
+
+static int32_t VerifySignatureStream(FILE *fp, const MetadataStruct *meta, mbedtls_x509_crt *certChain,
+ const unsigned char *restoredData, size_t restoredLen)
+{
+ int32_t ret = 0;
+ unsigned char hash[SHA256_HASH_SIZE] = {0};
+ mbedtls_md_context_t mdCtx;
+ size_t unencryptedLen = 0;
+ size_t processed = 0;
+ unsigned char *buffer = Pkcs7Calloc(CHUNK_SIZE, sizeof(char));
+ if (buffer == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "memory allocation failed!");
+ return PKCS7_MEMORY_EXHAUST;
+ }
+ size_t baseSize = FRONT_FIXED_SIZE + meta->dialViewCount;
+ unencryptedLen = meta->originalLen - baseSize;
+ mbedtls_md_init(&mdCtx);
+ mbedtls_md_setup(&mdCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+ mbedtls_md_starts(&mdCtx);
+ size_t processedRestored = 0;
+ fseek(fp, meta->encryptedLen - meta->padLen, SEEK_SET);
+ // 1. Process decrypted encrypted data blocks (including padding)
+ while (processedRestored < restoredLen) {
+ // Logic for Filling Buffer Zones
+ size_t remainingRestored = restoredLen - processedRestored;
+ size_t copySize = (remainingRestored > CHUNK_SIZE) ? CHUNK_SIZE : remainingRestored;
+ // Copy decrypted data to the buffer
+ ret = memcpy_s(buffer, copySize, restoredData + processedRestored, copySize);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Verification of dial signature failed!, ret:%d", ret);
+ ret = PKCS7_MEMORY_EXHAUST;
+ goto exit;
+ }
+ // If the buffer is not filled, try supplementing data from the file
+ if (copySize < CHUNK_SIZE) {
+ size_t need_read = CHUNK_SIZE - copySize;
+ size_t actually_read = fread(buffer + copySize, 1, need_read, fp);
+ copySize += actually_read;
+ }
+
+ // Update hash calculation
+ mbedtls_md_update(&mdCtx, buffer, copySize);
+ processedRestored += copySize;
+
+ // If it exceeds the original data range, jump out
+ if (processedRestored > restoredLen) {
+ break;
+ }
+ }
+
+ // 2. Process remaining unencrypted data
+ unencryptedLen -= processedRestored - restoredLen;
+ if (unencryptedLen > 0) {
+ while (processed < unencryptedLen) {
+ size_t remaining = unencryptedLen - processed;
+ size_t chunk = (remaining > CHUNK_SIZE) ? CHUNK_SIZE : remaining;
+
+ // Read unencrypted data blocks directly from files
+ if (fread(buffer, 1, chunk, fp) != chunk) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to read unencrypted data!");
+ ret = PKCS7_FILE_OPERATION_FAIL;
+ goto exit;
+ }
+ mbedtls_md_update(&mdCtx, buffer, chunk);
+ processed += chunk;
+ }
+ // Verify if it has been fully read
+ if (processed != unencryptedLen) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Unencrypted data length mismatch!", processed, unencryptedLen);
+ ret = PKCS7_INVALID_PARAM;
+ goto exit;
+ }
+ }
+ // Complete hash calculation
+ mbedtls_md_finish(&mdCtx, hash);
+
+ ret = VerifySignature(fp, meta, certChain, hash);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "VerifySignature failed!");
+ }
+exit:
+ mbedtls_md_free(&mdCtx);
+ if (buffer != NULL) {
+ Pkcs7Free(buffer);
+ buffer = NULL;
+ }
+ return ret;
+}
+
+static int32_t DecryptAesKey(mbedtls_cipher_context_t *ctx, const MetadataStruct *meta, const uint8_t *eccWorkKey,
+ unsigned char *aesKey)
+{
+ size_t olen = AES_KEY_LEN;
+ AesParams params = {
+ .ctx = ctx,
+ .key = eccWorkKey,
+ .iv = meta->iv2,
+ .input = meta->password,
+ .ilen = sizeof(meta->password),
+ .output = aesKey,
+ .olen = &olen,
+ .paddingMode = MBEDTLS_PADDING_NONE
+ };
+ int32_t ret = AesCrypt(¶ms);
+ if (ret == 0 && olen != AES_KEY_LEN) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Invalid AES key length: %zu", olen);
+ return PKCS7_INVALID_PARAM;
+ }
+ return ret;
+}
+
+static int32_t ReadAndPrepareData(FILE *fp, const MetadataStruct *meta, unsigned char **encryptedData, size_t *dataLen)
+{
+ *encryptedData = Pkcs7Calloc(meta->encryptedLen, 1);
+ if (*encryptedData == NULL) {
+ return PKCS7_MEMORY_EXHAUST;
+ }
+
+ fseek(fp, 0, SEEK_SET);
+ size_t readLen = fread(*encryptedData, 1, meta->encryptedLen - meta->padLen, fp);
+ if (readLen != meta->encryptedLen - meta->padLen) {
+ Pkcs7Free(*encryptedData);
+ return PKCS7_FILE_OPERATION_FAIL;
+ }
+
+ if (memcpy_s(*encryptedData + readLen, meta->padLen, meta->padData, meta->padLen) != 0) {
+ Pkcs7Free(*encryptedData);
+ return PKCS7_MEMORY_EXHAUST;
+ }
+
+ *dataLen = meta->encryptedLen;
+ return 0;
+}
+
+int32_t PKCS7_VerifyAndDecrypt(FILE *fp, bool firstLoad, MetadataStruct *meta, unsigned char *restoredBuf,
+ uint32_t originalLen)
+{
+ int32_t ret = 0;
+ unsigned char aesKey[AES_KEY_LEN] = {0};
+ uint8_t eccWorkKey[AES_KEY_LEN] = {0};
+ mbedtls_x509_crt *certChain = NULL;
+ mbedtls_cipher_context_t ctx;
+ unsigned char *encryptedData = NULL;
+ size_t dataLen = 0;
+
+ // Parameter validation
+ if (fp == NULL || meta == NULL || restoredBuf == NULL || originalLen < meta->encryptedLen) {
+ return PKCS7_INVALID_PARAM;
+ }
+
+ mbedtls_cipher_init(&ctx);
+ const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CBC);
+
+ // Setup cipher context
+ if ((ret = mbedtls_cipher_setup(&ctx, info)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Cipher setup failed: -0x%04X", -ret);
+ goto cleanup;
+ }
+
+ // ECC key handling
+ if (meta->pubKeyType == ENC_TYPE_ECC) {
+ if ((ret = PKCS7_GetKeyFromNv(NV_KEY_ID, eccWorkKey)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Get ECC key failed: %d", ret);
+ goto cleanup;
+ }
+ if ((ret = DecryptAesKey(&ctx, meta, eccWorkKey, aesKey)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Decrypt AES key failed: %d", ret);
+ goto cleanup;
+ }
+ }
+
+ // Read and decrypt data
+ if ((ret = ReadAndPrepareData(fp, meta, &encryptedData, &dataLen)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Read data failed: %d", ret);
+ goto cleanup;
+ }
+
+ size_t olen = meta->encryptedLen;
+ AesParams decryptParams = {
+ .ctx = &ctx,
+ .key = aesKey,
+ .iv = meta->iv1,
+ .input = encryptedData,
+ .ilen = dataLen,
+ .output = restoredBuf,
+ .olen = &olen,
+ .paddingMode = MBEDTLS_PADDING_PKCS7
+ };
+ if ((ret = AesCrypt(&decryptParams)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Decrypt failed: %d", ret);
+ goto cleanup;
+ }
+
+ // Signature verification for first load
+ if (firstLoad) {
+ if ((certChain = Pkcs7Calloc(1, sizeof(mbedtls_x509_crt))) == NULL) {
+ ret = PKCS7_MEMORY_EXHAUST;
+ goto cleanup;
+ }
+ mbedtls_x509_crt_init(certChain);
+
+ if ((ret = verifyCertChain(fp, meta, certChain)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Cert chain failed: %d", ret);
+ goto cleanup;
+ }
+
+ if ((ret = VerifySignatureStream(fp, meta, certChain, restoredBuf, olen)) != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Signature failed: %d", ret);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (certChain != NULL) {
+ mbedtls_x509_crt_free(certChain);
+ free(certChain);
+ }
+ if (encryptedData != NULL) {
+ Pkcs7Free(encryptedData);
+ }
+ mbedtls_cipher_free(&ctx);
+ memset_s(aesKey, AES_KEY_LEN, 0, AES_KEY_LEN);
+ memset_s(eccWorkKey, AES_KEY_LEN, 0, AES_KEY_LEN);
+ return ret;
+}
+
+static int32_t VerifyHashList()
+{
+ int32_t rc = 0;
+ const char *hashListFile = OEM_CERT_PATH"root_cert_hash_list.bin";
+ const char *signatureFile = OEM_CERT_PATH"hash_list_sign.bin";
+ unsigned char hash[SHA256_HASH_SIZE];
+ mbedtls_pk_context pk;
+ FILE *file = fopen(hashListFile, "rb");
+ if (!file) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to open file to verify.");
+ return PKCS7_VERIFY_FAIL;
+ }
+ rc = fseek(file, 0, SEEK_END);
+ if (rc != 0) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ long fileSize = ftell(file);
+ rc = fseek(file, 0, SEEK_SET);
+ if (rc != 0 || fileSize > INT_MAX) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ unsigned char *fileData = Pkcs7Calloc(fileSize, sizeof(char));
+ if (!fileData) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ int32_t fileLen = fread(fileData, 1, fileSize, file);
+ if (fileLen != fileSize) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ mbedtls_pk_init(&pk);
+ if ((rc = mbedtls_pk_parse_public_key(&pk, (const unsigned char *)ROOT_CA_OEM_PUBKEY_IN_PEM,
+ strlen(ROOT_CA_OEM_PUBKEY_IN_PEM) + 1)) != 0) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
+ mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
+ FILE *sigFile = fopen(signatureFile, "rb");
+ if (!sigFile) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ unsigned char *signature = Pkcs7Calloc(RSA3072_SIG_SIZE, sizeof(char));
+ if (!signature) {
+ rc = PKCS7_HAS_NO_SIGNER_CRT;
+ goto exit;
+ }
+ if (fread(signature, 1, RSA3072_SIG_SIZE, sigFile) != RSA3072_SIG_SIZE) {
+ rc = PKCS7_VERIFY_FAIL;
+ goto exit;
+ }
+ mbedtls_sha256(fileData, fileSize, hash, 0);
+ rc = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, hash, SHA256_HASH_SIZE, signature, RSA3072_SIG_SIZE);
+ if (rc != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "mbedtls_pk_verify failed! return %d\n", rc);
+ goto exit;
+ }
+exit:
+ if (file) {
+ fclose(file);
+ file = NULL;
+ }
+ if (sigFile) {
+ fclose(sigFile);
+ sigFile = NULL;
+ }
+ if (fileData) {
+ Pkcs7Free(fileData);
+ fileData = NULL;
+ }
+ if (signature) {
+ Pkcs7Free(signature);
+ signature = NULL;
+ }
+ mbedtls_pk_free(&pk);
+ return rc;
+}
+#endif
/* valid digest alg now: sha256 sha384 sha512 */
static bool InvalidDigestAlg(const mbedtls_asn1_buf *alg)
MBEDTLS_OID_CMP(MBEDTLS_OID_DIGEST_ALG_SHA512, alg);
}
-/*
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
- */
-static int GetContentInfoType(unsigned char **p, const unsigned char *end,
- mbedtls_asn1_buf *contentType, bool *hasContent)
+static int32_t GetContentInfoType(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *contentType,
+ bool *hasContent)
{
size_t seqLen = 0;
size_t len = 0;
- int rc;
+ int32_t rc;
rc = mbedtls_asn1_get_tag(p, end, &seqLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc) {
contentType->len = len;
contentType->p = *p;
*hasContent = (seqLen != len + (*p - start));
- *p += len; // pass the oid info to the real content location.
+ *p += len; /* pass the oid info to the real content location. */
- return rc;
+ return PKCS7_SUCC;
}
-static int GetContentLenOfContentInfo(unsigned char **p, const unsigned char *end, size_t *len)
+static int32_t GetContentLenOfContentInfo(unsigned char **p, const unsigned char *end, size_t *len)
{
return mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
}
-/*
- * Version ::= INTEGER
- */
-static int ParseSignerVersion(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerVersion(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
return mbedtls_asn1_get_int(p, end, &signer->version);
}
-/*
- * IssuerAndSerialNumber ::= SEQUENCE {
- * issuer Name,
- * serialNumber CertificateSerialNumber }
- *
- * Name ::= CHOICE { -- only one possibility for now --
- * rdnSequence RDNSequence }
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue }
- * AttributeType ::= OBJECT IDENTIFIER
- * AttributeValue ::= ANY -- DEFINED BY AttributeType
- *
- * CertificateSerialNumber ::= INTEGER
- */
-static int ParseSignerIssuerAndSerialNum(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerIssuerAndSerialNum(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc;
+ int32_t rc;
size_t len;
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
return rc;
}
-/*
- * digestAlgorithm DigestAlgorithmIdentifier,
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- * AlgorithmIdentifier ::= SEQUENCE { -- defined in X509
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- * }
- */
-static int ParseSignerDigestAlg(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerDigestAlg(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc = mbedtls_asn1_get_alg_null(p, end, &signer->digestAlgId);
+ int32_t rc = mbedtls_asn1_get_alg_null(p, end, &signer->digestAlgId);
if (rc) {
return rc;
}
if (InvalidDigestAlg(&signer->digestAlgId)) {
return PKCS7_INVALID_DIGEST_ALG;
}
- return rc;
+ return PKCS7_SUCC;
}
-/*
- * authenticatedAttributes? [0] IMPLICIT Attributes OPTIONAL,
- *
- * maybe some attributes
- * contentType, signingTime, messageDigest, unstructuredName
- * each attribute is constructed by a SEQUENCE
- * {
- * OID,
- * SET OF
- * }
- * here do not resolve the real content, just record the location.
- */
-static int ParseSignerAuthAttr(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerAuthAttr(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc;
- size_t len;
-
+ int32_t rc;
+ size_t len = 0;
unsigned char *raw = *p;
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
signer->authAttrRaw.p = raw;
signer->authAttrRaw.len = len + tlLen;
- return rc;
+ return PKCS7_SUCC;
}
/*
MBEDTLS_OID_CMP(MBEDTLS_OID_RSASSA_PSS, alg);
}
-/*
- * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
- * AlgorithmIdentifier ::= SEQUENCE { -- defined in X509
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- * }
- *
- */
-static int ParseSignerEncAlg(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerEncAlg(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc;
- mbedtls_asn1_buf params;
+ int32_t rc;
+ mbedtls_asn1_buf params = {0};
/* params not be used now */
rc = mbedtls_asn1_get_alg(p, end, &signer->digestEncAlgId, ¶ms);
if (rc) {
if (InvalidDigestEncAlg(&signer->digestEncAlgId)) {
return PKCS7_INVALID_SIGNING_ALG;
}
- return rc;
+ return PKCS7_SUCC;
}
/*
* encryptedDigest EncryptedDigest,
* EncryptedDigest ::= OCTET STRING
*/
-static int ParseSignerSignature(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerSignature(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (rc) {
signer->signature.len = len;
signer->signature.p = *p;
*p += len;
- return rc;
+ return PKCS7_SUCC;
}
-/* This must be called after pkcs7 parsed
- * OCTET STRING encode could be use primitive or constructed ?
- * we use constructed here.
- */
-static int GetSignerSignature(const SignerInfo *signer, unsigned char **sig, size_t *sigLen)
+static int32_t GetSignerSignature(const SignerInfo *signer, unsigned char **sig, size_t *sigLen)
{
size_t len = signer->signature.len;
unsigned char *buf = signer->signature.p;
return PKCS7_SUCC;
}
-/*
- * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL,
- */
-static int ParseSignerUnAuthAttr(unsigned char **p, const unsigned char *end, SignerInfo *signer)
+static int32_t ParseSignerUnAuthAttr(unsigned char **p, const unsigned char *end, SignerInfo *signer)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
/* the optional unauth attr is not exist */
if (end - *p < 1) {
signer->unAuthAttr.len = len;
signer->unAuthAttr.p = *p;
*p += len;
- return rc;
+ return PKCS7_SUCC;
}
-static int SerialCmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)
+static int32_t SerialCmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)
{
if (a->len == b->len && memcmp(a->p, b->p, a->len) == 0) {
return 0;
}
return -1;
}
-/*
- * below three function is from mbedtls because mbedtls not provide interface
- * of name compare.
- */
+
#define DIFF_NUM 32
-static int X509_MemcaseCmp(const void *s1, const void *s2, size_t len)
+static bool IsLegitString(int32_t tag)
{
- size_t i;
- unsigned char diff;
- const unsigned char *n1 = s1;
- const unsigned char *n2 = s2;
-
- for (i = 0; i < len; i++) {
- diff = n1[i] ^ n2[i];
-
- if (diff == 0) {
- continue;
- }
-
- if (diff == DIFF_NUM &&
- ((n1[i] >= 'a' && n1[i] <= 'z') ||
- (n1[i] >= 'A' && n1[i] <= 'Z'))) {
- continue;
- }
- return -1;
+ if (tag == MBEDTLS_ASN1_UTF8_STRING || tag == MBEDTLS_ASN1_PRINTABLE_STRING) {
+ return true;
}
-
- return 0;
+ return false;
}
-static int X509_StringCmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)
+static int32_t CompareX509String(const mbedtls_x509_buf *first, const mbedtls_x509_buf *second)
{
- if (a->tag == b->tag &&
- a->len == b->len &&
- memcmp(a->p, b->p, b->len) == 0) {
- return 0;
- }
-
- if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
- (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
- a->len == b->len &&
- X509_MemcaseCmp(a->p, b->p, b->len) == 0) {
+ if (IsLegitString(first->tag) && IsLegitString(second->tag)) {
+ for (int32_t i = 0; i < first->len; i++) {
+ if (first->p[i] == second->p[i] ||
+ ((islower(first->p[i]) != 0) && (first->p[i] - DIFF_NUM == second->p[i])) ||
+ ((isupper(first->p[i]) != 0) && (first->p[i] + DIFF_NUM == second->p[i]))) {
+ continue;
+ }
+ return -1;
+ }
return 0;
}
-
return -1;
}
-static int X509_NameCmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b)
+static int32_t GetDeps(const mbedtls_x509_name *nameList)
{
- /* Avoid recursion, it might not be optimised by the compiler */
- while (a != NULL || b != NULL) {
- if (a == NULL || b == NULL) {
- return -1;
- }
-
- /* type */
- if (a->oid.tag != b->oid.tag ||
- a->oid.len != b->oid.len ||
- memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) {
- return -1;
- }
-
- /* value */
- if (X509_StringCmp(&a->val, &b->val) != 0) {
- return -1;
- }
-
- /* structure of the list of sets */
- if (a->next_merged != b->next_merged) {
- return -1;
- }
-
- a = a->next;
- b = b->next;
+ int32_t deps = 0;
+ while (nameList != NULL) {
+ nameList = nameList->next;
+ deps++;
}
-
- return 0;
+ return deps;
}
-static void *Pkcs7Calloc(size_t nmemb, size_t size)
+static int32_t CompareX509NameList(const mbedtls_x509_name *first, const mbedtls_x509_name *second)
{
-#if (RUNNING_BOARD == LITE_WEARABLE)
- void *ptr = PSRAM_Malloc(nmemb * size);
- if (ptr == NULL) {
- return NULL;
+ if (first == NULL || second == NULL) {
+ return -1;
}
- (void)memset_s(ptr, nmemb * size, 0, nmemb * size);
- return ptr;
-#else
- return calloc(nmemb, size);
-#endif
+ int32_t firstDeps = GetDeps(first);
+ int32_t secondDeps = GetDeps(second);
+ if (firstDeps != secondDeps) {
+ return -1;
+ }
+ for (int32_t i = 0; i < firstDeps; i++) {
+ if (first->oid.tag != second->oid.tag ||
+ first->oid.len != second->oid.len ||
+ memcmp(first->oid.p, second->oid.p, second->oid.len) != 0 ||
+ first->MBEDTLS_PRIVATE(next_merged) != second->MBEDTLS_PRIVATE(next_merged) ||
+ first->val.len != second->val.len) {
+ return -1;
+ }
+ if (CompareX509String(&first->val, &second->val) != 0) {
+ return -1;
+ }
+ first = first->next;
+ second = second->next;
+ }
+ return 0;
}
-static void Pkcs7Free(void *ptr)
-{
-#if (RUNNING_BOARD == LITE_WEARABLE)
- PSRAM_Free(ptr);
-#else
- free(ptr);
-#endif
-}
-/*
- * SET OF SignerInfo
- * SignerInfo ::= SEQUENCE {
- * version Version,
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * digestAlgorithm DigestAlgorithmIdentifier,
- * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
- * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- * encryptedDigest EncryptedDigest,
- * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL,
- */
-static int ParseSignedDataSignerInfos(unsigned char **p, const unsigned char *end, SignerInfo *signers)
+static int32_t ParseSignedDataSignerInfos(unsigned char **p, const unsigned char *end, SignerInfo *signers)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET);
if (rc || len == 0) {
signers = signers->next;
}
}
-
-OUT:
return rc;
}
-static int ParseSignedDataVersion(unsigned char **p, const unsigned char *end, int *ver)
+static int32_t ParseSignedDataVersion(unsigned char **p, const unsigned char *end, int32_t *ver)
{
- int rc = mbedtls_asn1_get_int(p, end, ver);
+ int32_t rc = mbedtls_asn1_get_int(p, end, ver);
if (rc) {
return rc;
}
if (*ver != PKCS7_SIGNED_DATA_VERSION) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Invalid version : %d", *ver);
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Invalid version : %d\n", *ver);
return PKCS7_INVALID_VERSION;
}
- HILOG_INFO(LOG_MODULE_AAFWK, "Parse signed data version success");
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Parse signed data version success\n");
return PKCS7_SUCC;
}
-/*
- * digestAlgorithms DigestAlgorithmIdentifiers
- * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- * AlgorithmIdentifier ::= SEQUENCE { -- defined in X509
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- * }
- */
-static int ParseSignedDataDigestAlgs(unsigned char **p, const unsigned char *end, DigestAlgId *algIds)
+static int32_t ParseSignedDataDigestAlgs(unsigned char **p, const unsigned char *end, DigestAlgId *algIds)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
/* parse SET OF header */
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET);
/* parse SET OF 's digest alg content */
DigestAlgId *id = algIds;
- id->next = NULL;
while (*p < end) {
- mbedtls_asn1_buf params;
+ mbedtls_asn1_buf params = {0};
/* alg param is supported, but not be used now */
rc = mbedtls_asn1_get_alg(p, end, &id->algBuf, ¶ms);
if (rc) {
return PKCS7_SUCC;
}
-/*
- * parse signedData's content info, what content is defined by user.
- * it maybe store the original data be signed, or the calculated hash of original data.
- * here just get the content data, do not resolved the detail info.
- *
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
- */
-static int ParseSignedDataContentInfo(unsigned char **p, const unsigned char *end, Content *content)
+static void DlogContentInfo(const Content *content)
{
- int rc;
- size_t len;
+ int32_t len = content->data.len;
+ if (len <= 0) {
+ return;
+ }
+ char *info = Pkcs7Calloc(len + 1, sizeof(char));
+ if (info == NULL) {
+ return;
+ }
+ if (strncpy_s(info, len + 1, (char *)content->data.p, len) != EOK) {
+ Pkcs7Free(info);
+ return;
+ }
+ Pkcs7Free(info);
+}
+
+static int32_t ParseSignedDataContentInfo(unsigned char **p, const unsigned char *end, Content *content)
+{
+ int32_t rc;
+ size_t len = 0;
bool hasContent = false;
rc = GetContentInfoType(p, end, &content->oid, &hasContent);
if (rc) {
return rc;
}
- /*
- * for our use case, the optional content must has real content info.
- *
- * rfc2315(PKCS#7) 9.1 shows this:
- * contentInfo is the content that is signed. It can have __any__ of the defined content types
- * rfc2315(PKCS#7) 9.2 shows this:
- * authenticatedAttributes is a set of attributes that are signed (i.e., authenticated) by the signer.
- * The field is optional, but it must be present if the content type of the ContentInfo value being
- * signed __is not data__.
- * So the oid is allowed to be non-MBEDTLS_OID_PKCS7_DATA type? if so, delete below oid type check.
- * It defined six content types:data, signedData, envelopedData, signedAndEnvelopedData, digestedData,
- * and encryptedData.
- * As current content info is in signedData, so i think it can not be other content type other than data.
- * It is MBEDTLS_OID_PKCS7_DATA for all of pkcs7-signed-data packages signed by signning tools now.
- */
- if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content->oid) || hasContent == false) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Invalid content type or has no real content");
+
+ if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content->oid) || !hasContent) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Invalid content type or has no real content");
return PKCS7_INVALID_CONTENT_TYPE_OR_NO_CONTENT;
}
rc = GetContentLenOfContentInfo(p, end, &len);
content->data.tag = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC; // has no use
content->data.p = *p;
content->data.len = len;
+ DlogContentInfo(content);
*p += len;
- return rc;
+ return PKCS7_SUCC;
}
-/*
- * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
- * ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate
- * ExtendedCertificateOrCertificate ::= CHOICE {
- * certificate Certificate, -- X.509
- * extendedCertificate [0] IMPLICIT ExtendedCertificate }
- * Certificate ::= SEQUENCE {
- * tbsCertificate TBSCertificate,
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING }
- */
-static int ParseSignedDataCerts(unsigned char **p, const unsigned char *end, mbedtls_x509_crt **certs)
+static int32_t ParseSignedDataCerts(unsigned char **p, const unsigned char *end, mbedtls_x509_crt **certs)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Has no certificates in signed data.");
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Has no certificates in signed data.");
return PKCS7_SUCC;
}
*certs = mbedtls_calloc(1, sizeof(**certs));
mbedtls_x509_crt_init(*certs);
unsigned char *certsEnd = *p + len;
- int cnt = 0;
+ int32_t cnt = 0;
while (*p < certsEnd) {
/* scan every cert */
size_t oneCertLen;
unsigned char *seqBegin = *p;
rc = mbedtls_asn1_get_tag(p, end, &oneCertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc) {
+ mbedtls_free(*certs);
+ *certs = NULL;
return rc;
}
if (oneCertLen + (*p - seqBegin) > (certsEnd - seqBegin)) {
+ mbedtls_free(*certs);
+ *certs = NULL;
return PKCS7_PARSING_ERROR;
}
rc = mbedtls_x509_crt_parse(*certs, seqBegin, oneCertLen + (*p - seqBegin));
if (rc) {
+ mbedtls_free(*certs);
+ *certs = NULL;
return rc;
}
*p += oneCertLen;
cnt++;
}
- HILOG_INFO(LOG_MODULE_AAFWK, "Parse signed data certs success");
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Parse signed data certs success");
return rc;
}
-/*
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * CertificateRevocationLists ::= SET OF CertificateRevocationList
- * defined in RFC 1422
- * CertificateRevocationList ::= SIGNED SEQUENCE {
- * signature AlgorithmIdentifier,
- * issuer Name,
- * lastUpdate UTCTime,
- * nextUpdate UTCTime,
- * revokedCertificates SEQUENCE OF CRLEntry OPTIONAL}
- */
-static int ParseSignedDataCrl(unsigned char **p, const unsigned char *end, mbedtls_x509_crl *crl)
+static int32_t ParseSignedDataCrl(unsigned char **p, const unsigned char *end, mbedtls_x509_crl *crl)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
rc = mbedtls_asn1_get_tag(p, end, &len, (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) + 1);
if (rc) {
- HILOG_INFO(LOG_MODULE_AAFWK, "Has no crl in signed data.");
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Has no crl in signed data.");
return PKCS7_SUCC;
}
- (void)crl;
+ mbedtls_x509_crl_init(crl);
+ rc = mbedtls_x509_crl_parse(crl, *p, len);
*p += len;
return rc;
}
-/*
- * SignedData ::= SEQUENCE {
- * version Version,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * contentInfo ContentInfo,
- * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos }
- */
-static int ParseSignedData(unsigned char *buf, size_t bufLen, SignedData *signedData)
+static mbedtls_x509_crt *FindSuperCert(mbedtls_x509_crt *cur, mbedtls_x509_crt *certsList)
+{
+ /* current level's subject is next level issuer */
+ while (certsList != NULL) {
+ if (CompareX509NameList(&cur->issuer, &certsList->subject) == 0) {
+ break;
+ }
+ certsList = certsList->next;
+ }
+ return certsList;
+}
+
+static int32_t LoadSelfSignedCert(void)
+{
+ mbedtls_x509_crt_init(&g_ohosRootCert);
+ int32_t rc = mbedtls_x509_crt_parse(&g_ohosRootCert, OHOS_ROOT_CERT_IN_PEM, sizeof(OHOS_ROOT_CERT_IN_PEM));
+ if (rc) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK,"load oh signed ca failed %d", rc);
+ return rc;
+ } else {
+ HILOG_INFO(HILOG_MODULE_AAFWK,"load oh signed root ca success");
+ }
+ return rc;
+}
+
+static int32_t FindAndStoreRootCert(mbedtls_x509_crt *topCert)
+{
+ int32_t rc = PKCS7_PARSING_ERROR;
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ char certPath[MAX_CERTPATH_LEN];
+ if (access(OEM_CERT_PATH, F_OK) != 0) {
+ HILOG_DEBUG(HILOG_MODULE_AAFWK, "Please upload the application root certificate.");
+ return LoadSelfSignedCert();
+ }
+ dir = opendir(OEM_CERT_PATH);
+ if (dir == NULL) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Failed to open certificate directory.");
+ return PKCS7_BUILD_CERT_PATH_FAIL;
+ }
+ while ((entry = readdir(dir)) != NULL) {
+ const char *ext = strrchr(entry->d_name, '.');
+ if (ext == NULL || strcmp(ext, ".pem") != 0) {
+ continue;
+ }
+ rc = snprintf_s(certPath, sizeof(certPath), sizeof(certPath) - 1, OEM_CERT_PATH"%s", entry->d_name);
+ if (rc < 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Get cert path failed, return %d!", rc);
+ continue;
+ }
+ mbedtls_x509_crt tmpRootCert;
+ mbedtls_x509_crt_init(&tmpRootCert);
+ rc = mbedtls_x509_crt_parse_file(&tmpRootCert, certPath);
+ if (rc != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Parse %s failed: %d.", certPath, rc);
+ mbedtls_x509_crt_free(&tmpRootCert);
+ continue;
+ }
+ /* Compare the subject of the device root certificate and the issuer of the uppermost certificate. */
+ if (CompareX509NameList(&tmpRootCert.subject, &topCert->issuer) == 0) {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Found matching root cert: %s.", entry->d_name);
+ /* Reparse the root certificate to g_ohosRootCert. */
+ rc = mbedtls_x509_crt_parse_file(&g_ohosRootCert, certPath);
+ if (rc != 0) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Re-parsing root cert failed: %d!", rc);
+ mbedtls_x509_crt_free(&tmpRootCert);
+ closedir(dir);
+ return PKCS7_HAS_NO_SIGNER_CRT;
+ }
+ rc = PKCS7_SUCC;
+ mbedtls_x509_crt_free(&tmpRootCert);
+ break;
+ }
+ mbedtls_x509_crt_free(&tmpRootCert);
+ }
+
+ closedir(dir);
+ return rc;
+}
+
+static int32_t LoadRootCert()
+{
+ int32_t rc = 0;
+ if (!g_rootCertLoaded) {
+ mbedtls_x509_crt_init(&g_rootCaG2Cert);
+ rc = mbedtls_x509_crt_parse(&g_rootCaG2Cert, g_rootCaG2CertInPem, sizeof(g_rootCaG2CertInPem));
+ if (rc) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "load root ca failed!");
+ return rc;
+ } else {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "load root ca success.");
+ }
+ g_rootCertLoaded = true;
+ }
+ return rc;
+}
+
+static void UnLoadRootCert(void)
+{
+ if (g_rootCertLoaded) {
+ mbedtls_x509_crt_free(&g_rootCaG2Cert);
+ g_rootCertLoaded = false;
+ }
+}
+
+static int32_t LoadDebugModeRootCert(void)
+{
+ mbedtls_x509_crt_init(&g_debugModeRootCert);
+ int32_t rc = mbedtls_x509_crt_parse(&g_debugModeRootCert, g_debugModeRootCertInPem,
+ sizeof(g_debugModeRootCertInPem));
+ if (rc) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "load debug mode root ca failed %d", rc);
+ return rc;
+ } else {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "load debug mode root ca success");
+ }
+ return rc;
+}
+
+static int32_t UnLoadDebugModeRootCert(void)
+{
+ mbedtls_x509_crt_free(&g_debugModeRootCert);
+ return PKCS7_SUCC;
+}
+
+static void UnLoadSelfSignedCert(void)
+{
+ mbedtls_x509_crt_free(&g_ohosRootCert);
+}
+
+static mbedtls_x509_crt *GetLowLevelCerts(SignedData *signedData)
+{
+ SignerInfo *signer = &signedData->signers;
+ mbedtls_x509_buf *signerSerial = &signer->serial;
+ mbedtls_x509_name *signerIssuer = &signer->issuer;
+ mbedtls_x509_crt *cert = signedData->certs;
+ HILOG_INFO(HILOG_MODULE_AAFWK, "To filter one signer's cert");
+ while (cert != NULL) {
+ if (SerialCmp(signerSerial, &cert->serial) == 0 &&
+ CompareX509NameList(signerIssuer, &cert->issuer) == 0) {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Found signer's low level cert");
+ return cert;
+ }
+ cert = cert->next;
+ }
+ return NULL;
+}
+
+static int32_t ParseSignedData(unsigned char *buf, size_t bufLen, SignedData *signedData)
{
unsigned char *p = buf;
unsigned char *end = buf + bufLen;
size_t len = 0;
- size_t rc;
+ int32_t rc;
/* parse SignedData sequence header */
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
/* parse signerInfos */
rc = ParseSignedDataSignerInfos(&p, end, &signedData->signers);
+ HILOG_INFO(HILOG_MODULE_AAFWK, "ParseSignedDataSignerInfos %d", rc);
return rc;
}
static void FreeSignedDataCrl(Pkcs7 *pkcs7)
{
- /* add mbedtls_x509_crl_free(&pkcs7->signedData.crl) if added the crl parse */
- (void)pkcs7;
+ mbedtls_x509_crl_free(&pkcs7->signedData.crl);
return;
}
-#define CERT_BUF_LEN 1024
-static void DLogCertInfo(const mbedtls_x509_crt *cert)
+static int32_t GetCertsNumOfSignedData(const mbedtls_x509_crt *crts)
{
-#if !(RUNNING_BOARD == LITE_WEARABLE)
- char buf[CERT_BUF_LEN];
- mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", cert);
-#endif
-}
-
-static int GetCertsNumOfSignedData(const mbedtls_x509_crt *crts)
-{
- int cnt = 0;
+ int32_t cnt = 0;
while (crts != NULL) {
crts = crts->next;
cnt++;
return cnt;
}
-static mbedtls_x509_crt *FindSuperCert(mbedtls_x509_crt *cur, mbedtls_x509_crt *certsList)
-{
- /* current level's subject is next level issuer */
- while (certsList != NULL) {
- if (X509_NameCmp(&cur->issuer, &certsList->subject) == 0) {
- break;
- }
- certsList = certsList->next;
- }
- return certsList;
-}
-
static void DelCertOfSignedData(SignedData *signedData, mbedtls_x509_crt *crt)
{
mbedtls_x509_crt *head = signedData->certs;
signer->certPath.depth++;
}
-static bool IsRootCert(mbedtls_x509_crt *crt)
-{
- if (X509_NameCmp(&g_rootCaG2Cert.subject, &crt->subject) == 0) {
- return true;
- }
- if (g_debugModeEnabled) {
- if (X509_NameCmp(&g_debugModeRootCert.subject, &crt->subject) == 0) {
- return true;
- }
- }
- return false;
-}
-static int BuildSignerCertPath(SignerInfo *signer, mbedtls_x509_crt *lowerCrt, SignedData *signeData)
+static int32_t BuildSignerCertPath(SignerInfo *signer, mbedtls_x509_crt *lowerCrt, SignedData *signeData)
{
- int scanCnt = 0;
- int rc = PKCS7_SUCC;
- if (g_rootCertLoaded == false) {
+ int32_t scanCnt = 0;
+ int32_t rc = PKCS7_SUCC;
+ if (!g_rootCertLoaded) {
return PKCS7_ROOT_CA_NOT_VALID;
}
signer->rootCert = &g_rootCaG2Cert;
* find the next level ca cert */
mbedtls_x509_crt *cur = lowerCrt;
mbedtls_x509_crt *next = NULL;
- int certsCnt = GetCertsNumOfSignedData(certs);
+ int32_t certsCnt = GetCertsNumOfSignedData(certs);
DelCertOfSignedData(signeData, cur);
AddCertToSignerCertPath(signer, cur);
while (true) {
next = FindSuperCert(cur, signeData->certs);
if (next == NULL) {
+ mbedtls_x509_crt_init(&g_ohosRootCert);
+ rc = FindAndStoreRootCert(cur);
+ if (rc == 0) {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "load self signed root ca success");
+ } else {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "load self signed ca failed %d", rc);
+ }
break;
} else {
- if (IsRootCert(next)) {
- HILOG_INFO(LOG_MODULE_AAFWK, "root cert pack in signed data");
- break;
- }
DelCertOfSignedData(signeData, next);
AddCertToSignerCertPath(signer, next);
}
return rc;
}
-static int ConstructSignerCerts(SignedData *signedData)
+static int32_t ConstructSignerCerts(SignedData *signedData)
{
/* scan all of the signers , and filter the signer's certs by serial and name */
SignerInfo *signer = &signedData->signers;
while (signer != NULL) {
- mbedtls_x509_buf *signerSerial = &signer->serial;
- mbedtls_x509_name *signerIssuer = &signer->issuer;
- mbedtls_x509_crt *cert = signedData->certs;
- HILOG_INFO(LOG_MODULE_AAFWK, "To filter one signer's cert");
- while (cert != NULL) {
- if (SerialCmp(signerSerial, &cert->serial) == 0 &&
- X509_NameCmp(signerIssuer, &cert->issuer) == 0) {
- HILOG_INFO(LOG_MODULE_AAFWK, "Found signer's low level cert");
- DLogCertInfo(cert);
- break;
- }
- cert = cert->next;
- }
+ mbedtls_x509_crt *cert = GetLowLevelCerts(signedData);
if (cert == NULL) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Could not found signer's lowest cert");
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Could not found signer's lowest cert");
return PKCS7_INVALID_VALUE;
}
- int rc = BuildSignerCertPath(signer, cert, signedData);
+ int32_t rc = BuildSignerCertPath(signer, cert, signedData);
if (rc != 0) {
return rc;
}
+
signer = signer->next;
}
return 0;
}
/* get signer digest alg */
-static int GetSignerDigestAlg(const SignerInfo *signer, mbedtls_md_type_t *algType)
+static int32_t GetSignerDigestAlg(const SignerInfo *signer, mbedtls_md_type_t *algType)
{
const mbedtls_x509_buf *alg = &signer->digestAlgId;
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_DIGEST_ALG_SHA256, alg)) {
}
/* get signer pubkey of sign from signer cert */
-static int GetSignerPubKeyOfSignature(const SignerInfo *signer, mbedtls_pk_context **pk)
+static int32_t GetSignerPubKeyOfSignature(const SignerInfo *signer, mbedtls_pk_context **pk)
{
/* signer cert_path first cert is the lowest cert. yet is the signature cert */
if (signer == NULL || pk == NULL) {
return PKCS7_INVALID_VALUE;
}
-int PKCS7_VerifySignerSignature(const Pkcs7 *pkcs7, PKCS7_CalcDigest calcDigest)
+int32_t PKCS7_VerifySignerSignature(const Pkcs7 *pkcs7, PKCS7_CalcDigest calcDigest)
{
- int rc;
+ int32_t rc;
if (pkcs7 == NULL || calcDigest == NULL) {
return PKCS7_INVALID_PARAM;
}
-
const SignerInfo *signer = &pkcs7->signedData.signers;
unsigned char *sig = NULL;
size_t sigLen;
if (rc) {
return rc;
}
- HILOG_INFO(LOG_MODULE_AAFWK, "get signer signature len : %lu", sigLen);
+ HILOG_INFO(HILOG_MODULE_AAFWK, "get signer signature len : %zu", sigLen);
mbedtls_pk_context *pk = NULL;
rc = GetSignerPubKeyOfSignature(signer, &pk);
if (rc) {
return rc;
}
-
unsigned char hash[MAX_HASH_SIZE];
+ (void)memset_s(hash, MAX_HASH_SIZE, 0, MAX_HASH_SIZE);
size_t hashLen = 0;
rc = calcDigest(pkcs7, signer, digAlg, hash, &hashLen);
if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Calculate content hash failed by calling callback");
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Calculate content hash failed by calling callback");
return rc;
}
/* if is rsassa-pss, need to set padding version to V21, RFC3447 */
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_RSASSA_PSS, &signer->digestEncAlgId)) {
- mbedtls_rsa_set_padding(pk->pk_ctx, MBEDTLS_RSA_PKCS_V21, 0);
+ mbedtls_rsa_set_padding(pk->MBEDTLS_PRIVATE(pk_ctx), MBEDTLS_RSA_PKCS_V21, (mbedtls_md_type_t)0);
}
rc = mbedtls_pk_verify(pk, digAlg, hash, hashLen, sig, sigLen);
+ (void)memset_s(hash, MAX_HASH_SIZE, 0, MAX_HASH_SIZE);
if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Verify signature failed, returned -0x%04x", rc);
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Verify signature failed, returned -0x%04x", rc);
return rc;
} else {
- HILOG_INFO(LOG_MODULE_AAFWK, "Verify signer signature success");
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Verify signer signature success\n");
}
-
signer = signer->next;
}
return rc;
}
-static int LoadRootCert(void)
+static void DLogCrtVerifyInfo(uint32_t flags)
{
- int rc = 0;
- if (g_rootCertLoaded == false) {
- mbedtls_x509_crt_init(&g_rootCaG2Cert);
- rc = mbedtls_x509_crt_parse(&g_rootCaG2Cert, g_rootCaG2CertInPem, sizeof(g_rootCaG2CertInPem));
- if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "load root ca failed");
- return rc;
- } else {
- HILOG_INFO(LOG_MODULE_AAFWK, "load root ca success");
+ char vrfyBuf[VERIFY_BUF_LEN];
+ (void)memset_s(vrfyBuf, VERIFY_BUF_LEN, 0, VERIFY_BUF_LEN);
+ mbedtls_x509_crt_verify_info(vrfyBuf, sizeof(vrfyBuf), " ! ", flags);
+ HILOG_DEBUG(HILOG_MODULE_AAFWK, "%s", vrfyBuf);
+}
+
+static int32_t IsRevoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl)
+{
+ mbedtls_x509_crl_entry *cur = (mbedtls_x509_crl_entry *)(&crl->entry);
+ while (cur != NULL) {
+ if (cur->serial.len == 0) {
+ return PKCS7_SUCC;
}
- DLogCertInfo(&g_rootCaG2Cert);
- g_rootCertLoaded = true;
+ if (crt->serial.len != cur->serial.len) {
+ cur = cur->next;
+ continue;
+ }
+ if (memcmp(crt->serial.p, cur->serial.p, cur->serial.len) == 0) {
+ return PKCS7_IS_REVOKED;
+ }
+ cur = cur->next;
}
- return rc;
+ return PKCS7_SUCC;
}
-static void UnLoadRootCert(void)
+
+static int32_t VerifyCrl(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl)
{
- if (g_rootCertLoaded == true) {
- mbedtls_x509_crt_free(&g_rootCaG2Cert);
- g_rootCertLoaded = false;
+ const mbedtls_x509_crl *crlList = crl;
+ while (crlList != NULL) {
+ if (crlList->version == 0 ||
+ CompareX509NameList(&crlList->issuer, &crt->issuer) != 0) {
+ crlList = crlList->next;
+ continue;
+ }
+ HILOG_INFO(HILOG_MODULE_AAFWK, "find crl");
+ if (IsRevoked(crt, crlList)) {
+ return PKCS7_IS_REVOKED;
+ }
+ crlList = crlList->next;
}
+ return PKCS7_SUCC;
}
-static int LoadDebugModeRootCert(void)
+static int32_t VerifyClicert(mbedtls_x509_crt *clicert, mbedtls_x509_crt *rootCert, const Pkcs7 *pkcs7)
{
- int rc;
- mbedtls_x509_crt_init(&g_debugModeRootCert);
- rc = mbedtls_x509_crt_parse(&g_debugModeRootCert, g_debugModeRootCertInPem, sizeof(g_debugModeRootCertInPem));
+ uint32_t flags;
+ int32_t rc = mbedtls_x509_crt_verify(clicert, rootCert,
+ (mbedtls_x509_crl *)&pkcs7->signedData.crl, NULL, &flags, NULL, NULL);
if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "load debug mode root ca failed");
- return rc;
+ DLogCrtVerifyInfo(flags);
} else {
- HILOG_INFO(LOG_MODULE_AAFWK, "load debug mode root ca success");
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Verify signers cert chain root cert success");
+ if (VerifyCrl(clicert, (mbedtls_x509_crl *)&pkcs7->signedData.crl) != PKCS7_SUCC) {
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "cert crl verify failed");
+ return PKCS7_IS_REVOKED;
+ }
+ return PKCS7_SUCC;
}
- DLogCertInfo(&g_debugModeRootCert);
return rc;
}
-static int UnLoadDebugModeRootCert(void)
-{
- mbedtls_x509_crt_free(&g_debugModeRootCert);
- return PKCS7_SUCC;
-}
-int PKCS7_VerifyCertsChain(const Pkcs7 *pkcs7)
+int32_t PKCS7_VerifyCertsChain(const Pkcs7 *pkcs7)
{
if (pkcs7 == NULL) {
return PKCS7_INVALID_PARAM;
}
-
- int cnt = 0;
+ int32_t cnt = 0;
const SignerInfo *signer = &pkcs7->signedData.signers;
while (signer != NULL) {
mbedtls_x509_crt *clicert = signer->certPath.crt;
if (clicert == NULL) {
- signer = signer->next;
- HILOG_ERROR(LOG_MODULE_AAFWK, "Signer has no certs");
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Signer has no certs");
return PKCS7_HAS_NO_SIGNER_CRT;
}
- unsigned int flags;
- int rc;
+ int32_t rc;
cnt++;
- HILOG_INFO(LOG_MODULE_AAFWK, "signer : %d", cnt);
+ HILOG_INFO(HILOG_MODULE_AAFWK, "signer : %d", cnt);
if (g_debugModeEnabled) {
- rc = mbedtls_x509_crt_verify(clicert, &g_debugModeRootCert, NULL, NULL, &flags, NULL, NULL);
- if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK,
- "Verify signer[%d]'s cert failed by debug mode, rc: %d", cnt, rc);
- } else {
- HILOG_INFO(LOG_MODULE_AAFWK,
- "Verify signers cert chain by debug mode root cert success");
+ rc = VerifyClicert(clicert, &g_debugModeRootCert, pkcs7);
+ HILOG_DEBUG(HILOG_MODULE_AAFWK, "Verify inner: %d", rc);
+ if (rc == PKCS7_SUCC) {
signer = signer->next;
continue;
}
+ if (rc == PKCS7_IS_REVOKED) {
+ return PKCS7_IS_REVOKED;
+ }
}
-
- mbedtls_x509_crt *rootCert = signer->rootCert;
-
- rc = mbedtls_x509_crt_verify(clicert, rootCert, NULL, NULL, &flags, NULL, NULL);
- if (rc) {
- HILOG_ERROR(LOG_MODULE_AAFWK, "Verify signer[%d]'s cert failed, rc: %d", cnt, rc);
- return rc;
- } else {
- HILOG_INFO(LOG_MODULE_AAFWK, "Verify signer[%d]'s certs chain success", cnt);
+ rc = VerifyClicert(clicert, signer->rootCert, pkcs7);
+ HILOG_DEBUG(HILOG_MODULE_AAFWK, "Verify : %d", rc);
+ if (rc == PKCS7_SUCC) {
+ signer = signer->next;
+ continue;
}
- signer = signer->next;
+ if (rc == PKCS7_IS_REVOKED) {
+ return PKCS7_IS_REVOKED;
+ }
+#ifndef OHOS_SIGN_HAPS_BY_SERVER
+ rc = VerifyClicert(clicert, &g_ohosRootCert, pkcs7);
+ HILOG_DEBUG(HILOG_MODULE_AAFWK, "Verify self : %d", rc);
+ if (rc == PKCS7_SUCC) {
+ signer = signer->next;
+ continue;
+ }
+#endif
+ return rc;
}
return PKCS7_SUCC;
}
-int PKCS7_GetSignerSignningCertSubject(const SignerInfo *signer, char *subject, size_t subjectLen)
+int32_t PKCS7_GetSignerSignningCertSubject(const SignerInfo *signer, char *subject, size_t subjectLen)
{
- int rc;
+ int32_t rc;
if (signer == NULL || subject == NULL) {
return PKCS7_INVALID_PARAM;
}
return PKCS7_SUCC;
}
-int PKCS7_GetSignerSignningCertIssuer(const SignerInfo *signer, char *issuer, size_t issuerLen)
+int32_t PKCS7_GetSignerSignningCertIssuer(const SignerInfo *signer, char *issuer, size_t issuerLen)
{
- int rc;
+ int32_t rc;
if (signer == NULL || issuer == NULL) {
return PKCS7_INVALID_PARAM;
}
}
return cnt;
}
-static size_t GetSignerSignningCertDepth(const SignerInfo *signer)
+
+static bool IsIncludeRoot(const SignerInfo *signer)
+{
+ mbedtls_x509_crt *pre = signer->certPath.crt;
+ mbedtls_x509_crt *cur = pre;
+ int32_t i = 0;
+ while (i < signer->certPath.depth && cur != NULL) {
+ pre = cur;
+ cur = cur->next;
+ i++;
+ }
+
+ if (pre == NULL) {
+ return false;
+ }
+
+ /* root cert is a self-sign cert */
+ if (CompareX509NameList(&pre->issuer, &pre->subject) == 0) {
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Include root cert");
+ return true;
+ }
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Not include root cert");
+ return false;
+}
+
+static int32_t GetSignerSignningCertDepth(const SignerInfo *signer)
{
- return signer->certPath.depth + 1; // 1 for root cert;
+ if (IsIncludeRoot(signer)) {
+ return signer->certPath.depth;
+ }
+
+ /* root cert is not included in signer->certPath, add 1 for root cert */
+ return signer->certPath.depth + 1;
}
+
void PKCS7_FreeAllSignersResolvedInfo(SignersResovedInfo *sri)
{
if (sri == NULL) {
Pkcs7Free(sri);
return NULL;
}
- int rc;
-
+ int32_t rc;
const SignerInfo *signer = &pkcs7->signedData.signers;
- int idx = 0;
+ int32_t idx = 0;
while (signer != NULL && idx < signersCnt) {
rc = PKCS7_GetSignerSignningCertSubject(signer, sri->signers[idx].subject, sizeof(sri->signers[idx].subject));
if (rc) {
return NULL;
}
-int PKCS7_GetDigestInSignerAuthAttr(const SignerInfo *signer, unsigned char **dig, size_t *digLen)
+int32_t PKCS7_GetDigestInSignerAuthAttr(const SignerInfo *signer, unsigned char **dig, size_t *digLen)
{
+ if (signer == NULL || dig == NULL || digLen == NULL) {
+ return PKCS7_INVALID_VALUE;
+ }
unsigned char *p = signer->authAttr.p;
- unsigned char *end = p + signer->authAttr.len;
- size_t tmpLen;
- int rc;
-
if (p == NULL) {
return PKCS7_HAS_NO_AUTH_ATTR_IN_SIGNER;
}
+ unsigned char *end = p + signer->authAttr.len;
+ size_t tmpLen = 0;
+
/* SET OF SEQUENCE */
while (p < end) {
size_t seqLen;
unsigned char *seqEnd = NULL;
- rc = mbedtls_asn1_get_tag(&p, end, &seqLen, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED);
+ int32_t rc = mbedtls_asn1_get_tag(&p, end, &seqLen, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED);
if (rc) {
return rc;
}
return PKCS7_INVALID_VALUE;
}
-int PKCS7_GetSignerAuthAttr(const SignerInfo *signer, unsigned char **data, size_t *dataLen)
+int32_t PKCS7_GetSignerAuthAttr(const SignerInfo *signer, unsigned char **data, size_t *dataLen)
{
- if (signer->authAttrRaw.p == NULL) {
+ if (signer == NULL || signer->authAttrRaw.p == NULL || data == NULL || dataLen == NULL) {
return PKCS7_INVALID_VALUE;
}
*dataLen = signer->authAttrRaw.len;
*data = signer->authAttrRaw.p;
- /*
- * As PKCS7 explain:
- * authenticatedAttributes is a set of attributes that are signed (i.e.,
- * authenticated) by the signer. The field is optional, but it must be present if the content
- * type of the ContentInfo value being signed is not data. If the field is present,
- * it must contain, at a minimum, two attributes:
- * A PKCS#9 content-type attribute
- * A PKCS#9 message-digest attribute
- *
- * For clarity: The IMPLICIT [0] tag in the authenticatedAttributes field is not part of the Attributes
- * value. The Attributes value's tag is SET OF, and the DER encoding of the SET OF tag,
- * rather than of the IMPLICIT' [0] tag, is to be digested along with the length and contents
- * octets of the Attributes value
- *
- * So, the tag is SET OF(0x31) when signing, but it will changed to CONTEXT_SPECIFIC(0xa0) when packing to
- * signer's structure. so we must change it to original SET OF(0x31) for calculate digest.
- */
*(unsigned char *)signer->authAttrRaw.p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
return PKCS7_SUCC;
}
-int PKCS7_GetContentData(const Pkcs7 *pkcs7, unsigned char **data, size_t *dataLen)
+int32_t PKCS7_GetContentData(const Pkcs7 *pkcs7, unsigned char **data, size_t *dataLen)
{
if (pkcs7 == NULL || data == NULL || dataLen == NULL) {
return PKCS7_INVALID_PARAM;
size_t len = pkcs7->signedData.content.data.len;
unsigned char *end = p + len;
size_t octetLen;
- int rc = mbedtls_asn1_get_tag(&p, end, &octetLen, MBEDTLS_ASN1_OCTET_STRING);
+ int32_t rc = mbedtls_asn1_get_tag(&p, end, &octetLen, MBEDTLS_ASN1_OCTET_STRING);
if (rc != 0) {
return rc;
}
return PKCS7_SUCC;
}
-int PKCS7_EnableDebugMode(bool mode)
+int32_t PKCS7_EnableDebugMode(bool mode)
{
if (g_debugModeEnabled == mode) {
return PKCS7_SUCC;
}
- int rc = ((mode == true) ? LoadDebugModeRootCert() : UnLoadDebugModeRootCert());
+ int32_t rc = ((mode == true) ? LoadDebugModeRootCert() : UnLoadDebugModeRootCert());
if (rc) {
return rc;
}
g_debugModeEnabled = mode;
- return rc;
+ return PKCS7_SUCC;
}
+
#ifdef PARSE_PEM_FORMAT_SIGNED_DATA
-static int ParsePemFormatSignedData(const unsigned char *buf, size_t bufLen, mbedtls_pem_context *pem, char *format)
+static int32_t ParsePemFormatSignedData(const unsigned char *buf, size_t bufLen, mbedtls_pem_context *pem, char *format)
{
if (bufLen != 0 && strstr((const char *)buf, "-----BEGIN PKCS7-----") != NULL) {
- int ret;
- size_t useLen;
+ int32_t rc;
+ size_t useLen = 0;
mbedtls_pem_init(pem);
- ret = mbedtls_pem_read_buffer(pem, "-----BEGIN PKCS7-----", "-----END PKCS7-----",
+ rc = mbedtls_pem_read_buffer(pem, "-----BEGIN PKCS7-----", "-----END PKCS7-----",
buf, NULL, 0, &useLen);
- if (ret == 0 && useLen == bufLen) {
+ if (rc == 0 && useLen == bufLen) {
*format = PEM_FORMAT_SINGED_DATA;
return PKCS7_SUCC;
}
return PKCS7_INVALID_PARAM;
}
#endif
-int PKCS7_ParseSignedData(const unsigned char *buf, size_t bufLen, Pkcs7 *pkcs7)
+
+int32_t PKCS7_ParseSignedData(const unsigned char *buf, size_t bufLen, Pkcs7 *pkcs7)
{
- int rc;
- size_t len;
+ int32_t rc;
+ size_t len = 0;
bool hasContent = false;
unsigned char *start = NULL;
unsigned char *end = NULL;
(void)memset_s(pkcs7, sizeof(*pkcs7), 0, sizeof(*pkcs7));
start = (unsigned char *)buf;
#ifdef PARSE_PEM_FORMAT_SIGNED_DATA
- char format;
+ char format = 0;
rc = ParsePemFormatSignedData(buf, bufLen, &pkcs7->pem, &format);
if (rc) {
- goto OUT;
+ goto EXIT;
}
if (format == PEM_FORMAT_SINGED_DATA) {
- start = pkcs7->pem.buf;
- bufLen = pkcs7->pem.buflen;
+ start = pkcs7->pem.MBEDTLS_PRIVATE(buf);
+ bufLen = pkcs7->pem.MBEDTLS_PRIVATE(buflen);
}
#endif
- end = start + bufLen;
-
- /* loaded the root ca cert */
+#ifdef MARKET_ENABLE
+ if (access(OEM_CERT_PATH, F_OK) == 0) {
+ rc = VerifyHashList();
+ P_ERR_GOTO_WTTH_LOG(rc);
+ }
+#endif
+ /* loaded the c2 root ca cert */
rc = LoadRootCert();
- PKCS7_ERR_GOTO_OUT(rc);
- HILOG_INFO(LOG_MODULE_AAFWK, "Begin to parse pkcs#7 signed data", 0);
+ P_ERR_GOTO_WTTH_LOG(rc);
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Begin to parse pkcs#7 signed data");
+ end = start + bufLen;
/* parse the ContentInfo total head */
rc = GetContentInfoType(&start, end, &(pkcs7->contentTypeOid), &hasContent);
- PKCS7_ERR_GOTO_OUT(rc);
-
- if (!IsSigedDataOid(pkcs7) || hasContent == false) {
+ P_ERR_GOTO_WTTH_LOG(rc);
+ if (!IsSigedDataOid(pkcs7) || !hasContent) {
rc = PKCS7_INVALID_CONTENT_TYPE_OR_NO_CONTENT;
- HILOG_ERROR(LOG_MODULE_AAFWK,
- "Input data is not pkcs#7 signed data format or has no content info");
- goto OUT;
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "Input data is not pkcs#7 signed data format or has no content info");
+ goto EXIT;
}
rc = GetContentLenOfContentInfo(&start, end, &len);
- PKCS7_ERR_GOTO_OUT(rc);
+ P_ERR_GOTO_WTTH_LOG(rc);
if (start + len > end) {
- goto OUT;
+ rc = PKCS7_INVALID_CONTENT_TYPE_OR_NO_CONTENT;
+ HILOG_ERROR(HILOG_MODULE_AAFWK, "The length of input data is invalid");
+ goto EXIT;
}
rc = ParseSignedData(start, len, &(pkcs7->signedData));
- PKCS7_ERR_GOTO_OUT(rc);
-
- HILOG_INFO(LOG_MODULE_AAFWK, "Parse pkcs#7 signed data success");
-
+ P_ERR_GOTO_WTTH_LOG(rc);
+ HILOG_INFO(HILOG_MODULE_AAFWK, "Parse pkcs#7 signed data success");
rc = ConstructSignerCerts(&pkcs7->signedData);
- PKCS7_ERR_GOTO_OUT(rc);
+ P_ERR_GOTO_WTTH_LOG(rc);
return rc;
-OUT:
- PKCS7_FreeRes(pkcs7);
+EXIT:
return rc;
}
void PKCS7_FreeRes(Pkcs7 *pkcs7)
{
+ if (pkcs7 == NULL) {
+ return;
+ }
FreeSignedDataDigestAlgs(pkcs7);
FreeSignersInfo(pkcs7);
FreeSignedDataCerts(pkcs7);
FreeSignedDataCrl(pkcs7);
UnLoadRootCert();
- return;
-}
+#ifndef OHOS_SIGN_HAPS_BY_SERVER
+ UnLoadSelfSignedCert();
+#endif
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2025-2030 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <mbedtls/aes.h>
+#include <mbedtls/base64.h>
+#include "cipher.h"
+#include "securec.h"
+#include "cipher_log.h"
+
+#define AES_BYTE_SIZE 128
+#define MAX_BUFFER_SIZE (1024 * 16)
+#define KEY_LEN 16 // 128-bit key
+
+// 通用填充函数
+static int32_t AddPadding(char *data, int32_t dataLen, PaddingMode paddingMode)
+{
+ if (data == NULL || dataLen < 0) {
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (paddingMode == PADDING_NONE) {
+ return dataLen;
+ }
+
+ int pad_len = AES_BLOCK_SIZE - (dataLen % AES_BLOCK_SIZE);
+ if (pad_len == AES_BLOCK_SIZE) {
+ pad_len = (paddingMode == PADDING_NONE) ? 0 : AES_BLOCK_SIZE;
+ }
+
+ if (pad_len > 0) {
+ for (int i = 0; i < pad_len; i++) {
+ data[dataLen + i] = (char)pad_len;
+ }
+ }
+ return dataLen + pad_len;
+}
+
+// 通用解填充函数
+static int32_t RemovePadding(char *data, int32_t dataLen, PaddingMode paddingMode)
+{
+ if (data == NULL || dataLen <= 0) {
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (paddingMode == PADDING_NONE) {
+ return dataLen;
+ }
+
+ if (dataLen % AES_BLOCK_SIZE != 0) {
+ return ERROR_CODE_GENERAL;
+ }
+
+ uint8_t pad_len = data[dataLen - 1];
+ if (pad_len < 1 || pad_len > AES_BLOCK_SIZE) {
+ return ERROR_CODE_GENERAL;
+ }
+
+ for (int i = 1; i <= pad_len; i++) {
+ if (data[dataLen - i] != pad_len) {
+ return ERROR_CODE_GENERAL;
+ }
+ }
+ return dataLen - pad_len;
+}
+
+// 解析填充模式和加密模式
+static PaddingMode ParsePaddingModeAndType(const char *transformation, CipherAesMode *mode)
+{
+ PaddingMode padding = PADDING_PKCS5; // 默认PKCS5
+ *mode = CIPHER_AES_CBC; // 默认CBC模式
+
+ if (transformation == NULL) {
+ return padding;
+ }
+
+ // 检测填充模式
+ if (strstr(transformation, "PKCS5Padding") != NULL) {
+ padding = PADDING_PKCS5;
+ } else if (strstr(transformation, "PKCS7Padding") != NULL) {
+ padding = PADDING_PKCS7;
+ } else if (strstr(transformation, "NoPadding") != NULL) {
+ padding = PADDING_NONE;
+ }
+
+ // 检测加密模式
+ if (strstr(transformation, "ECB") != NULL) {
+ *mode = CIPHER_AES_ECB;
+ } else if (strstr(transformation, "CBC") != NULL) {
+ *mode = CIPHER_AES_CBC;
+ }
+
+ return padding;
+}
+
+static char *MallocDecodeData(const char *text, size_t *olen)
+{
+ if (text == NULL) {
+ return NULL;
+ }
+
+ size_t inputLen = strlen(text);
+ size_t decodeLen = 0;
+ int32_t ret = mbedtls_base64_decode(NULL, 0, &decodeLen, (const unsigned char *)text, inputLen);
+ if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
+ return NULL;
+ }
+
+ if (decodeLen == 0) {
+ return NULL;
+ }
+
+ // 分配精确长度,不添加额外终止符
+ char *decData = (char *)malloc(decodeLen);
+ if (decData == NULL) {
+ CIPHER_LOG_E("malloc failed, length:%zu.\n", decodeLen);
+ return NULL;
+ }
+
+ if (mbedtls_base64_decode((unsigned char *)decData, decodeLen, olen,
+ (const unsigned char *)text, inputLen) != 0) {
+ free(decData);
+ CIPHER_LOG_E("decode data failed, text:%s.\n", text);
+ return NULL;
+ }
+
+ return decData;
+}
+
+static char *MallocEncodeData(const unsigned char *text, size_t inputLen, size_t *outLen)
+{
+ if (text == NULL || inputLen == 0) {
+ return NULL;
+ }
+
+ size_t encodeLen = 0;
+ int32_t ret = mbedtls_base64_encode(NULL, 0, &encodeLen, text, inputLen);
+ if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
+ return NULL;
+ }
+
+ if (encodeLen == 0) {
+ return NULL;
+ }
+
+ char *encData = (char *)malloc(encodeLen + 1);
+ if (encData == NULL) {
+ CIPHER_LOG_E("malloc data failed, expect len:%zu.\n", encodeLen);
+ return NULL;
+ }
+
+ (void)memset_s(encData, encodeLen + 1, 0, encodeLen + 1);
+ if (mbedtls_base64_encode((unsigned char *)encData, encodeLen, outLen, text, inputLen) != 0) {
+ CIPHER_LOG_E("encode data failed.\n");
+ free(encData);
+ return NULL;
+ }
+
+ return encData;
+}
+
+// 使用二进制数据处理IV
+static int32_t SetIv(const unsigned char *ivBuf, size_t ivBufSize, int32_t ivOffset, int32_t ivLen, AesCryptContext *ctx)
+{
+ if (ctx == NULL) {
+ CIPHER_LOG_E("SetIv: NULL context\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // ECB模式不需要IV
+ if (ctx->mode == CIPHER_AES_ECB) {
+ ctx->iv.ivBuf = NULL;
+ ctx->iv.ivLen = 0;
+ ctx->iv.ivOffset = 0;
+ return ERROR_SUCCESS;
+ }
+
+ if (ivBuf == NULL) {
+ CIPHER_LOG_E("SetIv: NULL ivBuf\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (ivOffset < 0 || ivLen <= 0) {
+ CIPHER_LOG_E("ivLen or ivOffset negative err.\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (ivBufSize < (size_t)(ivOffset + ivLen)) {
+ CIPHER_LOG_E("ivBufSize too small: %zu < %d\n",
+ ivBufSize, ivOffset + ivLen);
+ return ERROR_CODE_GENERAL;
+ }
+
+ ctx->iv.ivBuf = malloc(ivLen);
+ if (ctx->iv.ivBuf == NULL) {
+ CIPHER_LOG_E("malloc failed for IV.\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ int32_t ret = memcpy_s(ctx->iv.ivBuf, ivLen, ivBuf + ivOffset, ivLen);
+ if (ret != EOK) {
+ CIPHER_LOG_E("memcpy failed, ret:%d.\n", ret);
+ free(ctx->iv.ivBuf);
+ ctx->iv.ivBuf = NULL;
+ return ERROR_CODE_GENERAL;
+ }
+
+ ctx->iv.ivLen = ivLen;
+ return ERROR_SUCCESS;
+}
+
+static int32_t InitAesCryptContext(const char *key, const AesIvMode *iv, AesCryptContext *ctx)
+{
+ int32_t ret;
+ if (iv == NULL || ctx == NULL || key == NULL) {
+ CIPHER_LOG_E("InitAesCryptContext: NULL parameter\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 解析填充模式和加密模式
+ ctx->paddingMode = ParsePaddingModeAndType(iv->transformation, &ctx->mode);
+
+ ctx->iv.ivOffset = iv->ivOffset;
+ ctx->iv.ivLen = (ctx->mode == CIPHER_AES_CBC) ? AES_BLOCK_SIZE : 0;
+
+ // ECB模式不需要IV长度检查
+ if (ctx->mode == CIPHER_AES_CBC) {
+ if (iv->ivLen != AES_BLOCK_SIZE) {
+ CIPHER_LOG_E("ivLen:%d error, need be %d Bytes.\n",
+ iv->ivLen, AES_BLOCK_SIZE);
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 处理Base64编码的IV
+ if (iv->ivBuf != NULL) {
+ size_t decodedIvLen = 0;
+ char* decodedIvBuf = MallocDecodeData(iv->ivBuf, &decodedIvLen);
+ if (decodedIvBuf == NULL) {
+ CIPHER_LOG_E("base64 decode failed for IV.\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 使用二进制数据设置IV
+ ret = SetIv((const unsigned char *)decodedIvBuf, decodedIvLen,
+ ctx->iv.ivOffset, ctx->iv.ivLen, ctx);
+ free(decodedIvBuf);
+
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("SetIv failed after decoding, ret:%d.\n", ret);
+ return ERROR_CODE_GENERAL;
+ }
+ } else {
+ // 直接使用二进制密钥数据
+ if (ctx->data.key == NULL) {
+ CIPHER_LOG_E("Key is NULL when using as IV\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ ret = SetIv((const unsigned char *)ctx->data.key, ctx->data.keyLen,
+ ctx->iv.ivOffset, ctx->iv.ivLen, ctx);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("SetIv from key failed, ret:%d.\n", ret);
+ return ERROR_CODE_GENERAL;
+ }
+ }
+ } else {
+ // ECB模式不需要IV
+ ctx->iv.ivBuf = NULL;
+ ctx->iv.ivLen = 0;
+ }
+ return ERROR_SUCCESS;
+}
+
+static int32_t InitAesCryptDataText(const char *action, const char *key, const char *text, CryptData *data, PaddingMode paddingMode)
+{
+ if (action == NULL || text == NULL || data == NULL) {
+ CIPHER_LOG_E("InitAesCryptDataText: NULL parameter\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (strcmp(action, "encrypt") == 0) {
+ data->action = MBEDTLS_AES_ENCRYPT;
+ int32_t originalLen = strlen(text);
+
+ // 计算填充后长度
+ int32_t paddedLen;
+ if (paddingMode == PADDING_NONE) {
+ paddedLen = originalLen;
+ // 无填充模式需要长度是块大小的倍数
+ if (paddedLen % AES_BLOCK_SIZE != 0) {
+ CIPHER_LOG_E("Text length %d not multiple of block size for NoPadding\n", paddedLen);
+ return ERROR_CODE_GENERAL;
+ }
+ } else {
+ int pad_len = AES_BLOCK_SIZE - (originalLen % AES_BLOCK_SIZE);
+ pad_len = (pad_len == 0) ? AES_BLOCK_SIZE : pad_len;
+ paddedLen = originalLen + pad_len;
+ }
+
+ if (paddedLen <= 0) {
+ CIPHER_LOG_E("Invalid padded length: %d\n", paddedLen);
+ return ERROR_CODE_GENERAL;
+ }
+
+ data->text = malloc(paddedLen + 1);
+ if (data->text == NULL) {
+ CIPHER_LOG_E("malloc failed for text\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ (void)memset_s(data->text, paddedLen + 1, 0, paddedLen + 1);
+
+ if (memcpy_s(data->text, paddedLen + 1, text, originalLen) != EOK) {
+ CIPHER_LOG_E("memcpy_s failed for text\n");
+ free(data->text);
+ data->text = NULL;
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 添加填充
+ if (paddingMode != PADDING_NONE) {
+ data->textLen = AddPadding(data->text, originalLen, paddingMode);
+ if (data->textLen != paddedLen) {
+ CIPHER_LOG_E("Padding failed: expected %d, got %d\n", paddedLen, data->textLen);
+ free(data->text);
+ data->text = NULL;
+ return ERROR_CODE_GENERAL;
+ }
+ } else {
+ data->textLen = paddedLen;
+ }
+ } else if (strcmp(action, "decrypt") == 0) {
+ data->action = MBEDTLS_AES_DECRYPT;
+ size_t textLen = 0;
+ data->text = MallocDecodeData(text, &textLen);
+ if (data->text == NULL) {
+ CIPHER_LOG_E("Base64 decode failed for ciphertext\n");
+ return ERROR_CODE_GENERAL;
+ }
+ data->textLen = (uint32_t)textLen;
+
+ // 无填充模式不需要对齐块大小
+ if (paddingMode != PADDING_NONE) {
+ // 确保数据长度是块大小的整数倍
+ if (data->textLen % AES_BLOCK_SIZE != 0) {
+ CIPHER_LOG_E("Ciphertext length %d not multiple of block size\n", data->textLen);
+ free(data->text);
+ data->text = NULL;
+ return ERROR_CODE_GENERAL;
+ }
+ }
+ } else {
+ CIPHER_LOG_E("Invalid action: %s\n", action);
+ return ERROR_CODE_GENERAL;
+ }
+ return ERROR_SUCCESS;
+}
+
+static int32_t InitAesData(const char *action, const char *key, const char *text, CryptData *data, PaddingMode paddingMode)
+{
+ if (action == NULL || text == NULL || data == NULL || key == NULL) {
+ CIPHER_LOG_E("InitAesData: NULL parameter\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 先初始化文本数据
+ int32_t ret = InitAesCryptDataText(action, key, text, data, paddingMode);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("InitAesCryptDataText failed\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 解码Base64编码的密钥
+ size_t keyLen = 0;
+ data->key = MallocDecodeData(key, &keyLen);
+ if (data->key == NULL) {
+ CIPHER_LOG_E("Base64 decode failed for key\n");
+ goto ERROR;
+ }
+
+ // 验证密钥长度(使用实际解码长度)
+ if (keyLen != KEY_LEN) {
+ CIPHER_LOG_E("key length:%zu error, need be %d Bytes.\n", keyLen, KEY_LEN);
+ (void)memset_s(data->key, keyLen, 0, keyLen);
+ free(data->key);
+ data->key = NULL;
+ goto ERROR;
+ }
+
+ // 使用实际解码长度
+ data->keyLen = keyLen;
+ return ERROR_SUCCESS;
+
+ERROR:
+ if (data->text != NULL) {
+ free(data->text);
+ data->text = NULL;
+ }
+ return ERROR_CODE_GENERAL;
+}
+
+void DeinitAesCryptData(AesCryptContext *aesCryptCxt)
+{
+ if (aesCryptCxt == NULL) {
+ return;
+ }
+
+ if (aesCryptCxt->iv.ivBuf != NULL) {
+ free(aesCryptCxt->iv.ivBuf);
+ aesCryptCxt->iv.ivBuf = NULL;
+ }
+
+ if (aesCryptCxt->data.key != NULL) {
+ (void)memset_s(aesCryptCxt->data.key, aesCryptCxt->data.keyLen, 0, aesCryptCxt->data.keyLen);
+ free(aesCryptCxt->data.key);
+ aesCryptCxt->data.key = NULL;
+ }
+
+ if (aesCryptCxt->data.text != NULL) {
+ free(aesCryptCxt->data.text);
+ aesCryptCxt->data.text = NULL;
+ }
+}
+
+static int32_t DoAesCbcEncrypt(mbedtls_aes_context *aesCtx, AesCryptContext *ctx)
+{
+ int32_t ret;
+ if (ctx->data.action == MBEDTLS_AES_ENCRYPT) {
+ ret = mbedtls_aes_setkey_enc(aesCtx, (const unsigned char *)ctx->data.key, AES_BYTE_SIZE);
+ } else {
+ ret = mbedtls_aes_setkey_dec(aesCtx, (const unsigned char *)ctx->data.key, AES_BYTE_SIZE);
+ }
+ if (ret != 0) {
+ CIPHER_LOG_E("aes setkey error, ret:%d.\n", ret);
+ return ERROR_CODE_GENERAL;
+ }
+
+ ret = mbedtls_aes_crypt_cbc(aesCtx, ctx->data.action, ctx->data.textLen,
+ (unsigned char *)ctx->iv.ivBuf, (const unsigned char *)ctx->data.text, (unsigned char *)ctx->data.text);
+ if (ret != 0) {
+ CIPHER_LOG_E("aes crypt cbc error, ret:%d.\n", ret);
+ return ERROR_CODE_GENERAL;
+ }
+
+ if (ctx->data.action == MBEDTLS_AES_ENCRYPT) {
+ size_t textLen = ctx->data.textLen;
+ char *out = MallocEncodeData((const unsigned char *)ctx->data.text, textLen, &textLen);
+ if (out == NULL) {
+ CIPHER_LOG_E("base64 encode failed.\n");
+ return ERROR_CODE_GENERAL;
+ }
+ ctx->data.textLen = (uint32_t)textLen;
+ free(ctx->data.text);
+ ctx->data.text = out;
+ } else {
+ // 使用上下文中的填充模式进行解填充
+ int32_t unpaddedLen = RemovePadding(ctx->data.text, ctx->data.textLen, ctx->paddingMode);
+ if (unpaddedLen < 0) {
+ CIPHER_LOG_E("remove padding failed.\n");
+ return ERROR_CODE_GENERAL;
+ }
+ ctx->data.textLen = unpaddedLen;
+
+ // 添加字符串终止符
+ ctx->data.text[unpaddedLen] = '\0';
+ }
+
+ return ERROR_SUCCESS;
+}
+
+// ECB模式加解密函数
+static int32_t DoAesEcbEncrypt(mbedtls_aes_context *aesCtx, AesCryptContext *ctx)
+{
+ int32_t ret;
+ if (ctx->data.action == MBEDTLS_AES_ENCRYPT) {
+ ret = mbedtls_aes_setkey_enc(aesCtx, (const unsigned char *)ctx->data.key, AES_BYTE_SIZE);
+ } else {
+ ret = mbedtls_aes_setkey_dec(aesCtx, (const unsigned char *)ctx->data.key, AES_BYTE_SIZE);
+ }
+ if (ret != 0) {
+ CIPHER_LOG_E("aes setkey error, ret:%d.\n", ret);
+ return ERROR_CODE_GENERAL;
+ }
+
+ // ECB模式需要分块处理
+ int32_t blockCount = ctx->data.textLen / AES_BLOCK_SIZE;
+ for (int i = 0; i < blockCount; i++) {
+ uint8_t input[AES_BLOCK_SIZE];
+ uint8_t output[AES_BLOCK_SIZE];
+ memcpy(input, ctx->data.text + i * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+ ret = mbedtls_aes_crypt_ecb(aesCtx, ctx->data.action, input, output);
+ if (ret != 0) {
+ CIPHER_LOG_E("aes crypt ecb error at block %d, ret:%d.\n", i, ret);
+ return ERROR_CODE_GENERAL;
+ }
+
+ memcpy(ctx->data.text + i * AES_BLOCK_SIZE, output, AES_BLOCK_SIZE);
+ }
+
+ if (ctx->data.action == MBEDTLS_AES_ENCRYPT) {
+ size_t textLen = ctx->data.textLen;
+ char *out = MallocEncodeData((const unsigned char *)ctx->data.text, textLen, &textLen);
+ if (out == NULL) {
+ CIPHER_LOG_E("base64 encode failed.\n");
+ return ERROR_CODE_GENERAL;
+ }
+ ctx->data.textLen = (uint32_t)textLen;
+ free(ctx->data.text);
+ ctx->data.text = out;
+ } else {
+ // 使用上下文中的填充模式进行解填充
+ int32_t unpaddedLen = RemovePadding(ctx->data.text, ctx->data.textLen, ctx->paddingMode);
+ if (unpaddedLen < 0) {
+ CIPHER_LOG_E("remove padding failed.\n");
+ return ERROR_CODE_GENERAL;
+ }
+ ctx->data.textLen = unpaddedLen;
+
+ // 添加字符串终止符
+ ctx->data.text[unpaddedLen] = '\0';
+ }
+
+ return ERROR_SUCCESS;
+}
+
+int32_t InitAesCryptData(const char *action, const char *text, const char *key, const AesIvMode *iv,
+ AesCryptContext *aesCryptCxt)
+{
+ if (action == NULL || text == NULL || key == NULL || iv == NULL || aesCryptCxt == NULL) {
+ CIPHER_LOG_E("InitAesCryptData: NULL parameter\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 初始化填充模式和加密模式
+ aesCryptCxt->paddingMode = ParsePaddingModeAndType(iv->transformation, &aesCryptCxt->mode);
+
+ // 初始化数据
+ int32_t ret = InitAesData(action, key, text, &(aesCryptCxt->data), aesCryptCxt->paddingMode);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("InitAesData failed, ret:%d.\n", ret);
+ DeinitAesCryptData(aesCryptCxt);
+ return ERROR_CODE_GENERAL;
+ }
+
+ // 初始化上下文(包括IV)
+ ret = InitAesCryptContext(key, iv, aesCryptCxt);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("InitAesCryptContext failed, ret:%d.\n", ret);
+ DeinitAesCryptData(aesCryptCxt);
+ return ERROR_CODE_GENERAL;
+ }
+ return ERROR_SUCCESS;
+}
+
+int32_t CipherAesCrypt(AesCryptContext* aesCryptCxt)
+{
+ if (aesCryptCxt == NULL) {
+ CIPHER_LOG_E("AesCrypt: NULL context\n");
+ return ERROR_CODE_GENERAL;
+ }
+
+ mbedtls_aes_context aes;
+ mbedtls_aes_init(&aes);
+ int32_t ret = ERROR_CODE_GENERAL;
+
+ if (aesCryptCxt->mode == CIPHER_AES_CBC) {
+ ret = DoAesCbcEncrypt(&aes, aesCryptCxt);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("Aes cbc crypt failed, ret:%d.\n", ret);
+ }
+ } else if (aesCryptCxt->mode == CIPHER_AES_ECB) {
+ ret = DoAesEcbEncrypt(&aes, aesCryptCxt);
+ if (ret != ERROR_SUCCESS) {
+ CIPHER_LOG_E("Aes ecb crypt failed, ret:%d.\n", ret);
+ }
+ } else {
+ CIPHER_LOG_E("unsupported crypt mode: %d\n", aesCryptCxt->mode);
+ }
+
+ mbedtls_aes_free(&aes);
+ return ret;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * 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.
+ */
+
+#include "cipher_module.h"
+#include "log.h"
+#include "securec.h"
+// OHOS BEGIN
+#include <string>
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+#include "mbedtls/sha256.h"
+#include "js_async_work.h"
+#endif
+
+const int8_t SHA256_LEN = 32;
+const int8_t SHA256_RESULT_LEN = SHA256_LEN * 2;
+const int32_t MAX_LEN = 16384;
+
+struct CipherMsgParams {
+ char *msgBody;
+ uint8_t type;
+ OHOS::ACELite::JSIValue context;
+ OHOS::ACELite::JSIValue callback;
+ bool flag;
+};
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+struct Sha256Context {
+ mbedtls_sha256_context context;
+};
+
+Sha256Context *g_sha256Context;
+#endif
+// OHOS END
+namespace OHOS {
+namespace ACELite {
+JSIValue CipherModule::Rsa(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ JSIValue undefValue = JSI::CreateUndefined();
+ if ((args == nullptr) || argsNum == 0 || JSI::ValueIsUndefined(args[0])) {
+ return undefValue;
+ }
+
+ JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
+ JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
+ JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);
+ char *strAction = JSI::GetStringProperty(args[0], "action");
+ char *strKey = JSI::GetStringProperty(args[0], "key");
+ char *strText = JSI::GetStringProperty(args[0], "text");
+ char *strTransformation = JSI::GetStringProperty(args[0], "transformation");
+ JSIValue code = JSI::CreateNumber(ERR_CODE);
+ JSIValue data = JSI::CreateString("System error");
+ JSIValue argvFail[ARGC_TWO] = { data, code };
+ JSIValue result = JSI::CreateObject();
+ JSIValue argvSuccess[ARGC_ONE] = { result };
+ int ret = ERROR_CODE_GENERAL;
+ RsaData textIn = { NULL, 0 };
+ RsaData textOut = { NULL, 0 };
+ RsaKeyData rsaKey = { NULL, NULL, NULL, 0 };
+ if ((strKey == nullptr) || (strText == nullptr)) {
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+ goto RELEASE;
+ }
+ rsaKey.key = strKey;
+ rsaKey.keyLen = strlen(strKey);
+ rsaKey.trans = strTransformation;
+ rsaKey.action = strAction;
+ textIn.data = strText;
+ textIn.length = strlen(strText);
+
+ ret = RsaCrypt(&rsaKey, &textIn, &textOut);
+ if ((ret != ERROR_SUCCESS) || (textOut.length == 0)) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "RsaCrypt failed.");
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+ goto RELEASE;
+ }
+ textOut.data = static_cast<char *>(ace_malloc(textOut.length));
+ if (textOut.data == nullptr) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "ace malloc failed.");
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+ goto RELEASE;
+ }
+ ret = memset_s(textOut.data, textOut.length, 0, textOut.length);
+ if (ret) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "memset failed.");
+ }
+ ret = RsaCrypt(&rsaKey, &textIn, &textOut);
+ if (ret != ERROR_SUCCESS) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "RsaCrypt failed.");
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+ goto RELEASE;
+ }
+ JSI::SetStringProperty(result, "text", (char*)textOut.data);
+ JSI::CallFunction(success, thisVal, argvSuccess, ARGC_ONE);
+
+RELEASE:
+ JSI::ReleaseString(strAction);
+ JSI::ReleaseString(strText);
+ ResetStrBuf(strKey);
+ JSI::ReleaseString(strKey);
+ JSI::ReleaseString(strTransformation);
+ JSI::CallFunction(complete, thisVal, nullptr, 0);
+ JSI::ReleaseValueList(success, fail, complete, result, code, data, ARGS_END);
+ if (textOut.data != nullptr) {
+ ace_free(textOut.data);
+ }
+
+ return undefValue;
+}
+// OHOS BEGIN
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+JSIValue CipherModule::Sha256All(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ JSIValue undefValue = JSI::CreateUndefined();
+ if ((args == nullptr) || argsNum == 0 || JSI::ValueIsUndefined(args[0])) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256 args error.");
+ return undefValue;
+ }
+ JSIValue context = JSI::AcquireValue(thisVal);
+ JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
+ JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
+ char *strText = JSI::GetStringProperty(args[0], "text");
+ unsigned char sha256Result[SHA256_LEN];
+ unsigned char *strResult = reinterpret_cast<unsigned char *>(strText);
+ int32_t ret = -1;
+ int size = 2;
+ int sizeBuffer = 3;
+ if (strlen(strText) == 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error , text is nullptr");
+ goto RELEASE;
+ }
+ ret = Sha256(strResult, strlen(strText), sha256Result);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256 error.");
+ CipherMsgToJS("Sha256All error", context, fail);
+ goto RELEASE;
+ }
+ char result[SHA256_RESULT_LEN + 1];
+ for (int i = 0; i < SHA256_LEN; i++) {
+ ret = sprintf_s(&result[i * size], sizeBuffer, "%02x", sha256Result[i]);
+ if (ret < 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256All sprintf_s error.");
+ goto RELEASE;
+ }
+ }
+ result[SHA256_RESULT_LEN] = '\0';
+ ret = CipherMsgToJS(result, context, success);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256All send message error.");
+ CipherMsgToJS("Sha256All send message error error", context, fail);
+ goto RELEASE;
+ }
+
+RELEASE:
+ JSI::ReleaseString(strText);
+ return undefValue;
+}
+
+JSIValue CipherModule::Sha256SubStarts(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ g_sha256Context = CreateSha256Context();
+ Sha256Starts(g_sha256Context);
+ return JSI::CreateUndefined();
+}
+
+JSIValue CipherModule::Sha256SubUpdate(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ JSIValue undefValue = JSI::CreateUndefined();
+ if ((args == nullptr) || argsNum == 0 || JSI::ValueIsUndefined(args[0])) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error.");
+ return undefValue;
+ }
+ char *strText = JSI::ValueToString(args[0]);
+ if (strlen(strText) == 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error , text is nullptr");
+ JSI::ReleaseString(strText);
+ return undefValue;
+ }
+ unsigned char *strTemp = reinterpret_cast<unsigned char *>(strText);
+ Sha256Update(g_sha256Context, strTemp, strlen(strText));
+ JSI::ReleaseString(strText);
+ return undefValue;
+}
+
+JSIValue CipherModule::Sha256SubFinish(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ JSIValue undefValue = JSI::CreateUndefined();
+ if ((args == nullptr) || argsNum == 0 || JSI::ValueIsUndefined(args[0])) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error.");
+ return undefValue;
+ }
+ JSIValue context = JSI::AcquireValue(thisVal);
+ JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
+ JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
+ unsigned char sha256Result[SHA256_LEN];
+ char result[SHA256_RESULT_LEN + 1];
+ Sha256Finish(g_sha256Context, sha256Result);
+ int32_t ret = 0;
+ int size = 2;
+ int sizeBuffer = 3;
+ for (int i = 0; i < SHA256_LEN; i++) {
+ ret = sprintf_s(&result[i * size], sizeBuffer, "%02x", sha256Result[i]);
+ if (ret < 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256SubFinish sprintf_s error.");
+ return undefValue;
+ }
+ }
+ result[SHA256_RESULT_LEN] = '\0';
+ ret = CipherMsgToJS(result, context, success);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Sha256SubFinish send message error.");
+ CipherMsgToJS("Sha256SubFinish error", context, fail);
+ }
+ DestroySha256Context(&g_sha256Context);
+ return undefValue;
+}
+#endif
+// OHOS END
+JSIValue CipherModule::Aes(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
+{
+ JSIValue undefValue = JSI::CreateUndefined();
+ if ((args == nullptr) || argsNum == 0 || JSI::ValueIsUndefined(args[0])) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error.");
+ return undefValue;
+ }
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ JSIValue context = JSI::AcquireValue(thisVal);
+#endif
+ JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
+ JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
+ char *strAction = JSI::GetStringProperty(args[0], "action");
+ char *strText = JSI::GetStringProperty(args[0], "text");
+ char *strKey = JSI::GetStringProperty(args[0], "key");
+ char *strTransformation = JSI::GetStringProperty(args[0], "transformation");
+ char *strIv = JSI::GetStringProperty(args[0], "iv");
+ double ivOffset = JSI::GetNumberProperty(args[0], "ivOffset");
+ JSIValue jsIvLen = JSI::GetNamedProperty(args[0], "ivLen");
+ JSIValue result = JSI::CreateObject();
+ JSIValue code = JSI::CreateNumber(ERR_CODE);
+ JSIValue argvSuccess[ARGC_ONE] = { result };
+ JSIValue data = JSI::CreateString("System error");
+ JSIValue argvFail[ARGC_TWO] = { data, code };
+ CipherAesMode mode = GetMode(strTransformation);
+ PaddingMode paddingMode = GetPaddingMode(strTransformation);
+ AesCryptContext aes = {{NULL, NULL, 0, 0, 0}, mode, {NULL, NULL, 0, 0}, paddingMode};
+ AesIvMode iv = {NULL, NULL, 0, 0};
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ std::string str;
+ int32_t textLen;
+#endif
+ int ret;
+ double ivLen = -1;
+ if (strlen(strText) == 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error , text is nullptr");
+ goto RELEASE;
+ }
+ if (!strcmp(strAction, "encrypt") && paddingMode == PADDING_NONE && strlen(strText) % AES_BLOCK_SIZE != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "args error , text is not valid");
+ goto RELEASE;
+ }
+ if (JSI::ValueIsNumber(jsIvLen)) {
+ ivLen = JSI::ValueToNumber(jsIvLen);
+ if (ivLen < 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Ivlen:%lf is not natural number.", ivLen);
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ CipherMsgToJS("Aes jsIvLen error", context, fail);
+#else
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+#endif
+ goto RELEASE;
+ }
+ }
+
+ iv.ivBuf = strIv;
+ iv.ivLen = ivLen;
+ iv.ivOffset = ivOffset;
+ iv.transformation = strTransformation;
+ ret = InitAesCryptData(strAction, strText, strKey, &iv, &aes);
+ if (ret != ERROR_SUCCESS) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "InitAesCryptData failed.");
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ CipherMsgToJS("InitAesCryptData failed", context, fail);
+#else
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+#endif
+ goto RELEASE;
+ }
+ ret = CipherAesCrypt(&aes);
+ if (ret != ERROR_SUCCESS) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "CipherAesCrypt failed.");
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ CipherMsgToJS("CipherAesCrypt failed", context, fail);
+#else
+ JSI::CallFunction(fail, thisVal, argvFail, ARGC_TWO);
+#endif
+ goto RELEASE;
+ }
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ str = aes.data.text;
+ textLen = aes.data.textLen;
+ ret = CipherMsgToJS(str.substr(0, textLen).c_str(), context, success);
+ if (ret != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Aes send message error.");
+ CipherMsgToJS("Aes send message error.", context, fail);
+ }
+#else
+ JSI::SetStringProperty(result, "text", (char*)aes.data.text);
+ JSI::CallFunction(success, thisVal, argvSuccess, ARGC_ONE);
+#endif
+
+RELEASE:
+ JSI::ReleaseString(strAction);
+ JSI::ReleaseString(strText);
+ ResetStrBuf(strKey);
+ ResetStrBuf(strIv);
+ JSI::ReleaseString(strKey);
+ JSI::ReleaseString(strIv);
+ JSI::ReleaseString(strTransformation);
+ DeinitAesCryptData(&aes);
+ return undefValue;
+}
+// OHOS BEGIN
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+void CipherModule::OnDestroy()
+{
+ if (g_sha256Context != nullptr) {
+ DestroySha256Context(&g_sha256Context);
+ g_sha256Context = nullptr;
+ }
+}
+#endif
+// OHOS END
+void CipherModule::ResetStrBuf(char *strBuf)
+{
+ if (strBuf == nullptr) {
+ return;
+ }
+
+ int ret = memset_s(strBuf, strlen(strBuf), 0, strlen(strBuf));
+ if (ret != EOK) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "memset failed.");
+ }
+}
+
+CipherAesMode CipherModule::GetMode(char *strTransformation)
+{
+ std::string str(strTransformation);
+ int firstIndex = str.find_first_of("/");
+ int lastIndex = str.find_last_of("/");
+ std::string substr = str.substr(firstIndex + 1, lastIndex - (firstIndex + 1));
+ CipherAesMode result = CIPHER_AES_CBC;
+ if (substr == "ECB") {
+ result = CIPHER_AES_ECB;
+ }
+ return result;
+}
+
+PaddingMode CipherModule::GetPaddingMode(char *strTransformation)
+{
+ PaddingMode result = PADDING_NONE;
+ if (!strcmp(strTransformation, "AES/CBC/PKCS5Padding") || !strcmp(strTransformation, "AES/ECB/PKCS5Padding")) {
+ result = PADDING_PKCS5;
+ } else if (!strcmp(strTransformation, "AES/CBC/PKCS7Padding") ||
+ !strcmp(strTransformation, "AES/ECB/PKCS7Padding")) {
+ result = PADDING_PKCS7;
+ }
+ return result;
+}
+
+// OHOS BEGIN
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+static int32_t CopyStr(char **destStr, const char *srcStr)
+{
+ if (destStr == nullptr || srcStr == nullptr) {
+ return -1;
+ }
+
+ uint32_t length = strlen(srcStr) + 1;
+ if (length > MAX_LEN) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "More than Max Memory");
+ return -1;
+ }
+ *destStr = static_cast<char *>(ace_malloc(length));
+ if (*destStr == nullptr) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to allocate memory for destination string");
+ return -1;
+ }
+
+ if (memset_s(*destStr, length, 0, length) != EOK) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to set memory for destination string");
+ ace_free(*destStr);
+ return -1;
+ }
+ if (memcpy_s(*destStr, length, srcStr, length) != EOK) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to copy source string to destination string");
+ ace_free(*destStr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void ExecuteSendMsgToJS(void *data)
+{
+ if (data == nullptr) {
+ return;
+ }
+ CipherMsgParams *params = static_cast<CipherMsgParams *>(data);
+
+ char *msgBody = params->msgBody;
+ OHOS::ACELite::JSIValue callback = params->callback;
+ OHOS::ACELite::JSIValue context = params->context;
+ delete params;
+ params = nullptr;
+
+ OHOS::ACELite::JSIValue dataInfo = OHOS::ACELite::JSI::CreateString(msgBody);
+ OHOS::ACELite::JSIValue callbackArgv[OHOS::ACELite::ARGC_ONE] = {dataInfo};
+ OHOS::ACELite::JSI::CallFunction(callback, context, callbackArgv, OHOS::ACELite::ARGC_ONE);
+ OHOS::ACELite::JSI::ReleaseValue(dataInfo);
+ ace_free(msgBody);
+ return;
+}
+#endif
+// OHOS END
+
+void InitCipherModule(JSIValue exports)
+{
+ JSI::SetModuleAPI(exports, "aes", CipherModule::Aes);
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+ JSI::SetModuleAPI(exports, "sha", CipherModule::Sha256All);
+ JSI::SetModuleAPI(exports, "shaInit", CipherModule::Sha256SubStarts);
+ JSI::SetModuleAPI(exports, "shaUpdate", CipherModule::Sha256SubUpdate);
+ JSI::SetModuleAPI(exports, "shaFinal", CipherModule::Sha256SubFinish);
+ JSI::SetOnDestroy(exports, CipherModule::OnDestroy);
+#endif
+}
+
+} // namespace ACELite
+} // namespace OHOS
+// OHOS START
+#ifdef HUKS_LITEWEARABLE_SUPPORT_ENABLED
+int32_t CipherMsgToJS(const char *msgBody, OHOS::ACELite::JSIValue context, OHOS::ACELite::JSIValue callback)
+{
+ CipherMsgParams *params = new CipherMsgParams();
+ if (params == nullptr) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to allocate memory for params");
+ return -1;
+ }
+ params->context = context;
+ params->callback = callback;
+ int32_t copyRet = OHOS::ACELite::CopyStr(¶ms->msgBody, msgBody);
+ if (copyRet != 0) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to copy msgBody");
+ OHOS::ACELite::ace_free(params->msgBody);
+ params->msgBody = nullptr;
+ delete params;
+ params = nullptr;
+ return copyRet;
+ }
+ bool ret =
+ OHOS::ACELite::JsAsyncWork::DispatchAsyncWork(OHOS::ACELite::ExecuteSendMsgToJS, static_cast<void *>(params));
+ if (!ret) {
+ HILOG_ERROR(HILOG_MODULE_ACE, "Failed to dispatch async work");
+ OHOS::ACELite::ace_free(params->msgBody);
+ params->msgBody = nullptr;
+ delete params;
+ params = nullptr;
+ return -1;
+ }
+ return 0;
+};
+#endif
+// OHOS END