色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙開發:Universal Keystore Kit密鑰管理服務 加密導入密鑰C、C++

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-07-08 15:26 ? 次閱讀

加密導入密鑰(C/C++)

以加密導入ECDH密鑰對為例,涉及業務側加密密鑰的[密鑰生成]、[協商]等操作不在本示例中體現。

具體的場景介紹及支持的算法規格

在CMake腳本中鏈接相關動態庫

target_link_libraries(entry PUBLIC libhuks_ndk.z.so)

開發步驟

  1. 設備A(導入設備)將待導入密鑰轉換成[HUKS密鑰材料格式]To_Import_Key(僅針對非對稱密鑰,若待導入密鑰是對稱密鑰則可省略此步驟)。
  2. 設備B(被導入設備)生成一個加密導入用途的、用于協商的非對稱密鑰對Wrapping_Key(公鑰Wrapping_Pk,私鑰Wrapping_Sk),其密鑰用途設置為unwrap,導出Wrapping_Key的公鑰材料Wrapping_Pk并保存。
  3. 設備A使用和設備B同樣的算法,生成一個加密導入用途的、用于協商的非對稱密鑰對Caller_Key(公鑰Caller_Pk,私鑰Caller_Sk),導出Caller_Key的公鑰材料Caller_Pk并保存。
  4. 設備A生成一個對稱密鑰Caller_Kek,該密鑰后續將用于加密To_Import_Key。
  5. 設備A基于Caller_Key的私鑰Caller_Sk和設備B Wrapping_Key的公鑰Wrapping_Pk,協商出Shared_Key。
  6. 設備A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc。
  7. 設備A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc。
  8. 設備A封裝Caller_Pk、Caller_Kek_Enc、To_Import_Key_Enc等加密導入的密鑰材料并發送給設備B,加密導入密鑰材料格式見[加密導入密鑰材料格式]。
  9. 設備B導入封裝的加密密鑰材料。
  10. 設備A、B刪除用于加密導入的密鑰。
  11. 開發前請熟悉鴻蒙開發指導文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]
#include "napi/native_api.h"
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include < algorithm >
OH_Huks_Result InitParamSet(struct OH_Huks_ParamSet **paramSet, const struct OH_Huks_Param *params,
                            uint32_t paramCount) {
    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        OH_Huks_FreeParamSet(paramSet);
        return ret;
    }
    ret = OH_Huks_BuildParamSet(paramSet);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        OH_Huks_FreeParamSet(paramSet);
        return ret;
    }
    return ret;
}
struct HksImportWrappedKeyTestParams {
    // server key, for real
    struct OH_Huks_Blob *wrappingKeyAlias;
    struct OH_Huks_ParamSet *genWrappingKeyParamSet;
    uint32_t publicKeySize;
    struct OH_Huks_Blob *callerKeyAlias;
    struct OH_Huks_ParamSet *genCallerKeyParamSet;
    struct OH_Huks_Blob *callerKekAlias;
    struct OH_Huks_Blob *callerKek;
    struct OH_Huks_ParamSet *importCallerKekParamSet;
    struct OH_Huks_Blob *callerAgreeKeyAlias;
    struct OH_Huks_ParamSet *agreeParamSet;
    struct OH_Huks_ParamSet *importWrappedKeyParamSet;
    struct OH_Huks_Blob *importedKeyAlias;
    struct OH_Huks_Blob *importedPlainKey;
    uint32_t keyMaterialLen;
};
static const uint32_t IV_SIZE = 16;
static uint8_t IV[IV_SIZE] = "bababababababab"; // 此處僅為測試數據,實際使用時該值每次應該不同
static const uint32_t WRAPPED_KEY_IV_SIZE = 16;
static uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab"; // 此處僅為測試數據,實際使用時該值每次應該不同
static const uint32_t AAD_SIZE = 16;
static uint8_t AAD[AAD_SIZE] = "abababababababa"; // 此處僅為測試數據,實際使用時該值每次應該不同
static const uint32_t NONCE_SIZE = 12;
static uint8_t NONCE[NONCE_SIZE] = "hahahahahah"; // 此處僅為測試數據,實際使用時該值每次應該不同
static const uint32_t AEAD_TAG_SIZE = 16;
static const uint32_t X25519_256_SIZE = 256;
static struct OH_Huks_Blob g_wrappingKeyAliasAes256 = {.size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"),
                                                       .data = (uint8_t *)"test_wrappingKey_x25519_aes256"};
