1 /*
2  *  Copyright (c) 2020, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for checksum calculation.
32  */
33 
34 #ifndef CHECKSUM_HPP_
35 #define CHECKSUM_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 
41 #include "common/message.hpp"
42 #include "net/ip4_types.hpp"
43 #include "net/ip6_address.hpp"
44 #include "net/ip6_headers.hpp"
45 #include "net/socket.hpp"
46 
47 namespace ot {
48 
49 /**
50  * Implements IP checksum calculation and verification.
51  *
52  */
53 class Checksum
54 {
55     friend class ChecksumTester;
56 
57 public:
58     /**
59      * Verifies the checksum in a given message (if UDP/ICMP6).
60      *
61      * @param[in] aMessage       The message to verify its checksum. The `aMessage.GetOffset()` should point to start
62      *                           UDP/ICMP6 header.
63      * @param[in] aMessageInfo   The message info associated with @p aMessage.
64      * @param[in] aIpProto       The Internet Protocol value.
65      *
66      * @retval kErrorNone    The checksum is valid if UDP/ICMP6 protocol, or not a UDP/ICMP6 protocol.
67      * @retval kErrorDrop    The check is not valid and message should be dropped.
68      *
69      */
70     static Error VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto);
71 
72     /**
73      * Calculates and then updates the checksum in a given message (if TCP/UDP/ICMPv6).
74      *
75      * @param[in,out] aMessage  The message to update the checksum in. The `aMessage.GetOffset()` should point to start
76      *                          of the TCP/UDP/ICMPv6 header. On exit the checksum field in TCP/UDP/ICMPv6 header in the
77      *                          message is updated.
78      * @param[in] aSource       The source address.
79      * @param[in] aDestination  The destination address.
80      * @param[in] aIpProto      The Internet Protocol value.
81      *
82      */
83     static void UpdateMessageChecksum(Message            &aMessage,
84                                       const Ip6::Address &aSource,
85                                       const Ip6::Address &aDestination,
86                                       uint8_t             aIpProto);
87 
88     /**
89      * Calculates and then updates the checksum in a given IPv4 message (if TCP/UDP/ICMP(v4)).
90      *
91      * @param[in,out] aMessage  The message to update the checksum in. The `aMessage.GetOffset()` should point to start
92      *                          of the TCP/UDP/ICMP(v4) header. On exit the checksum field in TCP/UDP/ICMP(v4) header in
93      *                          the message is updated.
94      * @param[in] aSource       The source address.
95      * @param[in] aDestination  The destination address.
96      * @param[in] aIpProto      The Internet Protocol value.
97      *
98      */
99     static void UpdateMessageChecksum(Message            &aMessage,
100                                       const Ip4::Address &aSource,
101                                       const Ip4::Address &aDestination,
102                                       uint8_t             aIpProto);
103 
104     /**
105      * Calculates and then updates the checksum field in the IPv4 header.
106      *
107      * @param[in,out] aHeader The IPv4 header to update the checksum in.
108      *
109      */
110     static void UpdateIp4HeaderChecksum(Ip4::Header &aHeader);
111 
112 private:
Checksum(void)113     Checksum(void)
114         : mValue(0)
115         , mAtOddIndex(false)
116     {
117     }
118 
GetValue(void) const119     uint16_t GetValue(void) const { return mValue; }
120     void     AddUint8(uint8_t aUint8);
121     void     AddUint16(uint16_t aUint16);
122     void     AddData(const uint8_t *aBuffer, uint16_t aLength);
123     void     WriteToMessage(uint16_t aOffset, Message &aMessage) const;
124     void     Calculate(const Ip6::Address &aSource,
125                        const Ip6::Address &aDestination,
126                        uint8_t             aIpProto,
127                        const Message      &aMessage);
128     void     Calculate(const Ip4::Address &aSource,
129                        const Ip4::Address &aDestination,
130                        uint8_t             aIpProto,
131                        const Message      &aMessage);
132 
133     static constexpr uint16_t kValidRxChecksum = 0xffff;
134 
135     uint16_t mValue;
136     bool     mAtOddIndex;
137 };
138 
139 } // namespace ot
140 
141 #endif // CHECKSUM_HPP_
142