| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines functions for encoding and decoding CHIP messages. |
| * The encoded messages contain CHIP packet header, encrypted payload |
| * header, encrypted payload and message authentication code, as per |
| * CHIP specifications. |
| * |
| */ |
| |
| #include <lib/support/CodeUtils.h> |
| #include <lib/support/SafeInt.h> |
| #include <transport/SecureMessageCodec.h> |
| |
| namespace chip { |
| |
| using System::PacketBuffer; |
| using System::PacketBufferHandle; |
| |
| namespace SecureMessageCodec { |
| |
| CHIP_ERROR Encrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, |
| PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf) |
| { |
| VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); |
| VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH); |
| VerifyOrReturnError(msgBuf->TotalLength() <= kMaxAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG); |
| |
| ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(msgBuf)); |
| |
| uint8_t * data = msgBuf->Start(); |
| size_t totalLen = msgBuf->TotalLength(); |
| |
| MessageAuthenticationCode mac; |
| ReturnErrorOnFailure(context.Encrypt(data, totalLen, data, nonce, packetHeader, mac)); |
| |
| uint16_t taglen = 0; |
| ReturnErrorOnFailure(mac.Encode(packetHeader, &data[totalLen], msgBuf->AvailableDataLength(), &taglen)); |
| |
| msgBuf->SetDataLength(totalLen + taglen); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR Decrypt(const CryptoContext & context, CryptoContext::ConstNonceView nonce, PayloadHeader & payloadHeader, |
| const PacketHeader & packetHeader, System::PacketBufferHandle & msg) |
| { |
| ReturnErrorCodeIf(msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); |
| |
| uint8_t * data = msg->Start(); |
| size_t len = msg->DataLength(); |
| |
| PacketBufferHandle origMsg; |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| /* This is a workaround for the case where PacketBuffer payload is not |
| allocated as an inline buffer to PacketBuffer structure */ |
| origMsg = std::move(msg); |
| msg = PacketBufferHandle::New(len); |
| VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); |
| msg->SetDataLength(len); |
| #endif |
| |
| uint16_t footerLen = packetHeader.MICTagLength(); |
| VerifyOrReturnError(footerLen <= len, CHIP_ERROR_INVALID_MESSAGE_LENGTH); |
| |
| uint16_t taglen = 0; |
| MessageAuthenticationCode mac; |
| ReturnErrorOnFailure(mac.Decode(packetHeader, &data[len - footerLen], footerLen, &taglen)); |
| VerifyOrReturnError(taglen == footerLen, CHIP_ERROR_INTERNAL); |
| |
| len = len - taglen; |
| msg->SetDataLength(len); |
| |
| uint8_t * plainText = msg->Start(); |
| ReturnErrorOnFailure(context.Decrypt(data, len, plainText, nonce, packetHeader, mac)); |
| |
| ReturnErrorOnFailure(payloadHeader.DecodeAndConsume(msg)); |
| return CHIP_NO_ERROR; |
| } |
| |
| } // namespace SecureMessageCodec |
| |
| } // namespace chip |