Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/ssl/sslencode.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is PRIVATE to SSL.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8
9
#include "nss.h"
10
#include "prnetdb.h"
11
#include "ssl.h"
12
#include "sslimpl.h"
13
14
/* Helper function to encode an unsigned integer into a buffer. */
15
static void
16
ssl_EncodeUintX(PRUint8 *to, PRUint64 value, unsigned int bytes)
17
0
{
18
0
    PRUint64 encoded;
19
0
20
0
    PORT_Assert(bytes > 0 && bytes <= sizeof(encoded));
21
0
22
0
    encoded = PR_htonll(value);
23
0
    PORT_Memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes),
24
0
                bytes);
25
0
}
26
27
/* Grow a buffer to hold newLen bytes of data.  When used for recv/xmit buffers,
28
 * the caller must hold xmitBufLock or recvBufLock, as appropriate. */
29
SECStatus
30
sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
31
0
{
32
0
    PORT_Assert(b);
33
0
    if (b->fixed) {
34
0
        PORT_Assert(newLen <= b->space);
35
0
        if (newLen > b->space) {
36
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
37
0
            return SECFailure;
38
0
        }
39
0
        return SECSuccess;
40
0
    }
41
0
42
0
    newLen = PR_MAX(newLen, b->len + 1024);
43
0
    if (newLen > b->space) {
44
0
        unsigned char *newBuf;
45
0
        if (b->buf) {
46
0
            newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen);
47
0
        } else {
48
0
            newBuf = (unsigned char *)PORT_Alloc(newLen);
49
0
        }
50
0
        if (!newBuf) {
51
0
            return SECFailure;
52
0
        }
53
0
        b->buf = newBuf;
54
0
        b->space = newLen;
55
0
    }
56
0
    return SECSuccess;
57
0
}
58
59
SECStatus
60
sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len)
61
0
{
62
0
    SECStatus rv = sslBuffer_Grow(b, b->len + len);
63
0
    if (rv != SECSuccess) {
64
0
        return SECFailure; /* Code already set. */
65
0
    }
66
0
    PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len);
67
0
    b->len += len;
68
0
    return SECSuccess;
69
0
}
70
71
SECStatus
72
sslBuffer_AppendNumber(sslBuffer *b, PRUint64 v, unsigned int size)
73
0
{
74
0
    SECStatus rv = sslBuffer_Grow(b, b->len + size);
75
0
    if (rv != SECSuccess) {
76
0
        return SECFailure;
77
0
    }
78
0
    ssl_EncodeUintX(SSL_BUFFER_NEXT(b), v, size);
79
0
    b->len += size;
80
0
    return SECSuccess;
81
0
}
82
83
SECStatus
84
sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len,
85
                         unsigned int size)
86
0
{
87
0
    PORT_Assert(size <= 4 && size > 0);
88
0
    PORT_Assert(b);
89
0
    if (len >= (1ULL << (8 * size))) {
90
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
91
0
        return SECFailure;
92
0
    }
93
0
94
0
    if (sslBuffer_Grow(b, b->len + len + size) != SECSuccess) {
95
0
        return SECFailure;
96
0
    }
97
0
98
0
    ssl_EncodeUintX(SSL_BUFFER_NEXT(b), len, size);
99
0
    b->len += size;
100
0
    if (len != 0) {
101
0
        PORT_Assert(data);
102
0
        /* We sometimes pass NULL, 0 and memcpy() doesn't want NULL. */
103
0
        PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len);
104
0
    }
105
0
    b->len += len;
106
0
    return SECSuccess;
107
0
}
108
109
SECStatus
110
sslBuffer_AppendBuffer(sslBuffer *b, const sslBuffer *append)
111
0
{
112
0
    return sslBuffer_Append(b, append->buf, append->len);
113
0
}
114
115
SECStatus
116
sslBuffer_AppendBufferVariable(sslBuffer *b, const sslBuffer *append,
117
                               unsigned int size)
