From 895d0bdfea59408674c84f07a8ce9382e616e449 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 11 Oct 2016 14:04:59 +0200 Subject: [PATCH] rebuild with OpenSSL 1.1.0, added backported upstream patch --- krb5-1.14.4-openssl11.patch | 1940 +++++++++++++++++++++++++++++++++++ krb5.spec | 6 +- 2 files changed, 1945 insertions(+), 1 deletion(-) create mode 100644 krb5-1.14.4-openssl11.patch 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 +-#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 + #include + #include + ++/* 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 + + /* +- * 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 + #include + ++#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; ienc_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 + #include + #include +-#include + #include + #include + #include + ++#if OPENSSL_VERSION_NUMBER >= 0x10100000L ++#include ++#else ++#include ++#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 - 1.14.4-6 +- rebuild with OpenSSL 1.1.0, added backported upstream patch + * Fri Sep 30 2016 Robbie Harwood - 1.14.4-5 - Properly close krad sockets - Resolves: #1380836