• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "string_util.h"
17 #include <stdbool.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "securec.h"
22 #include "clib_error.h"
23 #include "clib_types.h"
24 
25 #define OUT_OF_HEX 16
26 #define NUMBER_9_IN_DECIMAL 9
27 #define ASCII_CASE_DIFFERENCE_VALUE 32
28 #define DESENSITIZATION_LEN 4
29 
30 static const char * const g_base64CharacterTable =
31     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 
33 static const uint8_t g_base64DecodeTable[] = {
34     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
37     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
38     0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
39     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
40     0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
42 };
43 
HexToChar(uint8_t hex)44 static char HexToChar(uint8_t hex)
45 {
46     return (hex > NUMBER_9_IN_DECIMAL) ? (hex + 0x37) : (hex + 0x30); /* Convert to the corresponding character */
47 }
48 
ByteToHexString(const uint8_t * byte,uint32_t byteLen,char * hexStr,uint32_t hexLen)49 int32_t ByteToHexString(const uint8_t *byte, uint32_t byteLen, char *hexStr, uint32_t hexLen)
50 {
51     if (byte == NULL || hexStr == NULL) {
52         return CLIB_ERR_NULL_PTR;
53     }
54     /* The terminator('\0') needs 1 bit */
55     if (hexLen < byteLen * BYTE_TO_HEX_OPER_LENGTH + 1) {
56         return CLIB_ERR_INVALID_LEN;
57     }
58 
59     for (uint32_t i = 0; i < byteLen; i++) {
60         hexStr[i * BYTE_TO_HEX_OPER_LENGTH] = HexToChar((byte[i] & 0xF0) >> 4); /* 4: shift right for filling */
61         hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1] = HexToChar(byte[i] & 0x0F); /* get low four bits */
62     }
63     hexStr[byteLen * BYTE_TO_HEX_OPER_LENGTH] = '\0';
64 
65     return CLIB_SUCCESS;
66 }
67 
CharToHex(char c)68 static uint8_t CharToHex(char c)
69 {
70     if ((c >= 'A') && (c <= 'F')) {
71         return (c - 'A' + DEC);
72     } else if ((c >= 'a') && (c <= 'f')) {
73         return (c - 'a' + DEC);
74     } else if ((c >= '0') && (c <= '9')) {
75         return (c - '0');
76     } else {
77         return OUT_OF_HEX;
78     }
79 }
80 
HexStringToByte(const char * hexStr,uint8_t * byte,uint32_t byteLen)81 int32_t HexStringToByte(const char *hexStr, uint8_t *byte, uint32_t byteLen)
82 {
83     if (byte == NULL || hexStr == NULL) {
84         return CLIB_ERR_NULL_PTR;
85     }
86     uint32_t realHexLen = strlen(hexStr);
87     /* even number or not */
88     if (realHexLen % BYTE_TO_HEX_OPER_LENGTH != 0 || byteLen < realHexLen / BYTE_TO_HEX_OPER_LENGTH) {
89         return CLIB_ERR_INVALID_LEN;
90     }
91 
92     for (uint32_t i = 0; i < realHexLen / BYTE_TO_HEX_OPER_LENGTH; i++) {
93         uint8_t high = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH]);
94         uint8_t low = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1]);
95         if (high == OUT_OF_HEX || low == OUT_OF_HEX) {
96             return CLIB_ERR_INVALID_PARAM;
97         }
98         byte[i] = high << 4; /* 4: Set the high nibble */
99         byte[i] |= low; /* Set the low nibble */
100     }
101     return CLIB_SUCCESS;
102 }
103 
StringToInt64(const char * cp)104 int64_t StringToInt64(const char *cp)
105 {
106     if (cp == NULL) {
107         return 0;
108     }
109     return strtoll(cp, NULL, DEC);
110 }
111 
ConvertToAnonymousStr(const char * originalStr,char ** anonymousStr)112 void ConvertToAnonymousStr(const char *originalStr, char **anonymousStr)
113 {
114     if ((originalStr == NULL) || (anonymousStr == NULL)) {
115         return;
116     }
117     uint32_t desensitizationLen = DESENSITIZATION_LEN;
118     uint32_t len = strlen(originalStr);
119     if (len <= desensitizationLen) {
120         return;
121     }
122     *anonymousStr = (char *)ClibMalloc(len + 1, 0);
123     if ((*anonymousStr) == NULL) {
124         return;
125     }
126     if (memset_s(*anonymousStr, len + 1, '*', len) != EOK) {
127         ClibFree(*anonymousStr);
128         *anonymousStr = NULL;
129         return;
130     }
131     if (memcpy_s(*anonymousStr, len + 1, originalStr, len - desensitizationLen) != EOK) {
132         ClibFree(*anonymousStr);
133         *anonymousStr = NULL;
134         return;
135     }
136 }
137 
IsInvalidBase64Character(char c)138 static bool IsInvalidBase64Character(char c)
139 {
140     if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
141         return false;
142     }
143     if ('0' <= c && c <= '9') {
144         return false;
145     }
146     if (c == '+' || c == '/') {
147         return false;
148     }
149     return true;
150 }
151 
Base64StringToByte(const char * base64Str,uint8_t * byte,uint32_t * byteLen)152 int32_t Base64StringToByte(const char *base64Str, uint8_t *byte, uint32_t *byteLen)
153 {
154     if (base64Str == NULL || byte == NULL || byteLen == NULL) {
155         return CLIB_ERR_NULL_PTR;
156     }
157     uint32_t strLen = strlen(base64Str);
158     if (strLen < BYTE_TO_BASE64_MULTIPLIER) {
159         return CLIB_ERR_INVALID_LEN;
160     }
161     uint32_t len = strLen / BYTE_TO_BASE64_MULTIPLIER * BYTE_TO_BASE64_DIVISOR;
162     int j = 0;
163     for (int i = 0; i < 2; i++) { // at most two end fillings '='
164         if (base64Str[strLen - 1 - i] == '=') {
165             j++;
166         }
167     }
168     if (len - j > (*byteLen)) {
169         return CLIB_ERR_INVALID_LEN;
170     }
171     *byteLen = len - j;
172 
173     // 6 bits each character(first 2 bits pad 0), 4 characters as a group to decode
174     if (IsInvalidBase64Character(base64Str[0]) || IsInvalidBase64Character(base64Str[1]) ||
175         IsInvalidBase64Character(base64Str[2])) {
176         return CLIB_ERR_INVALID_PARAM;
177     }
178     for (uint32_t i = 0, j = 0; i < strLen - 2; j += 3, i += 4) {
179         if (IsInvalidBase64Character(base64Str[i + 3]) && i + 3 < strLen - j) {
180             return CLIB_ERR_INVALID_PARAM;
181         }
182         /* splice the last 6 bits of the first character's value and the first 2 bits of the second character's value */
183         byte[j] = (g_base64DecodeTable[(int)base64Str[i]] << 2) | (g_base64DecodeTable[(int)base64Str[i + 1]] >> 4);
184         /* splice the last 4 bits of the second character's value and the first 4 bits of the third character's value */
185         byte[j + 1] = (g_base64DecodeTable[(int)base64Str[i + 1]] << 4) |
186             (g_base64DecodeTable[(int)base64Str[i + 2]] >> 2);
187         /* splice the last 2 bits of the third character's value and the first 6 bits of the forth character's value */
188         byte[j + 2] = (g_base64DecodeTable[(int)base64Str[i + 2]] << 6) | (g_base64DecodeTable[(int)base64Str[i + 3]]);
189     }
190     return CLIB_SUCCESS;
191 }
192 
ByteToBase64String(const uint8_t * byte,uint32_t byteLen,char * base64Str,uint32_t strLen)193 int32_t ByteToBase64String(const uint8_t *byte, uint32_t byteLen, char *base64Str, uint32_t strLen)
194 {
195     if (byte == NULL || base64Str == NULL) {
196         return CLIB_ERR_NULL_PTR;
197     }
198     if (byteLen > (UINT32_MAX / BYTE_TO_BASE64_MULTIPLIER - 1) * BYTE_TO_BASE64_DIVISOR) {
199         return CLIB_ERR_INVALID_LEN;
200     }
201     uint32_t len = (byteLen / BYTE_TO_BASE64_DIVISOR + (byteLen % BYTE_TO_BASE64_DIVISOR != 0)) *
202         BYTE_TO_BASE64_MULTIPLIER;
203     if (len + 1 > strLen) {
204         return CLIB_ERR_INVALID_LEN;
205     }
206 
207     uint32_t i;
208     uint32_t j;
209     // 3 bytes as a group to encode
210     for (i = 0, j = 0; i < len - 2; j += 3, i += 4) {
211         /* take the first 6 bits of the first byte to map to base64 character */
212         base64Str[i] = g_base64CharacterTable[byte[j] >> 2];
213         /*
214          * splice the last 2 bits of the first byte and the first 4 bits of the second byte,
215          * and map to base64 character
216          */
217         base64Str[i + 1] = g_base64CharacterTable[((byte[j] & 0x3) << 4) | (byte[j + 1] >> 4)];
218         /*
219          * splice the last 4 bits of the second byte and the first 2 bits of the third byte,
220          * and map to base64 character
221          */
222         base64Str[i + 2] = g_base64CharacterTable[((byte[j + 1] & 0xf) << 2) | (byte[j + 2] >> 6)];
223         /* take the last 6 bits of the third byte to map to base64 character */
224         base64Str[i + 3] = g_base64CharacterTable[byte[j + 2] & 0x3f];
225     }
226 
227     // the lack of position fills '='
228     if (byteLen % 3 == 1) {
229         base64Str[i - 2] = '=';
230         base64Str[i - 1] = '=';
231     } else if (byteLen % 3 == 2) {
232         base64Str[i - 1] = '=';
233     }
234     base64Str[len] = '\0';
235 
236     return CLIB_SUCCESS;
237 }
238 
ToUpperCase(const char * oriStr,char ** desStr)239 int32_t ToUpperCase(const char *oriStr, char **desStr)
240 {
241     if (oriStr == NULL || desStr == NULL) {
242         return CLIB_ERR_NULL_PTR;
243     }
244     uint32_t len = strlen(oriStr);
245     *desStr = ClibMalloc(len + 1, 0);
246     if (*desStr == NULL) {
247         return CLIB_ERR_BAD_ALLOC;
248     }
249     for (uint32_t i = 0; i < len; i++) {
250         if ((oriStr[i] >= 'a') && (oriStr[i] <= 'f')) {
251             (*desStr)[i] = oriStr[i] - ASCII_CASE_DIFFERENCE_VALUE;
252         } else {
253             (*desStr)[i] = oriStr[i];
254         }
255     }
256     return CLIB_SUCCESS;
257 }