summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Mraz <tmraz@fedoraproject.org>2016-10-11 14:04:59 +0200
committerTomas Mraz <tmraz@fedoraproject.org>2016-10-11 14:04:59 +0200
commit895d0bdfea59408674c84f07a8ce9382e616e449 (patch)
tree2146070b25d390e56e3ee467aa4ba85d1f9066a6
parent76843c3ef01a06ba162cf5174009df5ca5e7fb02 (diff)
downloadkrb5-895d0bdfea59408674c84f07a8ce9382e616e449.tar.gz
krb5-895d0bdfea59408674c84f07a8ce9382e616e449.tar.xz
krb5-895d0bdfea59408674c84f07a8ce9382e616e449.zip
rebuild with OpenSSL 1.1.0, added backported upstream patch
-rw-r--r--krb5-1.14.4-openssl11.patch1940
-rw-r--r--krb5.spec6
2 files changed, 1945 insertions, 1 deletions
diff --git a/krb5-1.14.4-openssl11.patch b/krb5-1.14.4-openssl11.patch
new file mode 100644
index 0000000..3bf9077
--- /dev/null
+++ b/krb5-1.14.4-openssl11.patch
@@ -0,0 +1,1940 @@
+diff -up krb5-1.14.4/src/configure.in.openssl11 krb5-1.14.4/src/configure.in
+--- krb5-1.14.4/src/configure.in.openssl11 2016-09-29 18:02:15.298136450 +0200
++++ krb5-1.14.4/src/configure.in 2016-09-29 23:30:52.337207353 +0200
+@@ -1080,8 +1080,8 @@ enable_pkinit=try)
+ if test "$enable_pkinit" = yes || test "$enable_pkinit" = try; then
+ AC_CACHE_CHECK(for a recent enough OpenSSL, k5_cv_openssl_version_okay,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <openssl/opensslv.h>
+-#if OPENSSL_VERSION_NUMBER < 0x00908000L
+-# error openssl is too old, need 0.9.8
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++# error openssl is too old, need 1.0.0
+ #endif
+ int i = 1;
+ ])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
+diff -up krb5-1.14.4/src/lib/crypto/openssl/crypto_mod.h.openssl11 krb5-1.14.4/src/lib/crypto/openssl/crypto_mod.h
+--- krb5-1.14.4/src/lib/crypto/openssl/crypto_mod.h.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/crypto_mod.h 2016-09-29 23:29:55.700877637 +0200
+@@ -33,9 +33,17 @@
+ #ifndef CRYPTO_MOD_H
+ #define CRYPTO_MOD_H
+
++#include <openssl/crypto.h>
+ #include <openssl/aes.h>
+ #include <openssl/sha.h>
+
++/* 1.1 standardizes constructor and destructor names, renaming
++ * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#define EVP_MD_CTX_new EVP_MD_CTX_create
++#define EVP_MD_CTX_free EVP_MD_CTX_destroy
++#endif
++
+ #define aes_ctx AES_KEY
+ #define krb5int_aes_enc_key(k, len, ctx) AES_set_encrypt_key(k, 8*(len), ctx)
+ #define krb5int_aes_enc_blk(in, out, ctx) AES_encrypt(in, out, ctx)
+diff -up krb5-1.14.4/src/lib/crypto/openssl/enc_provider/aes.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/enc_provider/aes.c
+--- krb5-1.14.4/src/lib/crypto/openssl/enc_provider/aes.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/enc_provider/aes.c 2016-09-29 23:29:55.700877637 +0200
+@@ -65,22 +65,27 @@ cbc_enc(krb5_key key, const krb5_data *i
+ {
+ int ret, olen = BLOCK_SIZE;
+ unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ struct iov_cursor cursor;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
+- ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ ret = EVP_EncryptInit_ex(ctx, map_mode(key->keyblock.length),
+ NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (ret == 0)
++ if (ret == 0) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+- ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
++ ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE);
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, BLOCK_SIZE);
+ zap(oblock, BLOCK_SIZE);
+@@ -94,22 +99,27 @@ cbc_decr(krb5_key key, const krb5_data *
+ {
+ int ret = 0, olen = BLOCK_SIZE;
+ unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ struct iov_cursor cursor;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
+- ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ ret = EVP_DecryptInit_ex(ctx, map_mode(key->keyblock.length),
+ NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (ret == 0)
++ if (ret == 0) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+- ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
++ ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE);
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, BLOCK_SIZE);
+ zap(oblock, BLOCK_SIZE);
+diff -up krb5-1.14.4/src/lib/crypto/openssl/enc_provider/camellia.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/enc_provider/camellia.c
+--- krb5-1.14.4/src/lib/crypto/openssl/enc_provider/camellia.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/enc_provider/camellia.c 2016-09-29 23:29:55.701877642 +0200
+@@ -89,22 +89,27 @@ cbc_enc(krb5_key key, const krb5_data *i
+ {
+ int ret, olen = BLOCK_SIZE;
+ unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ struct iov_cursor cursor;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
+- ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ ret = EVP_EncryptInit_ex(ctx, map_mode(key->keyblock.length),
+ NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (ret == 0)
++ if (ret == 0) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+- ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
++ ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE);
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, BLOCK_SIZE);
+ zap(oblock, BLOCK_SIZE);
+@@ -118,22 +123,27 @@ cbc_decr(krb5_key key, const krb5_data *
+ {
+ int ret = 0, olen = BLOCK_SIZE;
+ unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ struct iov_cursor cursor;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
+- ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ ret = EVP_DecryptInit_ex(ctx, map_mode(key->keyblock.length),
+ NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (ret == 0)
++ if (ret == 0) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE);
+ k5_iov_cursor_get(&cursor, iblock);
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+- ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen, iblock, BLOCK_SIZE);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
++ ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE);
+ if (ret == 1)
+ k5_iov_cursor_put(&cursor, oblock);
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, BLOCK_SIZE);
+ zap(oblock, BLOCK_SIZE);
+diff -up krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des.c
+--- krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des.c 2016-09-29 23:29:55.701877642 +0200
+@@ -82,26 +82,29 @@ k5_des_encrypt(krb5_key key, const krb5_
+ int ret, olen = DES_BLOCK_SIZE;
+ unsigned char iblock[DES_BLOCK_SIZE], oblock[DES_BLOCK_SIZE];
+ struct iov_cursor cursor;
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ krb5_boolean empty;
+
+ ret = validate(key, ivec, data, num_data, &empty);
+ if (ret != 0 || empty)
+ return ret;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
+
+- ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
++ ret = EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL,
+ key->keyblock.contents, (ivec && ivec->data) ? (unsigned char*)ivec->data : NULL);
+- if (!ret)
++ if (!ret) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
++ EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+ k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
+- ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen,
+- (unsigned char *)iblock, DES_BLOCK_SIZE);
++ ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, DES_BLOCK_SIZE);
+ if (!ret)
+ break;
+ k5_iov_cursor_put(&cursor, oblock);
+@@ -110,7 +113,7 @@ k5_des_encrypt(krb5_key key, const krb5_
+ if (ivec != NULL)
+ memcpy(ivec->data, oblock, DES_BLOCK_SIZE);
+
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, sizeof(iblock));
+ zap(oblock, sizeof(oblock));
+@@ -127,27 +130,30 @@ k5_des_decrypt(krb5_key key, const krb5_
+ int ret, olen = DES_BLOCK_SIZE;
+ unsigned char iblock[DES_BLOCK_SIZE], oblock[DES_BLOCK_SIZE];
+ struct iov_cursor cursor;
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ krb5_boolean empty;
+
+ ret = validate(key, ivec, data, num_data, &empty);
+ if (ret != 0 || empty)
+ return ret;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
+
+- ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
++ ret = EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL,
+ key->keyblock.contents,
+ (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (!ret)
++ if (!ret) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
+
+ k5_iov_cursor_init(&cursor, data, num_data, DES_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
+- ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen,
+- iblock, DES_BLOCK_SIZE);
++ ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, DES_BLOCK_SIZE);
+ if (!ret)
+ break;
+ k5_iov_cursor_put(&cursor, oblock);
+@@ -156,7 +162,7 @@ k5_des_decrypt(krb5_key key, const krb5_
+ if (ivec != NULL)
+ memcpy(ivec->data, iblock, DES_BLOCK_SIZE);
+
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, sizeof(iblock));
+ zap(oblock, sizeof(oblock));
+diff -up krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des3.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des3.c
+--- krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des3.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/enc_provider/des3.c 2016-09-29 23:29:55.701877642 +0200
+@@ -81,27 +81,30 @@ k5_des3_encrypt(krb5_key key, const krb5
+ int ret, olen = DES3_BLOCK_SIZE;
+ unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
+ struct iov_cursor cursor;
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ krb5_boolean empty;
+
+ ret = validate(key, ivec, data, num_data, &empty);
+ if (ret != 0 || empty)
+ return ret;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
+
+- ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
++ ret = EVP_EncryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL,
+ key->keyblock.contents,
+ (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (!ret)
++ if (!ret) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
+
+ k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
+- ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &olen,
+- (unsigned char *)iblock, DES3_BLOCK_SIZE);
++ ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, DES3_BLOCK_SIZE);
+ if (!ret)
+ break;
+ k5_iov_cursor_put(&cursor, oblock);
+@@ -110,7 +113,7 @@ k5_des3_encrypt(krb5_key key, const krb5
+ if (ivec != NULL)
+ memcpy(ivec->data, oblock, DES3_BLOCK_SIZE);
+
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, sizeof(iblock));
+ zap(oblock, sizeof(oblock));
+@@ -127,26 +130,30 @@ k5_des3_decrypt(krb5_key key, const krb5
+ int ret, olen = DES3_BLOCK_SIZE;
+ unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE];
+ struct iov_cursor cursor;
+- EVP_CIPHER_CTX ciph_ctx;
++ EVP_CIPHER_CTX *ctx;
+ krb5_boolean empty;
+
+ ret = validate(key, ivec, data, num_data, &empty);
+ if (ret != 0 || empty)
+ return ret;
+
+- EVP_CIPHER_CTX_init(&ciph_ctx);
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
+
+- ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
++ ret = EVP_DecryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL,
+ key->keyblock.contents,
+ (ivec) ? (unsigned char*)ivec->data : NULL);
+- if (!ret)
++ if (!ret) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
+
+- EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
++ EVP_CIPHER_CTX_set_padding(ctx,0);
+
+ k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE);
+ while (k5_iov_cursor_get(&cursor, iblock)) {
+- ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &olen,
++ ret = EVP_DecryptUpdate(ctx, oblock, &olen,
+ (unsigned char *)iblock, DES3_BLOCK_SIZE);
+ if (!ret)
+ break;
+@@ -156,7 +163,7 @@ k5_des3_decrypt(krb5_key key, const krb5
+ if (ivec != NULL)
+ memcpy(ivec->data, iblock, DES3_BLOCK_SIZE);
+
+- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ zap(iblock, sizeof(iblock));
+ zap(oblock, sizeof(oblock));
+diff -up krb5-1.14.4/src/lib/crypto/openssl/enc_provider/rc4.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/enc_provider/rc4.c
+--- krb5-1.14.4/src/lib/crypto/openssl/enc_provider/rc4.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/enc_provider/rc4.c 2016-09-29 23:29:55.702877648 +0200
+@@ -36,15 +36,14 @@
+ #include <openssl/evp.h>
+
+ /*
+- * The loopback field is NULL if ctx is uninitialized (no encrypt or decrypt
+- * operation has taken place), or a pointer to the structure address if ctx is
+- * initialized. If the application copies the state (not a valid operation,
+- * but one which happens to works with some other enc providers), we can detect
+- * it via the loopback field and return a sane error code.
++ * The loopback field is a pointer to the structure. If the application copies
++ * the state (not a valid operation, but one which happens to works with some
++ * other enc providers), we can detect it via the loopback field and return a
++ * sane error code.
+ */
+ struct arcfour_state {
+ struct arcfour_state *loopback;
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX *ctx;
+ };
+
+ #define RC4_KEY_SIZE 16
+@@ -64,26 +63,30 @@ k5_arcfour_docrypt(krb5_key key,const kr
+ size_t i;
+ int ret = 1, tmp_len = 0;
+ krb5_crypto_iov *iov = NULL;
+- EVP_CIPHER_CTX ciph_ctx, *ctx;
++ EVP_CIPHER_CTX *ctx = NULL;
+ struct arcfour_state *arcstate;
+- krb5_boolean do_init = TRUE;
+
+ arcstate = (state != NULL) ? (struct arcfour_state *) state->data : NULL;
+ if (arcstate != NULL) {
+- ctx = &arcstate->ctx;
+- if (arcstate->loopback == arcstate)
+- do_init = FALSE;
+- else if (arcstate->loopback != NULL)
++ ctx = arcstate->ctx;
++ if (arcstate->loopback != arcstate)
+ return KRB5_CRYPTO_INTERNAL;
+- } else {
+- ctx = &ciph_ctx;
+ }
+- if (do_init) {
+- EVP_CIPHER_CTX_init(ctx);
++
++ if (ctx == NULL) {
++ ctx = EVP_CIPHER_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
+ ret = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, key->keyblock.contents,
+ NULL);
+- if (!ret)
++ if (!ret) {
++ EVP_CIPHER_CTX_free(ctx);
+ return KRB5_CRYPTO_INTERNAL;
++ }
++
++ if (arcstate != NULL)
++ arcstate->ctx = ctx;
+ }
+
+ for (i = 0; i < num_data; i++) {
+@@ -98,10 +101,8 @@ k5_arcfour_docrypt(krb5_key key,const kr
+ }
+ }
+
+- if (arcstate) /* Context is saved; mark as initialized. */
+- arcstate->loopback = arcstate;
+- else /* Context is not saved; clean it up now. */
+- EVP_CIPHER_CTX_cleanup(ctx);
++ if (arcstate == NULL)
++ EVP_CIPHER_CTX_free(ctx);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+@@ -114,9 +115,7 @@ k5_arcfour_free_state(krb5_data *state)
+ {
+ struct arcfour_state *arcstate = (struct arcfour_state *) state->data;
+
+- /* Clean up the OpenSSL context if it was initialized. */
+- if (arcstate && arcstate->loopback == arcstate)
+- EVP_CIPHER_CTX_cleanup(&arcstate->ctx);
++ EVP_CIPHER_CTX_free(arcstate->ctx);
+ free(arcstate);
+ }
+
+@@ -130,7 +129,8 @@ k5_arcfour_init_state(const krb5_keybloc
+ arcstate = calloc(1, sizeof(*arcstate));
+ if (arcstate == NULL)
+ return ENOMEM;
+- arcstate->loopback = NULL;
++ arcstate->loopback = arcstate;
++ arcstate->ctx = NULL;
+ new_state->data = (char *) arcstate;
+ new_state->length = sizeof(*arcstate);
+ return 0;
+diff -up krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md4.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md4.c
+--- krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md4.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md4.c 2016-09-29 23:29:55.702877648 +0200
+@@ -32,21 +32,24 @@
+ static krb5_error_code
+ k5_md4_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+ {
+- EVP_MD_CTX ctx;
++ EVP_MD_CTX *ctx;
+ unsigned int i;
+
+ if (output->length != MD4_DIGEST_LENGTH)
+ return KRB5_CRYPTO_INTERNAL;
+
+- EVP_MD_CTX_init(&ctx);
+- EVP_DigestInit_ex(&ctx, EVP_md4(), NULL);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ EVP_DigestInit_ex(ctx, EVP_md4(), NULL);
+ for (i = 0; i < num_data; i++) {
+ const krb5_data *d = &data[i].data;
+ if (SIGN_IOV(&data[i]))
+- EVP_DigestUpdate(&ctx, (unsigned char *)d->data, d->length);
++ EVP_DigestUpdate(ctx, (uint8_t *)d->data, d->length);
+ }
+- EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
+- EVP_MD_CTX_cleanup(&ctx);
++ EVP_DigestFinal_ex(ctx, (uint8_t *)output->data, NULL);
++ EVP_MD_CTX_free(ctx);
+ return 0;
+ }
+
+diff -up krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md5.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md5.c
+--- krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md5.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_md5.c 2016-09-29 23:29:55.702877648 +0200
+@@ -32,21 +32,24 @@
+ static krb5_error_code
+ k5_md5_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+ {
+- EVP_MD_CTX ctx;
++ EVP_MD_CTX *ctx;
+ unsigned int i;
+
+ if (output->length != MD5_DIGEST_LENGTH)
+ return KRB5_CRYPTO_INTERNAL;
+
+- EVP_MD_CTX_init(&ctx);
+- EVP_DigestInit_ex(&ctx, EVP_md5(), NULL);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
+ for (i = 0; i < num_data; i++) {
+ const krb5_data *d = &data[i].data;
+ if (SIGN_IOV(&data[i]))
+- EVP_DigestUpdate(&ctx, (unsigned char *)d->data, d->length);
++ EVP_DigestUpdate(ctx, (uint8_t *)d->data, d->length);
+ }
+- EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
+- EVP_MD_CTX_cleanup(&ctx);
++ EVP_DigestFinal_ex(ctx, (uint8_t *)output->data, NULL);
++ EVP_MD_CTX_free(ctx);
+ return 0;
+ }
+
+diff -up krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_sha1.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_sha1.c
+--- krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_sha1.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/hash_provider/hash_sha1.c 2016-09-29 23:29:55.702877648 +0200
+@@ -33,21 +33,24 @@
+ static krb5_error_code
+ k5_sha1_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+ {
+- EVP_MD_CTX ctx;
++ EVP_MD_CTX *ctx;
+ unsigned int i;
+
+ if (output->length != SHA_DIGEST_LENGTH)
+ return KRB5_CRYPTO_INTERNAL;
+
+- EVP_MD_CTX_init(&ctx);
+- EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
+ for (i = 0; i < num_data; i++) {
+ const krb5_data *d = &data[i].data;
+ if (SIGN_IOV(&data[i]))
+- EVP_DigestUpdate(&ctx, (unsigned char *)d->data, d->length);
++ EVP_DigestUpdate(ctx, (uint8_t *)d->data, d->length);
+ }
+- EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
+- EVP_MD_CTX_cleanup(&ctx);
++ EVP_DigestFinal_ex(ctx, (uint8_t *)output->data, NULL);
++ EVP_MD_CTX_free(ctx);
+ return 0;
+ }
+
+diff -up krb5-1.14.4/src/lib/crypto/openssl/hmac.c.openssl11 krb5-1.14.4/src/lib/crypto/openssl/hmac.c
+--- krb5-1.14.4/src/lib/crypto/openssl/hmac.c.openssl11 2016-09-13 21:59:44.000000000 +0200
++++ krb5-1.14.4/src/lib/crypto/openssl/hmac.c 2016-09-29 23:29:55.702877648 +0200
+@@ -55,6 +55,33 @@
+ #include <openssl/hmac.h>
+ #include <openssl/evp.h>
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++
++/* OpenSSL 1.1 makes HMAC_CTX opaque, while 1.0 does not have pointer
++ * constructors or destructors. */
++
++#define HMAC_CTX_new compat_hmac_ctx_new
++static HMAC_CTX *
++compat_hmac_ctx_new()
++{
++ HMAC_CTX *ctx;
++
++ ctx = calloc(1, sizeof(*ctx));
++ if (ctx != NULL)
++ HMAC_CTX_init(ctx);
++ return ctx;
++}
++
++#define HMAC_CTX_free compat_hmac_ctx_free
++static void
++compat_hmac_ctx_free(HMAC_CTX *ctx)
++{
++ HMAC_CTX_cleanup(ctx);
++ free(ctx);
++}
++
++#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
++
+ /*
+ * the HMAC transform looks like:
+ *
+@@ -88,7 +115,7 @@ krb5int_hmac_keyblock(const struct krb5_
+ {
+ unsigned int i = 0, md_len = 0;
+ unsigned char md[EVP_MAX_MD_SIZE];
+- HMAC_CTX c;
++ HMAC_CTX *ctx;
+ size_t hashsize, blocksize;
+
+ hashsize = hash->hashsize;
+@@ -102,20 +129,23 @@ krb5int_hmac_keyblock(const struct krb5_
+ if (!map_digest(hash))
+ return(KRB5_CRYPTO_INTERNAL); // unsupported alg
+
+- HMAC_CTX_init(&c);
+- HMAC_Init(&c, keyblock->contents, keyblock->length, map_digest(hash));
++ ctx = HMAC_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++
++ HMAC_Init(ctx, keyblock->contents, keyblock->length, map_digest(hash));
+ for (i = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (SIGN_IOV(iov))
+- HMAC_Update(&c, (unsigned char*) iov->data.data, iov->data.length);
++ HMAC_Update(ctx, (uint8_t *)iov->data.data, iov->data.length);
+ }
+- HMAC_Final(&c,(unsigned char *)md, &md_len);
++ HMAC_Final(ctx, md, &md_len);
+ if ( md_len <= output->length) {
+ output->length = md_len;
+ memcpy(output->data, md, output->length);
+ }
+- HMAC_CTX_cleanup(&c);
++ HMAC_CTX_free(ctx);
+ return 0;
+
+
+diff -up krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c.openssl11 krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+--- krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c.openssl11 2016-09-13 21:59:45.000000000 +0200
++++ krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c 2016-09-30 00:46:51.987555455 +0200
+@@ -49,9 +49,8 @@ static krb5_error_code pkinit_init_pkcs1
+ static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
+
+ static krb5_error_code pkinit_encode_dh_params
+-(BIGNUM *, BIGNUM *, BIGNUM *, unsigned char **, unsigned int *);
+-static DH *pkinit_decode_dh_params
+-(DH **, unsigned char **, unsigned int );
++(const BIGNUM *, const BIGNUM *, const BIGNUM *, uint8_t **, unsigned int *);
++static DH *decode_dh_params(const uint8_t *, unsigned int );
+ static int pkinit_check_dh_params(DH *dh1, DH *dh2);
+
+ static krb5_error_code pkinit_sign_data
+@@ -65,12 +64,12 @@ static krb5_error_code create_signature
+
+ static krb5_error_code pkinit_decode_data
+ (krb5_context context, pkinit_identity_crypto_context cryptoctx,
+- unsigned char *data, unsigned int data_len,
+- unsigned char **decoded, unsigned int *decoded_len);
++ const uint8_t *data, unsigned int data_len, uint8_t **decoded,
++ unsigned int *decoded_len);
+
+ static krb5_error_code decode_data
+-(unsigned char **, unsigned int *, unsigned char *, unsigned int,
+- EVP_PKEY *pkey, X509 *cert);
++(uint8_t **, unsigned int *, const uint8_t *, unsigned int, EVP_PKEY *pkey,
++ X509 *cert);
+
+ #ifdef DEBUG_DH
+ static void print_dh(DH *, char *);
+@@ -78,8 +77,7 @@ static void print_pubkey(BIGNUM *, char
+ #endif
+
+ static int prepare_enc_data
+-(unsigned char *indata, int indata_len, unsigned char **outdata,
+- int *outdata_len);
++(const uint8_t *indata, int indata_len, uint8_t **outdata, int *outdata_len);
+
+ static int openssl_callback (int, X509_STORE_CTX *);
+ static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
+@@ -125,8 +123,8 @@ static krb5_error_code pkinit_sign_data_
+ unsigned char **sig, unsigned int *sig_len);
+ static krb5_error_code pkinit_decode_data_pkcs11
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+- unsigned char *data, unsigned int data_len,
+- unsigned char **decoded_data, unsigned int *decoded_data_len);
++ const uint8_t *data, unsigned int data_len, uint8_t **decoded_data,
++ unsigned int *decoded_data_len);
+ #endif /* WITHOUT_PKCS11 */
+
+ static krb5_error_code pkinit_sign_data_fs
+@@ -135,8 +133,8 @@ static krb5_error_code pkinit_sign_data_
+ unsigned char **sig, unsigned int *sig_len);
+ static krb5_error_code pkinit_decode_data_fs
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+- unsigned char *data, unsigned int data_len,
+- unsigned char **decoded_data, unsigned int *decoded_data_len);
++ const uint8_t *data, unsigned int data_len, uint8_t **decoded_data,
++ unsigned int *decoded_data_len);
+
+ static krb5_error_code
+ create_krb5_invalidCertificates(krb5_context context,
+@@ -193,6 +191,66 @@ pkinit_pkcs11_code_to_text(int err);
+ (*_x509_pp) = PKCS7_cert_from_signer_info(_p7,_si)
+ #endif
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++
++/* 1.1 standardizes constructor and destructor names, renaming
++ * EVP_MD_CTX_{create,destroy} and deprecating ASN1_STRING_data. */
++
++#define EVP_MD_CTX_new EVP_MD_CTX_create
++#define EVP_MD_CTX_free EVP_MD_CTX_destroy
++#define ASN1_STRING_get0_data ASN1_STRING_data
++
++/* 1.1 makes many handle types opaque and adds accessors. Add compatibility
++ * versions of the new accessors we use for pre-1.1. */
++
++#define OBJ_get0_data(o) ((o)->data)
++#define OBJ_length(o) ((o)->length)
++
++#define DH_set0_pqg compat_dh_set0_pqg
++static int compat_dh_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
++{
++ /* The real function frees the old values and does argument checking, but
++ * our code doesn't need that. */
++ dh->p = p;
++ dh->q = q;
++ dh->g = g;
++ return 1;
++}
++
++#define DH_get0_pqg compat_dh_get0_pqg
++static void compat_dh_get0_pqg(const DH *dh, const BIGNUM **p,
++ const BIGNUM **q, const BIGNUM **g)
++{
++ if (p != NULL)
++ *p = dh->p;
++ if (q != NULL)
++ *q = dh->q;
++ if (g != NULL)
++ *g = dh->g;
++}
++
++#define DH_get0_key compat_dh_get0_key
++static void compat_dh_get0_key(const DH *dh, const BIGNUM **pub,
++ const BIGNUM **priv)
++{
++ if (pub != NULL)
++ *pub = dh->pub_key;
++ if (priv != NULL)
++ *priv = dh->priv_key;
++}
++
++/* Return true if the cert c includes a key usage which doesn't include u.
++ * Define using direct member access for pre-1.1. */
++#define ku_reject(c, u) \
++ (((c)->ex_flags & EXFLAG_KUSAGE) && !((c)->ex_kusage & (u)))
++
++#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
++
++/* Return true if the cert x includes a key usage which doesn't include u. */
++#define ku_reject(c, u) (!(X509_get_key_usage(c) & (u)))
++
++#endif
++
+ static struct pkcs11_errstrings {
+ short code;
+ char *text;
+@@ -286,7 +344,7 @@ static struct pkcs11_errstrings {
+ };
+
+ /* DH parameters */
+-unsigned char pkinit_1024_dhprime[128] = {
++static uint8_t oakley_1024[128] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+@@ -305,7 +363,7 @@ unsigned char pkinit_1024_dhprime[128] =
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+-unsigned char pkinit_2048_dhprime[2048/8] = {
++static uint8_t oakley_2048[2048/8] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+@@ -340,7 +398,7 @@ unsigned char pkinit_2048_dhprime[2048/8
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+-unsigned char pkinit_4096_dhprime[4096/8] = {
++static uint8_t oakley_4096[4096/8] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+@@ -802,43 +860,56 @@ pkinit_fini_pkinit_oids(pkinit_plg_crypt
+ ASN1_OBJECT_free(ctx->id_kp_serverAuth);
+ }
+
++/* Construct an OpenSSL DH object for an Oakley group. */
++static DH *
++make_oakley_dh(uint8_t *prime, size_t len)
++{
++ DH *dh = NULL;
++ BIGNUM *p = NULL, *q = NULL, *g = NULL;
++
++ p = BN_bin2bn(prime, len, NULL);
++ if (p == NULL)
++ goto cleanup;
++ q = BN_new();
++ if (q == NULL)
++ goto cleanup;
++ if (!BN_rshift1(q, p))
++ goto cleanup;
++ g = BN_new();
++ if (g == NULL)
++ goto cleanup;
++ if (!BN_set_word(g, DH_GENERATOR_2))
++ goto cleanup;
++
++ dh = DH_new();
++ if (dh == NULL)
++ goto cleanup;
++ DH_set0_pqg(dh, p, q, g);
++ p = g = q = NULL;
++
++cleanup:
++ BN_free(p);
++ BN_free(q);
++ BN_free(g);
++ return dh;
++}
++
+ static krb5_error_code
+ pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
+ {
+ krb5_error_code retval = ENOMEM;
+
+- plgctx->dh_1024 = DH_new();
++ plgctx->dh_1024 = make_oakley_dh(oakley_1024, sizeof(oakley_1024));
+ if (plgctx->dh_1024 == NULL)
+ goto cleanup;
+- plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
+- sizeof(pkinit_1024_dhprime), NULL);
+- if ((plgctx->dh_1024->g = BN_new()) == NULL ||
+- (plgctx->dh_1024->q = BN_new()) == NULL)
+- goto cleanup;
+- BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
+- BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
+
+- plgctx->dh_2048 = DH_new();
++ plgctx->dh_2048 = make_oakley_dh(oakley_2048, sizeof(oakley_2048));
+ if (plgctx->dh_2048 == NULL)
+ goto cleanup;
+- plgctx->dh_2048->p = BN_bin2bn(pkinit_2048_dhprime,
+- sizeof(pkinit_2048_dhprime), NULL);
+- if ((plgctx->dh_2048->g = BN_new()) == NULL ||
+- (plgctx->dh_2048->q = BN_new()) == NULL)
+- goto cleanup;
+- BN_set_word(plgctx->dh_2048->g, DH_GENERATOR_2);
+- BN_rshift1(plgctx->dh_2048->q, plgctx->dh_2048->p);
+
+- plgctx->dh_4096 = DH_new();
++ plgctx->dh_4096 = make_oakley_dh(oakley_4096, sizeof(oakley_4096));
+ if (plgctx->dh_4096 == NULL)
+ goto cleanup;
+- plgctx->dh_4096->p = BN_bin2bn(pkinit_4096_dhprime,
+- sizeof(pkinit_4096_dhprime), NULL);
+- if ((plgctx->dh_4096->g = BN_new()) == NULL ||
+- (plgctx->dh_4096->q = BN_new()) == NULL)
+- goto cleanup;
+- BN_set_word(plgctx->dh_4096->g, DH_GENERATOR_2);
+- BN_rshift1(plgctx->dh_4096->q, plgctx->dh_4096->p);
+
+ retval = 0;
+
+@@ -1072,7 +1143,7 @@ cms_signeddata_create(krb5_context conte
+ unsigned char *p;
+ STACK_OF(X509) * cert_stack = NULL;
+ ASN1_OCTET_STRING *digest_attr = NULL;
+- EVP_MD_CTX ctx, ctx2;
++ EVP_MD_CTX *ctx;
+ const EVP_MD *md_tmp = NULL;
+ unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
+ unsigned char *digestInfo_buf = NULL, *abuf = NULL;
+@@ -1115,7 +1186,7 @@ cms_signeddata_create(krb5_context conte
+ } else {
+ /* create a cert chain */
+ X509_STORE *certstore = NULL;
+- X509_STORE_CTX certctx;
++ X509_STORE_CTX *certctx;
+ STACK_OF(X509) *certstack = NULL;
+ char buf[DN_BUF_LEN];
+ unsigned int i = 0, size = 0;
+@@ -1123,16 +1194,19 @@ cms_signeddata_create(krb5_context conte
+ if ((certstore = X509_STORE_new()) == NULL)
+ goto cleanup;
+ pkiDebug("building certificate chain\n");
+- X509_STORE_set_verify_cb_func(certstore, openssl_callback);
+- X509_STORE_CTX_init(&certctx, certstore, cert,
++ X509_STORE_set_verify_cb(certstore, openssl_callback);
++ certctx = X509_STORE_CTX_new();
++ if (certctx == NULL)
++ goto cleanup;
++ X509_STORE_CTX_init(certctx, certstore, cert,
+ id_cryptoctx->intermediateCAs);
+- X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
+- if (!X509_verify_cert(&certctx)) {
+- retval = oerr_cert(context, 0, &certctx,
++ X509_STORE_CTX_trusted_stack(certctx, id_cryptoctx->trustedCAs);
++ if (!X509_verify_cert(certctx)) {
++ retval = oerr_cert(context, 0, certctx,
+ _("Failed to verify own certificate"));
+ goto cleanup;
+ }
+- certstack = X509_STORE_CTX_get1_chain(&certctx);
++ certstack = X509_STORE_CTX_get1_chain(certctx);
+ size = sk_X509_num(certstack);
+ pkiDebug("size of certificate chain = %d\n", size);
+ for(i = 0; i < size - 1; i++) {
+@@ -1141,7 +1215,7 @@ cms_signeddata_create(krb5_context conte
+ pkiDebug("cert #%d: %s\n", i, buf);
+ sk_X509_push(cert_stack, X509_dup(x));
+ }
+- X509_STORE_CTX_cleanup(&certctx);
++ X509_STORE_CTX_free(certctx);
+ X509_STORE_free(certstore);
+ sk_X509_pop_free(certstack, X509_free);
+ }
+@@ -1157,9 +1231,9 @@ cms_signeddata_create(krb5_context conte
+ goto cleanup;
+ /* because ASN1_INTEGER_set is used to set a 'long' we will do
+ * things the ugly way. */
+- M_ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
++ ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
+ if (!(p7si->issuer_and_serial->serial =
+- M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
++ ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+ goto cleanup;
+
+ /* will not fill-out EVP_PKEY because it's on the smartcard */
+@@ -1188,11 +1262,14 @@ cms_signeddata_create(krb5_context conte
+ } else {
+ /* add signed attributes */
+ /* compute sha1 digest over the EncapsulatedContentInfo */
+- EVP_MD_CTX_init(&ctx);
+- EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+- EVP_DigestUpdate(&ctx, data, data_len);
+- md_tmp = EVP_MD_CTX_md(&ctx);
+- EVP_DigestFinal_ex(&ctx, md_data, &md_len);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ goto cleanup;
++ EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
++ EVP_DigestUpdate(ctx, data, data_len);
++ md_tmp = EVP_MD_CTX_md(ctx);
++ EVP_DigestFinal_ex(ctx, md_data, &md_len);
++ EVP_MD_CTX_free(ctx);
+
+ /* create a message digest attr */
+ digest_attr = ASN1_OCTET_STRING_new();
+@@ -1227,14 +1304,17 @@ cms_signeddata_create(krb5_context conte
+ if (id_cryptoctx->pkcs11_method == 1 &&
+ id_cryptoctx->mech == CKM_RSA_PKCS) {
+ pkiDebug("mech = CKM_RSA_PKCS\n");
+- EVP_MD_CTX_init(&ctx2);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ goto cleanup;
+ /* if this is not draft9 request, include digest signed attribute */
+ if (cms_msg_type != CMS_SIGN_DRAFT9)
+- EVP_DigestInit_ex(&ctx2, md_tmp, NULL);
++ EVP_DigestInit_ex(ctx, md_tmp, NULL);
+ else
+- EVP_DigestInit_ex(&ctx2, EVP_sha1(), NULL);
+- EVP_DigestUpdate(&ctx2, abuf, alen);
+- EVP_DigestFinal_ex(&ctx2, md_data2, &md_len2);
++ EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
++ EVP_DigestUpdate(ctx, abuf, alen);
++ EVP_DigestFinal_ex(ctx, md_data2, &md_len2);
++ EVP_MD_CTX_free(ctx);
+
+ alg = X509_ALGOR_new();
+ if (alg == NULL)
+@@ -1339,11 +1419,9 @@ cms_signeddata_create(krb5_context conte
+ cleanup2:
+ if (p7si) {
+ if (cms_msg_type != CMS_SIGN_DRAFT9)
+- EVP_MD_CTX_cleanup(&ctx);
+ #ifndef WITHOUT_PKCS11
+ if (id_cryptoctx->pkcs11_method == 1 &&
+ id_cryptoctx->mech == CKM_RSA_PKCS) {
+- EVP_MD_CTX_cleanup(&ctx2);
+ free(digest_buf);
+ free(digestInfo_buf);
+ free(alg_buf);
+@@ -1396,7 +1474,7 @@ cms_signeddata_verify(krb5_context conte
+ CMS_SignerInfo *si = NULL;
+ X509 *x = NULL;
+ X509_STORE *store = NULL;
+- X509_STORE_CTX cert_ctx;
++ X509_STORE_CTX *cert_ctx;
+ STACK_OF(X509) *signerCerts = NULL;
+ STACK_OF(X509) *intermediateCAs = NULL;
+ STACK_OF(X509_CRL) *signerRevoked = NULL;
+@@ -1450,8 +1528,7 @@ cms_signeddata_verify(krb5_context conte
+ retval = ENOMEM;
+ goto cleanup;
+ }
+- memcpy(d, ASN1_STRING_data(*octets),
+- *data_len);
++ memcpy(d, ASN1_STRING_get0_data(*octets), *data_len);
+ *data = d;
+ goto out;
+ } else {
+@@ -1471,9 +1548,9 @@ cms_signeddata_verify(krb5_context conte
+ /* check if we are inforcing CRL checking */
+ vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
+ if (require_crl_checking)
+- X509_STORE_set_verify_cb_func(store, openssl_callback);
++ X509_STORE_set_verify_cb(store, openssl_callback);
+ else
+- X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls);
++ X509_STORE_set_verify_cb(store, openssl_callback_ignore_crls);
+ X509_STORE_set_flags(store, vflags);
+
+ /*
+@@ -1544,14 +1621,17 @@ cms_signeddata_verify(krb5_context conte
+ /* initialize x509 context with the received certificate and
+ * trusted and intermediate CA chains and CRLs
+ */
+- if (!X509_STORE_CTX_init(&cert_ctx, store, x, intermediateCAs))
++ cert_ctx = X509_STORE_CTX_new();
++ if (cert_ctx == NULL)
++ goto cleanup;
++ if (!X509_STORE_CTX_init(cert_ctx, store, x, intermediateCAs))
+ goto cleanup;
+
+- X509_STORE_CTX_set0_crls(&cert_ctx, revoked);
++ X509_STORE_CTX_set0_crls(cert_ctx, revoked);
+
+ /* add trusted CAs certificates for cert verification */
+ if (idctx->trustedCAs != NULL)
+- X509_STORE_CTX_trusted_stack(&cert_ctx, idctx->trustedCAs);
++ X509_STORE_CTX_trusted_stack(cert_ctx, idctx->trustedCAs);
+ else {
+ pkiDebug("unable to find any trusted CAs\n");
+ goto cleanup;
+@@ -1586,11 +1666,13 @@ cms_signeddata_verify(krb5_context conte
+ }
+ #endif
+
+- i = X509_verify_cert(&cert_ctx);
++ i = X509_verify_cert(cert_ctx);
+ if (i <= 0) {
+- int j = X509_STORE_CTX_get_error(&cert_ctx);
++ int j = X509_STORE_CTX_get_error(cert_ctx);
++ X509 *cert;
+
+- reqctx->received_cert = X509_dup(cert_ctx.current_cert);
++ cert = X509_STORE_CTX_get_current_cert(cert_ctx);
++ reqctx->received_cert = X509_dup(cert);
+ switch(j) {
+ case X509_V_ERR_CERT_REVOKED:
+ retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
+@@ -1605,7 +1687,7 @@ cms_signeddata_verify(krb5_context conte
+ default:
+ retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
+ }
+- (void)oerr_cert(context, retval, &cert_ctx,
++ (void)oerr_cert(context, retval, cert_ctx,
+ _("Failed to verify received certificate"));
+ if (reqctx->received_cert == NULL)
+ strlcpy(buf, "(none)", sizeof(buf));
+@@ -1626,9 +1708,9 @@ cms_signeddata_verify(krb5_context conte
+ } else {
+ /* retrieve verified certificate chain */
+ if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9)
+- verified_chain = X509_STORE_CTX_get1_chain(&cert_ctx);
++ verified_chain = X509_STORE_CTX_get1_chain(cert_ctx);
+ }
+- X509_STORE_CTX_cleanup(&cert_ctx);
++ X509_STORE_CTX_free(cert_ctx);
+ if (i <= 0)
+ goto cleanup;
+ out = BIO_new(BIO_s_mem());
+@@ -1670,8 +1752,7 @@ cms_signeddata_verify(krb5_context conte
+ pkiDebug("CMS Verification successful\n");
+ else {
+ pkiDebug("wrong oid in eContentType\n");
+- print_buffer(etype->data,
+- (unsigned int)etype->length);
++ print_buffer(OBJ_get0_data(etype), OBJ_length(etype));
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "wrong oid\n");
+ goto cleanup;
+@@ -2442,6 +2523,7 @@ pkinit_alg_agility_kdf(krb5_context cont
+ krb5_data *other_info = NULL;
+ krb5_data *supp_pub_info = NULL;
+ krb5_algorithm_identifier alg_id;
++ EVP_MD_CTX *ctx = NULL;
+ const EVP_MD *(*EVP_func)(void);
+
+ /* initialize random_data here to make clean-up safe */
+@@ -2512,23 +2594,26 @@ pkinit_alg_agility_kdf(krb5_context cont
+ * - Increment counter (modulo 2^32)
+ */
+ for (counter = 1; counter <= reps; counter++) {
+- EVP_MD_CTX c;
+ uint s = 0;
+ uint32_t be_counter = htonl(counter);
+
+- EVP_MD_CTX_init(&c);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL) {
++ retval = KRB5_CRYPTO_INTERNAL;
++ goto cleanup;
++ }
+
+ /* - Compute Hashi = H(counter || Z || OtherInfo). */
+- if (0 == EVP_DigestInit(&c, EVP_func())) {
++ if (!EVP_DigestInit(ctx, EVP_func())) {
+ krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
+ "Call to OpenSSL EVP_DigestInit() returned an error.");
+ retval = KRB5_CRYPTO_INTERNAL;
+ goto cleanup;
+ }
+
+- if ((0 == EVP_DigestUpdate(&c, &be_counter, 4)) ||
+- (0 == EVP_DigestUpdate(&c, secret->data, secret->length)) ||
+- (0 == EVP_DigestUpdate(&c, other_info->data, other_info->length))) {
++ if (!EVP_DigestUpdate(ctx, &be_counter, 4) ||
++ !EVP_DigestUpdate(ctx, secret->data, secret->length) ||
++ !EVP_DigestUpdate(ctx, other_info->data, other_info->length)) {
+ krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
+ "Call to OpenSSL EVP_DigestUpdate() returned an error.");
+ retval = KRB5_CRYPTO_INTERNAL;
+@@ -2536,7 +2621,7 @@ pkinit_alg_agility_kdf(krb5_context cont
+ }
+
+ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
+- if (0 == EVP_DigestFinal(&c, (unsigned char *)(random_data.data + offset), &s)) {
++ if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
+ krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
+ "Call to OpenSSL EVP_DigestUpdate() returned an error.");
+ retval = KRB5_CRYPTO_INTERNAL;
+@@ -2545,13 +2630,16 @@ pkinit_alg_agility_kdf(krb5_context cont
+ offset += s;
+ assert(s == hash_len);
+
+- EVP_MD_CTX_cleanup(&c);
++ EVP_MD_CTX_free(ctx);
++ ctx = NULL;
+ }
+
+ retval = krb5_c_random_to_key(context, enctype, &random_data,
+ key_block);
+
+ cleanup:
++ EVP_MD_CTX_free(ctx);
++
+ /* If this has been an error, free the allocated key_block, if any */
+ if (retval) {
+ krb5_free_keyblock_contents(context, key_block);
+@@ -2597,38 +2685,22 @@ client_create_dh(krb5_context context,
+ unsigned char *buf = NULL;
+ int dh_err = 0;
+ ASN1_INTEGER *pub_key = NULL;
++ const BIGNUM *pubkey_bn, *p, *q, *g;
+
+ if (cryptoctx->dh == NULL) {
+- if ((cryptoctx->dh = DH_new()) == NULL)
+- goto cleanup;
+- if ((cryptoctx->dh->g = BN_new()) == NULL ||
+- (cryptoctx->dh->q = BN_new()) == NULL)
+- goto cleanup;
+-
+- switch(dh_size) {
+- case 1024:
+- pkiDebug("client uses 1024 DH keys\n");
+- cryptoctx->dh->p = get_rfc2409_prime_1024(NULL);
+- break;
+- case 2048:
+- pkiDebug("client uses 2048 DH keys\n");
+- cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime,
+- sizeof(pkinit_2048_dhprime), NULL);
+- break;
+- case 4096:
+- pkiDebug("client uses 4096 DH keys\n");
+- cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime,
+- sizeof(pkinit_4096_dhprime), NULL);
+- break;
+- default:
++ if (dh_size == 1024)
++ cryptoctx->dh = make_oakley_dh(oakley_1024, sizeof(oakley_1024));
++ else if (dh_size == 2048)
++ cryptoctx->dh = make_oakley_dh(oakley_2048, sizeof(oakley_2048));
++ else if (dh_size == 4096)
++ cryptoctx->dh = make_oakley_dh(oakley_4096, sizeof(oakley_4096));
++ if (cryptoctx->dh == NULL)
+ goto cleanup;
+- }
+-
+- BN_set_word((cryptoctx->dh->g), DH_GENERATOR_2);
+- BN_rshift1(cryptoctx->dh->q, cryptoctx->dh->p);
+ }
+
+ DH_generate_key(cryptoctx->dh);
++ DH_get0_key(cryptoctx->dh, &pubkey_bn, NULL);
++
+ DH_check(cryptoctx->dh, &dh_err);
+ if (dh_err != 0) {
+ pkiDebug("Warning: dh_check failed with %d\n", dh_err);
+@@ -2646,7 +2718,7 @@ client_create_dh(krb5_context context,
+ print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
+ #endif
+
+- DH_check_pub_key(cryptoctx->dh, cryptoctx->dh->pub_key, &dh_err);
++ DH_check_pub_key(cryptoctx->dh, pubkey_bn, &dh_err);
+ if (dh_err != 0) {
+ pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
+ goto cleanup;
+@@ -2656,8 +2728,8 @@ client_create_dh(krb5_context context,
+ /* aglo: usually we could just call i2d_DHparams to encode DH params
+ * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
+ */
+- retval = pkinit_encode_dh_params(cryptoctx->dh->p, cryptoctx->dh->g,
+- cryptoctx->dh->q, dh_params, dh_params_len);
++ DH_get0_pqg(cryptoctx->dh, &p, &q, &g);
++ retval = pkinit_encode_dh_params(p, g, q, dh_params, dh_params_len);
+ if (retval)
+ goto cleanup;
+
+@@ -2667,8 +2739,11 @@ client_create_dh(krb5_context context,
+ * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+ * data element
+ */
+- if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL)
++ pub_key = BN_to_ASN1_INTEGER(pubkey_bn, NULL);
++ if (pub_key == NULL) {
++ retval = ENOMEM;
+ goto cleanup;
++ }
+ *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+ if ((buf = *dh_pubkey = malloc(*dh_pubkey_len)) == NULL) {
+ retval = ENOMEM;
+@@ -2786,20 +2861,19 @@ server_check_dh(krb5_context context,
+ int minbits)
+ {
+ DH *dh = NULL;
+- unsigned char *tmp = NULL;
++ const BIGNUM *p;
+ int dh_prime_bits;
+ krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+
+- tmp = (unsigned char *)dh_params->data;
+- dh = DH_new();
+- dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
++ dh = decode_dh_params((uint8_t *)dh_params->data, dh_params->length);
+ if (dh == NULL) {
+ pkiDebug("failed to decode dhparams\n");
+ goto cleanup;
+ }
+
+ /* KDC SHOULD check to see if the key parameters satisfy its policy */
+- dh_prime_bits = BN_num_bits(dh->p);
++ DH_get0_pqg(dh, &p, NULL, NULL);
++ dh_prime_bits = BN_num_bits(p);
+ if (minbits && dh_prime_bits < minbits) {
+ pkiDebug("client sent dh params with %d bits, we require %d\n",
+ dh_prime_bits, minbits);
+@@ -2818,6 +2892,30 @@ cleanup:
+ return retval;
+ }
+
++/* Duplicate a DH handle (parameters only, not public or private key). */
++static DH *
++dup_dh_params(const DH *src)
++{
++ const BIGNUM *oldp, *oldq, *oldg;
++ BIGNUM *p = NULL, *q = NULL, *g = NULL;
++ DH *dh;
++
++ DH_get0_pqg(src, &oldp, &oldq, &oldg);
++ p = BN_dup(oldp);
++ q = BN_dup(oldq);
++ g = BN_dup(oldg);
++ dh = DH_new();
++ if (p == NULL || q == NULL || g == NULL || dh == NULL) {
++ BN_free(p);
++ BN_free(q);
++ BN_free(g);
++ DH_free(dh);
++ return NULL;
++ }
++ DH_set0_pqg(dh, p, q, g);
++ return dh;
++}
++
+ /* kdc's dh function */
+ krb5_error_code
+ server_process_dh(krb5_context context,
+@@ -2835,43 +2933,42 @@ server_process_dh(krb5_context context,
+ DH *dh = NULL, *dh_server = NULL;
+ unsigned char *p = NULL;
+ ASN1_INTEGER *pub_key = NULL;
++ BIGNUM *client_pubkey = NULL;
++ const BIGNUM *server_pubkey;
+
+ *dh_pubkey = *server_key = NULL;
+ *dh_pubkey_len = *server_key_len = 0;
+
+ /* get client's received DH parameters that we saved in server_check_dh */
+ dh = cryptoctx->dh;
+-
+- dh_server = DH_new();
++ dh_server = dup_dh_params(dh);
+ if (dh_server == NULL)
+ goto cleanup;
+- dh_server->p = BN_dup(dh->p);
+- dh_server->g = BN_dup(dh->g);
+- dh_server->q = BN_dup(dh->q);
+
+ /* decode client's public key */
+ p = data;
+ pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
+ if (pub_key == NULL)
+ goto cleanup;
+- dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL);
+- if (dh->pub_key == NULL)
++ client_pubkey = ASN1_INTEGER_to_BN(pub_key, NULL);
++ if (client_pubkey == NULL)
+ goto cleanup;
+ ASN1_INTEGER_free(pub_key);
+
+ if (!DH_generate_key(dh_server))
+ goto cleanup;
++ DH_get0_key(dh_server, &server_pubkey, NULL);
+
+ /* generate DH session key */
+ *server_key_len = DH_size(dh_server);
+ if ((*server_key = malloc(*server_key_len)) == NULL)
+ goto cleanup;
+- compute_dh(*server_key, *server_key_len, dh->pub_key, dh_server);
++ compute_dh(*server_key, *server_key_len, client_pubkey, dh_server);
+
+ #ifdef DEBUG_DH
+ print_dh(dh_server, "client&server's DH params\n");
+- print_pubkey(dh->pub_key, "client's pub_key=");
+- print_pubkey(dh_server->pub_key, "server's pub_key=");
++ print_pubkey(client_pubkey, "client's pub_key=");
++ print_pubkey(server_pubkey, "server's pub_key=");
+ pkiDebug("server computed key=");
+ print_buffer(*server_key, *server_key_len);
+ #endif
+@@ -2883,7 +2980,8 @@ server_process_dh(krb5_context context,
+ * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+ * data element
+ */
+- if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL)
++ pub_key = BN_to_ASN1_INTEGER(server_pubkey, NULL);
++ if (pub_key == NULL)
+ goto cleanup;
+ *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+ if ((p = *dh_pubkey = malloc(*dh_pubkey_len)) == NULL)
+@@ -2899,8 +2997,8 @@ server_process_dh(krb5_context context,
+ return retval;
+
+ cleanup:
+- if (dh_server != NULL)
+- DH_free(dh_server);
++ BN_free(client_pubkey);
++ DH_free(dh_server);
+ free(*dh_pubkey);
+ free(*server_key);
+
+@@ -2911,15 +3009,14 @@ int
+ pkinit_openssl_init()
+ {
+ /* Initialize OpenSSL. */
+- CRYPTO_malloc_init();
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ return 0;
+ }
+
+ static krb5_error_code
+-pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q,
+- unsigned char **buf, unsigned int *buf_len)
++pkinit_encode_dh_params(const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
++ uint8_t **buf, unsigned int *buf_len)
+ {
+ krb5_error_code retval = ENOMEM;
+ int bufsize = 0, r = 0;
+@@ -2963,8 +3060,78 @@ cleanup:
+ return retval;
+ }
+
++#if OPENSSL_VERSION_NUMBER >= 0x10100000L
++
++/*
++ * We need to decode DomainParameters from RFC 3279 section 2.3.3. We would
++ * like to just call d2i_DHxparams(), but Microsoft's implementation may omit
++ * the q value in violation of the RFC. Instead we must copy the internal
++ * structures and sequence declarations from dh_asn1.c, modified to make the q
++ * field optional.
++ */
++
++typedef struct {
++ ASN1_BIT_STRING *seed;
++ BIGNUM *counter;
++} int_dhvparams;
++
++typedef struct {
++ BIGNUM *p;
++ BIGNUM *q;
++ BIGNUM *g;
++ BIGNUM *j;
++ int_dhvparams *vparams;
++} int_dhx942_dh;
++
++ASN1_SEQUENCE(DHvparams) = {
++ ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
++ ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
++} static_ASN1_SEQUENCE_END_name(int_dhvparams, DHvparams)
++
++ASN1_SEQUENCE(DHxparams) = {
++ ASN1_SIMPLE(int_dhx942_dh, p, BIGNUM),
++ ASN1_SIMPLE(int_dhx942_dh, g, BIGNUM),
++ ASN1_OPT(int_dhx942_dh, q, BIGNUM),
++ ASN1_OPT(int_dhx942_dh, j, BIGNUM),
++ ASN1_OPT(int_dhx942_dh, vparams, DHvparams),
++} static_ASN1_SEQUENCE_END_name(int_dhx942_dh, DHxparams)
++
++static DH *
++decode_dh_params(const uint8_t *p, unsigned int len)
++{
++ int_dhx942_dh *params;
++ DH *dh;
++
++ dh = DH_new();
++ if (dh == NULL)
++ return NULL;
++
++ params = (int_dhx942_dh *)ASN1_item_d2i(NULL, &p, len,
++ ASN1_ITEM_rptr(DHxparams));
++ if (params == NULL) {
++ DH_free(dh);
++ return NULL;
++ }
++
++ /* Steal the p, q, and g values from dhparams for dh. Ignore j and
++ * vparams. */
++ DH_set0_pqg(dh, params->p, params->q, params->g);
++ params->p = params->q = params->g = NULL;
++ ASN1_item_free((ASN1_VALUE *)params, ASN1_ITEM_rptr(DHxparams));
++ return dh;
++}
++
++#else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
++
++/*
++ * Do the same decoding (except without decoding j and vparams or checking the
++ * sequence length) using the pre-OpenSSL-1.1 asn1_mac.h. Define an internal
++ * function in the form demanded by the macros, then wrap it for caller
++ * convenience.
++ */
++
+ static DH *
+-pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
++decode_dh_params_int(DH ** a, uint8_t **pp, unsigned int len)
+ {
+ ASN1_INTEGER ai, *aip = NULL;
+ long length = (long) len;
+@@ -2980,8 +3147,8 @@ pkinit_decode_dh_params(DH ** a, unsigne
+ if (aip == NULL)
+ return NULL;
+ else {
+- (*a)->p = ASN1_INTEGER_to_BN(aip, NULL);
+- if ((*a)->p == NULL)
++ ret->p = ASN1_INTEGER_to_BN(aip, NULL);
++ if (ret->p == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+@@ -2993,8 +3160,8 @@ pkinit_decode_dh_params(DH ** a, unsigne
+ if (aip == NULL)
+ return NULL;
+ else {
+- (*a)->g = ASN1_INTEGER_to_BN(aip, NULL);
+- if ((*a)->g == NULL)
++ ret->g = ASN1_INTEGER_to_BN(aip, NULL);
++ if (ret->g == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+@@ -3005,10 +3172,10 @@ pkinit_decode_dh_params(DH ** a, unsigne
+ }
+ M_ASN1_D2I_get_opt(aip, d2i_ASN1_INTEGER, V_ASN1_INTEGER);
+ if (aip == NULL || ai.data == NULL)
+- (*a)->q = NULL;
++ ret->q = NULL;
+ else {
+- (*a)->q = ASN1_INTEGER_to_BN(aip, NULL);
+- if ((*a)->q == NULL)
++ ret->q = ASN1_INTEGER_to_BN(aip, NULL);
++ if (ret->q == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+@@ -3022,6 +3189,16 @@ pkinit_decode_dh_params(DH ** a, unsigne
+
+ }
+
++static DH *
++decode_dh_params(const uint8_t *p, unsigned int len)
++{
++ uint8_t *ptr = (uint8_t *)p;
++
++ return decode_dh_params_int(NULL, &ptr, len);
++}
++
++#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
++
+ static krb5_error_code
+ pkinit_create_sequence_of_principal_identifiers(
+ krb5_context context,
+@@ -3139,27 +3316,25 @@ pkinit_create_td_dh_parameters(krb5_cont
+ krb5_pa_data **pa_data = NULL;
+ krb5_data *encoded_algId = NULL;
+ krb5_algorithm_identifier **algId = NULL;
++ const BIGNUM *p, *q, *g;
+
+ if (opts->dh_min_bits > 4096)
+ goto cleanup;
+
+ if (opts->dh_min_bits <= 1024) {
+- retval = pkinit_encode_dh_params(plg_cryptoctx->dh_1024->p,
+- plg_cryptoctx->dh_1024->g, plg_cryptoctx->dh_1024->q,
+- &buf1, &buf1_len);
++ DH_get0_pqg(plg_cryptoctx->dh_1024, &p, &q, &g);
++ retval = pkinit_encode_dh_params(p, g, q, &buf1, &buf1_len);
+ if (retval)
+ goto cleanup;
+ }
+ if (opts->dh_min_bits <= 2048) {
+- retval = pkinit_encode_dh_params(plg_cryptoctx->dh_2048->p,
+- plg_cryptoctx->dh_2048->g, plg_cryptoctx->dh_2048->q,
+- &buf2, &buf2_len);
++ DH_get0_pqg(plg_cryptoctx->dh_2048, &p, &q, &g);
++ retval = pkinit_encode_dh_params(p, g, q, &buf2, &buf2_len);
+ if (retval)
+ goto cleanup;
+ }
+- retval = pkinit_encode_dh_params(plg_cryptoctx->dh_4096->p,
+- plg_cryptoctx->dh_4096->g, plg_cryptoctx->dh_4096->q,
+- &buf3, &buf3_len);
++ DH_get0_pqg(plg_cryptoctx->dh_4096, &p, &q, &g);
++ retval = pkinit_encode_dh_params(p, g, q, &buf3, &buf3_len);
+ if (retval)
+ goto cleanup;
+
+@@ -3320,16 +3495,19 @@ pkinit_check_kdc_pkid(krb5_context conte
+ static int
+ pkinit_check_dh_params(DH *dh1, DH *dh2)
+ {
++ const BIGNUM *p1, *p2, *g1, *g2;
+
+- if (BN_cmp(dh1->p, dh2->p) != 0) {
++ DH_get0_pqg(dh1, &p1, NULL, &g1);
++ DH_get0_pqg(dh2, &p2, NULL, &g2);
++ if (BN_cmp(p1, p2) != 0) {
+ pkiDebug("p is not well-known group dhparameter\n");
+ return -1;
+ }
+- if (BN_cmp(dh1->g, dh2->g) != 0) {
++ if (BN_cmp(g1, g2) != 0) {
+ pkiDebug("bad g dhparameter\n");
+ return -1;
+ }
+- pkiDebug("good %d dhparams\n", BN_num_bits(dh1->p));
++ pkiDebug("good %d dhparams\n", BN_num_bits(p1));
+ return 0;
+ }
+
+@@ -3348,17 +3526,19 @@ pkinit_process_td_dh_params(krb5_context
+
+ while (algId[i] != NULL) {
+ DH *dh = NULL;
+- unsigned char *tmp = NULL;
++ const BIGNUM *p;
+ int dh_prime_bits = 0;
+
+ if (algId[i]->algorithm.length != dh_oid.length ||
+ memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
+ goto cleanup;
+
+- tmp = (unsigned char *)algId[i]->parameters.data;
+- dh = DH_new();
+- dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
+- dh_prime_bits = BN_num_bits(dh->p);
++ dh = decode_dh_params((uint8_t *)algId[i]->parameters.data,
++ algId[i]->parameters.length);
++ if (dh == NULL)
++ goto cleanup;
++ DH_get0_pqg(dh, &p, NULL, NULL);
++ dh_prime_bits = BN_num_bits(p);
+ pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
+ *new_dh_size, dh_prime_bits);
+ ok = check_dh_wellknown(cryptoctx, dh, dh_prime_bits);
+@@ -3416,15 +3596,9 @@ openssl_callback(int ok, X509_STORE_CTX
+ static int
+ openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
+ {
+- if (!ok) {
+- switch (ctx->error) {
+- case X509_V_ERR_UNABLE_TO_GET_CRL:
+- return 1;
+- default:
+- return 0;
+- }
+- }
+- return ok;
++ if (ok)
++ return ok;
++ return X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL;
+ }
+
+ static ASN1_OBJECT *
+@@ -3480,43 +3654,33 @@ wrap_signeddata(unsigned char *data, uns
+ }
+
+ static int
+-prepare_enc_data(unsigned char *indata,
+- int indata_len,
+- unsigned char **outdata,
++prepare_enc_data(const uint8_t *indata, int indata_len, uint8_t **outdata,
+ int *outdata_len)
+ {
+- int retval = -1;
+- ASN1_const_CTX c;
+- long length = indata_len;
+- int Ttag, Tclass;
+- long Tlen;
+-
+- c.pp = (const unsigned char **)&indata;
+- c.q = *(const unsigned char **)&indata;
+- c.error = ERR_R_NESTED_ASN1_ERROR;
+- c.p= *(const unsigned char **)&indata;
+- c.max = (length == 0)?0:(c.p+length);
+-
+- asn1_GetSequence(&c,&length);
+-
+- ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+- c.p += Tlen;
+- ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
++ int tag, class;
++ long tlen, slen;
++ const uint8_t *p = indata, *oldp;
+
+- asn1_const_Finish(&c);
++ if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
++ return EINVAL;
++ if (tag != V_ASN1_SEQUENCE)
++ return EINVAL;
+
+- *outdata = malloc((size_t)Tlen);
+- if (*outdata == NULL) {
+- retval = ENOMEM;
+- goto cleanup;
+- }
+- memcpy(*outdata, c.p, (size_t)Tlen);
+- *outdata_len = Tlen;
++ oldp = p;
++ if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
++ return EINVAL;
++ p += tlen;
++ slen -= (p - oldp);
+
+- retval = 0;
+-cleanup:
++ if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
++ return EINVAL;
+
+- return retval;
++ *outdata = malloc(tlen);
++ if (*outdata == NULL)
++ return ENOMEM;
++ memcpy(*outdata, p, tlen);
++ *outdata_len = tlen;
++ return 0;
+ }
+
+ #ifndef WITHOUT_PKCS11
+@@ -3813,10 +3977,8 @@ pkinit_find_private_key(pkinit_identity_
+ static krb5_error_code
+ pkinit_decode_data_fs(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+- unsigned char *data,
+- unsigned int data_len,
+- unsigned char **decoded_data,
+- unsigned int *decoded_data_len)
++ const uint8_t *data, unsigned int data_len,
++ uint8_t **decoded_data, unsigned int *decoded_data_len)
+ {
+ if (decode_data(decoded_data, decoded_data_len, data, data_len,
+ id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs,
+@@ -3856,15 +4018,14 @@ pkinit_C_Decrypt(pkinit_identity_crypto_
+ static krb5_error_code
+ pkinit_decode_data_pkcs11(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+- unsigned char *data,
+- unsigned int data_len,
+- unsigned char **decoded_data,
++ const uint8_t *data, unsigned int data_len,
++ uint8_t **decoded_data,
+ unsigned int *decoded_data_len)
+ {
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG len;
+ CK_MECHANISM mech;
+- unsigned char *cp;
++ uint8_t *cp;
+ int r;
+
+ if (pkinit_open_session(context, id_cryptoctx)) {
+@@ -3891,8 +4052,9 @@ pkinit_decode_data_pkcs11(krb5_context c
+ pkiDebug("session %p edata %p edata_len %d data %p datalen @%p %d\n",
+ (void *) id_cryptoctx->session, (void *) data, (int) data_len,
+ (void *) cp, (void *) &len, (int) len);
+- if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len,
+- cp, &len)) != CKR_OK) {
++ r = pkinit_C_Decrypt(id_cryptoctx, (CK_BYTE_PTR) data, (CK_ULONG) data_len,
++ cp, &len);
++ if (r != CKR_OK) {
+ pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r));
+ if (r == CKR_BUFFER_TOO_SMALL)
+ pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
+@@ -3909,10 +4071,8 @@ pkinit_decode_data_pkcs11(krb5_context c
+ krb5_error_code
+ pkinit_decode_data(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+- unsigned char *data,
+- unsigned int data_len,
+- unsigned char **decoded_data,
+- unsigned int *decoded_data_len)
++ const uint8_t *data, unsigned int data_len,
++ uint8_t **decoded_data, unsigned int *decoded_data_len)
+ {
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+@@ -4030,9 +4190,9 @@ pkinit_sign_data(krb5_context context,
+
+
+ static krb5_error_code
+-decode_data(unsigned char **out_data, unsigned int *out_data_len,
+- unsigned char *data, unsigned int data_len,
+- EVP_PKEY *pkey, X509 *cert)
++decode_data(uint8_t **out_data, unsigned int *out_data_len,
++ const uint8_t *data, unsigned int data_len, EVP_PKEY *pkey,
++ X509 *cert)
+ {
+ krb5_error_code retval = ENOMEM;
+ unsigned char *buf = NULL;
+@@ -4072,22 +4232,25 @@ create_signature(unsigned char **sig, un
+ unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
+ {
+ krb5_error_code retval = ENOMEM;
+- EVP_MD_CTX md_ctx;
++ EVP_MD_CTX *ctx;
+
+ if (pkey == NULL)
+ return retval;
+
+- EVP_VerifyInit(&md_ctx, EVP_sha1());
+- EVP_SignUpdate(&md_ctx, data, data_len);
++ ctx = EVP_MD_CTX_new();
++ if (ctx == NULL)
++ return ENOMEM;
++ EVP_SignInit(ctx, EVP_sha1());
++ EVP_SignUpdate(ctx, data, data_len);
+ *sig_len = EVP_PKEY_size(pkey);
+ if ((*sig = malloc(*sig_len)) == NULL)
+ goto cleanup;
+- EVP_SignFinal(&md_ctx, *sig, sig_len, pkey);
++ EVP_SignFinal(ctx, *sig, sig_len, pkey);
+
+ retval = 0;
+
+ cleanup:
+- EVP_MD_CTX_cleanup(&md_ctx);
++ EVP_MD_CTX_free(ctx);
+
+ return retval;
+ }
+@@ -5526,8 +5689,8 @@ create_identifiers_from_stack(STACK_OF(X
+ if (is == NULL)
+ goto oom;
+ X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
+- M_ASN1_INTEGER_free(is->serial);
+- is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x));
++ ASN1_INTEGER_free(is->serial);
++ is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
+ if (is->serial == NULL)
+ goto oom;
+ len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+@@ -5679,8 +5842,8 @@ create_issuerAndSerial(krb5_context cont
+
+ is = PKCS7_ISSUER_AND_SERIAL_new();
+ X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
+- M_ASN1_INTEGER_free(is->serial);
+- is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
++ ASN1_INTEGER_free(is->serial);
++ is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+ len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+ if ((p = *out = malloc((size_t) len)) == NULL)
+ goto cleanup;
+@@ -5855,10 +6018,10 @@ pkcs7_dataDecode(krb5_context context,
+ int tmp_ret = 0;
+ ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+ tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
+- cert->cert_info->issuer);
++ X509_get_issuer_name(cert));
+ if (!tmp_ret) {
+- tmp_ret = M_ASN1_INTEGER_cmp(cert->cert_info->serialNumber,
+- ri->issuer_and_serial->serial);
++ tmp_ret = ASN1_INTEGER_cmp(X509_get_serialNumber(cert),
++ ri->issuer_and_serial->serial);
+ if (!tmp_ret)
+ break;
+ }
+@@ -5878,8 +6041,8 @@ pkcs7_dataDecode(krb5_context context,
+ for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+ ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+ jj = pkinit_decode_data(context, id_cryptoctx,
+- M_ASN1_STRING_data(ri->enc_key),
+- (unsigned int) M_ASN1_STRING_length(ri->enc_key),
++ ASN1_STRING_get0_data(ri->enc_key),
++ ASN1_STRING_length(ri->enc_key),
+ &tmp, &tmp_len);
+ if (jj) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+@@ -5896,14 +6059,13 @@ pkcs7_dataDecode(krb5_context context,
+ }
+
+ if (ri == NULL) {
+- PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
+ goto cleanup;
+ }
+ }
+ else {
+ jj = pkinit_decode_data(context, id_cryptoctx,
+- M_ASN1_STRING_data(ri->enc_key),
+- (unsigned int) M_ASN1_STRING_length(ri->enc_key),
++ ASN1_STRING_get0_data(ri->enc_key),
++ ASN1_STRING_length(ri->enc_key),
+ &tmp, &tmp_len);
+ if (jj || tmp_len <= 0) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+@@ -5925,8 +6087,6 @@ pkcs7_dataDecode(krb5_context context,
+ * determined by the size of the decrypted RSA key.
+ */
+ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) {
+- PKCS7err(PKCS7_F_PKCS7_DATADECODE,
+- PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
+ goto cleanup;
+ }
+ }
+diff -up krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h.openssl11 krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
+--- krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h.openssl11 2016-09-13 21:59:45.000000000 +0200
++++ krb5-1.14.4/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h 2016-09-29 23:30:52.341207376 +0200
+@@ -42,11 +42,16 @@
+ #include <openssl/x509v3.h>
+ #include <openssl/err.h>
+ #include <openssl/evp.h>
+-#include <openssl/asn1_mac.h>
+ #include <openssl/sha.h>
+ #include <openssl/asn1.h>
+ #include <openssl/pem.h>
+
++#if OPENSSL_VERSION_NUMBER >= 0x10100000L
++#include <openssl/asn1t.h>
++#else
++#include <openssl/asn1_mac.h>
++#endif
++
+ #define DN_BUF_LEN 256
+ #define MAX_CREDS_ALLOWED 20
+
+@@ -129,8 +134,4 @@ struct _pkinit_cert_iter_data {
+ unsigned int index;
+ };
+
+-/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
+-#define ku_reject(x, usage) \
+- (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+-
+ #endif /* _PKINIT_CRYPTO_OPENSSL_H */
+diff -up krb5-1.14.4/src/plugins/tls/k5tls/openssl.c.openssl11 krb5-1.14.4/src/plugins/tls/k5tls/openssl.c
+--- krb5-1.14.4/src/plugins/tls/k5tls/openssl.c.openssl11 2016-09-13 21:59:45.000000000 +0200
++++ krb5-1.14.4/src/plugins/tls/k5tls/openssl.c 2016-09-29 23:30:43.882158131 +0200
+@@ -181,13 +181,13 @@ check_cert_address(X509 *x, const char *
+ struct in6_addr sin6;
+
+ /* Parse the IP address into an octet string. */
+- ip = M_ASN1_OCTET_STRING_new();
++ ip = ASN1_OCTET_STRING_new();
+ if (ip == NULL)
+ return FALSE;
+ if (inet_pton(AF_INET, text, &sin)) {
+- M_ASN1_OCTET_STRING_set(ip, &sin, sizeof(sin));
++ ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin, sizeof(sin));
+ } else if (inet_pton(AF_INET6, text, &sin6)) {
+- M_ASN1_OCTET_STRING_set(ip, &sin6, sizeof(sin6));
++ ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin6, sizeof(sin6));
+ } else {
+ ASN1_OCTET_STRING_free(ip);
+ return FALSE;
+@@ -317,7 +317,7 @@ verify_callback(int preverify_ok, X509_S
+ if (err != X509_V_OK) {
+ bio = BIO_new(BIO_s_mem());
+ if (bio != NULL) {
+- X509_NAME_print_ex(bio, x->cert_info->subject, 0, 0);
++ X509_NAME_print_ex(bio, X509_get_subject_name(x), 0, 0);
+ count = BIO_get_mem_data(bio, &cert);
+ errstr = X509_verify_cert_error_string(err);
+ TRACE_TLS_CERT_ERROR(context, depth, count, cert, err, errstr);
diff --git a/krb5.spec b/krb5.spec
index a3bc7db..8048a50 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -13,7 +13,7 @@
Summary: The Kerberos network authentication system
Name: krb5
Version: 1.14.4
-Release: 5%{?dist}
+Release: 6%{?dist}
# - Maybe we should explode from the now-available-to-everybody tarball instead?
# http://web.mit.edu/kerberos/dist/krb5/1.13/krb5-1.13.2-signed.tar
# - The sources below are stored in a lookaside cache. Upload with
@@ -69,6 +69,7 @@ Patch21: Rename-prng_os.c-to-prng_device.c.patch
Patch22: Add-getrandom-to-k5_get_os_entropy-using-syscall.patch
Patch23: Add-OS-prng-intended-for-use-with-getrandom.patch
Patch24: Properly-handle-EOF-condition-on-libkrad-sockets.patch
+Patch25: krb5-1.14.4-openssl11.patch
License: MIT
URL: http://web.mit.edu/kerberos/www/
@@ -723,6 +724,9 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
+* Tue Oct 11 2016 Tomáš Mráz <tmraz@redhat.com> - 1.14.4-6
+- rebuild with OpenSSL 1.1.0, added backported upstream patch
+
* Fri Sep 30 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.4-5
- Properly close krad sockets
- Resolves: #1380836