1/*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "signature_tools_log.h"
17#include "pkcs7_data.h"
18#include "constant.h"
19#include "local_signer.h"
20
21namespace OHOS {
22namespace SignatureTools {
23/**
24* Create local signer.
25*
26* @param keyPair   Private key to sign
27* @param certificates Cert chain to sign
28*/
29LocalSigner::LocalSigner(EVP_PKEY* keyPair, STACK_OF(X509)* certificates) :m_keyPair(keyPair),
30m_certificates(certificates)
31{
32    bool check = m_keyPair == NULL ||
33                 PKCS7Data::SortX509Stack(m_certificates) < 0 ||
34                 X509_check_private_key(sk_X509_value(m_certificates, 0), m_keyPair) != 1;
35    if (check) {
36        SIGNATURE_TOOLS_LOGW("Warning: invalid local signer!\n");
37        sk_X509_pop_free(m_certificates, X509_free);
38        m_certificates = NULL;
39    }
40}
41LocalSigner::~LocalSigner()
42{
43    if (m_keyPair) {
44        EVP_PKEY_free(m_keyPair);
45        m_keyPair = NULL;
46    }
47    if (m_certificates) {
48        sk_X509_pop_free(m_certificates, X509_free);
49        m_certificates = NULL;
50    }
51}
52STACK_OF(X509_CRL)* LocalSigner::GetCrls() const
53{
54    return NULL;
55}
56
57static X509* X509Dup(const X509* x509)
58{
59    return X509_dup(const_cast<X509*>(x509));
60}
61
62STACK_OF(X509)* LocalSigner::GetCertificates() const
63{
64    if (m_certificates == NULL) {
65        return m_certificates;
66    }
67    return sk_X509_deep_copy(m_certificates, X509Dup, X509_free);
68}
69std::string LocalSigner::GetSignature(const std::string& data, const std::string& signAlg) const
70{
71    EVP_MD_CTX* hashCtx = NULL;
72    EVP_PKEY_CTX* privateKeyCtx = NULL;
73    unsigned char* sigResult = NULL;
74    const EVP_MD* hash = NULL;
75    size_t sigLen;
76    std::string ret;
77
78    if (signAlg == SIGN_ALG_SHA256) {
79        hash = EVP_sha256();
80    } else if (signAlg == SIGN_ALG_SHA384) {
81        hash = EVP_sha384();
82    } else {
83        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
84                            signAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed");
85        return ret;
86    }
87
88    /* calculate signature value */
89    bool result = !(hashCtx = EVP_MD_CTX_new())                                          ||
90                  (EVP_DigestSignInit(hashCtx, &privateKeyCtx, hash, NULL, m_keyPair) <= 0) ||
91                  (EVP_DigestSignUpdate(hashCtx, data.data(), data.size()) <= 0)         ||
92                  (EVP_DigestSignFinal(hashCtx, NULL, &sigLen) <= 0)                     ||
93                  !(sigResult = reinterpret_cast<unsigned char*>(OPENSSL_malloc(sigLen)))  ||
94                  (EVP_DigestSignFinal(hashCtx, sigResult, &sigLen) <= 0);
95    if (result) {
96        PrintErrorNumberMsg("SIGN_ERROR", SIGN_ERROR, "compute signature value failed");
97        goto err;
98    }
99    ret.assign(reinterpret_cast<const char*>(sigResult), sigLen);
100err:
101    OPENSSL_free(sigResult);
102    EVP_MD_CTX_free(hashCtx);
103    return ret;
104}
105} // namespace SignatureTools
106} // namespace OHOS