xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/infineon/bcmdhd/bcmstdlib_s.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Broadcom Secure Standard Library.
3  *
4  * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5  *
6  * Copyright (C) 1999-2017, Broadcom Corporation
7  *
8  *      Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  *
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions of
18  * the license of that module.  An independent module is a module which is not
19  * derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  *
22  *      Notwithstanding the above, under no circumstances may you combine this
23  * software in any way with any other Broadcom software provided under a license
24  * other than the GPL, without Broadcom's express prior written consent.
25  *
26  *
27  * <<Broadcom-WL-IPTag/Open:>>
28  *
29  * $Id $
30  */
31 
32 #include <bcm_cfg.h>
33 #include <typedefs.h>
34 #include <bcmdefs.h>
35 #ifdef BCMDRIVER
36 #include <osl.h>
37 #else /* BCMDRIVER */
38 #include <stddef.h>
39 #include <string.h>
40 #endif /* else BCMDRIVER */
41 
42 #include <bcmstdlib_s.h>
43 #include <bcmutils.h>
44 
45 /*
46  * __SIZE_MAX__ value is depending on platform:
47  * Firmware Dongle: RAMSIZE (Dongle Specific Limit).
48  * LINUX NIC/Windows/MACOSX/Application: OS Native or
49  * 0xFFFFFFFFu if not defined.
50  */
51 #ifndef SIZE_MAX
52 #ifndef __SIZE_MAX__
53 #define __SIZE_MAX__ 0xFFFFFFFFu
54 #endif /* __SIZE_MAX__ */
55 #define SIZE_MAX __SIZE_MAX__
56 #endif /* SIZE_MAX */
57 #define RSIZE_MAX (SIZE_MAX >> 1u)
58 
59 #if !defined(__STDC_WANT_SECURE_LIB__) && !(defined(__STDC_LIB_EXT1__) && \
60 	defined(__STDC_WANT_LIB_EXT1__))
61 /*
62  * memmove_s - secure memmove
63  * dest : pointer to the object to copy to
64  * destsz : size of the destination buffer
65  * src : pointer to the object to copy from
66  * n : number of bytes to copy
67  * Return Value : zero on success and non-zero on error
68  * Also on error, if dest is not a null pointer and destsz not greater
69  * than RSIZE_MAX, writes destsz zero bytes into the dest object.
70  */
71 int
memmove_s(void * dest,size_t destsz,const void * src,size_t n)72 memmove_s(void *dest, size_t destsz, const void *src, size_t n)
73 {
74 	int err = BCME_OK;
75 
76 	if ((!dest) || (((char *)dest + destsz) < (char *)dest)) {
77 		err = BCME_BADARG;
78 		goto exit;
79 	}
80 
81 	if (destsz > RSIZE_MAX) {
82 		err = BCME_BADLEN;
83 		goto exit;
84 	}
85 
86 	if (destsz < n) {
87 		memset(dest, 0, destsz);
88 		err = BCME_BADLEN;
89 		goto exit;
90 	}
91 
92 	if ((!src) || (((const char *)src + n) < (const char *)src)) {
93 		memset(dest, 0, destsz);
94 		err = BCME_BADARG;
95 		goto exit;
96 	}
97 
98 	memmove(dest, src, n);
99 exit:
100 	return err;
101 }
102 
103 /*
104  * memcpy_s - secure memcpy
105  * dest : pointer to the object to copy to
106  * destsz : size of the destination buffer
107  * src : pointer to the object to copy from
108  * n : number of bytes to copy
109  * Return Value : zero on success and non-zero on error
110  * Also on error, if dest is not a null pointer and destsz not greater
111  * than RSIZE_MAX, writes destsz zero bytes into the dest object.
112  */
113 int
memcpy_s(void * dest,size_t destsz,const void * src,size_t n)114 memcpy_s(void *dest, size_t destsz, const void *src, size_t n)
115 {
116 	int err = BCME_OK;
117 	char *d = dest;
118 	const char *s = src;
119 
120 	if ((!d) || ((d + destsz) < d)) {
121 		err = BCME_BADARG;
122 		goto exit;
123 	}
124 
125 	if (destsz > RSIZE_MAX) {
126 		err = BCME_BADLEN;
127 		goto exit;
128 	}
129 
130 	if (destsz < n) {
131 		memset(dest, 0, destsz);
132 		err = BCME_BADLEN;
133 		goto exit;
134 	}
135 
136 	if ((!s) || ((s + n) < s)) {
137 		memset(dest, 0, destsz);
138 		err = BCME_BADARG;
139 		goto exit;
140 	}
141 
142 	/* overlap checking between dest and src */
143 	if (!(((d + destsz) <= s) || (d >= (s + n)))) {
144 		memset(dest, 0, destsz);
145 		err = BCME_BADARG;
146 		goto exit;
147 	}
148 
149 	(void)memcpy(dest, src, n);
150 exit:
151 	return err;
152 }
153 
154 /*
155  * memset_s - secure memset
156  * dest : pointer to the object to be set
157  * destsz : size of the destination buffer
158  * c : byte value
159  * n : number of bytes to be set
160  * Return Value : zero on success and non-zero on error
161  * Also on error, if dest is not a null pointer and destsz not greater
162  * than RSIZE_MAX, writes destsz bytes with value c into the dest object.
163  */
164 int
memset_s(void * dest,size_t destsz,int c,size_t n)165 memset_s(void *dest, size_t destsz, int c, size_t n)
166 {
167 	int err = BCME_OK;
168 	if ((!dest) || (((char *)dest + destsz) < (char *)dest)) {
169 		err = BCME_BADARG;
170 		goto exit;
171 	}
172 
173 	if (destsz > RSIZE_MAX) {
174 		err = BCME_BADLEN;
175 		goto exit;
176 	}
177 
178 	if (destsz < n) {
179 		(void)memset(dest, c, destsz);
180 		err = BCME_BADLEN;
181 		goto exit;
182 	}
183 
184 	(void)memset(dest, c, n);
185 exit:
186 	return err;
187 }
188 #endif /* !__STDC_WANT_SECURE_LIB__ && !(__STDC_LIB_EXT1__ && __STDC_WANT_LIB_EXT1__) */
189 
190 #if !defined(FREEBSD) && !defined(BCM_USE_PLATFORM_STRLCPY)
191 /**
192  * strlcpy - Copy a %NUL terminated string into a sized buffer
193  * @dest: Where to copy the string to
194  * @src: Where to copy the string from
195  * @size: size of destination buffer 0 if input parameters are NOK
196  * return: string leng of src (assume src is NUL terminated)
197  *
198  * Compatible with *BSD: the result is always a valid
199  * NUL-terminated string that fits in the buffer (unless,
200  * of course, the buffer size is zero). It does not pad
201  * out the result like strncpy() does.
202  */
strlcpy(char * dest,const char * src,size_t size)203 size_t strlcpy(char *dest, const char *src, size_t size)
204 {
205 	const char *s = src;
206 	size_t n;
207 
208 	if (dest == NULL) {
209 		return 0;
210 	}
211 
212 	/* terminate dest if src is NULL and return 0 as only NULL was added */
213 	if (s == NULL) {
214 		*dest = '\0';
215 		return 0;
216 	}
217 
218 	/* allows us to handle size 0 */
219 	if (size == 0) {
220 		n = 0;
221 	} else {
222 		n = size - 1u;
223 	}
224 
225 	/* perform copy */
226 	while (*s && n != 0) {
227 		*dest++ = *s++;
228 		n--;
229 	}
230 
231 	*dest = '\0';
232 
233 	/* count to end of s or compensate for NULL */
234 	if (n == 0) {
235 		while (*s++)
236 			;
237 	} else {
238 		s++;
239 	}
240 
241 	/* return bytes copied not accounting NUL */
242 	return (s - src - 1u);
243 }
244 #endif // endif
245 
246 /**
247  * strlcat_s - Concatenate a %NUL terminated string with a sized buffer
248  * @dest: Where to concatenate the string to
249  * @src: Where to copy the string from
250  * @size: size of destination buffer
251  * return: string length of created string (i.e. the initial length of dest plus the length of src)
252  *         not including the NUL char, up until size
253  *
254  * Unlike strncat(), strlcat() take the full size of the buffer (not just the number of bytes to
255  * copy) and guarantee to NUL-terminate the result (even when there's nothing to concat).
256  * If the length of dest string concatinated with the src string >= size, truncation occurs.
257  *
258  * Compatible with *BSD: the result is always a valid NUL-terminated string that fits in the buffer
259  * (unless, of course, the buffer size is zero).
260  *
261  * If either src or dest is not NUL-terminated, dest[size-1] will be set to NUL.
262  * If size < strlen(dest) + strlen(src), dest[size-1] will be set to NUL.
263  * If size == 0, dest[0] will be set to NUL.
264  */
265 size_t
strlcat_s(char * dest,const char * src,size_t size)266 strlcat_s(char *dest, const char *src, size_t size)
267 {
268 	char *d = dest;
269 	const char *s = src;	/* point to the start of the src string */
270 	size_t n = size;
271 	size_t dlen;
272 	size_t bytes_to_copy = 0;
273 
274 	if (dest == NULL) {
275 		return 0;
276 	}
277 
278 	/* set d to point to the end of dest string (up to size) */
279 	while (n != 0 && *d != '\0') {
280 		d++;
281 		n--;
282 	}
283 	dlen = (size_t)(d - dest);
284 
285 	if (s != NULL) {
286 		size_t slen = 0;
287 
288 		/* calculate src len in case it's not null-terminated */
289 		n = size;
290 		while (n-- != 0 && *(s + slen) != '\0') {
291 			++slen;
292 		}
293 
294 		n = size - dlen;	/* maximum num of chars to copy */
295 		if (n != 0) {
296 			/* copy relevant chars (until end of src buf or given size is reached) */
297 			bytes_to_copy = MIN(slen - (size_t)(s - src), n - 1);
298 			(void)memcpy(d, s, bytes_to_copy);
299 			d += bytes_to_copy;
300 		}
301 	}
302 	if (n == 0 && dlen != 0) {
303 		--d;	/* nothing to copy, but NUL-terminate dest anyway */
304 	}
305 	*d = '\0';	/* NUL-terminate dest */
306 
307 	return (dlen + bytes_to_copy);
308 }
309