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 
21 namespace OHOS {
22 namespace SignatureTools {
23 /**
24 * Create local signer.
25 *
26 * @param keyPair   Private key to sign
27 * @param certificates Cert chain to sign
28 */
LocalSigner(EVP_PKEY* keyPair, STACK_OF(X509)* certificates)29 LocalSigner::LocalSigner(EVP_PKEY* keyPair, STACK_OF(X509)* certificates) :m_keyPair(keyPair),
30 m_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 }
41 LocalSigner::~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 }
52 STACK_OF(X509_CRL)* LocalSigner::GetCrls() const
53 {
54     return NULL;
55 }
56 
57 static X509* X509Dup(const X509* x509)
58 {
59     return X509_dup(const_cast<X509*>(x509));
60 }
61 
62 STACK_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 }
69 std::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);
100 err:
101     OPENSSL_free(sigResult);
102     EVP_MD_CTX_free(hashCtx);
103     return ret;
104 }
105 } // namespace SignatureTools
106 } // namespace OHOS