1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Utility                                                             */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "tx_api.h"
29 #include "nx_api.h"
30 
31 /* Define the base64 letters.  */
32 static CHAR _nx_utility_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _nx_utility_string_length_check                     PORTABLE C      */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Yuxin Zhou, Microsoft Corporation                                   */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function traverses the string and returns the string length,   */
47 /*    if the string is invalid or the string length is bigger than max    */
48 /*    string length, returns error.                                       */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    input_string                          Pointer to input string       */
53 /*    string_length                         Pointer to string length      */
54 /*    max_string_length                     Max string length             */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    status                                Completion status             */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    None                                                                */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    Application Code                                                    */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
73 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
_nx_utility_string_length_check(CHAR * input_string,UINT * string_length,UINT max_string_length)77 UINT  _nx_utility_string_length_check(CHAR *input_string, UINT *string_length, UINT max_string_length)
78 {
79 
80 UINT    i;
81 
82 
83     /* Check for invalid input pointers.  */
84     if (input_string == NX_NULL)
85     {
86         return(NX_PTR_ERROR);
87     }
88 
89     /* Traverse the string.  */
90     for (i = 0; input_string[i]; i++)
91     {
92 
93         /* Check if the string length is bigger than the max string length.  */
94         if (i >= max_string_length)
95         {
96             return(NX_SIZE_ERROR);
97         }
98     }
99 
100     /* Return the string length if string_length is not NULL.
101        String_length being NULL indicates the caller needs to check for string
102        length within the max_string_length. */
103     if (string_length)
104     {
105         *string_length = i;
106     }
107 
108     /* Return success.  */
109     return(NX_SUCCESS);
110 }
111 
112 /**************************************************************************/
113 /*                                                                        */
114 /*  FUNCTION                                               RELEASE        */
115 /*                                                                        */
116 /*    _nx_utility_string_to_uint                          PORTABLE C      */
117 /*                                                           6.1.3        */
118 /*  AUTHOR                                                                */
119 /*                                                                        */
120 /*    Yuxin Zhou, Microsoft Corporation                                   */
121 /*                                                                        */
122 /*  DESCRIPTION                                                           */
123 /*                                                                        */
124 /*    This function converts the string to unsigned integer.              */
125 /*                                                                        */
126 /*  INPUT                                                                 */
127 /*                                                                        */
128 /*    input_string                          Pointer to input string       */
129 /*    string_length                         Length of input string        */
130 /*    number                                Pointer to the number         */
131 /*                                                                        */
132 /*  OUTPUT                                                                */
133 /*                                                                        */
134 /*    status                                Completion status             */
135 /*                                                                        */
136 /*  CALLS                                                                 */
137 /*                                                                        */
138 /*    None                                                                */
139 /*                                                                        */
140 /*  CALLED BY                                                             */
141 /*                                                                        */
142 /*    Application Code                                                    */
143 /*                                                                        */
144 /*  RELEASE HISTORY                                                       */
145 /*                                                                        */
146 /*    DATE              NAME                      DESCRIPTION             */
147 /*                                                                        */
148 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
149 /*                                                                        */
150 /**************************************************************************/
_nx_utility_string_to_uint(CHAR * input_string,UINT string_length,UINT * number)151 UINT  _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number)
152 {
153 
154 UINT i;
155 
156 
157     /* Check for invalid input pointers.  */
158     if ((input_string == NX_NULL) || (number == NX_NULL))
159     {
160         return(NX_PTR_ERROR);
161     }
162 
163     /* Check string length.  */
164     if (string_length == 0)
165     {
166         return(NX_SIZE_ERROR);
167     }
168 
169     /* Initialize.  */
170     i = 0;
171     *number = 0;
172 
173     /* Traverse the string.  */
174     while (i < string_length)
175     {
176 
177         /* Is a numeric character present?  */
178         if ((input_string[i] >= '0') && (input_string[i] <= '9'))
179         {
180 
181             /* Check overflow. Max Value: Hex:0xFFFFFFFF, Decimal: 4294967295.  */
182             if (((*number == 429496729) && (input_string[i] > '5')) ||
183                 (*number >= 429496730))
184             {
185                 return(NX_OVERFLOW);
186             }
187 
188             /* Yes, numeric character is present. Update the number.  */
189             *number =  (*number * 10) + (UINT) (input_string[i] - '0');
190         }
191         else
192         {
193             return(NX_INVALID_PARAMETERS);
194         }
195 
196         i++;
197     }
198 
199     /* Return success.  */
200     return(NX_SUCCESS);
201 }
202 
203 /**************************************************************************/
204 /*                                                                        */
205 /*  FUNCTION                                               RELEASE        */
206 /*                                                                        */
207 /*    _nx_utility_uint_to_string                          PORTABLE C      */
208 /*                                                           6.1.9        */
209 /*  AUTHOR                                                                */
210 /*                                                                        */
211 /*    Yuxin Zhou, Microsoft Corporation                                   */
212 /*                                                                        */
213 /*  DESCRIPTION                                                           */
214 /*                                                                        */
215 /*    This function converts the unsigned integer to string.              */
216 /*                                                                        */
217 /*  INPUT                                                                 */
218 /*                                                                        */
219 /*    number                                Input number                  */
220 /*    base                                  Base of the conversion        */
221 /*                                           8 for OCT                    */
222 /*                                           10 for DEC                   */
223 /*                                           16 for HEX                   */
224 /*    string_buffer                         Pointer to string buffer      */
225 /*    string_buffer_size                    Size of string buffer         */
226 /*                                                                        */
227 /*  OUTPUT                                                                */
228 /*                                                                        */
229 /*    size                                  The size of output string     */
230 /*                                                                        */
231 /*  CALLS                                                                 */
232 /*                                                                        */
233 /*    None                                                                */
234 /*                                                                        */
235 /*  CALLED BY                                                             */
236 /*                                                                        */
237 /*    Application Code                                                    */
238 /*                                                                        */
239 /*  RELEASE HISTORY                                                       */
240 /*                                                                        */
241 /*    DATE              NAME                      DESCRIPTION             */
242 /*                                                                        */
243 /*  08-02-2021     Yuxin Zhou               Initial Version 6.1.8         */
244 /*  10-15-2021     Yuxin Zhou               Modified comment(s),          */
245 /*                                            checked invalid input value,*/
246 /*                                            resulting in version 6.1.9  */
247 /*                                                                        */
248 /**************************************************************************/
_nx_utility_uint_to_string(UINT number,UINT base,CHAR * string_buffer,UINT string_buffer_size)249 UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size)
250 {
251 UINT i;
252 UINT digit;
253 UINT size;
254 
255     /* Check for invalid input pointers.  */
256     if ((string_buffer == NX_NULL) || (string_buffer_size == 0) || (base == 0))
257     {
258         return(0);
259     }
260 
261     /* Initialize.  */
262     i = 0;
263     size = 0;
264 
265     /* Loop to convert the number to ASCII. Minus 1 to put NULL terminal.  */
266     while (size < string_buffer_size - 1)
267     {
268 
269         /* Shift the current digits over one.  */
270         for (i = size; i != 0; i--)
271         {
272 
273             /* Move each digit over one place.  */
274             string_buffer[i] = string_buffer[i-1];
275         }
276 
277         /* Compute the next decimal digit.  */
278         digit = number % base;
279 
280         /* Update the input number.  */
281         number = number / base;
282 
283         /* Store the new digit in ASCII form.  */
284         if (digit < 10)
285         {
286             string_buffer[0] = (CHAR) (digit + '0');
287         }
288         else
289         {
290             string_buffer[0] = (CHAR) (digit + 'a' - 0xa);
291         }
292 
293         /* Increment the size.  */
294         size++;
295 
296         /* Determine if the number is now zero.  */
297         if (number == 0)
298             break;
299     }
300 
301     /* Determine if there is an overflow error.  */
302     if (number)
303     {
304 
305         /* Error, return bad values to user.  */
306         size = 0;
307     }
308 
309     /* Make the string NULL terminated.  */
310     string_buffer[size] = (CHAR) NX_NULL;
311 
312     /* Return size to caller.  */
313     return(size);
314 }
315 
316 /**************************************************************************/
317 /*                                                                        */
318 /*  FUNCTION                                               RELEASE        */
319 /*                                                                        */
320 /*    _nx_utility_base64_encode                           PORTABLE C      */
321 /*                                                           6.2.0        */
322 /*  AUTHOR                                                                */
323 /*                                                                        */
324 /*    Yuxin Zhou, Microsoft Corporation                                   */
325 /*                                                                        */
326 /*  DESCRIPTION                                                           */
327 /*                                                                        */
328 /*    This function encodes the input string into a base64                */
329 /*    representation.                                                     */
330 /*                                                                        */
331 /*  INPUT                                                                 */
332 /*                                                                        */
333 /*    name                                  Name string                   */
334 /*    name_size                             Size of name                  */
335 /*    base64name                            Encoded base64 name string    */
336 /*    base64name_size                       Size of encoded base64 name   */
337 /*    bytes_copied                          Number of bytes copied        */
338 /*                                                                        */
339 /*  OUTPUT                                                                */
340 /*                                                                        */
341 /*    status                                Completion status             */
342 /*                                                                        */
343 /*  CALLS                                                                 */
344 /*                                                                        */
345 /*    None                                                                */
346 /*                                                                        */
347 /*  CALLED BY                                                             */
348 /*                                                                        */
349 /*    Application Code                                                    */
350 /*                                                                        */
351 /*  RELEASE HISTORY                                                       */
352 /*                                                                        */
353 /*    DATE              NAME                      DESCRIPTION             */
354 /*                                                                        */
355 /*  04-02-2021     Yuxin Zhou               Initial Version 6.1.6         */
356 /*  10-31-2022     Yuxin Zhou               Modified comment(s),          */
357 /*                                            improved the internal logic,*/
358 /*                                            resulting in version 6.2.0  */
359 /*                                                                        */
360 /**************************************************************************/
_nx_utility_base64_encode(UCHAR * name,UINT name_size,UCHAR * base64name,UINT base64name_size,UINT * bytes_copied)361 UINT _nx_utility_base64_encode(UCHAR *name, UINT name_size, UCHAR *base64name, UINT base64name_size, UINT *bytes_copied)
362 {
363 UINT    pad;
364 UINT    i, j;
365 UINT    step;
366 UINT    input_name_size = name_size;
367 
368 
369     /* Check for invalid input pointers.  */
370     if ((name == NX_NULL) || (base64name == NX_NULL) || (bytes_copied == NX_NULL))
371     {
372         return(NX_PTR_ERROR);
373     }
374 
375     /* Check the size.  */
376     if ((name_size == 0) || (base64name_size == 0))
377     {
378         return(NX_SIZE_ERROR);
379     }
380 
381     /* Adjust the length to represent the base64 name.  */
382     name_size = ((name_size * 8) / 6);
383 
384     /* Default padding to none.  */
385     pad = 0;
386 
387     /* Determine if an extra conversion is needed.  */
388     if ((name_size * 6) % 24)
389     {
390 
391         /* Some padding is needed.  */
392 
393         /* Calculate the number of pad characters.  */
394         pad = (name_size * 6) % 24;
395         pad = (24 - pad) / 6;
396         pad = pad - 1;
397 
398         /* Adjust the length to pickup the character fraction.  */
399         name_size++;
400     }
401 
402     /* Check the buffer size.  */
403     if (base64name_size <= (name_size + pad))
404     {
405         return(NX_SIZE_ERROR);
406     }
407 
408     /* Setup index into the base64name.  */
409     j = 0;
410 
411     /* Compute the base64name.  */
412     step = 0;
413     i = 0;
414     while (j < name_size)
415     {
416 
417         /* Determine which step we are in.  */
418         if (step == 0)
419         {
420 
421             /* Use first 6 bits of name character for index.  */
422             base64name[j++] = (UCHAR)_nx_utility_base64_array[((UCHAR)name[i]) >> 2];
423             step++;
424         }
425         else if (step == 1)
426         {
427 
428             /* Use last 2 bits of name character and first 4 bits of next name character for index.  */
429             if ((i + 1) < input_name_size)
430             {
431                 base64name[j++] = (UCHAR)_nx_utility_base64_array[((((UCHAR)name[i]) & 0x3) << 4) | (((UCHAR)name[i + 1]) >> 4)];
432             }
433             else
434             {
435 
436                 /* If no more name character, pad with zero.  */
437                 base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0x3) << 4];
438             }
439             i++;
440             step++;
441         }
442         else if (step == 2)
443         {
444 
445             /* Use last 4 bits of name character and first 2 bits of next name character for index.  */
446             if ((i + 1) < input_name_size)
447             {
448                 base64name[j++] = (UCHAR)_nx_utility_base64_array[((((UCHAR)name[i]) & 0xF) << 2) | (((UCHAR)name[i + 1]) >> 6)];
449             }
450             else
451             {
452 
453                 /* If no more name character, pad with zero.  */
454                 base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0xF) << 2];
455             }
456             i++;
457             step++;
458         }
459         else /* Step 3 */
460         {
461 
462             /* Use last 6 bits of name character for index.  */
463             base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0x3F)];
464             i++;
465             step = 0;
466         }
467     }
468 
469     /* Now add the PAD characters.  */
470     while (pad--)
471     {
472 
473         /* Pad base64name with '=' characters.  */
474         base64name[j++] = '=';
475     }
476 
477     /* Put a NULL character in.  */
478     base64name[j] = NX_NULL;
479     *bytes_copied = j;
480 
481     return(NX_SUCCESS);
482 }
483 
484 /**************************************************************************/
485 /*                                                                        */
486 /*  FUNCTION                                               RELEASE        */
487 /*                                                                        */
488 /*    _nx_utility_base64_decode                           PORTABLE C      */
489 /*                                                           6.1.10       */
490 /*  AUTHOR                                                                */
491 /*                                                                        */
492 /*    Yuxin Zhou, Microsoft Corporation                                   */
493 /*                                                                        */
494 /*  DESCRIPTION                                                           */
495 /*                                                                        */
496 /*    This function decodes the input base64 ASCII string and converts    */
497 /*    it into a standard ASCII representation.                            */
498 /*                                                                        */
499 /*  INPUT                                                                 */
500 /*                                                                        */
501 /*    base64name                            Encoded base64 name string    */
502 /*    base64name_size                       Size of encoded base64 name   */
503 /*    name                                  Name string                   */
504 /*    name_size                             Size of name                  */
505 /*    bytes_copied                          Number of bytes copied        */
506 /*                                                                        */
507 /*  OUTPUT                                                                */
508 /*                                                                        */
509 /*    None                                                                */
510 /*                                                                        */
511 /*  CALLS                                                                 */
512 /*                                                                        */
513 /*    None                                                                */
514 /*                                                                        */
515 /*  CALLED BY                                                             */
516 /*                                                                        */
517 /*    Application Code                                                    */
518 /*                                                                        */
519 /*  RELEASE HISTORY                                                       */
520 /*                                                                        */
521 /*    DATE              NAME                      DESCRIPTION             */
522 /*                                                                        */
523 /*  04-02-2021     Yuxin Zhou               Initial Version 6.1.6         */
524 /*  10-15-2021     Yuxin Zhou               Modified comment(s),          */
525 /*                                            removed useless condition,  */
526 /*                                            resulting in version 6.1.9  */
527 /*  01-31-2022     Yuxin Zhou               Modified comment(s),          */
528 /*                                            fixed the issue of reading  */
529 /*                                            overflow,                   */
530 /*                                            resulting in version 6.1.10 */
531 /*                                                                        */
532 /**************************************************************************/
_nx_utility_base64_decode(UCHAR * base64name,UINT base64name_size,UCHAR * name,UINT name_size,UINT * bytes_copied)533 UINT _nx_utility_base64_decode(UCHAR *base64name, UINT base64name_size, UCHAR *name, UINT name_size, UINT *bytes_copied)
534 {
535 UINT    i, j;
536 UINT    value1, value2;
537 UINT    step;
538 UINT    source_size = base64name_size;
539 
540     /* Check for invalid input pointers.  */
541     if ((base64name == NX_NULL) || (name == NX_NULL) || (bytes_copied == NX_NULL))
542     {
543         return(NX_PTR_ERROR);
544     }
545 
546     /* Check the size.  */
547     if ((base64name_size == 0) || (name_size == 0))
548     {
549         return(NX_SIZE_ERROR);
550     }
551 
552     /* Adjust the length to represent the ASCII name.  */
553     base64name_size = ((base64name_size * 6) / 8);
554 
555     if ((base64name_size) && (base64name[source_size - 1] == '='))
556     {
557         base64name_size--;
558 
559         if ((base64name_size) && (base64name[source_size - 2] == '='))
560         {
561             base64name_size--;
562         }
563     }
564 
565     /* Check the buffer size.  */
566     if (name_size <= base64name_size)
567     {
568         return(NX_SIZE_ERROR);
569     }
570 
571     /* Setup index into the ASCII name.  */
572     j = 0;
573 
574     /* Compute the ASCII name.  */
575     step = 0;
576     i =  0;
577     while ((j < base64name_size) && (base64name[i]) && (base64name[i] != '='))
578     {
579 
580         /* Derive values of the Base64 name.  */
581         if ((base64name[i] >= 'A') && (base64name[i] <= 'Z'))
582             value1 =  (UINT) (base64name[i] - 'A');
583         else if ((base64name[i] >= 'a') && (base64name[i] <= 'z'))
584             value1 =  (UINT) (base64name[i] - 'a') + 26;
585         else if ((base64name[i] >= '0') && (base64name[i] <= '9'))
586             value1 =  (UINT) (base64name[i] - '0') + 52;
587         else if ((base64name[i] == '+') ||
588                  (base64name[i] == '-')) /* Base64 URL.  */
589             value1 =  62;
590         else if ((base64name[i] == '/') ||
591                  (base64name[i] == '_')) /* Base64 URL.  */
592             value1 =  63;
593         else
594             value1 =  0;
595 
596         /* Derive value for the next character.  */
597         if ((base64name[i + 1] >= 'A') && (base64name[i + 1] <= 'Z'))
598             value2 =  (UINT) (base64name[i+1] - 'A');
599         else if ((base64name[i + 1] >= 'a') && (base64name[i + 1] <= 'z'))
600             value2 =  (UINT) (base64name[i+1] - 'a') + 26;
601         else if ((base64name[i + 1] >= '0') && (base64name[i + 1] <= '9'))
602             value2 =  (UINT) (base64name[i+1] - '0') + 52;
603         else if ((base64name[i + 1] == '+') ||
604                  (base64name[i + 1] == '-')) /* Base64 URL.  */
605             value2 =  62;
606         else if ((base64name[i + 1] == '/') ||
607                  (base64name[i + 1] == '_')) /* Base64 URL.  */
608             value2 =  63;
609         else
610             value2 =  0;
611 
612         /* Determine which step we are in.  */
613         if (step == 0)
614         {
615 
616             /* Use first value and first 2 bits of second value.  */
617             name[j++] = (UCHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3));
618             i++;
619             step++;
620         }
621         else if (step == 1)
622         {
623 
624             /* Use last 4 bits of first value and first 4 bits of next value.  */
625             name[j++] = (UCHAR) (((value1 & 0xF) << 4) | (value2 >> 2));
626             i++;
627             step++;
628         }
629         else
630         {
631 
632             /* Use first 2 bits and following 6 bits of next value.  */
633             name[j++] = (UCHAR) (((value1 & 3) << 6) | (value2 & 0x3f));
634             i++;
635             i++;
636             step =  0;
637         }
638     }
639 
640     /* Put a NULL character in.  */
641     name[j] = NX_NULL;
642     *bytes_copied = j;
643 
644     return(NX_SUCCESS);
645 }