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