1 /*
2  *	cipherSuite.c
3  *	Release $Name: MATRIXSSL-3-3-0-OPEN $
4  *
5  *	Wrappers for the various cipher suites.
6  *	Enable specific suites at compile time in matrixsslConfig.h
7  */
8 /*
9  *	Copyright (c) AuthenTec, Inc. 2011-2012
10  *	Copyright (c) PeerSec Networks, 2002-2011
11  *	All Rights Reserved
12  *
13  *	The latest version of this code is available at http://www.matrixssl.org
14  *
15  *	This software is open source; you can redistribute it and/or modify
16  *	it under the terms of the GNU General Public License as published by
17  *	the Free Software Foundation; either version 2 of the License, or
18  *	(at your option) any later version.
19  *
20  *	This General Public License does NOT permit incorporating this software
21  *	into proprietary programs.  If you are unable to comply with the GPL, a
22  *	commercial license for this software may be purchased from AuthenTec at
23  *	http://www.authentec.com/Products/EmbeddedSecurity/SecurityToolkits.aspx
24  *
25  *	This program is distributed in WITHOUT ANY WARRANTY; without even the
26  *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27  *	See the GNU General Public License for more details.
28  *
29  *	You should have received a copy of the GNU General Public License
30  *	along with this program; if not, write to the Free Software
31  *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32  *	http://www.gnu.org/copyleft/gpl.html
33  */
34 /******************************************************************************/
35 
36 #include "matrixsslApi.h"
37 
38 /******************************************************************************/
39 /*	Symmetric cipher initializtion wrappers for cipher suites */
40 /******************************************************************************/
41 /*
42 	SSL_NULL_WITH_NULL_NULL cipher functions
43 	Used in handshaking before SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC message
44 */
csNullInit(sslSec_t * sec,int32 type,uint32 keysize)45 static int32 csNullInit(sslSec_t *sec, int32 type, uint32 keysize)
46 {
47 	return 0;
48 }
49 
50 /******************************************************************************/
51 #ifdef USE_ARC4_CIPHER_SUITE
52 /******************************************************************************/
csArc4Init(sslSec_t * sec,int32 type,uint32 keysize)53 static int32 csArc4Init(sslSec_t *sec, int32 type, uint32 keysize)
54 {
55 	if (type == INIT_ENCRYPT_CIPHER) {
56 		memset(&(sec->encryptCtx), 0, sizeof(psRc4Key_t));
57 		psArc4Init(&(sec->encryptCtx), sec->writeKey, keysize);
58 	} else {
59 		memset(&(sec->decryptCtx), 0, sizeof(psRc4Key_t));
60 		psArc4Init(&(sec->decryptCtx), sec->readKey, keysize);
61 	}
62 	return PS_SUCCESS;
63 }
64 #endif /* USE_ARC4_CIPHER_SUITE */
65 /******************************************************************************/
66 
67 /******************************************************************************/
68 #ifdef USE_3DES_CIPHER_SUITE
69 /******************************************************************************/
csDes3Init(sslSec_t * sec,int32 type,uint32 keysize)70 static int32 csDes3Init(sslSec_t *sec, int32 type, uint32 keysize)
71 {
72 	int32	err;
73 
74 	psAssert(keysize == DES3_KEY_LEN);
75 
76 	if (type == INIT_ENCRYPT_CIPHER) {
77 		memset(&(sec->encryptCtx), 0, sizeof(des3_CBC));
78 		if ((err = psDes3Init(&(sec->encryptCtx), sec->writeIV, sec->writeKey,
79 							  DES3_KEY_LEN)) < 0) {
80 			return err;
81 		}
82 #ifdef USE_TLS_1_1
83 		if (sec->explicitIv) {
84 			sec->encryptCtx.des3.explicitIV = 1;
85 		}
86 #endif /* USE_TLS_1_1 */
87 	} else {
88 		memset(&(sec->decryptCtx), 0, sizeof(des3_CBC));
89 		if ((err = psDes3Init(&(sec->decryptCtx), sec->readIV, sec->readKey,
90 							  DES3_KEY_LEN)) < 0) {
91 			return err;
92 		}
93 #ifdef USE_TLS_1_1
94 		if (sec->explicitIv) {
95 			sec->decryptCtx.des3.explicitIV = 1;
96 		}
97 #endif /* USE_TLS_1_1 */
98 	}
99 	return PS_SUCCESS;
100 }
101 #endif /* USE_3DES_CIPHER_SUITE */
102 /******************************************************************************/
103 
104 
105 #ifdef USE_AES_CIPHER_SUITE
106 /******************************************************************************/
csAesInit(sslSec_t * sec,int32 type,uint32 keysize)107 static int32 csAesInit(sslSec_t *sec, int32 type, uint32 keysize)
108 {
109 	int32	err;
110 
111 	if (type == INIT_ENCRYPT_CIPHER) {
112 		memset(&(sec->encryptCtx), 0, sizeof(aes_CBC));
113 		if ((err = psAesInit(&(sec->encryptCtx), sec->writeIV, sec->writeKey,
114 							 keysize)) < 0) {
115 			return err;
116 		}
117 #ifdef USE_TLS_1_1
118 		if (sec->explicitIv) {
119 			sec->encryptCtx.aes.explicitIV = 1;
120 		}
121 #endif /* USE_TLS_1_1 */
122 	} else {
123 		memset(&(sec->decryptCtx), 0, sizeof(aes_CBC));
124 		if ((err = psAesInit(&(sec->decryptCtx), sec->readIV, sec->readKey,
125 							 keysize)) < 0) {
126 			return err;
127 		}
128 #ifdef USE_TLS_1_1
129 		if (sec->explicitIv) {
130 			sec->decryptCtx.aes.explicitIV = 1;
131 		}
132 #endif /* USE_TLS_1_1 */
133 	}
134 	return PS_SUCCESS;
135 }
136 #endif /* USE_AES_CIPHER_SUITE */
137 /******************************************************************************/
138 
139 
140 
141 /******************************************************************************/
142 /*	Null cipher crypto */
143 /******************************************************************************/
csNullEncrypt(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,uint32 len)144 static int32 csNullEncrypt(psCipherContext_t *ctx, unsigned char *in,
145 						 unsigned char *out, uint32 len)
146 {
147 	if (out != in) {
148 		memcpy(out, in, len);
149 	}
150 	return len;
151 }
152 
csNullDecrypt(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,uint32 len)153 static int32 csNullDecrypt(psCipherContext_t *ctx, unsigned char *in,
154 						 unsigned char *out, uint32 len)
155 {
156 	if (out != in) {
157 		memmove(out, in, len);
158 	}
159 	return len;
160 }
161 
162 /******************************************************************************/
163 /*	HMAC wrappers for cipher suites */
164 /******************************************************************************/
csNullGenerateMac(void * ssl,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)165 static int32 csNullGenerateMac(void *ssl, unsigned char type,
166 						unsigned char *data, uint32 len, unsigned char *mac)
167 {
168 	return 0;
169 }
170 
csNullVerifyMac(void * ssl,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)171 static int32 csNullVerifyMac(void *ssl, unsigned char type,
172 						unsigned char *data, uint32 len, unsigned char *mac)
173 {
174 	return 0;
175 }
176 
177 #ifdef USE_SHA_MAC
178 /******************************************************************************/
csShaGenerateMac(void * sslv,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)179 static int32 csShaGenerateMac(void *sslv, unsigned char type,
180 					unsigned char *data, uint32 len, unsigned char *mac)
181 {
182 	ssl_t	*ssl = (ssl_t*)sslv;
183 
184 #ifdef USE_TLS
185 	if (ssl->flags & SSL_FLAGS_TLS) {
186 		return tlsHMACSha1(ssl, HMAC_CREATE, type, data, len, mac);
187 	} else {
188 #endif /* USE_TLS */
189 #ifndef DISABLE_SSLV3
190 		return ssl3HMACSha1(ssl->sec.writeMAC, ssl->sec.seq, type, data,
191 				len, mac);
192 #else
193 		return PS_ARG_FAIL;
194 #endif /* DISABLE_SSLV3 */
195 #ifdef USE_TLS
196 	}
197 #endif /* USE_TLS */
198 }
199 
csShaVerifyMac(void * sslv,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)200 static int32 csShaVerifyMac(void *sslv, unsigned char type,
201 					unsigned char *data, uint32 len, unsigned char *mac)
202 {
203 	int32			hashSize;
204 	unsigned char	buf[MAX_HASH_SIZE];
205 	ssl_t	*ssl = (ssl_t*)sslv;
206 
207 	hashSize = SHA1_HASH_SIZE;
208 #ifdef USE_TLS
209 	if (ssl->flags & SSL_FLAGS_TLS) {
210 		tlsHMACSha1(ssl, HMAC_VERIFY, type, data, len, buf);
211 	} else {
212 #endif /* USE_TLS */
213 #ifndef DISABLE_SSLV3
214 		ssl3HMACSha1(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf);
215 #endif /* DISABLE_SSLV3 */
216 #ifdef USE_TLS
217 	}
218 #endif /* USE_TLS */
219 	if (memcmp(buf, mac, hashSize) == 0) {
220 		return PS_SUCCESS;
221 	}
222 	return PS_FAILURE;
223 }
224 #endif /* USE_SHA_MAC */
225 /******************************************************************************/
226 
227 /******************************************************************************/
228 #ifdef USE_MD5_MAC
229 /******************************************************************************/
csMd5GenerateMac(void * sslv,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)230 static int32 csMd5GenerateMac(void *sslv, unsigned char type,
231 					unsigned char *data, uint32 len, unsigned char *mac)
232 {
233 	ssl_t	*ssl = (ssl_t*)sslv;
234 #ifdef USE_TLS
235 	if (ssl->flags & SSL_FLAGS_TLS) {
236 		return tlsHMACMd5(ssl, HMAC_CREATE, type, data, len, mac);
237 	} else {
238 #endif /* USE_TLS */
239 #ifndef DISABLE_SSLV3
240 		return ssl3HMACMd5(ssl->sec.writeMAC, ssl->sec.seq, type, data,
241 						   len, mac);
242 #else
243 		return PS_ARG_FAIL;
244 #endif /* DISABLE_SSLV3 */
245 #ifdef USE_TLS
246 	}
247 #endif /* USE_TLS */
248 }
249 
csMd5VerifyMac(void * sslv,unsigned char type,unsigned char * data,uint32 len,unsigned char * mac)250 static int32 csMd5VerifyMac(void *sslv, unsigned char type, unsigned char *data,
251 					uint32 len, unsigned char *mac)
252 {
253 	unsigned char	buf[MD5_HASH_SIZE];
254 	ssl_t	*ssl = (ssl_t*)sslv;
255 
256 #ifdef USE_TLS
257 	if (ssl->flags & SSL_FLAGS_TLS) {
258 		tlsHMACMd5(ssl, HMAC_VERIFY, type, data, len, buf);
259 	} else {
260 #endif /* USE_TLS */
261 #ifndef DISABLE_SSLV3
262 		ssl3HMACMd5(ssl->sec.readMAC, ssl->sec.remSeq, type, data, len, buf);
263 #endif /* DISABLE_SSLV3 */
264 #ifdef USE_TLS
265 	}
266 #endif /* USE_TLS */
267 	if (memcmp(buf, mac, MD5_HASH_SIZE) == 0) {
268 		return PS_SUCCESS;
269 	}
270 	return PS_FAILURE;
271 }
272 #endif /* USE_MD5_MAC */
273 /******************************************************************************/
274 
275 /******************************************************************************/
276 /*	Public Key operations wrappers for cipher suites */
277 /******************************************************************************/
278 /******************************************************************************/
279 /******************************************************************************/
280 
csRsaEncryptPub(psPool_t * pool,psPubKey_t * key,unsigned char * in,uint32 inlen,unsigned char * out,uint32 outlen)281 int32 csRsaEncryptPub(psPool_t *pool, psPubKey_t *key,
282 			unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen)
283 {
284 	psAssert(key->type == PS_RSA);
285 	return psRsaEncryptPub(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen);
286 }
287 
csRsaDecryptPub(psPool_t * pool,psPubKey_t * key,unsigned char * in,uint32 inlen,unsigned char * out,uint32 outlen)288 int32 csRsaDecryptPub(psPool_t *pool, psPubKey_t *key,
289 			unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen)
290 {
291 	psAssert(key->type == PS_RSA);
292 	return psRsaDecryptPub(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen);
293 }
294 
csRsaEncryptPriv(psPool_t * pool,psPubKey_t * key,unsigned char * in,uint32 inlen,unsigned char * out,uint32 outlen)295 int32 csRsaEncryptPriv(psPool_t *pool, psPubKey_t *key,
296 			unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen)
297 {
298 	return PS_UNSUPPORTED_FAIL;
299 }
300 
csRsaDecryptPriv(psPool_t * pool,psPubKey_t * key,unsigned char * in,uint32 inlen,unsigned char * out,uint32 outlen)301 int32 csRsaDecryptPriv(psPool_t *pool, psPubKey_t *key,
302 			unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen)
303 {
304 	psAssert(key->type == PS_RSA);
305 	return psRsaDecryptPriv(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen);
306 }
307 /******************************************************************************/
308 
309 
310 static sslCipherSpec_t	supportedCiphers[] = {
311 /*
312 	New ciphers should be added here, similar to the ones below
313 
314 	Ciphers are listed in order of greater security at top... this generally
315 	means the slower ones are on top as well.
316 */
317 
318 #ifdef USE_TLS_RSA_WITH_AES_256_CBC_SHA
319 	{TLS_RSA_WITH_AES_256_CBC_SHA,
320 		CS_RSA,
321 		CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_SHA1,
322 		20,			/* macSize */
323 		32,			/* keySize */
324 		16,			/* ivSize */
325 		16,			/* blocksize */
326 		csAesInit,
327 		psAesEncrypt,
328 		psAesDecrypt,
329 		csShaGenerateMac,
330 		csShaVerifyMac},
331 #endif /* USE_TLS_RSA_WITH_AES_256_CBC_SHA */
332 
333 #ifdef USE_TLS_RSA_WITH_AES_128_CBC_SHA
334 	{TLS_RSA_WITH_AES_128_CBC_SHA,
335 		CS_RSA,
336 		CRYPTO_FLAGS_AES | CRYPTO_FLAGS_SHA1,
337 		20,			/* macSize */
338 		16,			/* keySize */
339 		16,			/* ivSize */
340 		16,			/* blocksize */
341 		csAesInit,
342 		psAesEncrypt,
343 		psAesDecrypt,
344 		csShaGenerateMac,
345 		csShaVerifyMac},
346 #endif /* USE_TLS_RSA_WITH_AES_128_CBC_SHA */
347 
348 
349 #ifdef USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA
350 	{SSL_RSA_WITH_3DES_EDE_CBC_SHA,
351 		CS_RSA,
352 		CRYPTO_FLAGS_3DES | CRYPTO_FLAGS_SHA1,
353 		20,			/* macSize */
354 		24,			/* keySize */
355 		8,			/* ivSize */
356 		8,			/* blocksize */
357 		csDes3Init,
358 		psDes3Encrypt,
359 		psDes3Decrypt,
360 		csShaGenerateMac,
361 		csShaVerifyMac},
362 #endif /* USE_SSL_RSA_WITH_3DES_EDE_CBC_SHA */
363 
364 #ifdef USE_SSL_RSA_WITH_RC4_128_SHA
365 	{SSL_RSA_WITH_RC4_128_SHA,
366 		CS_RSA,
367 		CRYPTO_FLAGS_ARC4 | CRYPTO_FLAGS_SHA1,
368 		20,			/* macSize */
369 		16,			/* keySize */
370 		0,			/* ivSize */
371 		1,			/* blocksize */
372 		csArc4Init,
373 		psArc4,
374 		psArc4,
375 		csShaGenerateMac,
376 		csShaVerifyMac},
377 #endif /* USE_SSL_RSA_WITH_RC4_128_SHA */
378 
379 #ifdef USE_SSL_RSA_WITH_RC4_128_MD5
380 	{SSL_RSA_WITH_RC4_128_MD5,
381 		CS_RSA,
382 		CRYPTO_FLAGS_ARC4 | CRYPTO_FLAGS_MD5,
383 		16,			/* macSize */
384 		16,			/* keySize */
385 		0,			/* ivSize */
386 		1,			/* blocksize */
387 		csArc4Init,
388 		psArc4,
389 		psArc4,
390 		csMd5GenerateMac,
391 		csMd5VerifyMac},
392 #endif /* USE_SSL_RSA_WITH_RC4_128_MD5 */
393 
394 
395 /*
396 	These two USE_SSL_RSA_WITH_NULL ciphers are not recommended for use
397 	in production applications.
398 */
399 #ifdef USE_SSL_RSA_WITH_NULL_SHA
400 	{SSL_RSA_WITH_NULL_SHA,
401 		CS_RSA,
402 		CRYPTO_FLAGS_SHA1,
403 		20,			/* macSize */
404 		0,			/* keySize */
405 		0,			/* ivSize */
406 		0,			/* blocksize */
407 		csNullInit,
408 		csNullEncrypt,
409 		csNullDecrypt,
410 		csShaGenerateMac,
411 		csShaVerifyMac},
412 #endif /* USE_SSL_RSA_WITH_NULL_SHA */
413 
414 #ifdef USE_SSL_RSA_WITH_NULL_MD5
415 	{SSL_RSA_WITH_NULL_MD5,
416 		CS_RSA,
417 		CRYPTO_FLAGS_MD5,
418 		16,			/* macSize */
419 		0,			/* keySize */
420 		0,			/* ivSize */
421 		0,			/* blocksize */
422 		csNullInit,
423 		csNullEncrypt,
424 		csNullDecrypt,
425 		csMd5GenerateMac,
426 		csMd5VerifyMac},
427 #endif /* USE_SSL_RSA_WITH_NULL_MD5 */
428 
429 /*
430 	The NULL Cipher suite must exist and be the last in this list
431 */
432 	{SSL_NULL_WITH_NULL_NULL,
433 		CS_NULL,
434 		0,
435 		0,
436 		0,
437 		0,
438 		0,
439 		csNullInit,
440 		csNullEncrypt,
441 		csNullDecrypt,
442 		csNullGenerateMac,
443 		csNullVerifyMac}
444 };
445 
446 #ifdef USE_SERVER_SIDE_SSL
447 /******************************************************************************/
448 /*
449 	Disable and re-enable ciphers suites on a global or per-session level.
450 	This is only a server-side feature because the client is always able to
451 	nominate the specific cipher it wishes to use.  Servers may want to disable
452 	specific ciphers for a given session (or globally without having to
453 	rebuild the library).
454 
455 	This function must be called immediately after matrixSslNewServerSession
456 
457 	If ssl is NULL, the setting will be global.  If a cipher is globally
458 	disabled, the per-session setting will be ignored.
459 
460 	flags:
461 		PS_TRUE to reenable (always enabled by default if compiled in)
462 		PS_FALSE to disable cipher suite
463 */
matrixSslSetCipherSuiteEnabledStatus(ssl_t * ssl,uint16 cipherId,uint32 flags)464 int32 matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl, uint16 cipherId,
465 			uint32 flags)
466 {
467 	uint16	i, j;
468 
469 	if (ssl && !(ssl->flags & SSL_FLAGS_SERVER)) {
470 		return PS_UNSUPPORTED_FAIL;
471 	}
472 	if (flags != PS_TRUE && flags != PS_FALSE) {
473 		return PS_ARG_FAIL;
474 	}
475 	for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) {
476 		if (supportedCiphers[i].ident == cipherId) {
477 			if (ssl == NULL) {
478 /*
479 				Global status of cipher suite.  Disabled status takes
480 				precident over session setting
481 */
482 				if (flags == PS_TRUE) {
483 					supportedCiphers[i].flags &= ~CRYPTO_FLAGS_DISABLED;
484 				} else {
485 					supportedCiphers[i].flags |= CRYPTO_FLAGS_DISABLED;
486 				}
487 				return PS_SUCCESS;
488 			} else {
489 /*
490 				Status of this suite for a specific session
491 */
492 				for (j = 0; j < SSL_MAX_DISABLED_CIPHERS; j++) {
493 					if (flags == PS_FALSE) {
494 						/* Find first empty spot to add disabled cipher */
495 						if (ssl->disabledCiphers[j] == 0x0 ||
496 								ssl->disabledCiphers[j] == cipherId) {
497 							ssl->disabledCiphers[j] = cipherId;
498 							return PS_SUCCESS;
499 						}
500 					} else {
501 						if (ssl->disabledCiphers[j] == cipherId) {
502 							ssl->disabledCiphers[j] = 0x0;
503 							return PS_SUCCESS;
504 						}
505 					}
506 				}
507 				if (flags == PS_FALSE) {
508 					return PS_LIMIT_FAIL; /* No empty spot in disabledCiphers */
509 				} else {
510 					/* Tried to re-enabled a cipher that wasn't disabled */
511 					return PS_SUCCESS;
512 				}
513 			}
514 		}
515 	}
516 	return PS_FAILURE; /* Cipher not found */
517 }
518 #endif /* USE_SERVER_SIDE_SSL */
519 
520 #ifdef VALIDATE_KEY_MATERIAL
521 /*
522 	TODO: these currently allow any cert in the chain to return success but
523 	it would be better to force only the parent-most(?) to be checked
524 */
haveCorrectKeyAlg(psX509Cert_t * cert,int32 keyAlg)525 static int32 haveCorrectKeyAlg(psX509Cert_t *cert, int32 keyAlg)
526 {
527 	while (cert) {
528 		if (cert->pubKeyAlgorithm == keyAlg) {
529 			return PS_SUCCESS;
530 		}
531 		cert = cert->next;
532 	}
533 	return PS_FAILURE;
534 }
535 
536 
537 /******************************************************************************/
538 /*
539 	Don't report a matching cipher suite if the user hasn't loaded the
540 	proper public key material to support it
541  */
haveKeyMaterial(ssl_t * ssl,int32 cipherType)542 static int32 haveKeyMaterial(ssl_t *ssl, int32 cipherType)
543 {
544 /*
545 	Standard RSA ciphers types
546 */
547 	if (cipherType == CS_RSA) {
548 		if (ssl->flags & SSL_FLAGS_SERVER) {
549 #ifdef USE_SERVER_SIDE_SSL
550 			if (ssl->keys == NULL || ssl->keys->cert == NULL ||
551 					ssl->keys->privKey == NULL) {
552 				return PS_FAILURE;
553 			}
554 			if (haveCorrectKeyAlg(ssl->keys->cert, OID_RSA_KEY_ALG) < 0) {
555 				return PS_FAILURE;
556 			}
557 #else
558 			return PS_FAILURE;
559 #endif /* USE_SERVER_SIDE_SSL */
560 
561 #ifdef USE_CLIENT_SIDE_SSL
562 		} else {
563 			if (ssl->keys == NULL || ssl->keys->CAcerts == NULL) {
564 				return PS_FAILURE;
565 			}
566 			if (haveCorrectKeyAlg(ssl->keys->CAcerts, OID_RSA_KEY_ALG) < 0) {
567 				return PS_FAILURE;
568 			}
569 #endif /* USE_CLIENT_SIDE_SSL */
570 		}
571 	}
572 
573 
574 
575 
576 	return PS_SUCCESS;
577 }
578 #endif /* VALIDATE_KEY_MATERIAL */
579 
580 /******************************************************************************/
581 /*
582 	Lookup the given cipher spec ID and return a pointer to the structure
583 	if found.  This is used when negotiating security, to find out what suites
584 	we support.
585 */
sslGetCipherSpec(ssl_t * ssl,uint32 id)586 sslCipherSpec_t *sslGetCipherSpec(ssl_t *ssl, uint32 id)
587 {
588 	int16	i;
589 #ifdef USE_SERVER_SIDE_SSL
590 	int16	j;
591 #endif /* USE_SERVER_SIDE_SSL */
592 
593 	i = 0;
594 	do {
595 		if (supportedCiphers[i].ident == id) {
596 #ifdef USE_SERVER_SIDE_SSL
597 /*
598 			Globally disabled?
599 */
600 			if (supportedCiphers[i].flags & CRYPTO_FLAGS_DISABLED) {
601 				psTraceIntInfo("Matched cipher suite %d but disabled by user\n",
602 					id);
603 				return NULL;
604 			}
605 /*
606 			Disabled for session?
607 */
608 			if (id != 0) { /* Disable NULL_WITH_NULL_NULL not possible */
609 				for (j = 0; j < SSL_MAX_DISABLED_CIPHERS; j++) {
610 					if (ssl->disabledCiphers[j] == id) {
611 						psTraceIntInfo("Matched cipher suite %d but disabled by user\n",
612 							id);
613 						return NULL;
614 					}
615 				}
616 			}
617 #endif /* USE_SERVER_SIDE_SSL */
618 /*
619 			Unusable due to key material not available?
620 */
621 #ifdef VALIDATE_KEY_MATERIAL
622 			if (haveKeyMaterial(ssl, supportedCiphers[i].type) == PS_SUCCESS) {
623 				return &supportedCiphers[i];
624 			}
625 			psTraceIntInfo("Matched cipher suite %d but no supporting keys\n",
626 				id);
627 #else
628 			return &supportedCiphers[i];
629 #endif /* VALIDATE_KEY_MATERIAL */
630 		}
631 	} while (supportedCiphers[i++].ident != SSL_NULL_WITH_NULL_NULL) ;
632 
633 	return NULL;
634 }
635 
636 
637 /******************************************************************************/
638 /*
639 	Write out a list of the supported cipher suites to the caller's buffer
640 	First 2 bytes are the number of cipher suite bytes, the remaining bytes are
641 	the cipher suites, as two byte, network byte order values.
642 */
sslGetCipherSpecList(ssl_t * ssl,unsigned char * c,int32 len,int32 addScsv)643 int32 sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
644 		int32 addScsv)
645 {
646 	unsigned char	*end, *p;
647 	unsigned short	i;
648 	int32			ignored;
649 
650 	if (len < 4) {
651 		return -1;
652 	}
653 	end = c + len;
654 	p = c; c += 2;
655 
656 	ignored = 0;
657 	for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) {
658 		if (end - c < 2) {
659 			return -1;
660 		}
661 #ifdef VALIDATE_KEY_MATERIAL
662 		if (haveKeyMaterial(ssl, supportedCiphers[i].type) != PS_SUCCESS) {
663 			ignored += 2;
664 			continue;
665 		}
666 #endif
667 		*c = (unsigned char)((supportedCiphers[i].ident & 0xFF00) >> 8); c++;
668 		*c = (unsigned char)(supportedCiphers[i].ident & 0xFF); c++;
669 	}
670 	i *= 2;
671 	i -= (unsigned short)ignored;
672 #ifdef ENABLE_SECURE_REHANDSHAKES
673 	if (addScsv == 1) {
674 		*c = ((TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF00) >> 8); c++;
675 		*c = TLS_EMPTY_RENEGOTIATION_INFO_SCSV  & 0xFF; c++;
676 		i += 2;
677 	}
678 #endif
679 	*p = (unsigned char)(i >> 8); p++;
680 	*p = (unsigned char)(i & 0xFF);
681 	return i + 2;
682 }
683 
684 /******************************************************************************/
685 /*
686 	Return the length of the cipher spec list, including initial length bytes,
687 	(minus any suites that we don't have the key material to support)
688 */
sslGetCipherSpecListLen(ssl_t * ssl)689 int32 sslGetCipherSpecListLen(ssl_t *ssl)
690 {
691 	int32	i, ignored;
692 
693 	ignored = 0;
694 	for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++) {
695 #ifdef VALIDATE_KEY_MATERIAL
696 		if (haveKeyMaterial(ssl, supportedCiphers[i].type) != PS_SUCCESS) {
697 			ignored += 2;
698 		}
699 #endif
700 	}
701 	return (i * 2) + 2 - ignored;
702 }
703 
704 /******************************************************************************/
705 
706