Tomato 1.26
[tomato.git] / release / src / router / matrixssl / src / cipherSuite.c
blobc61724aca4e16e52456605185ffc7ba59c724cec
1 /*
2 * cipherSuite.c
3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * Wrappers for the various cipher suites.
6 * Contributors should add additional cipher suites here.
7 * Enable specific suites at compile time in matrixConfig.h
8 */
9 /*
10 * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
11 * The latest version of this code is available at http://www.matrixssl.org
13 * This software is open source; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This General Public License does NOT permit incorporating this software
19 * into proprietary programs. If you are unable to comply with the GPL, a
20 * commercial license for this software may be purchased from PeerSec Networks
21 * at http://www.peersec.com
23 * This program is distributed in WITHOUT ANY WARRANTY; without even the
24 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 * See the GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * http://www.gnu.org/copyleft/gpl.html
32 /******************************************************************************/
34 #include "matrixInternal.h"
36 /******************************************************************************/
38 Using void *ssl rather than ssl_t *ssl is a workaround for a chicken-egg
39 issue in matrixInternal.h where these function prototypes are used
40 before ssl_t is defined.
42 #ifdef USE_SHA1_MAC
43 static int32 sha1GenerateMac(void *ssl, unsigned char type, unsigned char *data,
44 int32 len, unsigned char *mac);
45 static int32 sha1VerifyMac(void *ssl, unsigned char type, unsigned char *data,
46 int32 len, unsigned char *mac);
47 #endif
49 #ifdef USE_MD5_MAC
50 static int32 md5GenerateMac(void *ssl, unsigned char type, unsigned char *data,
51 int32 len, unsigned char *mac);
52 static int32 md5VerifyMac(void *ssl, unsigned char type, unsigned char *data,
53 int32 len, unsigned char *mac);
54 #endif
56 #ifdef USE_SSL_RSA_WITH_RC4_128_MD5
57 static int32 matrixCipher4Init(sslSec_t *sec, int32 type);
58 #endif /* USE_SSL_RSA_WITH_RC4_128_MD5 */
60 #ifdef USE_SSL_RSA_WITH_RC4_128_SHA
61 static int32 matrixCipher5Init(sslSec_t *sec, int32 type);
62 #endif /* USE_SSL_RSA_WITH_RC4_128_SHA */
64 #ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
65 static int32 matrixCipherAInit(sslSec_t *sec, int32 type);
66 #endif /* USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA */
71 static int32 nullInit(sslSec_t *sec, int32 type);
72 static int32 nullEncrypt(sslCipherContext_t *ctx, unsigned char *in,
73 unsigned char *out, int32 len);
74 static int32 nullDecrypt(sslCipherContext_t *ctx, unsigned char *in,
75 unsigned char *out, int32 len);
76 static int32 nullEncryptPub(psPool_t *pool, sslRsaKey_t *key,
77 unsigned char *in, int32 inlen,
78 unsigned char *out, int32 outlen);
79 static int32 nullDecryptPriv(psPool_t *pool, sslRsaKey_t *key,
80 unsigned char *in, int32 inlen,
81 unsigned char *out, int32 outlen);
82 static int32 nullGenerateMac(void *ssl, unsigned char type, unsigned char *data,
83 int32 len, unsigned char *mac);
84 static int32 nullVerifyMac(void *ssl, unsigned char type, unsigned char *data,
85 int32 len, unsigned char *mac);
87 /******************************************************************************/
89 static sslCipherSpec_t supportedCiphers[] = {
91 New ciphers should be added here, similar to the ones below
92 These ciphers should be in order of the most desireable to the
93 least desireable ciphers to negotiate.
95 #ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
96 {SSL_RSA_WITH_3DES_EDE_CBC_SHA,
97 20, /* macSize */
98 24, /* keySize */
99 8, /* ivSize */
100 8, /* blocksize */
101 matrixCipherAInit,
102 matrix3desEncrypt,
103 matrix3desDecrypt,
104 NULL,
105 matrixRsaDecryptPub,
106 matrixRsaEncryptPub,
107 matrixRsaDecryptPriv,
108 sha1GenerateMac,
109 sha1VerifyMac},
110 #endif /* USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA */
111 #ifdef USE_SSL_RSA_WITH_RC4_128_SHA
112 {SSL_RSA_WITH_RC4_128_SHA,
113 20, /* macSize */
114 16, /* keySize */
115 0, /* ivSize */
116 1, /* blocksize */
117 matrixCipher5Init,
118 matrixArc4,
119 matrixArc4,
120 NULL,
121 matrixRsaDecryptPub,
122 matrixRsaEncryptPub,
123 matrixRsaDecryptPriv,
124 sha1GenerateMac,
125 sha1VerifyMac},
126 #endif /* USE_SSL_RSA_WITH_RC4_128_SHA */
127 #ifdef USE_SSL_RSA_WITH_RC4_128_MD5
128 {SSL_RSA_WITH_RC4_128_MD5,
129 16, /* macSize */
130 16, /* keySize */
131 0, /* ivSize */
132 1, /* blocksize */
133 matrixCipher4Init,
134 matrixArc4,
135 matrixArc4,
136 NULL,
137 matrixRsaDecryptPub,
138 matrixRsaEncryptPub,
139 matrixRsaDecryptPriv,
140 md5GenerateMac,
141 md5VerifyMac},
142 #endif /* USE_SSL_RSA_WITH_RC4_128_MD5 */
144 These two USE_SSL_RSA_WITH_NULL ciphers are not recommended for use
145 in production applications.
147 #ifdef USE_SSL_RSA_WITH_NULL_MD5
148 {SSL_RSA_WITH_NULL_MD5,
149 16, /* macSize */
150 0, /* keySize */
151 0, /* ivSize */
152 0, /* blocksize */
153 nullInit,
154 nullEncrypt,
155 nullDecrypt,
156 matrixRsaEncryptPriv,
157 matrixRsaDecryptPub,
158 matrixRsaEncryptPub,
159 matrixRsaDecryptPriv,
160 md5GenerateMac,
161 md5VerifyMac},
162 #endif /* USE_SSL_RSA_WITH_NULL_MD5 */
163 #ifdef USE_SSL_RSA_WITH_NULL_SHA
164 {SSL_RSA_WITH_NULL_SHA,
165 20, /* macSize */
166 0, /* keySize */
167 0, /* ivSize */
168 0, /* blocksize */
169 nullInit,
170 nullEncrypt,
171 nullDecrypt,
172 matrixRsaEncryptPriv,
173 matrixRsaDecryptPub,
174 matrixRsaEncryptPub,
175 matrixRsaDecryptPriv,
176 sha1GenerateMac,
177 sha1VerifyMac},
178 #endif /* USE_SSL_RSA_WITH_NULL_SHA */
180 The NULL Cipher suite must exist and be the last in this list
182 {SSL_NULL_WITH_NULL_NULL,
187 nullInit,
188 nullEncrypt,
189 nullDecrypt,
190 nullEncryptPub,
191 nullDecryptPriv,
192 nullEncryptPub,
193 nullDecryptPriv,
194 nullGenerateMac,
195 nullVerifyMac}
198 /******************************************************************************/
200 Lookup the given cipher spec ID and return a pointer to the structure
201 if found. This is used when negotiating security, to find out what suites
202 we support.
204 sslCipherSpec_t *sslGetCipherSpec(int32 id)
206 int32 i;
208 i = 0;
209 do {
210 if ((int32)supportedCiphers[i].id == id) {
211 return &supportedCiphers[i];
213 } while (supportedCiphers[i++].id != SSL_NULL_WITH_NULL_NULL) ;
215 return NULL;
218 /******************************************************************************/
220 Write out a list of the supported cipher suites to the caller's buffer
221 First 2 bytes are the number of cipher suite bytes, the remaining bytes are
222 the cipher suites, as two byte, network byte order values.
224 int32 sslGetCipherSpecList(unsigned char *c, int32 len)
226 unsigned char *end, *p;
227 unsigned short i;
229 if (len < 4) {
230 return -1;
232 end = c + len;
233 p = c; c += 2;
234 for (i = 0; supportedCiphers[i].id != SSL_NULL_WITH_NULL_NULL; i++) {
235 if (end - c < 2) {
236 return -1;
238 *c = (unsigned char)((supportedCiphers[i].id & 0xFF00) >> 8); c++;
239 *c = (unsigned char)(supportedCiphers[i].id & 0xFF); c++;
241 i *= 2;
242 *p = (unsigned char)(i >> 8); p++;
243 *p = (unsigned char)(i & 0xFF);
244 return i + 2;
247 /******************************************************************************/
249 Return the length of the cipher spec list, including initial length bytes
251 int32 sslGetCipherSpecListLen(void)
253 int32 i;
255 for (i = 0; supportedCiphers[i].id != SSL_NULL_WITH_NULL_NULL; i++) {
257 return (i * 2) + 2;
261 /******************************************************************************/
264 #ifdef USE_SHA1_MAC
265 static int32 sha1GenerateMac(void *sslv, unsigned char type, unsigned char *data,
266 int32 len, unsigned char *mac)
268 ssl_t *ssl = (ssl_t*)sslv;
269 return ssl3HMACSha1(ssl->sec.writeMAC, ssl->sec.seq, type, data, len, mac);
272 static int32 sha1VerifyMac(void *sslv, unsigned char type, unsigned char *data,
273 int32 len, unsigned char *mac)
275 ssl_t *ssl = (ssl_t*)sslv;
276 unsigned char buf[SSL_SHA1_HASH_SIZE];
278 ssl3HMACSha1(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf);
279 if (memcmp(buf, mac, SSL_SHA1_HASH_SIZE) == 0) {
280 return 0;
282 return -1;
284 #endif /* USE_SHA1_MAC */
286 /******************************************************************************/
289 #ifdef USE_MD5_MAC
290 static int32 md5GenerateMac(void *sslv, unsigned char type, unsigned char *data,
291 int32 len, unsigned char *mac)
293 ssl_t *ssl = (ssl_t*)sslv;
294 return ssl3HMACMd5(ssl->sec.writeMAC, ssl->sec.seq, type, data, len, mac);
297 static int32 md5VerifyMac(void *sslv, unsigned char type, unsigned char *data,
298 int32 len, unsigned char *mac)
300 ssl_t *ssl = (ssl_t*)sslv;
301 unsigned char buf[SSL_MD5_HASH_SIZE];
303 ssl3HMACMd5(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf);
304 if (memcmp(buf, mac, SSL_MD5_HASH_SIZE) == 0) {
305 return 0;
307 return -1;
310 #endif /* USE_MD5_MAC */
312 /******************************************************************************/
314 SSL_RSA_WITH_RC4_128_SHA cipher init
316 #ifdef USE_SSL_RSA_WITH_RC4_128_MD5
317 static int32 matrixCipher4Init(sslSec_t *sec, int32 type)
319 if (type == INIT_ENCRYPT_CIPHER) {
320 matrixArc4Init(&(sec->encryptCtx), sec->writeKey, 16);
321 } else {
322 matrixArc4Init(&(sec->decryptCtx), sec->readKey, 16);
325 return 0;
327 #endif /* USE_SSL_RSA_WITH_RC4_128_MD5 */
329 /******************************************************************************/
331 SSL_RSA_WITH_RC4_128_SHA cipher init
333 #ifdef USE_SSL_RSA_WITH_RC4_128_SHA
334 static int32 matrixCipher5Init(sslSec_t *sec, int32 type)
336 if (type == INIT_ENCRYPT_CIPHER) {
337 matrixArc4Init(&(sec->encryptCtx), sec->writeKey, 16);
338 } else {
339 matrixArc4Init(&(sec->decryptCtx), sec->readKey, 16);
342 return 0;
344 #endif /* USE_SSL_RSA_WITH_RC4_128_SHA */
346 /******************************************************************************/
348 SSL_RSA_WITH_3DES_EDE_CBC_SHA cipher init
350 #ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
351 static int32 matrixCipherAInit(sslSec_t *sec, int32 type)
353 if (type == INIT_ENCRYPT_CIPHER) {
354 if (matrix3desInit(&(sec->encryptCtx), sec->writeIV, sec->writeKey,
355 SSL_DES3_KEY_LEN) < 0) {
356 return -1;
358 } else {
359 if (matrix3desInit(&(sec->decryptCtx), sec->readIV, sec->readKey,
360 SSL_DES3_KEY_LEN) < 0) {
361 return -1;
364 return 0;
366 #endif /* USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA */
369 /******************************************************************************/
371 SSL_NULL_WITH_NULL_NULL cipher functions
372 Used in handshaking before SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC message
373 FUTURE - remove the memcpy to support in-situ decryption
375 static int32 nullInit(sslSec_t *sec, int32 type)
377 return 0;
380 static int32 nullEncrypt(sslCipherContext_t *ctx, unsigned char *in,
381 unsigned char *out, int32 len)
383 if (out != in) {
384 memcpy(out, in, len);
386 return len;
389 static int32 nullDecrypt(sslCipherContext_t *ctx, unsigned char *in,
390 unsigned char *out, int32 len)
392 if (out != in) {
393 memcpy(out, in, len);
395 return len;
399 FUTURE - remove both apis below
401 static int32 nullEncryptPub(psPool_t *pool, sslRsaKey_t *key,
402 unsigned char *in, int32 inlen,
403 unsigned char *out, int32 outlen)
405 if (inlen <= outlen) {
406 matrixStrDebugMsg("Error: output buffer too small for NULL encrypt\n",
407 NULL);
408 return -1;
410 memcpy(out, in, inlen);
411 return inlen;
414 static int32 nullDecryptPriv(psPool_t *pool, sslRsaKey_t *key,
415 unsigned char *in, int32 inlen,
416 unsigned char *out, int32 outlen)
418 if (inlen <= outlen) {
419 matrixStrDebugMsg("Error: output buffer too small for NULL decrypt\n",
420 NULL);
421 return -1;
423 memcpy(out, in, inlen);
424 return inlen;
427 static int32 nullGenerateMac(void *ssl, unsigned char type, unsigned char *data,
428 int32 len, unsigned char *mac)
430 return 0;
433 static int32 nullVerifyMac(void *ssl, unsigned char type, unsigned char *data,
434 int32 len, unsigned char *mac)
436 return 0;
441 /******************************************************************************/