From nobody Mon Feb 9 19:52:55 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+76199+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+76199+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1623154389; cv=none; d=zohomail.com; s=zohoarc; b=czf25z5mDR/ohUsQ1yOD0ps5q9kguHQoCF+zj0O3oI40iEbkgjS3takOC8tB7EPQxO+h7ZzdlNrFe3RF2dfPAsNzGi60l4MTqWGrshbyi25Db8wevP2lvvyN70BR5PUD9q0KnYmfvnij3INSC0JM07c543ZTH7tZSKAA1fmY2xA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1623154389; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=YycfVKlDISV2q+AleVSKL8M7Vl1RavsC+bP5rNI54JY=; b=R6WKoNaRUowVUh+FP4024f1SRj8lQe/RBe2S53gi5Nxqt3FxXIACXTdBA8GoaGN49ymGSSPoslcJ9mXpxyn+Sh7QfZuf7f7Y85DgaFKnoLUlUSo/koIdnZ7bbbPD+ldvs9DtpYHeextRrZHb6NbMO96bmMPV7WxHaW86zFQ0rtM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+76199+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1623154389832574.5375725612643; Tue, 8 Jun 2021 05:13:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id xJCUYY1788612x4pbOJUHGAf; Tue, 08 Jun 2021 05:13:09 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.groups.io with SMTP id smtpd.web10.11403.1623154388095847461 for ; Tue, 08 Jun 2021 05:13:08 -0700 X-Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-240-a_2uocLcONqwVF9F83sqFg-1; Tue, 08 Jun 2021 08:13:04 -0400 X-MC-Unique: a_2uocLcONqwVF9F83sqFg-1 X-Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9D22D106BAA8; Tue, 8 Jun 2021 12:13:03 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-113-27.ams2.redhat.com [10.36.113.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 39CA5620DE; Tue, 8 Jun 2021 12:13:02 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Jiaxin Wu , Maciej Rabeda , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Siyuan Fu Subject: [edk2-devel] [PUBLIC edk2 PATCH v2 01/10] NetworkPkg/IScsiDxe: wrap IScsiCHAP source files to 80 characters Date: Tue, 8 Jun 2021 14:12:50 +0200 Message-Id: <20210608121259.32451-2-lersek@redhat.com> In-Reply-To: <20210608121259.32451-1-lersek@redhat.com> References: <20210608121259.32451-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: 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 X-Gm-Message-State: kx02PuwPRcjfYFPL9AYGn6mXx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1623154389; bh=YycfVKlDISV2q+AleVSKL8M7Vl1RavsC+bP5rNI54JY=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=MwLPODOTPEwd79q1mrG2PbXM8UXqQtYL0q5uFXLFYwgCOjmNzyKjlNJmiK7a34cKvEc u1tbnvOPxxfwd1gAOlCsqlcKMhr/w82uHXlDK2svzterI7/a4yUjfz+XFFDAEspfgpsRN Qzcx1MhaZxwnpd+WMF+ucpqzjdGgBbP7zq4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Working with overlong lines is difficult for me; rewrap the CHAP-related source files in IScsiDxe to 80 characters width. No functional changes. Cc: Jiaxin Wu Cc: Maciej Rabeda Cc: Philippe Mathieu-Daud=C3=A9 Cc: Siyuan Fu Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3356 Signed-off-by: Laszlo Ersek Reviewed-by: Maciej Rabeda Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- NetworkPkg/IScsiDxe/IScsiCHAP.h | 3 +- NetworkPkg/IScsiDxe/IScsiCHAP.c | 90 +++++++++++++++----- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.h b/NetworkPkg/IScsiDxe/IScsiCHA= P.h index 140bba0dcd76..5e59fb678bd7 100644 --- a/NetworkPkg/IScsiDxe/IScsiCHAP.h +++ b/NetworkPkg/IScsiDxe/IScsiCHAP.h @@ -72,31 +72,32 @@ typedef struct _ISCSI_CHAP_AUTH_DATA { =20 @retval EFI_SUCCESS The Login Response passed the CHAP validati= on. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred. @retval Others Other errors as indicated. =20 **/ EFI_STATUS IScsiCHAPOnRspReceived ( IN ISCSI_CONNECTION *Conn ); /** This function fills the CHAP authentication information into the login P= DU during the security negotiation stage in the iSCSI connection login. =20 @param[in] Conn The iSCSI connection. @param[in, out] Pdu The PDU to send out. =20 @retval EFI_SUCCESS All check passed and the phase-related CHAP - authentication info is filled into the iSC= SI PDU. + authentication info is filled into the iSC= SI + PDU. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred. =20 **/ EFI_STATUS IScsiCHAPToSendReq ( IN ISCSI_CONNECTION *Conn, IN OUT NET_BUF *Pdu ); =20 #endif diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHA= P.c index 355c6f129f68..cbbc56ae5b43 100644 --- a/NetworkPkg/IScsiDxe/IScsiCHAP.c +++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c @@ -1,42 +1,45 @@ /** @file - This file is for Challenge-Handshake Authentication Protocol (CHAP) Conf= iguration. + This file is for Challenge-Handshake Authentication Protocol (CHAP) + Configuration. =20 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include "IScsiImpl.h" =20 /** Initiator calculates its own expected hash value. =20 @param[in] ChapIdentifier iSCSI CHAP identifier sent by authentica= tor. @param[in] ChapSecret iSCSI CHAP secret of the authenticator. @param[in] SecretLength The length of iSCSI CHAP secret. @param[in] ChapChallenge The challenge message sent by authentica= tor. @param[in] ChallengeLength The length of iSCSI CHAP challenge messa= ge. @param[out] ChapResponse The calculation of the expected hash val= ue. =20 - @retval EFI_SUCCESS The expected hash value was calculatedly= successfully. - @retval EFI_PROTOCOL_ERROR The length of the secret should be at le= ast the - length of the hash value for the hashing= algorithm chosen. + @retval EFI_SUCCESS The expected hash value was calculatedly + successfully. + @retval EFI_PROTOCOL_ERROR The length of the secret should be at le= ast + the length of the hash value for the has= hing + algorithm chosen. @retval EFI_PROTOCOL_ERROR MD5 hash operation fail. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete MD= 5. =20 **/ EFI_STATUS IScsiCHAPCalculateResponse ( IN UINT32 ChapIdentifier, IN CHAR8 *ChapSecret, IN UINT32 SecretLength, IN UINT8 *ChapChallenge, IN UINT32 ChallengeLength, OUT UINT8 *ChapResponse ) { UINTN Md5ContextSize; VOID *Md5Ctx; CHAR8 IdByte[1]; EFI_STATUS Status; =20 @@ -78,40 +81,42 @@ IScsiCHAPCalculateResponse ( goto Exit; } =20 if (Md5Final (Md5Ctx, ChapResponse)) { Status =3D EFI_SUCCESS; } =20 Exit: FreePool (Md5Ctx); return Status; } =20 /** The initiator checks the CHAP response replied by target against its own calculation of the expected hash value. =20 @param[in] AuthData iSCSI CHAP authentication data. @param[in] TargetResponse The response from target. =20 - @retval EFI_SUCCESS The response from target passed authen= tication. - @retval EFI_SECURITY_VIOLATION The response from target was not expec= ted value. + @retval EFI_SUCCESS The response from target passed + authentication. + @retval EFI_SECURITY_VIOLATION The response from target was not expec= ted + value. @retval Others Other errors as indicated. =20 **/ EFI_STATUS IScsiCHAPAuthTarget ( IN ISCSI_CHAP_AUTH_DATA *AuthData, IN UINT8 *TargetResponse ) { EFI_STATUS Status; UINT32 SecretSize; UINT8 VerifyRsp[ISCSI_CHAP_RSP_LEN]; =20 Status =3D EFI_SUCCESS; =20 SecretSize =3D (UINT32) AsciiStrLen (AuthData->AuthConfig->ReverseCHAPS= ecret); Status =3D IScsiCHAPCalculateResponse ( AuthData->OutIdentifier, AuthData->AuthConfig->ReverseCHAPSecret, @@ -177,187 +182,211 @@ IScsiCHAPOnRspReceived ( // NetbufQueCopy (&Conn->RspQue, 0, Len, Data); =20 // // Build the key-value list from the data segment of the Login Response. // KeyValueList =3D IScsiBuildKeyValueList ((CHAR8 *) Data, Len); if (KeyValueList =3D=3D NULL) { Status =3D EFI_OUT_OF_RESOURCES; goto ON_EXIT; } =20 Status =3D EFI_PROTOCOL_ERROR; =20 switch (Conn->AuthStep) { case ISCSI_AUTH_INITIAL: // // The first Login Response. // - Value =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_P= ORTAL_GROUP_TAG); + Value =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_TARGET_PORTAL_GROUP_TAG + ); if (Value =3D=3D NULL) { goto ON_EXIT; } =20 Result =3D IScsiNetNtoi (Value); if (Result > 0xFFFF) { goto ON_EXIT; } =20 Session->TargetPortalGroupTag =3D (UINT16) Result; =20 - Value =3D IScsiGetValueByKeyFromList (KeyValue= List, ISCSI_KEY_AUTH_METHOD); + Value =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_AUTH_METHOD + ); if (Value =3D=3D NULL) { goto ON_EXIT; } // - // Initiator mandates CHAP authentication but target replies without "= CHAP", or - // initiator suggets "None" but target replies with some kind of auth = method. + // Initiator mandates CHAP authentication but target replies without + // "CHAP", or initiator suggets "None" but target replies with some ki= nd of + // auth method. // if (Session->AuthType =3D=3D ISCSI_AUTH_TYPE_NONE) { if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) !=3D 0) { goto ON_EXIT; } } else if (Session->AuthType =3D=3D ISCSI_AUTH_TYPE_CHAP) { if (AsciiStrCmp (Value, ISCSI_AUTH_METHOD_CHAP) !=3D 0) { goto ON_EXIT; } } else { goto ON_EXIT; } =20 // // Transit to CHAP step one. // Conn->AuthStep =3D ISCSI_CHAP_STEP_ONE; Status =3D EFI_SUCCESS; break; =20 case ISCSI_CHAP_STEP_TWO: // // The Target replies with CHAP_A=3D CHAP_I=3D CHAP_C=3D // - Value =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_ALG= ORITHM); + Value =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_CHAP_ALGORITHM + ); if (Value =3D=3D NULL) { goto ON_EXIT; } =20 Algorithm =3D IScsiNetNtoi (Value); if (Algorithm !=3D ISCSI_CHAP_ALGORITHM_MD5) { // // Unsupported algorithm is chosen by target. // goto ON_EXIT; } =20 - Identifier =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHA= P_IDENTIFIER); + Identifier =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_CHAP_IDENTIFIER + ); if (Identifier =3D=3D NULL) { goto ON_EXIT; } =20 - Challenge =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP= _CHALLENGE); + Challenge =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_CHAP_CHALLENGE + ); if (Challenge =3D=3D NULL) { goto ON_EXIT; } // // Process the CHAP identifier and CHAP Challenge from Target. // Calculate Response value. // Result =3D IScsiNetNtoi (Identifier); if (Result > 0xFF) { goto ON_EXIT; } =20 AuthData->InIdentifier =3D (UINT32) Result; AuthData->InChallengeLength =3D ISCSI_CHAP_AUTH_MAX_LEN; - IScsiHexToBin ((UINT8 *) AuthData->InChallenge, &AuthData->InChallenge= Length, Challenge); + IScsiHexToBin ( + (UINT8 *) AuthData->InChallenge, + &AuthData->InChallengeLength, + Challenge + ); Status =3D IScsiCHAPCalculateResponse ( AuthData->InIdentifier, AuthData->AuthConfig->CHAPSecret, (UINT32) AsciiStrLen (AuthData->AuthConfig->CHAPSecret), AuthData->InChallenge, AuthData->InChallengeLength, AuthData->CHAPResponse ); =20 // // Transit to next step. // Conn->AuthStep =3D ISCSI_CHAP_STEP_THREE; break; =20 case ISCSI_CHAP_STEP_THREE: // // One way CHAP authentication and the target would like to // authenticate us. // Status =3D EFI_SUCCESS; break; =20 case ISCSI_CHAP_STEP_FOUR: ASSERT (AuthData->AuthConfig->CHAPType =3D=3D ISCSI_CHAP_MUTUAL); // // The forth step, CHAP_N=3D CHAP_R=3D is received from Target. // Name =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_NAME= ); if (Name =3D=3D NULL) { goto ON_EXIT; } =20 - Response =3D IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_= RESPONSE); + Response =3D IScsiGetValueByKeyFromList ( + KeyValueList, + ISCSI_KEY_CHAP_RESPONSE + ); if (Response =3D=3D NULL) { goto ON_EXIT; } =20 RspLen =3D ISCSI_CHAP_RSP_LEN; IScsiHexToBin (TargetRsp, &RspLen, Response); =20 // // Check the CHAP Name and Response replied by Target. // Status =3D IScsiCHAPAuthTarget (AuthData, TargetRsp); break; =20 default: break; } =20 ON_EXIT: =20 if (KeyValueList !=3D NULL) { IScsiFreeKeyValueList (KeyValueList); } =20 FreePool (Data); =20 return Status; } =20 =20 /** This function fills the CHAP authentication information into the login P= DU during the security negotiation stage in the iSCSI connection login. =20 @param[in] Conn The iSCSI connection. @param[in, out] Pdu The PDU to send out. =20 @retval EFI_SUCCESS All check passed and the phase-related CHAP - authentication info is filled into the iSC= SI PDU. + authentication info is filled into the iSC= SI + PDU. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred. =20 **/ EFI_STATUS IScsiCHAPToSendReq ( IN ISCSI_CONNECTION *Conn, IN OUT NET_BUF *Pdu ) { EFI_STATUS Status; ISCSI_SESSION *Session; ISCSI_LOGIN_REQUEST *LoginReq; ISCSI_CHAP_AUTH_DATA *AuthData; CHAR8 *Value; CHAR8 ValueStr[256]; CHAR8 *Response; UINT32 RspLen; CHAR8 *Challenge; @@ -376,95 +405,114 @@ IScsiCHAPToSendReq ( RspLen =3D 2 * ISCSI_CHAP_RSP_LEN + 3; Response =3D AllocateZeroPool (RspLen); if (Response =3D=3D NULL) { return EFI_OUT_OF_RESOURCES; } =20 ChallengeLen =3D 2 * ISCSI_CHAP_RSP_LEN + 3; Challenge =3D AllocateZeroPool (ChallengeLen); if (Challenge =3D=3D NULL) { FreePool (Response); return EFI_OUT_OF_RESOURCES; } =20 switch (Conn->AuthStep) { case ISCSI_AUTH_INITIAL: // // It's the initial Login Request. Fill in the key=3Dvalue pairs manda= tory // for the initial Login Request. // - IScsiAddKeyValuePair (Pdu, ISCSI_KEY_INITIATOR_NAME, mPrivate->Initiat= orName); + IScsiAddKeyValuePair ( + Pdu, + ISCSI_KEY_INITIATOR_NAME, + mPrivate->InitiatorName + ); IScsiAddKeyValuePair (Pdu, ISCSI_KEY_SESSION_TYPE, "Normal"); IScsiAddKeyValuePair ( Pdu, ISCSI_KEY_TARGET_NAME, Session->ConfigData->SessionConfigData.TargetName ); =20 if (Session->AuthType =3D=3D ISCSI_AUTH_TYPE_NONE) { Value =3D ISCSI_KEY_VALUE_NONE; ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT); } else { Value =3D ISCSI_AUTH_METHOD_CHAP; } =20 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_AUTH_METHOD, Value); =20 break; =20 case ISCSI_CHAP_STEP_ONE: // - // First step, send the Login Request with CHAP_A=3D key-val= ue pair. + // First step, send the Login Request with CHAP_A=3D key-val= ue + // pair. // AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", ISCSI_CHAP_ALGORITHM_M= D5); IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_ALGORITHM, ValueStr); =20 Conn->AuthStep =3D ISCSI_CHAP_STEP_TWO; break; =20 case ISCSI_CHAP_STEP_THREE: // // Third step, send the Login Request with CHAP_N=3D CHAP_R=3D or // CHAP_N=3D CHAP_R=3D CHAP_I=3D CHAP_C=3D if target authe= ntication is // required too. // // CHAP_N=3D // - IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->A= uthConfig->CHAPName); + IScsiAddKeyValuePair ( + Pdu, + ISCSI_KEY_CHAP_NAME, + (CHAR8 *) &AuthData->AuthConfig->CHAPName + ); // // CHAP_R=3D // - IScsiBinToHex ((UINT8 *) AuthData->CHAPResponse, ISCSI_CHAP_RSP_LEN, R= esponse, &RspLen); + IScsiBinToHex ( + (UINT8 *) AuthData->CHAPResponse, + ISCSI_CHAP_RSP_LEN, + Response, + &RspLen + ); IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response); =20 if (AuthData->AuthConfig->CHAPType =3D=3D ISCSI_CHAP_MUTUAL) { // // CHAP_I=3D // IScsiGenRandom ((UINT8 *) &AuthData->OutIdentifier, 1); AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentif= ier); IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr); // // CHAP_C=3D // IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN= ); AuthData->OutChallengeLength =3D ISCSI_CHAP_RSP_LEN; - IScsiBinToHex ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN,= Challenge, &ChallengeLen); + IScsiBinToHex ( + (UINT8 *) AuthData->OutChallenge, + ISCSI_CHAP_RSP_LEN, + Challenge, + &ChallengeLen + ); IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge); =20 Conn->AuthStep =3D ISCSI_CHAP_STEP_FOUR; } // // Set the stage transition flag. // ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT); break; =20 default: Status =3D EFI_PROTOCOL_ERROR; break; } =20 FreePool (Response); FreePool (Challenge); =20 return Status; --=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 (#76199): https://edk2.groups.io/g/devel/message/76199 Mute This Topic: https://groups.io/mt/83394107/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-