Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #ifndef _XFRM_CONTROLLER_H
     17 #define _XFRM_CONTROLLER_H
     18 
     19 #include <atomic>
     20 #include <list>
     21 #include <map>
     22 #include <string>
     23 #include <utility> // for pair
     24 
     25 #include <linux/netlink.h>
     26 #include <linux/xfrm.h>
     27 #include <sysutils/SocketClient.h>
     28 #include <utils/RWLock.h>
     29 
     30 #include "NetdConstants.h"
     31 
     32 namespace android {
     33 namespace net {
     34 
     35 // Suggest we avoid the smallest and largest ints
     36 class XfrmMessage;
     37 class TransportModeSecurityAssociation;
     38 
     39 class XfrmSocket {
     40 public:
     41     virtual void close() {
     42         if (mSock > 0) {
     43             ::close(mSock);
     44         }
     45         mSock = -1;
     46     }
     47 
     48     virtual bool open() = 0;
     49 
     50     virtual ~XfrmSocket() { close(); }
     51 
     52     virtual int sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
     53                             iovec* iov, int iovLen) const = 0;
     54 
     55 protected:
     56     int mSock;
     57 };
     58 
     59 enum struct XfrmDirection : uint8_t {
     60     IN = XFRM_POLICY_IN,
     61     OUT = XFRM_POLICY_OUT,
     62     FORWARD = XFRM_POLICY_FWD,
     63     MASK = XFRM_POLICY_MASK,
     64 };
     65 
     66 enum struct XfrmMode : uint8_t {
     67     TRANSPORT = XFRM_MODE_TRANSPORT,
     68     TUNNEL = XFRM_MODE_TUNNEL,
     69 };
     70 
     71 struct XfrmAlgo {
     72     std::string name;
     73     std::vector<uint8_t> key;
     74     uint16_t truncLenBits;
     75 };
     76 
     77 struct XfrmSaId {
     78     XfrmDirection direction;
     79     xfrm_address_t dstAddr; // network order
     80     xfrm_address_t srcAddr;
     81     int addrFamily;  // AF_INET or AF_INET6
     82     int transformId; // requestId
     83     int spi;
     84 };
     85 
     86 struct XfrmSaInfo : XfrmSaId {
     87     XfrmAlgo auth;
     88     XfrmAlgo crypt;
     89     int netId;
     90     XfrmMode mode;
     91 };
     92 
     93 class XfrmController {
     94 public:
     95     XfrmController();
     96 
     97     int ipSecAllocateSpi(int32_t transformId, int32_t direction, const std::string& localAddress,
     98                          const std::string& remoteAddress, int32_t inSpi, int32_t* outSpi);
     99 
    100     int ipSecAddSecurityAssociation(
    101         int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
    102         const std::string& remoteAddress, int64_t underlyingNetworkHandle, int32_t spi,
    103         const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
    104         const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
    105         int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort, int32_t* allocatedSpi);
    106 
    107     int ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
    108                                        const std::string& localAddress,
    109                                        const std::string& remoteAddress, int32_t spi);
    110 
    111     int ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
    112                                          int32_t transformId, int32_t direction,
    113                                          const std::string& localAddress,
    114                                          const std::string& remoteAddress, int32_t spi);
    115 
    116     int ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket);
    117 
    118 private:
    119     // prevent concurrent modification of XFRM
    120     android::RWLock mLock;
    121 
    122     static constexpr size_t MAX_ALGO_LENGTH = 128;
    123 
    124 /*
    125  * Below is a redefinition of the xfrm_usersa_info struct that is part
    126  * of the Linux uapi <linux/xfrm.h> to align the structures to a 64-bit
    127  * boundary.
    128  */
    129 #ifdef NETLINK_COMPAT32
    130     // Shadow the kernel definition of xfrm_usersa_info with a 64-bit aligned version
    131     struct xfrm_usersa_info : ::xfrm_usersa_info {
    132     } __attribute__((aligned(8)));
    133     // Shadow the kernel's version, using the aligned version of xfrm_usersa_info
    134     struct xfrm_userspi_info {
    135         struct xfrm_usersa_info info;
    136         __u32 min;
    137         __u32 max;
    138     };
    139 
    140     /*
    141      * Anyone who encounters a failure when sending netlink messages should look here
    142      * first. Hitting the static_assert() below should be a strong hint that Android
    143      * IPsec will probably not work with your current settings.
    144      *
    145      * Again, experimentally determined, the "flags" field should be the first byte in
    146      * the final word of the xfrm_usersa_info struct. The check validates the size of
    147      * the padding to be 7.
    148      *
    149      * This padding is verified to be correct on gcc/x86_64 kernel, and clang/x86 userspace.
    150      */
    151     static_assert(sizeof(::xfrm_usersa_info) % 8 != 0, "struct xfrm_usersa_info has changed "
    152                                                        "alignment. Please consider whether this "
    153                                                        "patch is needed.");
    154     static_assert(sizeof(xfrm_usersa_info) - offsetof(xfrm_usersa_info, flags) == 8,
    155                   "struct xfrm_usersa_info probably misaligned with kernel struct.");
    156     static_assert(sizeof(xfrm_usersa_info) % 8 == 0, "struct xfrm_usersa_info_t is not 64-bit  "
    157                                                      "aligned. Please consider whether this patch "
    158                                                      "is needed.");
    159     static_assert(sizeof(::xfrm_userspi_info) - sizeof(::xfrm_usersa_info) ==
    160                       sizeof(xfrm_userspi_info) - sizeof(xfrm_usersa_info),
    161                   "struct xfrm_userspi_info has changed and does not match the kernel struct.");
    162 #endif
    163 
    164     struct nlattr_algo_crypt {
    165         nlattr hdr;
    166         xfrm_algo crypt;
    167         uint8_t key[MAX_ALGO_LENGTH]; // 1024 bit key, TODO: move off stack
    168     };
    169 
    170     struct nlattr_algo_auth {
    171         nlattr hdr;
    172         xfrm_algo_auth auth;
    173         uint8_t key[MAX_ALGO_LENGTH]; // 1024 bit key, TODO: move off stack
    174     };
    175 
    176     struct nlattr_user_tmpl {
    177         nlattr hdr;
    178         xfrm_user_tmpl tmpl;
    179     };
    180 
    181     // helper function for filling in the XfrmSaInfo structure
    182     static int fillXfrmSaId(int32_t direction, const std::string& localAddress,
    183                             const std::string& remoteAddress, int32_t spi, XfrmSaId* xfrmId);
    184 
    185     // Top level functions for managing a Transport Mode Transform
    186     static int addTransportModeTransform(const XfrmSaInfo& record);
    187     static int removeTransportModeTransform(const XfrmSaInfo& record);
    188 
    189     // TODO(messagerefactor): FACTOR OUT ALL MESSAGE BUILDING CODE BELOW HERE
    190     // Shared between SA and SP
    191     static void fillTransportModeSelector(const XfrmSaInfo& record, xfrm_selector* selector);
    192 
    193     // Shared between Transport and Tunnel Mode
    194     static int fillNlAttrXfrmAlgoEnc(const XfrmAlgo& in_algo, nlattr_algo_crypt* algo);
    195     static int fillNlAttrXfrmAlgoAuth(const XfrmAlgo& in_algo, nlattr_algo_auth* algo);
    196 
    197     // Functions for Creating a Transport Mode SA
    198     static int createTransportModeSecurityAssociation(const XfrmSaInfo& record,
    199                                                       const XfrmSocket& sock);
    200     static int fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa);
    201 
    202     // Functions for deleting a Transport Mode SA
    203     static int deleteSecurityAssociation(const XfrmSaId& record, const XfrmSocket& sock);
    204     static int fillUserSaId(const XfrmSaId& record, xfrm_usersa_id* said);
    205     static int fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl);
    206     static int fillTransportModeUserSpInfo(const XfrmSaInfo& record, xfrm_userpolicy_info* usersp);
    207 
    208     static int allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
    209                            uint32_t* outSpi, const XfrmSocket& sock);
    210 
    211     // END TODO(messagerefactor)
    212 };
    213 
    214 } // namespace net
    215 } // namespace android
    216 
    217 #endif /* !defined(XFRM_CONTROLLER_H) */
    218