blob: 7c0c59da8391f82d0c22bba50a3c0a2161c7562d [file] [log] [blame]
Nathan Harold1a371532017-01-30 12:30:48 -08001/*
2 *
3 * Copyright (C) 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <string>
19#include <vector>
20
21#include <ctype.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <getopt.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Nathan Harold420ceac2017-04-05 19:36:59 -070028
29#define __STDC_FORMAT_MACROS
Nathan Harold1a371532017-01-30 12:30:48 -080030#include <inttypes.h>
31
32#include <arpa/inet.h>
33#include <netinet/in.h>
34
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <sys/wait.h>
39
40#include <linux/in.h>
41#include <linux/netlink.h>
42#include <linux/xfrm.h>
43
44#include "android-base/stringprintf.h"
45#include "android-base/strings.h"
46#include "android-base/unique_fd.h"
47#define LOG_TAG "XfrmController"
48#include "NetdConstants.h"
49#include "NetlinkCommands.h"
50#include "ResponseCode.h"
51#include "XfrmController.h"
52#include <cutils/log.h>
53#include <cutils/properties.h>
54#include <logwrap/logwrap.h>
55
56#define VDBG 1 // STOPSHIP if true
57
58namespace android {
59namespace net {
60
Nathan Harold39b5df42017-08-02 18:45:25 -070061// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080062constexpr uint32_t ALGO_MASK_AUTH_ALL = ~0;
Nathan Harold39b5df42017-08-02 18:45:25 -070063// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080064constexpr uint32_t ALGO_MASK_CRYPT_ALL = ~0;
Nathan Harold39b5df42017-08-02 18:45:25 -070065// Exposed for testing
Nathan Harold1a371532017-01-30 12:30:48 -080066constexpr uint8_t REPLAY_WINDOW_SIZE = 4;
67
Nathan Harold39b5df42017-08-02 18:45:25 -070068namespace {
69
Nathan Harold1a371532017-01-30 12:30:48 -080070constexpr uint32_t RAND_SPI_MIN = 1;
71constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE;
72
73constexpr uint32_t INVALID_SPI = 0;
74
75#define XFRM_MSG_TRANS(x) \
76 case x: \
77 return #x;
78
79const char* xfrmMsgTypeToString(uint16_t msg) {
80 switch (msg) {
81 XFRM_MSG_TRANS(XFRM_MSG_NEWSA)
82 XFRM_MSG_TRANS(XFRM_MSG_DELSA)
83 XFRM_MSG_TRANS(XFRM_MSG_GETSA)
84 XFRM_MSG_TRANS(XFRM_MSG_NEWPOLICY)
85 XFRM_MSG_TRANS(XFRM_MSG_DELPOLICY)
86 XFRM_MSG_TRANS(XFRM_MSG_GETPOLICY)
87 XFRM_MSG_TRANS(XFRM_MSG_ALLOCSPI)
88 XFRM_MSG_TRANS(XFRM_MSG_ACQUIRE)
89 XFRM_MSG_TRANS(XFRM_MSG_EXPIRE)
90 XFRM_MSG_TRANS(XFRM_MSG_UPDPOLICY)
91 XFRM_MSG_TRANS(XFRM_MSG_UPDSA)
92 XFRM_MSG_TRANS(XFRM_MSG_POLEXPIRE)
93 XFRM_MSG_TRANS(XFRM_MSG_FLUSHSA)
94 XFRM_MSG_TRANS(XFRM_MSG_FLUSHPOLICY)
95 XFRM_MSG_TRANS(XFRM_MSG_NEWAE)
96 XFRM_MSG_TRANS(XFRM_MSG_GETAE)
97 XFRM_MSG_TRANS(XFRM_MSG_REPORT)
98 XFRM_MSG_TRANS(XFRM_MSG_MIGRATE)
99 XFRM_MSG_TRANS(XFRM_MSG_NEWSADINFO)
100 XFRM_MSG_TRANS(XFRM_MSG_GETSADINFO)
101 XFRM_MSG_TRANS(XFRM_MSG_GETSPDINFO)
102 XFRM_MSG_TRANS(XFRM_MSG_NEWSPDINFO)
103 XFRM_MSG_TRANS(XFRM_MSG_MAPPING)
104 default:
105 return "XFRM_MSG UNKNOWN";
106 }
107}
108
109// actually const but cannot be declared as such for reasons
110uint8_t kPadBytesArray[] = {0, 0, 0};
111void* kPadBytes = static_cast<void*>(kPadBytesArray);
112
113#if VDBG
Nathan Harold420ceac2017-04-05 19:36:59 -0700114#define LOG_HEX(__desc16__, __buf__, __len__) \
115 do { \
116 logHex(__desc16__, __buf__, __len__); \
117 } while (0)
118#define LOG_IOV(__iov__, __iov_len__) \
119 do { \
120 logIov(__iov__, __iov_len__); \
121 } while (0)
Nathan Harold1a371532017-01-30 12:30:48 -0800122
123void logHex(const char* desc16, const char* buf, size_t len) {
124 char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
125 int offset = 0;
126 if (desc16) {
127 sprintf(printBuf, "{%-16s}", desc16);
128 offset += 18; // prefix string length
129 }
130 sprintf(printBuf + offset, "[%4.4u]: ", (len > 9999) ? 9999 : (unsigned)len);
131 offset += 8;
132
133 for (uint32_t j = 0; j < (uint32_t)len; j++) {
134 sprintf(&printBuf[j * 2 + offset], "%0.2x", buf[j]);
135 }
136 ALOGD("%s", printBuf);
137 delete[] printBuf;
138}
139
140void logIov(const iovec* iov, size_t iovLen) {
141 for (uint32_t i = 0; i < (uint32_t)iovLen; i++) {
142 const iovec* row = &iov[i];
143 logHex(0, reinterpret_cast<char*>(row->iov_base), row->iov_len);
144 }
145}
146
147#else
148#define LOG_HEX(__desc16__, __buf__, __len__)
149#define LOG_IOV(__iov__, __iov_len__)
150#endif
151
152class XfrmSocketImpl : public XfrmSocket {
153private:
154 static constexpr int NLMSG_DEFAULTSIZE = 8192;
155
156 union NetlinkResponse {
157 nlmsghdr hdr;
158 struct _err_ {
159 nlmsghdr hdr;
160 nlmsgerr err;
161 } err;
162
163 struct _buf_ {
164 nlmsghdr hdr;
165 char buf[NLMSG_DEFAULTSIZE];
166 } buf;
167 };
168
169public:
170 virtual bool open() {
171 mSock = openNetlinkSocket(NETLINK_XFRM);
172 if (mSock <= 0) {
173 ALOGW("Could not get a new socket, line=%d", __LINE__);
174 return false;
175 }
176
177 return true;
178 }
179
180 static int validateResponse(NetlinkResponse response, size_t len) {
181 if (len < sizeof(nlmsghdr)) {
182 ALOGW("Invalid response message received over netlink");
183 return -EBADMSG;
184 }
185
186 switch (response.hdr.nlmsg_type) {
187 case NLMSG_NOOP:
188 case NLMSG_DONE:
189 return 0;
190 case NLMSG_OVERRUN:
191 ALOGD("Netlink request overran kernel buffer");
192 return -EBADMSG;
193 case NLMSG_ERROR:
194 if (len < sizeof(NetlinkResponse::_err_)) {
195 ALOGD("Netlink message received malformed error response");
196 return -EBADMSG;
197 }
198 return response.err.err.error; // Netlink errors are negative errno.
199 case XFRM_MSG_NEWSA:
200 break;
201 }
202
203 if (response.hdr.nlmsg_type < XFRM_MSG_BASE /*== NLMSG_MIN_TYPE*/ ||
204 response.hdr.nlmsg_type > XFRM_MSG_MAX) {
205 ALOGD("Netlink message responded with an out-of-range message ID");
206 return -EBADMSG;
207 }
208
209 // TODO Add more message validation here
210 return 0;
211 }
212
213 virtual int sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
214 iovec* iov, int iovLen) const {
215 nlmsghdr nlMsg = {
216 .nlmsg_type = nlMsgType, .nlmsg_flags = nlMsgFlags, .nlmsg_seq = nlMsgSeqNum,
217 };
218
219 iov[0].iov_base = &nlMsg;
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700220 iov[0].iov_len = NLMSG_HDRLEN;
Nathan Harold1a371532017-01-30 12:30:48 -0800221 for (int i = 0; i < iovLen; ++i) {
222 nlMsg.nlmsg_len += iov[i].iov_len;
223 }
224
225 ALOGD("Sending Netlink XFRM Message: %s", xfrmMsgTypeToString(nlMsgType));
226 if (VDBG)
227 LOG_IOV(iov, iovLen);
228
229 int ret;
230
231 if (writev(mSock, iov, iovLen) < 0) {
232 ALOGE("netlink socket writev failed (%s)", strerror(errno));
233 return -errno;
234 }
235
236 NetlinkResponse* response = new NetlinkResponse{};
237
238 if ((ret = recv(mSock, response, sizeof(*response), 0)) < 0) {
239 ALOGE("netlink response contains error (%s)", strerror(errno));
240 delete response;
241 return -errno;
242 }
243
244 LOG_HEX("netlink msg resp", reinterpret_cast<char*>(response), ret);
245
246 ret = validateResponse(*response, ret);
247 delete response;
248 if (ret < 0)
249 ALOGE("netlink response contains error (%s)", strerror(-ret));
250 return ret;
251 }
252};
253
254int convertToXfrmAddr(const std::string& strAddr, xfrm_address_t* xfrmAddr) {
255 if (strAddr.length() == 0) {
256 memset(xfrmAddr, 0, sizeof(*xfrmAddr));
257 return AF_UNSPEC;
258 }
259
260 if (inet_pton(AF_INET6, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
261 return AF_INET6;
262 } else if (inet_pton(AF_INET, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
263 return AF_INET;
264 } else {
265 return -EAFNOSUPPORT;
266 }
267}
268
269void fillXfrmNlaHdr(nlattr* hdr, uint16_t type, uint16_t len) {
270 hdr->nla_type = type;
271 hdr->nla_len = len;
272}
273
274void fillXfrmCurLifetimeDefaults(xfrm_lifetime_cur* cur) {
275 memset(reinterpret_cast<char*>(cur), 0, sizeof(*cur));
276}
277void fillXfrmLifetimeDefaults(xfrm_lifetime_cfg* cfg) {
278 cfg->soft_byte_limit = XFRM_INF;
279 cfg->hard_byte_limit = XFRM_INF;
280 cfg->soft_packet_limit = XFRM_INF;
281 cfg->hard_packet_limit = XFRM_INF;
282}
283
284/*
285 * Allocate SPIs within an (inclusive) range of min-max.
286 * returns 0 (INVALID_SPI) once the entire range has been parsed.
287 */
288class RandomSpi {
289public:
290 RandomSpi(int min, int max) : mMin(min) {
291 time_t t;
292 srand((unsigned int)time(&t));
293 // TODO: more random random
294 mNext = rand();
295 mSize = max - min + 1;
296 mCount = mSize;
297 }
298
299 uint32_t next() {
300 if (!mCount)
301 return 0;
302 mCount--;
303 return (mNext++ % mSize) + mMin;
304 }
305
306private:
307 uint32_t mNext;
308 uint32_t mSize;
309 uint32_t mMin;
310 uint32_t mCount;
311};
312
313} // namespace
314
315//
316// Begin XfrmController Impl
317//
318//
319XfrmController::XfrmController(void) {}
320
321int XfrmController::ipSecAllocateSpi(int32_t transformId, int32_t direction,
322 const std::string& localAddress,
323 const std::string& remoteAddress, int32_t inSpi,
324 int32_t* outSpi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800325 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
326 ALOGD("transformId=%d", transformId);
327 ALOGD("direction=%d", direction);
328 ALOGD("localAddress=%s", localAddress.c_str());
329 ALOGD("remoteAddress=%s", remoteAddress.c_str());
330 ALOGD("inSpi=%0.8x", inSpi);
331
332 XfrmSaInfo saInfo{};
333 int ret;
334
335 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, INVALID_SPI, &saInfo)) < 0) {
336 return ret;
337 }
338
339 XfrmSocketImpl sock;
340 if (!sock.open()) {
341 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
342 return -1; // TODO: return right error; for whatever reason the sock
343 // failed to open
344 }
345
346 int minSpi = RAND_SPI_MIN, maxSpi = RAND_SPI_MAX;
347
348 if (inSpi)
349 minSpi = maxSpi = inSpi;
350 ret = allocateSpi(saInfo, minSpi, maxSpi, reinterpret_cast<uint32_t*>(outSpi), sock);
351 if (ret < 0) {
352 ALOGD("Failed to Allocate an SPI, line=%d", __LINE__);
353 *outSpi = INVALID_SPI;
354 }
355
356 return ret;
357}
358
359int XfrmController::ipSecAddSecurityAssociation(
360 int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
Nathan Harold420ceac2017-04-05 19:36:59 -0700361 const std::string& remoteAddress, int64_t underlyingNetworkHandle, int32_t spi,
Nathan Harold1a371532017-01-30 12:30:48 -0800362 const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
363 const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
ludiec836052017-05-20 14:17:05 -0700364 int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort) {
Nathan Harold1a371532017-01-30 12:30:48 -0800365 android::RWLock::AutoWLock lock(mLock);
366
367 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
368 ALOGD("transformId=%d", transformId);
369 ALOGD("mode=%d", mode);
370 ALOGD("direction=%d", direction);
371 ALOGD("localAddress=%s", localAddress.c_str());
372 ALOGD("remoteAddress=%s", remoteAddress.c_str());
Nathan Harold420ceac2017-04-05 19:36:59 -0700373 ALOGD("underlyingNetworkHandle=%" PRIx64, underlyingNetworkHandle);
Nathan Harold1a371532017-01-30 12:30:48 -0800374 ALOGD("spi=%0.8x", spi);
375 ALOGD("authAlgo=%s", authAlgo.c_str());
376 ALOGD("authTruncBits=%d", authTruncBits);
377 ALOGD("cryptAlgo=%s", cryptAlgo.c_str());
378 ALOGD("cryptTruncBits=%d,", cryptTruncBits);
379 ALOGD("encapType=%d", encapType);
380 ALOGD("encapLocalPort=%d", encapLocalPort);
381 ALOGD("encapRemotePort=%d", encapRemotePort);
382
383 XfrmSaInfo saInfo{};
384 int ret;
385
386 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
387 return ret;
388 }
389
390 saInfo.transformId = transformId;
391
392 // STOPSHIP : range check the key lengths to prevent puncturing and overflow
393 saInfo.auth = XfrmAlgo{
394 .name = authAlgo, .key = authKey, .truncLenBits = static_cast<uint16_t>(authTruncBits)};
395
396 saInfo.crypt = XfrmAlgo{
397 .name = cryptAlgo, .key = cryptKey, .truncLenBits = static_cast<uint16_t>(cryptTruncBits)};
398
399 saInfo.direction = static_cast<XfrmDirection>(direction);
400
401 switch (static_cast<XfrmMode>(mode)) {
402 case XfrmMode::TRANSPORT:
403 case XfrmMode::TUNNEL:
404 saInfo.mode = static_cast<XfrmMode>(mode);
405 break;
406 default:
407 return -EINVAL;
408 }
409
410 XfrmSocketImpl sock;
411 if (!sock.open()) {
412 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
413 return -1; // TODO: return right error; for whatever reason the sock
414 // failed to open
415 }
416
Nathan Harold420ceac2017-04-05 19:36:59 -0700417 switch (static_cast<XfrmEncapType>(encapType)) {
418 case XfrmEncapType::ESPINUDP:
419 case XfrmEncapType::ESPINUDP_NON_IKE:
420 if (saInfo.addrFamily != AF_INET) {
421 return -EAFNOSUPPORT;
422 }
423 switch (saInfo.direction) {
424 case XfrmDirection::IN:
425 saInfo.encap.srcPort = encapRemotePort;
426 saInfo.encap.dstPort = encapLocalPort;
427 break;
428 case XfrmDirection::OUT:
429 saInfo.encap.srcPort = encapLocalPort;
430 saInfo.encap.dstPort = encapRemotePort;
431 break;
432 default:
433 return -EINVAL;
434 }
435 // fall through
436 case XfrmEncapType::NONE:
437 saInfo.encap.type = static_cast<XfrmEncapType>(encapType);
438 break;
439 default:
440 return -EINVAL;
441 }
442
Nathan Harold1a371532017-01-30 12:30:48 -0800443 ret = createTransportModeSecurityAssociation(saInfo, sock);
444 if (ret < 0) {
445 ALOGD("Failed creating a Security Association, line=%d", __LINE__);
446 return ret; // something went wrong creating the SA
447 }
448
Nathan Harold1a371532017-01-30 12:30:48 -0800449 return 0;
450}
451
452int XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
453 const std::string& localAddress,
454 const std::string& remoteAddress, int32_t spi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800455 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
456 ALOGD("transformId=%d", transformId);
457 ALOGD("direction=%d", direction);
458 ALOGD("localAddress=%s", localAddress.c_str());
459 ALOGD("remoteAddress=%s", remoteAddress.c_str());
460 ALOGD("spi=%0.8x", spi);
461
462 XfrmSaId saId;
463 int ret;
464
465 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saId)) < 0) {
466 return ret;
467 }
468
469 XfrmSocketImpl sock;
470 if (!sock.open()) {
471 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
472 return -1; // TODO: return right error; for whatever reason the sock
473 // failed to open
474 }
475
476 ret = deleteSecurityAssociation(saId, sock);
477 if (ret < 0) {
478 ALOGD("Failed to delete Security Association, line=%d", __LINE__);
479 return ret; // something went wrong deleting the SA
480 }
481
482 return ret;
483}
484
485int XfrmController::fillXfrmSaId(int32_t direction, const std::string& localAddress,
486 const std::string& remoteAddress, int32_t spi, XfrmSaId* xfrmId) {
487 xfrm_address_t localXfrmAddr{}, remoteXfrmAddr{};
488
489 int addrFamilyLocal, addrFamilyRemote;
490 addrFamilyRemote = convertToXfrmAddr(remoteAddress, &remoteXfrmAddr);
491 addrFamilyLocal = convertToXfrmAddr(localAddress, &localXfrmAddr);
492 if (addrFamilyRemote < 0 || addrFamilyLocal < 0) {
493 return -EINVAL;
494 }
495
496 if (addrFamilyRemote == AF_UNSPEC ||
497 (addrFamilyLocal != AF_UNSPEC && addrFamilyLocal != addrFamilyRemote)) {
498 ALOGD("Invalid or Mismatched Address Families, %d != %d, line=%d", addrFamilyLocal,
499 addrFamilyRemote, __LINE__);
500 return -EINVAL;
501 }
502
503 xfrmId->addrFamily = addrFamilyRemote;
504
505 xfrmId->spi = htonl(spi);
506
507 switch (static_cast<XfrmDirection>(direction)) {
508 case XfrmDirection::IN:
509 xfrmId->dstAddr = localXfrmAddr;
510 xfrmId->srcAddr = remoteXfrmAddr;
511 break;
512
513 case XfrmDirection::OUT:
514 xfrmId->dstAddr = remoteXfrmAddr;
515 xfrmId->srcAddr = localXfrmAddr;
516 break;
517
518 default:
519 ALOGD("Invalid XFRM direction, line=%d", __LINE__);
520 // Invalid direction for Transport mode transform: time to bail
521 return -EINVAL;
522 }
523 return 0;
524}
525
526int XfrmController::ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
527 int32_t transformId, int32_t direction,
528 const std::string& localAddress,
529 const std::string& remoteAddress,
530 int32_t spi) {
531 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
532 ALOGD("transformId=%d", transformId);
533 ALOGD("direction=%d", direction);
534 ALOGD("localAddress=%s", localAddress.c_str());
535 ALOGD("remoteAddress=%s", remoteAddress.c_str());
536 ALOGD("spi=%0.8x", spi);
537
538 struct sockaddr_storage saddr;
539
540 socklen_t len = sizeof(saddr);
541 int err;
542 int userSocket = socket.get();
543
544 if ((err = getsockname(userSocket, reinterpret_cast<struct sockaddr*>(&saddr), &len)) < 0) {
545 ALOGE("Failed to get socket info in %s", __FUNCTION__);
546 return -err;
547 }
548
549 XfrmSaInfo saInfo{};
550 saInfo.transformId = transformId;
551 saInfo.direction = static_cast<XfrmDirection>(direction);
552 saInfo.spi = spi;
553
554 if ((err = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
555 ALOGE("Couldn't build SA ID %s", __FUNCTION__);
556 return -err;
557 }
558
559 if (saInfo.addrFamily != saddr.ss_family) {
560 ALOGE("Transform address family(%d) differs from socket address "
Nathan Harold420ceac2017-04-05 19:36:59 -0700561 "family(%d)!",
562 saInfo.addrFamily, saddr.ss_family);
Nathan Harold1a371532017-01-30 12:30:48 -0800563 return -EINVAL;
564 }
565
566 struct {
567 xfrm_userpolicy_info info;
568 xfrm_user_tmpl tmpl;
569 } policy{};
570
571 fillTransportModeUserSpInfo(saInfo, &policy.info);
572 fillUserTemplate(saInfo, &policy.tmpl);
573
574 LOG_HEX("XfrmUserPolicy", reinterpret_cast<char*>(&policy), sizeof(policy));
575
576 int sockOpt, sockLayer;
577 switch (saInfo.addrFamily) {
578 case AF_INET:
579 sockOpt = IP_XFRM_POLICY;
580 sockLayer = SOL_IP;
581 break;
582 case AF_INET6:
583 sockOpt = IPV6_XFRM_POLICY;
584 sockLayer = SOL_IPV6;
585 break;
586 default:
587 return -EAFNOSUPPORT;
588 }
589
590 err = setsockopt(userSocket, sockLayer, sockOpt, &policy, sizeof(policy));
591 if (err < 0) {
592 err = errno;
593 ALOGE("Error setting socket option for XFRM! (%s)", strerror(err));
594 }
595
596 return -err;
597}
598
599int XfrmController::ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket) {
600 (void)socket;
601 return 0;
602}
603
604void XfrmController::fillTransportModeSelector(const XfrmSaInfo& record, xfrm_selector* selector) {
605 selector->family = record.addrFamily;
606 selector->proto = AF_UNSPEC; // TODO: do we need to match the protocol? it's
607 // possible via the socket
608 selector->ifindex = record.netId; // TODO : still need to sort this out
609}
610
611int XfrmController::createTransportModeSecurityAssociation(const XfrmSaInfo& record,
612 const XfrmSocket& sock) {
613 xfrm_usersa_info usersa{};
614 nlattr_algo_crypt crypt{};
615 nlattr_algo_auth auth{};
Nathan Harold420ceac2017-04-05 19:36:59 -0700616 nlattr_encap_tmpl encap{};
Nathan Harold1a371532017-01-30 12:30:48 -0800617
Nathan Harold420ceac2017-04-05 19:36:59 -0700618 enum {
619 NLMSG_HDR,
620 USERSA,
621 USERSA_PAD,
622 CRYPT,
623 CRYPT_PAD,
624 AUTH,
625 AUTH_PAD,
626 ENCAP,
627 ENCAP_PAD,
628 iovLen
629 };
Nathan Harold1a371532017-01-30 12:30:48 -0800630
631 iovec iov[] = {
632 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
633 {&usersa, 0}, // main usersa_info struct
634 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
635 {&crypt, 0}, // adjust size if crypt algo is present
636 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
637 {&auth, 0}, // adjust size if auth algo is present
638 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold420ceac2017-04-05 19:36:59 -0700639 {&encap, 0}, // adjust size if auth algo is present
640 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold1a371532017-01-30 12:30:48 -0800641 };
642
643 int len;
644 len = iov[USERSA].iov_len = fillUserSaInfo(record, &usersa);
645 iov[USERSA_PAD].iov_len = NLMSG_ALIGN(len) - len;
646
647 len = iov[CRYPT].iov_len = fillNlAttrXfrmAlgoEnc(record.crypt, &crypt);
648 iov[CRYPT_PAD].iov_len = NLA_ALIGN(len) - len;
649
650 len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
651 iov[AUTH_PAD].iov_len = NLA_ALIGN(len) - len;
652
Nathan Harold420ceac2017-04-05 19:36:59 -0700653 len = iov[ENCAP].iov_len = fillNlAttrXfrmEncapTmpl(record, &encap);
654 iov[ENCAP_PAD].iov_len = NLA_ALIGN(len) - len;
Nathan Harold1a371532017-01-30 12:30:48 -0800655 return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
656}
657
658int XfrmController::fillNlAttrXfrmAlgoEnc(const XfrmAlgo& inAlgo, nlattr_algo_crypt* algo) {
659 int len = NLA_HDRLEN + sizeof(xfrm_algo);
660 strncpy(algo->crypt.alg_name, inAlgo.name.c_str(), sizeof(algo->crypt.alg_name));
661 algo->crypt.alg_key_len = inAlgo.key.size() * 8; // bits
662 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
663 len += inAlgo.key.size();
664 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_CRYPT, len);
665 return len;
666}
667
668int XfrmController::fillNlAttrXfrmAlgoAuth(const XfrmAlgo& inAlgo, nlattr_algo_auth* algo) {
669 int len = NLA_HDRLEN + sizeof(xfrm_algo_auth);
670 strncpy(algo->auth.alg_name, inAlgo.name.c_str(), sizeof(algo->auth.alg_name));
671 algo->auth.alg_key_len = inAlgo.key.size() * 8; // bits
672
673 // This is the extra field for ALG_AUTH_TRUNC
674 algo->auth.alg_trunc_len = inAlgo.truncLenBits;
675
676 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
677 len += inAlgo.key.size();
678
679 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_AUTH_TRUNC, len);
680 return len;
681}
682
Nathan Harold420ceac2017-04-05 19:36:59 -0700683int XfrmController::fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl) {
684 if (record.encap.type == XfrmEncapType::NONE) {
685 return 0;
686 }
687
688 int len = NLA_HDRLEN + sizeof(xfrm_encap_tmpl);
689 tmpl->tmpl.encap_type = static_cast<uint16_t>(record.encap.type);
690 tmpl->tmpl.encap_sport = htons(record.encap.srcPort);
691 tmpl->tmpl.encap_dport = htons(record.encap.dstPort);
692 fillXfrmNlaHdr(&tmpl->hdr, XFRMA_ENCAP, len);
693 return len;
694}
695
Nathan Harold1a371532017-01-30 12:30:48 -0800696int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
697 fillTransportModeSelector(record, &usersa->sel);
698
699 usersa->id.proto = IPPROTO_ESP;
700 usersa->id.spi = record.spi;
701 usersa->id.daddr = record.dstAddr;
702
703 usersa->saddr = record.srcAddr;
704
705 fillXfrmLifetimeDefaults(&usersa->lft);
706 fillXfrmCurLifetimeDefaults(&usersa->curlft);
707 memset(&usersa->stats, 0, sizeof(usersa->stats)); // leave stats zeroed out
708 usersa->reqid = record.transformId;
709 usersa->family = record.addrFamily;
710 usersa->mode = static_cast<uint8_t>(record.mode);
711 usersa->replay_window = REPLAY_WINDOW_SIZE;
712 usersa->flags = 0; // TODO: should we actually set flags, XFRM_SA_XFLAG_DONT_ENCAP_DSCP?
713 return sizeof(*usersa);
714}
715
716int XfrmController::fillUserSaId(const XfrmSaId& record, xfrm_usersa_id* said) {
717 said->daddr = record.dstAddr;
718 said->spi = record.spi;
719 said->family = record.addrFamily;
720 said->proto = IPPROTO_ESP;
721
722 return sizeof(*said);
723}
724
725int XfrmController::deleteSecurityAssociation(const XfrmSaId& record, const XfrmSocket& sock) {
726 xfrm_usersa_id said{};
727
728 enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
729
730 iovec iov[] = {
731 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
732 {&said, 0}, // main usersa_info struct
733 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
734 };
735
736 int len;
737 len = iov[USERSAID].iov_len = fillUserSaId(record, &said);
738 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
739
740 return sock.sendMessage(XFRM_MSG_DELSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
741}
742
743int XfrmController::allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
744 uint32_t* outSpi, const XfrmSocket& sock) {
745 xfrm_userspi_info spiInfo{};
746
747 enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
748
749 iovec iov[] = {
750 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
751 {&spiInfo, 0}, // main userspi_info struct
752 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
753 };
754
755 int len;
756 if (fillUserSaInfo(record, &spiInfo.info) == 0) {
757 ALOGE("Failed to fill transport SA Info");
758 }
759
760 len = iov[USERSAID].iov_len = sizeof(spiInfo);
761 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
762
763 RandomSpi spiGen = RandomSpi(minSpi, maxSpi);
764 int spi, ret;
765 while ((spi = spiGen.next()) != INVALID_SPI) {
766 spiInfo.min = spi;
767 spiInfo.max = spi;
768 ret = sock.sendMessage(XFRM_MSG_ALLOCSPI, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
769
770 /* If the SPI is in use, we'll get ENOENT */
771 if (ret == -ENOENT)
772 continue;
773
774 if (ret == 0) {
775 *outSpi = spi;
Nathan Harold420ceac2017-04-05 19:36:59 -0700776 ALOGD("Allocated an SPI: %x", *outSpi);
Nathan Harold1a371532017-01-30 12:30:48 -0800777 } else {
778 *outSpi = INVALID_SPI;
779 ALOGE("SPI Allocation Failed with error %d", ret);
780 }
781
782 return ret;
783 }
784
785 // Should always be -ENOENT if we get here
786 return ret;
787}
788
789int XfrmController::fillTransportModeUserSpInfo(const XfrmSaInfo& record,
790 xfrm_userpolicy_info* usersp) {
791 fillTransportModeSelector(record, &usersp->sel);
792 fillXfrmLifetimeDefaults(&usersp->lft);
793 fillXfrmCurLifetimeDefaults(&usersp->curlft);
Nathan Harold420ceac2017-04-05 19:36:59 -0700794 /* if (index) index & 0x3 == dir -- must be true
795 * xfrm_user.c:verify_newpolicy_info() */
Nathan Harold1a371532017-01-30 12:30:48 -0800796 usersp->index = 0;
797 usersp->dir = static_cast<uint8_t>(record.direction);
798 usersp->action = XFRM_POLICY_ALLOW;
799 usersp->flags = XFRM_POLICY_LOCALOK;
800 usersp->share = XFRM_SHARE_UNIQUE;
801 return sizeof(*usersp);
802}
803
804int XfrmController::fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl) {
805 tmpl->id.daddr = record.dstAddr;
806 tmpl->id.spi = record.spi;
807 tmpl->id.proto = IPPROTO_ESP;
808
809 tmpl->family = record.addrFamily;
810 tmpl->saddr = record.srcAddr;
811 tmpl->reqid = record.transformId;
812 tmpl->mode = static_cast<uint8_t>(record.mode);
813 tmpl->share = XFRM_SHARE_UNIQUE;
814 tmpl->optional = 0; // if this is true, then a failed state lookup will be considered OK:
815 // http://lxr.free-electrons.com/source/net/xfrm/xfrm_policy.c#L1492
816 tmpl->aalgos = ALGO_MASK_AUTH_ALL; // TODO: if there's a bitmask somewhere of
817 // algos, we should find it and apply it.
818 // I can't find one.
819 tmpl->ealgos = ALGO_MASK_CRYPT_ALL; // TODO: if there's a bitmask somewhere...
820 return 0;
821}
822
823} // namespace net
824} // namespace android