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 }