1 /*
2  * Copyright (C) 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 "../include/wifi_openssl_utils.h"
17 #include <openssl/evp.h>
18 #include <openssl/rand.h>
19 #include "common.h"
20 #include "log.h"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "WifiOpensslUtils"
24 
25 namespace OHOS {
26 namespace Wifi {
27 
28 #define AES_GCM_128 2
29 #define AES_GCM_256 3
30 #define AES_GCM_TAG_LEN 4
31 
GetInstance()32 WifiOpensslUtils &WifiOpensslUtils::GetInstance()
33 {
34     static WifiOpensslUtils gWifiOpensslUtils;
35     return gWifiOpensslUtils;
36 }
37 
WifiOpensslUtils()38 WifiOpensslUtils::WifiOpensslUtils()
39 {
40     LOGI("%{public}s create success", __func__);
41 }
42 
~WifiOpensslUtils()43 WifiOpensslUtils::~WifiOpensslUtils()
44 {
45     LOGI("%{public}s destory success", __func__);
46 }
47 
GetAesCipher(int aesType)48 EVP_CIPHER *GetAesCipher(int aesType)
49 {
50     EVP_CIPHER *cipher = nullptr;
51     LOGD("%{public}s aesType %{public}d !", __func__, aesType);
52     switch (aesType) {
53         case AES_GCM_128 :
54             cipher = const_cast<EVP_CIPHER *>(EVP_aes_128_gcm());
55             break;
56         case AES_GCM_256 :
57             cipher = const_cast<EVP_CIPHER *>(EVP_aes_256_gcm());
58             break;
59         default:
60             cipher = const_cast<EVP_CIPHER *>(EVP_aes_128_gcm());
61     }
62     return cipher;
63 }
64 
OpensslAesEncrypt(const uint8_t * plainText,int plainTextLen,struct AesCipherInfo * info,uint8_t * cipherText,int * cipherTextLen)65 int WifiOpensslUtils::OpensslAesEncrypt(const uint8_t *plainText, int plainTextLen,
66     struct AesCipherInfo *info, uint8_t *cipherText, int *cipherTextLen)
67 {
68     LOGI("enter %{public}s", __func__);
69     int res = -1;
70     if (plainText == nullptr || plainTextLen == 0 || info == nullptr ||
71         cipherText == nullptr || cipherTextLen == nullptr) {
72         LOGE("%{public}s param is illegal", __func__);
73         return res;
74     }
75 
76     EVP_CIPHER_CTX *ctx = nullptr;
77     int len = 0;
78     const EVP_CIPHER *cipher = GetAesCipher(info->aesType);
79 
80     if ((ctx = EVP_CIPHER_CTX_new()) == nullptr) {
81         goto err;
82     }
83 
84     if (EVP_EncryptInit_ex(ctx, cipher, nullptr, nullptr, nullptr) != 1) {
85         goto err;
86     }
87 
88     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_IV_LEN, nullptr) != 1) {
89         goto err;
90     }
91 
92     if (EVP_EncryptInit_ex(ctx, nullptr, nullptr, info->key, info->iv) != 1) {
93         goto err;
94     }
95 
96     if (EVP_EncryptUpdate(ctx, cipherText, &len, plainText, plainTextLen) != 1) {
97         goto err;
98     }
99     *cipherTextLen = len;
100 
101     if (EVP_EncryptFinal_ex(ctx, cipherText + len, &len) != 1) {
102         goto err;
103     }
104     *cipherTextLen += len;
105 
106     uint8_t tag[AES_GCM_TAG_LEN];
107     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GCM_TAG_LEN, static_cast<void *>(tag)) != 1) {
108         goto err;
109     }
110 
111     if (memcpy_s(cipherText + *cipherTextLen, AES_GCM_TAG_LEN, tag, AES_GCM_TAG_LEN) != 0) {
112         LOGE("%{public}s: Aes Encrypt memcpy_s failed !", __func__);
113         goto err;
114     }
115     *cipherTextLen += AES_GCM_TAG_LEN;
116     res = 0;
117 err:
118     if (ctx != nullptr) {
119         LOGE("%{public}s: Aes Encrypt encrypt res %{public}d !", __func__, res);
120         EVP_CIPHER_CTX_free(ctx);
121     }
122     return res;
123 }
124 
OpensslAesDecrypt(const uint8_t * cipherText,int cipherTextLen,struct AesCipherInfo * info,uint8_t * plainText,int * plainTextLen)125 int WifiOpensslUtils::OpensslAesDecrypt(const uint8_t *cipherText, int cipherTextLen,
126     struct AesCipherInfo *info, uint8_t *plainText, int *plainTextLen)
127 {
128     LOGI("enter %{public}s", __func__);
129     int res = -1;
130     if (cipherText == nullptr || cipherTextLen == 0 || info == nullptr ||
131         cipherTextLen <= AES_GCM_TAG_LEN) {
132         LOGE("%{public}s param is illegal", __func__);
133         return res;
134     }
135 
136     EVP_CIPHER_CTX *ctx = nullptr;
137     int len = 0;
138     const EVP_CIPHER *cipher = GetAesCipher(info->aesType);
139 
140     if ((ctx = EVP_CIPHER_CTX_new()) == nullptr) {
141         LOGI("%{public}s: Aes decrypt new ctx fail!", __func__);
142         goto err;
143     }
144 
145     if (EVP_DecryptInit_ex(ctx, cipher, nullptr, nullptr, nullptr) != 1) {
146         LOGI("%{public}s: Aes decrypt init fail!", __func__);
147         goto err;
148     }
149 
150     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_IV_LEN, nullptr) != 1) {
151         LOGI("%{public}s: Aes decrypt set iv len fail!", __func__);
152         goto err;
153     }
154 
155     if (EVP_DecryptInit_ex(ctx, nullptr, nullptr, info->key, info->iv) != 1) {
156         LOGI("%{public}s: Aes decrypt set key & iv fail!", __func__);
157         goto err;
158     }
159 
160     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GCM_TAG_LEN,
161         static_cast<void *>(const_cast<uint8_t *>(cipherText + (cipherTextLen - AES_GCM_TAG_LEN)))) != 1) {
162         LOGI("%{public}s: Aes decrypt tag fail!", __func__);
163         goto err;
164     }
165 
166     if (EVP_DecryptUpdate(ctx, plainText, &len, cipherText, cipherTextLen - AES_GCM_TAG_LEN) != 1) {
167         LOGI("%{public}s: Aes decrypt start decrypt fail!", __func__);
168         goto err;
169     }
170     *plainTextLen = len;
171 
172     if (EVP_DecryptFinal_ex(ctx, plainText + len, &len) != 1) {
173         LOGI("%{public}s: Aes decrypt final fail!", __func__);
174         goto err;
175     }
176     *plainTextLen += len;
177 
178     res = 0;
179 err:
180     if (ctx != nullptr) {
181         EVP_CIPHER_CTX_free(ctx);
182     }
183     return res;
184 }
185 
186 }
187 }
188