From nobody Sat Apr 27 16:07:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+43162+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43162+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562063347; cv=none; d=zoho.com; s=zohoarc; b=oFwBiqU/fZWC0vxW1GhdAE7yT1/cCYf2BGRPDMVpEl+32IUwCWyiwgA2BsZBIDdXhBFSDYBGGNYiPjuDT5B/np3NwHzsIt/sRTEoFh3He/Wkjdu3Sx3MyYEVfY9vDcQVCQb23dpymOW2oVYQZUJDvbzEEcvBvboSeO1oXqO0hf8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562063347; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=ySz34XQlbmcmwRnn3KJYpU+oumZacfBYWegJcu4H/c8=; b=frAPYpEo0LSNyKMKieR55bMqP37jUywl257TNvedH9KNIy6t4mxPbR9Onw3y/zLCV9dsUNzyGNfZmXgoqUcJATagDwE58A0TlDPJMXVj7l5RXQfd4inTmwnkZ6LuX9bQkRnPNtCojCP5lDim0fTcS/JYT1V4wDuqht264DlfINQ= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43162+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1562063347923241.97136246448542; Tue, 2 Jul 2019 03:29:07 -0700 (PDT) Return-Path: X-Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by groups.io with SMTP; Tue, 02 Jul 2019 03:29:07 -0700 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C7C1258E33; Tue, 2 Jul 2019 10:28:50 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-117-172.ams2.redhat.com [10.36.117.172]) by smtp.corp.redhat.com (Postfix) with ESMTP id 260201972C; Tue, 2 Jul 2019 10:28:48 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Liming Gao , =?UTF-8?q?Marvin=20H=C3=A4user?= , Michael D Kinney , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhichao Gao Subject: [edk2-devel] [PATCH 1/3] MdePkg/BaseLib: re-specify Base64Decode(), and add temporary stub impl Date: Tue, 2 Jul 2019 12:28:34 +0200 Message-Id: <20190702102836.27589-2-lersek@redhat.com> In-Reply-To: <20190702102836.27589-1-lersek@redhat.com> References: <20190702102836.27589-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 02 Jul 2019 10:29:06 +0000 (UTC) Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1562063347; bh=ykDJYGSaIUTDxRfI6MHhhWPpn8zlTi2pSBSoW0RpBec=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=jOQUbBfnjHsYfi5qnYQo0oequ09cgkGs6AzPB0revCqdaVc9ann3JD+nwaqVh/gbAhS 4hwPjR5urYlieFuhrueOeen0/rXtOxHhdo4gClSQu6Kd/csJsaG+Zopnp9vG5ziYprAnA v4Y6khq3MYHCrPUSpJtbQ5YhAWPH04MuErQ= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Rewrite Base64Decode() from scratch, due to reasons listed in the second reference below. As first step, redo the interface contract, and replace the current implementation with a stub that asserts FALSE, then fails. Cc: Liming Gao Cc: Marvin H=C3=A4user Cc: Michael D Kinney Cc: Philippe Mathieu-Daud=C3=A9 Cc: Zhichao Gao Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1891 Ref: http://mid.mail-archive.com/c495bd0b-ea4d-7206-8a4f-a7149760d19a@redha= t.com Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daude --- MdePkg/Include/Library/BaseLib.h | 99 +++++-- MdePkg/Library/BaseLib/String.c | 285 ++++++-------------- 2 files changed, 168 insertions(+), 216 deletions(-) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/Base= Lib.h index ebd7dd274cf4..5ef03e24edb1 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -2785,31 +2785,94 @@ Base64Encode ( ); =20 /** - Convert Base64 ascii string to binary data based on RFC4648. + Decode Base64 ASCII encoded data to 8-bit binary representation, based on + RFC4648. =20 - Produce Null-terminated binary data in the output buffer specified by De= stination and DestinationSize. - The binary data is produced by converting the Base64 ascii string specif= ied by Source and SourceLength. + Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648. =20 - @param Source Input ASCII characters - @param SourceLength Number of ASCII characters - @param Destination Pointer to output buffer - @param DestinationSize Caller is responsible for passing in buffer of at= least DestinationSize. - Set 0 to get the size needed. Set to bytes stored= on return. + Whitespace is ignored at all positions: + - 0x09 ('\t') horizontal tab + - 0x0A ('\n') new line + - 0x0B ('\v') vertical tab + - 0x0C ('\f') form feed + - 0x0D ('\r') carriage return + - 0x20 (' ') space =20 - @retval RETURN_SUCCESS When binary buffer is filled in. - @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize = is NULL. - @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is= bigger than (MAX_ADDRESS -(UINTN)Destination ). - @retval RETURN_INVALID_PARAMETER If there is any invalid character in = input stream. - @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than requ= ired buffer size. + The minimum amount of required padding (with ASCII 0x3D, '=3D') is toler= ated + and enforced at the end of the Base64 ASCII encoded data, and only there. =20 - **/ + Other characters outside of the encoding alphabet cause the function to + reject the Base64 ASCII encoded data. + + @param[in] Source Array of CHAR8 elements containing the B= ase64 + ASCII encoding. May be NULL if SourceSiz= e is + zero. + + @param[in] SourceSize Number of CHAR8 elements in Source. + + @param[out] Destination Array of UINT8 elements receiving the de= coded + 8-bit binary representation. Allocated b= y the + caller. May be NULL if DestinationSize is + zero on input. If NULL, decoding is + performed, but the 8-bit binary + representation is not stored. If non-NUL= L and + the function returns an error, the conte= nts + of Destination are indeterminate. + + @param[in,out] DestinationSize On input, the number of UINT8 elements t= hat + the caller allocated for Destination. On + output, if the function returns + RETURN_SUCCESS or RETURN_BUFFER_TOO_SMAL= L, + the number of UINT8 elements that are + required for decoding the Base64 ASCII + representation. If the function returns a + value different from both RETURN_SUCCESS= and + RETURN_BUFFER_TOO_SMALL, then Destinatio= nSize + is indeterminate on output. + + @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source ha= ve + been decoded to on-output DestinationS= ize + UINT8 elements at Destination. Note th= at + RETURN_SUCCESS covers the case when + DestinationSize is zero on input, and + Source decodes to zero bytes (due to + containing at most ignored whitespace). + + @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is = not + large enough for decoding SourceSize C= HAR8 + elements at Source. The required numbe= r of + UINT8 elements has been stored to + DestinationSize. + + @retval RETURN_INVALID_PARAMETER DestinationSize is NULL. + + @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not = zero. + + @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSi= ze is + not zero on input. + + @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source + + SourceSize) would wrap around MAX_ADDR= ESS. + + @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destinat= ion + + DestinationSize) would wrap around + MAX_ADDRESS, as specified on input. + + @retval RETURN_INVALID_PARAMETER None of Source and Destination are NUL= L, + and CHAR8[SourceSize] at Source overla= ps + UINT8[DestinationSize] at Destination,= as + specified on input. + + @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in + Source. +**/ RETURN_STATUS EFIAPI Base64Decode ( - IN CONST CHAR8 *Source, - IN UINTN SourceLength, - OUT UINT8 *Destination OPTIONAL, - IN OUT UINTN *DestinationSize + IN CONST CHAR8 *Source OPTIONAL, + IN UINTN SourceSize, + OUT UINT8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize ); =20 /** diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/Strin= g.c index 32e189791cb8..f8397035c32a 100644 --- a/MdePkg/Library/BaseLib/String.c +++ b/MdePkg/Library/BaseLib/String.c @@ -1757,45 +1757,10 @@ AsciiStrToUnicodeStr ( =20 #endif =20 -// -// The basis for Base64 encoding is RFC 4686 https://tools.ietf.org/html/r= fc4648 -// -// RFC 4686 has a number of MAY and SHOULD cases. This implementation cho= oses -// the more restrictive versions for security concerns (see RFC 4686 secti= on 3.3). -// -// A invalid character, if encountered during the decode operation, causes= the data -// to be rejected. In addition, the '=3D' padding character is only allowe= d at the end -// of the Base64 encoded string. -// -#define BAD_V 99 - STATIC CHAR8 EncodingTable[] =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; =20 -STATIC UINT8 DecodingTable[] =3D { - // - // Valid characters ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz= 0123456789+/ - // Also, set '=3D' as a zero for decoding - // 0 , 1, 2, 3, 4, = 5, 6, 7, 8, 9, a, = b, c, d, e, f - 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 - 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 - 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 - 52, 53, 54, 55, 56, 57, 58, 59, 60, = 61, BAD_V, BAD_V, BAD_V, 0, BAD_V, BAD_V, // 30 - BAD_V, 0, 1, 2, 3, 4, 5, 6, 7, = 8, 9, 10, 11, 12, 13, 14, // 40 - 15, 16, 17, 18, 19, 20, 21, 22, 23, = 24, 25, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 50 - BAD_V, 26, 27, 28, 29, 30, 31, 32, 33, = 34, 35, 36, 37, 38, 39, 40, // 60 - 41, 42, 43, 44, 45, 46, 47, 48, 49, = 50, 51, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 70 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 -}; - /** Convert binary data to a Base64 encoded ascii string based on RFC4648. =20 @@ -1918,174 +1883,98 @@ Base64Encode ( } =20 /** - Convert Base64 ascii string to binary data based on RFC4648. - - Produce Null-terminated binary data in the output buffer specified by De= stination and DestinationSize. - The binary data is produced by converting the Base64 ascii string specif= ied by Source and SourceLength. - - @param Source Input ASCII characters - @param SourceLength Number of ASCII characters - @param Destination Pointer to output buffer - @param DestinationSize Caller is responsible for passing in buffer of = at least DestinationSize. - Set 0 to get the size needed. Set to bytes stor= ed on return. - - @retval RETURN_SUCCESS When binary buffer is filled in. - @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize = is NULL. - @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is= bigger than (MAX_ADDRESS -(UINTN)Destination ). - @retval RETURN_INVALID_PARAMETER If there is any invalid character in = input stream. - @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than requ= ired buffer size. - **/ + Decode Base64 ASCII encoded data to 8-bit binary representation, based on + RFC4648. + + Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648. + + Whitespace is ignored at all positions: + - 0x09 ('\t') horizontal tab + - 0x0A ('\n') new line + - 0x0B ('\v') vertical tab + - 0x0C ('\f') form feed + - 0x0D ('\r') carriage return + - 0x20 (' ') space + + The minimum amount of required padding (with ASCII 0x3D, '=3D') is toler= ated + and enforced at the end of the Base64 ASCII encoded data, and only there. + + Other characters outside of the encoding alphabet cause the function to + reject the Base64 ASCII encoded data. + + @param[in] Source Array of CHAR8 elements containing the B= ase64 + ASCII encoding. May be NULL if SourceSiz= e is + zero. + + @param[in] SourceSize Number of CHAR8 elements in Source. + + @param[out] Destination Array of UINT8 elements receiving the de= coded + 8-bit binary representation. Allocated b= y the + caller. May be NULL if DestinationSize is + zero on input. If NULL, decoding is + performed, but the 8-bit binary + representation is not stored. If non-NUL= L and + the function returns an error, the conte= nts + of Destination are indeterminate. + + @param[in,out] DestinationSize On input, the number of UINT8 elements t= hat + the caller allocated for Destination. On + output, if the function returns + RETURN_SUCCESS or RETURN_BUFFER_TOO_SMAL= L, + the number of UINT8 elements that are + required for decoding the Base64 ASCII + representation. If the function returns a + value different from both RETURN_SUCCESS= and + RETURN_BUFFER_TOO_SMALL, then Destinatio= nSize + is indeterminate on output. + + @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source ha= ve + been decoded to on-output DestinationS= ize + UINT8 elements at Destination. Note th= at + RETURN_SUCCESS covers the case when + DestinationSize is zero on input, and + Source decodes to zero bytes (due to + containing at most ignored whitespace). + + @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is = not + large enough for decoding SourceSize C= HAR8 + elements at Source. The required numbe= r of + UINT8 elements has been stored to + DestinationSize. + + @retval RETURN_INVALID_PARAMETER DestinationSize is NULL. + + @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not = zero. + + @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSi= ze is + not zero on input. + + @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source + + SourceSize) would wrap around MAX_ADDR= ESS. + + @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destinat= ion + + DestinationSize) would wrap around + MAX_ADDRESS, as specified on input. + + @retval RETURN_INVALID_PARAMETER None of Source and Destination are NUL= L, + and CHAR8[SourceSize] at Source overla= ps + UINT8[DestinationSize] at Destination,= as + specified on input. + + @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in + Source. +**/ RETURN_STATUS EFIAPI Base64Decode ( - IN CONST CHAR8 *Source, - IN UINTN SourceLength, - OUT UINT8 *Destination OPTIONAL, - IN OUT UINTN *DestinationSize + IN CONST CHAR8 *Source OPTIONAL, + IN UINTN SourceSize, + OUT UINT8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize ) { - - UINT32 Value; - CHAR8 Chr; - INTN BufferSize; - UINTN SourceIndex; - UINTN DestinationIndex; - UINTN Index; - UINTN ActualSourceLength; - - // - // Check pointers are not NULL - // - if ((Source =3D=3D NULL) || (DestinationSize =3D=3D NULL)) { - return RETURN_INVALID_PARAMETER; - } - - // - // Check if SourceLength or DestinationSize is valid - // - if ((SourceLength >=3D (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSi= ze >=3D (MAX_ADDRESS - (UINTN)Destination))){ - return RETURN_INVALID_PARAMETER; - } - - ActualSourceLength =3D 0; - BufferSize =3D 0; - - // - // Determine the actual number of valid characters in the string. - // All invalid characters except selected white space characters, - // will cause the Base64 string to be rejected. White space to allow - // properly formatted XML will be ignored. - // - // See section 3.3 of RFC 4648. - // - for (SourceIndex =3D 0; SourceIndex < SourceLength; SourceIndex++) { - - // - // '=3D' is part of the quantum - // - if (Source[SourceIndex] =3D=3D '=3D') { - ActualSourceLength++; - BufferSize--; - - // - // Only two '=3D' characters can be valid. - // - if (BufferSize < -2) { - return RETURN_INVALID_PARAMETER; - } - } - else { - Chr =3D Source[SourceIndex]; - if (BAD_V !=3D DecodingTable[(UINT8) Chr]) { - - // - // The '=3D' characters are only valid at the end, so any - // valid character after an '=3D', will be flagged as an error. - // - if (BufferSize < 0) { - return RETURN_INVALID_PARAMETER; - } - ActualSourceLength++; - } - else { - - // - // The reset of the decoder will ignore all invalid characters all= owed here. - // Ignoring selected white space is useful. In this case, the dec= oder will - // ignore ' ', '\t', '\n', and '\r'. - // - if ((Chr !=3D ' ') &&(Chr !=3D '\t') &&(Chr !=3D '\n') &&(Chr !=3D= '\r')) { - return RETURN_INVALID_PARAMETER; - } - } - } - } - - // - // The Base64 character string must be a multiple of 4 character quantum= s. - // - if (ActualSourceLength % 4 !=3D 0) { - return RETURN_INVALID_PARAMETER; - } - - BufferSize +=3D ActualSourceLength / 4 * 3; - if (BufferSize < 0) { - return RETURN_INVALID_PARAMETER; - } - - // - // BufferSize is >=3D 0 - // - if ((Destination =3D=3D NULL) || (*DestinationSize < (UINTN) BufferSize)= ) { - *DestinationSize =3D BufferSize; - return RETURN_BUFFER_TOO_SMALL; - } - - // - // If no decodable characters, return a size of zero. RFC 4686 test vect= or 1. - // - if (ActualSourceLength =3D=3D 0) { - *DestinationSize =3D 0; - return RETURN_SUCCESS; - } - - // - // Input data is verified to be a multiple of 4 valid charcters. Proces= s four - // characters at a time. Uncounted (ie. invalid) characters will be ign= ored. - // - for (SourceIndex =3D 0, DestinationIndex =3D 0; (SourceIndex < SourceLen= gth) && (DestinationIndex < *DestinationSize); ) { - Value =3D 0; - - // - // Get 24 bits of data from 4 input characters, each character represe= nting 6 bits - // - for (Index =3D 0; Index < 4; Index++) { - do { - Chr =3D DecodingTable[(UINT8) Source[SourceIndex++]]; - } while (Chr =3D=3D BAD_V); - Value <<=3D 6; - Value |=3D (UINT32)Chr; - } - - // - // Store 3 bytes of binary data (24 bits) - // - *Destination++ =3D (UINT8) (Value >> 16); - DestinationIndex++; - - // - // Due to the '=3D' special cases for the two bytes at the end, - // we have to check the length and not store the padding data - // - if (DestinationIndex++ < *DestinationSize) { - *Destination++ =3D (UINT8) (Value >> 8); - } - if (DestinationIndex++ < *DestinationSize) { - *Destination++ =3D (UINT8) Value; - } - } - - return RETURN_SUCCESS; + ASSERT (FALSE); + return RETURN_INVALID_PARAMETER; } =20 /** --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#43162): https://edk2.groups.io/g/devel/message/43162 Mute This Topic: https://groups.io/mt/32284615/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sat Apr 27 16:07:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+43161+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43161+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562063347; cv=none; d=zoho.com; s=zohoarc; b=jmXxCtsfgHnhvfcCBPb7eUyKQ0n/dpHPIzJ4DDYARdudhRHnKBelIuxKYBqhVaiS88Q6LCtdtcKM2a6CyRRgcxXwND19VYWalgOD1Vj747Zw5kIBL8IykhaOuiBNMT+aDuGwlSgWAv3M88cRWcjBcs2muRPU1Gwcbpm8D6faQtY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562063347; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=x74DT/s3CJ+/jq3jn1xK5tshjGRrQQp8r+KQDpk/e3Y=; b=IpuVS+YbsIWAwgQ7WX2X4egvoWZXvasCivYf5X1LSnhvzAZ8fuOpZ5DWBe63BKh/BTeU88+ZcKLXvTQ/CY9T89pVLeZc3fkY6OGjs1yGQmopUnZ4rlqYIaztJSy6IelyDfcDhbXo2h2glVx37Wu+L48JEusp0ev6MEoGlG8tzbM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43161+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1562063347527337.7834467434342; Tue, 2 Jul 2019 03:29:07 -0700 (PDT) Return-Path: X-Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by groups.io with SMTP; Tue, 02 Jul 2019 03:29:06 -0700 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7CE2730872ED; Tue, 2 Jul 2019 10:28:55 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-117-172.ams2.redhat.com [10.36.117.172]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2652419730; Tue, 2 Jul 2019 10:28:50 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Liming Gao , =?UTF-8?q?Marvin=20H=C3=A4user?= , Michael D Kinney , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Zhichao Gao Subject: [edk2-devel] [PATCH 2/3] MdePkg/BaseLib: rewrite Base64Decode() Date: Tue, 2 Jul 2019 12:28:35 +0200 Message-Id: <20190702102836.27589-3-lersek@redhat.com> In-Reply-To: <20190702102836.27589-1-lersek@redhat.com> References: <20190702102836.27589-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Tue, 02 Jul 2019 10:29:03 +0000 (UTC) Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1562063346; bh=udN/PYgeArdaw7Lv8Aq2136CyOJHsxhR4lA7w8CYfYk=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=SEUuQ8hnSaVEYvM76XM3xOhS5dpZZOtoBWo5kuAv7hB/2S2hk8sTEcvsS8YPyaYzT6n vu1hZcO/cs+bb4Di2sIRnzWOmhvkoknKl+4bHNNgwKTMTaT9IivJnnitoeMQ7UxtSXUnP rKdm7aAN/2oHUCUtLOOw/7w8+XAZe8eTH3Q= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Rewrite Base64Decode() from scratch, due to reasons listed in the second reference below. Implement Base64Decode() according to the specification added in the previous patch. The decoder scans the input buffer once, it has no inner loop(s), and it spills each output byte as soon as the output byte is complete. Cc: Liming Gao Cc: Marvin H=C3=A4user Cc: Michael D Kinney Cc: Philippe Mathieu-Daud=C3=A9 Cc: Zhichao Gao Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1891 Ref: http://mid.mail-archive.com/c495bd0b-ea4d-7206-8a4f-a7149760d19a@redha= t.com Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daude --- MdePkg/Library/BaseLib/String.c | 249 +++++++++++++++++++- 1 file changed, 247 insertions(+), 2 deletions(-) diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/Strin= g.c index f8397035c32a..6198ccbc9672 100644 --- a/MdePkg/Library/BaseLib/String.c +++ b/MdePkg/Library/BaseLib/String.c @@ -1973,8 +1973,253 @@ Base64Decode ( IN OUT UINTN *DestinationSize ) { - ASSERT (FALSE); - return RETURN_INVALID_PARAMETER; + BOOLEAN PaddingMode; + UINTN SixBitGroupsConsumed; + UINT32 Accumulator; + UINTN OriginalDestinationSize; + UINTN SourceIndex; + + if (DestinationSize =3D=3D NULL) { + return RETURN_INVALID_PARAMETER; + } + + // + // Check Source array validity. + // + if (Source =3D=3D NULL) { + if (SourceSize > 0) { + // + // At least one CHAR8 element at NULL Source. + // + return RETURN_INVALID_PARAMETER; + } + } else if (SourceSize > MAX_ADDRESS - (UINTN)Source) { + // + // Non-NULL Source, but it wraps around. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Check Destination array validity. + // + if (Destination =3D=3D NULL) { + if (*DestinationSize > 0) { + // + // At least one UINT8 element at NULL Destination. + // + return RETURN_INVALID_PARAMETER; + } + } else if (*DestinationSize > MAX_ADDRESS - (UINTN)Destination) { + // + // Non-NULL Destination, but it wraps around. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Check for overlap. + // + if (Source !=3D NULL && Destination !=3D NULL) { + // + // Both arrays have been provided, and we know from earlier that each = array + // is valid in itself. + // + if ((UINTN)Source + SourceSize <=3D (UINTN)Destination) { + // + // Source array precedes Destination array, OK. + // + } else if ((UINTN)Destination + *DestinationSize <=3D (UINTN)Source) { + // + // Destination array precedes Source array, OK. + // + } else { + // + // Overlap. + // + return RETURN_INVALID_PARAMETER; + } + } + + // + // Decoding loop setup. + // + PaddingMode =3D FALSE; + SixBitGroupsConsumed =3D 0; + Accumulator =3D 0; + OriginalDestinationSize =3D *DestinationSize; + *DestinationSize =3D 0; + + // + // Decoding loop. + // + for (SourceIndex =3D 0; SourceIndex < SourceSize; SourceIndex++) { + CHAR8 SourceChar; + UINT32 Base64Value; + UINT8 DestinationOctet; + + SourceChar =3D Source[SourceIndex]; + + // + // Whitespace is ignored at all positions (regardless of padding mode). + // + if (SourceChar =3D=3D '\t' || SourceChar =3D=3D '\n' || SourceChar =3D= =3D '\v' || + SourceChar =3D=3D '\f' || SourceChar =3D=3D '\r' || SourceChar =3D= =3D ' ') { + continue; + } + + // + // If we're in padding mode, accept another padding character, as long= as + // that padding character completes the quantum. This completes case (= 2) + // from RFC4648, Chapter 4. "Base 64 Encoding": + // + // (2) The final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by= two + // "=3D" padding characters. + // + if (PaddingMode) { + if (SourceChar =3D=3D '=3D' && SixBitGroupsConsumed =3D=3D 3) { + SixBitGroupsConsumed =3D 0; + continue; + } + return RETURN_INVALID_PARAMETER; + } + + // + // When not in padding mode, decode Base64Value based on RFC4648, "Tab= le 1: + // The Base 64 Alphabet". + // + if ('A' <=3D SourceChar && SourceChar <=3D 'Z') { + Base64Value =3D SourceChar - 'A'; + } else if ('a' <=3D SourceChar && SourceChar <=3D 'z') { + Base64Value =3D 26 + (SourceChar - 'a'); + } else if ('0' <=3D SourceChar && SourceChar <=3D '9') { + Base64Value =3D 52 + (SourceChar - '0'); + } else if (SourceChar =3D=3D '+') { + Base64Value =3D 62; + } else if (SourceChar =3D=3D '/') { + Base64Value =3D 63; + } else if (SourceChar =3D=3D '=3D') { + // + // Enter padding mode. + // + PaddingMode =3D TRUE; + + if (SixBitGroupsConsumed =3D=3D 2) { + // + // If we have consumed two 6-bit groups from the current quantum b= efore + // encountering the first padding character, then this is case (2)= from + // RFC4648, Chapter 4. "Base 64 Encoding". Bump SixBitGroupsConsum= ed, + // and we'll enforce another padding character. + // + SixBitGroupsConsumed =3D 3; + } else if (SixBitGroupsConsumed =3D=3D 3) { + // + // If we have consumed three 6-bit groups from the current quantum + // before encountering the first padding character, then this is c= ase + // (3) from RFC4648, Chapter 4. "Base 64 Encoding". The quantum is= now + // complete. + // + SixBitGroupsConsumed =3D 0; + } else { + // + // Padding characters are not allowed at the first two positions o= f a + // quantum. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Wherever in a quantum we enter padding mode, we enforce the paddi= ng + // bits pending in the accumulator -- from the last 6-bit group just + // preceding the padding character -- to be zero. Refer to RFC4648, + // Chapter 3.5. "Canonical Encoding". + // + if (Accumulator !=3D 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // Advance to the next source character. + // + continue; + } else { + // + // Other characters outside of the encoding alphabet are rejected. + // + return RETURN_INVALID_PARAMETER; + } + + // + // Feed the bits of the current 6-bit group of the quantum to the + // accumulator. + // + Accumulator =3D (Accumulator << 6) | Base64Value; + SixBitGroupsConsumed++; + switch (SixBitGroupsConsumed) { + case 1: + // + // No octet to spill after consuming the first 6-bit group of the + // quantum; advance to the next source character. + // + continue; + case 2: + // + // 12 bits accumulated (6 pending + 6 new); prepare for spilling an + // octet. 4 bits remain pending. + // + DestinationOctet =3D (UINT8)(Accumulator >> 4); + Accumulator &=3D 0xF; + break; + case 3: + // + // 10 bits accumulated (4 pending + 6 new); prepare for spilling an + // octet. 2 bits remain pending. + // + DestinationOctet =3D (UINT8)(Accumulator >> 2); + Accumulator &=3D 0x3; + break; + default: + ASSERT (SixBitGroupsConsumed =3D=3D 4); + // + // 8 bits accumulated (2 pending + 6 new); prepare for spilling an o= ctet. + // The quantum is complete, 0 bits remain pending. + // + DestinationOctet =3D (UINT8)Accumulator; + Accumulator =3D 0; + SixBitGroupsConsumed =3D 0; + break; + } + + // + // Store the decoded octet if there's room left. Increment + // (*DestinationSize) unconditionally. + // + if (*DestinationSize < OriginalDestinationSize) { + ASSERT (Destination !=3D NULL); + Destination[*DestinationSize] =3D DestinationOctet; + } + (*DestinationSize)++; + + // + // Advance to the next source character. + // + } + + // + // If Source terminates mid-quantum, then Source is invalid. + // + if (SixBitGroupsConsumed !=3D 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // Done. + // + if (*DestinationSize <=3D OriginalDestinationSize) { + return RETURN_SUCCESS; + } + return RETURN_BUFFER_TOO_SMALL; } =20 /** --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#43161): https://edk2.groups.io/g/devel/message/43161 Mute This Topic: https://groups.io/mt/32284614/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sat Apr 27 16:07:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+43160+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43160+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562063346; cv=none; d=zoho.com; s=zohoarc; b=DZ05RweHz1ob0yLr4XWlYaLlulnK00Ng6F6t4oCSF2JcZV2t9PEnE9kfV9SanuVzwJ3TH+dnBrTV4q2LmYuSHf0lfKVLWmR/tjLmtDZEJKruWX6prUirKs5bAT2mXfvXII4koT4ZR5Y5YYkC2L431kS/Y8GIoejiyLVRavUb2Ow= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562063346; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=cjqsr+FHmaVhK7Zr2Bm9P07uX1VV90jGoMl2RE0ilLM=; b=JSxxTCBEitqHgcwwxeuTMRRVk3yucgUmFtNbXYBcGp3RubdpgiDEkjU1doECLyvwi5AcdGN+T42tH5EAisFQVTzYqsQ8OVA5/A9KH+GuuzfGGCk6rs7MF6P7LDwTccblJ1+CYOoQ8oSeNLUMEB17kQMQ5FRBj+n7zib8pNY4bwE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+43160+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1562063345975863.4303034870939; Tue, 2 Jul 2019 03:29:05 -0700 (PDT) Return-Path: X-Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by groups.io with SMTP; Tue, 02 Jul 2019 03:29:04 -0700 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2172C10C94; Tue, 2 Jul 2019 10:29:01 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-117-172.ams2.redhat.com [10.36.117.172]) by smtp.corp.redhat.com (Postfix) with ESMTP id CDBCA19732; Tue, 2 Jul 2019 10:28:55 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Ard Biesheuvel , Jordan Justen , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [PATCH 3/3] OvmfPkg/EnrollDefaultKeys: clean up Base64Decode() retval handling Date: Tue, 2 Jul 2019 12:28:36 +0200 Message-Id: <20190702102836.27589-4-lersek@redhat.com> In-Reply-To: <20190702102836.27589-1-lersek@redhat.com> References: <20190702102836.27589-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 02 Jul 2019 10:29:03 +0000 (UTC) Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1562063344; bh=j7pNqG7vRQryyGdZkyHMshrhmBr6A7fvdnXtuqL/M14=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=PvWfUxyCaUa0u+GrMr/20RW9RYsKVMMGHK/v/AVdC9R4taPxcurKKkM0TgxxctyclUX YtdT2SAg7fW6hgpYHEP6GdiOVi17hU1bHg83BRlF7aFIcbwpbBkdwBcRBXbOt0X0ZfDqv bHSO/VU2tLwDlt0s+tz2EGgGPnFzNlPUkck= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Base64Decode() now guarantees that DestinationSize is larger on output than it was on input if RETURN_BUFFER_TOO_SMALL is returned. Clean up the retval handling for the first Base64Decode() call in EnrollDefaultKeys, which used to work around the ambiguity in the previous Base64Decode() interface contract. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Philippe Mathieu-Daud=C3=A9 Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1891 Signed-off-by: Laszlo Ersek Reviewed-by: Philippe Mathieu-Daude --- OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c b/OvmfPkg/Enroll= DefaultKeys/EnrollDefaultKeys.c index f45cb799f726..302b80d97720 100644 --- a/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c +++ b/OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c @@ -154,14 +154,8 @@ GetPkKek1 ( Status =3D Base64Decode (Base64Cert, Base64CertLen, NULL, &DecodedCertSi= ze); switch (Status) { case EFI_BUFFER_TOO_SMALL: - if (DecodedCertSize > 0) { - break; - } - // - // Fall through: the above Base64Decode() call is ill-specified in Bas= eLib - // if Source decodes to zero bytes (for example if it consists of igno= red - // whitespace only). - // + ASSERT (DecodedCertSize > 0); + break; case EFI_SUCCESS: AsciiPrint ("error: empty certificate after app prefix %g\n", &gOvmfPkKek1AppPrefixGuid); --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#43160): https://edk2.groups.io/g/devel/message/43160 Mute This Topic: https://groups.io/mt/32284613/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-