File: onwire.c

package info (click to toggle)
kronosnet 1.32-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,080 kB
  • sloc: ansic: 25,419; sh: 5,295; makefile: 664
file content (127 lines) | stat: -rw-r--r-- 4,009 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright (C) 2019-2025 Red Hat, Inc.  All rights reserved.
 *
 * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 *
 * This software licensed under LGPL-2.0+
 */

#include "config.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "crypto.h"
#include "internals.h"
#include "logging.h"
#include "common.h"
#include "transport_udp.h"
#include "transport_sctp.h"

/*
 * unencrypted packet looks like:
 *
 * | ip | protocol  | knet_header | unencrypted data                                  |
 * | onwire_len                                                                       |
 * | proto_overhead |
 *                  | data_len                                                        |
 *                                | app MTU                                           |
 *
 * encrypted packet looks like (not to scale):
 *
 * | ip | protocol  | salt | crypto(knet_header | data)      | crypto_data_pad | hash |
 * | onwire_len                                                                       |
 * | proto_overhead |
 *                  | data_len                                                        |
 *                                              | app MTU    |
 *
 * knet_h->sec_block_size is >= 0 if encryption will pad the data
 * knet_h->sec_salt_size is >= 0 if encryption is enabled
 * knet_h->sec_hash_size is >= 0 if signing is enabled
 */

/*
 * this function takes in the data that we would like to send
 * and tells us the outgoing onwire data size with crypto and
 * all the headers adjustment.
 * calling thread needs to account for protocol overhead.
 */

size_t calc_data_outlen(knet_handle_t knet_h, size_t inlen)
{
	size_t outlen = inlen, pad_len = 0;

	if (knet_h->sec_block_size) {
		/*
		 * if the crypto mechanism requires padding, calculate the padding
		 * and add it back to outlen because that's what the crypto layer
		 * would do.
		 */
		pad_len = knet_h->sec_block_size - (outlen % knet_h->sec_block_size);

		outlen = outlen + pad_len;
	}

	return outlen + knet_h->sec_salt_size + knet_h->sec_hash_size;
}

/*
 * this function takes in the data that we would like to send
 * and tells us what is the real maximum data we can send
 * accounting for headers and crypto
 * calling thread needs to account for protocol overhead.
 */

size_t calc_max_data_outlen(knet_handle_t knet_h, size_t inlen)
{
	size_t outlen = inlen, pad_len = 0;

	if (knet_h->sec_block_size) {
		/*
		 * drop both salt and hash, that leaves only the crypto data and padding
		 * we need to calculate the padding based on the real encrypted data
		 * that includes the knet_header.
		 */
		outlen = outlen - (knet_h->sec_salt_size + knet_h->sec_hash_size);

		/*
		 * if the crypto mechanism requires padding, calculate the padding
		 * and remove it, to align the data.
		 * NOTE: we need to remove pad_len + 1 because, based on testing,
		 * if we send data that are already aligned to block_size, the
		 * crypto implementations will add another block_size!
		 * so we want to make sure that our data won't add an unnecessary
		 * block_size that we need to remove later.
		 */
		pad_len = outlen % knet_h->sec_block_size;

		outlen = outlen - (pad_len + 1);

		/*
		 * add both hash and salt size back, similar to padding above,
		 * the crypto layer will add them to the outlen
		 */
		outlen = outlen + (knet_h->sec_salt_size + knet_h->sec_hash_size);
	}

	/*
	 * drop KNET_HEADER_ALL_SIZE to provide a clean application MTU
	 * and various crypto headers
	 */
	outlen = outlen - (KNET_HEADER_ALL_SIZE + knet_h->sec_salt_size + knet_h->sec_hash_size);

	return outlen;
}

/*
 * set the lowest possible value as failsafe for all links.
 * KNET_PMTUD_MIN_MTU_V4 < KNET_PMTUD_MIN_MTU_V6
 * KNET_PMTUD_OVERHEAD_V6 > KNET_PMTUD_OVERHEAD_V4
 * KNET_PMTUD_SCTP_OVERHEAD > KNET_PMTUD_UDP_OVERHEAD
 */

size_t calc_min_mtu(knet_handle_t knet_h)
{
	return calc_max_data_outlen(knet_h, KNET_PMTUD_MIN_MTU_V4 - (KNET_PMTUD_OVERHEAD_V6 + KNET_PMTUD_SCTP_OVERHEAD));
}