Ver Fonte

minor changes

ambrop7 há 15 anos atrás
pai
commit
0557db2ac5

+ 19 - 6
client/DatagramPeerIO.c

@@ -56,6 +56,7 @@ int init_persistent_io (DatagramPeerIO *o, btime_t latency, PacketPassInterface
     
     // init assembler
     if (!FragmentProtoAssembler_Init(&o->recv_assembler, o->spproto_payload_mtu, recv_userif, 1, fragmentproto_max_chunks_for_frame(o->spproto_payload_mtu, o->payload_mtu), BReactor_PendingGroup(o->reactor))) {
+        BLog(BLOG_ERROR, "FragmentProtoAssembler_Init failed");
         goto fail0;
     }
     
@@ -64,6 +65,7 @@ int init_persistent_io (DatagramPeerIO *o, btime_t latency, PacketPassInterface
     
     // init decoder
     if (!SPProtoDecoder_Init(&o->recv_decoder, PacketPassNotifier_GetInput(&o->recv_notifier), o->sp_params, 2, BReactor_PendingGroup(o->reactor))) {
+        BLog(BLOG_ERROR, "SPProtoDecoder_Init failed");
         goto fail1;
     }
     
@@ -72,6 +74,7 @@ int init_persistent_io (DatagramPeerIO *o, btime_t latency, PacketPassInterface
     
     // init buffer
     if (!SinglePacketBuffer_Init(&o->recv_buffer, PacketRecvConnector_GetOutput(&o->recv_connector), SPProtoDecoder_GetInput(&o->recv_decoder), BReactor_PendingGroup(o->reactor))) {
+        BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
         goto fail2;
     }
     
@@ -81,7 +84,7 @@ int init_persistent_io (DatagramPeerIO *o, btime_t latency, PacketPassInterface
     FragmentProtoDisassembler_Init(&o->send_disassembler, o->reactor, o->payload_mtu, o->spproto_payload_mtu, -1, latency);
     
     // init encoder
-    if (!SPProtoEncoder_Init(&o->send_encoder, o->sp_params, FragmentProtoDisassembler_GetOutput(&o->send_disassembler), BReactor_PendingGroup(o->reactor))) {
+    if (!SPProtoEncoder_Init(&o->send_encoder, FragmentProtoDisassembler_GetOutput(&o->send_disassembler), o->sp_params, BReactor_PendingGroup(o->reactor))) {
         BLog(BLOG_ERROR, "SPProtoEncoder_Init failed");
         goto fail3;
     }
@@ -277,10 +280,8 @@ void send_encoder_notifier_handler (DatagramPeerIO *o, uint8_t *data, int data_l
 int DatagramPeerIO_Init (DatagramPeerIO *o, BReactor *reactor, int payload_mtu, int socket_mtu, struct spproto_security_params sp_params, btime_t latency, PacketPassInterface *recv_userif)
 {
     ASSERT(payload_mtu >= 0)
-    ASSERT(payload_mtu <= UINT16_MAX)
     ASSERT(socket_mtu >= 0)
-    ASSERT(spproto_validate_security_params(sp_params))
-    ASSERT(spproto_payload_mtu_for_carrier_mtu(sp_params, socket_mtu) > sizeof(struct fragmentproto_chunk_header))
+    spproto_assert_security_params(sp_params);
     ASSERT(PacketPassInterface_GetMTU(recv_userif) >= payload_mtu)
     
     // set parameters
@@ -288,11 +289,23 @@ int DatagramPeerIO_Init (DatagramPeerIO *o, BReactor *reactor, int payload_mtu,
     o->payload_mtu = payload_mtu;
     o->sp_params = sp_params;
     
+    // check payload MTU (for FragmentProto)
+    if (o->payload_mtu > UINT16_MAX) {
+        BLog(BLOG_ERROR, "payload MTU is too big");
+        goto fail1;
+    }
+    
     // calculate SPProto payload MTU
-    o->spproto_payload_mtu = spproto_payload_mtu_for_carrier_mtu(o->sp_params, socket_mtu);
+    if ((o->spproto_payload_mtu = spproto_payload_mtu_for_carrier_mtu(o->sp_params, socket_mtu)) <= (int)sizeof(struct fragmentproto_chunk_header)) {
+        BLog(BLOG_ERROR, "socket MTU is too small");
+        goto fail1;
+    }
     
     // calculate effective socket MTU
-    o->effective_socket_mtu = spproto_carrier_mtu_for_payload_mtu(o->sp_params, o->spproto_payload_mtu);
+    if ((o->effective_socket_mtu = spproto_carrier_mtu_for_payload_mtu(o->sp_params, o->spproto_payload_mtu)) < 0) {
+        BLog(BLOG_ERROR, "spproto_carrier_mtu_for_payload_mtu failed !?");
+        goto fail1;
+    }
     
     // set no OTP warning handler
     if (SPPROTO_HAVE_OTP(o->sp_params)) {

+ 1 - 1
client/DatagramPeerIO.h

@@ -134,7 +134,7 @@ typedef struct {
  * @param socket_mtu maximum datagram size for the socket. Must be >=0. Must be large enough so it is possible to
  *                   send a FragmentProto chunk with one byte of data over SPProto, i.e. the following has to hold:
  *                   spproto_payload_mtu_for_carrier_mtu(sp_params, socket_mtu) > sizeof(struct fragmentproto_chunk_header)
- * @param sp_params SPProto security parameters. Must be valid according to {@link spproto_validate_security_params}.
+ * @param sp_params SPProto security parameters
  * @param latency latency parameter to {@link FragmentProtoDisassembler_Init}.
  * @param recv_userif interface to pass received packets to the user. Its MTU must be >=payload_mtu.
  * @return 1 on success, 0 on failure

+ 3 - 3
client/PasswordSender.c

@@ -69,15 +69,15 @@ void PasswordSender_Init (PasswordSender *o, uint64_t password, int ssl, BSocket
     // init sink
     StreamPassInterface *sink_if;
     if (o->ssl) {
-        PRStreamSink_Init(&o->sink.ssl, FlowErrorReporter_Create(&o->domain, COMPONENT_SINK), o->ssl_bprfd,  BReactor_PendingGroup(reactor));
+        PRStreamSink_Init(&o->sink.ssl, FlowErrorReporter_Create(&o->domain, COMPONENT_SINK), o->ssl_bprfd, BReactor_PendingGroup(reactor));
         sink_if = PRStreamSink_GetInput(&o->sink.ssl);
     } else {
-        StreamSocketSink_Init(&o->sink.plain, FlowErrorReporter_Create(&o->domain, COMPONENT_SINK), o->plain_sock,  BReactor_PendingGroup(reactor));
+        StreamSocketSink_Init(&o->sink.plain, FlowErrorReporter_Create(&o->domain, COMPONENT_SINK), o->plain_sock, BReactor_PendingGroup(reactor));
         sink_if = StreamSocketSink_GetInput(&o->sink.plain);
     }
     
     // init PacketStreamSender
-    PacketStreamSender_Init(&o->pss, sink_if, sizeof(o->password),  BReactor_PendingGroup(reactor));
+    PacketStreamSender_Init(&o->pss, sink_if, sizeof(o->password), BReactor_PendingGroup(reactor));
     
     // init SinglePacketSender
     SinglePacketSender_Init(&o->sps, (uint8_t *)&o->password, sizeof(o->password), PacketStreamSender_GetInput(&o->pss), (SinglePacketSender_handler)sent_handler, o, BReactor_PendingGroup(reactor));

+ 6 - 0
client/StreamPeerIO.c

@@ -632,6 +632,12 @@ int StreamPeerIO_Init (
     pio->handler_error = handler_error;
     pio->user = user;
     
+    // check payload MTU
+    if (pio->payload_mtu > PACKETPROTO_MAXPAYLOAD) {
+        BLog(BLOG_ERROR, "payload MTU is too large");
+        goto fail0;
+    }
+    
     // init persistent I/O modules
     if (!init_persistent_io(pio, user_recv_if)) {
         goto fail0;

+ 24 - 19
client/client.c

@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <limits.h>
 
 #include <protocol/msgproto.h>
 #include <protocol/addr.h>
@@ -415,7 +416,7 @@ int main (int argc, char *argv[])
     // setup signal handler
     if (!BSignal_Init(&ss, signal_handler, NULL)) {
         BLog(BLOG_ERROR, "BSignal_Init failed");
-        goto fail1b;
+        goto fail2;
     }
     
     if (options.ssl) {
@@ -425,35 +426,35 @@ int main (int argc, char *argv[])
         // register local NSPR file types
         if (!DummyPRFileDesc_GlobalInit()) {
             BLog(BLOG_ERROR, "DummyPRFileDesc_GlobalInit failed");
-            goto fail2;
+            goto fail3;
         }
         if (!BSocketPRFileDesc_GlobalInit()) {
             BLog(BLOG_ERROR, "BSocketPRFileDesc_GlobalInit failed");
-            goto fail2;
+            goto fail3;
         }
         
         // init NSS
         if (NSS_Init(options.nssdb) != SECSuccess) {
             BLog(BLOG_ERROR, "NSS_Init failed (%d)", (int)PR_GetError());
-            goto fail2;
+            goto fail3;
         }
         
         // set cipher policy
         if (NSS_SetDomesticPolicy() != SECSuccess) {
             BLog(BLOG_ERROR, "NSS_SetDomesticPolicy failed (%d)", (int)PR_GetError());
-            goto fail3;
+            goto fail4;
         }
         
         // init server cache
         if (SSL_ConfigServerSessionIDCache(0, 0, 0, NULL) != SECSuccess) {
             BLog(BLOG_ERROR, "SSL_ConfigServerSessionIDCache failed (%d)", (int)PR_GetError());
-            goto fail3;
+            goto fail4;
         }
         
         // open server certificate and private key
         if (!open_nss_cert_and_key(options.client_cert_name, &client_cert, &client_key)) {
             BLog(BLOG_ERROR, "Cannot open certificate and key");
-            goto fail4;
+            goto fail5;
         }
     }
     
@@ -468,7 +469,7 @@ int main (int argc, char *argv[])
                 (options.peer_ssl ? client_key : NULL)
             )) {
                 BLog(BLOG_ERROR, "PasswordListener_Init failed");
-                goto fail5;
+                goto fail6;
             }
             num_listeners++;
         }
@@ -477,7 +478,7 @@ int main (int argc, char *argv[])
     // init device
     if (!BTap_Init(&device.btap, &ss, options.tapdev, device_error_handler, NULL, 0)) {
         BLog(BLOG_ERROR, "BTap_Init failed");
-        goto fail5;
+        goto fail6;
     }
     
     // remember device MTU
@@ -488,13 +489,17 @@ int main (int argc, char *argv[])
     // init device input
     if (!DataProtoDevice_Init(&device.input_dpd, BTap_GetOutput(&device.btap), device_input_dpd_handler, NULL, &ss)) {
         BLog(BLOG_ERROR, "DataProtoDevice_Init failed");
-        goto fail5a;
+        goto fail7;
     }
     
     // init device output
     PacketPassFairQueue_Init(&device.output_queue, BTap_GetInput(&device.btap), BReactor_PendingGroup(&ss), 1, 1);
     
     // calculate data MTU
+    if (device.mtu > INT_MAX - DATAPROTO_MAX_OVERHEAD) {
+        BLog(BLOG_ERROR, "Device MTU is too large");
+        goto fail8;
+    }
     data_mtu = DATAPROTO_MAX_OVERHEAD + device.mtu;
     
     // init peers list
@@ -519,7 +524,7 @@ int main (int argc, char *argv[])
         server_handler_error, server_handler_ready, server_handler_newclient, server_handler_endclient, server_handler_message
     )) {
         BLog(BLOG_ERROR, "ServerConnection_Init failed");
-        goto fail10;
+        goto fail9;
     }
     
     // enter event loop
@@ -557,33 +562,33 @@ int main (int argc, char *argv[])
     }
     
     ServerConnection_Free(&server);
-fail10:
+fail9:
     FrameDecider_Free(&frame_decider);
+fail8:
     PacketPassFairQueue_Free(&device.output_queue);
     DataProtoDevice_Free(&device.input_dpd);
-fail5a:
+fail7:
     BTap_Free(&device.btap);
-fail5:
+fail6:
     if (options.transport_mode == TRANSPORT_MODE_TCP) {
         while (num_listeners-- > 0) {
             PasswordListener_Free(&listeners[num_listeners]);
         }
     }
-fail4a:
     if (options.ssl) {
         CERT_DestroyCertificate(client_cert);
         SECKEY_DestroyPrivateKey(client_key);
-fail4:
+fail5:
         ASSERT_FORCE(SSL_ShutdownServerSessionIDCache() == SECSuccess)
-fail3:
+fail4:
         SSL_ClearSessionCache();
         ASSERT_FORCE(NSS_Shutdown() == SECSuccess)
-fail2:
+fail3:
         ASSERT_FORCE(PR_Cleanup() == PR_SUCCESS)
         PL_ArenaFinish();
     }
     BSignal_Finish();
-fail1b:
+fail2:
     BReactor_Free(&ss);
 fail1:
     BLog(BLOG_NOTICE, "exiting");

+ 1 - 3
flow/FragmentProtoDisassembler.c

@@ -97,7 +97,6 @@ static void write_chunks (FragmentProtoDisassembler *o)
 static void input_handler_send (FragmentProtoDisassembler *o, uint8_t *data, int data_len)
 {
     ASSERT(data_len >= 0)
-    ASSERT(data_len <= o->input_mtu)
     ASSERT(o->in_len == -1)
     
     // set input packet
@@ -161,13 +160,12 @@ void FragmentProtoDisassembler_Init (FragmentProtoDisassembler *o, BReactor *rea
     
     // init arguments
     o->reactor = reactor;
-    o->input_mtu = input_mtu;
     o->output_mtu = output_mtu;
     o->chunk_mtu = chunk_mtu;
     o->latency = latency;
     
     // init input
-    PacketPassInterface_Init(&o->input, o->input_mtu, (PacketPassInterface_handler_send)input_handler_send, o, BReactor_PendingGroup(reactor));
+    PacketPassInterface_Init(&o->input, input_mtu, (PacketPassInterface_handler_send)input_handler_send, o, BReactor_PendingGroup(reactor));
     PacketPassInterface_EnableCancel(&o->input, (PacketPassInterface_handler_cancel)input_handler_cancel);
     
     // init output

+ 1 - 2
flow/FragmentProtoDisassembler.h

@@ -46,7 +46,6 @@
  */
 typedef struct {
     BReactor *reactor;
-    int input_mtu;
     int output_mtu;
     int chunk_mtu;
     btime_t latency;
@@ -67,7 +66,7 @@ typedef struct {
  *
  * @param o the object
  * @param reactor reactor we live in
- * @param input_mtu maximum input packet size. Must be >=0 and <2^16
+ * @param input_mtu maximum input packet size. Must be >=0 and <=UINT16_MAX.
  * @param output_mtu maximum output packet size. Must be >sizeof(struct fragmentproto_chunk_header).
  * @param chunk_mtu maximum chunk size. Must be >0, or <0 for no explicit limit.
  * @param latency maximum time a pending output packet with some data can wait for more data

+ 2 - 1
flow/SPProtoDecoder.c

@@ -169,7 +169,8 @@ static void output_handler_done (SPProtoDecoder *o)
 
 int SPProtoDecoder_Init (SPProtoDecoder *o, PacketPassInterface *output, struct spproto_security_params sp_params, int num_otp_seeds, BPendingGroup *pg)
 {
-    ASSERT(spproto_validate_security_params(sp_params))
+    spproto_assert_security_params(sp_params);
+    ASSERT(spproto_carrier_mtu_for_payload_mtu(sp_params, PacketPassInterface_GetMTU(output)) >= 0)
     ASSERT(!SPPROTO_HAVE_OTP(sp_params) || num_otp_seeds >= 2)
     
     // init arguments

+ 3 - 2
flow/SPProtoDecoder.h

@@ -61,8 +61,9 @@ typedef struct {
  * Initializes the object.
  *
  * @param o the object
- * @param output output interface
- * @param sp_params CCProto parameters. Must be valid.
+ * @param output output interface. Its MTU must not be too large, i.e. this must hold:
+ *               spproto_carrier_mtu_for_payload_mtu(sp_params, output MTU) >= 0
+ * @param sp_params SPProto parameters
  * @param encryption_key if using encryption, the encryption key
  * @param num_otp_seeds if using OTPs, how many OTP seeds to keep for checking
  *                      receiving packets. Must be >=2 if using OTPs.

+ 13 - 24
flow/SPProtoEncoder.c

@@ -51,8 +51,8 @@ static int encode_packet (SPProtoEncoder *o)
     
     ASSERT(o->in_len <= o->input_mtu)
     
-    // plaintext is either output packet or our buffer
-    uint8_t *plaintext = (!SPPROTO_HAVE_ENCRYPTION(o->sp_params) ? o->out : o->buf);
+    // determine plaintext location
+    uint8_t *plaintext = (SPPROTO_HAVE_ENCRYPTION(o->sp_params) ? o->buf : o->out);
     
     // plaintext begins with header
     uint8_t *header = plaintext;
@@ -62,7 +62,7 @@ static int encode_packet (SPProtoEncoder *o)
     
     // write OTP
     if (SPPROTO_HAVE_OTP(o->sp_params)) {
-        struct spproto_otpdata *header_otpd = (struct spproto_otpdata *)(header + SPPROTO_HEADER_OTPDATA_OFF(o->group->sp_params));
+        struct spproto_otpdata *header_otpd = (struct spproto_otpdata *)(header + SPPROTO_HEADER_OTPDATA_OFF(o->sp_params));
         header_otpd->seed_id = htol16(o->otpgen_seed_id);
         header_otpd->otp = OTPGenerator_GetOTP(&o->otpgen);
     }
@@ -105,18 +105,6 @@ static int encode_packet (SPProtoEncoder *o)
         out_len = plaintext_len;
     }
     
-    return out_len;
-}
-
-static void do_encode (SPProtoEncoder *o)
-{
-    ASSERT(o->in_len >= 0)
-    ASSERT(o->out_have)
-    ASSERT(can_encode(o))
-    
-    // encode
-    int out_len = encode_packet(o);
-    
     // finish packet
     o->in_len = -1;
     o->out_have = 0;
@@ -126,7 +114,7 @@ static void do_encode (SPProtoEncoder *o)
 static void maybe_encode (SPProtoEncoder *o)
 {
     if (o->in_len >= 0 && o->out_have && can_encode(o)) {
-        do_encode(o);
+        encode_packet(o);
     }
 }
 
@@ -141,32 +129,33 @@ static void output_handler_recv (SPProtoEncoder *o, uint8_t *data)
     o->out = data;
     
     // determine plaintext location
-    uint8_t *plaintext = (!SPPROTO_HAVE_ENCRYPTION(o->sp_params) ? o->out : o->buf);
+    uint8_t *plaintext = (SPPROTO_HAVE_ENCRYPTION(o->sp_params) ? o->buf : o->out);
     
     // schedule receive
     PacketRecvInterface_Receiver_Recv(o->input, plaintext + SPPROTO_HEADER_LEN(o->sp_params));
 }
 
-static void input_handler_done (SPProtoEncoder *o, int in_len)
+static void input_handler_done (SPProtoEncoder *o, int data_len)
 {
-    ASSERT(in_len >= 0)
-    ASSERT(in_len <= o->input_mtu)
+    ASSERT(data_len >= 0)
+    ASSERT(data_len <= o->input_mtu)
     ASSERT(o->in_len == -1)
     ASSERT(o->out_have)
     DebugObject_Access(&o->d_obj);
     
     // remember input packet
-    o->in_len = in_len;
+    o->in_len = data_len;
     
     // encode if possible
     if (can_encode(o)) {
-        do_encode(o);
+        encode_packet(o);
     }
 }
 
-int SPProtoEncoder_Init (SPProtoEncoder *o, struct spproto_security_params sp_params, PacketRecvInterface *input, BPendingGroup *pg)
+int SPProtoEncoder_Init (SPProtoEncoder *o, PacketRecvInterface *input, struct spproto_security_params sp_params, BPendingGroup *pg)
 {
-    ASSERT(spproto_validate_security_params(sp_params))
+    spproto_assert_security_params(sp_params);
+    ASSERT(spproto_carrier_mtu_for_payload_mtu(sp_params, PacketRecvInterface_GetMTU(input)) >= 0)
     
     // init parameters
     o->sp_params = sp_params;

+ 4 - 3
flow/SPProtoEncoder.h

@@ -68,12 +68,13 @@ typedef struct {
  * The object is initialized in blocked state.
  *
  * @param o the object
- * @param sp_params SPProto security parameters. Must be valid according to {@link spproto_validate_security_params}.
- * @param input input interface
+ * @param input input interface. Its MTU must not be too large, i.e. this must hold:
+ *              spproto_carrier_mtu_for_payload_mtu(sp_params, input MTU) >= 0
+ * @param sp_params SPProto security parameters
  * @param pg pending group
  * @return 1 on success, 0 on failure
  */
-int SPProtoEncoder_Init (SPProtoEncoder *o, struct spproto_security_params sp_params, PacketRecvInterface *input, BPendingGroup *pg) WARN_UNUSED;
+int SPProtoEncoder_Init (SPProtoEncoder *o, PacketRecvInterface *input, struct spproto_security_params sp_params, BPendingGroup *pg) WARN_UNUSED;
 
 /**
  * Frees the object.

+ 22 - 17
protocol/spproto.h

@@ -51,6 +51,7 @@
 #define BADVPN_PROTOCOL_SPPROTO_H
 
 #include <stdint.h>
+#include <limits.h>
 
 #include <misc/debug.h>
 #include <misc/balign.h>
@@ -117,34 +118,30 @@ struct spproto_otpdata {
 #define SPPROTO_HEADER_LEN(_params) (SPPROTO_HEADER_HASH_OFF(_params) + SPPROTO_HEADER_HASH_LEN(_params))
 
 /**
- * Checks if the given SPProto security parameters are valid.
+ * Asserts that the given SPProto security parameters are valid.
  * 
- * @param params security parameters to check
- * @return 1 if valid, 0 if not
+ * @param params security parameters
  */
-static int spproto_validate_security_params (struct spproto_security_params params)
+static void spproto_assert_security_params (struct spproto_security_params params)
 {
-    return (
-        (params.hash_mode == SPPROTO_HASH_MODE_NONE || BHash_type_valid(params.hash_mode)) &&
-        (params.encryption_mode == SPPROTO_ENCRYPTION_MODE_NONE || BEncryption_cipher_valid(params.encryption_mode)) &&
-        (params.otp_mode == SPPROTO_OTP_MODE_NONE || BEncryption_cipher_valid(params.otp_mode)) &&
-        (params.otp_mode == SPPROTO_OTP_MODE_NONE || params.otp_num > 0)
-    );
+    ASSERT(params.hash_mode == SPPROTO_HASH_MODE_NONE || BHash_type_valid(params.hash_mode))
+    ASSERT(params.encryption_mode == SPPROTO_ENCRYPTION_MODE_NONE || BEncryption_cipher_valid(params.encryption_mode))
+    ASSERT(params.otp_mode == SPPROTO_OTP_MODE_NONE || BEncryption_cipher_valid(params.otp_mode))
+    ASSERT(params.otp_mode == SPPROTO_OTP_MODE_NONE || params.otp_num > 0)
 }
 
 /**
  * Calculates the maximum payload size for SPProto given the
  * security parameters and the maximum encoded packet size.
  * 
- * @param params security parameters Must be valid according to
- *               {@link spproto_validate_security_params}.
+ * @param params security parameters
  * @param carrier_mtu maximum encoded packet size. Must be >=0.
  * @return maximum payload size. Negative means is is impossible
  *         to encode anything.
  */
 static int spproto_payload_mtu_for_carrier_mtu (struct spproto_security_params params, int carrier_mtu)
 {
-    ASSERT(spproto_validate_security_params(params))
+    spproto_assert_security_params(params);
     ASSERT(carrier_mtu >= 0)
     
     if (params.encryption_mode == SPPROTO_ENCRYPTION_MODE_NONE) {
@@ -159,20 +156,28 @@ static int spproto_payload_mtu_for_carrier_mtu (struct spproto_security_params p
  * Calculates the maximum encoded packet size for SPProto given the
  * security parameters and the maximum payload size.
  * 
- * @param params security parameters Must be valid according to
- *               {@link spproto_validate_security_params}.
+ * @param params security parameters
  * @param payload_mtu maximum payload size. Must be >=0.
- * @return maximum encoded packet size
+ * @return maximum encoded packet size, -1 if payload_mtu is too large
  */
 static int spproto_carrier_mtu_for_payload_mtu (struct spproto_security_params params, int payload_mtu)
 {
-    ASSERT(spproto_validate_security_params(params))
+    spproto_assert_security_params(params);
     ASSERT(payload_mtu >= 0)
     
     if (params.encryption_mode == SPPROTO_ENCRYPTION_MODE_NONE) {
+        if (payload_mtu > INT_MAX - SPPROTO_HEADER_LEN(params)) {
+            return -1;
+        }
+        
         return (SPPROTO_HEADER_LEN(params) + payload_mtu);
     } else {
         int block_size = BEncryption_cipher_block_size(params.encryption_mode);
+        
+        if (payload_mtu > INT_MAX - (block_size + SPPROTO_HEADER_LEN(params) + block_size)) {
+            return -1;
+        }
+        
         return (block_size + BALIGN_UP_N((SPPROTO_HEADER_LEN(params) + payload_mtu + 1), block_size));
     }
 }