118
0
{
119
0
    return sslBuffer_AppendVariable(b, append->buf, append->len, size);
120
0
}
121
122
SECStatus
123
sslBuffer_Skip(sslBuffer *b, unsigned int size, unsigned int *savedOffset)
124
0
{
125
0
    if (sslBuffer_Grow(b, b->len + size) != SECSuccess) {
126
0
        return SECFailure;
127
0
    }
128
0
129
0
    if (savedOffset) {
130
0
        *savedOffset = b->len;
131
0
    }
132
0
    b->len += size;
133
0
    return SECSuccess;
134
0
}
135
136
/* A common problem is that a buffer is used to construct a variable length
137
 * structure of unknown length.  The length field for that structure is then
138
 * populated afterwards.  This function makes this process a little easier.
139
 *
140
 * To use this, before encoding the variable length structure, skip the spot
141
 * where the length would be using sslBuffer_Skip().  After encoding the
142
 * structure, and before encoding anything else, call this function passing the
143
 * value returned from sslBuffer_Skip() as |at| to have the length inserted.
144
 */
145
SECStatus
146
sslBuffer_InsertLength(sslBuffer *b, unsigned int at, unsigned int size)
147
0
{
148
0
    unsigned int len;
149
0
150
0
    PORT_Assert(b->len >= at + size);
151
0
    PORT_Assert(b->space >= at + size);
152
0
    len = b->len - (at + size);
153
0
154
0
    PORT_Assert(size <= 4 && size > 0);
155
0
    if (len >= (1ULL << (8 * size))) {
156
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
157
0
        return SECFailure;
158
0
    }
159
0
160
0
    ssl_EncodeUintX(SSL_BUFFER_BASE(b) + at, len, size);
161
0
    return SECSuccess;
162
0
}
163
164
void
165
sslBuffer_Clear(sslBuffer *b)
166
0
{
167
0
    if (!b->fixed) {
168
0
        if (b->buf) {
169
0
            PORT_Free(b->buf);
170
0
            b->buf = NULL;
171
0
        }
172
0
        b->space = 0;
173
0
    }
174
0
    b->len = 0;
175
0
}
176
177
SECStatus
178
sslRead_Read(sslReader *reader, unsigned int count, sslReadBuffer *out)
179
0
{
180
0
    if (!reader || !out) {
181
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
182
0
        return SECFailure;
183
0
    }
184
0
    if (reader->buf.len < reader->offset ||
185
0
        count > SSL_READER_REMAINING(reader)) {
186
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
187
0
        return SECFailure;
188
0
    }
189
0
190
0
    out->buf = SSL_READER_CURRENT(reader);
191
0
    out->len = count;
192
0
    reader->offset += count;
193
0
194
0
    return SECSuccess;
195
0
}
196
197
SECStatus
198
sslRead_ReadVariable(sslReader *reader, unsigned int sizeLen, sslReadBuffer *out)
199
0
{
200
0
    PRUint64 variableLen = 0;
201
0
    SECStatus rv = sslRead_ReadNumber(reader, sizeLen, &variableLen);
202
0
    if (rv != SECSuccess) {
203
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
204
0
        return SECFailure;
205
0
    }
206
0
    if (!variableLen) {
207
0
        // It is ok to have an empty variable.
208
0
        out->len = variableLen;
209
0
        return SECSuccess;
210
0
    }
211
0
    return sslRead_Read(reader, variableLen, out);
212
0
}
213
214
SECStatus
215
sslRead_ReadNumber(sslReader *reader, unsigned int bytes, PRUint64 *num)
216
0
{
217
0
    if (!reader || !num) {
218
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
219
0
        return SECFailure;
220
0
    }
221
0
    if (reader->buf.len < reader->offset ||
222
0
        bytes > SSL_READER_REMAINING(reader) ||
223
0
        bytes > 8) {
224
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
225
0
        return SECFailure;
226
0
    }
227
0
    unsigned int i;
228
0
    PRUint64 number = 0;
229
0
    for (i = 0; i < bytes; i++) {
230
0
        number = (number << 8) + reader->buf.buf[i + reader->offset];
231
0
    }
232
0
233
0
    reader->offset = reader->offset + bytes;
234
0
    *num = number;
235
0
    return SECSuccess;
236
0
}
237
238
/**************************************************************************
239
 * Append Handshake functions.
240
 * All these functions set appropriate error codes.
241
 * Most rely on ssl3_AppendHandshake to set the error code.
242
 **************************************************************************/
