This adds a new backend for libhcrypto: the OpenSSL backend.
Now libhcrypto has these backends:
- hcrypto itself (i.e., the algorithms coded in lib/hcrypto)
- Common Crypto (OS X)
- PKCS#11 (specifically for Solaris, but not Solaris-specific)
- Windows CNG (Windows)
- OpenSSL (generic)
The ./configure --with-openssl=... option no longer disables the use of
hcrypto. Instead it enables the use of OpenSSL as a (and the default)
backend in libhcrypto. The libhcrypto framework is now always used.
OpenSSL should no longer be used directly within Heimdal, except in the
OpenSSL hcrypto backend itself, and files where elliptic curve (EC)
crypto is needed.
Because libhcrypto's EC support is incomplete, we can only use OpenSSL
for EC. Currently that means separating all EC-using code so that it
does not use hcrypto, thus the libhx509/hxtool and PKINIT EC code has
been moved out of the files it used to be in.
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_readline) $(INCLUDE_hcrypto)
+AM_CPPFLAGS += $(INCLUDE_readline)
man_MANS = ktutil.1
WFLAGS += $(WFLAGS_LITE)
-AM_CPPFLAGS += -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_hcrypto)
+AM_CPPFLAGS += -I$(srcdir)/../common $(INCLUDE_readline)
bin_PROGRAMS = ftp
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto)
-
bin_PROGRAMS = otp otpprint
bin_SUIDS = otp
otp_SOURCES = otp.c otp_locl.h
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto)
-
bin_PROGRAMS = su
bin_SUIDS = su
su_SOURCES = su.c supaths.h
m4_define([test_headers], [
#undef KRB5 /* makes md4.h et al unhappy */
- #ifdef HAVE_OPENSSL
+ #ifdef HAVE_HCRYPTO_W_OPENSSL
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
EVP_CIPHER_iv_length(((EVP_CIPHER*)0));
UI_UTIL_read_pw_string(0,0,0,0);
RAND_status();
- #ifdef HAVE_OPENSSL
+ #ifdef HAVE_HCRYPTO_W_OPENSSL
EC_KEY_new();
#endif
DES_cbc_encrypt(0, 0, 0, schedule, 0, 0);
RC4(0, 0, 0, 0);])
-m4_define([bn_headers], [
- #include <stdlib.h>
- #include <openssl/bn.h>
- ])
-m4_define([bn_body], [
- BIGNUM *bn = BN_new();
- BN_set_word(bn, 1);
- if (BN_is_negative(bn))
- exit(EXIT_FAILURE);
- BN_set_negative(bn, 1);
- if (!BN_is_negative(bn))
- exit(EXIT_FAILURE);
- exit(EXIT_SUCCESS);
- ])
-
AC_DEFUN([KRB_CRYPTO],[
-crypto_lib=unknown
AC_WITH_ALL([openssl])
-DIR_hcrypto=
-
AC_MSG_CHECKING([for crypto library])
openssl=no
-if test "$crypto_lib" = "unknown" -a "$with_openssl" != "no"; then
- save_CFLAGS="$CFLAGS"
- save_LIBS="$LIBS"
- INCLUDE_hcrypto=
- LIB_hcrypto=
+if test "$with_openssl" = "yes"; then
+ with_openssl=/usr
+fi
+if test "$with_openssl" != "no"; then
+ INCLUDE_openssl_crypto=
+ LIB_openssl_crypto=
if test "$with_openssl_include" != ""; then
- INCLUDE_hcrypto="-I${with_openssl_include}"
+ INCLUDE_openssl_crypto="${with_openssl_include}"
+ else
+ INCLUDE_openssl_crypto="${with_openssl}/include"
fi
if test "$with_openssl_lib" != ""; then
- LIB_hcrypto="-L${with_openssl_lib}"
+ LIB_openssl_crypto="-L${with_openssl_lib}"
fi
- CFLAGS="-DHAVE_OPENSSL ${INCLUDE_hcrypto} ${CFLAGS}"
- saved_LIB_hcrypto="$LIB_hcrypto"
- for lres in "" "-ldl" "-lnsl -lsocket" "-lnsl -lsocket -ldl"; do
- LIB_hcrypto="${saved_LIB_hcrypto} -lcrypto $lres"
- LIB_hcrypto_a="$LIB_hcrypto"
- LIB_hcrypto_so="$LIB_hcrypto"
- LIB_hcrypto_appl="$LIB_hcrypto"
- LIBS="${LIBS} ${LIB_hcrypto}"
- AC_LINK_IFELSE([AC_LANG_PROGRAM([test_headers],[test_body])], [
- crypto_lib=libcrypto openssl=yes
- AC_MSG_RESULT([libcrypto])
- AC_RUN_IFELSE([AC_LANG_PROGRAM([bn_headers],[bn_body])], [
- AC_DEFINE([HAVE_BN_IS_NEGATIVE], 1, [define if OpenSSL provides BN_is_negative])
- ])
- ])
- if test "$crypto_lib" = libcrypto ; then
- break;
- fi
- done
- AC_CHECK_LIB(crypto, OPENSSL_init, [])
- CFLAGS="$save_CFLAGS"
- LIBS="$save_LIBS"
+ CFLAGS="-DHAVE_HCRYPTO_W_OPENSSL -I${INCLUDE_openssl_crypto} ${CFLAGS}"
+ # XXX What about rpath? Yeah...
+ AC_CHECK_LIB([crypto], [OPENSSL_init],
+ [LIB_openssl_crypto="${LIB_openssl_crypto} -lcrypto"; openssl=yes], [openssl=no], [])
+ # These cases are just for static linking on older OSes,
+ # presumably.
+ if test "$openssl" = "no"; then
+ AC_CHECK_LIB([crypto], [OPENSSL_init],
+ [LIB_openssl_crypto="${LIB_openssl_crypto} -lcrypto -ldl"; openssl=yes], [openssl=no], [-ldl])
+ fi
+ if test "$openssl" = "no"; then
+ AC_CHECK_LIB([crypto], [OPENSSL_init],
+ [LIB_openssl_crypto="${LIB_openssl_crypto} -lcrypto -ldl -lnsl"; openssl=yes], [openssl=no], [-ldl -lnsl])
+ fi
+ if test "$openssl" = "no"; then
+ AC_CHECK_LIB([crypto], [OPENSSL_init],
+ [LIB_openssl_crypto="${LIB_openssl_crypto} -lcrypto -ldl -lnsl -lsocket"; openssl=yes], [openssl=no], [-ldl -lnsl -lsocket])
+ fi
fi
-if test "$crypto_lib" = "unknown"; then
-
- DIR_hcrypto='hcrypto'
- LIB_hcrypto='$(top_builddir)/lib/hcrypto/libhcrypto.la'
- LIB_hcrypto_a='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.a'
- LIB_hcrypto_so='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.so'
- LIB_hcrypto_appl="-lhcrypto"
+LIB_hcrypto='$(top_builddir)/lib/hcrypto/libhcrypto.la'
+LIB_hcrypto_a='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.a'
+LIB_hcrypto_so='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.so'
+LIB_hcrypto_appl="-lhcrypto"
- AC_MSG_RESULT([included libhcrypto])
-
-fi
+AC_MSG_RESULT([included libhcrypto])
AC_ARG_WITH(pkcs11-module,
AS_HELP_STRING([--with-pkcs11-module=path],
fi
if test "$openssl" = "yes"; then
- AC_DEFINE([HAVE_OPENSSL], 1, [define to use openssl's libcrypto])
+ AC_DEFINE([HAVE_HCRYPTO_W_OPENSSL], 1, [define to use openssl's libcrypto as the default backend for libhcrypto])
fi
-AM_CONDITIONAL(HAVE_OPENSSL, test "$openssl" = yes)dnl
+AM_CONDITIONAL(HAVE_HCRYPTO_W_OPENSSL, test "$openssl" = yes)dnl
-AC_SUBST(DIR_hcrypto)
-AC_SUBST(INCLUDE_hcrypto)
+AC_SUBST(INCLUDE_openssl_crypto)
+AC_SUBST(LIB_openssl_crypto)
AC_SUBST(LIB_hcrypto)
AC_SUBST(LIB_hcrypto_a)
AC_SUBST(LIB_hcrypto_so)
/***********************************************************************
- * Copyright (c) 2009, Secure Endpoints Inc.
+ * Copyright (c) 2009-2016, Secure Endpoints Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* Define to 1 if you have the `openpty' function. */
/* #define HAVE_OPENPTY 1 */
-/* define to use openssl's libcrypto */
-/* #undef HAVE_OPENSSL */
+/* define to 1 to use openssl's libcrypto as a (default) backend for libhcrypto */
+/* #undef HAVE_HCRYPTO_W_OPENSSL */
/* Define to enable basic OSF C2 support. */
/* #undef HAVE_OSFC2 */
#error "need config.h"
#endif
-#ifdef HAVE_OPENSSL
-
-#define OPENSSL_DES_LIBDES_COMPATIBILITY
-
-#include <openssl/evp.h>
-#include <openssl/des.h>
-#include <openssl/rc4.h>
-#include <openssl/rc2.h>
-#include <openssl/md4.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
-#include <openssl/ui.h>
-#include <openssl/rand.h>
-#include <openssl/engine.h>
-#include <openssl/pkcs12.h>
-#include <openssl/pem.h>
-#include <openssl/hmac.h>
-#include <openssl/rsa.h>
-#include <openssl/dsa.h>
-#include <openssl/ec.h>
-#include <openssl/ecdsa.h>
-#include <openssl/ecdh.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-#ifndef HAVE_BN_IS_NEGATIVE
-#define BN_set_negative(bn, flag) ((bn)->neg=(flag)?1:0)
-#define BN_is_negative(bn) ((bn)->neg != 0)
-#endif
-
-#else /* !HAVE_OPENSSL */
-
#ifdef KRB5
#include <krb5-types.h>
#endif
#include <hcrypto/engine.h>
#include <hcrypto/pkcs12.h>
#include <hcrypto/hmac.h>
-#include <hcrypto/ec.h>
-#include <hcrypto/ecdsa.h>
-#include <hcrypto/ecdh.h>
-
-#endif /* HAVE_OPENSSL */
#endif /* __crypto_header__ */
rc4.h \
rsa.h \
sha.h \
- ui.h
+ ui.h \
+ undef.h
EXTRA_DIST = NTMakefile
/*
- * Copyright (c) 2003 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_readline) $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5 -I$(top_builddir)/include/gssapi
+AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_readline) -I$(srcdir)/../lib/krb5 -I$(top_builddir)/include/gssapi
bin_PROGRAMS = kadmin
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5
+AM_CPPFLAGS += $(INCLUDE_libintl) -I$(srcdir)/../lib/krb5
libexec_PROGRAMS = kcm
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5
+AM_CPPFLAGS += $(INCLUDE_libintl) -I$(srcdir)/../lib/krb5
lib_LTLIBRARIES = libkdc.la
kerberos5.c \
krb5tgs.c \
pkinit.c \
+ pkinit-ec.c \
log.c \
misc.c \
kx509.c \
$(LIB_kdb) \
$(top_builddir)/lib/ntlm/libheimntlm.la \
$(LIB_hcrypto) \
+ $(LIB_openssl_crypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
$(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
########################################################################
#
-# Copyright (c) 2009, Secure Endpoints Inc.
+# Copyright (c) 2009-2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
$(LIBEXECDIR)\kdc.exe: \
$(OBJ)\connect.obj $(OBJ)\config.obj $(OBJ)\announce.obj \
$(OBJ)\main.obj $(OBJ)\kdc-version.res \
- $(LIBKDC) $(BIN_LIBS)
+ $(LIBKDC) $(BIN_LIBS) $(LIB_openssl_crypto)
$(EXECONLINK)
$(EXEPREP)
$(OBJ)\kerberos5.obj \
$(OBJ)\krb5tgs.obj \
$(OBJ)\pkinit.obj \
+ $(OBJ)\pkinit-ec.obj \
$(OBJ)\log.obj \
$(OBJ)\misc.obj \
$(OBJ)\kx509.obj \
$(OBJ)\windc.obj
LIBKDC_LIBS=\
- $(LIBHDB) \
- $(LIBHEIMBASE) \
- $(LIBHEIMDAL) \
- $(LIBHEIMNTLM) \
+ $(LIBHDB) \
+ $(LIBHEIMBASE) \
+ $(LIBHEIMDAL) \
+ $(LIBHEIMNTLM) \
+ $(LIB_openssl_crypto) \
$(LIBROKEN)
LIBKDCRES=$(OBJ)\libkdc-version.res
kerberos5.c \
krb5tgs.c \
pkinit.c \
+ pkinit-ec.c \
log.c \
misc.c \
kx509.c \
--- /dev/null
+/*
+ * Copyright (c) 2016 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#ifdef PKINIT
+
+/*
+ * As with the other *-ec.c files in Heimdal, this is a bit of a hack.
+ *
+ * The idea is to use OpenSSL for EC because hcrypto doesn't have the
+ * required functionality at this time. To do this we segregate
+ * EC-using code into separate source files and then we arrange for them
+ * to get the OpenSSL headers and not the conflicting hcrypto ones.
+ *
+ * Because of auto-generated *-private.h headers, we end up needing to
+ * make sure various types are defined before we include them, thus the
+ * strange header include order here.
+ */
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#define HEIM_NO_CRYPTO_HDRS
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#define NO_HCRYPTO_POLLUTION
+
+#include <hcrypto/des.h>
+
+#include "kdc_locl.h"
+
+#include <heim_asn1.h>
+#include <rfc2459_asn1.h>
+#include <cms_asn1.h>
+#include <pkinit_asn1.h>
+
+#include <hx509.h>
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static void
+free_client_ec_param(krb5_context context,
+ EC_KEY *ec_key_pk,
+ EC_KEY *ec_key_key)
+{
+ if (ec_key_pk != NULL)
+ EC_KEY_free(ec_key_pk);
+ if (ec_key_key != NULL)
+ EC_KEY_free(ec_key_key);
+}
+#endif
+
+void
+_kdc_pk_free_client_ec_param(krb5_context context,
+ void *ec_key_pk,
+ void *ec_key_key)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ free_client_ec_param(context, ec_key_pk, ec_key_key);
+#endif
+}
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+generate_ecdh_keyblock(krb5_context context,
+ EC_KEY *ec_key_pk, /* the client's public key */
+ EC_KEY **ec_key_key, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
+{
+ const EC_GROUP *group;
+ EC_KEY *ephemeral;
+ krb5_keyblock key;
+ krb5_error_code ret;
+ unsigned char *p;
+ size_t size;
+ int len;
+
+ *dh_gen_key = NULL;
+ *dh_gen_keylen = 0;
+ *ec_key_key = NULL;
+
+ memset(&key, 0, sizeof(key));
+
+ if (ec_key_pk == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "public_key");
+ return ret;
+ }
+
+ group = EC_KEY_get0_group(ec_key_pk);
+ if (group == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "failed to get the group of "
+ "the client's public key");
+ return ret;
+ }
+
+ ephemeral = EC_KEY_new();
+ if (ephemeral == NULL)
+ return krb5_enomem(context);
+
+ EC_KEY_set_group(ephemeral, group);
+
+ if (EC_KEY_generate_key(ephemeral) != 1) {
+ EC_KEY_free(ephemeral);
+ return krb5_enomem(context);
+ }
+
+ size = (EC_GROUP_get_degree(group) + 7) / 8;
+ p = malloc(size);
+ if (p == NULL) {
+ EC_KEY_free(ephemeral);
+ return krb5_enomem(context);
+ }
+
+ len = ECDH_compute_key(p, size,
+ EC_KEY_get0_public_key(ec_key_pk),
+ ephemeral, NULL);
+ if (len <= 0) {
+ free(p);
+ EC_KEY_free(ephemeral);
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "Failed to compute ECDH "
+ "public shared secret");
+ return ret;
+ }
+
+ *ec_key_key = ephemeral;
+ *dh_gen_key = p;
+ *dh_gen_keylen = len;
+
+ return 0;
+}
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+krb5_error_code
+_kdc_generate_ecdh_keyblock(krb5_context context,
+ void *ec_key_pk, /* the client's public key */
+ void **ec_key_key, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return generate_ecdh_keyblock(context, ec_key_pk,
+ (EC_KEY **)ec_key_key,
+ dh_gen_key, dh_gen_keylen);
+#else
+ return ENOTSUP;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+get_ecdh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ EC_KEY **out)
+{
+ ECParameters ecp;
+ EC_KEY *public = NULL;
+ krb5_error_code ret;
+ const unsigned char *p;
+ size_t len;
+ int nid;
+
+ if (dh_key_info->algorithm.parameters == NULL) {
+ krb5_set_error_message(context, KRB5_BADMSGTYPE,
+ "PKINIT missing algorithm parameter "
+ "in clientPublicValue");
+ return KRB5_BADMSGTYPE;
+ }
+
+ memset(&ecp, 0, sizeof(ecp));
+
+ ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
+ dh_key_info->algorithm.parameters->length, &ecp, &len);
+ if (ret)
+ goto out;
+
+ if (ecp.element != choice_ECParameters_namedCurve) {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
+ nid = NID_X9_62_prime256v1;
+ else {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ /* XXX verify group is ok */
+
+ public = EC_KEY_new_by_curve_name(nid);
+
+ p = dh_key_info->subjectPublicKey.data;
+ len = dh_key_info->subjectPublicKey.length / 8;
+ if (o2i_ECPublicKey(&public, &p, len) == NULL) {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to decode ECDH key");
+ goto out;
+ }
+ *out = public;
+ public = NULL;
+
+ out:
+ if (public)
+ EC_KEY_free(public);
+ free_ECParameters(&ecp);
+ return ret;
+}
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+krb5_error_code
+_kdc_get_ecdh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ void **out)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return get_ecdh_param(context, config, dh_key_info, (EC_KEY **)out);
+#else
+ return ENOTSUP;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
+
+
+/*
+ *
+ */
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+serialize_ecdh_key(krb5_context context,
+ EC_KEY *key,
+ unsigned char **out,
+ size_t *out_len)
+{
+ krb5_error_code ret = 0;
+ unsigned char *p;
+ int len;
+
+ *out = NULL;
+ *out_len = 0;
+
+ len = i2o_ECPublicKey(key, NULL);
+ if (len <= 0)
+ return EOVERFLOW;
+
+ *out = malloc(len);
+ if (*out == NULL)
+ return krb5_enomem(context);
+
+ p = *out;
+ len = i2o_ECPublicKey(key, &p);
+ if (len <= 0) {
+ free(*out);
+ *out = NULL;
+ ret = EINVAL; /* XXX Better error please */
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to encode ECDH key");
+ return ret;
+ }
+
+ *out_len = len * 8;
+ return ret;
+}
+#endif
+
+krb5_error_code
+_kdc_serialize_ecdh_key(krb5_context context,
+ void *key,
+ unsigned char **out,
+ size_t *out_len)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return serialize_ecdh_key(context, key, out, out_len);
+#else
+ return ENOTSUP;
+#endif
+}
+
+#endif
/*
- * Copyright (c) 2003 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
BIGNUM *public_key;
DH *key;
} dh;
-#ifdef HAVE_OPENSSL
struct {
- EC_KEY *public_key;
- EC_KEY *key;
+ void *public_key;
+ void *key;
} ecdh;
-#endif
} u;
hx509_cert cert;
unsigned nonce;
if (cp->u.dh.public_key)
BN_free(cp->u.dh.public_key);
}
-#ifdef HAVE_OPENSSL
- if (cp->keyex == USE_ECDH) {
- if (cp->u.ecdh.key)
- EC_KEY_free(cp->u.ecdh.key);
- if (cp->u.ecdh.public_key)
- EC_KEY_free(cp->u.ecdh.public_key);
- }
-#endif
+ if (cp->keyex == USE_ECDH)
+ _kdc_pk_free_client_ec_param(context, cp->u.ecdh.key,
+ cp->u.ecdh.public_key);
krb5_free_keyblock_contents(context, &cp->reply_key);
if (cp->dh_group_name)
free(cp->dh_group_name);
if (client_params->u.dh.public_key == NULL) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "public_key");
+ krb5_set_error_message(context, ret, "missing DH public_key");
goto out;
}
}
ret = 0;
-#ifdef HAVE_OPENSSL
} else if (client_params->keyex == USE_ECDH) {
-
if (client_params->u.ecdh.public_key == NULL) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "public_key");
- goto out;
- }
-
- client_params->u.ecdh.key = EC_KEY_new();
- if (client_params->u.ecdh.key == NULL) {
- ret = ENOMEM;
+ krb5_set_error_message(context, ret, "missing ECDH public_key");
goto out;
}
- EC_KEY_set_group(client_params->u.ecdh.key,
- EC_KEY_get0_group(client_params->u.ecdh.public_key));
-
- if (EC_KEY_generate_key(client_params->u.ecdh.key) != 1) {
- ret = ENOMEM;
- goto out;
- }
-
- size = (EC_GROUP_get_degree(EC_KEY_get0_group(client_params->u.ecdh.key)) + 7) / 8;
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret,
- N_("malloc: out of memory", ""));
- goto out;
- }
-
- dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
- EC_KEY_get0_public_key(client_params->u.ecdh.public_key),
- client_params->u.ecdh.key, NULL);
-
-#endif /* HAVE_OPENSSL */
+ ret = _kdc_generate_ecdh_keyblock(context,
+ client_params->u.ecdh.public_key,
+ &client_params->u.ecdh.key,
+ &dh_gen_key, &dh_gen_keylen);
+ if (ret)
+ goto out;
} else {
ret = KRB5KRB_ERR_GENERIC;
krb5_set_error_message(context, ret,
return ret;
}
-#ifdef HAVE_OPENSSL
-
-static krb5_error_code
-get_ecdh_param(krb5_context context,
- krb5_kdc_configuration *config,
- SubjectPublicKeyInfo *dh_key_info,
- pk_client_params *client_params)
-{
- ECParameters ecp;
- EC_KEY *public = NULL;
- krb5_error_code ret;
- const unsigned char *p;
- size_t len;
- int nid;
-
- if (dh_key_info->algorithm.parameters == NULL) {
- krb5_set_error_message(context, KRB5_BADMSGTYPE,
- "PKINIT missing algorithm parameter "
- "in clientPublicValue");
- return KRB5_BADMSGTYPE;
- }
-
- memset(&ecp, 0, sizeof(ecp));
-
- ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
- dh_key_info->algorithm.parameters->length, &ecp, &len);
- if (ret)
- goto out;
-
- if (ecp.element != choice_ECParameters_namedCurve) {
- ret = KRB5_BADMSGTYPE;
- goto out;
- }
-
- if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
- nid = NID_X9_62_prime256v1;
- else {
- ret = KRB5_BADMSGTYPE;
- goto out;
- }
-
- /* XXX verify group is ok */
-
- public = EC_KEY_new_by_curve_name(nid);
-
- p = dh_key_info->subjectPublicKey.data;
- len = dh_key_info->subjectPublicKey.length / 8;
- if (o2i_ECPublicKey(&public, &p, len) == NULL) {
- ret = KRB5_BADMSGTYPE;
- krb5_set_error_message(context, ret,
- "PKINIT failed to decode ECDH key");
- goto out;
- }
- client_params->u.ecdh.public_key = public;
- public = NULL;
-
- out:
- if (public)
- EC_KEY_free(public);
- free_ECParameters(&ecp);
- return ret;
-}
-
-#endif /* HAVE_OPENSSL */
-
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
krb5_kdc_configuration *config,
cp->keyex = USE_DH;
ret = get_dh_param(context, config,
ap.clientPublicValue, cp);
-#ifdef HAVE_OPENSSL
} else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
cp->keyex = USE_ECDH;
- ret = get_ecdh_param(context, config,
- ap.clientPublicValue, cp);
-#endif /* HAVE_OPENSSL */
+ ret = _kdc_get_ecdh_param(context, config,
+ ap.clientPublicValue,
+ &cp->u.ecdh.public_key);
} else {
ret = KRB5_BADMSGTYPE;
krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
dh_info.subjectPublicKey.length = buf.length * 8;
dh_info.subjectPublicKey.data = buf.data;
krb5_data_zero(&buf);
-#ifdef HAVE_OPENSSL
} else if (cp->keyex == USE_ECDH) {
- unsigned char *p;
- int len;
-
- len = i2o_ECPublicKey(cp->u.ecdh.key, NULL);
- if (len <= 0)
- abort();
-
- p = malloc(len);
- if (p == NULL)
- abort();
-
- dh_info.subjectPublicKey.length = len * 8;
- dh_info.subjectPublicKey.data = p;
-
- len = i2o_ECPublicKey(cp->u.ecdh.key, &p);
- if (len <= 0)
- abort();
-#endif
+ unsigned char *p;
+ ret = _kdc_serialize_ecdh_key(context, cp->u.ecdh.key, &p,
+ &dh_info.subjectPublicKey.length);
+ dh_info.subjectPublicKey.data = p;
+ if (ret)
+ goto out;
} else
krb5_abortx(context, "no keyex selected ?");
switch (cp->keyex) {
case USE_DH: type = "dh"; break;
-#ifdef HAVE_OPENSSL
case USE_ECDH: type = "ecdh"; break;
-#endif
default: krb5_abortx(context, "unknown keyex"); break;
}
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto)
-
man_MANS = kpasswd.1 kpasswdd.8
bin_PROGRAMS = kpasswd
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5 \
+AM_CPPFLAGS += -I$(srcdir)/../lib/krb5 \
$(INCLUDE_libintl) \
-DHEIMDAL_LOCALEDIR='"$(localedir)"'
########################################################################
#
-# Copyright (c) 2009,2011, Secure Endpoints Inc.
+# Copyright (c) 2009-2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
/*
- * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * Copyright (c) 2010-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
-I$(srcdir)/ntlm \
-I$(srcdir)/krb5 \
-I$(srcdir)/spnego \
- $(INCLUDE_libintl) \
- $(INCLUDE_hcrypto)
+ $(INCLUDE_libintl)
lib_LTLIBRARIES = libgssapi.la
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
include $(top_srcdir)/Makefile.am.common
+if HAVE_HCRYPTO_W_OPENSSL
+AM_CPPFLAGS += -I$(INCLUDE_openssl_crypto)
+endif
+
AM_CPPFLAGS += -I$(top_srcdir)/lib/hx509 \
- -I$(srcdir)/libtommath -DUSE_HCRYPTO_LTM=1
+ -I$(srcdir)/libtommath -DUSE_HCRYPTO_LTM=1
lib_LTLIBRARIES = libhcrypto.la
check_LTLIBRARIES = libhctest.la
$(LIB_heimbase) \
$(LIBADD_roken)
+if HAVE_HCRYPTO_W_OPENSSL
+libhcrypto_la_LIBADD += $(LIB_openssl_crypto)
+endif
+
hcryptoincludedir = $(includedir)/hcrypto
buildhcryptoinclude = $(buildinclude)/hcrypto
evp.h \
evp-hcrypto.h \
evp-cc.h \
+ evp-openssl.h \
evp-pkcs11.h \
hmac.h \
md2.h \
rc4.h \
rsa.h \
sha.h \
- ui.h
+ ui.h \
+ undef.h
install-build-headers:: $(hcryptoinclude_HEADERS)
@foo='$(hcryptoinclude_HEADERS)'; \
evp.h \
evp-hcrypto.c \
evp-cc.c \
+ evp-openssl.c \
evp-pkcs11.c \
engine.c \
engine.h \
sha512.c \
validate.c \
ui.c \
- ui.h
+ ui.h \
+ undef.h
ltmsources = \
libtommath/tommath.h \
########################################################################
#
-# Copyright (c) 2009, Secure Endpoints Inc.
+# Copyright (c) 2009-2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
HX509DIR = $(SRC)\lib\hx509
+!if INCLUDE_openssl_crypto
+openssl_inc=-I$(INCLUDE_openssl_crypto)
+!endif
+
intcflags=-DKRB5 -DASN1_LIB -I$(HCRYPTOINCLUDEDIR) -DUSE_HCRYPTO_LTM=1 \
- -I$(HX509DIR)
+ -I$(HX509DIR) $(openssl_inc)
# Do dependencies first
$(HCRYPTOINCLUDEDIR)\evp.h \
$(HCRYPTOINCLUDEDIR)\evp-hcrypto.h \
$(HCRYPTOINCLUDEDIR)\evp-cc.h \
+ $(HCRYPTOINCLUDEDIR)\evp-openssl.h \
$(HCRYPTOINCLUDEDIR)\evp-pkcs11.h \
$(HCRYPTOINCLUDEDIR)\evp-wincng.h \
$(HCRYPTOINCLUDEDIR)\evp-w32.h \
$(HCRYPTOINCLUDEDIR)\rc4.h \
$(HCRYPTOINCLUDEDIR)\rsa.h \
$(HCRYPTOINCLUDEDIR)\sha.h \
- $(HCRYPTOINCLUDEDIR)\ui.h
+ $(HCRYPTOINCLUDEDIR)\ui.h \
+ $(HCRYPTOINCLUDEDIR)\undef.h
mkincdir:
!if !exist($(HCRYPTOINCLUDEDIR))
$(OBJ)\evp.obj \
$(OBJ)\evp-hcrypto.obj \
$(OBJ)\evp-cc.obj \
+ $(OBJ)\evp-openssl.obj \
$(OBJ)\evp-pkcs11.obj \
$(OBJ)\evp-wincng.obj \
$(OBJ)\evp-w32.obj \
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#define BN_GENCB hc_BN_GENCB
#define BN_CTX hc_BN_CTX
#define BN_BLINDING hc_BN_BLINDING
+#define BN_MONT_CTX hc_BN_MONT_CTX
+
/*
*
#define _HEIM_DH_H 1
/* symbol renaming */
+#define DH hc_DH
+#define DH_METHOD hc_DH_METHOD
#define DH_null_method hc_DH_null_method
#define DH_tfm_method hc_DH_tfm_method
#define DH_ltm_method hc_DH_ltm_method
#include <hcrypto/bn.h>
/* symbol renaming */
+#define DSA hc_DSA
+#define DSA_METHOD hc_DSA_METHOD
#define DSA_null_method hc_DSA_null_method
#define DSA_new hc_DSA_new
#define DSA_free hc_DSA_free
/*
- * Copyright (c) 2009 Kungliga Tekniska Högskolan
+ * Copyright (c) 2009-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
--- /dev/null
+/*
+ * Copyright (c) 2016, Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* OpenSSL provider */
+
+#include "config.h"
+#include <roken.h>
+#include <heimbase.h>
+
+#include <assert.h>
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+
+/*
+ * This is the OpenSSL 1.x backend for hcrypto. It has been tested with
+ * OpenSSL 1.0.1f and OpenSSL 1.1.0-pre3-dev.
+ *
+ * NOTE: In order for this to work with OpenSSL 1.1.x and up, it is
+ * critical to use opaque OpenSSL type accessors everywhere /
+ * never use knowledge of opaque OpenSSL type internals.
+ */
+
+#include <evp.h>
+#include <evp-openssl.h>
+
+/*
+ * This being an OpenSSL backend for hcrypto... we need to be able to
+ * refer to types and objects (functions) from both, OpenSSL and
+ * hcrypto.
+ *
+ * The hcrypto API is *very* similar to the OpenSSL 1.0.x API, with the
+ * same type and symbol names in many cases, except that the hcrypto
+ * names are prefixed with hc_*. hcrypto has convenience macros that
+ * provide OpenSSL aliases for the hcrypto interfaces, and hcrypto
+ * applications are expected to use the OpenSSL names.
+ *
+ * Since here we must be able to refer to types and objects from both
+ * OpenSSL and from hcrypto, we disable the hcrypto renaming for the
+ * rest of this file. These #undefs could be collected into an
+ * <hcrypto/undef.h> for the purpose of permitting other applications to
+ * use both, hcrypto and OpenSSL in the same source files (provided that
+ * such applications refer to hcrypto types and objects by their proper
+ * hc_-prefixed names).
+ */
+#include <undef.h>
+
+/* Now it's safe to include OpenSSL headers */
+#include <openssl/evp.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#endif
+
+/* A HEIM_BASE_ONCE argument struct for per-EVP one-time initialization */
+struct once_init_cipher_ctx {
+ hc_EVP_CIPHER **hc_memoizep; /* ptr to static ptr to hc_EVP_CIPHER */
+ hc_EVP_CIPHER *hc_memoize; /* ptr to static hc_EVP_CIPHER */
+ unsigned long flags;
+ unsigned char *initialized;
+ int nid;
+};
+
+/* Our wrapper for OpenSSL EVP_CIPHER_CTXs */
+struct ossl_cipher_ctx {
+ EVP_CIPHER_CTX *ossl_cipher_ctx; /* OpenSSL cipher ctx */
+ const EVP_CIPHER *ossl_cipher; /* OpenSSL cipher */
+ int initialized;
+};
+
+/*
+ * Our hc_EVP_CIPHER init() method; wraps around OpenSSL
+ * EVP_CipherInit_ex().
+ *
+ * This is very similar to the init() function pointer in an OpenSSL
+ * EVP_CIPHER, but a) we can't access them in 1.1, and b) the method
+ * invocation protocols in hcrypto and OpenSSL are similar but not the
+ * same, thus we must have this wrapper.
+ */
+static int
+cipher_ctx_init(hc_EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data; /* EVP_CIPHER_CTX wrapper */
+ const EVP_CIPHER *c;
+
+ assert(ossl_ctx != NULL);
+ assert(ctx->cipher != NULL);
+ assert(ctx->cipher->app_data != NULL);
+
+ /*
+ * Here be dragons.
+ *
+ * We need to make sure that the OpenSSL EVP_CipherInit_ex() is
+ * called with cipher!=NULL just once per EVP_CIPHER_CTX, otherwise
+ * state in the OpenSSL EVP_CIPHER_CTX will get cleaned up and then
+ * we'll segfault.
+ *
+ * hcrypto applications can re-initialize an (hc_)EVP_CIPHER_CTX as
+ * usual by calling (hc)EVP_CipherInit_ex() with a non-NULL cipher
+ * argument, and that will cause cipher_cleanup() (below) to be
+ * called.
+ */
+ c = ossl_ctx->ossl_cipher = ctx->cipher->app_data; /* OpenSSL's EVP_CIPHER * */
+ if (!ossl_ctx->initialized) {
+ ossl_ctx->ossl_cipher_ctx = EVP_CIPHER_CTX_new();
+ if (ossl_ctx->ossl_cipher_ctx == NULL)
+ return 0;
+ /*
+ * So we always call EVP_CipherInit_ex() with c!=NULL, but other
+ * things NULL...
+ */
+ if (!EVP_CipherInit_ex(ossl_ctx->ossl_cipher_ctx, c, NULL, NULL, NULL, enc))
+ return 0;
+ ossl_ctx->initialized = 1;
+ }
+
+ /* ...and from here on always call EVP_CipherInit_ex() with c=NULL */
+ if ((ctx->cipher->flags & hc_EVP_CIPH_VARIABLE_LENGTH) &&
+ ctx->key_len > 0)
+ EVP_CIPHER_CTX_set_key_length(ossl_ctx->ossl_cipher_ctx, ctx->key_len);
+
+ return EVP_CipherInit_ex(ossl_ctx->ossl_cipher_ctx, NULL, NULL, key, iv, enc);
+}
+
+static int
+cipher_do_cipher(hc_EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int len)
+{
+ struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
+
+ assert(ossl_ctx != NULL);
+ return EVP_Cipher(ossl_ctx->ossl_cipher_ctx, out, in, len);
+}
+
+static int
+cipher_cleanup(hc_EVP_CIPHER_CTX *ctx)
+{
+ struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
+
+ if (ossl_ctx == NULL || !ossl_ctx->initialized)
+ return 1;
+
+ if (ossl_ctx->ossl_cipher_ctx != NULL)
+ EVP_CIPHER_CTX_free(ossl_ctx->ossl_cipher_ctx);
+
+ ossl_ctx->ossl_cipher_ctx = NULL;
+ ossl_ctx->ossl_cipher = NULL;
+ ossl_ctx->initialized = 0;
+ return 1;
+}
+
+static int
+cipher_ctrl(hc_EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+ struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
+
+ assert(ossl_ctx != NULL);
+ return EVP_CIPHER_CTX_ctrl(ossl_ctx->ossl_cipher_ctx, type, arg, ptr);
+}
+
+
+static void
+get_EVP_CIPHER_once_cb(void *d)
+{
+ struct once_init_cipher_ctx *arg = d;
+ const EVP_CIPHER *ossl_evp;
+ hc_EVP_CIPHER *hc_evp;
+
+ hc_evp = arg->hc_memoize;
+
+ /*
+ * We lookup EVP_CIPHER *s by NID so that we don't fail to find a
+ * symbol such as EVP_aes...() when libcrypto changes after build
+ * time (e.g., updates, LD_LIBRARY_PATH/LD_PRELOAD).
+ */
+ ossl_evp = EVP_get_cipherbynid(arg->nid);
+ if (ossl_evp == NULL) {
+ (void) memset(hc_evp, 0, sizeof(*hc_evp));
+ *arg->hc_memoizep = NULL;
+ *arg->initialized = 1;
+ return;
+ }
+
+ /* Build the hc_EVP_CIPHER */
+ hc_evp->nid = EVP_CIPHER_nid(ossl_evp); /* We would an hcrypto NIDs if we had them */
+ hc_evp->block_size = EVP_CIPHER_block_size(ossl_evp);
+ hc_evp->key_len = EVP_CIPHER_key_length(ossl_evp);
+ hc_evp->iv_len = EVP_CIPHER_iv_length(ossl_evp);
+
+ /*
+ * We force hc_EVP_CipherInit_ex to always call our init() function,
+ * otherwise we don't get a chance to call EVP_CipherInit_ex()
+ * correctly.
+ */
+ hc_evp->flags = hc_EVP_CIPH_ALWAYS_CALL_INIT | arg->flags;
+
+ /* Our cipher context */
+ hc_evp->ctx_size = sizeof(struct ossl_cipher_ctx);
+
+ /* Our wrappers */
+ hc_evp->init = cipher_ctx_init;
+ hc_evp->do_cipher = cipher_do_cipher;
+ hc_evp->cleanup = cipher_cleanup;
+ hc_evp->set_asn1_parameters = NULL;
+ hc_evp->get_asn1_parameters = NULL;
+ hc_evp->ctrl = cipher_ctrl;
+
+ /* Our link to the OpenSSL EVP_CIPHER */
+ hc_evp->app_data = (void *)ossl_evp;
+
+ /* Finally, set the static hc_EVP_CIPHER * to the one we just built */
+ *arg->hc_memoizep = hc_evp;
+ *arg->initialized = 1;
+}
+
+static hc_EVP_CIPHER *
+get_EVP_CIPHER(heim_base_once_t *once, hc_EVP_CIPHER *hc_memoize,
+ hc_EVP_CIPHER **hc_memoizep, unsigned long flags,
+ unsigned char *initialized, int nid)
+{
+ struct once_init_cipher_ctx arg;
+
+ arg.flags = flags;
+ arg.hc_memoizep = hc_memoizep;
+ arg.hc_memoize = hc_memoize;
+ arg.initialized = initialized;
+ arg.nid = nid;
+ heim_base_once_f(once, &arg, get_EVP_CIPHER_once_cb);
+ return *hc_memoizep; /* May be NULL */
+}
+
+#define OSSL_CIPHER_ALGORITHM(name, flags) \
+ const hc_EVP_CIPHER *hc_EVP_ossl_##name(void) \
+ { \
+ static hc_EVP_CIPHER ossl_##name##_st; \
+ static hc_EVP_CIPHER *ossl_##name; \
+ static heim_base_once_t once = HEIM_BASE_ONCE_INIT; \
+ static unsigned char initialized; \
+ if (initialized) \
+ return ossl_##name; \
+ return get_EVP_CIPHER(&once, &ossl_##name##_st, &ossl_##name, \
+ flags, &initialized, NID_##name); \
+ }
+
+/* As above, but for EVP_MDs */
+
+struct ossl_md_ctx {
+ EVP_MD_CTX *ossl_md_ctx; /* OpenSSL md ctx */
+ const EVP_MD *ossl_md; /* OpenSSL md */
+ int initialized;
+};
+
+static int
+ossl_md_init(struct ossl_md_ctx *ctx, const EVP_MD *md)
+{
+ if (ctx->initialized)
+ EVP_MD_CTX_free(ctx->ossl_md_ctx);
+ ctx->initialized = 0;
+
+ ctx->ossl_md = md;
+ ctx->ossl_md_ctx = EVP_MD_CTX_new();
+ if (!EVP_DigestInit(ctx->ossl_md_ctx, md)) {
+ EVP_MD_CTX_free(ctx->ossl_md_ctx);
+ ctx->ossl_md_ctx = NULL;
+ ctx->ossl_md = NULL;
+ return 0;
+ }
+ ctx->initialized = 1;
+ return 1;
+}
+
+static int
+ossl_md_update(hc_EVP_MD_CTX *d, const void *data, size_t count)
+{
+ struct ossl_md_ctx *ctx = (void *)d;
+
+ return EVP_DigestUpdate(ctx->ossl_md_ctx, data, count);
+}
+
+static int
+ossl_md_final(void *md_data, hc_EVP_MD_CTX *d)
+{
+ struct ossl_md_ctx *ctx = (void *)d;
+
+ return EVP_DigestFinal(ctx->ossl_md_ctx, md_data, NULL);
+}
+
+static int
+ossl_md_cleanup(hc_EVP_MD_CTX *d)
+{
+ struct ossl_md_ctx *ctx = (void *)d;
+
+ if (!ctx->initialized)
+ return 1;
+ EVP_MD_CTX_free(ctx->ossl_md_ctx);
+ ctx->ossl_md = NULL;
+ ctx->initialized = 0;
+
+ return 1;
+}
+
+struct once_init_md_ctx {
+ const EVP_MD **ossl_memoizep;
+ hc_EVP_MD **hc_memoizep;
+ hc_EVP_MD *hc_memoize;
+ hc_evp_md_init md_init;
+ int nid;
+ unsigned char *initialized;
+};
+
+static void
+get_EVP_MD_once_cb(void *d)
+{
+ struct once_init_md_ctx *arg = d;
+ const EVP_MD *ossl_evp;
+ hc_EVP_MD *hc_evp;
+
+ hc_evp = arg->hc_memoize;
+ *arg->ossl_memoizep = ossl_evp = EVP_get_digestbynid(arg->nid);
+
+ if (ossl_evp == NULL) {
+ (void) memset(hc_evp, 0, sizeof(*hc_evp));
+ *arg->hc_memoizep = NULL;
+ *arg->initialized = 1;
+ return;
+ }
+
+ /* Build the hc_EVP_MD */
+ hc_evp->ctx_size = sizeof(struct ossl_md_ctx);
+ hc_evp->init = arg->md_init;
+ hc_evp->update = ossl_md_update;
+ hc_evp->final = ossl_md_final;
+ hc_evp->cleanup = ossl_md_cleanup;
+
+ *arg->hc_memoizep = hc_evp;
+ *arg->initialized = 1;
+}
+
+static hc_EVP_MD *
+get_EVP_MD(heim_base_once_t *once, hc_EVP_MD *hc_memoize,
+ hc_EVP_MD **hc_memoizep, const EVP_MD **ossl_memoizep,
+ hc_evp_md_init md_init, unsigned char *initialized, int nid)
+{
+ struct once_init_md_ctx ctx;
+
+ ctx.ossl_memoizep = ossl_memoizep;
+ ctx.hc_memoizep = hc_memoizep;
+ ctx.hc_memoize = hc_memoize;
+ ctx.md_init = md_init;
+ ctx.initialized = initialized;
+ ctx.nid = nid;
+ heim_base_once_f(once, &ctx, get_EVP_MD_once_cb);
+ return *hc_memoizep; /* May be NULL */
+}
+
+#define OSSL_MD_ALGORITHM(name) \
+ static const EVP_MD *ossl_EVP_##name; \
+ static hc_EVP_MD *ossl_##name; \
+ static int ossl_init_##name(hc_EVP_MD_CTX *d) \
+ { \
+ return ossl_md_init((void *)d, ossl_EVP_##name); \
+ } \
+ const hc_EVP_MD *hc_EVP_ossl_##name(void) \
+ { \
+ static hc_EVP_MD ossl_##name##_st; \
+ static heim_base_once_t once = HEIM_BASE_ONCE_INIT; \
+ static unsigned char initialized; \
+ if (initialized) \
+ return ossl_##name; \
+ return get_EVP_MD(&once, &ossl_##name##_st, &ossl_##name, \
+ &ossl_EVP_##name, ossl_init_##name, \
+ &initialized, NID_##name); \
+ }
+
+/**
+ * The triple DES cipher type (OpenSSL provider)
+ *
+ * @return the DES-EDE3-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(des_ede3_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The DES cipher type (OpenSSL provider)
+ *
+ * @return the DES-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(des_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The AES-128 cipher type (OpenSSL provider)
+ *
+ * @return the AES-128-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_128_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The AES-192 cipher type (OpenSSL provider)
+ *
+ * @return the AES-192-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_192_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The AES-256 cipher type (OpenSSL provider)
+ *
+ * @return the AES-256-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_256_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The AES-128 CFB8 cipher type (OpenSSL provider)
+ *
+ * @return the AES-128-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_128_cfb8, hc_EVP_CIPH_CFB8_MODE)
+
+/**
+ * The AES-192 CFB8 cipher type (OpenSSL provider)
+ *
+ * @return the AES-192-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_192_cfb8, hc_EVP_CIPH_CFB8_MODE)
+
+/**
+ * The AES-256 CFB8 cipher type (OpenSSL provider)
+ *
+ * @return the AES-256-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(aes_256_cfb8, hc_EVP_CIPH_CFB8_MODE)
+
+/*
+ * RC2 is only needed for tests of PKCS#12 support, which currently uses
+ * the RC2 PBE. So no RC2 -> tests fail.
+ */
+
+/**
+ * The RC2 cipher type - OpenSSL
+ *
+ * @return the RC2 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(rc2_cbc,
+ hc_EVP_CIPH_CBC_MODE |
+ hc_EVP_CIPH_VARIABLE_LENGTH)
+
+/**
+ * The RC2-40 cipher type - OpenSSL
+ *
+ * @return the RC2-40 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(rc2_40_cbc,
+ hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The RC2-64 cipher type - OpenSSL
+ *
+ * @return the RC2-64 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(rc2_64_cbc,
+ hc_EVP_CIPH_CBC_MODE |
+ hc_EVP_CIPH_VARIABLE_LENGTH)
+
+/**
+ * The Camellia-128 cipher type - OpenSSL
+ *
+ * @return the Camellia-128 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(camellia_128_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The Camellia-198 cipher type - OpenSSL
+ *
+ * @return the Camellia-198 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(camellia_192_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The Camellia-256 cipher type - OpenSSL
+ *
+ * @return the Camellia-256 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(camellia_256_cbc, hc_EVP_CIPH_CBC_MODE)
+
+/**
+ * The RC4 cipher type (OpenSSL provider)
+ *
+ * @return the RC4 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(rc4,
+ hc_EVP_CIPH_STREAM_CIPHER |
+ hc_EVP_CIPH_VARIABLE_LENGTH)
+
+/**
+ * The RC4-40 cipher type (OpenSSL provider)
+ *
+ * @return the RC4 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_CIPHER_ALGORITHM(rc4_40,
+ hc_EVP_CIPH_STREAM_CIPHER |
+ hc_EVP_CIPH_VARIABLE_LENGTH)
+
+/**
+ * The MD2 hash algorithm (OpenSSL provider)
+ *
+ * @return the MD2 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(md2)
+
+/**
+ * The MD4 hash algorithm (OpenSSL provider)
+ *
+ * @return the MD4 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(md4)
+
+/**
+ * The MD5 hash algorithm (OpenSSL provider)
+ *
+ * @return the MD5 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(md5)
+
+/**
+ * The SHA-1 hash algorithm (OpenSSL provider)
+ *
+ * @return the SHA-1 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(sha1)
+
+/**
+ * The SHA-256 hash algorithm (OpenSSL provider)
+ *
+ * @return the SHA-256 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(sha256)
+
+/**
+ * The SHA-384 hash algorithm (OpenSSL provider)
+ *
+ * @return the SHA-384 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(sha384)
+
+/**
+ * The SHA-512 hash algorithm (OpenSSL provider)
+ *
+ * @return the SHA-512 EVP_MD pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+OSSL_MD_ALGORITHM(sha512)
+
+#else /* HAVE_HCRYPTO_W_OPENSSL */
+static char dummy;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
--- /dev/null
+/*
+ * Copyright (c) 2009-2016 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef HEIM_EVP_OSSL_H
+#define HEIM_EVP_OSSL_H 1
+
+/* symbol renaming */
+#define EVP_ossl_md2 hc_EVP_ossl_md2
+#define EVP_ossl_md4 hc_EVP_ossl_md4
+#define EVP_ossl_md5 hc_EVP_ossl_md5
+#define EVP_ossl_sha1 hc_EVP_ossl_sha1
+#define EVP_ossl_sha256 hc_EVP_ossl_sha256
+#define EVP_ossl_sha384 hc_EVP_ossl_sha384
+#define EVP_ossl_sha512 hc_EVP_ossl_sha512
+#define EVP_ossl_des_cbc hc_EVP_ossl_des_cbc
+#define EVP_ossl_des_ede3_cbc hc_EVP_ossl_des_ede3_cbc
+#define EVP_ossl_aes_128_cbc hc_EVP_ossl_aes_128_cbc
+#define EVP_ossl_aes_192_cbc hc_EVP_ossl_aes_192_cbc
+#define EVP_ossl_aes_256_cbc hc_EVP_ossl_aes_256_cbc
+#define EVP_ossl_aes_128_cfb8 hc_EVP_ossl_aes_128_cfb8
+#define EVP_ossl_aes_192_cfb8 hc_EVP_ossl_aes_192_cfb8
+#define EVP_ossl_aes_256_cfb8 hc_EVP_ossl_aes_256_cfb8
+#define EVP_ossl_rc4 hc_EVP_ossl_rc4
+#define EVP_ossl_rc4_40 hc_EVP_ossl_rc4_40
+#define EVP_ossl_rc2_40_cbc hc_EVP_ossl_rc2_40_cbc
+#define EVP_ossl_rc2_64_cbc hc_EVP_ossl_rc2_64_cbc
+#define EVP_ossl_rc2_cbc hc_EVP_ossl_rc2_cbc
+#define EVP_ossl_camellia_128_cbc hc_EVP_ossl_camellia_128_cbc
+#define EVP_ossl_camellia_192_cbc hc_EVP_ossl_camellia_192_cbc
+#define EVP_ossl_camellia_256_cbc hc_EVP_ossl_camellia_256_cbc
+
+/*
+ *
+ */
+
+HC_CPP_BEGIN
+
+const hc_EVP_MD * hc_EVP_ossl_md2(void);
+const hc_EVP_MD * hc_EVP_ossl_md4(void);
+const hc_EVP_MD * hc_EVP_ossl_md5(void);
+const hc_EVP_MD * hc_EVP_ossl_sha1(void);
+const hc_EVP_MD * hc_EVP_ossl_sha256(void);
+const hc_EVP_MD * hc_EVP_ossl_sha384(void);
+const hc_EVP_MD * hc_EVP_ossl_sha512(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_rc2_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_rc2_40_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_rc2_64_cbc(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_rc4(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_rc4_40(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_des_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_des_ede3_cbc(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_128_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_192_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_256_cbc(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_128_cfb8(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_192_cfb8(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_aes_256_cfb8(void);
+
+const hc_EVP_CIPHER * hc_EVP_ossl_camellia_128_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_camellia_192_cbc(void);
+const hc_EVP_CIPHER * hc_EVP_ossl_camellia_256_cbc(void);
+
+HC_CPP_END
+
+#endif /* HEIM_EVP_OSSL_H */
/*
- * Copyright (c) 2015, Secure Endpoints Inc.
+ * Copyright (c) 2015-2016, Secure Endpoints Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/*
- * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#include <evp-cc.h>
#include <evp-w32.h>
#include <evp-pkcs11.h>
+#include <evp-openssl.h>
#include <krb5-types.h>
# define HCRYPTO_DEF_PROVIDER cc
# elif __sun
# define HCRYPTO_DEF_PROVIDER pkcs11_hcrypto
+# elif HAVE_HCRYPTO_W_OPENSSL
+# define HCRYPTO_DEF_PROVIDER ossl
# else
# define HCRYPTO_DEF_PROVIDER hcrypto
# endif
/*
- * Copyright (c) 2005 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 2005 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* cipher is used in (use EVP_CIPHER.._mode() to extract the
* mode). The rest of the flag field is a bitfield.
*/
-#define hc_EVP_CIPH_STREAM_CIPHER 1
+#define hc_EVP_CIPH_STREAM_CIPHER 0
#define hc_EVP_CIPH_CBC_MODE 2
#define hc_EVP_CIPH_CFB8_MODE 4
#define hc_EVP_CIPH_MODE 0x7
const unsigned char *, unsigned int);
int (*cleanup)(EVP_CIPHER_CTX *);
int ctx_size;
- void *set_asn1_parameters;
- void *get_asn1_parameters;
+ int (*set_asn1_parameters)(void);
+ int (*get_asn1_parameters)(void);
int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
#define EVP_CTRL_RAND_KEY 0x6
unsigned char final[EVP_MAX_BLOCK_LENGTH];
};
+/*
+ * LIES. It's not an EVP_MD_CTX that gets passed to these functions
+ * here in hcrypto, but an object of ctx_size.
+ */
typedef int (*hc_evp_md_init)(EVP_MD_CTX *);
typedef int (*hc_evp_md_update)(EVP_MD_CTX *,const void *, size_t);
typedef int (*hc_evp_md_final)(void *, EVP_MD_CTX *);
;! hc_EVP_cc_aes_192_cfb8
;! hc_EVP_cc_aes_256_cfb8
+ hc_EVP_ossl_md2
+ hc_EVP_ossl_md4
+ hc_EVP_ossl_md5
+ hc_EVP_ossl_sha1
+ hc_EVP_ossl_sha256
+ hc_EVP_ossl_sha384
+ hc_EVP_ossl_sha512
+ hc_EVP_ossl_des_ede3_cbc
+ hc_EVP_ossl_aes_128_cbc
+ hc_EVP_ossl_aes_192_cbc
+ hc_EVP_ossl_aes_256_cbc
+ hc_EVP_ossl_aes_128_cfb8
+ hc_EVP_ossl_aes_192_cfb8
+ hc_EVP_ossl_aes_256_cfb8
+ hc_EVP_ossl_rc2_cbc
+ hc_EVP_ossl_rc2_40_cbc
+ hc_EVP_ossl_rc4
+ hc_EVP_ossl_rc4_40
+
hc_EVP_pkcs11_md2
hc_EVP_pkcs11_md4
hc_EVP_pkcs11_md5
/*
- * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
char buf[1000];
ectx = EVP_MD_CTX_create();
+ if (hash->evp() == NULL) {
+ printf("unavailable\n");
+ continue;
+ }
EVP_DigestInit_ex(ectx, hash->evp(), NULL);
(*hash->init)(ctx);
#ifndef _HEIM_RAND_H
#define _HEIM_RAND_H 1
+#define RAND_METHOD hc_RAND_METHOD
+
typedef struct RAND_METHOD RAND_METHOD;
#include <hcrypto/engine.h>
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#include <evp-cc.h>
#include <evp-w32.h>
#include <evp-pkcs11.h>
+#include <evp-openssl.h>
#include <hex.h>
#include <err.h>
ret += test_cipher(i, EVP_pkcs11_rc4(), &rc4_tests[i]);
#endif /* PKCS11_MODULE_PATH */
+ /* OpenSSL */
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ for (i = 0; i < sizeof(aes_tests)/sizeof(aes_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_aes_256_cbc(), &aes_tests[i]);
+ for (i = 0; i < sizeof(aes_cfb_tests)/sizeof(aes_cfb_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_aes_128_cfb8(), &aes_cfb_tests[i]);
+ for (i = 0; i < sizeof(rc2_tests)/sizeof(rc2_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_rc2_cbc(), &rc2_tests[i]);
+ for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_rc2_40_cbc(), &rc2_40_tests[i]);
+ for (i = 0; i < sizeof(des_ede3_tests)/sizeof(des_ede3_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_des_ede3_cbc(), &des_ede3_tests[i]);
+ for (i = 0; i < sizeof(rc4_tests)/sizeof(rc4_tests[0]); i++)
+ ret += test_cipher(i, EVP_ossl_rc4(), &rc4_tests[i]);
+#endif /* PKCS11_MODULE_PATH */
+
return ret;
}
hc_EVP_hcrypto_rc4;
hc_EVP_hcrypto_rc4_40;
+ hc_EVP_ossl_md2;
+ hc_EVP_ossl_md4;
+ hc_EVP_ossl_md5;
+ hc_EVP_ossl_sha1;
+ hc_EVP_ossl_sha256;
+ hc_EVP_ossl_sha384;
+ hc_EVP_ossl_sha512;
+ hc_EVP_ossl_des_ede3_cbc;
+ hc_EVP_ossl_aes_128_cbc;
+ hc_EVP_ossl_aes_192_cbc;
+ hc_EVP_ossl_aes_256_cbc;
+ hc_EVP_ossl_aes_128_cfb8;
+ hc_EVP_ossl_aes_192_cfb8;
+ hc_EVP_ossl_aes_256_cfb8;
+ hc_EVP_ossl_rc2_cbc;
+ hc_EVP_ossl_rc2_40_cbc;
+ hc_EVP_ossl_rc4;
+ hc_EVP_ossl_rc4_40;
+
hc_EVP_pkcs11_md2;
hc_EVP_pkcs11_md4;
hc_EVP_pkcs11_md5;
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += -I../asn1 -I$(srcdir)/../asn1 $(INCLUDE_hcrypto)
+AM_CPPFLAGS += -I../asn1 -I$(srcdir)/../asn1
AM_CPPFLAGS += $(INCLUDE_openldap) -DHDB_DB_DIR=\"$(DIR_hdbdir)\"
AM_CPPFLAGS += -I$(srcdir)/../krb5
AM_CPPFLAGS += $(INCLUDE_sqlite3)
cms.c \
collector.c \
crypto.c \
+ crypto-ec.c \
doxygen.c \
error.c \
env.c \
libhx509_la_LIBADD = \
$(LIB_com_err) \
$(LIB_hcrypto) \
+ $(LIB_openssl_crypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(top_builddir)/lib/wind/libwind.la \
$(top_builddir)/lib/base/libheimbase.la \
endif
$(libhx509_la_OBJECTS): $(srcdir)/version-script.map $(nodist_include_HEADERS) $(priv_headers)
-libhx509_la_CPPFLAGS = $(INCLUDE_hcrypto)
nodist_libhx509_la_SOURCES = $(BUILT_SOURCES)
$(gen_files_ocsp) ocsp_asn1.hx ocsp_asn1-priv.hx: ocsp_asn1_files
$(hxtool_OBJECTS): hxtool-commands.h hx509_err.h
-hxtool_CPPFLAGS = $(INCLUDE_hcrypto)
hxtool_LDADD = \
libhx509.la \
$(top_builddir)/lib/asn1/libasn1.la \
LDADD = libhx509.la
test_soft_pkcs11_LDADD = libhx509.la
-test_soft_pkcs11_CPPFLAGS = $(INCLUDE_hcrypto)
-test_name_CPPFLAGS = $(INCLUDE_hcrypto)
test_name_LDADD = libhx509.la $(LIB_roken)
-test_expr_CPPFLAGS = $(INCLUDE_hcrypto)
test_expr_LDADD = libhx509.la $(LIB_roken)
TESTS = $(SCRIPT_TESTS) $(PROGRAM_TESTS)
########################################################################
#
-# Copyright (c) 2009, Secure Endpoints Inc.
+# Copyright (c) 2009-2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
$(OBJ)\cms.obj \
$(OBJ)\collector.obj \
$(OBJ)\crypto.obj \
+ $(OBJ)\crypto-ec.obj \
$(OBJ)\error.obj \
$(OBJ)\env.obj \
$(OBJ)\file.obj \
$(SRCDIR)\cms.c \
$(SRCDIR)\collector.c \
$(SRCDIR)\crypto.c \
+ $(SRCDIR)\crypto-ec.c \
$(SRCDIR)\doxygen.c \
$(SRCDIR)\error.c \
$(SRCDIR)\env.c \
cd $(SRCDIR)
$(BINDIR)\hxtool.exe: $(OBJ)\tool\hxtool.obj $(OBJ)\tool\hxtool-commands.obj $(LIBHEIMDAL) $(OBJ)\hxtool-version.res
- $(EXECONLINK) $(LIBHEIMDAL) $(LIBROKEN) $(LIBSL) $(LIBVERS) $(LIBCOMERR)
+ $(EXECONLINK) $(LIBHEIMDAL) $(LIBROKEN) $(LIBSL) $(LIBVERS) $(LIBCOMERR) $(LIB_openssl_crypto)
$(EXEPREP)
$(OBJ)\hx509-protos.h:
--- /dev/null
+/*
+ * Copyright (c) 2016 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#define HEIM_NO_CRYPTO_HDRS
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+#include "hx_locl.h"
+
+extern const AlgorithmIdentifier _hx509_signature_sha256_data;
+extern const AlgorithmIdentifier _hx509_signature_sha1_data;
+
+void
+_hx509_private_eckey_free(void *eckey)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ EC_KEY_free(eckey);
+#endif
+}
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static int
+heim_oid2ecnid(heim_oid *oid)
+{
+ /*
+ * Now map to openssl OID fun
+ */
+
+ if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
+ return NID_X9_62_prime256v1;
+ else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
+ return NID_secp160r1;
+ else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
+ return NID_secp160r2;
+
+ return NID_undef;
+}
+
+static int
+parse_ECParameters(hx509_context context,
+ heim_octet_string *parameters, int *nid)
+{
+ ECParameters ecparam;
+ size_t size;
+ int ret;
+
+ if (parameters == NULL) {
+ ret = HX509_PARSING_KEY_FAILED;
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters missing");
+ return ret;
+ }
+
+ ret = decode_ECParameters(parameters->data, parameters->length,
+ &ecparam, &size);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to decode EC parameters");
+ return ret;
+ }
+
+ if (ecparam.element != choice_ECParameters_namedCurve) {
+ free_ECParameters(&ecparam);
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters is not a named curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+
+ *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
+ free_ECParameters(&ecparam);
+ if (*nid == NID_undef) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to find matcing NID for EC curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+static int
+ecdsa_verify_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const Certificate *signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ const heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ const SubjectPublicKeyInfo *spi;
+ heim_octet_string digest;
+ int ret;
+ EC_KEY *key = NULL;
+ int groupnid;
+ EC_GROUP *group;
+ const unsigned char *p;
+ long len;
+
+ digest_alg = sig_alg->digest_alg;
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &digest);
+ if (ret)
+ return ret;
+
+ /* set up EC KEY */
+ spi = &signer->tbsCertificate.subjectPublicKeyInfo;
+
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+
+ /*
+ * Find the group id
+ */
+
+ ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
+ if (ret) {
+ der_free_octet_string(&digest);
+ return ret;
+ }
+
+ /*
+ * Create group, key, parse key
+ */
+
+ key = EC_KEY_new();
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ EC_KEY_set_group(key, group);
+ EC_GROUP_free(group);
+
+ p = spi->subjectPublicKey.data;
+ len = spi->subjectPublicKey.length / 8;
+
+ if (o2i_ECPublicKey(&key, &p, len) == NULL) {
+ EC_KEY_free(key);
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+
+ ret = ECDSA_verify(-1, digest.data, digest.length,
+ sig->data, sig->length, key);
+ der_free_octet_string(&digest);
+ EC_KEY_free(key);
+ if (ret != 1) {
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+ecdsa_create_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const hx509_private_key signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ AlgorithmIdentifier *signatureAlgorithm,
+ heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ heim_octet_string indata;
+ const heim_oid *sig_oid;
+ unsigned int siglen;
+ int ret;
+
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig_oid = sig_alg->sig_oid;
+ digest_alg = sig_alg->digest_alg;
+
+ if (signatureAlgorithm) {
+ ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
+ "\x05\x00", 2);
+ if (ret) {
+ hx509_clear_error_string(context);
+ return ret;
+ }
+ }
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &indata);
+ if (ret)
+ goto error;
+
+ sig->length = ECDSA_size(signer->private_key.ecdsa);
+ sig->data = malloc(sig->length);
+ if (sig->data == NULL) {
+ der_free_octet_string(&indata);
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto error;
+ }
+
+ siglen = sig->length;
+
+ ret = ECDSA_sign(-1, indata.data, indata.length,
+ sig->data, &siglen, signer->private_key.ecdsa);
+ der_free_octet_string(&indata);
+ if (ret != 1) {
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ hx509_set_error_string(context, 0, ret,
+ "ECDSA sign failed: %d", ret);
+ goto error;
+ }
+ if (siglen > sig->length)
+ _hx509_abort("ECDSA signature prelen longer the output len");
+
+ sig->length = siglen;
+
+ return 0;
+ error:
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ return ret;
+}
+
+static int
+ecdsa_available(const hx509_private_key signer,
+ const AlgorithmIdentifier *sig_alg)
+{
+ const struct signature_alg *sig;
+ const EC_GROUP *group;
+ BN_CTX *bnctx = NULL;
+ BIGNUM *order = NULL;
+ int ret = 0;
+
+ if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig = _hx509_find_sig_alg(&sig_alg->algorithm);
+
+ if (sig == NULL || sig->digest_size == 0)
+ return 0;
+
+ group = EC_KEY_get0_group(signer->private_key.ecdsa);
+ if (group == NULL)
+ return 0;
+
+ bnctx = BN_CTX_new();
+ order = BN_new();
+ if (order == NULL)
+ goto err;
+
+ if (EC_GROUP_get_order(group, order, bnctx) != 1)
+ goto err;
+
+ if (BN_num_bytes(order) > sig->digest_size)
+ ret = 1;
+ err:
+ if (bnctx)
+ BN_CTX_free(bnctx);
+ if (order)
+ BN_clear_free(order);
+
+ return ret;
+}
+
+static int
+ecdsa_private_key2SPKI(hx509_context context,
+ hx509_private_key private_key,
+ SubjectPublicKeyInfo *spki)
+{
+ memset(spki, 0, sizeof(*spki));
+ return ENOMEM;
+}
+
+static int
+ecdsa_private_key_export(hx509_context context,
+ const hx509_private_key key,
+ hx509_key_format_t format,
+ heim_octet_string *data)
+{
+ return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
+}
+
+static int
+ecdsa_private_key_import(hx509_context context,
+ const AlgorithmIdentifier *keyai,
+ const void *data,
+ size_t len,
+ hx509_key_format_t format,
+ hx509_private_key private_key)
+{
+ const unsigned char *p = data;
+ EC_KEY **pkey = NULL;
+ EC_KEY *key;
+
+ if (keyai->parameters) {
+ EC_GROUP *group;
+ int groupnid;
+ int ret;
+
+ ret = parse_ECParameters(context, keyai->parameters, &groupnid);
+ if (ret)
+ return ret;
+
+ key = EC_KEY_new();
+ if (key == NULL)
+ return ENOMEM;
+
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ if (group == NULL) {
+ EC_KEY_free(key);
+ return ENOMEM;
+ }
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_set_group(key, group) == 0) {
+ EC_KEY_free(key);
+ EC_GROUP_free(group);
+ return ENOMEM;
+ }
+ EC_GROUP_free(group);
+ pkey = &key;
+ }
+
+ switch (format) {
+ case HX509_KEY_FORMAT_DER:
+
+ private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
+ if (private_key->private_key.ecdsa == NULL) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse EC private key");
+ return HX509_PARSING_KEY_FAILED;
+ }
+ private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
+ break;
+
+ default:
+ return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
+ }
+
+ return 0;
+}
+
+static int
+ecdsa_generate_private_key(hx509_context context,
+ struct hx509_generate_private_context *ctx,
+ hx509_private_key private_key)
+{
+ return ENOMEM;
+}
+
+static BIGNUM *
+ecdsa_get_internal(hx509_context context,
+ hx509_private_key key,
+ const char *type)
+{
+ return NULL;
+}
+
+static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
+const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
+ { 6, rk_UNCONST(ecPublicKey) }, NULL
+};
+
+static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
+ { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
+};
+
+static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
+ { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
+};
+
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha1(void)
+{ return &_hx509_signature_ecdsa_with_sha1_data; }
+
+
+hx509_private_key_ops ecdsa_private_key_ops = {
+ "EC PRIVATE KEY",
+ ASN1_OID_ID_ECPUBLICKEY,
+ ecdsa_available,
+ ecdsa_private_key2SPKI,
+ ecdsa_private_key_export,
+ ecdsa_private_key_import,
+ ecdsa_generate_private_key,
+ ecdsa_get_internal
+};
+
+const struct signature_alg ecdsa_with_sha256_alg = {
+ "ecdsa-with-sha256",
+ ASN1_OID_ID_ECDSA_WITH_SHA256,
+ &_hx509_signature_ecdsa_with_sha256_data,
+ ASN1_OID_ID_ECPUBLICKEY,
+ &_hx509_signature_sha256_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
+ SIG_PUBLIC_SIG|SELF_SIGNED_OK,
+ 0,
+ NULL,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 32
+};
+
+const struct signature_alg ecdsa_with_sha1_alg = {
+ "ecdsa-with-sha1",
+ ASN1_OID_ID_ECDSA_WITH_SHA1,
+ &_hx509_signature_ecdsa_with_sha1_data,
+ ASN1_OID_ID_ECPUBLICKEY,
+ &_hx509_signature_sha1_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
+ SIG_PUBLIC_SIG|SELF_SIGNED_OK,
+ 0,
+ NULL,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 20
+};
+
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+const AlgorithmIdentifier *
+hx509_signature_ecPublicKey(void)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return &_hx509_signature_ecPublicKey;
+#else
+ return NULL;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha256(void)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return &_hx509_signature_ecdsa_with_sha256_data;
+#else
+ return NULL;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
/*
- * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#include "hx_locl.h"
-struct hx509_crypto;
-
-struct signature_alg;
-
-struct hx509_generate_private_context {
- const heim_oid *key_oid;
- int isCA;
- unsigned long num_bits;
-};
-
-struct hx509_private_key_ops {
- const char *pemtype;
- const heim_oid *key_oid;
- int (*available)(const hx509_private_key,
- const AlgorithmIdentifier *);
- int (*get_spki)(hx509_context,
- const hx509_private_key,
- SubjectPublicKeyInfo *);
- int (*export)(hx509_context context,
- const hx509_private_key,
- hx509_key_format_t,
- heim_octet_string *);
- int (*import)(hx509_context, const AlgorithmIdentifier *,
- const void *, size_t, hx509_key_format_t,
- hx509_private_key);
- int (*generate_private_key)(hx509_context,
- struct hx509_generate_private_context *,
- hx509_private_key);
- BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
-};
-
-struct hx509_private_key {
- unsigned int ref;
- const struct signature_alg *md;
- const heim_oid *signature_alg;
- union {
- RSA *rsa;
- void *keydata;
-#ifdef HAVE_OPENSSL
- EC_KEY *ecdsa;
-#endif
- } private_key;
- hx509_private_key_ops *ops;
-};
-
-/*
- *
- */
-
-struct signature_alg {
- const char *name;
- const heim_oid *sig_oid;
- const AlgorithmIdentifier *sig_alg;
- const heim_oid *key_oid;
- const AlgorithmIdentifier *digest_alg;
- int flags;
-#define PROVIDE_CONF 0x1
-#define REQUIRE_SIGNER 0x2
-#define SELF_SIGNED_OK 0x4
-#define WEAK_SIG_ALG 0x8
-
-#define SIG_DIGEST 0x100
-#define SIG_PUBLIC_SIG 0x200
-#define SIG_SECRET 0x400
-
-#define RA_RSA_USES_DIGEST_INFO 0x1000000
-
- time_t best_before; /* refuse signature made after best before date */
- const EVP_MD *(*evp_md)(void);
- int (*verify_signature)(hx509_context context,
- const struct signature_alg *,
- const Certificate *,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- const heim_octet_string *);
- int (*create_signature)(hx509_context,
- const struct signature_alg *,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- AlgorithmIdentifier *,
- heim_octet_string *);
- int digest_size;
-};
-
-static const struct signature_alg *
-find_sig_alg(const heim_oid *oid);
-
/*-
* RFC5758 specifies no parameters for ecdsa-with-SHA<N> signatures
* RFC5754 specifies NULL parameters for sha<N>WithRSAEncryption signatures
{ 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
};
-static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
-const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
- { 6, rk_UNCONST(ecPublicKey) }, NULL
-};
-
-static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
-const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
- { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
-};
-
-static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
-const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
- { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
-};
-
static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
{ 7, rk_UNCONST(rsa_with_sha512_oid) }, rk_UNCONST(&null_entry_oid)
*
*/
-static int
-set_digest_alg(DigestAlgorithmIdentifier *id,
- const heim_oid *oid,
- const void *param, size_t length)
+int
+_hx509_set_digest_alg(DigestAlgorithmIdentifier *id,
+ const heim_oid *oid,
+ const void *param, size_t length)
{
int ret;
if (param) {
return 0;
}
-#ifdef HAVE_OPENSSL
-
-static int
-heim_oid2ecnid(heim_oid *oid)
-{
- /*
- * Now map to openssl OID fun
- */
-
- if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
- return NID_X9_62_prime256v1;
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
- return NID_secp160r1;
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
- return NID_secp160r2;
-
- return -1;
-}
-
-static int
-parse_ECParameters(hx509_context context,
- heim_octet_string *parameters, int *nid)
-{
- ECParameters ecparam;
- size_t size;
- int ret;
-
- if (parameters == NULL) {
- ret = HX509_PARSING_KEY_FAILED;
- hx509_set_error_string(context, 0, ret,
- "EC parameters missing");
- return ret;
- }
-
- ret = decode_ECParameters(parameters->data, parameters->length,
- &ecparam, &size);
- if (ret) {
- hx509_set_error_string(context, 0, ret,
- "Failed to decode EC parameters");
- return ret;
- }
-
- if (ecparam.element != choice_ECParameters_namedCurve) {
- free_ECParameters(&ecparam);
- hx509_set_error_string(context, 0, ret,
- "EC parameters is not a named curve");
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
- }
-
- *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
- free_ECParameters(&ecparam);
- if (*nid == -1) {
- hx509_set_error_string(context, 0, ret,
- "Failed to find matcing NID for EC curve");
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
- }
- return 0;
-}
-
-
-/*
- *
- */
-
-static int
-ecdsa_verify_signature(hx509_context context,
- const struct signature_alg *sig_alg,
- const Certificate *signer,
- const AlgorithmIdentifier *alg,
- const heim_octet_string *data,
- const heim_octet_string *sig)
-{
- const AlgorithmIdentifier *digest_alg;
- const SubjectPublicKeyInfo *spi;
- heim_octet_string digest;
- int ret;
- EC_KEY *key = NULL;
- int groupnid;
- EC_GROUP *group;
- const unsigned char *p;
- long len;
-
- digest_alg = sig_alg->digest_alg;
-
- ret = _hx509_create_signature(context,
- NULL,
- digest_alg,
- data,
- NULL,
- &digest);
- if (ret)
- return ret;
-
- /* set up EC KEY */
- spi = &signer->tbsCertificate.subjectPublicKeyInfo;
-
- if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
-
-#ifdef HAVE_OPENSSL
- /*
- * Find the group id
- */
-
- ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
- if (ret) {
- der_free_octet_string(&digest);
- return ret;
- }
-
- /*
- * Create group, key, parse key
- */
-
- key = EC_KEY_new();
- group = EC_GROUP_new_by_curve_name(groupnid);
- EC_KEY_set_group(key, group);
- EC_GROUP_free(group);
-
- p = spi->subjectPublicKey.data;
- len = spi->subjectPublicKey.length / 8;
-
- if (o2i_ECPublicKey(&key, &p, len) == NULL) {
- EC_KEY_free(key);
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
- }
-#else
- key = SubjectPublicKeyInfo2EC_KEY(spi);
-#endif
-
- ret = ECDSA_verify(-1, digest.data, digest.length,
- sig->data, sig->length, key);
- der_free_octet_string(&digest);
- EC_KEY_free(key);
- if (ret != 1) {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- return ret;
- }
-
- return 0;
-}
-
-static int
-ecdsa_create_signature(hx509_context context,
- const struct signature_alg *sig_alg,
- const hx509_private_key signer,
- const AlgorithmIdentifier *alg,
- const heim_octet_string *data,
- AlgorithmIdentifier *signatureAlgorithm,
- heim_octet_string *sig)
-{
- const AlgorithmIdentifier *digest_alg;
- heim_octet_string indata;
- const heim_oid *sig_oid;
- unsigned int siglen;
- int ret;
-
- if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
- _hx509_abort("internal error passing private key to wrong ops");
-
- sig_oid = sig_alg->sig_oid;
- digest_alg = sig_alg->digest_alg;
-
- if (signatureAlgorithm) {
- ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
- if (ret) {
- hx509_clear_error_string(context);
- return ret;
- }
- }
-
- ret = _hx509_create_signature(context,
- NULL,
- digest_alg,
- data,
- NULL,
- &indata);
- if (ret)
- goto error;
-
- sig->length = ECDSA_size(signer->private_key.ecdsa);
- sig->data = malloc(sig->length);
- if (sig->data == NULL) {
- der_free_octet_string(&indata);
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto error;
- }
-
- siglen = sig->length;
-
- ret = ECDSA_sign(-1, indata.data, indata.length,
- sig->data, &siglen, signer->private_key.ecdsa);
- der_free_octet_string(&indata);
- if (ret != 1) {
- ret = HX509_CMS_FAILED_CREATE_SIGATURE;
- hx509_set_error_string(context, 0, ret,
- "ECDSA sign failed: %d", ret);
- goto error;
- }
- if (siglen > sig->length)
- _hx509_abort("ECDSA signature prelen longer the output len");
-
- sig->length = siglen;
-
- return 0;
- error:
- if (signatureAlgorithm)
- free_AlgorithmIdentifier(signatureAlgorithm);
- return ret;
-}
-
-static int
-ecdsa_available(const hx509_private_key signer,
- const AlgorithmIdentifier *sig_alg)
-{
- const struct signature_alg *sig;
- const EC_GROUP *group;
- BN_CTX *bnctx = NULL;
- BIGNUM *order = NULL;
- int ret = 0;
-
- if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
- _hx509_abort("internal error passing private key to wrong ops");
-
- sig = find_sig_alg(&sig_alg->algorithm);
-
- if (sig == NULL || sig->digest_size == 0)
- return 0;
-
- group = EC_KEY_get0_group(signer->private_key.ecdsa);
- if (group == NULL)
- return 0;
-
- bnctx = BN_CTX_new();
- order = BN_new();
- if (order == NULL)
- goto err;
-
- if (EC_GROUP_get_order(group, order, bnctx) != 1)
- goto err;
-
- if (BN_num_bytes(order) > sig->digest_size)
- ret = 1;
- err:
- if (bnctx)
- BN_CTX_free(bnctx);
- if (order)
- BN_clear_free(order);
-
- return ret;
-}
-
-
-#endif /* HAVE_OPENSSL */
-
/*
*
*/
return HX509_ALG_NOT_SUPP;
if (signatureAlgorithm) {
- ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
+ ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
+ "\x05\x00", 2);
if (ret) {
hx509_clear_error_string(context);
return ret;
}
spki->subjectPublicKey.length = len * 8;
- ret = set_digest_alg(&spki->algorithm, ASN1_OID_ID_PKCS1_RSAENCRYPTION,
- "\x05\x00", 2);
+ ret = _hx509_set_digest_alg(&spki->algorithm,
+ ASN1_OID_ID_PKCS1_RSAENCRYPTION,
+ "\x05\x00", 2);
if (ret) {
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
free(spki->subjectPublicKey.data);
rsa_get_internal
};
-#ifdef HAVE_OPENSSL
-
-static int
-ecdsa_private_key2SPKI(hx509_context context,
- hx509_private_key private_key,
- SubjectPublicKeyInfo *spki)
-{
- memset(spki, 0, sizeof(*spki));
- return ENOMEM;
-}
-
-static int
-ecdsa_private_key_export(hx509_context context,
- const hx509_private_key key,
- hx509_key_format_t format,
- heim_octet_string *data)
-{
- return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
-}
-
-static int
-ecdsa_private_key_import(hx509_context context,
- const AlgorithmIdentifier *keyai,
- const void *data,
- size_t len,
- hx509_key_format_t format,
- hx509_private_key private_key)
-{
- const unsigned char *p = data;
- EC_KEY **pkey = NULL;
- EC_KEY *key;
-
- if (keyai->parameters) {
- EC_GROUP *group;
- int groupnid;
- int ret;
-
- ret = parse_ECParameters(context, keyai->parameters, &groupnid);
- if (ret)
- return ret;
-
- key = EC_KEY_new();
- if (key == NULL)
- return ENOMEM;
-
- group = EC_GROUP_new_by_curve_name(groupnid);
- if (group == NULL) {
- EC_KEY_free(key);
- return ENOMEM;
- }
- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
- if (EC_KEY_set_group(key, group) == 0) {
- EC_KEY_free(key);
- EC_GROUP_free(group);
- return ENOMEM;
- }
- EC_GROUP_free(group);
- pkey = &key;
- }
-
- switch (format) {
- case HX509_KEY_FORMAT_DER:
-
- private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
- if (private_key->private_key.ecdsa == NULL) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Failed to parse EC private key");
- return HX509_PARSING_KEY_FAILED;
- }
- private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
- break;
-
- default:
- return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
- }
-
- return 0;
-}
-
-static int
-ecdsa_generate_private_key(hx509_context context,
- struct hx509_generate_private_context *ctx,
- hx509_private_key private_key)
-{
- return ENOMEM;
-}
-
-static BIGNUM *
-ecdsa_get_internal(hx509_context context,
- hx509_private_key key,
- const char *type)
-{
- return NULL;
-}
-
-
-static hx509_private_key_ops ecdsa_private_key_ops = {
- "EC PRIVATE KEY",
- ASN1_OID_ID_ECPUBLICKEY,
- ecdsa_available,
- ecdsa_private_key2SPKI,
- ecdsa_private_key_export,
- ecdsa_private_key_import,
- ecdsa_generate_private_key,
- ecdsa_get_internal
-};
-
-#endif /* HAVE_OPENSSL */
-
/*
*
*/
if (signatureAlgorithm) {
int ret;
- ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
- "\x05\x00", 2);
+ ret = _hx509_set_digest_alg(signatureAlgorithm,
+ sig_alg->sig_oid, "\x05\x00", 2);
if (ret)
return ret;
}
return 0;
}
-#ifdef HAVE_OPENSSL
-
-static const struct signature_alg ecdsa_with_sha256_alg = {
- "ecdsa-with-sha256",
- ASN1_OID_ID_ECDSA_WITH_SHA256,
- &_hx509_signature_ecdsa_with_sha256_data,
- ASN1_OID_ID_ECPUBLICKEY,
- &_hx509_signature_sha256_data,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
- 0,
- NULL,
- ecdsa_verify_signature,
- ecdsa_create_signature,
- 32
-};
-
-static const struct signature_alg ecdsa_with_sha1_alg = {
- "ecdsa-with-sha1",
- ASN1_OID_ID_ECDSA_WITH_SHA1,
- &_hx509_signature_ecdsa_with_sha1_data,
- ASN1_OID_ID_ECPUBLICKEY,
- &_hx509_signature_sha1_data,
- PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
- 0,
- NULL,
- ecdsa_verify_signature,
- ecdsa_create_signature,
- 20
-};
-
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+extern const struct signature_alg ecdsa_with_sha256_alg;
+extern const struct signature_alg ecdsa_with_sha1_alg;
#endif
static const struct signature_alg heim_rsa_pkcs1_x509 = {
*/
static const struct signature_alg *sig_algs[] = {
-#ifdef HAVE_OPENSSL
+#ifdef HAVE_HCRYPTO_W_OPENSSL
&ecdsa_with_sha256_alg,
&ecdsa_with_sha1_alg,
#endif
NULL
};
-static const struct signature_alg *
-find_sig_alg(const heim_oid *oid)
+const struct signature_alg *
+_hx509_find_sig_alg(const heim_oid *oid)
{
unsigned int i;
for (i = 0; sig_algs[i]; i++)
/*
*
*/
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+extern hx509_private_key_ops ecdsa_private_key_ops;
+#endif
static struct hx509_private_key_ops *private_algs[] = {
&rsa_private_key_ops,
-#ifdef HAVE_OPENSSL
+#ifdef HAVE_HCRYPTO_W_OPENSSL
&ecdsa_private_key_ops,
#endif
NULL
{
const struct signature_alg *md;
- md = find_sig_alg(&alg->algorithm);
+ md = _hx509_find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
{
const struct signature_alg *md;
- md = find_sig_alg(&alg->algorithm);
+ md = _hx509_find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
if (cert)
signer = _hx509_get_cert(cert);
- md = find_sig_alg(&alg->algorithm);
+ md = _hx509_find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
{
const struct signature_alg *md;
- md = find_sig_alg(&alg->algorithm);
+ md = _hx509_find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
"algorithm no supported");
hx509_signature_md5(void)
{ return &_hx509_signature_md5_data; }
-const AlgorithmIdentifier *
-hx509_signature_ecPublicKey(void)
-{ return &_hx509_signature_ecPublicKey; }
-
-const AlgorithmIdentifier *
-hx509_signature_ecdsa_with_sha256(void)
-{ return &_hx509_signature_ecdsa_with_sha256_data; }
-
-const AlgorithmIdentifier *
-hx509_signature_ecdsa_with_sha1(void)
-{ return &_hx509_signature_ecdsa_with_sha1_data; }
-
const AlgorithmIdentifier *
hx509_signature_rsa_with_sha512(void)
{ return &_hx509_signature_rsa_with_sha512_data; }
if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
if ((*key)->private_key.rsa)
RSA_free((*key)->private_key.rsa);
-#ifdef HAVE_OPENSSL
- } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) {
- if ((*key)->private_key.ecdsa)
- EC_KEY_free((*key)->private_key.ecdsa);
-#endif
+ } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid,
+ ASN1_OID_ID_ECPUBLICKEY) == 0 &&
+ (*key)->private_key.ecdsa != NULL) {
+ _hx509_private_eckey_free((*key)->private_key.ecdsa);
}
(*key)->private_key.rsa = NULL;
free(*key);
{
if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {
*c = EVP_rc2_40_cbc();
+ if (*c == NULL)
+ return NULL;
*md = EVP_sha1();
+ if (*md == NULL)
+ return NULL;
*s2k = PBE_string2key;
return &asn1_oid_private_rc2_40;
} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {
*c = EVP_rc2_cbc();
+ if (*c == NULL)
+ return NULL;
*md = EVP_sha1();
+ if (*md == NULL)
+ return NULL;
*s2k = PBE_string2key;
return ASN1_OID_ID_PKCS3_RC2_CBC;
#if 0
} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {
*c = EVP_rc4_40();
+ if (*c == NULL)
+ return NULL;
*md = EVP_sha1();
+ if (*md == NULL)
+ return NULL;
*s2k = PBE_string2key;
return NULL;
} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {
*c = EVP_rc4();
+ if (*c == NULL)
+ return NULL;
*md = EVP_sha1();
+ if (*md == NULL)
+ return NULL;
*s2k = PBE_string2key;
return ASN1_OID_ID_PKCS3_RC4;
#endif
} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {
*c = EVP_des_ede3_cbc();
+ if (*c == NULL)
+ return NULL;
*md = EVP_sha1();
+ if (*md == NULL)
+ return NULL;
*s2k = PBE_string2key;
return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;
}
if (key == NULL)
return NULL;
- md = find_sig_alg(key->signature_alg);
+ md = _hx509_find_sig_alg(key->signature_alg);
if (md == NULL)
return NULL;
return md->key_oid;
/*
- * Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#include <der.h>
+/*
+ * We use OpenSSL for EC, but to do this we need to disable cross-references
+ * between OpenSSL and hcrypto bn.h and such. Source files that use OpenSSL EC
+ * must define HEIM_NO_CRYPTO_HDRS before including this file.
+ */
+
#define HC_DEPRECATED_CRYPTO
+#ifndef HEIM_NO_CRYPTO_HDRS
#include "crypto-headers.h"
+#endif
struct hx509_keyset_ops;
struct hx509_collector;
extern const AlgorithmIdentifier * _hx509_crypto_default_digest_alg;
extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;
+/*
+ * Private bits from crypto.c, so crypto-ec.c can also see them.
+ *
+ * This is part of the use-OpenSSL-for-EC hack.
+ */
+
+struct hx509_crypto;
+
+struct signature_alg;
+
+struct hx509_generate_private_context {
+ const heim_oid *key_oid;
+ int isCA;
+ unsigned long num_bits;
+};
+
+struct hx509_private_key_ops {
+ const char *pemtype;
+ const heim_oid *key_oid;
+ int (*available)(const hx509_private_key,
+ const AlgorithmIdentifier *);
+ int (*get_spki)(hx509_context,
+ const hx509_private_key,
+ SubjectPublicKeyInfo *);
+ int (*export)(hx509_context context,
+ const hx509_private_key,
+ hx509_key_format_t,
+ heim_octet_string *);
+ int (*import)(hx509_context, const AlgorithmIdentifier *,
+ const void *, size_t, hx509_key_format_t,
+ hx509_private_key);
+ int (*generate_private_key)(hx509_context,
+ struct hx509_generate_private_context *,
+ hx509_private_key);
+ BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
+};
+
+struct hx509_private_key {
+ unsigned int ref;
+ const struct signature_alg *md;
+ const heim_oid *signature_alg;
+ union {
+ RSA *rsa;
+ void *keydata;
+ void *ecdsa; /* EC_KEY */
+ } private_key;
+ hx509_private_key_ops *ops;
+};
+
+/*
+ *
+ */
+
+struct signature_alg {
+ const char *name;
+ const heim_oid *sig_oid;
+ const AlgorithmIdentifier *sig_alg;
+ const heim_oid *key_oid;
+ const AlgorithmIdentifier *digest_alg;
+ int flags;
+#define PROVIDE_CONF 0x1
+#define REQUIRE_SIGNER 0x2
+#define SELF_SIGNED_OK 0x4
+#define WEAK_SIG_ALG 0x8
+
+#define SIG_DIGEST 0x100
+#define SIG_PUBLIC_SIG 0x200
+#define SIG_SECRET 0x400
+
+#define RA_RSA_USES_DIGEST_INFO 0x1000000
+
+ time_t best_before; /* refuse signature made after best before date */
+ const EVP_MD *(*evp_md)(void);
+ int (*verify_signature)(hx509_context context,
+ const struct signature_alg *,
+ const Certificate *,
+ const AlgorithmIdentifier *,
+ const heim_octet_string *,
+ const heim_octet_string *);
+ int (*create_signature)(hx509_context,
+ const struct signature_alg *,
+ const hx509_private_key,
+ const AlgorithmIdentifier *,
+ const heim_octet_string *,
+ AlgorithmIdentifier *,
+ heim_octet_string *);
+ int digest_size;
+};
+
/*
* Configurable options
*/
/*
- * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
if (m != NULL)
printf("dh: %s\n", m->name);
}
-#ifdef HAVE_OPENSSL
+#ifdef HAVE_HCRYPTO_W_OPENSSL
{
printf("ecdsa: ECDSA_METHOD-not-export\n");
}
{ "CERTIFICATE", parse_certificate, NULL },
{ "PRIVATE KEY", parse_pkcs8_private_key, NULL },
{ "RSA PRIVATE KEY", parse_pem_private_key, hx509_signature_rsa },
+#ifdef HAVE_HCRYPTO_W_OPENSSL
{ "EC PRIVATE KEY", parse_pem_private_key, hx509_signature_ecPublicKey }
+#endif
};
if KRB5
DEPLIB_krb5 = ../krb5/libkrb5.la $(LIB_hcrypto)
-krb5_am_workaround = $(INCLUDE_hcrypto) -I$(top_srcdir)/lib/krb5
+krb5_am_workaround = -I$(top_srcdir)/lib/krb5
else
DEPLIB_krb5 =
krb5_am_workaround =
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto) -I../com_err -I$(srcdir)/../com_err $(INCLUDE_sqlite3) $(INCLUDE_libintl)
+AM_CPPFLAGS += -I../com_err -I$(srcdir)/../com_err $(INCLUDE_sqlite3) $(INCLUDE_libintl)
bin_PROGRAMS = verify_krb5_conf
$(top_builddir)/lib/wind/libwind.la \
$(top_builddir)/lib/base/libheimbase.la \
$(LIB_pkinit) \
+ $(LIB_openssl_crypto) \
$(use_sqlite) \
$(LIB_com_err) \
$(LIB_hcrypto) \
padata.c \
pcache.c \
pkinit.c \
+ pkinit-ec.c \
principal.c \
prog_setup.c \
prompter_posix.c \
########################################################################
#
-# Copyright (c) 2009 - 2013, Secure Endpoints Inc.
+# Copyright (c) 2009 - 2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
$(OBJ)\padata.obj \
$(OBJ)\pcache.obj \
$(OBJ)\pkinit.obj \
+ $(OBJ)\pkinit-ec.obj \
$(OBJ)\plugin.obj \
$(OBJ)\principal.obj \
$(OBJ)\prog_setup.obj \
pac.c \
padata.c \
pkinit.c \
+ pkinit-ec.c \
plugin.c \
principal.c \
prog_setup.c \
# libkrb5
$(LIBKRB5): $(libkrb5_OBJS) $(libkrb5_gen_OBJS)
- $(LIBCON_C) -OUT:$@ $(LIBHEIMBASE) @<<
+ $(LIBCON_C) -OUT:$@ $(LIBHEIMBASE) $(LIB_openssl_crypto) @<<
$(libkrb5_OBJS: =
)
$(libkrb5_gen_OBJS: =
/*
- * Copyright (c) 2003 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#include <err.h>
#include <assert.h>
-#ifdef HAVE_OPENSSL
-#include <openssl/evp.h>
-#endif
-
static int verbose = 0;
static void
/*
- * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
extern struct _krb5_encryption_type *_krb5_etypes[];
extern int _krb5_num_etypes;
+/* NO_HCRYPTO_POLLUTION is defined in pkinit-ec.c. See commentary there. */
+#ifndef NO_HCRYPTO_POLLUTION
/* Interface to the EVP crypto layer provided by hcrypto */
struct _krb5_evp_schedule {
+ /*
+ * Normally we'd say EVP_CIPHER_CTX here, but! this header gets
+ * included in lib/krb5/pkinit-ec.ck
+ */
EVP_CIPHER_CTX ectx;
EVP_CIPHER_CTX dctx;
};
+#endif
/*
- * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <wind.h>
+/*
+ * We use OpenSSL for EC, but to do this we need to disable cross-references
+ * between OpenSSL and hcrypto bn.h and such. Source files that use OpenSSL EC
+ * must define HEIM_NO_CRYPTO_HDRS before including this file.
+ */
#define HC_DEPRECATED_CRYPTO
+#ifndef HEIM_NO_CRYPTO_HDRS
#include "crypto-headers.h"
+#endif
#include <krb5_asn1.h>
+#include <pkinit_asn1.h>
struct send_to_kdc;
PKINIT_27 = 2
};
+struct krb5_pk_init_ctx_data {
+ struct krb5_pk_identity *id;
+ enum { USE_RSA, USE_DH, USE_ECDH } keyex;
+ union {
+ DH *dh;
+ void *eckey;
+ } u;
+ krb5_data *clientDHNonce;
+ struct krb5_dh_moduli **m;
+ hx509_peer_info peer;
+ enum krb5_pk_type type;
+ unsigned int require_binding:1;
+ unsigned int require_eku:1;
+ unsigned int require_krbtgt_otherName:1;
+ unsigned int require_hostname_match:1;
+ unsigned int trustedCertifiers:1;
+ unsigned int anonymous:1;
+};
+
#endif /* PKINIT */
#define ISTILDE(x) (x == '~')
--- /dev/null
+/*
+ * Copyright (c) 2016 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#ifdef PKINIT
+
+/*
+ * As with the other *-ec.c files in Heimdal, this is a bit of a hack.
+ *
+ * The idea is to use OpenSSL for EC because hcrypto doesn't have the
+ * required functionality at this time. To do this we segregate
+ * EC-using code into separate source files and then we arrange for them
+ * to get the OpenSSL headers and not the conflicting hcrypto ones.
+ *
+ * Because of auto-generated *-private.h headers, we end up needing to
+ * make sure various types are defined before we include them, thus the
+ * strange header include order here.
+ */
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#define HEIM_NO_CRYPTO_HDRS
+#endif
+
+#include <config.h>
+
+/*
+ * NO_HCRYPTO_POLLUTION -> don't refer to hcrypto type/function names
+ * that we don't need in this file and which would clash with OpenSSL's
+ * in ways that are difficult to address in cleaner ways.
+ *
+ * In the medium- to long-term what we should do is move all PK in
+ * Heimdal to the newer EVP interfaces for PK and then nothing outside
+ * lib/hcrypto should ever have to include OpenSSL headers, and -more
+ * specifically- the only thing that should ever have to include OpenSSL
+ * headers is the OpenSSL backend to hcrypto.
+ */
+#define NO_HCRYPTO_POLLUTION
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <hcrypto/des.h>
+#include "krb5_locl.h"
+
+#include <cms_asn1.h>
+#include <pkcs8_asn1.h>
+#include <pkcs9_asn1.h>
+#include <pkcs12_asn1.h>
+#include <pkinit_asn1.h>
+#include <asn1_err.h>
+
+#include <der.h>
+
+krb5_error_code
+_krb5_build_authpack_subjectPK_EC(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ AuthPack *a)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ krb5_error_code ret;
+ ECParameters ecp;
+ unsigned char *p;
+ size_t size;
+ int xlen;
+
+ /* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */
+
+ ecp.element = choice_ECParameters_namedCurve;
+ ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1,
+ &ecp.u.namedCurve);
+ if (ret)
+ return ret;
+
+ ALLOC(a->clientPublicValue->algorithm.parameters, 1);
+ if (a->clientPublicValue->algorithm.parameters == NULL) {
+ free_ECParameters(&ecp);
+ return krb5_enomem(context);
+ }
+ ASN1_MALLOC_ENCODE(ECParameters, p, xlen, &ecp, &size, ret);
+ free_ECParameters(&ecp);
+ if (ret)
+ return ret;
+ if ((int)size != xlen)
+ krb5_abortx(context, "asn1 internal error");
+
+ a->clientPublicValue->algorithm.parameters->data = p;
+ a->clientPublicValue->algorithm.parameters->length = size;
+
+ /* copy in public key */
+
+ ret = der_copy_oid(&asn1_oid_id_ecPublicKey,
+ &a->clientPublicValue->algorithm.algorithm);
+ if (ret)
+ return ret;
+
+ ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ if (ctx->u.eckey == NULL)
+ return krb5_enomem(context);
+
+ ret = EC_KEY_generate_key(ctx->u.eckey);
+ if (ret != 1)
+ return EINVAL;
+
+ xlen = i2o_ECPublicKey(ctx->u.eckey, NULL);
+ if (xlen <= 0)
+ return EINVAL;
+
+ p = malloc(xlen);
+ if (p == NULL)
+ return krb5_enomem(context);
+
+ a->clientPublicValue->subjectPublicKey.data = p;
+
+ xlen = i2o_ECPublicKey(ctx->u.eckey, &p);
+ if (xlen <= 0) {
+ a->clientPublicValue->subjectPublicKey.data = NULL;
+ free(p);
+ return EINVAL;
+ }
+
+ a->clientPublicValue->subjectPublicKey.length = xlen * 8;
+
+ return 0;
+
+ /* XXX verify that this is right with RFC3279 */
+#else
+ krb5_set_error_message(context, ENOTSUP,
+ N_("PKINIT: ECDH not supported", ""));
+ return ENOTSUP;
+#endif
+}
+
+krb5_error_code
+_krb5_pk_rd_pa_reply_ecdh_compute_key(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ const unsigned char *in,
+ size_t in_sz,
+ unsigned char **out,
+ int *out_sz)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ krb5_error_code ret = 0;
+ int dh_gen_keylen;
+
+ const EC_GROUP *group;
+ EC_KEY *public = NULL;
+
+ group = EC_KEY_get0_group(ctx->u.eckey);
+
+ public = EC_KEY_new();
+ if (public == NULL)
+ return krb5_enomem(context);
+ if (EC_KEY_set_group(public, group) != 1) {
+ EC_KEY_free(public);
+ return krb5_enomem(context);
+ }
+
+ if (o2i_ECPublicKey(&public, &in, in_sz) == NULL) {
+ EC_KEY_free(public);
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't parse ECDH public key", ""));
+ return ret;
+ }
+
+ *out_sz = (EC_GROUP_get_degree(group) + 7) / 8;
+ if (*out_sz < 0)
+ return EOVERFLOW;
+ *out = malloc(*out_sz);
+ if (*out == NULL) {
+ EC_KEY_free(public);
+ return krb5_enomem(context);
+ }
+ dh_gen_keylen = ECDH_compute_key(*out, *out_sz,
+ EC_KEY_get0_public_key(public),
+ ctx->u.eckey, NULL);
+ EC_KEY_free(public);
+ if (dh_gen_keylen <= 0) {
+ ret = KRB5KRB_ERR_GENERIC;
+ dh_gen_keylen = 0;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't compute ECDH public key", ""));
+ free(*out);
+ *out = NULL;
+ *out_sz = 0;
+ }
+ *out_sz = dh_gen_keylen;
+
+ return ret;
+#else
+ krb5_set_error_message(context, ENOTSUP,
+ N_("PKINIT: ECDH not supported", ""));
+ return ENOTSUP;
+#endif
+}
+
+void
+_krb5_pk_eckey_free(void *eckey)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ EC_KEY_free(eckey);
+#endif
+}
+
+#else
+
+static char lib_krb5_pkinit_ec_c = '\0';
+
+#endif
/*
- * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
hx509_cert cert;
};
-struct krb5_pk_init_ctx_data {
- struct krb5_pk_identity *id;
- enum { USE_RSA, USE_DH, USE_ECDH } keyex;
- union {
- DH *dh;
-#ifdef HAVE_OPENSSL
- EC_KEY *eckey;
-#endif
- } u;
- krb5_data *clientDHNonce;
- struct krb5_dh_moduli **m;
- hx509_peer_info peer;
- enum krb5_pk_type type;
- unsigned int require_binding:1;
- unsigned int require_eku:1;
- unsigned int require_krbtgt_otherName:1;
- unsigned int require_hostname_match:1;
- unsigned int trustedCertifiers:1;
- unsigned int anonymous:1;
-};
-
static void
pk_copy_error(krb5_context context,
hx509_context hx509ctx,
return ret;
if (size != dhbuf.length)
krb5_abortx(context, "asn1 internal error");
+ a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
+ a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
} else if (ctx->keyex == USE_ECDH) {
-#ifdef HAVE_OPENSSL
- ECParameters ecp;
- unsigned char *p;
- int xlen;
-
- /* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */
-
- ecp.element = choice_ECParameters_namedCurve;
- ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1,
- &ecp.u.namedCurve);
- if (ret)
- return ret;
-
- ALLOC(a->clientPublicValue->algorithm.parameters, 1);
- if (a->clientPublicValue->algorithm.parameters == NULL) {
- free_ECParameters(&ecp);
- return ENOMEM;
- }
- ASN1_MALLOC_ENCODE(ECParameters, p, xlen, &ecp, &size, ret);
- free_ECParameters(&ecp);
- if (ret)
- return ret;
- if ((int)size != xlen)
- krb5_abortx(context, "asn1 internal error");
-
- a->clientPublicValue->algorithm.parameters->data = p;
- a->clientPublicValue->algorithm.parameters->length = size;
-
- /* copy in public key */
-
- ret = der_copy_oid(&asn1_oid_id_ecPublicKey,
- &a->clientPublicValue->algorithm.algorithm);
- if (ret)
- return ret;
-
- ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- if (ctx->u.eckey == NULL)
- return ENOMEM;
-
- ret = EC_KEY_generate_key(ctx->u.eckey);
- if (ret != 1)
- return EINVAL;
-
- /* encode onto dhkey */
-
- xlen = i2o_ECPublicKey(ctx->u.eckey, NULL);
- if (xlen <= 0)
- abort();
-
- dhbuf.data = malloc(xlen);
- if (dhbuf.data == NULL)
- abort();
- dhbuf.length = xlen;
- p = dhbuf.data;
-
- xlen = i2o_ECPublicKey(ctx->u.eckey, &p);
- if (xlen <= 0)
- abort();
-
- /* XXX verify that this is right with RFC3279 */
-#else
- return EINVAL;
-#endif
+ ret = _krb5_build_authpack_subjectPK_EC(context, ctx, a);
+ if (ret)
+ return ret;
} else
krb5_abortx(context, "internal error");
- a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
- a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
}
{
}
} else {
-#ifdef HAVE_OPENSSL
- const EC_GROUP *group;
- EC_KEY *public = NULL;
-
- group = EC_KEY_get0_group(ctx->u.eckey);
-
- public = EC_KEY_new();
- if (public == NULL) {
- ret = ENOMEM;
- goto out;
- }
- if (EC_KEY_set_group(public, group) != 1) {
- EC_KEY_free(public);
- ret = ENOMEM;
- goto out;
- }
-
- if (o2i_ECPublicKey(&public, &p, size) == NULL) {
- EC_KEY_free(public);
- ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret,
- N_("PKINIT: Can't parse ECDH public key", ""));
- goto out;
- }
-
- size = (EC_GROUP_get_degree(group) + 7) / 8;
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- EC_KEY_free(public);
- ret = krb5_enomem(context);
- goto out;
- }
- dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
- EC_KEY_get0_public_key(public), ctx->u.eckey, NULL);
- EC_KEY_free(public);
- if (dh_gen_keylen == -1) {
- ret = KRB5KRB_ERR_GENERIC;
- dh_gen_keylen = 0;
- krb5_set_error_message(context, ret,
- N_("PKINIT: Can't compute ECDH public key", ""));
- goto out;
- }
-#else
- ret = EINVAL;
-#endif
+ ret = _krb5_pk_rd_pa_reply_ecdh_compute_key(context, ctx, p,
+ size, &dh_gen_key,
+ &dh_gen_keylen);
+ if (ret)
+ goto out;
}
if (dh_gen_keylen <= 0) {
case USE_RSA:
break;
case USE_ECDH:
-#ifdef HAVE_OPENSSL
if (ctx->u.eckey)
- EC_KEY_free(ctx->u.eckey);
-#endif
+ _krb5_pk_eckey_free(ctx->u.eckey);
break;
}
if (ctx->id) {
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto)
-
lib_LTLIBRARIES = libheimntlm.la
dist_include_HEADERS = heimntlm.h $(srcdir)/heimntlm-protos.h
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_hcrypto) $(ROKEN_RENAME)
+AM_CPPFLAGS += $(ROKEN_RENAME)
if HAVE_DBHEADER
AM_CPPFLAGS += -I$(DBHEADER)
endif
-e "s!@PTHREAD_LIBADD\@!$(PTHREAD_LIBADD)!g" \
-e "s!@LIB_crypt\@!$(LIB_crypt)!g" \
-e "s!@LIB_dbopen\@!$(LIB_dbopen)!g" \
- -e "s!@INCLUDE_hcrypto\@!$(INCLUDE_hcrypto)!g" \
-e "s!@LIB_hcrypto_appl\@!$(LIB_hcrypto_appl)!g" \
-e "s!@LIB_dlopen\@!$(LIB_dlopen)!g" \
-e "s!@LIB_door_create\@!$(LIB_door_create)!g" \
echo ${lib_flags}
fi
if test "$do_cflags" = "yes"; then
- cflags="@INCLUDE_hcrypto@"
+ cflags=""
if test X"${includedir}" != X/usr/include; then
cflags="-I${includedir} $cflags"
fi
# Disable AFS support
NO_AFS=1
+# OpenSSL (mostly not needed on Windows, but should work)
+# INCLUDE_openssl_crypto=
+# LIB_openssl_crypto=
+
# OpenLDAP package is available
# OPENLDAP=1