blob: fb8c04778be19910f540dc6d1d282b91d8fe04c6 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 * acknowledgment:
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com).
108 *
109 */
110/* ====================================================================
111 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
112 * ECC cipher suite support in OpenSSL originally developed by
113 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
114 */
115/* ====================================================================
116 * Copyright 2005 Nokia. All rights reserved.
117 *
118 * The portions of the attached software ("Contribution") is developed by
119 * Nokia Corporation and is licensed pursuant to the OpenSSL open source
120 * license.
121 *
122 * The Contribution, originally written by Mika Kousa and Pasi Eronen of
123 * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
124 * support (see RFC 4279) to OpenSSL.
125 *
126 * No patent licenses or other rights except those expressly stated in
127 * the OpenSSL open source license shall be deemed granted or received
128 * expressly, by implication, estoppel, or otherwise.
129 *
130 * No assurances are provided by Nokia that the Contribution does not
131 * infringe the patent or other intellectual property rights of any third
132 * party or that the license provides you with all the necessary rights
133 * to make use of the Contribution.
134 *
135 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
136 * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
137 * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
138 * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
139 * OTHERWISE. */
140
141#include <stdio.h>
142#include <assert.h>
143
Adam Langley95c29f32014-06-20 12:00:00 -0700144#include <openssl/engine.h>
145#include <openssl/mem.h>
146#include <openssl/obj.h>
147
148#include "ssl_locl.h"
149
Adam Langley95c29f32014-06-20 12:00:00 -0700150
Adam Langleyfcf25832014-12-18 17:42:32 -0800151struct handshake_digest {
152 long mask;
153 const EVP_MD *(*md_func)(void);
David Benjamind633d632014-08-30 14:43:27 -0400154};
Adam Langley95c29f32014-06-20 12:00:00 -0700155
Adam Langleyfcf25832014-12-18 17:42:32 -0800156static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = {
157 {SSL_HANDSHAKE_MAC_MD5, EVP_md5},
158 {SSL_HANDSHAKE_MAC_SHA, EVP_sha1},
159 {SSL_HANDSHAKE_MAC_SHA256, EVP_sha256},
160 {SSL_HANDSHAKE_MAC_SHA384, EVP_sha384},
161};
Adam Langley95c29f32014-06-20 12:00:00 -0700162
Adam Langleyfcf25832014-12-18 17:42:32 -0800163#define CIPHER_ADD 1
164#define CIPHER_KILL 2
165#define CIPHER_DEL 3
166#define CIPHER_ORD 4
167#define CIPHER_SPECIAL 5
Adam Langley95c29f32014-06-20 12:00:00 -0700168
Adam Langleyfcf25832014-12-18 17:42:32 -0800169typedef struct cipher_order_st {
170 const SSL_CIPHER *cipher;
171 int active;
172 int dead;
173 int in_group;
174 struct cipher_order_st *next, *prev;
175} CIPHER_ORDER;
Adam Langley95c29f32014-06-20 12:00:00 -0700176
Adam Langleyfcf25832014-12-18 17:42:32 -0800177static const SSL_CIPHER cipher_aliases[] =
178 {
179 {0, SSL_TXT_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700180
Adam Langleyfcf25832014-12-18 17:42:32 -0800181 /* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in
182 ALL!) */
183 {0, SSL_TXT_CMPDEF, 0, SSL_kEDH | SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0,
184 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700185
Adam Langleyfcf25832014-12-18 17:42:32 -0800186 /* key exchange aliases
187 * (some of those using only a single bit here combine
188 * multiple key exchange algs according to the RFCs,
189 * e.g. kEDH combines DHE_DSS and DHE_RSA) */
190 {0, SSL_TXT_kRSA, 0, SSL_kRSA, 0, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700191
Adam Langleyfcf25832014-12-18 17:42:32 -0800192 {0, SSL_TXT_kEDH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0},
193 {0, SSL_TXT_DH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700194
Adam Langleyfcf25832014-12-18 17:42:32 -0800195 {0, SSL_TXT_kEECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0},
196 {0, SSL_TXT_ECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700197
Adam Langleyfcf25832014-12-18 17:42:32 -0800198 {0, SSL_TXT_kPSK, 0, SSL_kPSK, 0, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700199
Adam Langleyfcf25832014-12-18 17:42:32 -0800200 /* server authentication aliases */
201 {0, SSL_TXT_aRSA, 0, 0, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0},
202 {0, SSL_TXT_aNULL, 0, 0, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
203 {0, SSL_TXT_aECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
204 {0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
205 {0, SSL_TXT_aPSK, 0, 0, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700206
Adam Langleyfcf25832014-12-18 17:42:32 -0800207 /* aliases combining key exchange and server authentication */
208 {0, SSL_TXT_EDH, 0, SSL_kEDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
209 {0, SSL_TXT_EECDH, 0, SSL_kEECDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
210 {0, SSL_TXT_RSA, 0, SSL_kRSA, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0},
211 {0, SSL_TXT_ADH, 0, SSL_kEDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
212 {0, SSL_TXT_AECDH, 0, SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
213 {0, SSL_TXT_PSK, 0, SSL_kPSK, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700214
Adam Langleyfcf25832014-12-18 17:42:32 -0800215 /* symmetric encryption aliases */
216 {0, SSL_TXT_3DES, 0, 0, 0, SSL_3DES, 0, 0, 0, 0, 0, 0},
217 {0, SSL_TXT_RC4, 0, 0, 0, SSL_RC4, 0, 0, 0, 0, 0, 0},
218 {0, SSL_TXT_AES128, 0, 0, 0, SSL_AES128 | SSL_AES128GCM, 0, 0, 0, 0, 0, 0},
219 {0, SSL_TXT_AES256, 0, 0, 0, SSL_AES256 | SSL_AES256GCM, 0, 0, 0, 0, 0, 0},
220 {0, SSL_TXT_AES, 0, 0, 0, SSL_AES, 0, 0, 0, 0, 0, 0},
221 {0, SSL_TXT_AES_GCM, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM, 0, 0, 0, 0, 0,
222 0},
223 {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700224
Adam Langleyfcf25832014-12-18 17:42:32 -0800225 /* MAC aliases */
226 {0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5, 0, 0, 0, 0, 0},
227 {0, SSL_TXT_SHA1, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
228 {0, SSL_TXT_SHA, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
229 {0, SSL_TXT_SHA256, 0, 0, 0, 0, SSL_SHA256, 0, 0, 0, 0, 0},
230 {0, SSL_TXT_SHA384, 0, 0, 0, 0, SSL_SHA384, 0, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700231
Adam Langleyfcf25832014-12-18 17:42:32 -0800232 /* protocol version aliases */
233 {0, SSL_TXT_SSLV3, 0, 0, 0, 0, 0, SSL_SSLV3, 0, 0, 0, 0},
234 {0, SSL_TXT_TLSV1, 0, 0, 0, 0, 0, SSL_TLSV1, 0, 0, 0, 0},
235 {0, SSL_TXT_TLSV1_2, 0, 0, 0, 0, 0, SSL_TLSV1_2, 0, 0, 0, 0},
Adam Langley95c29f32014-06-20 12:00:00 -0700236
Adam Langleyfcf25832014-12-18 17:42:32 -0800237 /* strength classes */
238 {0, SSL_TXT_MEDIUM, 0, 0, 0, 0, 0, 0, SSL_MEDIUM, 0, 0, 0},
239 {0, SSL_TXT_HIGH, 0, 0, 0, 0, 0, 0, SSL_HIGH, 0, 0, 0},
240 /* FIPS 140-2 approved ciphersuite */
241 {0, SSL_TXT_FIPS, 0, 0, 0, 0, 0, 0, SSL_FIPS, 0, 0, 0},
242};
Adam Langley95c29f32014-06-20 12:00:00 -0700243
Adam Langleyc9fb3752014-06-20 12:00:00 -0700244/* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object
245 * for |s->cipher|. It returns 1 on success and 0 on error. */
Adam Langleyfcf25832014-12-18 17:42:32 -0800246int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead) {
247 const SSL_CIPHER *c = s->cipher;
Adam Langleyc9fb3752014-06-20 12:00:00 -0700248
Adam Langleyfcf25832014-12-18 17:42:32 -0800249 *aead = NULL;
Adam Langleyc9fb3752014-06-20 12:00:00 -0700250
Adam Langleyfcf25832014-12-18 17:42:32 -0800251 if (c == NULL) {
252 return 0;
253 }
Adam Langleyc9fb3752014-06-20 12:00:00 -0700254
Adam Langleyfcf25832014-12-18 17:42:32 -0800255 if ((c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) == 0 &&
256 (c->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) == 0) {
257 return 0;
258 }
Adam Langleyc9fb3752014-06-20 12:00:00 -0700259
Adam Langleyfcf25832014-12-18 17:42:32 -0800260 switch (c->algorithm_enc) {
261 case SSL_AES128GCM:
262 *aead = EVP_aead_aes_128_gcm();
263 return 1;
264
265 case SSL_AES256GCM:
266 *aead = EVP_aead_aes_256_gcm();
267 return 1;
268
269 case SSL_CHACHA20POLY1305:
270 *aead = EVP_aead_chacha20_poly1305();
271 return 1;
272
273 case SSL_RC4:
274 if (c->algorithm_mac != SSL_MD5) {
275 return 0;
276 }
277 *aead = EVP_aead_rc4_md5_tls();
278 return 1;
279 }
280
281 return 0;
282}
Adam Langleyc9fb3752014-06-20 12:00:00 -0700283
284int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
Adam Langleyfcf25832014-12-18 17:42:32 -0800285 const EVP_MD **md, int *mac_pkey_type,
286 int *mac_secret_size) {
287 const SSL_CIPHER *c;
Adam Langley95c29f32014-06-20 12:00:00 -0700288
Adam Langleyfcf25832014-12-18 17:42:32 -0800289 c = s->cipher;
290 if (c == NULL ||
291 /* This function doesn't deal with EVP_AEAD. See
292 * |ssl_cipher_get_aead_evp|. */
293 (c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) ||
294 enc == NULL ||
295 md == NULL) {
296 return 0;
297 }
Adam Langley95c29f32014-06-20 12:00:00 -0700298
Adam Langleyfcf25832014-12-18 17:42:32 -0800299 switch (c->algorithm_enc) {
300 case SSL_3DES:
301 *enc = EVP_des_ede3_cbc();
302 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700303
Adam Langleyfcf25832014-12-18 17:42:32 -0800304 case SSL_RC4:
305 *enc = EVP_rc4();
306 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700307
Adam Langleyfcf25832014-12-18 17:42:32 -0800308 case SSL_AES128:
309 *enc = EVP_aes_128_cbc();
310 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700311
Adam Langleyfcf25832014-12-18 17:42:32 -0800312 case SSL_AES256:
313 *enc = EVP_aes_256_cbc();
314 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700315
Adam Langleyfcf25832014-12-18 17:42:32 -0800316 default:
317 return 0;
318 }
David Benjamind633d632014-08-30 14:43:27 -0400319
Adam Langleyfcf25832014-12-18 17:42:32 -0800320 if (!ssl_cipher_get_mac(s, md, mac_pkey_type, mac_secret_size)) {
321 return 0;
322 }
323
324 assert(*enc != NULL && *md != NULL);
325
326/* TODO(fork): enable the stitched cipher modes. */
David Benjamind633d632014-08-30 14:43:27 -0400327#if 0
Adam Langley95c29f32014-06-20 12:00:00 -0700328 if (s->ssl_version>>8 != TLS1_VERSION_MAJOR ||
329 s->ssl_version < TLS1_VERSION)
330 return 1;
331
Adam Langley95c29f32014-06-20 12:00:00 -0700332 if (c->algorithm_enc == SSL_RC4 &&
333 c->algorithm_mac == SSL_MD5 &&
334 (evp=EVP_get_cipherbyname("RC4-HMAC-MD5")))
335 *enc = evp, *md = NULL;
336 else if (c->algorithm_enc == SSL_AES128 &&
337 c->algorithm_mac == SSL_SHA1 &&
338 (evp=EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA1")))
339 *enc = evp, *md = NULL;
340 else if (c->algorithm_enc == SSL_AES256 &&
341 c->algorithm_mac == SSL_SHA1 &&
342 (evp=EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
343 *enc = evp, *md = NULL;
344#endif
David Benjamind633d632014-08-30 14:43:27 -0400345
Adam Langleyfcf25832014-12-18 17:42:32 -0800346 return 1;
347}
Adam Langley95c29f32014-06-20 12:00:00 -0700348
Adam Langleyfcf25832014-12-18 17:42:32 -0800349int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md,
350 int *mac_pkey_type, int *mac_secret_size) {
351 const SSL_CIPHER *c;
Adam Langley9447dff2014-06-24 17:29:06 -0700352
Adam Langleyfcf25832014-12-18 17:42:32 -0800353 c = s->cipher;
354 if (c == NULL) {
355 return 0;
356 }
Adam Langley9447dff2014-06-24 17:29:06 -0700357
Adam Langleyfcf25832014-12-18 17:42:32 -0800358 switch (c->algorithm_mac) {
359 case SSL_MD5:
360 *md = EVP_md5();
361 break;
Adam Langley9447dff2014-06-24 17:29:06 -0700362
Adam Langleyfcf25832014-12-18 17:42:32 -0800363 case SSL_SHA1:
364 *md = EVP_sha1();
365 break;
Adam Langley9447dff2014-06-24 17:29:06 -0700366
Adam Langleyfcf25832014-12-18 17:42:32 -0800367 case SSL_SHA256:
368 *md = EVP_sha256();
369 break;
370
371 case SSL_SHA384:
372 *md = EVP_sha384();
373 break;
374
375 default:
376 return 0;
377 }
378
379 if (mac_pkey_type != NULL) {
380 *mac_pkey_type = EVP_PKEY_HMAC;
381 }
382 if (mac_secret_size != NULL) {
383 *mac_secret_size = EVP_MD_size(*md);
384 }
385
386 return 1;
387}
388
389int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) {
390 if (idx < 0 || idx >= SSL_MAX_DIGEST) {
391 return 0;
392 }
393 *mask = ssl_handshake_digests[idx].mask;
394 *md = ssl_handshake_digests[idx].md_func();
395 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700396}
397
398#define ITEM_SEP(a) \
Adam Langleyfcf25832014-12-18 17:42:32 -0800399 (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
Adam Langley95c29f32014-06-20 12:00:00 -0700400
401static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr,
Adam Langleyfcf25832014-12-18 17:42:32 -0800402 CIPHER_ORDER **tail) {
403 if (curr == *tail) {
404 return;
405 }
406 if (curr == *head) {
407 *head = curr->next;
408 }
409 if (curr->prev != NULL) {
410 curr->prev->next = curr->next;
411 }
412 if (curr->next != NULL) {
413 curr->next->prev = curr->prev;
414 }
415 (*tail)->next = curr;
416 curr->prev = *tail;
417 curr->next = NULL;
418 *tail = curr;
419}
Adam Langley95c29f32014-06-20 12:00:00 -0700420
421static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
Adam Langleyfcf25832014-12-18 17:42:32 -0800422 CIPHER_ORDER **tail) {
423 if (curr == *head) {
424 return;
425 }
426 if (curr == *tail) {
427 *tail = curr->prev;
428 }
429 if (curr->next != NULL) {
430 curr->next->prev = curr->prev;
431 }
432 if (curr->prev != NULL) {
433 curr->prev->next = curr->next;
434 }
435 (*head)->prev = curr;
436 curr->next = *head;
437 curr->prev = NULL;
438 *head = curr;
439}
Adam Langley95c29f32014-06-20 12:00:00 -0700440
David Benjamin82c9e902014-12-12 15:55:27 -0500441static void ssl_cipher_collect_ciphers(const SSL_PROTOCOL_METHOD *ssl_method,
Adam Langleyfcf25832014-12-18 17:42:32 -0800442 int num_of_ciphers,
443 CIPHER_ORDER *co_list,
444 CIPHER_ORDER **head_p,
445 CIPHER_ORDER **tail_p) {
446 int i, co_list_num;
447 const SSL_CIPHER *c;
Adam Langley95c29f32014-06-20 12:00:00 -0700448
Adam Langleyfcf25832014-12-18 17:42:32 -0800449 /* We have num_of_ciphers descriptions compiled in, depending on the method
450 * selected (SSLv2 and/or SSLv3, TLSv1 etc). These will later be sorted in a
451 * linked list with at most num entries. */
Adam Langley95c29f32014-06-20 12:00:00 -0700452
Adam Langleyfcf25832014-12-18 17:42:32 -0800453 /* Get the initial list of ciphers */
454 co_list_num = 0; /* actual count of ciphers */
455 for (i = 0; i < num_of_ciphers; i++) {
456 c = ssl_method->get_cipher(i);
457 /* drop those that use any of that is not available */
458 if (c != NULL && c->valid) {
459 co_list[co_list_num].cipher = c;
460 co_list[co_list_num].next = NULL;
461 co_list[co_list_num].prev = NULL;
462 co_list[co_list_num].active = 0;
463 co_list[co_list_num].in_group = 0;
464 co_list_num++;
465 }
466 }
Adam Langley95c29f32014-06-20 12:00:00 -0700467
Adam Langleyfcf25832014-12-18 17:42:32 -0800468 /* Prepare linked list from list entries. */
469 if (co_list_num > 0) {
470 co_list[0].prev = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700471
Adam Langleyfcf25832014-12-18 17:42:32 -0800472 if (co_list_num > 1) {
473 co_list[0].next = &co_list[1];
Adam Langley95c29f32014-06-20 12:00:00 -0700474
Adam Langleyfcf25832014-12-18 17:42:32 -0800475 for (i = 1; i < co_list_num - 1; i++) {
476 co_list[i].prev = &co_list[i - 1];
477 co_list[i].next = &co_list[i + 1];
478 }
Adam Langley95c29f32014-06-20 12:00:00 -0700479
Adam Langleyfcf25832014-12-18 17:42:32 -0800480 co_list[co_list_num - 1].prev = &co_list[co_list_num - 2];
481 }
482
483 co_list[co_list_num - 1].next = NULL;
484
485 *head_p = &co_list[0];
486 *tail_p = &co_list[co_list_num - 1];
487 }
488}
Adam Langley95c29f32014-06-20 12:00:00 -0700489
490static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
Adam Langleyfcf25832014-12-18 17:42:32 -0800491 int num_of_group_aliases,
492 CIPHER_ORDER *head) {
493 CIPHER_ORDER *ciph_curr;
494 const SSL_CIPHER **ca_curr;
495 int i;
Adam Langley95c29f32014-06-20 12:00:00 -0700496
Adam Langleyfcf25832014-12-18 17:42:32 -0800497 /* First, add the real ciphers as already collected. */
498 ciph_curr = head;
499 ca_curr = ca_list;
500 while (ciph_curr != NULL) {
501 *ca_curr = ciph_curr->cipher;
502 ca_curr++;
503 ciph_curr = ciph_curr->next;
504 }
Adam Langley95c29f32014-06-20 12:00:00 -0700505
Adam Langleyfcf25832014-12-18 17:42:32 -0800506 /* Now we add the available ones from the cipher_aliases[] table. They
507 * represent either one or more algorithms, some of which in any affected
508 * category must be supported (set in enabled_mask), or represent a cipher
509 * strength value (will be added in any case because algorithms=0). */
510 for (i = 0; i < num_of_group_aliases; i++) {
511 *ca_curr = cipher_aliases + i;
512 ca_curr++;
513 }
Adam Langley95c29f32014-06-20 12:00:00 -0700514
Adam Langleyfcf25832014-12-18 17:42:32 -0800515 *ca_curr = NULL; /* end of list */
516}
Adam Langley95c29f32014-06-20 12:00:00 -0700517
Adam Langleyfcf25832014-12-18 17:42:32 -0800518static void ssl_cipher_apply_rule(
519 unsigned long cipher_id, unsigned long alg_mkey, unsigned long alg_auth,
520 unsigned long alg_enc, unsigned long alg_mac, unsigned long alg_ssl,
521 unsigned long algo_strength, int rule, int strength_bits, int in_group,
522 CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) {
523 CIPHER_ORDER *head, *tail, *curr, *next, *last;
524 const SSL_CIPHER *cp;
525 int reverse = 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700526
Adam Langleyfcf25832014-12-18 17:42:32 -0800527 if (rule == CIPHER_DEL) {
528 /* needed to maintain sorting between currently deleted ciphers */
529 reverse = 1;
530 }
Adam Langley95c29f32014-06-20 12:00:00 -0700531
Adam Langleyfcf25832014-12-18 17:42:32 -0800532 head = *head_p;
533 tail = *tail_p;
Adam Langley95c29f32014-06-20 12:00:00 -0700534
Adam Langleyfcf25832014-12-18 17:42:32 -0800535 if (reverse) {
536 next = tail;
537 last = head;
538 } else {
539 next = head;
540 last = tail;
541 }
Adam Langley95c29f32014-06-20 12:00:00 -0700542
Adam Langleyfcf25832014-12-18 17:42:32 -0800543 curr = NULL;
544 for (;;) {
545 if (curr == last) {
546 break;
547 }
Adam Langley95c29f32014-06-20 12:00:00 -0700548
Adam Langleyfcf25832014-12-18 17:42:32 -0800549 curr = next;
550 if (curr == NULL) {
551 break;
552 }
Adam Langleye3142a72014-07-24 17:56:48 -0700553
Adam Langleyfcf25832014-12-18 17:42:32 -0800554 next = reverse ? curr->prev : curr->next;
555 cp = curr->cipher;
Adam Langleye3142a72014-07-24 17:56:48 -0700556
Adam Langleyfcf25832014-12-18 17:42:32 -0800557 /* Selection criteria is either the value of strength_bits
558 * or the algorithms used. */
559 if (strength_bits >= 0) {
560 if (strength_bits != cp->strength_bits) {
561 continue;
562 }
563 } else {
564 if ((alg_mkey && !(alg_mkey & cp->algorithm_mkey)) ||
565 (alg_auth && !(alg_auth & cp->algorithm_auth)) ||
566 (alg_enc && !(alg_enc & cp->algorithm_enc)) ||
567 (alg_mac && !(alg_mac & cp->algorithm_mac)) ||
568 (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) ||
569 (algo_strength && !(algo_strength & cp->algo_strength))) {
570 continue;
571 }
572 }
Adam Langleye3142a72014-07-24 17:56:48 -0700573
Adam Langleyfcf25832014-12-18 17:42:32 -0800574 /* add the cipher if it has not been added yet. */
575 if (rule == CIPHER_ADD) {
576 /* reverse == 0 */
577 if (!curr->active) {
578 ll_append_tail(&head, curr, &tail);
579 curr->active = 1;
580 curr->in_group = in_group;
581 }
582 }
Adam Langley95c29f32014-06-20 12:00:00 -0700583
Adam Langleyfcf25832014-12-18 17:42:32 -0800584 /* Move the added cipher to this location */
585 else if (rule == CIPHER_ORD) {
586 /* reverse == 0 */
587 if (curr->active) {
588 ll_append_tail(&head, curr, &tail);
589 curr->in_group = 0;
590 }
591 } else if (rule == CIPHER_DEL) {
592 /* reverse == 1 */
593 if (curr->active) {
594 /* most recently deleted ciphersuites get best positions
595 * for any future CIPHER_ADD (note that the CIPHER_DEL loop
596 * works in reverse to maintain the order) */
597 ll_append_head(&head, curr, &tail);
598 curr->active = 0;
599 curr->in_group = 0;
600 }
601 } else if (rule == CIPHER_KILL) {
602 /* reverse == 0 */
603 if (head == curr) {
604 head = curr->next;
605 } else {
606 curr->prev->next = curr->next;
607 }
Adam Langley95c29f32014-06-20 12:00:00 -0700608
Adam Langleyfcf25832014-12-18 17:42:32 -0800609 if (tail == curr) {
610 tail = curr->prev;
611 }
612 curr->active = 0;
613 if (curr->next != NULL) {
614 curr->next->prev = curr->prev;
615 }
616 if (curr->prev != NULL) {
617 curr->prev->next = curr->next;
618 }
619 curr->next = NULL;
620 curr->prev = NULL;
621 }
622 }
Adam Langley95c29f32014-06-20 12:00:00 -0700623
Adam Langleyfcf25832014-12-18 17:42:32 -0800624 *head_p = head;
625 *tail_p = tail;
626}
Adam Langley95c29f32014-06-20 12:00:00 -0700627
628static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
Adam Langleyfcf25832014-12-18 17:42:32 -0800629 CIPHER_ORDER **tail_p) {
630 int max_strength_bits, i, *number_uses;
631 CIPHER_ORDER *curr;
Adam Langley95c29f32014-06-20 12:00:00 -0700632
Adam Langleyfcf25832014-12-18 17:42:32 -0800633 /* This routine sorts the ciphers with descending strength. The sorting must
634 * keep the pre-sorted sequence, so we apply the normal sorting routine as
635 * '+' movement to the end of the list. */
636 max_strength_bits = 0;
637 curr = *head_p;
638 while (curr != NULL) {
639 if (curr->active && curr->cipher->strength_bits > max_strength_bits) {
640 max_strength_bits = curr->cipher->strength_bits;
641 }
642 curr = curr->next;
643 }
Adam Langley95c29f32014-06-20 12:00:00 -0700644
Adam Langleyfcf25832014-12-18 17:42:32 -0800645 number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int));
646 if (!number_uses) {
647 OPENSSL_PUT_ERROR(SSL, ssl_cipher_strength_sort, ERR_R_MALLOC_FAILURE);
648 return 0;
649 }
650 memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
Adam Langley95c29f32014-06-20 12:00:00 -0700651
Adam Langleyfcf25832014-12-18 17:42:32 -0800652 /* Now find the strength_bits values actually used. */
653 curr = *head_p;
654 while (curr != NULL) {
655 if (curr->active) {
656 number_uses[curr->cipher->strength_bits]++;
657 }
658 curr = curr->next;
659 }
Adam Langley95c29f32014-06-20 12:00:00 -0700660
Adam Langleyfcf25832014-12-18 17:42:32 -0800661 /* Go through the list of used strength_bits values in descending order. */
662 for (i = max_strength_bits; i >= 0; i--) {
663 if (number_uses[i] > 0) {
664 ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0, head_p,
665 tail_p);
666 }
667 }
668
669 OPENSSL_free(number_uses);
670 return 1;
671}
Adam Langley95c29f32014-06-20 12:00:00 -0700672
673static int ssl_cipher_process_rulestr(const char *rule_str,
Adam Langleyfcf25832014-12-18 17:42:32 -0800674 CIPHER_ORDER **head_p,
675 CIPHER_ORDER **tail_p,
676 const SSL_CIPHER **ca_list) {
677 unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength;
678 const char *l, *buf;
679 int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
680 unsigned long cipher_id = 0;
681 char ch;
Adam Langley95c29f32014-06-20 12:00:00 -0700682
Adam Langleyfcf25832014-12-18 17:42:32 -0800683 retval = 1;
684 l = rule_str;
685 for (;;) {
686 ch = *l;
Adam Langley95c29f32014-06-20 12:00:00 -0700687
Adam Langleyfcf25832014-12-18 17:42:32 -0800688 if (ch == '\0') {
689 break; /* done */
690 }
Adam Langley95c29f32014-06-20 12:00:00 -0700691
Adam Langleyfcf25832014-12-18 17:42:32 -0800692 if (in_group) {
693 if (ch == ']') {
694 if (!in_group) {
695 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
696 SSL_R_UNEXPECTED_GROUP_CLOSE);
697 retval = found = in_group = 0;
698 break;
699 }
700 if (*tail_p) {
701 (*tail_p)->in_group = 0;
702 }
703 in_group = 0;
704 l++;
705 continue;
706 }
David Benjamin37d92462014-09-20 17:54:24 -0400707
Adam Langleyfcf25832014-12-18 17:42:32 -0800708 if (ch == '|') {
709 rule = CIPHER_ADD;
710 l++;
711 continue;
712 } else if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') &&
713 !(ch >= '0' && ch <= '9')) {
714 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
715 SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
716 retval = found = in_group = 0;
717 break;
718 } else {
719 rule = CIPHER_ADD;
720 }
721 } else if (ch == '-') {
722 rule = CIPHER_DEL;
723 l++;
724 } else if (ch == '+') {
725 rule = CIPHER_ORD;
726 l++;
727 } else if (ch == '!') {
728 rule = CIPHER_KILL;
729 l++;
730 } else if (ch == '@') {
731 rule = CIPHER_SPECIAL;
732 l++;
733 } else if (ch == '[') {
734 if (in_group) {
735 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_NESTED_GROUP);
736 retval = found = in_group = 0;
737 break;
738 }
739 in_group = 1;
740 has_group = 1;
741 l++;
742 continue;
743 } else {
744 rule = CIPHER_ADD;
745 }
Adam Langley95c29f32014-06-20 12:00:00 -0700746
Adam Langleyfcf25832014-12-18 17:42:32 -0800747 /* If preference groups are enabled, the only legal operator is +.
748 * Otherwise the in_group bits will get mixed up. */
749 if (has_group && rule != CIPHER_ADD) {
750 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
751 SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
752 retval = found = in_group = 0;
753 break;
754 }
Adam Langley95c29f32014-06-20 12:00:00 -0700755
Adam Langleyfcf25832014-12-18 17:42:32 -0800756 if (ITEM_SEP(ch)) {
757 l++;
758 continue;
759 }
Adam Langley95c29f32014-06-20 12:00:00 -0700760
Adam Langleyfcf25832014-12-18 17:42:32 -0800761 alg_mkey = 0;
762 alg_auth = 0;
763 alg_enc = 0;
764 alg_mac = 0;
765 alg_ssl = 0;
766 algo_strength = 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700767
Adam Langleyfcf25832014-12-18 17:42:32 -0800768 for (;;) {
769 ch = *l;
770 buf = l;
771 buflen = 0;
772 while (((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) ||
773 ((ch >= 'a') && (ch <= 'z')) || (ch == '-') || (ch == '.')) {
774 ch = *(++l);
775 buflen++;
776 }
Adam Langley95c29f32014-06-20 12:00:00 -0700777
Adam Langleyfcf25832014-12-18 17:42:32 -0800778 if (buflen == 0) {
779 /* We hit something we cannot deal with, it is no command or separator
780 * nor alphanumeric, so we call this an error. */
781 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
782 SSL_R_INVALID_COMMAND);
783 retval = found = in_group = 0;
784 l++;
785 break;
786 }
Adam Langley95c29f32014-06-20 12:00:00 -0700787
Adam Langleyfcf25832014-12-18 17:42:32 -0800788 if (rule == CIPHER_SPECIAL) {
789 found = 0; /* unused -- avoid compiler warning */
790 break; /* special treatment */
791 }
Adam Langley95c29f32014-06-20 12:00:00 -0700792
Adam Langleyfcf25832014-12-18 17:42:32 -0800793 /* check for multi-part specification */
794 if (ch == '+') {
795 multi = 1;
796 l++;
797 } else {
798 multi = 0;
799 }
Adam Langley95c29f32014-06-20 12:00:00 -0700800
Adam Langleyfcf25832014-12-18 17:42:32 -0800801 /* Now search for the cipher alias in the ca_list. Be careful with the
802 * strncmp, because the "buflen" limitation will make the rule "ADH:SOME"
803 * and the cipher "ADH-MY-CIPHER" look like a match for buflen=3. So
804 * additionally check whether the cipher name found has the correct
805 * length. We can save a strlen() call: just checking for the '\0' at the
806 * right place is sufficient, we have to strncmp() anyway. (We cannot use
807 * strcmp(), because buf is not '\0' terminated.) */
808 j = found = 0;
809 cipher_id = 0;
810 while (ca_list[j]) {
811 if (!strncmp(buf, ca_list[j]->name, buflen) &&
812 (ca_list[j]->name[buflen] == '\0')) {
813 found = 1;
814 break;
815 } else {
816 j++;
817 }
818 }
Adam Langley95c29f32014-06-20 12:00:00 -0700819
Adam Langleyfcf25832014-12-18 17:42:32 -0800820 if (!found) {
821 break; /* ignore this entry */
822 }
Adam Langley95c29f32014-06-20 12:00:00 -0700823
Adam Langleyfcf25832014-12-18 17:42:32 -0800824 if (ca_list[j]->algorithm_mkey) {
825 if (alg_mkey) {
826 alg_mkey &= ca_list[j]->algorithm_mkey;
827 if (!alg_mkey) {
828 found = 0;
829 break;
830 }
831 } else {
832 alg_mkey = ca_list[j]->algorithm_mkey;
833 }
834 }
Adam Langley95c29f32014-06-20 12:00:00 -0700835
Adam Langleyfcf25832014-12-18 17:42:32 -0800836 if (ca_list[j]->algorithm_auth) {
837 if (alg_auth) {
838 alg_auth &= ca_list[j]->algorithm_auth;
839 if (!alg_auth) {
840 found = 0;
841 break;
842 }
843 } else {
844 alg_auth = ca_list[j]->algorithm_auth;
845 }
846 }
Adam Langley95c29f32014-06-20 12:00:00 -0700847
Adam Langleyfcf25832014-12-18 17:42:32 -0800848 if (ca_list[j]->algorithm_enc) {
849 if (alg_enc) {
850 alg_enc &= ca_list[j]->algorithm_enc;
851 if (!alg_enc) {
852 found = 0;
853 break;
854 }
855 } else {
856 alg_enc = ca_list[j]->algorithm_enc;
857 }
858 }
Adam Langley95c29f32014-06-20 12:00:00 -0700859
Adam Langleyfcf25832014-12-18 17:42:32 -0800860 if (ca_list[j]->algorithm_mac) {
861 if (alg_mac) {
862 alg_mac &= ca_list[j]->algorithm_mac;
863 if (!alg_mac) {
864 found = 0;
865 break;
866 }
867 } else {
868 alg_mac = ca_list[j]->algorithm_mac;
869 }
870 }
Adam Langley858a88d2014-06-20 12:00:00 -0700871
Adam Langleyfcf25832014-12-18 17:42:32 -0800872 if (ca_list[j]->algo_strength) {
873 if (algo_strength) {
874 algo_strength &= ca_list[j]->algo_strength;
875 if (!algo_strength) {
876 found = 0;
877 break;
878 }
879 } else {
880 algo_strength |= ca_list[j]->algo_strength;
881 }
882 }
Adam Langley95c29f32014-06-20 12:00:00 -0700883
Adam Langleyfcf25832014-12-18 17:42:32 -0800884 if (ca_list[j]->valid) {
885 /* explicit ciphersuite found; its protocol version does not become
886 * part of the search pattern! */
887 cipher_id = ca_list[j]->id;
888 } else {
889 /* not an explicit ciphersuite; only in this case, the protocol version
890 * is considered part of the search pattern. */
891 if (ca_list[j]->algorithm_ssl) {
892 if (alg_ssl) {
893 alg_ssl &= ca_list[j]->algorithm_ssl;
894 if (!alg_ssl) {
895 found = 0;
896 break;
897 }
898 } else {
899 alg_ssl = ca_list[j]->algorithm_ssl;
900 }
901 }
902 }
Adam Langley95c29f32014-06-20 12:00:00 -0700903
Adam Langleyfcf25832014-12-18 17:42:32 -0800904 if (!multi) {
905 break;
906 }
907 }
Adam Langley95c29f32014-06-20 12:00:00 -0700908
Adam Langleyfcf25832014-12-18 17:42:32 -0800909 /* Ok, we have the rule, now apply it. */
910 if (rule == CIPHER_SPECIAL) {
911 /* special command */
912 ok = 0;
913 if (buflen == 8 && !strncmp(buf, "STRENGTH", 8)) {
914 ok = ssl_cipher_strength_sort(head_p, tail_p);
915 } else {
916 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
917 SSL_R_INVALID_COMMAND);
918 }
Adam Langley95c29f32014-06-20 12:00:00 -0700919
Adam Langleyfcf25832014-12-18 17:42:32 -0800920 if (ok == 0) {
921 retval = 0;
922 }
Adam Langley95c29f32014-06-20 12:00:00 -0700923
Adam Langleyfcf25832014-12-18 17:42:32 -0800924 /* We do not support any "multi" options together with "@", so throw away
925 * the rest of the command, if any left, until end or ':' is found. */
926 while (*l != '\0' && !ITEM_SEP(*l)) {
927 l++;
928 }
929 } else if (found) {
930 ssl_cipher_apply_rule(cipher_id, alg_mkey, alg_auth, alg_enc, alg_mac,
931 alg_ssl, algo_strength, rule, -1, in_group, head_p,
932 tail_p);
933 } else {
934 while (*l != '\0' && !ITEM_SEP(*l)) {
935 l++;
936 }
937 }
938 }
Adam Langley95c29f32014-06-20 12:00:00 -0700939
Adam Langleyfcf25832014-12-18 17:42:32 -0800940 if (in_group) {
941 OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND);
942 retval = 0;
943 }
Adam Langley95c29f32014-06-20 12:00:00 -0700944
Adam Langleyfcf25832014-12-18 17:42:32 -0800945 return retval;
946}
Adam Langley95c29f32014-06-20 12:00:00 -0700947
Adam Langleyfcf25832014-12-18 17:42:32 -0800948STACK_OF(SSL_CIPHER) *
949ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
950 struct ssl_cipher_preference_list_st **cipher_list,
951 STACK_OF(SSL_CIPHER) * *cipher_list_by_id,
952 const char *rule_str, CERT *c) {
953 int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
954 STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
955 const char *rule_p;
956 CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
957 const SSL_CIPHER **ca_list = NULL;
958 uint8_t *in_group_flags = NULL;
959 unsigned int num_in_group_flags = 0;
960 struct ssl_cipher_preference_list_st *pref_list = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700961
Adam Langleyfcf25832014-12-18 17:42:32 -0800962 /* Return with error if nothing to do. */
963 if (rule_str == NULL || cipher_list == NULL) {
964 return NULL;
965 }
David Benjamin5213df42014-08-20 14:19:54 -0400966
Adam Langleyfcf25832014-12-18 17:42:32 -0800967 /* Now we have to collect the available ciphers from the compiled in ciphers.
968 * We cannot get more than the number compiled in, so it is used for
969 * allocation. */
970 num_of_ciphers = ssl_method->num_ciphers();
971 co_list =
972 (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
973 if (co_list == NULL) {
974 OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
975 return NULL;
976 }
Adam Langley95c29f32014-06-20 12:00:00 -0700977
Adam Langleyfcf25832014-12-18 17:42:32 -0800978 ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, co_list, &head, &tail);
Adam Langley95c29f32014-06-20 12:00:00 -0700979
Adam Langleyfcf25832014-12-18 17:42:32 -0800980 /* Now arrange all ciphers by preference:
981 * TODO(davidben): Compute this order once and copy it. */
Adam Langley95c29f32014-06-20 12:00:00 -0700982
Adam Langleyfcf25832014-12-18 17:42:32 -0800983 /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
984 * key exchange mechanisms */
985 ssl_cipher_apply_rule(0, SSL_kEECDH, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, -1,
986 0, &head, &tail);
987 ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
988 &tail);
989 ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head,
990 &tail);
Adam Langley95c29f32014-06-20 12:00:00 -0700991
Adam Langleyfcf25832014-12-18 17:42:32 -0800992 /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer
993 * CHACHA20 unless there is hardware support for fast and constant-time
994 * AES_GCM. */
995 if (EVP_has_aes_hardware()) {
996 ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
997 &head, &tail);
998 ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
999 &head, &tail);
1000 ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD,
1001 -1, 0, &head, &tail);
1002 } else {
1003 ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD,
1004 -1, 0, &head, &tail);
1005 ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
1006 &head, &tail);
1007 ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
1008 &head, &tail);
1009 }
Adam Langley95c29f32014-06-20 12:00:00 -07001010
Adam Langleyfcf25832014-12-18 17:42:32 -08001011 /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, RC4_128_SHA,
1012 * RC4_128_MD5, 3DES_EDE_CBC_SHA. */
1013 ssl_cipher_apply_rule(0, 0, 0, SSL_AES256, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
1014 &tail);
1015 ssl_cipher_apply_rule(0, 0, 0, SSL_AES128, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
1016 &tail);
1017 ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, ~SSL_MD5, 0, 0, CIPHER_ADD, -1, 0,
1018 &head, &tail);
1019 ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, SSL_MD5, 0, 0, CIPHER_ADD, -1, 0,
1020 &head, &tail);
1021 ssl_cipher_apply_rule(0, 0, 0, SSL_3DES, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
1022 &tail);
Adam Langley95c29f32014-06-20 12:00:00 -07001023
Adam Langleyfcf25832014-12-18 17:42:32 -08001024 /* Temporarily enable everything else for sorting */
1025 ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
Adam Langley95c29f32014-06-20 12:00:00 -07001026
Adam Langleyfcf25832014-12-18 17:42:32 -08001027 /* Move ciphers without forward secrecy to the end. */
1028 ssl_cipher_apply_rule(0, ~(SSL_kEDH | SSL_kEECDH), 0, 0, 0, 0, 0, CIPHER_ORD,
1029 -1, 0, &head, &tail);
Adam Langley95c29f32014-06-20 12:00:00 -07001030
Adam Langleyfcf25832014-12-18 17:42:32 -08001031 /* Move anonymous ciphers to the end. Usually, these will remain disabled.
1032 * (For applications that allow them, they aren't too bad, but we prefer
1033 * authenticated ciphers.)
1034 * TODO(davidben): Remove them altogether? */
1035 ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
1036 &tail);
Adam Langley95c29f32014-06-20 12:00:00 -07001037
Adam Langleyfcf25832014-12-18 17:42:32 -08001038 /* Now disable everything (maintaining the ordering!) */
1039 ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
Adam Langley95c29f32014-06-20 12:00:00 -07001040
Adam Langleyfcf25832014-12-18 17:42:32 -08001041 /* We also need cipher aliases for selecting based on the rule_str. There
1042 * might be two types of entries in the rule_str: 1) names of ciphers
1043 * themselves 2) aliases for groups of ciphers. For 1) we need the available
1044 * ciphers and for 2) the cipher groups of cipher_aliases added together in
1045 * one list (otherwise we would be happy with just the cipher_aliases
1046 * table). */
1047 num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER);
1048 num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
1049 ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
1050 if (ca_list == NULL) {
1051 OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
1052 goto err;
1053 }
1054 ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, head);
Adam Langley95c29f32014-06-20 12:00:00 -07001055
Adam Langleyfcf25832014-12-18 17:42:32 -08001056 /* If the rule_string begins with DEFAULT, apply the default rule before
1057 * using the (possibly available) additional rules. */
1058 ok = 1;
1059 rule_p = rule_str;
1060 if (strncmp(rule_str, "DEFAULT", 7) == 0) {
1061 ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, &head, &tail,
1062 ca_list);
1063 rule_p += 7;
1064 if (*rule_p == ':') {
1065 rule_p++;
1066 }
1067 }
Adam Langley858a88d2014-06-20 12:00:00 -07001068
Adam Langleyfcf25832014-12-18 17:42:32 -08001069 if (ok && strlen(rule_p) > 0) {
1070 ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list);
1071 }
Adam Langley95c29f32014-06-20 12:00:00 -07001072
Nick Harper4dd053e2014-12-22 14:58:54 -08001073 OPENSSL_free((void *)ca_list); /* Not needed anymore */
Adam Langley0b5c1ac2014-06-20 12:00:00 -07001074
Adam Langleyfcf25832014-12-18 17:42:32 -08001075 if (!ok) {
1076 goto err;
1077 }
1078
1079 /* Allocate new "cipherstack" for the result, return with error
1080 * if we cannot get one. */
1081 cipherstack = sk_SSL_CIPHER_new_null();
1082 if (cipherstack == NULL) {
1083 goto err;
1084 }
1085
1086 in_group_flags = OPENSSL_malloc(num_of_ciphers);
1087 if (!in_group_flags) {
1088 goto err;
1089 }
1090
1091 /* The cipher selection for the list is done. The ciphers are added
1092 * to the resulting precedence to the STACK_OF(SSL_CIPHER). */
1093 for (curr = head; curr != NULL; curr = curr->next) {
1094 if (curr->active) {
1095 sk_SSL_CIPHER_push(cipherstack, curr->cipher);
1096 in_group_flags[num_in_group_flags++] = curr->in_group;
1097 }
1098 }
1099 OPENSSL_free(co_list); /* Not needed any longer */
1100 co_list = NULL;
1101
1102 tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
1103 if (tmp_cipher_list == NULL) {
1104 goto err;
1105 }
1106 pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
1107 if (!pref_list) {
1108 goto err;
1109 }
1110 pref_list->ciphers = cipherstack;
1111 pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
1112 if (!pref_list->in_group_flags) {
1113 goto err;
1114 }
1115 memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
1116 OPENSSL_free(in_group_flags);
1117 in_group_flags = NULL;
1118 if (*cipher_list != NULL) {
1119 ssl_cipher_preference_list_free(*cipher_list);
1120 }
1121 *cipher_list = pref_list;
1122 pref_list = NULL;
1123
1124 if (cipher_list_by_id != NULL) {
1125 if (*cipher_list_by_id != NULL) {
1126 sk_SSL_CIPHER_free(*cipher_list_by_id);
1127 }
1128 *cipher_list_by_id = tmp_cipher_list;
1129 tmp_cipher_list = NULL;
Adam Langleya307dfd2015-01-09 15:42:58 -08001130 (void) sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp);
Adam Langleyfcf25832014-12-18 17:42:32 -08001131
1132 sk_SSL_CIPHER_sort(*cipher_list_by_id);
1133 } else {
1134 sk_SSL_CIPHER_free(tmp_cipher_list);
1135 tmp_cipher_list = NULL;
1136 }
1137
1138 return cipherstack;
Adam Langley858a88d2014-06-20 12:00:00 -07001139
1140err:
Adam Langleyfcf25832014-12-18 17:42:32 -08001141 if (co_list) {
1142 OPENSSL_free(co_list);
1143 }
1144 if (in_group_flags) {
1145 OPENSSL_free(in_group_flags);
1146 }
1147 if (cipherstack) {
1148 sk_SSL_CIPHER_free(cipherstack);
1149 }
1150 if (tmp_cipher_list) {
1151 sk_SSL_CIPHER_free(tmp_cipher_list);
1152 }
1153 if (pref_list && pref_list->in_group_flags) {
1154 OPENSSL_free(pref_list->in_group_flags);
1155 }
1156 if (pref_list) {
1157 OPENSSL_free(pref_list);
1158 }
1159 return NULL;
1160}
Adam Langley95c29f32014-06-20 12:00:00 -07001161
Adam Langleyfcf25832014-12-18 17:42:32 -08001162const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf,
1163 int len) {
1164 const char *ver;
1165 const char *kx, *au, *enc, *mac;
1166 unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl;
1167 static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
Adam Langley95c29f32014-06-20 12:00:00 -07001168
Adam Langleyfcf25832014-12-18 17:42:32 -08001169 alg_mkey = cipher->algorithm_mkey;
1170 alg_auth = cipher->algorithm_auth;
1171 alg_enc = cipher->algorithm_enc;
1172 alg_mac = cipher->algorithm_mac;
1173 alg_ssl = cipher->algorithm_ssl;
Adam Langley95c29f32014-06-20 12:00:00 -07001174
Adam Langleyfcf25832014-12-18 17:42:32 -08001175 if (alg_ssl & SSL_SSLV3) {
1176 ver = "SSLv3";
1177 } else if (alg_ssl & SSL_TLSV1_2) {
1178 ver = "TLSv1.2";
1179 } else {
1180 ver = "unknown";
1181 }
Adam Langley95c29f32014-06-20 12:00:00 -07001182
Adam Langleyfcf25832014-12-18 17:42:32 -08001183 switch (alg_mkey) {
1184 case SSL_kRSA:
1185 kx = "RSA";
1186 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001187
Adam Langleyfcf25832014-12-18 17:42:32 -08001188 case SSL_kEDH:
1189 kx = "DH";
1190 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001191
Adam Langleyfcf25832014-12-18 17:42:32 -08001192 case SSL_kEECDH:
1193 kx = "ECDH";
1194 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001195
Adam Langleyfcf25832014-12-18 17:42:32 -08001196 case SSL_kPSK:
1197 kx = "PSK";
1198 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001199
Adam Langleyfcf25832014-12-18 17:42:32 -08001200 default:
1201 kx = "unknown";
1202 }
Adam Langley95c29f32014-06-20 12:00:00 -07001203
Adam Langleyfcf25832014-12-18 17:42:32 -08001204 switch (alg_auth) {
1205 case SSL_aRSA:
1206 au = "RSA";
1207 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001208
Adam Langleyfcf25832014-12-18 17:42:32 -08001209 case SSL_aNULL:
1210 au = "None";
1211 break;
Adam Langley4d4bff82014-06-20 12:00:00 -07001212
Adam Langleyfcf25832014-12-18 17:42:32 -08001213 case SSL_aECDSA:
1214 au = "ECDSA";
1215 break;
Adam Langley4d4bff82014-06-20 12:00:00 -07001216
Adam Langleyfcf25832014-12-18 17:42:32 -08001217 case SSL_aPSK:
1218 au = "PSK";
1219 break;
Adam Langley4d4bff82014-06-20 12:00:00 -07001220
Adam Langleyfcf25832014-12-18 17:42:32 -08001221 default:
1222 au = "unknown";
1223 break;
1224 }
Adam Langleyde0b2022014-06-20 12:00:00 -07001225
Adam Langleyfcf25832014-12-18 17:42:32 -08001226 switch (alg_enc) {
1227 case SSL_3DES:
1228 enc = "3DES(168)";
1229 break;
Adam Langley95c29f32014-06-20 12:00:00 -07001230
Adam Langleyfcf25832014-12-18 17:42:32 -08001231 case SSL_RC4:
1232 enc = "RC4(128)";
1233 break;
1234
1235 case SSL_AES128:
1236 enc = "AES(128)";
1237 break;
1238
1239 case SSL_AES256:
1240 enc = "AES(256)";
1241 break;
1242
1243 case SSL_AES128GCM:
1244 enc = "AESGCM(128)";
1245 break;
1246
1247 case SSL_AES256GCM:
1248 enc = "AESGCM(256)";
1249 break;
1250
1251 case SSL_CHACHA20POLY1305:
1252 enc = "ChaCha20-Poly1305";
1253 break;
1254
1255 default:
1256 enc = "unknown";
1257 break;
1258 }
1259
1260 switch (alg_mac) {
1261 case SSL_MD5:
1262 mac = "MD5";
1263 break;
1264
1265 case SSL_SHA1:
1266 mac = "SHA1";
1267 break;
1268
1269 case SSL_SHA256:
1270 mac = "SHA256";
1271 break;
1272
1273 case SSL_SHA384:
1274 mac = "SHA384";
1275 break;
1276
1277 case SSL_AEAD:
1278 mac = "AEAD";
1279 break;
1280
1281 default:
1282 mac = "unknown";
1283 break;
1284 }
1285
1286 if (buf == NULL) {
1287 len = 128;
1288 buf = OPENSSL_malloc(len);
1289 if (buf == NULL)
1290 return "OPENSSL_malloc Error";
1291 } else if (len < 128) {
1292 return "Buffer too small";
1293 }
1294
1295 BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac);
1296 return buf;
1297}
1298
1299int SSL_CIPHER_is_AES(const SSL_CIPHER *c) {
1300 return (c->algorithm_enc & SSL_AES) != 0;
1301}
1302
1303int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c) {
1304 return (c->algorithm_mac & SSL_MD5) != 0;
1305}
1306
1307int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c) {
1308 return (c->algorithm_mac & (SSL_AES128GCM | SSL_AES256GCM)) != 0;
1309}
1310
1311int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c) {
1312 return (c->algorithm_enc & SSL_CHACHA20POLY1305) != 0;
1313}
1314
1315const char *SSL_CIPHER_get_version(const SSL_CIPHER *c) {
1316 int i;
1317
1318 if (c == NULL) {
1319 return "(NONE)";
1320 }
1321
1322 i = (int)(c->id >> 24L);
1323 if (i == 3) {
1324 return "TLSv1/SSLv3";
1325 } else if (i == 2) {
1326 return "SSLv2";
1327 } else {
1328 return "unknown";
1329 }
1330}
Adam Langley95c29f32014-06-20 12:00:00 -07001331
1332/* return the actual cipher being used */
Adam Langleyfcf25832014-12-18 17:42:32 -08001333const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) {
1334 if (c != NULL) {
1335 return c->name;
1336 }
1337
1338 return "(NONE)";
1339}
Adam Langley95c29f32014-06-20 12:00:00 -07001340
Adam Langleyf1df2b32014-08-11 17:37:53 -07001341const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
1342 if (cipher == NULL) {
1343 return "";
1344 }
1345
1346 switch (cipher->algorithm_mkey) {
1347 case SSL_kRSA:
1348 return SSL_TXT_RSA;
Adam Langleyfcf25832014-12-18 17:42:32 -08001349
Adam Langleyf1df2b32014-08-11 17:37:53 -07001350 case SSL_kEDH:
1351 switch (cipher->algorithm_auth) {
Adam Langleyf1df2b32014-08-11 17:37:53 -07001352 case SSL_aRSA:
1353 return "DHE_" SSL_TXT_RSA;
1354 case SSL_aNULL:
1355 return SSL_TXT_DH "_anon";
1356 default:
1357 return "UNKNOWN";
1358 }
Adam Langleyfcf25832014-12-18 17:42:32 -08001359
Adam Langleyf1df2b32014-08-11 17:37:53 -07001360 case SSL_kEECDH:
1361 switch (cipher->algorithm_auth) {
1362 case SSL_aECDSA:
1363 return "ECDHE_" SSL_TXT_ECDSA;
1364 case SSL_aRSA:
1365 return "ECDHE_" SSL_TXT_RSA;
1366 case SSL_aNULL:
1367 return SSL_TXT_ECDH "_anon";
1368 default:
1369 return "UNKNOWN";
1370 }
Adam Langleyfcf25832014-12-18 17:42:32 -08001371
Adam Langleyf1df2b32014-08-11 17:37:53 -07001372 default:
1373 return "UNKNOWN";
1374 }
1375}
1376
Adam Langley95c29f32014-06-20 12:00:00 -07001377/* number of bits for symmetric cipher */
Adam Langleyfcf25832014-12-18 17:42:32 -08001378int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) {
1379 int ret = 0;
Adam Langley95c29f32014-06-20 12:00:00 -07001380
Adam Langleyfcf25832014-12-18 17:42:32 -08001381 if (c != NULL) {
1382 if (alg_bits != NULL) {
1383 *alg_bits = c->alg_bits;
1384 }
1385 ret = c->strength_bits;
1386 }
Adam Langley95c29f32014-06-20 12:00:00 -07001387
Adam Langleyfcf25832014-12-18 17:42:32 -08001388 return ret;
1389}
Adam Langley95c29f32014-06-20 12:00:00 -07001390
Adam Langleyfcf25832014-12-18 17:42:32 -08001391unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c) { return c->id; }
Adam Langley95c29f32014-06-20 12:00:00 -07001392
Adam Langleyfcf25832014-12-18 17:42:32 -08001393void *SSL_COMP_get_compression_methods(void) { return NULL; }
1394
1395int SSL_COMP_add_compression_method(int id, void *cm) { return 1; }
1396
1397const char *SSL_COMP_get_name(const void *comp) { return NULL; }
Adam Langley95c29f32014-06-20 12:00:00 -07001398
1399/* For a cipher return the index corresponding to the certificate type */
Adam Langleyfcf25832014-12-18 17:42:32 -08001400int ssl_cipher_get_cert_index(const SSL_CIPHER *c) {
1401 unsigned long alg_a = c->algorithm_auth;
Adam Langley95c29f32014-06-20 12:00:00 -07001402
Adam Langleyfcf25832014-12-18 17:42:32 -08001403 if (alg_a & SSL_aECDSA) {
1404 return SSL_PKEY_ECC;
1405 } else if (alg_a & SSL_aRSA) {
1406 return SSL_PKEY_RSA_ENC;
1407 }
Adam Langley95c29f32014-06-20 12:00:00 -07001408
Adam Langleyfcf25832014-12-18 17:42:32 -08001409 return -1;
1410}
David Benjamin9c651c92014-07-12 13:27:45 -04001411
Adam Langleyfcf25832014-12-18 17:42:32 -08001412/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server
1413 * public key in the key exchange, sent in a server Certificate message.
1414 * Otherwise it returns 0. */
1415int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) {
1416 /* Anonymous ciphers do not include a server certificate. */
1417 if (cipher->algorithm_auth & SSL_aNULL) {
1418 return 0;
1419 }
1420
1421 /* Neither do PSK ciphers, except for RSA_PSK. */
1422 if ((cipher->algorithm_auth & SSL_aPSK) &&
1423 !(cipher->algorithm_mkey & SSL_kRSA)) {
1424 return 0;
1425 }
1426
1427 /* All other ciphers include it. */
1428 return 1;
1429}
1430
1431/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a
1432 * ServerKeyExchange message. Otherwise it returns 0.
David Benjamin9c651c92014-07-12 13:27:45 -04001433 *
1434 * Unlike ssl_cipher_has_server_public_key, some ciphers take optional
Adam Langleyfcf25832014-12-18 17:42:32 -08001435 * ServerKeyExchanges. PSK and RSA_PSK only use the ServerKeyExchange to
1436 * communicate a psk_identity_hint, so it is optional. */
1437int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
1438 /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
1439 if (cipher->algorithm_mkey & SSL_kEDH || cipher->algorithm_mkey & SSL_kEECDH) {
1440 return 1;
1441 }
1442
1443 /* It is optional in all others. */
1444 return 0;
1445}