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