243
0
#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
244
#define MIN_SEND_BUF_LENGTH 4000
245
246
SECStatus
247
ssl3_AppendHandshake(sslSocket *ss, const void *void_src, unsigned int bytes)
248
0
{
249
0
    unsigned char *src = (unsigned char *)void_src;
250
0
    int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
251
0
    SECStatus rv;
252
0
253
0
    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* protects sendBuf. */
254
0
255
0
    if (!bytes)
256
0
        return SECSuccess;
257
0
    if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) {
258
0
        rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
259
0
                                                        PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
260
0
        if (rv != SECSuccess)
261
0
            return SECFailure; /* sslBuffer_Grow sets a memory error code. */
262
0
        room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len;
263
0
    }
264
0
265
0
    PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char *)void_src, bytes));
266
0
    rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
267
0
    if (rv != SECSuccess)
268
0
        return SECFailure; /* error code set by ssl3_UpdateHandshakeHashes */
269
0
270
0
    while (bytes > room) {
271
0
        if (room > 0)
272
0
            PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src,
273
0
                        room);
274
0
        ss->sec.ci.sendBuf.len += room;
275
0
        rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
276
0
        if (rv != SECSuccess) {
277
0
            return SECFailure; /* error code set by ssl3_FlushHandshake */
278
0
        }
279
0
        bytes -= room;
280
0
        src += room;
281
0
        room = ss->sec.ci.sendBuf.space;
282
0
        PORT_Assert(ss->sec.ci.sendBuf.len == 0);
283
0
    }
284
0
    PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, bytes);
285
0
    ss->sec.ci.sendBuf.len += bytes;
286
0
    return SECSuccess;
287
0
}
288
289
SECStatus
290
ssl3_AppendHandshakeNumber(sslSocket *ss, PRUint64 num, unsigned int lenSize)
291
0
{
292
0
    PRUint8 b[sizeof(num)];
293
0
    SSL_TRC(60, ("%d: number:", SSL_GETPID()));
294
0
    ssl_EncodeUintX(b, num, lenSize);
295
0
    return ssl3_AppendHandshake(ss, b, lenSize);
296
0
}
297
298
SECStatus
299
ssl3_AppendHandshakeVariable(sslSocket *ss, const PRUint8 *src,
300
                             unsigned int bytes, unsigned int lenSize)
301
0
{
302
0
    SECStatus rv;
303
0
304
0
    PORT_Assert((bytes < (1 << 8) && lenSize == 1) ||
305
0
                (bytes < (1L << 16) && lenSize == 2) ||
306
0
                (bytes < (1L << 24) && lenSize == 3));
307
0
308
0
    SSL_TRC(60, ("%d: append variable:", SSL_GETPID()));
309
0
    rv = ssl3_AppendHandshakeNumber(ss, bytes, lenSize);
310
0
    if (rv != SECSuccess) {
311
0
        return SECFailure; /* error code set by AppendHandshake. */
312
0
    }
313
0
    SSL_TRC(60, ("data:"));
314
0
    return ssl3_AppendHandshake(ss, src, bytes);
315
0
}
316
317
SECStatus
318
ssl3_AppendBufferToHandshake(sslSocket *ss, sslBuffer *buf)
319
0
{
320
0
    return ssl3_AppendHandshake(ss, buf->buf, buf->len);
321
0
}
322
323
SECStatus
324
ssl3_AppendBufferToHandshakeVariable(sslSocket *ss, sslBuffer *buf,
325
                                     unsigned int lenSize)
326
0
{
327
0
    return ssl3_AppendHandshakeVariable(ss, buf->buf, buf->len, lenSize);
328
0
}