Newer
Older
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
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#define USE_SOCKETS
#include "ssl_locl.h"
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
//#define DEBUG
#define MAX_EMPTY_RECORDS 10 /* Might not be needed */
/* Read record from the underlying communication medium
* This method attempts to read and decrypt the . */
static int spp_get_record(SSL *s) {
int ssl_major,ssl_minor,al;
int enc_err,n,i,ret= -1;
SSL3_RECORD *rr;
SSL_SESSION *sess;
SPP_SLICE *slice;
SPP_CTX ctx_tmp;
SPP_CTX *spp_ctx;
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
short version;
unsigned mac_size, orig_len;
size_t extra;
unsigned empty_record_count = 0;
rr= &(s->s3->rrec);
sess=s->session;
if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
extra=SSL3_RT_MAX_EXTRA;
else
extra=0;
if (extra && !s->s3->init_extra) {
/* An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
* set after ssl3_setup_buffers() was done */
SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
return -1;
}
again:
/* check if we have the header */
if ((s->rstate != SSL_ST_READ_BODY) ||
(s->packet_length < SPP_RT_HEADER_LENGTH)) {
n=ssl3_read_n(s, SPP_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
if (n <= 0) return(n); /* error or non-blocking */
s->rstate=SSL_ST_READ_BODY;
p=s->packet;
#ifdef DEBUG
fprintf(stderr, "Received record header: ");
spp_print_buffer(p, SPP_RT_HEADER_LENGTH);
#endif
/* Pull apart the header into the SSL3_RECORD */
rr->type= *(p++);
ssl_major= *(p++);
ssl_minor= *(p++);
version=(ssl_major<<8)|ssl_minor;
n2s(p,rr->length);
/* New header fields: slice_id, proxy_id */
rr->slice_id = *(p++);
if (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
s->read_stats.handshake_bytes += SPP_RT_HEADER_LENGTH;
else
s->read_stats.header_bytes += SPP_RT_HEADER_LENGTH;
s->read_stats.bytes += rr->length + SPP_RT_HEADER_LENGTH;
#if 0
fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length);
#endif
/* Lets check version */
if (!s->first_packet) {
if (version != s->version) {
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
if ((s->version & 0xFF00) == (version & 0xFF00) && !s->enc_write_ctx && !s->write_hash)
/* Send back error using their minor version number :-) */
s->version = (unsigned short)version;
al=SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
}
if ((version>>8) != SPP_VERSION_MAJOR) {
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
goto err;
}
if (rr->length > s->s3->rbuf.len - SPP_RT_HEADER_LENGTH) {
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
goto f_err;
}
/* now s->rstate == SSL_ST_READ_BODY */
}
/* s->rstate == SSL_ST_READ_BODY, get and decode the data */
if (rr->length > s->packet_length-SPP_RT_HEADER_LENGTH) {
/* now s->packet_length == SPP_RT_HEADER_LENGTH */
i=rr->length;
n=ssl3_read_n(s,i,i,1);
if (n <= 0) return(n); /* error or non-blocking io */
/* now n == rr->length,
* and s->packet_length == SPP_RT_HEADER_LENGTH + rr->length */
}
s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
/* At this point, s->packet_length == SPP_RT_HEADER_LNGTH + rr->length,
* and we have that many bytes in s->packet
*/
rr->input= &(s->packet[SPP_RT_HEADER_LENGTH]);
/* ok, we can now read from 's->packet' data into 'rr'
* rr->input points at rr->length bytes, which
* need to be copied into rr->data by either
* the decryption or by the decompression
* When the data is 'copied' into the rr->data buffer,
* rr->input will be pointed at the new buffer */
/* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
* rr->length bytes of encrypted compressed stuff. */
/* check is not needed I believe */
if (rr->length > SPP_RT_MAX_ENCRYPTED_LENGTH+extra) {
al=SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto f_err;
}
/* decrypt in place in 'rr->input' */
rr->data=rr->input;
slice = SPP_get_slice_by_id(s, rr->slice_id);
//printf("Receiving record slice %d\n", rr->slice_id);
/* Get slice from id if it can be found. */
/*if (!slice) {
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto f_err;
} */
s->read_slice = slice;
/* Setup up the ctx for this read
* provided that it is for a slice. */
if (slice != NULL) {
#ifdef DEBUG
printf("Encrypted packet:");
spp_print_buffer(rr->data, rr->length);
#endif
/* If we are not a proxy, use temporary state. */
if (s->proxy == 1) {
spp_ctx = (SPP_CTX*)OPENSSL_malloc(sizeof(SPP_CTX));
} else {
spp_ctx = &(ctx_tmp);
}
spp_ctx->mac_length=0;
spp_ctx->integrity_mac=spp_ctx->read_mac=spp_ctx->write_mac=NULL;
s->spp_read_ctx = spp_ctx;
} else {
s->spp_read_ctx = NULL;
}
/* Send to ssp_enc for decryption. */
enc_err = s->method->ssl3_enc->enc(s,0);
/* enc_err is:
* 0: (in non-constant time) if the record is publically invalid.
* 1: if the padding is valid
* -1: if the padding is invalid */
if (enc_err == 0) {
al=SSL_AD_DECRYPTION_FAILED;
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
goto f_err;
}
#ifdef TLS_DEBUG
printf("dec %d\n",rr->length);
{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif
/*if (slice != NULL) {
printf("Slice not NULL\n");
if (EVP_MD_CTX_md(slice->read_mac->read_hash) != NULL) {
printf("MD not NULL\n");
}
}*/
/* r->length is now the compressed data plus mac */
/* We can read this record */
if ((sess != NULL) &&
(s->enc_read_ctx != NULL) &&
(slice != NULL) &&
(EVP_MD_CTX_md(slice->read_mac->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
#ifdef DEBUG
printf("Parsing 3MAC\n");
#endif
Loading
Loading full blame…