1a339c2d4Sopenharmony_ci/*
2a339c2d4Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3a339c2d4Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a339c2d4Sopenharmony_ci * you may not use this file except in compliance with the License.
5a339c2d4Sopenharmony_ci * You may obtain a copy of the License at
6a339c2d4Sopenharmony_ci *
7a339c2d4Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a339c2d4Sopenharmony_ci *
9a339c2d4Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a339c2d4Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a339c2d4Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a339c2d4Sopenharmony_ci * See the License for the specific language governing permissions and
13a339c2d4Sopenharmony_ci * limitations under the License.
14a339c2d4Sopenharmony_ci */
15a339c2d4Sopenharmony_ci
16a339c2d4Sopenharmony_ci#include "scrypt.h"
17a339c2d4Sopenharmony_ci#include <openssl/ossl_typ.h>
18a339c2d4Sopenharmony_ci#include <openssl/kdf.h>
19a339c2d4Sopenharmony_ci#include "securec.h"
20a339c2d4Sopenharmony_ci#include <unordered_map>
21a339c2d4Sopenharmony_ci#include "iam_logger.h"
22a339c2d4Sopenharmony_ci
23a339c2d4Sopenharmony_ci#define LOG_TAG "PIN_AUTH_SDK"
24a339c2d4Sopenharmony_ci
25a339c2d4Sopenharmony_cinamespace OHOS {
26a339c2d4Sopenharmony_cinamespace UserIam {
27a339c2d4Sopenharmony_cinamespace PinAuth {
28a339c2d4Sopenharmony_cinamespace {
29a339c2d4Sopenharmony_ciconstexpr uint32_t OUT_LENGTH = 64;
30a339c2d4Sopenharmony_ciconstexpr uint32_t SCRYPT_N_V0 = 32768;
31a339c2d4Sopenharmony_ciconstexpr uint32_t SCRYPT_N_V1 = 2048;
32a339c2d4Sopenharmony_ciconstexpr uint32_t SCRYPT_R = 8;
33a339c2d4Sopenharmony_ciconstexpr uint32_t SCRYPT_P = 1;
34a339c2d4Sopenharmony_ciconstexpr uint32_t SCRYPT_P_V3 = 2;
35a339c2d4Sopenharmony_ci
36a339c2d4Sopenharmony_cistruct ScryptParameters {
37a339c2d4Sopenharmony_ci    int32_t scryptN;
38a339c2d4Sopenharmony_ci    int32_t scryptR;
39a339c2d4Sopenharmony_ci    int32_t scryptP;
40a339c2d4Sopenharmony_ci};
41a339c2d4Sopenharmony_ci
42a339c2d4Sopenharmony_cistd::unordered_map<uint32_t, ScryptParameters> g_version2Param_ = {
43a339c2d4Sopenharmony_ci    { PIN_ALGO_VERSION_V0, { SCRYPT_N_V0, SCRYPT_R, SCRYPT_P } },
44a339c2d4Sopenharmony_ci    { PIN_ALGO_VERSION_V1, { SCRYPT_N_V1, SCRYPT_R, SCRYPT_P } },
45a339c2d4Sopenharmony_ci    { PIN_ALGO_VERSION_V2, { SCRYPT_N_V1, SCRYPT_R, SCRYPT_P } },
46a339c2d4Sopenharmony_ci    { PIN_ALGO_VERSION_V3, { SCRYPT_N_V1, SCRYPT_R, SCRYPT_P_V3 } }
47a339c2d4Sopenharmony_ci};
48a339c2d4Sopenharmony_ci}
49a339c2d4Sopenharmony_ci
50a339c2d4Sopenharmony_cibool Scrypt::DoScrypt(const std::vector<uint8_t> &data, uint32_t algoVersion, EVP_PKEY_CTX *pctx)
51a339c2d4Sopenharmony_ci{
52a339c2d4Sopenharmony_ci    auto index = g_version2Param_.find(algoVersion);
53a339c2d4Sopenharmony_ci    if (index == g_version2Param_.end()) {
54a339c2d4Sopenharmony_ci        IAM_LOGE("version is not in g_version2Param_");
55a339c2d4Sopenharmony_ci        return false;
56a339c2d4Sopenharmony_ci    }
57a339c2d4Sopenharmony_ci    ScryptParameters scryptParameters = index->second;
58a339c2d4Sopenharmony_ci    if (EVP_PKEY_CTX_set1_pbe_pass(pctx, reinterpret_cast<const char *>(data.data()), data.size()) <= 0) {
59a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_CTX_set1_pbe_pass fail");
60a339c2d4Sopenharmony_ci        return false;
61a339c2d4Sopenharmony_ci    }
62a339c2d4Sopenharmony_ci    if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, algoParameter_.data(), algoParameter_.size()) <= 0) {
63a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_CTX_set1_scrypt_salt fail");
64a339c2d4Sopenharmony_ci        return false;
65a339c2d4Sopenharmony_ci    }
66a339c2d4Sopenharmony_ci    if (EVP_PKEY_CTX_set_scrypt_N(pctx, scryptParameters.scryptN) <= 0) {
67a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_CTX_set_scrypt_N fail");
68a339c2d4Sopenharmony_ci        return false;
69a339c2d4Sopenharmony_ci    }
70a339c2d4Sopenharmony_ci    if (EVP_PKEY_CTX_set_scrypt_r(pctx, scryptParameters.scryptR) <= 0) {
71a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_CTX_set_scrypt_r fail");
72a339c2d4Sopenharmony_ci        return false;
73a339c2d4Sopenharmony_ci    }
74a339c2d4Sopenharmony_ci    if (EVP_PKEY_CTX_set_scrypt_p(pctx, scryptParameters.scryptP) <= 0) {
75a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_CTX_set_scrypt_p fail");
76a339c2d4Sopenharmony_ci        return false;
77a339c2d4Sopenharmony_ci    }
78a339c2d4Sopenharmony_ci
79a339c2d4Sopenharmony_ci    return true;
80a339c2d4Sopenharmony_ci}
81a339c2d4Sopenharmony_ci
82a339c2d4Sopenharmony_cistd::vector<uint8_t> Scrypt::GetScrypt(const std::vector<uint8_t> &data, uint32_t algoVersion)
83a339c2d4Sopenharmony_ci{
84a339c2d4Sopenharmony_ci    IAM_LOGI("start");
85a339c2d4Sopenharmony_ci    std::vector<uint8_t> out;
86a339c2d4Sopenharmony_ci    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
87a339c2d4Sopenharmony_ci    if (EVP_PKEY_derive_init(pctx) <= 0) {
88a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_derive_init fail");
89a339c2d4Sopenharmony_ci        return out;
90a339c2d4Sopenharmony_ci    }
91a339c2d4Sopenharmony_ci
92a339c2d4Sopenharmony_ci    if (!DoScrypt(data, algoVersion, pctx)) {
93a339c2d4Sopenharmony_ci        IAM_LOGE("DoScrypt fail");
94a339c2d4Sopenharmony_ci        EVP_PKEY_CTX_free(pctx);
95a339c2d4Sopenharmony_ci        return out;
96a339c2d4Sopenharmony_ci    }
97a339c2d4Sopenharmony_ci    out.resize(OUT_LENGTH);
98a339c2d4Sopenharmony_ci    size_t outlen = out.size();
99a339c2d4Sopenharmony_ci    if (EVP_PKEY_derive(pctx, out.data(), &outlen) <= 0) {
100a339c2d4Sopenharmony_ci        IAM_LOGE("EVP_PKEY_derive fail");
101a339c2d4Sopenharmony_ci        EVP_PKEY_CTX_free(pctx);
102a339c2d4Sopenharmony_ci        (void)memset_s(out.data(), out.size(), 0, out.size());
103a339c2d4Sopenharmony_ci        out.clear();
104a339c2d4Sopenharmony_ci        return out;
105a339c2d4Sopenharmony_ci    }
106a339c2d4Sopenharmony_ci
107a339c2d4Sopenharmony_ci    EVP_PKEY_CTX_free(pctx);
108a339c2d4Sopenharmony_ci    return out;
109a339c2d4Sopenharmony_ci}
110a339c2d4Sopenharmony_ci} // namespace PinAuth
111a339c2d4Sopenharmony_ci} // namespace UserIam
112a339c2d4Sopenharmony_ci} // namespace OHOS