static struct OH_Huks_Blob g_callerKeyAliasAes256 = {.size = (uint32_t)strlen("test_caller_key_x25519_aes256"),
                                                     .data = (uint8_t *)"test_caller_key_x25519_aes256"};
static struct OH_Huks_Blob g_callerKekAliasAes256 = {.size = (uint32_t)strlen("test_caller_kek_x25519_aes256"),
                                                     .data = (uint8_t *)"test_caller_kek_x25519_aes256"};
static struct OH_Huks_Blob g_callerAes256Kek = {.size = (uint32_t)strlen("This is kek to encrypt plain key"),
                                                .data = (uint8_t *)"This is kek to encrypt plain key"};
static struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = {.size =
                                                              (uint32_t)strlen("test_caller_agree_key_x25519_aes256"),
                                                          .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"};
static struct OH_Huks_Blob g_importedKeyAliasAes256 = {.size = (uint32_t)strlen("test_import_key_x25519_aes256"),
                                                       .data = (uint8_t *)"test_import_key_x25519_aes256"};
static struct OH_Huks_Blob g_importedAes256PlainKey = {.size = (uint32_t)strlen("This is plain key to be imported"),
                                                       .data = (uint8_t *)"This is plain key to be imported"};
static struct OH_Huks_Param g_importWrappedAes256Params[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
    {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING},
    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此處僅為測試數據,實際使用時該值應與調用者信息相關
    {.tag = OH_HUKS_TAG_NONCE,
     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此處僅為測試數據,實際使用時該值每次應該不同
static const uint32_t g_x25519PubKeySize = 32;
static struct OH_Huks_Param g_genWrappingKeyParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
static struct OH_Huks_Param g_genCallerX25519Params[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
static struct OH_Huks_Param g_importParamsCallerKek[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
    {.tag = OH_HUKS_TAG_IV,
     .blob = {.size = WRAPPED_KEY_IV_SIZE,
              .data = (uint8_t *)WRAPPED_KEY_IV}}}; // 此處僅為測試數據,實際使用時該值每次應該不同
static struct OH_Huks_Param g_callerAgreeParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
static struct OH_Huks_Param g_aesKekEncryptParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此處僅為測試數據,實際使用時該值應與調用者信息相關
    {.tag = OH_HUKS_TAG_NONCE,
     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此處僅為測試數據,實際使用時該值每次應該不同
static struct OH_Huks_Param g_importAgreeKeyParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
    {.tag = OH_HUKS_TAG_IV,
     .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // 此處僅為測試數據,實際使用時該值每次應該不同
OH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias,
                            const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey) {
    uint8_t temp[10] = {0};
    struct OH_Huks_Blob inData = {sizeof(temp), temp};
    uint8_t handleU[sizeof(uint64_t)] = {0};
    struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU};
    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    uint8_t outDataU[1024] = {0};
    struct OH_Huks_Blob outDataUpdate = {1024, outDataU};
    ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    return ret;
}
OH_Huks_Result MallocAndCheckBlobData(struct OH_Huks_Blob *blob, const uint32_t blobSize) {
    struct OH_Huks_Result ret;
    ret.errorCode = OH_HUKS_SUCCESS;
    blob- >data = (uint8_t *)malloc(blobSize);
    if (blob- >data == NULL) {
        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
    }
    return ret;
}
static const uint32_t TIMES = 4;
static const uint32_t MAX_UPDATE_SIZE = 64;
static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
#define HUKS_FREE_BLOB(blob)                                                                                           
    do {                                                                                                               
        if ((blob).data != nullptr) {                                                                                  
            free((blob).data);                                                                                         
            (blob).data = nullptr;                                                                                     
        }                                                                                                              
        (blob).size = 0;                                                                                               
    } while (0)
#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8)
static OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet,
                                           const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData) {
    struct OH_Huks_Result ret;
    ret.errorCode = OH_HUKS_SUCCESS;
    struct OH_Huks_Blob inDataSeg = *inData;
    uint8_t *lastPtr = inData- >data + inData- >size - 1;
    struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL};
    uint8_t *cur = outData- >data;
    outData- >size = 0;
    inDataSeg.size = MAX_UPDATE_SIZE;
    bool isFinished = false;
    while (inDataSeg.data <= lastPtr) {
        if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) {
            outDataSeg.size = MAX_OUTDATA_SIZE;
        } else {
            isFinished = true;
            inDataSeg.size = lastPtr - inDataSeg.data + 1;
            break;
        }
        if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
            return ret;
        }
        ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg);
        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
            free(outDataSeg.data);
            return ret;
        }
        std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur);
        cur += outDataSeg.size;
        outData- >size += outDataSeg.size;
        free(outDataSeg.data);
        if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) {
            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
            return ret;
        }
        inDataSeg.data += MAX_UPDATE_SIZE;
    }
    struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL};
    if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
        return ret;
    }
    ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        free(outDataFinish.data);
        return ret;
    }
    std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur);
    outData- >size += outDataFinish.size;
    free(outDataFinish.data);
    return ret;
}
OH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet,
                           const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText) {
    uint8_t handle[sizeof(uint64_t)] = {0};
    struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle};
    OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText);
    return ret;
}
static OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size,
                                          struct OH_Huks_Blob *outData) {
    uint32_t totalLength = size * sizeof(uint32_t);
    struct OH_Huks_Result ret;
    ret.errorCode = OH_HUKS_SUCCESS;
    /* 計算大小 */
    for (uint32_t i = 0; i < size; ++i) {
        totalLength += blobArray[i]- >size;
    }
    struct OH_Huks_Blob outBlob = {0, nullptr};
    outBlob.size = totalLength;
    ret = MallocAndCheckBlobData(&outBlob, outBlob.size);
    if (ret.errorCode != OH_HUKS_SUCCESS) {
        return ret;
    }
    uint32_t offset = 0;
    /* 拷貝數據 */
    for (uint32_t i = 0; i < size; ++i) {
        if (totalLength - offset >= sizeof(blobArray[i]- >size)) {
            std::copy(reinterpret_cast< uint8_t * >(&blobArray[i]- >size),
                      reinterpret_cast< uint8_t * >(&blobArray[i]- >size) + sizeof(blobArray[i]- >size),
                      outBlob.data + offset);
        } else {
            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
            return ret;
        }
        offset += sizeof(blobArray[i]- >size);
        if (totalLength - offset >= blobArray[i]- >size) {
            std::copy(blobArray[i]- >data, blobArray[i]- >data + blobArray[i]- >size, outBlob.data + offset);
        } else {
            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
            return ret;
        }
        offset += blobArray[i]- >size;
    }
    outData- >size = outBlob.size;
    outData- >data = outBlob.data;
    return ret;
}
static OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params) {
    struct OH_Huks_Result ret;
    ret.errorCode = OH_HUKS_SUCCESS;
    if (params == nullptr) {
        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
        return ret;
    }
    if (params- >wrappingKeyAlias == nullptr || params- >genWrappingKeyParamSet == nullptr ||
        params- >callerKeyAlias == nullptr || params- >genCallerKeyParamSet == nullptr ||
        params- >callerKekAlias == nullptr || params- >callerKek == nullptr ||
        params- >importCallerKekParamSet == nullptr || params- >callerAgreeKeyAlias == nullptr ||
        params- >agreeParamSet == nullptr || params- >importWrappedKeyParamSet == nullptr ||
        params- >importedKeyAlias == nullptr || params- >importedPlainKey == nullptr) {
        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
        return ret;
    }
    return ret;
}
static OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params,
                                                     struct OH_Huks_Blob *huksPublicKey) {
    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params- >wrappingKeyAlias, params- >genWrappingKeyParamSet, nullptr);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    huksPublicKey- >size = params- >publicKeySize;
    ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey- >size);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_ExportPublicKeyItem(params- >wrappingKeyAlias, nullptr, huksPublicKey);
    return ret;
}
static OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params,
                                                       struct OH_Huks_Blob *callerSelfPublicKey) {
    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params- >callerKeyAlias, params- >genCallerKeyParamSet, nullptr);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    callerSelfPublicKey- >size = params- >publicKeySize;
    ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey- >size);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_ExportPublicKeyItem(params- >callerKeyAlias, params- >genWrappingKeyParamSet, callerSelfPublicKey);
    return ret;
}
static OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params,
                                                    const struct OH_Huks_Blob *huksPublicKey,
                                                    struct OH_Huks_Blob *outSharedKey) {
    OH_Huks_Result ret =
        OH_Huks_ImportKeyItem(params- >callerKekAlias, params- >importCallerKekParamSet, params- >callerKek);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = MallocAndCheckBlobData(outSharedKey, outSharedKey- >size);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = HuksAgreeKey(params- >agreeParamSet, params- >callerKeyAlias, huksPublicKey, outSharedKey);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr;
    ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams,
                       sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param));
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_ImportKeyItem(params- >callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey);
    OH_Huks_FreeParamSet(&importAgreeKeyParams);
    return ret;
}
static OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params,
                                                    struct OH_Huks_Blob *plainCipherText,
                                                    struct OH_Huks_Blob *kekCipherText) {
    struct OH_Huks_ParamSet *encryptParamSet = nullptr;
    OH_Huks_Result ret =
        InitParamSet(&encryptParamSet, g_aesKekEncryptParams, sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param));
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = HuksEncrypt(params- >callerKekAlias, encryptParamSet, params- >importedPlainKey, plainCipherText);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = HuksEncrypt(params- >callerAgreeKeyAlias, encryptParamSet, params- >callerKek, kekCipherText);
    OH_Huks_FreeParamSet(&encryptParamSet);
    return ret;
}
static OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params,
                                       struct OH_Huks_Blob *plainCipher, struct OH_Huks_Blob *kekCipherText,
                                       struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData) {
    struct OH_Huks_Blob commonAad = {.size = AAD_SIZE, .data = reinterpret_cast< uint8_t * >(AAD)};
    struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE, .data = reinterpret_cast< uint8_t * >(NONCE)};
    struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)¶ms- >keyMaterialLen};
    /* 從密文中拷貝AEAD的tag并縮小其大小 */
    const uint32_t tagSize = AEAD_TAG_SIZE;
    uint8_t kekTagBuf[tagSize] = {0};
    struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf};
    std::copy(plainCipher- >data + (plainCipher- >size - tagSize),
              plainCipher- >data + (plainCipher- >size - tagSize) + tagSize, kekTag.data);
    plainCipher- >size -= tagSize;
    /* 從密鑰加密密鑰的密文中拷貝AEAD的tag并縮小其大小 */
    uint8_t agreeKeyTagBuf[tagSize] = {0};
    struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf};
    std::copy(kekCipherText- >data + (kekCipherText- >size - tagSize),
              kekCipherText- >data + (kekCipherText- >size - tagSize) + tagSize, agreeKeyTagBuf);
    kekCipherText- >size -= tagSize;
    struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad,   &commonNonce, &agreeKeyTag,    kekCipherText,
                                        &commonAad,    &commonNonce, &kekTag,      &keyMaterialLen, plainCipher};
    OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    struct OH_Huks_Param *purpose = nullptr;
    ret = OH_Huks_GetParam(params- >importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    ret = OH_Huks_ImportWrappedKeyItem(params- >importedKeyAlias, params- >wrappingKeyAlias,
                                       params- >importWrappedKeyParamSet, wrappedKeyData);
    return ret;
}
OH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params) {
    OH_Huks_Result ret = CheckParamsValid(params);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return ret;
    }
    struct OH_Huks_Blob huksPublicKey = {0, nullptr};
    struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr};
    struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr};
    struct OH_Huks_Blob wrappedKeyData = {0, nullptr};
    uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
    struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer};
    uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
    struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer};
    /* 模擬加密導入密鑰場景,設備A為遠端設備(導入設備),設備B為本端設備(被導入設備) */
    do {
        /**
         * 1.設備A將待導入密鑰轉換成HUKS密鑰材料格式To_Import_Key(僅針對非對稱密鑰,若待導入密鑰是對稱密鑰則可省略此步驟),
         *   本示例使用g_importedAes256PlainKey(對稱密鑰)作為模擬
         */
        /* 2.設備B生成一個加密導入用途的、用于協商的非對稱密鑰對Wrapping_Key(公鑰Wrapping_Pk,私鑰Wrapping_Sk),其密鑰用途設置為unwrap,導出Wrapping_Key公鑰Wrapping_Pk存放在變量huksPublicKey中
         */
        ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey);
        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
            break;
        }
        /* 3.設備A使用和設備B同樣的算法,生成一個加密導入用途的、用于協商的非對稱密鑰對Caller_Key(公鑰Caller_Pk,私鑰Caller_Sk),導出Caller_Key公鑰Caller_Pk存放在變量callerSelfPublicKey中
         */
        ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
            break;
        }
        /**
         * 4. 設備A生成一個對稱密鑰Caller_Kek,該密鑰后續將用于加密To_Import_Key
         * 5. 設備A基于Caller_Key的私鑰Caller_Sk和設備B Wrapping_Key的公鑰Wrapping_Pk,協商出Shared_Key
         */
        ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
            break;
        }
        /**
         * 6. 設備A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc
         * 7. 設備A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc
         */
        ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
            break;
        }
        /* 8. 設備A封裝Caller_Pk、To_Import_Key_Enc、Caller_Kek_Enc等加密導入的材料并發送給設備B。
         * 本示例作為變量存放在callerSelfPublicKey,plainCipherText,kekCipherText
         * 9. 設備B導入封裝的加密密鑰材料
         */
        ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
    } while (0);
    /* 10. 設備A、B刪除用于加密導入的密鑰 */
    HUKS_FREE_BLOB(huksPublicKey);
    HUKS_FREE_BLOB(callerSelfPublicKey);
    HUKS_FREE_BLOB(outSharedKey);
    HUKS_FREE_BLOB(wrappedKeyData);
    return ret;
}
void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params) {
    OH_Huks_Result ret = CheckParamsValid(params);
    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
        return;
    }
    (void)OH_Huks_DeleteKeyItem(params- >wrappingKeyAlias, nullptr);
    (void)OH_Huks_DeleteKeyItem(params- >callerKeyAlias, nullptr);
    (void)OH_Huks_DeleteKeyItem(params- >callerKekAlias, nullptr);
    (void)OH_Huks_DeleteKeyItem(params- >callerAgreeKeyAlias, nullptr);
    (void)OH_Huks_DeleteKeyItem(params- >importedKeyAlias, nullptr);
}
static OH_Huks_Result InitCommonTestParamsAndDoImport(struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams,
                                                      const struct OH_Huks_Param *importedKeyParamSetArray,
                                                      uint32_t arraySize) {
    struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr;
    struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr;
    struct OH_Huks_ParamSet *callerImportParamsKek = nullptr;
    struct OH_Huks_ParamSet *agreeParamSet = nullptr;
    struct OH_Huks_ParamSet *importPlainKeyParams = nullptr;
    OH_Huks_Result ret;
    do {
        ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams,
                           sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param));
        if (ret.errorCode != OH_HUKS_SUCCESS) {
            break;
        }
        importWrappedKeyTestParams- >genWrappingKeyParamSet = genX25519KeyParamSet;
        importWrappedKeyTestParams- >publicKeySize = g_x25519PubKeySize;
        ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params,
                           sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param));
        if (ret.errorCode != OH_HUKS_SUCCESS) {
            break;
        }
        importWrappedKeyTestParams- >genCallerKeyParamSet = genCallerKeyParamSet;
        ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek,
                           sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param));
        if (ret.errorCode != OH_HUKS_SUCCESS) {
            break;
        }
        importWrappedKeyTestParams- >importCallerKekParamSet = callerImportParamsKek;
        ret = InitParamSet(&agreeParamSet, g_callerAgreeParams, sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param));
        if (ret.errorCode != OH_HUKS_SUCCESS) {
            break;
        }
        importWrappedKeyTestParams- >agreeParamSet = agreeParamSet;
        ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize);
        if (ret.errorCode != OH_HUKS_SUCCESS) {
            break;
        }
        importWrappedKeyTestParams- >importWrappedKeyParamSet = importPlainKeyParams;
        ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams);
    } while (0);
    OH_Huks_FreeParamSet(&genX25519KeyParamSet);
    OH_Huks_FreeParamSet(&genCallerKeyParamSet);
    OH_Huks_FreeParamSet(&callerImportParamsKek);
    OH_Huks_FreeParamSet(&agreeParamSet);
    OH_Huks_FreeParamSet(&importPlainKeyParams);
    return ret;
}
static napi_value ImportWrappedKey(napi_env env, napi_callback_info info) {
    struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0};
    importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256;
    importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size;
    importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256;
    importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256;
    importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek;
    importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256;
    importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256;
    importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey;
    OH_Huks_Result ohResult =
        InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params,
                                        sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param));
    HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001);
    napi_value ret;
    napi_create_int32(env, ohResult.errorCode, &ret);
    return ret;
}

`HarmonyOSOpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`

QQ截圖20240705211300.png

調測驗證

調用[OH_Huks_IsKeyItemExist]驗證密鑰是否存在,如密鑰存在即表示密鑰導入成功。

#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include < string.h >
static napi_value IsKeyExist(napi_env env, napi_callback_info info)
{
    /* 1.指定密鑰別名 */
    struct OH_Huks_Blob keyAlias = {
        (uint32_t)strlen("test_key"),
        (uint8_t *)"test_key"
    };
    
    /* 2.調用OH_Huks_IsKeyItemExist判斷密鑰是否存在  */
    struct OH_Huks_Result ohResult = OH_Huks_IsKeyItemExist(&keyAlias, NULL);
    if (ohResult.errorCode != OH_HUKS_SUCCESS) {
        // 失敗 
    } else {
        // 成功
    }
}

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2108

    瀏覽量

    73620
  • 鴻蒙
    +關注

    關注

    57

    文章

    2339

    瀏覽量

    42805
收藏 人收藏

    評論

    相關推薦

    鴻蒙開發Universal Keystore Kit密鑰管理服務簡介

    Universal Keystore Kit密鑰管理服務,下述簡稱為HUKS)向業務/應用提供
    的頭像 發表于 07-04 14:20 ?437次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b>簡介

    鴻蒙開發Universal Keystore Kit密鑰管理服務 生成密鑰CC++

    以生成ECC密鑰為例,生成隨機密鑰。具體的場景介紹及支持的算法規格。
    的頭像 發表于 07-06 10:48 ?1136次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> 生成<b class='flag-5'>密鑰</b><b class='flag-5'>C</b>、<b class='flag-5'>C++</b>

    鴻蒙開發Universal Keystore Kit密鑰管理服務 密鑰導入介紹及算法規格

    如果業務在HUKS外部生成密鑰(比如應用間協商生成、服務器端生成),業務可以將密鑰導入到HUKS中由HUKS進行管理
    的頭像 發表于 07-06 10:45 ?676次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> <b class='flag-5'>密鑰</b><b class='flag-5'>導入</b>介紹及算法規格

    鴻蒙開發Universal Keystore Kit密鑰管理服務 明文導入密鑰 ArkTS

    分別以導入AES256與RSA2048密鑰為例,具體的場景介紹及支持的算法規格
    的頭像 發表于 07-08 10:22 ?375次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> 明文<b class='flag-5'>導入</b><b class='flag-5'>密鑰</b> ArkTS

    鴻蒙開發Universal Keystore Kit密鑰管理服務 明文導入密鑰CC++

    以明文導入ECC密鑰為例。具體的場景介紹及支持的算法規格
    的頭像 發表于 07-08 10:01 ?300次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> 明文<b class='flag-5'>導入</b><b class='flag-5'>密鑰</b><b class='flag-5'>C</b>、<b class='flag-5'>C++</b>

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 加密導入密鑰 ArkTS

    加密導入ECDH密鑰對為例,涉及業務側加密密鑰的[密鑰生成]、[協商])等操作不在本示例中體現。
    的頭像 發表于 07-08 14:22 ?357次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b> <b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> <b class='flag-5'>加密</b><b class='flag-5'>導入</b><b class='flag-5'>密鑰</b> ArkTS

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 密鑰協商 CC++

    以協商密鑰類型為ECDH,并密鑰僅在HUKS內使用為例,完成密鑰協商。具體的場景介紹及支持的算法規格,請參考[密鑰生成支持的算法]。
    的頭像 發表于 07-10 14:27 ?347次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b> <b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> <b class='flag-5'>密鑰</b>協商 <b class='flag-5'>C</b>、<b class='flag-5'>C++</b>

    鴻蒙開發Universal Keystore Kit密鑰管理服務 密鑰派生CC++

    以HKDF256密鑰為例,完成密鑰派生。具體的場景介紹及支持的算法規格,請參考[密鑰生成支持的算法]。
    的頭像 發表于 07-11 14:28 ?290次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b><b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> <b class='flag-5'>密鑰</b>派生<b class='flag-5'>C</b>、<b class='flag-5'>C++</b>

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 HMAC CC++

    HMAC是密鑰相關的哈希運算消息認證碼(Hash-based Message Authentication Code),是一種基于Hash函數和密鑰進行消息認證的方法。
    的頭像 發表于 07-12 09:36 ?321次閱讀

    鴻蒙開發Universal Keystore Kit密鑰管理服務 密鑰刪除C C++

    為保證數據安全性,當不需要使用該密鑰時,應該刪除密鑰
    的頭像 發表于 07-18 15:47 ?289次閱讀

    鴻蒙開發Universal Keystore Kit密鑰管理服務 查詢密鑰是否存在CC++

    HUKS提供了接口供應用查詢指定密鑰是否存在。
    的頭像 發表于 07-16 09:58 ?285次閱讀

    鴻蒙開發Universal Keystore Kit密鑰管理服務 查詢密鑰是否存在C C++

    HUKS提供了接口供應用查詢指定密鑰是否存在。
    的頭像 發表于 07-16 14:21 ?232次閱讀

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 獲取密鑰屬性ArkTS

    HUKS提供了接口供業務獲取指定密鑰的相關屬性。在獲取指定密鑰屬性前,需要確保已在HUKS中生成或導入持久化存儲的密鑰
    的頭像 發表于 07-17 10:46 ?307次閱讀

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 獲取密鑰屬性C C++

    HUKS提供了接口供業務獲取指定密鑰的相關屬性。在獲取指定密鑰屬性前,需要確保已在HUKS中生成或導入持久化存儲的密鑰
    的頭像 發表于 07-17 09:47 ?360次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b> <b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> 獲取<b class='flag-5'>密鑰</b>屬性<b class='flag-5'>C</b> <b class='flag-5'>C++</b>

    鴻蒙開發Universal Keystore Kit 密鑰管理服務 密鑰導出 C C++

    業務需要獲取持久化存儲的非對稱密鑰的公鑰時使用,當前支持ECC/RSA/ED25519/X25519的公鑰導出。
    的頭像 發表于 07-18 10:28 ?385次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>:<b class='flag-5'>Universal</b> <b class='flag-5'>Keystore</b> <b class='flag-5'>Kit</b> <b class='flag-5'>密鑰</b><b class='flag-5'>管理</b><b class='flag-5'>服務</b> <b class='flag-5'>密鑰</b>導出 <b class='flag-5'>C</b> <b class='flag-5'>C++</b>
    主站蜘蛛池模板: 亚洲影院在线播放| 亚洲精品白色在线发布| 亚洲国产精品无码中文字满| 在线观看视频中文字幕| FREECHINESE东北群交| 国产精品资源网站在线观看| 久久偷拍人| 手机在线免费观看毛片| 友田真希息与子中文字幕| 春暖花开 性 欧洲| 久久99精品视频| 日本男女动态图| 曰批国产精品视频免费观看| 风情韵味人妻HD| 久久在精品线影院精品国产| 色姐妹久久综合在线av| 在线看无码的免费网站| 国产精品成人无码久免费| 美女被爆羞羞天美传媒| 亚洲 自拍 欧洲 视频二区| 99热这里只有精品88| 精品国产福利在线视频| 色偷偷爱偷偷要| 97国产露脸精品国产麻豆| 国产亚洲精品在浅麻豆| 人妻插B视频一区二区三区| 伊人久久电影院| 国产乱人伦AV麻豆网| 欧洲馒头大肥p| 在线免费观看a视频| 国产欧美日韩国产高清| 情欲.美女高潮| 最近的2019中文字幕HD| 国产一区91| 特级毛片s级全部免费| 97在线视频免费| 久久91精品国产91| 亚洲AV色香蕉一区二区9255| 多人乱肉高hnp| 欧美特级特黄AAAAA片| 最新亚洲人成网站在线影院|