);\r
\r
/**\r
- Convert Base64 ascii string to binary data based on RFC4648.\r
-\r
- Produce Null-terminated binary data in the output buffer specified by Destination and DestinationSize.\r
- The binary data is produced by converting the Base64 ascii string specified by Source and SourceLength.\r
-\r
- @param Source Input ASCII characters\r
- @param SourceLength Number of ASCII characters\r
- @param Destination Pointer to output buffer\r
- @param DestinationSize Caller is responsible for passing in buffer of at least DestinationSize.\r
- Set 0 to get the size needed. Set to bytes stored on return.\r
-\r
- @retval RETURN_SUCCESS When binary buffer is filled in.\r
- @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL.\r
- @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS -(UINTN)Destination ).\r
- @retval RETURN_INVALID_PARAMETER If there is any invalid character in input stream.\r
- @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than required buffer size.\r
-\r
- **/\r
+ Decode Base64 ASCII encoded data to 8-bit binary representation, based on\r
+ RFC4648.\r
+\r
+ Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648.\r
+\r
+ Whitespace is ignored at all positions:\r
+ - 0x09 ('\t') horizontal tab\r
+ - 0x0A ('\n') new line\r
+ - 0x0B ('\v') vertical tab\r
+ - 0x0C ('\f') form feed\r
+ - 0x0D ('\r') carriage return\r
+ - 0x20 (' ') space\r
+\r
+ The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated\r
+ and enforced at the end of the Base64 ASCII encoded data, and only there.\r
+\r
+ Other characters outside of the encoding alphabet cause the function to\r
+ reject the Base64 ASCII encoded data.\r
+\r
+ @param[in] Source Array of CHAR8 elements containing the Base64\r
+ ASCII encoding. May be NULL if SourceSize is\r
+ zero.\r
+\r
+ @param[in] SourceSize Number of CHAR8 elements in Source.\r
+\r
+ @param[out] Destination Array of UINT8 elements receiving the decoded\r
+ 8-bit binary representation. Allocated by the\r
+ caller. May be NULL if DestinationSize is\r
+ zero on input. If NULL, decoding is\r
+ performed, but the 8-bit binary\r
+ representation is not stored. If non-NULL and\r
+ the function returns an error, the contents\r
+ of Destination are indeterminate.\r
+\r
+ @param[in,out] DestinationSize On input, the number of UINT8 elements that\r
+ the caller allocated for Destination. On\r
+ output, if the function returns\r
+ RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL,\r
+ the number of UINT8 elements that are\r
+ required for decoding the Base64 ASCII\r
+ representation. If the function returns a\r
+ value different from both RETURN_SUCCESS and\r
+ RETURN_BUFFER_TOO_SMALL, then DestinationSize\r
+ is indeterminate on output.\r
+\r
+ @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have\r
+ been decoded to on-output DestinationSize\r
+ UINT8 elements at Destination. Note that\r
+ RETURN_SUCCESS covers the case when\r
+ DestinationSize is zero on input, and\r
+ Source decodes to zero bytes (due to\r
+ containing at most ignored whitespace).\r
+\r
+ @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not\r
+ large enough for decoding SourceSize CHAR8\r
+ elements at Source. The required number of\r
+ UINT8 elements has been stored to\r
+ DestinationSize.\r
+\r
+ @retval RETURN_INVALID_PARAMETER DestinationSize is NULL.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is\r
+ not zero on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source +\r
+ SourceSize) would wrap around MAX_ADDRESS.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination +\r
+ DestinationSize) would wrap around\r
+ MAX_ADDRESS, as specified on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL,\r
+ and CHAR8[SourceSize] at Source overlaps\r
+ UINT8[DestinationSize] at Destination, as\r
+ specified on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in\r
+ Source.\r
+**/\r
RETURN_STATUS\r
EFIAPI\r
Base64Decode (\r
- IN CONST CHAR8 *Source,\r
- IN UINTN SourceLength,\r
- OUT UINT8 *Destination OPTIONAL,\r
- IN OUT UINTN *DestinationSize\r
+ IN CONST CHAR8 *Source OPTIONAL,\r
+ IN UINTN SourceSize,\r
+ OUT UINT8 *Destination OPTIONAL,\r
+ IN OUT UINTN *DestinationSize\r
);\r
\r
/**\r
\r
#endif\r
\r
-//\r
-// The basis for Base64 encoding is RFC 4686 https://tools.ietf.org/html/rfc4648\r
-//\r
-// RFC 4686 has a number of MAY and SHOULD cases. This implementation chooses\r
-// the more restrictive versions for security concerns (see RFC 4686 section 3.3).\r
-//\r
-// A invalid character, if encountered during the decode operation, causes the data\r
-// to be rejected. In addition, the '=' padding character is only allowed at the end\r
-// of the Base64 encoded string.\r
-//\r
-#define BAD_V 99\r
-\r
STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
"abcdefghijklmnopqrstuvwxyz"\r
"0123456789+/";\r
\r
-STATIC UINT8 DecodingTable[] = {\r
- //\r
- // Valid characters ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r
- // Also, set '=' as a zero for decoding\r
- // 0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 10\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, 62, BAD_V, BAD_V, BAD_V, 63, // 20\r
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD_V, BAD_V, BAD_V, 0, BAD_V, BAD_V, // 30\r
- BAD_V, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40\r
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 50\r
- BAD_V, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60\r
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 70\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 80\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 90\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // a0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // b0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // c0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // d0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // d0\r
- BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V // f0\r
-};\r
-\r
/**\r
Convert binary data to a Base64 encoded ascii string based on RFC4648.\r
\r
}\r
\r
/**\r
- Convert Base64 ascii string to binary data based on RFC4648.\r
-\r
- Produce Null-terminated binary data in the output buffer specified by Destination and DestinationSize.\r
- The binary data is produced by converting the Base64 ascii string specified by Source and SourceLength.\r
-\r
- @param Source Input ASCII characters\r
- @param SourceLength Number of ASCII characters\r
- @param Destination Pointer to output buffer\r
- @param DestinationSize Caller is responsible for passing in buffer of at least DestinationSize.\r
- Set 0 to get the size needed. Set to bytes stored on return.\r
-\r
- @retval RETURN_SUCCESS When binary buffer is filled in.\r
- @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL.\r
- @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS -(UINTN)Destination ).\r
- @retval RETURN_INVALID_PARAMETER If there is any invalid character in input stream.\r
- @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than required buffer size.\r
- **/\r
+ Decode Base64 ASCII encoded data to 8-bit binary representation, based on\r
+ RFC4648.\r
+\r
+ Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648.\r
+\r
+ Whitespace is ignored at all positions:\r
+ - 0x09 ('\t') horizontal tab\r
+ - 0x0A ('\n') new line\r
+ - 0x0B ('\v') vertical tab\r
+ - 0x0C ('\f') form feed\r
+ - 0x0D ('\r') carriage return\r
+ - 0x20 (' ') space\r
+\r
+ The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated\r
+ and enforced at the end of the Base64 ASCII encoded data, and only there.\r
+\r
+ Other characters outside of the encoding alphabet cause the function to\r
+ reject the Base64 ASCII encoded data.\r
+\r
+ @param[in] Source Array of CHAR8 elements containing the Base64\r
+ ASCII encoding. May be NULL if SourceSize is\r
+ zero.\r
+\r
+ @param[in] SourceSize Number of CHAR8 elements in Source.\r
+\r
+ @param[out] Destination Array of UINT8 elements receiving the decoded\r
+ 8-bit binary representation. Allocated by the\r
+ caller. May be NULL if DestinationSize is\r
+ zero on input. If NULL, decoding is\r
+ performed, but the 8-bit binary\r
+ representation is not stored. If non-NULL and\r
+ the function returns an error, the contents\r
+ of Destination are indeterminate.\r
+\r
+ @param[in,out] DestinationSize On input, the number of UINT8 elements that\r
+ the caller allocated for Destination. On\r
+ output, if the function returns\r
+ RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL,\r
+ the number of UINT8 elements that are\r
+ required for decoding the Base64 ASCII\r
+ representation. If the function returns a\r
+ value different from both RETURN_SUCCESS and\r
+ RETURN_BUFFER_TOO_SMALL, then DestinationSize\r
+ is indeterminate on output.\r
+\r
+ @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have\r
+ been decoded to on-output DestinationSize\r
+ UINT8 elements at Destination. Note that\r
+ RETURN_SUCCESS covers the case when\r
+ DestinationSize is zero on input, and\r
+ Source decodes to zero bytes (due to\r
+ containing at most ignored whitespace).\r
+\r
+ @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not\r
+ large enough for decoding SourceSize CHAR8\r
+ elements at Source. The required number of\r
+ UINT8 elements has been stored to\r
+ DestinationSize.\r
+\r
+ @retval RETURN_INVALID_PARAMETER DestinationSize is NULL.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is\r
+ not zero on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source +\r
+ SourceSize) would wrap around MAX_ADDRESS.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination +\r
+ DestinationSize) would wrap around\r
+ MAX_ADDRESS, as specified on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL,\r
+ and CHAR8[SourceSize] at Source overlaps\r
+ UINT8[DestinationSize] at Destination, as\r
+ specified on input.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in\r
+ Source.\r
+**/\r
RETURN_STATUS\r
EFIAPI\r
Base64Decode (\r
- IN CONST CHAR8 *Source,\r
- IN UINTN SourceLength,\r
- OUT UINT8 *Destination OPTIONAL,\r
- IN OUT UINTN *DestinationSize\r
+ IN CONST CHAR8 *Source OPTIONAL,\r
+ IN UINTN SourceSize,\r
+ OUT UINT8 *Destination OPTIONAL,\r
+ IN OUT UINTN *DestinationSize\r
)\r
{\r
-\r
- UINT32 Value;\r
- CHAR8 Chr;\r
- INTN BufferSize;\r
- UINTN SourceIndex;\r
- UINTN DestinationIndex;\r
- UINTN Index;\r
- UINTN ActualSourceLength;\r
-\r
- //\r
- // Check pointers are not NULL\r
- //\r
- if ((Source == NULL) || (DestinationSize == NULL)) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Check if SourceLength or DestinationSize is valid\r
- //\r
- if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))){\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- ActualSourceLength = 0;\r
- BufferSize = 0;\r
-\r
- //\r
- // Determine the actual number of valid characters in the string.\r
- // All invalid characters except selected white space characters,\r
- // will cause the Base64 string to be rejected. White space to allow\r
- // properly formatted XML will be ignored.\r
- //\r
- // See section 3.3 of RFC 4648.\r
- //\r
- for (SourceIndex = 0; SourceIndex < SourceLength; SourceIndex++) {\r
-\r
- //\r
- // '=' is part of the quantum\r
- //\r
- if (Source[SourceIndex] == '=') {\r
- ActualSourceLength++;\r
- BufferSize--;\r
-\r
- //\r
- // Only two '=' characters can be valid.\r
- //\r
- if (BufferSize < -2) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
- }\r
- else {\r
- Chr = Source[SourceIndex];\r
- if (BAD_V != DecodingTable[(UINT8) Chr]) {\r
-\r
- //\r
- // The '=' characters are only valid at the end, so any\r
- // valid character after an '=', will be flagged as an error.\r
- //\r
- if (BufferSize < 0) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
- ActualSourceLength++;\r
- }\r
- else {\r
-\r
- //\r
- // The reset of the decoder will ignore all invalid characters allowed here.\r
- // Ignoring selected white space is useful. In this case, the decoder will\r
- // ignore ' ', '\t', '\n', and '\r'.\r
- //\r
- if ((Chr != ' ') &&(Chr != '\t') &&(Chr != '\n') &&(Chr != '\r')) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
- }\r
- }\r
- }\r
-\r
- //\r
- // The Base64 character string must be a multiple of 4 character quantums.\r
- //\r
- if (ActualSourceLength % 4 != 0) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- BufferSize += ActualSourceLength / 4 * 3;\r
- if (BufferSize < 0) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // BufferSize is >= 0\r
- //\r
- if ((Destination == NULL) || (*DestinationSize < (UINTN) BufferSize)) {\r
- *DestinationSize = BufferSize;\r
- return RETURN_BUFFER_TOO_SMALL;\r
- }\r
-\r
- //\r
- // If no decodable characters, return a size of zero. RFC 4686 test vector 1.\r
- //\r
- if (ActualSourceLength == 0) {\r
- *DestinationSize = 0;\r
- return RETURN_SUCCESS;\r
- }\r
-\r
- //\r
- // Input data is verified to be a multiple of 4 valid charcters. Process four\r
- // characters at a time. Uncounted (ie. invalid) characters will be ignored.\r
- //\r
- for (SourceIndex = 0, DestinationIndex = 0; (SourceIndex < SourceLength) && (DestinationIndex < *DestinationSize); ) {\r
- Value = 0;\r
-\r
- //\r
- // Get 24 bits of data from 4 input characters, each character representing 6 bits\r
- //\r
- for (Index = 0; Index < 4; Index++) {\r
- do {\r
- Chr = DecodingTable[(UINT8) Source[SourceIndex++]];\r
- } while (Chr == BAD_V);\r
- Value <<= 6;\r
- Value |= (UINT32)Chr;\r
- }\r
-\r
- //\r
- // Store 3 bytes of binary data (24 bits)\r
- //\r
- *Destination++ = (UINT8) (Value >> 16);\r
- DestinationIndex++;\r
-\r
- //\r
- // Due to the '=' special cases for the two bytes at the end,\r
- // we have to check the length and not store the padding data\r
- //\r
- if (DestinationIndex++ < *DestinationSize) {\r
- *Destination++ = (UINT8) (Value >> 8);\r
- }\r
- if (DestinationIndex++ < *DestinationSize) {\r
- *Destination++ = (UINT8) Value;\r
- }\r
- }\r
-\r
- return RETURN_SUCCESS;\r
+ ASSERT (FALSE);\r
+ return RETURN_INVALID_PARAMETER;\r
}\r
\r
/**\r