summaryrefslogtreecommitdiff
path: root/gpxe/src/crypto/ssl_constructs.h
blob: ab3aa70372f18319ce9bd88c5dc239b557948193 (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
// Note: This file still needs some work.
// Note: I had to redefine the enums to a set of const values,
//   so that the size of the variable would be correct.

// Typedefs
// (As defined by the SSL v3.0 RFC Draft)
// URL: http://wp.netscape.com/eng/ssl3/draft302.txt
typedef unsigned char uint8;
typedef uint8 uint16[2];
typedef uint8 uint24[3];
typedef uint8 uint32[4];
typedef uint8 uint64[8];

// Record layers
typedef struct _ProtocolVersion{
  uint8 major, minor;
} ProtocolVersion;

const ProtocolVersion version = { 3, 0 };

typedef uint8 ContentType;
const ContentType content_type_change_cipher_spec_type = 20;
const ContentType content_type_alert = 21;
const ContentType content_type_handshake = 22;
const ContentType content_type_application_data = 23;

typedef struct _SSLPlaintext{
  ContentType type;
  ProtocolVersion version;
  uint16 length; // can not exceed 2^14 bytes
  uint8 fragment[16384]; // 2^14 = 16,384 bytes
} SSLPlaintext;

typedef struct _SSLCompressed{
  ContentType type;
  ProtocolVersion version;
  uint16 length; // can not exceed 2^14 + 1024
  uint8 fragment[17408]; // SSLCompressed.length
} SSLCompressed;

typedef struct _SSLCiphertext{
  ContentType type;
  ProtocolVersion version;
  uint16 length;
  uint8 fragment; // so we have a pointer to the data, and don't have to do math
  // fragment; type GenericStreamCipher or GenericBlockCipher
} SSLCiphertext; // recast to get fragment

typedef struct _GenericStreamCipher{
  uint8 content[17408]; // SSLCompressed.length
  uint8 MAC[]; // CipherSpec.hash_size
} GenericStreamCipher;

typedef struct _SSLStreamCiphertext{
  ContentType type;
  ProtocolVersion version;
  uint16 length; // can not exceed 2^14 + 2048 = 18,456
  GenericStreamCipher fragment;
} SSLStreamCiphertext;

typedef struct _GenericBlockCipher{
  uint8 content[17408]; // SSLConpressed.length
  uint8 MAC[0]; // CipherSpec.hash_size
  // padding is used to bring the plaintext to
  // a multiple of the block cipher's block length.
  uint8 padding[0]; // GenericBlockCipher.padding_length
  uint8 padding_length;
} GenericBlockCipher;

typedef struct _SSLBlockCiphertext{
  ContentType type;
  ProtocolVersion version;
  uint16 length; // can not exceed 2^14 + 2048 = 18,456
  GenericBlockCipher fragment;
} SSLBlockCiphertext;

// Change cipher specs message
typedef struct _ChangeCipherSpec{
  enum { type_change_cipher_spec=1, type_size=255 } type;
} ChangeCipherSpec;

// Alert messages
typedef uint8 AlertLevel;
const AlertLevel alert_level_warning = 1;
const AlertLevel alert_level_fatal=2;

typedef uint8 AlertDescription;
const AlertDescription alert_description_close_notify = 0;
const AlertDescription alert_description_unexpected_message = 10;
const AlertDescription alert_description_bad_record_mac = 20;
const AlertDescription alert_description_decompression_failure = 30;
const AlertDescription alert_description_handshake_failure = 40;
const AlertDescription alert_description_no_certificate = 41;
const AlertDescription alert_description_bad_certificate = 42;
const AlertDescription alert_description_unsupported_certificate = 43;
const AlertDescription alert_description_certificate_revoked = 44;
const AlertDescription alert_description_certificate_expired = 45;
const AlertDescription alert_description_certificate_unknown = 46;
const AlertDescription alert_description_illegal_parameter = 47;

typedef struct _Alert{
  AlertLevel level;
  AlertDescription description;
} Alert;

// Handshake protocol
// What is the best way to have a generic pointer to the body struct??
typedef uint8 HandshakeType;
const HandshakeType handshake_type_hello_request = 0;
const HandshakeType handshake_type_client_hello = 1;
const HandshakeType handshake_type_server_hello = 2;
const HandshakeType handshake_type_certificate = 11;
const HandshakeType handshake_type_server_key_exchange = 12;
const HandshakeType handshake_type_certificate_request = 13;
const HandshakeType handshake_type_server_done = 14;
const HandshakeType handshake_type_certificate_verify = 15;
const HandshakeType handshake_type_client_key_exchange = 16;
const HandshakeType handshake_type_finished = 20;

typedef struct _Handshake{
  HandshakeType msg_type;
  uint24 length;
  // body; // one of HandshakeType structs
} Handshake; // generic Handshake, need to recast to get body

// Hello messages
typedef struct _HelloRequest{} HelloRequest;

typedef struct _HelloRequestHandshake{
  HandshakeType msg_type;
  uint24 length;
  HelloRequest body;
} HelloRequestHandshake;

typedef struct _Random{
  uint32 gmt_unix_time;
  uint8 random_bytes[28];
} Random;

//typedef uint8 SessionID[32]; // <0..32>
typedef uint8 SessionIDLength;
typedef uint8 SessionID;

typedef uint16 CipherSuiteLength;
typedef uint8 CipherSuite[2];

typedef uint8 CompressionMethodLength;
typedef uint8 CompressionMethod;
const CompressionMethod compression_method_null = 0;


typedef struct _ClientHello{
  ProtocolVersion client_version;
  Random random;
  SessionIDLength session_id_length;
  SessionID *session_id;
  SessionID *session_id_end;
  CipherSuiteLength *cipher_suites_length;
  CipherSuite *cipher_suites; // min size is one entry
  CipherSuite *cipher_suites_end;
  //CipherSuite cipher_suites[32768]; // <2..2^16-1> = 65,536 bytes and CipherSuite is 2 bytes
  CompressionMethodLength *compression_methods_length;
  CompressionMethod *compression_methods;
  CompressionMethod *compression_methods_end;
  //CompressionMethod *compression_methods; // min size is zero
  //CompressionMethod compression_methods[256]; // <0..2^8-1> = 256 bytes and CompressionMethod is 1 byte
} ClientHello;

typedef struct _ClientHelloHandshake{
  //HandshakeType msg_type;
  uint8 msg_type;
  uint24 length;
  ClientHello body;
} ClientHelloHandshake;

typedef struct _ServerHello{
  ProtocolVersion server_version;
  Random random;
  SessionID session_id;
  CipherSuite cipher_suite;
  CompressionMethod compression_method;
} ServerHello;

typedef struct _ServerHelloHandshake{
  HandshakeType msg_type;
  uint24 length;
  ServerHello body;
} ServerHelloHandshake;

// Server authentication and key exchange messages
typedef uint8 ASN1Cert[16777216]; // <1..2^24-1> = 16,777,216 bytes

typedef struct _Certificate{
  ASN1Cert certificate_list[1]; // <1..2^24-1> / ANS1Cert = 1
  // for some reason the size of certificate_list and ASN1Cert is the same, so only one certificate in the list
} Certificate;

typedef uint8 KeyExchangeAlgorithm;
const KeyExchangeAlgorithm key_exchange_algorithm_rsa = 0;
const KeyExchangeAlgorithm key_exchange_algorithm_diffie_hellman = 1;
const KeyExchangeAlgorithm key_exchange_algorithm_fortezza_kea = 2;

typedef struct _AnonSignature{
  struct {};
} AnonSignature;

typedef struct _RSASignature{
  uint8 md5_hash[16];
  uint8 sha_hash[20];
} RSASignature;

typedef struct _DSASignature{
  uint8 sha_hash[20];
} DSASignature;

// use union??,  make a mess to reference, but easy to make Signature type.
typedef union _Signature{ AnonSignature anon; RSASignature rsa; DSASignature dsa; } Signature;

typedef struct _ServerRSAParams{
  uint8 RSA_modulus[65536]; // <1..2^16-1> = 65,536
  uint8 RSA_exponent[65536]; // <1..2^16-1> = 65,536
} ServerRSAParams;

typedef struct _ServerDHParams{
  uint8 DH_p[65536]; // <1..2^16-1>
  uint8 DH_g[65536]; // <1..2^16-1>
  uint8 DH_Ys[65536]; // <1..2^16-1>
} ServerDHParams;

typedef struct _ServerDHKeyExchange{
  ServerDHParams params;
  Signature signed_params;
} ServerDHKeyExchange;

typedef struct _ServerRSAKeyExchange{
  ServerRSAParams params;
  Signature signed_params;
} ServerRSAKeyExchange;

typedef uint8 SignatureAlgorithm;
const SignatureAlgorithm signature_algorithm_anonymous = 0;
const SignatureAlgorithm signature_algorithm_rsa = 1;
const SignatureAlgorithm signature_algorithm_dsa = 2;

typedef uint8 CertificateType;
const CertificateType certificate_type_RSA_sign = 1;
const CertificateType certificate_type_DSS_sign = 2;
const CertificateType certificate_type_RSA_fixed_DH = 3;
const CertificateType certificate_type_DSS_fixed_DH = 4;
const CertificateType certificate_type_RSA_ephemeral_DH = 5;
const CertificateType certificate_type_DSS_ephemeral_DH = 6;
const CertificateType certificate_type_FORTEZZA_MISSI = 20;

typedef uint8 DistinguishedName[65536]; // <1..2^16-1> = 65,536

typedef struct _CertificateRequest{
  CertificateType certificate_types[256]; // <1..2^8-1>
  DistinguishedName certificate_authorities[1]; // <3...2^16-1> / DistinguishedName
  // this is another one that is odd with a list size of 1
} CertificateRequest;

typedef struct _ServerHelloDone{} ServerHelloDone;

// Client authentication and key exchange messages
typedef struct _PreMasterSecret{
  ProtocolVersion client_version;
  uint8 random[46];
} PreMasterSecret;

typedef struct _EncryptedPreMasterSecret{
  PreMasterSecret pre_master_secret;
} EncryptedPreMasterSecret;

typedef struct _RSAClientKeyExchange{
  EncryptedPreMasterSecret exchange_keys;
} RSAClientKeyExchange;

typedef uint8 PublicValueEncoding;
const PublicValueEncoding public_value_encoding_implicit = 0;
const PublicValueEncoding public_value_encoding_explicit = 1;

typedef struct _ClientDiffieHellmanPublic{
  // This is a select on PublicValueEncoding,  and I chose the larger size
  uint8 dh_public[65536]; // DH_Yc<1..2^16-1>, the dh public value
} ClientDiffieHellmanPublic;

typedef struct _DHClientKeyExhange{
  ClientDiffieHellmanPublic exchange_keys;
} DHClientKeyExchange;

typedef struct _CertificateVerify{
  Signature signature;
} CertificateVerify;

// Handshake finalization message
typedef struct _Finished{
  uint8 md5_hash[16];
  uint8 sha_hash[20];
} Finished;

// The CipherSuite
CipherSuite SSL_NULL_WITH_NULL_NULL                     = { 0x00, 0x13 };
CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA        = { 0x00, 0x0B };
CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA                 = { 0x00, 0x0C };
CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA       = { 0x00, 0x11 };
CipherSuite SSL_DH_anon_EXPORT_WITH_RC4_40_MD5          = { 0x00, 0x17 };
CipherSuite SSL_DH_anon_WITH_RC4_128_MD5                = { 0x00, 0x18 };

// The CipherSpec
typedef uint8 CipherType;
const CipherType cipher_type_stream = 0;
const CipherType cipher_type_block = 1;

typedef uint8 IsExportable;
const IsExportable is_exportable_true = 0;
const IsExportable is_exportable_false = 1;

typedef uint8 BulkCipherAlgorithm;
const BulkCipherAlgorithm bulk_cipher_algorithm_null = 0;
const BulkCipherAlgorithm bulk_cipher_algorithm_rc4 = 1;
const BulkCipherAlgorithm bulk_cipher_algorithm_rc2 = 2;
const BulkCipherAlgorithm bulk_cipher_algorithm_des = 3;
const BulkCipherAlgorithm bulk_cipher_algorithm_3des = 4;
const BulkCipherAlgorithm bulk_cipher_algorithm_des40 = 5;
const BulkCipherAlgorithm bulk_cipher_algorithm_fortezza = 6;

typedef uint8 MACAlgorithm;
const MACAlgorithm mac_algorithm_null = 0;
const MACAlgorithm mac_algorithm_md5 = 1;
const MACAlgorithm mac_algorithm_sha = 2;

typedef struct _CipherSpec{
  BulkCipherAlgorithm bulk_cipher_algorithm;
  MACAlgorithm mac_algorithm;
  CipherType cipher_type;
  IsExportable is_exportable;
  uint8 hash_size;
  uint8 key_material;
  uint8 IV_size;
} CipherSpec;