\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
+ Produce a Null-terminated Ascii string in the output buffer specified by Destination and DestinationSize.\r
+ The Ascii string is produced by converting the data string specified by Source and SourceLength.\r
+\r
+ @param Source Input UINT8 data\r
+ @param SourceLength Number of UINT8 bytes of data\r
+ @param Destination Pointer to output string buffer\r
+ @param DestinationSize Size of ascii buffer. Set to 0 to get the size needed.\r
+ Caller is responsible for passing in buffer of DestinationSize\r
+\r
+ @retval RETURN_SUCCESS When ascii 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_BUFFER_TOO_SMALL If SourceLength is 0 and DestinationSize is <1.\r
+ @retval RETURN_BUFFER_TOO_SMALL If Destination is NULL or DestinationSize is smaller than required buffersize.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+Base64Encode (\r
+ IN CONST UINT8 *Source,\r
+ IN UINTN SourceLength,\r
+ OUT CHAR8 *Destination OPTIONAL,\r
+ IN OUT UINTN *DestinationSize\r
+ )\r
+{\r
+\r
+ UINTN RequiredSize;\r
+ UINTN Left;\r
+\r
+ //\r
+ // Check pointers, and SourceLength is valid\r
+ //\r
+ if ((Source == NULL) || (DestinationSize == NULL)) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Allow for RFC 4648 test vector 1\r
+ //\r
+ if (SourceLength == 0) {\r
+ if (*DestinationSize < 1) {\r
+ *DestinationSize = 1;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+ *DestinationSize = 1;\r
+ *Destination = '\0';\r
+ return RETURN_SUCCESS;\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
+ //\r
+ // 4 ascii per 3 bytes + NULL\r
+ //\r
+ RequiredSize = ((SourceLength + 2) / 3) * 4 + 1;\r
+ if ((Destination == NULL) || *DestinationSize < RequiredSize) {\r
+ *DestinationSize = RequiredSize;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Left = SourceLength;\r
+\r
+ //\r
+ // Encode 24 bits (three bytes) into 4 ascii characters\r
+ //\r
+ while (Left >= 3) {\r
+\r
+ *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2 ];\r
+ *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
+ *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2) + ((Source[2] & 0xc0) >> 6)];\r
+ *Destination++ = EncodingTable[( Source[2] & 0x3f)];\r
+ Left -= 3;\r
+ Source += 3;\r
+ }\r
+\r
+ //\r
+ // Handle the remainder, and add padding '=' characters as necessary.\r
+ //\r
+ switch (Left) {\r
+ case 0:\r
+\r
+ //\r
+ // No bytes Left, done.\r
+ //\r
+ break;\r
+ case 1:\r
+\r
+ //\r
+ // One more data byte, two pad characters\r
+ //\r
+ *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2];\r
+ *Destination++ = EncodingTable[((Source[0] & 0x03) << 4)];\r
+ *Destination++ = '=';\r
+ *Destination++ = '=';\r
+ break;\r
+ case 2:\r
+\r
+ //\r
+ // Two more data bytes, and one pad character\r
+ //\r
+ *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2];\r
+ *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
+ *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2)];\r
+ *Destination++ = '=';\r
+ break;\r
+ }\r
+ //\r
+ // Add terminating NULL\r
+ //\r
+ *Destination = '\0';\r
+ return RETURN_SUCCESS;\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
+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
+ )\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 |= 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
+}\r
+\r
/**\r
Converts an 8-bit value to an 8-bit BCD value.\r
\r