/src/gnutls/lib/algorithms/ciphers.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2011-2012 Free Software Foundation, Inc. |
3 | | * |
4 | | * Author: Nikos Mavrogiannopoulos |
5 | | * |
6 | | * This file is part of GnuTLS. |
7 | | * |
8 | | * The GnuTLS is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public License |
10 | | * as published by the Free Software Foundation; either version 2.1 of |
11 | | * the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, but |
14 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
20 | | * |
21 | | */ |
22 | | |
23 | | #include "gnutls_int.h" |
24 | | #include <algorithms.h> |
25 | | #include "errors.h" |
26 | | #include <x509/common.h> |
27 | | #include "c-strcase.h" |
28 | | |
29 | | /* Note that all algorithms are in CBC or STREAM modes. |
30 | | * Do not add any algorithms in other modes (avoid modified algorithms). |
31 | | * View first: "The order of encryption and authentication for |
32 | | * protecting communications" by Hugo Krawczyk - CRYPTO 2001 |
33 | | * |
34 | | * On update, make sure to update MAX_CIPHER_BLOCK_SIZE, MAX_CIPHER_IV_SIZE, |
35 | | * and MAX_CIPHER_KEY_SIZE as well. |
36 | | * If any ciphers are removed, remove them from the back-end but |
37 | | * keep them in that list to allow backwards compatibility with applications |
38 | | * that specify them (they will be a no-op). |
39 | | */ |
40 | | static const cipher_entry_st algorithms[] = { |
41 | | {.name = "AES-256-CBC", |
42 | | .id = GNUTLS_CIPHER_AES_256_CBC, |
43 | | .blocksize = 16, |
44 | | .keysize = 32, |
45 | | .type = CIPHER_BLOCK, |
46 | | .explicit_iv = 16, |
47 | | .cipher_iv = 16}, |
48 | | {.name = "AES-192-CBC", |
49 | | .id = GNUTLS_CIPHER_AES_192_CBC, |
50 | | .blocksize = 16, |
51 | | .keysize = 24, |
52 | | .type = CIPHER_BLOCK, |
53 | | .explicit_iv = 16, |
54 | | .cipher_iv = 16}, |
55 | | {.name = "AES-128-CBC", |
56 | | .id = GNUTLS_CIPHER_AES_128_CBC, |
57 | | .blocksize = 16, |
58 | | .keysize = 16, |
59 | | .type = CIPHER_BLOCK, |
60 | | .explicit_iv = 16, |
61 | | .cipher_iv = 16}, |
62 | | {.name = "AES-128-GCM", |
63 | | .id = GNUTLS_CIPHER_AES_128_GCM, |
64 | | .blocksize = 16, |
65 | | .keysize = 16, |
66 | | .type = CIPHER_AEAD, |
67 | | .implicit_iv = 4, |
68 | | .explicit_iv = 8, |
69 | | .cipher_iv = 12, |
70 | | .tagsize = 16}, |
71 | | {.name = "AES-192-GCM", |
72 | | .id = GNUTLS_CIPHER_AES_192_GCM, |
73 | | .blocksize = 16, |
74 | | .keysize = 24, |
75 | | .type = CIPHER_AEAD, |
76 | | .implicit_iv = 4, |
77 | | .explicit_iv = 8, |
78 | | .cipher_iv = 12, |
79 | | .tagsize = 16}, |
80 | | {.name = "AES-256-GCM", |
81 | | .id = GNUTLS_CIPHER_AES_256_GCM, |
82 | | .blocksize = 16, |
83 | | .keysize = 32, |
84 | | .type = CIPHER_AEAD, |
85 | | .implicit_iv = 4, |
86 | | .explicit_iv = 8, |
87 | | .cipher_iv = 12, |
88 | | .tagsize = 16}, |
89 | | {.name = "AES-128-CCM", |
90 | | .id = GNUTLS_CIPHER_AES_128_CCM, |
91 | | .blocksize = 16, |
92 | | .keysize = 16, |
93 | | .type = CIPHER_AEAD, |
94 | | .implicit_iv = 4, |
95 | | .explicit_iv = 8, |
96 | | .cipher_iv = 12, |
97 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, |
98 | | .tagsize = 16}, |
99 | | {.name = "AES-256-CCM", |
100 | | .id = GNUTLS_CIPHER_AES_256_CCM, |
101 | | .blocksize = 16, |
102 | | .keysize = 32, |
103 | | .type = CIPHER_AEAD, |
104 | | .implicit_iv = 4, |
105 | | .explicit_iv = 8, |
106 | | .cipher_iv = 12, |
107 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, |
108 | | .tagsize = 16}, |
109 | | {.name = "AES-128-CCM-8", |
110 | | .id = GNUTLS_CIPHER_AES_128_CCM_8, |
111 | | .blocksize = 16, |
112 | | .keysize = 16, |
113 | | .type = CIPHER_AEAD, |
114 | | .implicit_iv = 4, |
115 | | .explicit_iv = 8, |
116 | | .cipher_iv = 12, |
117 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, |
118 | | .tagsize = 8}, |
119 | | {.name = "AES-256-CCM-8", |
120 | | .id = GNUTLS_CIPHER_AES_256_CCM_8, |
121 | | .blocksize = 16, |
122 | | .keysize = 32, |
123 | | .type = CIPHER_AEAD, |
124 | | .implicit_iv = 4, |
125 | | .explicit_iv = 8, |
126 | | .cipher_iv = 12, |
127 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD, |
128 | | .tagsize = 8}, |
129 | | {.name = "ARCFOUR-128", |
130 | | .id = GNUTLS_CIPHER_ARCFOUR_128, |
131 | | .blocksize = 1, |
132 | | .keysize = 16, |
133 | | .type = CIPHER_STREAM, |
134 | | 0, 0, 0, 0}, |
135 | | {.name = "ESTREAM-SALSA20-256", |
136 | | .id = GNUTLS_CIPHER_ESTREAM_SALSA20_256, |
137 | | .blocksize = 64, |
138 | | .keysize = 32, |
139 | | .type = CIPHER_STREAM, 0, 0, 8, 0}, |
140 | | {.name = "SALSA20-256", |
141 | | .id = GNUTLS_CIPHER_SALSA20_256, |
142 | | .blocksize = 64, |
143 | | .keysize = 32, |
144 | | .type = CIPHER_STREAM, |
145 | | .explicit_iv = 0, |
146 | | .cipher_iv = 8}, |
147 | | {.name = "CHACHA20-32", |
148 | | .id = GNUTLS_CIPHER_CHACHA20_32, |
149 | | .blocksize = 64, |
150 | | .keysize = 32, |
151 | | .type = CIPHER_STREAM, |
152 | | .explicit_iv = 0, |
153 | | /* IV includes counter */ |
154 | | .cipher_iv = 16}, |
155 | | {.name = "CHACHA20-64", |
156 | | .id = GNUTLS_CIPHER_CHACHA20_64, |
157 | | .blocksize = 64, |
158 | | .keysize = 32, |
159 | | .type = CIPHER_STREAM, |
160 | | .explicit_iv = 0, |
161 | | /* IV includes counter */ |
162 | | .cipher_iv = 16}, |
163 | | {.name = "CAMELLIA-256-CBC", |
164 | | .id = GNUTLS_CIPHER_CAMELLIA_256_CBC, |
165 | | .blocksize = 16, |
166 | | .keysize = 32, |
167 | | .type = CIPHER_BLOCK, |
168 | | .explicit_iv = 16, |
169 | | .cipher_iv = 16}, |
170 | | {.name = "CAMELLIA-192-CBC", |
171 | | .id = GNUTLS_CIPHER_CAMELLIA_192_CBC, |
172 | | .blocksize = 16, |
173 | | .keysize = 24, |
174 | | .type = CIPHER_BLOCK, |
175 | | .explicit_iv = 16, |
176 | | .cipher_iv = 16}, |
177 | | {.name = "CAMELLIA-128-CBC", |
178 | | .id = GNUTLS_CIPHER_CAMELLIA_128_CBC, |
179 | | .blocksize = 16, |
180 | | .keysize = 16, |
181 | | .type = CIPHER_BLOCK, |
182 | | .explicit_iv = 16, |
183 | | .cipher_iv = 16}, |
184 | | {.name = "CHACHA20-POLY1305", |
185 | | .id = GNUTLS_CIPHER_CHACHA20_POLY1305, |
186 | | .blocksize = 64, |
187 | | .keysize = 32, |
188 | | .type = CIPHER_AEAD, |
189 | | .implicit_iv = 12, |
190 | | .explicit_iv = 0, |
191 | | /* in chacha20 we don't need a rekey after 2^24 messages */ |
192 | | .flags = GNUTLS_CIPHER_FLAG_XOR_NONCE | GNUTLS_CIPHER_FLAG_NO_REKEY, |
193 | | .cipher_iv = 12, |
194 | | .tagsize = 16}, |
195 | | {.name = "CAMELLIA-128-GCM", |
196 | | .id = GNUTLS_CIPHER_CAMELLIA_128_GCM, |
197 | | .blocksize = 16, |
198 | | .keysize = 16, |
199 | | .type = CIPHER_AEAD, 4, 8, 12, 16}, |
200 | | {.name = "CAMELLIA-256-GCM", |
201 | | .id = GNUTLS_CIPHER_CAMELLIA_256_GCM, |
202 | | .blocksize = 16, |
203 | | .keysize = 32, |
204 | | .type = CIPHER_AEAD, |
205 | | .implicit_iv = 4, |
206 | | .explicit_iv = 8, |
207 | | .cipher_iv = 12, |
208 | | .tagsize = 16}, |
209 | | {.name = "GOST28147-TC26Z-CFB", |
210 | | .id = GNUTLS_CIPHER_GOST28147_TC26Z_CFB, |
211 | | .blocksize = 8, |
212 | | .keysize = 32, |
213 | | .type = CIPHER_STREAM, |
214 | | .implicit_iv = 8, |
215 | | .cipher_iv = 8}, |
216 | | {.name = "GOST28147-CPA-CFB", |
217 | | .id = GNUTLS_CIPHER_GOST28147_CPA_CFB, |
218 | | .blocksize = 8, |
219 | | .keysize = 32, |
220 | | .type = CIPHER_STREAM, |
221 | | .implicit_iv = 8, |
222 | | .cipher_iv = 8}, |
223 | | {.name = "GOST28147-CPB-CFB", |
224 | | .id = GNUTLS_CIPHER_GOST28147_CPB_CFB, |
225 | | .blocksize = 8, |
226 | | .keysize = 32, |
227 | | .type = CIPHER_STREAM, |
228 | | .implicit_iv = 8, |
229 | | .cipher_iv = 8}, |
230 | | {.name = "GOST28147-CPC-CFB", |
231 | | .id = GNUTLS_CIPHER_GOST28147_CPC_CFB, |
232 | | .blocksize = 8, |
233 | | .keysize = 32, |
234 | | .type = CIPHER_STREAM, |
235 | | .implicit_iv = 8, |
236 | | .cipher_iv = 8}, |
237 | | {.name = "GOST28147-CPD-CFB", |
238 | | .id = GNUTLS_CIPHER_GOST28147_CPD_CFB, |
239 | | .blocksize = 8, |
240 | | .keysize = 32, |
241 | | .type = CIPHER_STREAM, |
242 | | .implicit_iv = 8, |
243 | | .cipher_iv = 8}, |
244 | | |
245 | | {.name = "AES-128-CFB8", |
246 | | .id = GNUTLS_CIPHER_AES_128_CFB8, |
247 | | .blocksize = 16, |
248 | | .keysize = 16, |
249 | | .type = CIPHER_BLOCK, |
250 | | .explicit_iv = 16, |
251 | | .cipher_iv = 16}, |
252 | | {.name = "AES-192-CFB8", |
253 | | .id = GNUTLS_CIPHER_AES_192_CFB8, |
254 | | .blocksize = 16, |
255 | | .keysize = 24, |
256 | | .type = CIPHER_BLOCK, |
257 | | .explicit_iv = 16, |
258 | | .cipher_iv = 16}, |
259 | | {.name = "AES-256-CFB8", |
260 | | .id = GNUTLS_CIPHER_AES_256_CFB8, |
261 | | .blocksize = 16, |
262 | | .keysize = 32, |
263 | | .type = CIPHER_BLOCK, |
264 | | .explicit_iv = 16, |
265 | | .cipher_iv = 16}, |
266 | | {.name = "AES-128-XTS", |
267 | | .id = GNUTLS_CIPHER_AES_128_XTS, |
268 | | .blocksize = 16, |
269 | | .keysize = 32, |
270 | | .type = CIPHER_BLOCK, |
271 | | .explicit_iv = 16, |
272 | | .cipher_iv = 16}, |
273 | | {.name = "AES-256-XTS", |
274 | | .id = GNUTLS_CIPHER_AES_256_XTS, |
275 | | .blocksize = 16, |
276 | | .keysize = 64, |
277 | | .type = CIPHER_BLOCK, |
278 | | .explicit_iv = 16, |
279 | | .cipher_iv = 16}, |
280 | | {.name = "AES-128-SIV", |
281 | | .id = GNUTLS_CIPHER_AES_128_SIV, |
282 | | .blocksize = 16, |
283 | | .keysize = 32, |
284 | | .type = CIPHER_AEAD, |
285 | | .explicit_iv = 16, |
286 | | .cipher_iv = 16, |
287 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD | |
288 | | GNUTLS_CIPHER_FLAG_TAG_PREFIXED, |
289 | | .tagsize = 16}, |
290 | | {.name = "AES-256-SIV", |
291 | | .id = GNUTLS_CIPHER_AES_256_SIV, |
292 | | .blocksize = 16, |
293 | | .keysize = 64, |
294 | | .type = CIPHER_AEAD, |
295 | | .explicit_iv = 16, |
296 | | .cipher_iv = 16, |
297 | | .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD | |
298 | | GNUTLS_CIPHER_FLAG_TAG_PREFIXED, |
299 | | .tagsize = 16}, |
300 | | {.name = "GOST28147-TC26Z-CNT", |
301 | | .id = GNUTLS_CIPHER_GOST28147_TC26Z_CNT, |
302 | | .blocksize = 8, |
303 | | .keysize = 32, |
304 | | .type = CIPHER_STREAM, |
305 | | .implicit_iv = 8, |
306 | | .cipher_iv = 8}, |
307 | | {.name = "MAGMA-CTR-ACPKM", |
308 | | .id = GNUTLS_CIPHER_MAGMA_CTR_ACPKM, |
309 | | .blocksize = 8, |
310 | | .keysize = 32, |
311 | | .type = CIPHER_STREAM, |
312 | | .implicit_iv = 4, |
313 | | .cipher_iv = 8}, |
314 | | {.name = "KUZNYECHIK-CTR-ACPKM", |
315 | | .id = GNUTLS_CIPHER_KUZNYECHIK_CTR_ACPKM, |
316 | | .blocksize = 16, |
317 | | .keysize = 32, |
318 | | .type = CIPHER_STREAM, |
319 | | .implicit_iv = 8, |
320 | | .cipher_iv = 16}, |
321 | | {.name = "3DES-CBC", |
322 | | .id = GNUTLS_CIPHER_3DES_CBC, |
323 | | .blocksize = 8, |
324 | | .keysize = 24, |
325 | | .type = CIPHER_BLOCK, |
326 | | .explicit_iv = 8, |
327 | | .cipher_iv = 8}, |
328 | | {.name = "DES-CBC", |
329 | | .id = GNUTLS_CIPHER_DES_CBC, |
330 | | .blocksize = 8, |
331 | | .keysize = 8, |
332 | | .type = CIPHER_BLOCK, |
333 | | .explicit_iv = 8, |
334 | | .cipher_iv = 8}, |
335 | | {.name = "ARCFOUR-40", |
336 | | .id = GNUTLS_CIPHER_ARCFOUR_40, |
337 | | .blocksize = 1, |
338 | | .keysize = 5, |
339 | | .type = CIPHER_STREAM}, |
340 | | {.name = "RC2-40", |
341 | | .id = GNUTLS_CIPHER_RC2_40_CBC, |
342 | | .blocksize = 8, |
343 | | .keysize = 5, |
344 | | .type = CIPHER_BLOCK, |
345 | | .explicit_iv = 8, |
346 | | .cipher_iv = 8}, |
347 | | {.name = "NULL", |
348 | | .id = GNUTLS_CIPHER_NULL, |
349 | | .blocksize = 1, |
350 | | .keysize = 0, |
351 | | .type = CIPHER_STREAM}, |
352 | | {0, 0, 0, 0, 0, 0, 0} |
353 | | }; |
354 | | |
355 | | #define GNUTLS_CIPHER_LOOP(b) \ |
356 | 0 | const cipher_entry_st *p; \ |
357 | 0 | for(p = algorithms; p->name != NULL; p++) { b ; } |
358 | | |
359 | | #define GNUTLS_ALG_LOOP(a) \ |
360 | 0 | GNUTLS_CIPHER_LOOP( if(p->id == algorithm) { a; break; } ) |
361 | | |
362 | | /* CIPHER functions */ |
363 | | |
364 | | const cipher_entry_st *_gnutls_cipher_to_entry(gnutls_cipher_algorithm_t c) |
365 | 0 | { |
366 | 0 | GNUTLS_CIPHER_LOOP(if (c == p->id) return p) ; |
367 | |
|
368 | 0 | return NULL; |
369 | 0 | } |
370 | | |
371 | | /* Returns cipher entry even for ciphers that are not supported, |
372 | | * but are listed (e.g., deprecated ciphers). |
373 | | */ |
374 | | const cipher_entry_st *cipher_name_to_entry(const char *name) |
375 | 0 | { |
376 | 0 | GNUTLS_CIPHER_LOOP(if (c_strcasecmp(p->name, name) == 0) { |
377 | 0 | return p;} |
378 | 0 | ) ; |
379 | |
|
380 | 0 | return NULL; |
381 | 0 | } |
382 | | |
383 | | /** |
384 | | * gnutls_cipher_get_block_size: |
385 | | * @algorithm: is an encryption algorithm |
386 | | * |
387 | | * Returns: the block size of the encryption algorithm. |
388 | | * |
389 | | * Since: 2.10.0 |
390 | | **/ |
391 | | unsigned gnutls_cipher_get_block_size(gnutls_cipher_algorithm_t algorithm) |
392 | 0 | { |
393 | 0 | size_t ret = 0; |
394 | 0 | GNUTLS_ALG_LOOP(ret = p->blocksize); |
395 | 0 | return ret; |
396 | |
|
397 | 0 | } |
398 | | |
399 | | /** |
400 | | * gnutls_cipher_get_tag_size: |
401 | | * @algorithm: is an encryption algorithm |
402 | | * |
403 | | * This function returns the tag size of an authenticated encryption |
404 | | * algorithm. For non-AEAD algorithms, it returns zero. |
405 | | * |
406 | | * Returns: the tag size of the authenticated encryption algorithm. |
407 | | * |
408 | | * Since: 3.2.2 |
409 | | **/ |
410 | | unsigned gnutls_cipher_get_tag_size(gnutls_cipher_algorithm_t algorithm) |
411 | 0 | { |
412 | 0 | return _gnutls_cipher_get_tag_size(cipher_to_entry(algorithm)); |
413 | 0 | } |
414 | | |
415 | | /** |
416 | | * gnutls_cipher_get_iv_size: |
417 | | * @algorithm: is an encryption algorithm |
418 | | * |
419 | | * This function returns the size of the initialization vector (IV) for the |
420 | | * provided algorithm. For algorithms with variable size IV (e.g., AES-CCM), |
421 | | * the returned size will be the one used by TLS. |
422 | | * |
423 | | * Returns: block size for encryption algorithm. |
424 | | * |
425 | | * Since: 3.2.0 |
426 | | **/ |
427 | | unsigned gnutls_cipher_get_iv_size(gnutls_cipher_algorithm_t algorithm) |
428 | 0 | { |
429 | 0 | size_t ret = 0; |
430 | 0 | GNUTLS_ALG_LOOP(ret = p->cipher_iv); |
431 | 0 | return ret; |
432 | 0 | } |
433 | | |
434 | | /** |
435 | | * gnutls_cipher_get_key_size: |
436 | | * @algorithm: is an encryption algorithm |
437 | | * |
438 | | * This function returns the key size of the provided algorithm. |
439 | | * |
440 | | * Returns: length (in bytes) of the given cipher's key size, or 0 if |
441 | | * the given cipher is invalid. |
442 | | **/ |
443 | | size_t gnutls_cipher_get_key_size(gnutls_cipher_algorithm_t algorithm) |
444 | 0 | { /* In bytes */ |
445 | 0 | size_t ret = 0; |
446 | 0 | GNUTLS_ALG_LOOP(ret = p->keysize); |
447 | 0 | return ret; |
448 | |
|
449 | 0 | } |
450 | | |
451 | | /** |
452 | | * gnutls_cipher_get_name: |
453 | | * @algorithm: is an encryption algorithm |
454 | | * |
455 | | * Convert a #gnutls_cipher_algorithm_t type to a string. |
456 | | * |
457 | | * Returns: a pointer to a string that contains the name of the |
458 | | * specified cipher, or %NULL. |
459 | | **/ |
460 | | const char *gnutls_cipher_get_name(gnutls_cipher_algorithm_t algorithm) |
461 | 0 | { |
462 | 0 | const char *ret = NULL; |
463 | | |
464 | | /* avoid prefix */ |
465 | 0 | GNUTLS_ALG_LOOP(ret = p->name); |
466 | |
|
467 | 0 | return ret; |
468 | 0 | } |
469 | | |
470 | | /** |
471 | | * gnutls_cipher_get_id: |
472 | | * @name: is a cipher algorithm name |
473 | | * |
474 | | * The names are compared in a case insensitive way. |
475 | | * |
476 | | * Returns: return a #gnutls_cipher_algorithm_t value corresponding to |
477 | | * the specified cipher, or %GNUTLS_CIPHER_UNKNOWN on error. |
478 | | **/ |
479 | | gnutls_cipher_algorithm_t gnutls_cipher_get_id(const char *name) |
480 | 0 | { |
481 | 0 | gnutls_cipher_algorithm_t ret = GNUTLS_CIPHER_UNKNOWN; |
482 | |
|
483 | 0 | GNUTLS_CIPHER_LOOP(if (c_strcasecmp(p->name, name) == 0) { |
484 | 0 | if (p->id == GNUTLS_CIPHER_NULL |
485 | 0 | || _gnutls_cipher_exists(p->id)) |
486 | 0 | ret = p->id; break;} |
487 | 0 | ) ; |
488 | |
|
489 | 0 | return ret; |
490 | 0 | } |
491 | | |
492 | | /** |
493 | | * gnutls_cipher_list: |
494 | | * |
495 | | * Get a list of supported cipher algorithms. Note that not |
496 | | * necessarily all ciphers are supported as TLS cipher suites. For |
497 | | * example, DES is not supported as a cipher suite, but is supported |
498 | | * for other purposes (e.g., PKCS#8 or similar). |
499 | | * |
500 | | * This function is not thread safe. |
501 | | * |
502 | | * Returns: a (0)-terminated list of #gnutls_cipher_algorithm_t |
503 | | * integers indicating the available ciphers. |
504 | | * |
505 | | **/ |
506 | | const gnutls_cipher_algorithm_t *gnutls_cipher_list(void) |
507 | 0 | { |
508 | 0 | static gnutls_cipher_algorithm_t supported_ciphers[MAX_ALGOS] = { 0 }; |
509 | |
|
510 | 0 | if (supported_ciphers[0] == 0) { |
511 | 0 | int i = 0; |
512 | |
|
513 | 0 | GNUTLS_CIPHER_LOOP(if |
514 | 0 | (p->id == GNUTLS_CIPHER_NULL |
515 | 0 | || _gnutls_cipher_exists(p->id)) |
516 | 0 | supported_ciphers[i++] = p->id;) ; |
517 | 0 | supported_ciphers[i++] = 0; |
518 | 0 | } |
519 | |
|
520 | 0 | return supported_ciphers; |
521 | 0 | } |