154aa6d63Sopenharmony_ci/*
254aa6d63Sopenharmony_ci * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
354aa6d63Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
454aa6d63Sopenharmony_ci * you may not use this file except in compliance with the License.
554aa6d63Sopenharmony_ci * You may obtain a copy of the License at
654aa6d63Sopenharmony_ci *
754aa6d63Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
854aa6d63Sopenharmony_ci *
954aa6d63Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1054aa6d63Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1154aa6d63Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1254aa6d63Sopenharmony_ci * See the License for the specific language governing permissions and
1354aa6d63Sopenharmony_ci * limitations under the License.
1454aa6d63Sopenharmony_ci */
1554aa6d63Sopenharmony_ci#include "digest_common.h"
1654aa6d63Sopenharmony_ci#include "signature_tools_log.h"
1754aa6d63Sopenharmony_ci#include "openssl/err.h"
1854aa6d63Sopenharmony_ci
1954aa6d63Sopenharmony_cinamespace OHOS {
2054aa6d63Sopenharmony_cinamespace SignatureTools {
2154aa6d63Sopenharmony_ciconst int32_t DigestCommon::OPENSSL_ERR_MESSAGE_MAX_LEN = 1024;
2254aa6d63Sopenharmony_ci
2354aa6d63Sopenharmony_ciint32_t DigestCommon::GetDigestAlgorithmOutputSizeBytes(int32_t nId)
2454aa6d63Sopenharmony_ci{
2554aa6d63Sopenharmony_ci    return EVP_MD_size(EVP_get_digestbynid(nId));
2654aa6d63Sopenharmony_ci}
2754aa6d63Sopenharmony_ci
2854aa6d63Sopenharmony_cibool DigestCommon::CheckDigestParameter(const DigestParameter& digestParameter)
2954aa6d63Sopenharmony_ci{
3054aa6d63Sopenharmony_ci    if (digestParameter.md == nullptr) {
3154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("md is nullptr");
3254aa6d63Sopenharmony_ci        return false;
3354aa6d63Sopenharmony_ci    }
3454aa6d63Sopenharmony_ci    if (digestParameter.ctxPtr == nullptr) {
3554aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("ctxPtr is nullptr");
3654aa6d63Sopenharmony_ci        return false;
3754aa6d63Sopenharmony_ci    }
3854aa6d63Sopenharmony_ci    return true;
3954aa6d63Sopenharmony_ci}
4054aa6d63Sopenharmony_ci
4154aa6d63Sopenharmony_cibool DigestCommon::DigestInit(const DigestParameter& digestParameter)
4254aa6d63Sopenharmony_ci{
4354aa6d63Sopenharmony_ci    if (!CheckDigestParameter(digestParameter)) {
4454aa6d63Sopenharmony_ci        return false;
4554aa6d63Sopenharmony_ci    }
4654aa6d63Sopenharmony_ci    if (EVP_DigestInit(digestParameter.ctxPtr, digestParameter.md) <= 0) {
4754aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
4854aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestInit failed");
4954aa6d63Sopenharmony_ci        return false;
5054aa6d63Sopenharmony_ci    }
5154aa6d63Sopenharmony_ci    return true;
5254aa6d63Sopenharmony_ci}
5354aa6d63Sopenharmony_ci
5454aa6d63Sopenharmony_ci/* the caller must ensure that EVP_DigestInit was called before calling this function */
5554aa6d63Sopenharmony_cibool DigestCommon::DigestUpdate(const DigestParameter& digestParameter,
5654aa6d63Sopenharmony_ci                                         const unsigned char content[], int32_t len)
5754aa6d63Sopenharmony_ci{
5854aa6d63Sopenharmony_ci    if (content == nullptr) {
5954aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("content is nullptr");
6054aa6d63Sopenharmony_ci        return false;
6154aa6d63Sopenharmony_ci    }
6254aa6d63Sopenharmony_ci    if (!CheckDigestParameter(digestParameter)) {
6354aa6d63Sopenharmony_ci        return false;
6454aa6d63Sopenharmony_ci    }
6554aa6d63Sopenharmony_ci    if (EVP_DigestUpdate(digestParameter.ctxPtr, content, len) <= 0) {
6654aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
6754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestUpdate failed");
6854aa6d63Sopenharmony_ci        return false;
6954aa6d63Sopenharmony_ci    }
7054aa6d63Sopenharmony_ci    return true;
7154aa6d63Sopenharmony_ci}
7254aa6d63Sopenharmony_ci
7354aa6d63Sopenharmony_ciint32_t DigestCommon::GetDigest(const DigestParameter& digestParameter,
7454aa6d63Sopenharmony_ci                                         unsigned char(&out)[EVP_MAX_MD_SIZE])
7554aa6d63Sopenharmony_ci{
7654aa6d63Sopenharmony_ci    uint32_t outLen = 0;
7754aa6d63Sopenharmony_ci    if (!CheckDigestParameter(digestParameter)) {
7854aa6d63Sopenharmony_ci        return outLen;
7954aa6d63Sopenharmony_ci    }
8054aa6d63Sopenharmony_ci    if (EVP_DigestFinal(digestParameter.ctxPtr, out, &outLen) <= 0) {
8154aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
8254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestFinal failed");
8354aa6d63Sopenharmony_ci        outLen = 0;
8454aa6d63Sopenharmony_ci    }
8554aa6d63Sopenharmony_ci    return outLen;
8654aa6d63Sopenharmony_ci}
8754aa6d63Sopenharmony_ci
8854aa6d63Sopenharmony_ciint32_t DigestCommon::GetDigest(const ByteBuffer& chunk,
8954aa6d63Sopenharmony_ci                                         const std::vector<OptionalBlock>& optionalBlocks,
9054aa6d63Sopenharmony_ci                                         const DigestParameter& digestParameter,
9154aa6d63Sopenharmony_ci                                         unsigned char(&out)[EVP_MAX_MD_SIZE])
9254aa6d63Sopenharmony_ci{
9354aa6d63Sopenharmony_ci    int32_t chunkLen = chunk.Remaining();
9454aa6d63Sopenharmony_ci    uint32_t outLen = 0;
9554aa6d63Sopenharmony_ci    if (digestParameter.md == nullptr) {
9654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("md is nullprt");
9754aa6d63Sopenharmony_ci        return outLen;
9854aa6d63Sopenharmony_ci    }
9954aa6d63Sopenharmony_ci    if (digestParameter.ctxPtr == nullptr) {
10054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("ctxPtr is nullprt");
10154aa6d63Sopenharmony_ci        return outLen;
10254aa6d63Sopenharmony_ci    }
10354aa6d63Sopenharmony_ci    if (EVP_DigestInit(digestParameter.ctxPtr, digestParameter.md) <= 0) {
10454aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
10554aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestInit failed");
10654aa6d63Sopenharmony_ci        return outLen;
10754aa6d63Sopenharmony_ci    }
10854aa6d63Sopenharmony_ci    if (EVP_DigestUpdate(digestParameter.ctxPtr, chunk.GetBufferPtr(), chunkLen) <= 0) {
10954aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
11054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestUpdate chunk failed");
11154aa6d63Sopenharmony_ci        return outLen;
11254aa6d63Sopenharmony_ci    }
11354aa6d63Sopenharmony_ci    for (int32_t i = 0; i < static_cast<int>(optionalBlocks.size()); i++) {
11454aa6d63Sopenharmony_ci        chunkLen = optionalBlocks[i].optionalBlockValue.GetCapacity();
11554aa6d63Sopenharmony_ci        if (EVP_DigestUpdate(digestParameter.ctxPtr, optionalBlocks[i].optionalBlockValue.GetBufferPtr(),
11654aa6d63Sopenharmony_ci            chunkLen) <= 0) {
11754aa6d63Sopenharmony_ci            GetOpensslErrorMessage();
11854aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("EVP_DigestUpdate %dst optional block failed", i);
11954aa6d63Sopenharmony_ci            return outLen;
12054aa6d63Sopenharmony_ci        }
12154aa6d63Sopenharmony_ci    }
12254aa6d63Sopenharmony_ci    if (EVP_DigestFinal(digestParameter.ctxPtr, out, &outLen) <= 0) {
12354aa6d63Sopenharmony_ci        GetOpensslErrorMessage();
12454aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("EVP_DigestFinal failed");
12554aa6d63Sopenharmony_ci        outLen = 0;
12654aa6d63Sopenharmony_ci    }
12754aa6d63Sopenharmony_ci    return outLen;
12854aa6d63Sopenharmony_ci}
12954aa6d63Sopenharmony_ci
13054aa6d63Sopenharmony_civoid DigestCommon::GetOpensslErrorMessage()
13154aa6d63Sopenharmony_ci{
13254aa6d63Sopenharmony_ci    unsigned long retOpenssl;
13354aa6d63Sopenharmony_ci    char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
13454aa6d63Sopenharmony_ci    while ((retOpenssl = ERR_get_error()) != 0) {
13554aa6d63Sopenharmony_ci        ERR_error_string(retOpenssl, errOpenssl);
13654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("openssl err: %lu, message: %s", retOpenssl, errOpenssl);
13754aa6d63Sopenharmony_ci    }
13854aa6d63Sopenharmony_ci}
13954aa6d63Sopenharmony_ci
14054aa6d63Sopenharmony_ciint32_t DigestCommon::GetDigestAlgorithmId(int32_t signAlgorithm)
14154aa6d63Sopenharmony_ci{
14254aa6d63Sopenharmony_ci    switch (signAlgorithm) {
14354aa6d63Sopenharmony_ci        case ALGORITHM_SHA256_WITH_ECDSA:
14454aa6d63Sopenharmony_ci        case ALGORITHM_SHA256_WITH_DSA:
14554aa6d63Sopenharmony_ci            return NID_sha256;
14654aa6d63Sopenharmony_ci        case ALGORITHM_SHA384_WITH_ECDSA:
14754aa6d63Sopenharmony_ci        case ALGORITHM_SHA384_WITH_DSA:
14854aa6d63Sopenharmony_ci            return NID_sha384;
14954aa6d63Sopenharmony_ci        case ALGORITHM_SHA512_WITH_ECDSA:
15054aa6d63Sopenharmony_ci        case ALGORITHM_SHA512_WITH_DSA:
15154aa6d63Sopenharmony_ci            return NID_sha512;
15254aa6d63Sopenharmony_ci        default:
15354aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("signAlgorithm: %d error", signAlgorithm);
15454aa6d63Sopenharmony_ci            return NID_undef;
15554aa6d63Sopenharmony_ci    }
15654aa6d63Sopenharmony_ci}
15754aa6d63Sopenharmony_ci
15854aa6d63Sopenharmony_cistd::string DigestCommon::GetDigestAlgorithmString(int32_t signAlgorithm)
15954aa6d63Sopenharmony_ci{
16054aa6d63Sopenharmony_ci    switch (signAlgorithm) {
16154aa6d63Sopenharmony_ci        case ALGORITHM_SHA256_WITH_ECDSA:
16254aa6d63Sopenharmony_ci            return "SHA-256";
16354aa6d63Sopenharmony_ci        case ALGORITHM_SHA384_WITH_ECDSA:
16454aa6d63Sopenharmony_ci            return "SHA-384";
16554aa6d63Sopenharmony_ci        case ALGORITHM_SHA512_WITH_ECDSA:
16654aa6d63Sopenharmony_ci            return "SHA-512";
16754aa6d63Sopenharmony_ci        default:
16854aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("signAlgorithm: %d error", signAlgorithm);
16954aa6d63Sopenharmony_ci            return "";
17054aa6d63Sopenharmony_ci    }
17154aa6d63Sopenharmony_ci}
17254aa6d63Sopenharmony_ci} // namespace SignatureTools
17354aa6d63Sopenharmony_ci} // namespace OHOS