summaryrefslogtreecommitdiffstats
path: root/net/curvecp/protocol.h
blob: 041bf38958c5c416bf26db69eab06c1221ad9d9c (plain)
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CURVECP_PROTOCOL_H_
#define NET_CURVECP_PROTOCOL_H_

// Mike's thoughts on the protocol:
//   1) the packet layer probably should have a "close" mechanism.  although
//      some clients won't use it, it is nice to have.
//
//   2) when do we re "initiate"?  maybe connections should have an inferred
//      lifetime, and client should always re-initiate after 1min?
//
//   3) An initiate packet can cary 640B of data.  But how does the app layer
//      know that only 640B of data is available there?  This is a bit awkward?

#include "base/basictypes.h"

namespace net {

typedef unsigned char uchar;

// Messages can range in size from 16 to 1088 bytes.
const int kMinMessageLength = 16;
const int kMaxMessageLength = 1088;

// Maximum packet size.
const int kMaxPacketLength = kMaxMessageLength + 96;



// Packet layer.

// All Packets start with an 8 byte identifier.
struct Packet {
  char id[8];
};

// A HelloPacket is sent from the client to the server to establish a secure
// cookie to use when communicating with a server.
struct HelloPacket : Packet {
  uchar server_extension[16];
  uchar client_extension[16];
  uchar client_shortterm_public_key[32];
  uchar zero[64];
  uchar nonce[8];
  uchar box[80];
};

// A CookiePacket is sent from the server to the client in response to a
// HelloPacket.
struct CookiePacket : Packet {
  uchar client_extension[16];
  uchar server_extension[16];
  uchar nonce[16];
  uchar box[144];
};

// An InitiatePacket is sent from the client to the server to initiate
// the connection once a cookie has been exchanged.
struct InitiatePacket : Packet {
  uchar server_extension[16];
  uchar client_extension[16];
  uchar client_shortterm_public_key[32];
  uchar server_cookie[96];
  uchar initiate_nonce[8];

  uchar client_longterm_public_key[32];
  uchar nonce[16];
  uchar box[48];
  uchar server_name[256];

  // A message is carried here.
};

// A ClientMessagePacket contains a Message from the client to the server.
struct ClientMessagePacket : Packet {
  uchar server_extension[16];
  uchar client_extension[16];
  uchar client_shortterm_public_key[32];
  uchar nonce[8];

  // A message is carried here of at least 16 bytes.
};

// A ServerMessagePacket contains a Message from the server to the client.
struct ServerMessagePacket : Packet {
  uchar client_extension[16];
  uchar server_extension[16];
  uchar nonce[8];

  // A message is carried here of at least 16 bytes.
};




// Messaging layer.

struct Message {
  // If message_id is all zero, this Message is a pure ACK message.
  uchar message_id[4];
  // For regular messages going back and forth, last_message_received will be
  // zero.  For an ACK, it will be filled in and can be used to compute RTT.
  uchar last_message_received[4];
  uchar acknowledge_1[8];  // bytes acknowledged in the first range.
  uchar gap_1[4];          // gap between the first range and the second range.
  uchar acknowledge_2[2];  // bytes acknowledged in the second range.
  uchar gap_2[2];          // gap between the second range and the third range.
  uchar acknowledge_3[2];  // bytes acknowledged in the third range.
  uchar gap_3[2];          // gap between the third range and the fourth range.
  uchar acknowledge_4[2];  // bytes acknowledged in the fourth range.
  uchar gap_4[2];          // gap between the fourth range and the fifth range.
  uchar acknowledge_5[2];  // bytes acknowledged in the fifth range.
  uchar gap_5[2];          // gap between the fifth range and the sixth range.
  uchar acknowledge_6[2];  // bytes acknowledged in the sixth range.
  union {
    struct {
      unsigned short unused:4;
      unsigned short fail:1;
      unsigned short success:1;
      unsigned short length:10;
    } bits;
    uchar val[2];
  } size;
  uchar position[8];
  uchar padding[16];

  bool is_ack() { return *(reinterpret_cast<int32*>(message_id)) == 0; }
};

// Connection state
// TODO(mbelshe) move this to the messenger.
struct ConnectionState {
  uchar client_shortterm_public_key[32];

  // Fields we'll need going forward:
  //
  // uchar secret_key_client_short_server_short[32];
  // crypto_uint64 received_nonce;
  // crypto_uint64 sent_nonce;
  // uchar client_extension[16];
  // uchar server_extension[16];
};

void uint16_pack(uchar* dest, uint16 val);
uint16 uint16_unpack(uchar* src);
void uint32_pack(uchar* dest, uint32 val);
uint32 uint32_unpack(uchar* src);
void uint64_pack(uchar* dest, uint64 val);
uint64 uint64_unpack(uchar* src);


}  // namespace net

#endif  // NET_CURVECP_PROTOCOL_H_