evp-openssl: fallback to hcrypto
[heimdal.git] / lib / hcrypto / evp-openssl.c
blob0c50ee1ee0350d58c3a5954c446cfe20f4610bf5
1 /*
2 * Copyright (c) 2016, Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
32 /* OpenSSL provider */
34 #include "config.h"
35 #include <roken.h>
36 #include <heimbase.h>
38 #include <assert.h>
39 #include <evp.h>
41 #ifdef HAVE_HCRYPTO_W_OPENSSL
44 * This is the OpenSSL 1.x backend for hcrypto. It has been tested with
45 * OpenSSL 1.0.1f and OpenSSL 1.1.0-pre3-dev.
47 * NOTE: In order for this to work with OpenSSL 1.1.x and up, it is
48 * critical to use opaque OpenSSL type accessors everywhere /
49 * never use knowledge of opaque OpenSSL type internals.
52 #include <evp-openssl.h>
55 * This being an OpenSSL backend for hcrypto... we need to be able to
56 * refer to types and objects (functions) from both, OpenSSL and
57 * hcrypto.
59 * The hcrypto API is *very* similar to the OpenSSL 1.0.x API, with the
60 * same type and symbol names in many cases, except that the hcrypto
61 * names are prefixed with hc_*. hcrypto has convenience macros that
62 * provide OpenSSL aliases for the hcrypto interfaces, and hcrypto
63 * applications are expected to use the OpenSSL names.
65 * Since here we must be able to refer to types and objects from both
66 * OpenSSL and from hcrypto, we disable the hcrypto renaming for the
67 * rest of this file. These #undefs could be collected into an
68 * <hcrypto/undef.h> for the purpose of permitting other applications to
69 * use both, hcrypto and OpenSSL in the same source files (provided that
70 * such applications refer to hcrypto types and objects by their proper
71 * hc_-prefixed names).
73 #include <undef.h>
75 /* Now it's safe to include OpenSSL headers */
76 #include <openssl/evp.h>
78 #if OPENSSL_VERSION_NUMBER < 0x10100000L
79 #define EVP_MD_CTX_new EVP_MD_CTX_create
80 #define EVP_MD_CTX_free EVP_MD_CTX_destroy
81 #endif
83 /* A HEIM_BASE_ONCE argument struct for per-EVP one-time initialization */
84 struct once_init_cipher_ctx {
85 const hc_EVP_CIPHER **hc_memoizep;
86 hc_EVP_CIPHER *hc_memoize;
87 const hc_EVP_CIPHER *fallback;
88 unsigned long flags;
89 unsigned char *initialized;
90 int nid;
93 /* Our wrapper for OpenSSL EVP_CIPHER_CTXs */
94 struct ossl_cipher_ctx {
95 EVP_CIPHER_CTX *ossl_cipher_ctx; /* OpenSSL cipher ctx */
96 const EVP_CIPHER *ossl_cipher; /* OpenSSL cipher */
97 int initialized;
101 * Our hc_EVP_CIPHER init() method; wraps around OpenSSL
102 * EVP_CipherInit_ex().
104 * This is very similar to the init() function pointer in an OpenSSL
105 * EVP_CIPHER, but a) we can't access them in 1.1, and b) the method
106 * invocation protocols in hcrypto and OpenSSL are similar but not the
107 * same, thus we must have this wrapper.
109 static int
110 cipher_ctx_init(hc_EVP_CIPHER_CTX *ctx, const unsigned char *key,
111 const unsigned char *iv, int enc)
113 struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data; /* EVP_CIPHER_CTX wrapper */
114 const EVP_CIPHER *c;
116 assert(ossl_ctx != NULL);
117 assert(ctx->cipher != NULL);
118 assert(ctx->cipher->app_data != NULL);
121 * Here be dragons.
123 * We need to make sure that the OpenSSL EVP_CipherInit_ex() is
124 * called with cipher!=NULL just once per EVP_CIPHER_CTX, otherwise
125 * state in the OpenSSL EVP_CIPHER_CTX will get cleaned up and then
126 * we'll segfault.
128 * hcrypto applications can re-initialize an (hc_)EVP_CIPHER_CTX as
129 * usual by calling (hc)EVP_CipherInit_ex() with a non-NULL cipher
130 * argument, and that will cause cipher_cleanup() (below) to be
131 * called.
133 c = ossl_ctx->ossl_cipher = ctx->cipher->app_data; /* OpenSSL's EVP_CIPHER * */
134 if (!ossl_ctx->initialized) {
135 ossl_ctx->ossl_cipher_ctx = EVP_CIPHER_CTX_new();
136 if (ossl_ctx->ossl_cipher_ctx == NULL)
137 return 0;
139 * So we always call EVP_CipherInit_ex() with c!=NULL, but other
140 * things NULL...
142 if (!EVP_CipherInit_ex(ossl_ctx->ossl_cipher_ctx, c, NULL, NULL, NULL, enc))
143 return 0;
144 ossl_ctx->initialized = 1;
147 /* ...and from here on always call EVP_CipherInit_ex() with c=NULL */
148 if ((ctx->cipher->flags & hc_EVP_CIPH_VARIABLE_LENGTH) &&
149 ctx->key_len > 0)
150 EVP_CIPHER_CTX_set_key_length(ossl_ctx->ossl_cipher_ctx, ctx->key_len);
152 return EVP_CipherInit_ex(ossl_ctx->ossl_cipher_ctx, NULL, NULL, key, iv, enc);
155 static int
156 cipher_do_cipher(hc_EVP_CIPHER_CTX *ctx, unsigned char *out,
157 const unsigned char *in, unsigned int len)
159 struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
161 assert(ossl_ctx != NULL);
162 return EVP_Cipher(ossl_ctx->ossl_cipher_ctx, out, in, len);
165 static int
166 cipher_cleanup(hc_EVP_CIPHER_CTX *ctx)
168 struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
170 if (ossl_ctx == NULL || !ossl_ctx->initialized)
171 return 1;
173 if (ossl_ctx->ossl_cipher_ctx != NULL)
174 EVP_CIPHER_CTX_free(ossl_ctx->ossl_cipher_ctx);
176 ossl_ctx->ossl_cipher_ctx = NULL;
177 ossl_ctx->ossl_cipher = NULL;
178 ossl_ctx->initialized = 0;
179 return 1;
182 static int
183 cipher_ctrl(hc_EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
185 struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
187 assert(ossl_ctx != NULL);
188 return EVP_CIPHER_CTX_ctrl(ossl_ctx->ossl_cipher_ctx, type, arg, ptr);
192 static void
193 get_EVP_CIPHER_once_cb(void *d)
195 struct once_init_cipher_ctx *arg = d;
196 const EVP_CIPHER *ossl_evp;
197 hc_EVP_CIPHER *hc_evp;
199 hc_evp = arg->hc_memoize;
202 * We lookup EVP_CIPHER *s by NID so that we don't fail to find a
203 * symbol such as EVP_aes...() when libcrypto changes after build
204 * time (e.g., updates, LD_LIBRARY_PATH/LD_PRELOAD).
206 ossl_evp = EVP_get_cipherbynid(arg->nid);
207 if (ossl_evp == NULL) {
208 (void) memset(hc_evp, 0, sizeof(*hc_evp));
209 *arg->hc_memoizep = arg->fallback;
210 *arg->initialized = 1;
211 return;
214 /* Build the hc_EVP_CIPHER */
215 hc_evp->nid = EVP_CIPHER_nid(ossl_evp); /* We would an hcrypto NIDs if we had them */
216 hc_evp->block_size = EVP_CIPHER_block_size(ossl_evp);
217 hc_evp->key_len = EVP_CIPHER_key_length(ossl_evp);
218 hc_evp->iv_len = EVP_CIPHER_iv_length(ossl_evp);
221 * We force hc_EVP_CipherInit_ex to always call our init() function,
222 * otherwise we don't get a chance to call EVP_CipherInit_ex()
223 * correctly.
225 hc_evp->flags = hc_EVP_CIPH_ALWAYS_CALL_INIT | arg->flags;
227 /* Our cipher context */
228 hc_evp->ctx_size = sizeof(struct ossl_cipher_ctx);
230 /* Our wrappers */
231 hc_evp->init = cipher_ctx_init;
232 hc_evp->do_cipher = cipher_do_cipher;
233 hc_evp->cleanup = cipher_cleanup;
234 hc_evp->set_asn1_parameters = NULL;
235 hc_evp->get_asn1_parameters = NULL;
236 hc_evp->ctrl = cipher_ctrl;
238 /* Our link to the OpenSSL EVP_CIPHER */
239 hc_evp->app_data = (void *)ossl_evp;
241 /* Finally, set the static hc_EVP_CIPHER * to the one we just built */
242 *arg->hc_memoizep = hc_evp;
243 *arg->initialized = 1;
246 static const hc_EVP_CIPHER *
247 get_EVP_CIPHER(heim_base_once_t *once, hc_EVP_CIPHER *hc_memoize,
248 const hc_EVP_CIPHER **hc_memoizep,
249 const hc_EVP_CIPHER *fallback,
250 unsigned long flags, unsigned char *initialized, int nid)
252 struct once_init_cipher_ctx arg;
254 arg.flags = flags;
255 arg.hc_memoizep = hc_memoizep;
256 arg.hc_memoize = hc_memoize;
257 arg.fallback = fallback;
258 arg.initialized = initialized;
259 arg.nid = nid;
260 heim_base_once_f(once, &arg, get_EVP_CIPHER_once_cb);
261 return *hc_memoizep; /* May be NULL */
264 #define OSSL_CIPHER_ALGORITHM(name, flags) \
265 extern const hc_EVP_CIPHER *hc_EVP_hcrypto_##name(void); \
266 const hc_EVP_CIPHER *hc_EVP_ossl_##name(void) \
268 static hc_EVP_CIPHER ossl_##name##_st; \
269 static const hc_EVP_CIPHER *ossl_##name; \
270 static heim_base_once_t once = HEIM_BASE_ONCE_INIT; \
271 static unsigned char initialized; \
272 if (initialized) \
273 return ossl_##name; \
274 return get_EVP_CIPHER(&once, &ossl_##name##_st, &ossl_##name, \
275 hc_EVP_hcrypto_##name(), \
276 flags, &initialized, NID_##name); \
279 /* As above, but for EVP_MDs */
281 struct ossl_md_ctx {
282 EVP_MD_CTX *ossl_md_ctx; /* OpenSSL md ctx */
283 const EVP_MD *ossl_md; /* OpenSSL md */
284 int initialized;
287 static int
288 ossl_md_init(struct ossl_md_ctx *ctx, const EVP_MD *md)
290 if (ctx->initialized)
291 EVP_MD_CTX_free(ctx->ossl_md_ctx);
292 ctx->initialized = 0;
294 ctx->ossl_md = md;
295 ctx->ossl_md_ctx = EVP_MD_CTX_new();
296 if (!EVP_DigestInit(ctx->ossl_md_ctx, md)) {
297 EVP_MD_CTX_free(ctx->ossl_md_ctx);
298 ctx->ossl_md_ctx = NULL;
299 ctx->ossl_md = NULL;
300 return 0;
302 ctx->initialized = 1;
303 return 1;
306 static int
307 ossl_md_update(hc_EVP_MD_CTX *d, const void *data, size_t count)
309 struct ossl_md_ctx *ctx = (void *)d;
311 return EVP_DigestUpdate(ctx->ossl_md_ctx, data, count);
314 static int
315 ossl_md_final(void *md_data, hc_EVP_MD_CTX *d)
317 struct ossl_md_ctx *ctx = (void *)d;
319 return EVP_DigestFinal(ctx->ossl_md_ctx, md_data, NULL);
322 static int
323 ossl_md_cleanup(hc_EVP_MD_CTX *d)
325 struct ossl_md_ctx *ctx = (void *)d;
327 if (!ctx->initialized)
328 return 1;
329 EVP_MD_CTX_free(ctx->ossl_md_ctx);
330 ctx->ossl_md = NULL;
331 ctx->initialized = 0;
333 return 1;
336 struct once_init_md_ctx {
337 const EVP_MD **ossl_memoizep;
338 const hc_EVP_MD **hc_memoizep;
339 hc_EVP_MD *hc_memoize;
340 const hc_EVP_MD *fallback;
341 hc_evp_md_init md_init;
342 int nid;
343 unsigned char *initialized;
346 static void
347 get_EVP_MD_once_cb(void *d)
349 struct once_init_md_ctx *arg = d;
350 const EVP_MD *ossl_evp;
351 hc_EVP_MD *hc_evp;
353 hc_evp = arg->hc_memoize;
354 *arg->ossl_memoizep = ossl_evp = EVP_get_digestbynid(arg->nid);
356 if (ossl_evp == NULL) {
357 (void) memset(hc_evp, 0, sizeof(*hc_evp));
358 *arg->hc_memoizep = arg->fallback;
359 *arg->initialized = 1;
360 return;
363 /* Build the hc_EVP_MD */
364 hc_evp->ctx_size = sizeof(struct ossl_md_ctx);
365 hc_evp->init = arg->md_init;
366 hc_evp->update = ossl_md_update;
367 hc_evp->final = ossl_md_final;
368 hc_evp->cleanup = ossl_md_cleanup;
370 *arg->hc_memoizep = hc_evp;
371 *arg->initialized = 1;
374 static const hc_EVP_MD *
375 get_EVP_MD(heim_base_once_t *once, hc_EVP_MD *hc_memoize,
376 const hc_EVP_MD **hc_memoizep, const EVP_MD **ossl_memoizep,
377 const hc_EVP_MD *fallback,
378 hc_evp_md_init md_init, unsigned char *initialized, int nid)
380 struct once_init_md_ctx ctx;
382 ctx.ossl_memoizep = ossl_memoizep;
383 ctx.hc_memoizep = hc_memoizep;
384 ctx.hc_memoize = hc_memoize;
385 ctx.fallback = fallback;
386 ctx.md_init = md_init;
387 ctx.initialized = initialized;
388 ctx.nid = nid;
389 heim_base_once_f(once, &ctx, get_EVP_MD_once_cb);
390 return *hc_memoizep; /* May be NULL */
393 #define OSSL_MD_ALGORITHM(name) \
394 extern const hc_EVP_MD *hc_EVP_hcrypto_##name(void); \
395 static const EVP_MD *ossl_EVP_##name; \
396 static const hc_EVP_MD *ossl_##name; \
397 static int ossl_init_##name(hc_EVP_MD_CTX *d) \
399 return ossl_md_init((void *)d, ossl_EVP_##name); \
401 const hc_EVP_MD *hc_EVP_ossl_##name(void) \
403 static hc_EVP_MD ossl_##name##_st; \
404 static heim_base_once_t once = HEIM_BASE_ONCE_INIT; \
405 static unsigned char initialized; \
406 if (initialized) \
407 return ossl_##name; \
408 return get_EVP_MD(&once, &ossl_##name##_st, &ossl_##name, \
409 &ossl_EVP_##name, hc_EVP_hcrypto_##name(), \
410 ossl_init_##name, &initialized, NID_##name); \
413 #else /* HAVE_HCRYPTO_W_OPENSSL */
415 #define OSSL_CIPHER_ALGORITHM(name, flags) \
416 const hc_EVP_CIPHER *hc_EVP_ossl_##name(void) \
418 return hc_EVP_hcrypto_##name(); \
421 #define OSSL_MD_ALGORITHM(name) \
422 const hc_EVP_MD *hc_EVP_ossl_##name(void) \
424 return hc_EVP_hcrypto_##name(); \
427 #endif /* HAVE_HCRYPTO_W_OPENSSL */
430 * The triple DES cipher type (OpenSSL provider)
432 * @return the DES-EDE3-CBC EVP_CIPHER pointer.
434 * @ingroup hcrypto_evp
436 OSSL_CIPHER_ALGORITHM(des_ede3_cbc, hc_EVP_CIPH_CBC_MODE)
439 * The DES cipher type (OpenSSL provider)
441 * @return the DES-CBC EVP_CIPHER pointer.
443 * @ingroup hcrypto_evp
445 OSSL_CIPHER_ALGORITHM(des_cbc, hc_EVP_CIPH_CBC_MODE)
448 * The AES-128 cipher type (OpenSSL provider)
450 * @return the AES-128-CBC EVP_CIPHER pointer.
452 * @ingroup hcrypto_evp
454 OSSL_CIPHER_ALGORITHM(aes_128_cbc, hc_EVP_CIPH_CBC_MODE)
457 * The AES-192 cipher type (OpenSSL provider)
459 * @return the AES-192-CBC EVP_CIPHER pointer.
461 * @ingroup hcrypto_evp
463 OSSL_CIPHER_ALGORITHM(aes_192_cbc, hc_EVP_CIPH_CBC_MODE)
466 * The AES-256 cipher type (OpenSSL provider)
468 * @return the AES-256-CBC EVP_CIPHER pointer.
470 * @ingroup hcrypto_evp
472 OSSL_CIPHER_ALGORITHM(aes_256_cbc, hc_EVP_CIPH_CBC_MODE)
475 * The AES-128 CFB8 cipher type (OpenSSL provider)
477 * @return the AES-128-CFB8 EVP_CIPHER pointer.
479 * @ingroup hcrypto_evp
481 OSSL_CIPHER_ALGORITHM(aes_128_cfb8, hc_EVP_CIPH_CFB8_MODE)
484 * The AES-192 CFB8 cipher type (OpenSSL provider)
486 * @return the AES-192-CFB8 EVP_CIPHER pointer.
488 * @ingroup hcrypto_evp
490 OSSL_CIPHER_ALGORITHM(aes_192_cfb8, hc_EVP_CIPH_CFB8_MODE)
493 * The AES-256 CFB8 cipher type (OpenSSL provider)
495 * @return the AES-256-CFB8 EVP_CIPHER pointer.
497 * @ingroup hcrypto_evp
499 OSSL_CIPHER_ALGORITHM(aes_256_cfb8, hc_EVP_CIPH_CFB8_MODE)
502 * RC2 is only needed for tests of PKCS#12 support, which currently uses
503 * the RC2 PBE. So no RC2 -> tests fail.
507 * The RC2 cipher type - OpenSSL
509 * @return the RC2 EVP_CIPHER pointer.
511 * @ingroup hcrypto_evp
513 OSSL_CIPHER_ALGORITHM(rc2_cbc,
514 hc_EVP_CIPH_CBC_MODE |
515 hc_EVP_CIPH_VARIABLE_LENGTH)
518 * The RC2-40 cipher type - OpenSSL
520 * @return the RC2-40 EVP_CIPHER pointer.
522 * @ingroup hcrypto_evp
524 OSSL_CIPHER_ALGORITHM(rc2_40_cbc,
525 hc_EVP_CIPH_CBC_MODE)
528 * The RC2-64 cipher type - OpenSSL
530 * @return the RC2-64 EVP_CIPHER pointer.
532 * @ingroup hcrypto_evp
534 OSSL_CIPHER_ALGORITHM(rc2_64_cbc,
535 hc_EVP_CIPH_CBC_MODE |
536 hc_EVP_CIPH_VARIABLE_LENGTH)
539 * The Camellia-128 cipher type - OpenSSL
541 * @return the Camellia-128 EVP_CIPHER pointer.
543 * @ingroup hcrypto_evp
545 OSSL_CIPHER_ALGORITHM(camellia_128_cbc, hc_EVP_CIPH_CBC_MODE)
548 * The Camellia-198 cipher type - OpenSSL
550 * @return the Camellia-198 EVP_CIPHER pointer.
552 * @ingroup hcrypto_evp
554 OSSL_CIPHER_ALGORITHM(camellia_192_cbc, hc_EVP_CIPH_CBC_MODE)
557 * The Camellia-256 cipher type - OpenSSL
559 * @return the Camellia-256 EVP_CIPHER pointer.
561 * @ingroup hcrypto_evp
563 OSSL_CIPHER_ALGORITHM(camellia_256_cbc, hc_EVP_CIPH_CBC_MODE)
566 * The RC4 cipher type (OpenSSL provider)
568 * @return the RC4 EVP_CIPHER pointer.
570 * @ingroup hcrypto_evp
572 OSSL_CIPHER_ALGORITHM(rc4,
573 hc_EVP_CIPH_STREAM_CIPHER |
574 hc_EVP_CIPH_VARIABLE_LENGTH)
577 * The RC4-40 cipher type (OpenSSL provider)
579 * @return the RC4 EVP_CIPHER pointer.
581 * @ingroup hcrypto_evp
583 OSSL_CIPHER_ALGORITHM(rc4_40,
584 hc_EVP_CIPH_STREAM_CIPHER |
585 hc_EVP_CIPH_VARIABLE_LENGTH)
588 * The MD2 hash algorithm (OpenSSL provider)
590 * @return the MD2 EVP_MD pointer.
592 * @ingroup hcrypto_evp
594 OSSL_MD_ALGORITHM(md2)
597 * The MD4 hash algorithm (OpenSSL provider)
599 * @return the MD4 EVP_MD pointer.
601 * @ingroup hcrypto_evp
603 OSSL_MD_ALGORITHM(md4)
606 * The MD5 hash algorithm (OpenSSL provider)
608 * @return the MD5 EVP_MD pointer.
610 * @ingroup hcrypto_evp
612 OSSL_MD_ALGORITHM(md5)
615 * The SHA-1 hash algorithm (OpenSSL provider)
617 * @return the SHA-1 EVP_MD pointer.
619 * @ingroup hcrypto_evp
621 OSSL_MD_ALGORITHM(sha1)
624 * The SHA-256 hash algorithm (OpenSSL provider)
626 * @return the SHA-256 EVP_MD pointer.
628 * @ingroup hcrypto_evp
630 OSSL_MD_ALGORITHM(sha256)
633 * The SHA-384 hash algorithm (OpenSSL provider)
635 * @return the SHA-384 EVP_MD pointer.
637 * @ingroup hcrypto_evp
639 OSSL_MD_ALGORITHM(sha384)
642 * The SHA-512 hash algorithm (OpenSSL provider)
644 * @return the SHA-512 EVP_MD pointer.
646 * @ingroup hcrypto_evp
648 OSSL_MD_ALGORITHM(sha512)