1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2010-2020. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #include "cipher.h"
22
23 #ifdef HAVE_DES
24 #define COND_NO_DES_PTR(Ptr) (Ptr)
25 #else
26 #define COND_NO_DES_PTR(Ptr) (NULL)
27 #endif
28
29 static struct cipher_type_t cipher_types[] =
30 {
31 #ifdef HAVE_RC2
32 {{"rc2_cbc"}, {&EVP_rc2_cbc}, 0, NO_FIPS_CIPHER},
33 #else
34 {{"rc2_cbc"}, {NULL}, 0, NO_FIPS_CIPHER},
35 #endif
36 #ifdef HAVE_RC4
37 {{"rc4"}, {&EVP_rc4}, 0, NO_FIPS_CIPHER},
38 #else
39 {{"rc4"}, {NULL}, 0, NO_FIPS_CIPHER},
40 #endif
41 {{"des_cbc"}, {COND_NO_DES_PTR(&EVP_des_cbc)}, 0, NO_FIPS_CIPHER},
42 {{"des_cfb"}, {COND_NO_DES_PTR(&EVP_des_cfb8)}, 0, NO_FIPS_CIPHER},
43 {{"des_ecb"}, {COND_NO_DES_PTR(&EVP_des_ecb)}, 0, NO_FIPS_CIPHER | ECB_BUG_0_9_8L},
44
45 {{"des_ede3_cbc"}, {COND_NO_DES_PTR(&EVP_des_ede3_cbc)}, 0, 0},
46
47 #ifdef HAVE_DES_ede3_cfb_encrypt
48 {{"des_ede3_cfb"}, {COND_NO_DES_PTR(&EVP_des_ede3_cfb8)}, 0, 0},
49 #else
50 {{"des_ede3_cfb"}, {NULL}, 0, 0},
51 #endif
52
53 #ifdef HAVE_BF
54 {{"blowfish_cbc"}, {&EVP_bf_cbc}, 0, NO_FIPS_CIPHER},
55 {{"blowfish_cfb64"}, {&EVP_bf_cfb64}, 0, NO_FIPS_CIPHER},
56 {{"blowfish_ofb64"}, {&EVP_bf_ofb}, 0, NO_FIPS_CIPHER},
57 {{"blowfish_ecb"}, {&EVP_bf_ecb}, 0, NO_FIPS_CIPHER | ECB_BUG_0_9_8L},
58 #else
59 {{"blowfish_cbc"}, {NULL}, 0, 0},
60 {{"blowfish_cfb64"}, {NULL}, 0, 0},
61 {{"blowfish_ofb64"}, {NULL}, 0, 0},
62 {{"blowfish_ecb"}, {NULL}, 0, 0},
63 #endif
64
65 {{"aes_128_cbc"}, {&EVP_aes_128_cbc}, 16, 0},
66 {{"aes_192_cbc"}, {&EVP_aes_192_cbc}, 24, 0},
67 {{"aes_256_cbc"}, {&EVP_aes_256_cbc}, 32, 0},
68
69 {{"aes_128_cfb8"}, {&EVP_aes_128_cfb8}, 16, AES_CFBx},
70 {{"aes_192_cfb8"}, {&EVP_aes_192_cfb8}, 24, AES_CFBx},
71 {{"aes_256_cfb8"}, {&EVP_aes_256_cfb8}, 32, AES_CFBx},
72
73 {{"aes_128_cfb128"}, {&EVP_aes_128_cfb128}, 16, AES_CFBx},
74 {{"aes_192_cfb128"}, {&EVP_aes_192_cfb128}, 24, AES_CFBx},
75 {{"aes_256_cfb128"}, {&EVP_aes_256_cfb128}, 32, AES_CFBx},
76
77 {{"aes_128_ecb"}, {&EVP_aes_128_ecb}, 16, ECB_BUG_0_9_8L},
78 {{"aes_192_ecb"}, {&EVP_aes_192_ecb}, 24, ECB_BUG_0_9_8L},
79 {{"aes_256_ecb"}, {&EVP_aes_256_ecb}, 32, ECB_BUG_0_9_8L},
80
81 #if defined(HAVE_EVP_AES_CTR)
82 {{"aes_128_ctr"}, {&EVP_aes_128_ctr}, 16, 0},
83 {{"aes_192_ctr"}, {&EVP_aes_192_ctr}, 24, 0},
84 {{"aes_256_ctr"}, {&EVP_aes_256_ctr}, 32, 0},
85 #else
86 {{"aes_128_ctr"}, {NULL}, 16, AES_CTR_COMPAT},
87 {{"aes_192_ctr"}, {NULL}, 24, AES_CTR_COMPAT},
88 {{"aes_256_ctr"}, {NULL}, 32, AES_CTR_COMPAT},
89 #endif
90
91 #if defined(HAVE_CHACHA20)
92 {{"chacha20"}, {&EVP_chacha20}, 32, NO_FIPS_CIPHER},
93 #else
94 {{"chacha20"}, {NULL}, 0, NO_FIPS_CIPHER},
95 #endif
96
97 /*==== AEAD ciphers ====*/
98 #if defined(HAVE_CHACHA20_POLY1305)
99 {{"chacha20_poly1305"}, {&EVP_chacha20_poly1305}, 0, NO_FIPS_CIPHER | AEAD_CIPHER, {{EVP_CTRL_AEAD_SET_IVLEN,EVP_CTRL_AEAD_GET_TAG,EVP_CTRL_AEAD_SET_TAG}}},
100 #else
101 {{"chacha20_poly1305"}, {NULL}, 0, NO_FIPS_CIPHER | AEAD_CIPHER, {{0,0,0}}},
102 #endif
103
104 #if defined(HAVE_GCM)
105 {{"aes_128_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
106 {{"aes_192_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
107 {{"aes_256_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
108 #else
109 {{"aes_128_gcm"}, {NULL}, 16, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
110 {{"aes_192_gcm"}, {NULL}, 24, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
111 {{"aes_256_gcm"}, {NULL}, 32, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
112 #endif
113
114 #if defined(HAVE_CCM)
115 {{"aes_128_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
116 {{"aes_192_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
117 {{"aes_256_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
118 #else
119 {{"aes_128_ccm"}, {NULL}, 16, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
120 {{"aes_192_ccm"}, {NULL}, 24, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
121 {{"aes_256_ccm"}, {NULL}, 32, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
122 #endif
123
124 /*==== Specialy handled ciphers, only for inclusion in algorithm's list ====*/
125 #ifdef HAVE_AES_IGE
126 {{"aes_ige256"}, {NULL}, 0, NO_FIPS_CIPHER | NON_EVP_CIPHER},
127 #endif
128
129 /*==== End of list ==== */
130
131 {{NULL},{NULL},0,0}
132 };
133
134 ErlNifResourceType* evp_cipher_ctx_rtype;
135
136 static size_t num_cipher_types = 0;
137
evp_cipher_ctx_dtor(ErlNifEnv * env,struct evp_cipher_ctx * ctx)138 static void evp_cipher_ctx_dtor(ErlNifEnv* env, struct evp_cipher_ctx* ctx) {
139 if (ctx == NULL)
140 return;
141
142 if (ctx->ctx)
143 EVP_CIPHER_CTX_free(ctx->ctx);
144
145 #if !defined(HAVE_EVP_AES_CTR)
146 if (ctx->env)
147 enif_free_env(ctx->env);
148 #endif
149 }
150
init_cipher_ctx(ErlNifEnv * env)151 int init_cipher_ctx(ErlNifEnv *env) {
152 evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX",
153 (ErlNifResourceDtor*) evp_cipher_ctx_dtor,
154 ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
155 NULL);
156 if (evp_cipher_ctx_rtype == NULL)
157 goto err;
158
159 return 1;
160
161 err:
162 PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'");
163 return 0;
164 }
165
init_cipher_types(ErlNifEnv * env)166 void init_cipher_types(ErlNifEnv* env)
167 {
168 struct cipher_type_t* p = cipher_types;
169
170 num_cipher_types = 0;
171 for (p = cipher_types; p->type.str; p++) {
172 num_cipher_types++;
173 p->type.atom = enif_make_atom(env, p->type.str);
174 if (p->cipher.funcp)
175 p->cipher.p = p->cipher.funcp();
176 }
177 p->type.atom = atom_false; /* end marker */
178
179 qsort(cipher_types, num_cipher_types, sizeof(cipher_types[0]), cmp_cipher_types);
180 }
181
get_cipher_type(ERL_NIF_TERM type,size_t key_len)182 const struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len)
183 {
184 struct cipher_type_t key;
185
186 key.type.atom = type;
187 key.key_len = key_len;
188
189 return bsearch(&key, cipher_types, num_cipher_types, sizeof(cipher_types[0]), cmp_cipher_types);
190 }
191
192
cmp_cipher_types(const void * keyp,const void * elemp)193 int cmp_cipher_types(const void *keyp, const void *elemp) {
194 const struct cipher_type_t *key = keyp;
195 const struct cipher_type_t *elem = elemp;
196
197 if (key->type.atom < elem->type.atom) return -1;
198 else if (key->type.atom > elem->type.atom) return 1;
199 else /* key->type.atom == elem->type.atom */
200 if (!elem->key_len || key->key_len == elem->key_len) return 0;
201 else if (key->key_len < elem->key_len) return -1;
202 else return 1;
203 }
204
205
cipher_info_nif(ErlNifEnv * env,int argc,const ERL_NIF_TERM argv[])206 ERL_NIF_TERM cipher_info_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
207 {/* (Type) */
208 const struct cipher_type_t *cipherp;
209 const EVP_CIPHER *cipher;
210 ERL_NIF_TERM ret, ret_mode;
211 unsigned type;
212 unsigned long mode;
213
214 if ((cipherp = get_cipher_type_no_key(argv[0])) == NULL)
215 return enif_make_badarg(env);
216
217 if (CIPHER_FORBIDDEN_IN_FIPS(cipherp))
218 return enif_raise_exception(env, atom_notsup);
219 if ((cipher = cipherp->cipher.p) == NULL)
220 return enif_raise_exception(env, atom_notsup);
221
222 ret = enif_make_new_map(env);
223
224 type = EVP_CIPHER_type(cipher);
225 enif_make_map_put(env, ret, atom_type,
226 type == NID_undef ? atom_undefined : enif_make_int(env, type),
227 &ret);
228
229 enif_make_map_put(env, ret, atom_key_length,
230 enif_make_int(env, EVP_CIPHER_key_length(cipher)), &ret);
231 enif_make_map_put(env, ret, atom_iv_length,
232 enif_make_int(env, EVP_CIPHER_iv_length(cipher)), &ret);
233 enif_make_map_put(env, ret, atom_block_size,
234 enif_make_int(env, EVP_CIPHER_block_size(cipher)), &ret);
235
236 mode = EVP_CIPHER_mode(cipher);
237 switch (mode) {
238 case EVP_CIPH_ECB_MODE:
239 ret_mode = atom_ecb_mode;
240 break;
241
242 case EVP_CIPH_CBC_MODE:
243 ret_mode = atom_cbc_mode;
244 break;
245
246 case EVP_CIPH_CFB_MODE:
247 ret_mode = atom_cfb_mode;
248 break;
249
250 case EVP_CIPH_OFB_MODE:
251 ret_mode = atom_ofb_mode;
252 break;
253
254 #ifdef EVP_CIPH_CTR_MODE
255 case EVP_CIPH_CTR_MODE:
256 ret_mode = atom_ctr_mode;
257 break;
258 #endif
259
260 #ifdef EVP_CIPH_GCM_MODE
261 case EVP_CIPH_GCM_MODE:
262 ret_mode = atom_gcm_mode;
263 break;
264 #endif
265
266 #ifdef EVP_CIPH_CCM_MODE
267 case EVP_CIPH_CCM_MODE:
268 ret_mode = atom_ccm_mode;
269 break;
270 #endif
271
272 #ifdef EVP_CIPH_XTS_MODE
273 case EVP_CIPH_XTS_MODE:
274 ret_mode = atom_xts_mode;
275 break;
276 #endif
277
278 #ifdef EVP_CIPH_WRAP_MODE
279 case EVP_CIPH_WRAP_MODE:
280 ret_mode = atom_wrap_mode;
281 break;
282 #endif
283
284 #ifdef EVP_CIPH_OCB_MODE
285 case EVP_CIPH_OCB_MODE:
286 ret_mode = atom_ocb_mode;
287 break;
288 #endif
289
290 case EVP_CIPH_STREAM_CIPHER:
291 ret_mode = atom_stream_cipher;
292 break;
293
294 default:
295 ret_mode = atom_undefined;
296 break;
297 }
298
299 enif_make_map_put(env, ret, atom_mode, ret_mode, &ret);
300
301 return ret;
302 }
303
get_cipher_type_no_key(ERL_NIF_TERM type)304 const struct cipher_type_t* get_cipher_type_no_key(ERL_NIF_TERM type)
305 {
306 struct cipher_type_t key;
307
308 key.type.atom = type;
309
310 return bsearch(&key, cipher_types, num_cipher_types, sizeof(cipher_types[0]), cmp_cipher_types_no_key);
311 }
312
cmp_cipher_types_no_key(const void * keyp,const void * elemp)313 int cmp_cipher_types_no_key(const void *keyp, const void *elemp) {
314 const struct cipher_type_t *key = keyp;
315 const struct cipher_type_t *elem = elemp;
316
317 if (key->type.atom < elem->type.atom) return -1;
318 else if (key->type.atom > elem->type.atom) return 1;
319 else /* key->type.atom == elem->type.atom */ return 0;
320 }
321
322
cipher_types_as_list(ErlNifEnv * env)323 ERL_NIF_TERM cipher_types_as_list(ErlNifEnv* env)
324 {
325 struct cipher_type_t* p;
326 ERL_NIF_TERM prev, hd;
327
328 hd = enif_make_list(env, 0);
329 prev = atom_undefined;
330
331 for (p = cipher_types; (p->type.atom & (p->type.atom != atom_false)); p++) {
332 if ((prev == p->type.atom) ||
333 CIPHER_FORBIDDEN_IN_FIPS(p) )
334 continue;
335
336 if ((p->cipher.p != NULL) ||
337 (p->flags & AES_CTR_COMPAT) ||
338 (p->type.atom == atom_aes_ige256)) /* Special handling. Bad indeed... */
339 {
340 hd = enif_make_list_cell(env, p->type.atom, hd);
341 }
342 }
343
344 return hd;
345 }
346