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