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