cleaned up errno handling.
[gnutls.git] / lib / algorithms / ciphers.c
blob7c88231da20937f5d15ac1c2d1c2fd7c261cda5a
1 /*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <algorithms.h>
25 #include <gnutls_errors.h>
26 #include <x509/common.h>
28 struct gnutls_cipher_entry
30 const char *name;
31 gnutls_cipher_algorithm_t id;
32 uint16_t blocksize;
33 uint16_t keysize;
34 unsigned block:1;
35 uint16_t iv; /* the size of IV */
36 unsigned export_flag:1; /* 0 non export */
37 unsigned auth:1; /* Whether it is authenc cipher */
39 typedef struct gnutls_cipher_entry gnutls_cipher_entry;
41 /* Note that all algorithms are in CBC or STREAM modes.
42 * Do not add any algorithms in other modes (avoid modified algorithms).
43 * View first: "The order of encryption and authentication for
44 * protecting communications" by Hugo Krawczyk - CRYPTO 2001
46 * Make sure to update MAX_CIPHER_BLOCK_SIZE and MAX_CIPHER_KEY_SIZE as well.
48 static const gnutls_cipher_entry algorithms[] = {
49 {"AES-256-CBC", GNUTLS_CIPHER_AES_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0, 0},
50 {"AES-192-CBC", GNUTLS_CIPHER_AES_192_CBC, 16, 24, CIPHER_BLOCK, 16, 0, 0},
51 {"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0, 0},
52 {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 0, 1},
53 {"AES-256-GCM", GNUTLS_CIPHER_AES_256_GCM, 16, 32, CIPHER_STREAM, AEAD_IMPLICIT_DATA_SIZE, 0, 1},
54 {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 0, 0, 0},
55 {"CAMELLIA-256-CBC", GNUTLS_CIPHER_CAMELLIA_256_CBC, 16, 32, CIPHER_BLOCK,
56 16, 0, 0},
57 {"CAMELLIA-128-CBC", GNUTLS_CIPHER_CAMELLIA_128_CBC, 16, 16, CIPHER_BLOCK,
58 16, 0, 0},
59 {"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 0, 0},
60 {"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 8, 0, 0},
61 {"ARCFOUR-40", GNUTLS_CIPHER_ARCFOUR_40, 1, 5, CIPHER_STREAM, 0, 1, 0},
62 {"RC2-40", GNUTLS_CIPHER_RC2_40_CBC, 8, 5, CIPHER_BLOCK, 8, 1, 0},
64 #ifdef ENABLE_OPENPGP
65 {"IDEA-PGP-CFB", GNUTLS_CIPHER_IDEA_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
66 {"3DES-PGP-CFB", GNUTLS_CIPHER_3DES_PGP_CFB, 8, 24, CIPHER_BLOCK, 8, 0, 0},
67 {"CAST5-PGP-CFB", GNUTLS_CIPHER_CAST5_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
68 {"BLOWFISH-PGP-CFB", GNUTLS_CIPHER_BLOWFISH_PGP_CFB, 8,
69 16 /*actually unlimited */ , CIPHER_BLOCK, 8, 0, 0},
70 {"SAFER-SK128-PGP-CFB", GNUTLS_CIPHER_SAFER_SK128_PGP_CFB, 8, 16,
71 CIPHER_BLOCK, 8, 0, 0},
72 {"AES-128-PGP-CFB", GNUTLS_CIPHER_AES128_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
73 0, 0},
74 {"AES-192-PGP-CFB", GNUTLS_CIPHER_AES192_PGP_CFB, 16, 24, CIPHER_BLOCK, 16,
75 0, 0},
76 {"AES-256-PGP-CFB", GNUTLS_CIPHER_AES256_PGP_CFB, 16, 32, CIPHER_BLOCK, 16,
77 0, 0},
78 {"TWOFISH-PGP-CFB", GNUTLS_CIPHER_TWOFISH_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
79 0, 0},
80 #endif
81 {"NULL", GNUTLS_CIPHER_NULL, 1, 0, CIPHER_STREAM, 0, 0, 0},
82 {0, 0, 0, 0, 0, 0, 0}
85 #define GNUTLS_CIPHER_LOOP(b) \
86 const gnutls_cipher_entry *p; \
87 for(p = algorithms; p->name != NULL; p++) { b ; }
89 #define GNUTLS_ALG_LOOP(a) \
90 GNUTLS_CIPHER_LOOP( if(p->id == algorithm) { a; break; } )
92 /* CIPHER functions */
94 /**
95 * gnutls_cipher_get_block_size:
96 * @algorithm: is an encryption algorithm
98 * Get block size for encryption algorithm.
100 * Returns: block size for encryption algorithm.
102 * Since: 2.10.0
105 gnutls_cipher_get_block_size (gnutls_cipher_algorithm_t algorithm)
107 size_t ret = 0;
108 GNUTLS_ALG_LOOP (ret = p->blocksize);
109 return ret;
113 /* returns the priority */
115 _gnutls_cipher_priority (gnutls_session_t session,
116 gnutls_cipher_algorithm_t algorithm)
118 unsigned int i;
119 for (i = 0; i < session->internals.priorities.cipher.algorithms; i++)
121 if (session->internals.priorities.cipher.priority[i] == algorithm)
122 return i;
124 return -1;
129 _gnutls_cipher_is_block (gnutls_cipher_algorithm_t algorithm)
131 size_t ret = 0;
133 GNUTLS_ALG_LOOP (ret = p->block);
134 return ret;
139 _gnutls_cipher_algo_is_aead (gnutls_cipher_algorithm_t algorithm)
141 size_t ret = 0;
143 GNUTLS_ALG_LOOP (ret = p->auth);
144 return ret;
149 * gnutls_cipher_get_key_size:
150 * @algorithm: is an encryption algorithm
152 * Get key size for cipher.
154 * Returns: length (in bytes) of the given cipher's key size, or 0 if
155 * the given cipher is invalid.
157 size_t
158 gnutls_cipher_get_key_size (gnutls_cipher_algorithm_t algorithm)
159 { /* In bytes */
160 size_t ret = 0;
161 GNUTLS_ALG_LOOP (ret = p->keysize);
162 return ret;
167 _gnutls_cipher_get_iv_size (gnutls_cipher_algorithm_t algorithm)
168 { /* In bytes */
169 size_t ret = 0;
170 GNUTLS_ALG_LOOP (ret = p->iv);
171 return ret;
176 _gnutls_cipher_get_export_flag (gnutls_cipher_algorithm_t algorithm)
177 { /* In bytes */
178 size_t ret = 0;
179 GNUTLS_ALG_LOOP (ret = p->export_flag);
180 return ret;
185 * gnutls_cipher_get_name:
186 * @algorithm: is an encryption algorithm
188 * Convert a #gnutls_cipher_algorithm_t type to a string.
190 * Returns: a pointer to a string that contains the name of the
191 * specified cipher, or %NULL.
193 const char *
194 gnutls_cipher_get_name (gnutls_cipher_algorithm_t algorithm)
196 const char *ret = NULL;
198 /* avoid prefix */
199 GNUTLS_ALG_LOOP (ret = p->name);
201 return ret;
205 * gnutls_cipher_get_id:
206 * @name: is a cipher algorithm name
208 * The names are compared in a case insensitive way.
210 * Returns: return a #gnutls_cipher_algorithm_t value corresponding to
211 * the specified cipher, or %GNUTLS_CIPHER_UNKNOWN on error.
213 gnutls_cipher_algorithm_t
214 gnutls_cipher_get_id (const char *name)
216 gnutls_cipher_algorithm_t ret = GNUTLS_CIPHER_UNKNOWN;
218 GNUTLS_CIPHER_LOOP (
219 if (strcasecmp (p->name, name) == 0)
221 ret = p->id;
222 break;
226 return ret;
230 * gnutls_cipher_list:
232 * Get a list of supported cipher algorithms. Note that not
233 * necessarily all ciphers are supported as TLS cipher suites. For
234 * example, DES is not supported as a cipher suite, but is supported
235 * for other purposes (e.g., PKCS#8 or similar).
237 * This function is not thread safe.
239 * Returns: a (0)-terminated list of #gnutls_cipher_algorithm_t
240 * integers indicating the available ciphers.
243 const gnutls_cipher_algorithm_t *
244 gnutls_cipher_list (void)
246 static gnutls_cipher_algorithm_t supported_ciphers[MAX_ALGOS] = {0};
248 if (supported_ciphers[0] == 0)
250 int i = 0;
252 GNUTLS_CIPHER_LOOP (
253 if (_gnutls_cipher_exists(p->id))
254 supported_ciphers[i++]=p->id;
256 supported_ciphers[i++]=0;
259 return supported_ciphers;
263 _gnutls_cipher_is_ok (gnutls_cipher_algorithm_t algorithm)
265 ssize_t ret = -1;
266 GNUTLS_ALG_LOOP (ret = p->id);
267 if (ret >= 0)
268 ret = 0;
269 else
270 ret = 1;
271 return ret;