[PATCH] Add support for new openssl-1.1.0 APIs

Pádraig Brady pbrady at fb.com
Tue Apr 26 19:25:27 EDT 2016


openssl-1.1.0 made HMAC_CTX, EVP_MD_CTX, and EVP_CIPHER_CTX
opaque types, therefore adjust how we use these interfaces accordingly,
while also being backwards compatible with the older interfaces.
Note EVP_CIPHER_CTX_{new,free} have been available since openssl-0.9.8
and since krb5 already enforces that version or later we just
use those new interfaces unconditionally.
---
 src/configure.in                                   |  4 ++
 src/include/k5-platform.h                          | 13 ++++
 src/lib/crypto/openssl/enc_provider/aes.c          | 38 +++++++----
 src/lib/crypto/openssl/enc_provider/camellia.c     | 38 +++++++----
 src/lib/crypto/openssl/enc_provider/des.c          | 36 ++++++----
 src/lib/crypto/openssl/enc_provider/des3.c         | 36 ++++++----
 src/lib/crypto/openssl/enc_provider/rc4.c          | 29 +++++---
 src/lib/crypto/openssl/hash_provider/hash_md4.c    | 19 ++++--
 src/lib/crypto/openssl/hash_provider/hash_md5.c    | 19 ++++--
 src/lib/crypto/openssl/hash_provider/hash_sha1.c   | 19 ++++--
 src/lib/crypto/openssl/hmac.c                      | 25 +++++--
 src/lib/crypto/openssl/sha256.c                    | 15 +++--
 src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 78 ++++++++++++++--------
 13 files changed, 243 insertions(+), 126 deletions(-)

diff --git a/src/configure.in b/src/configure.in
index 8216045..e032fc9 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -280,6 +280,10 @@ builtin|openssl)
   AC_CHECK_LIB(crypto, CMS_get0_content,
                [AC_DEFINE([HAVE_OPENSSL_CMS], 1,
                           [Define if OpenSSL supports cms.])])
+  AC_CHECK_TYPES([HMAC_CTX, EVP_MD_CTX], [], [], [[
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+  ]])
   ;;
 nss)
   if test "${PKINIT_CRYPTO_IMPL_CFLAGS+set}" != set; then
diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
index 994f463..013606d 100644
--- a/src/include/k5-platform.h
+++ b/src/include/k5-platform.h
@@ -1099,4 +1099,17 @@ extern int k5_getopt_long(int nargc, char **nargv, char *options,
 #define getopt_long k5_getopt_long
 #endif /* HAVE_GETOPT_LONG */
 
+/*
+ * Compatibility for changed APIs in openssl-1.1.0.
+ * Pre openssl-1.1.0 will have these defined.
+ */
+#if HAVE_HMAC_CTX
+# define HMAC_CTX_free HMAC_CTX_cleanup
+#endif /* HAVE_HMAC_CTX */
+
+#if HAVE_EVP_MD_CTX
+# define EVP_MD_CTX_new() EVP_MD_CTX_create()
+# define EVP_MD_CTX_free(x) EVP_MD_CTX_destroy(x)
+#endif /* HAVE_EVP_MD_CTX */
+
 #endif /* K5_PLATFORM_H */
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
index 8afa1a7..7ad9d41 100644
--- a/src/lib/crypto/openssl/enc_provider/aes.c
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
@@ -65,22 +65,27 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
 {
     int             ret, olen = BLOCK_SIZE;
     unsigned char   iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
-    EVP_CIPHER_CTX  ciph_ctx;
+    EVP_CIPHER_CTX  *ciph_ctx;
     struct iov_cursor cursor;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
-    ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
+
+    ret = EVP_EncryptInit_ex(ciph_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(ciph_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(ciph_ctx,0);
+    ret = EVP_EncryptUpdate(ciph_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(ciph_ctx);
 
     zap(iblock, BLOCK_SIZE);
     zap(oblock, BLOCK_SIZE);
@@ -94,22 +99,27 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
 {
     int              ret = 0, olen = BLOCK_SIZE;
     unsigned char    iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
-    EVP_CIPHER_CTX   ciph_ctx;
+    EVP_CIPHER_CTX   *ciph_ctx;
     struct iov_cursor cursor;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
-    ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
+
+    ret = EVP_DecryptInit_ex(ciph_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(ciph_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(ciph_ctx,0);
+    ret = EVP_DecryptUpdate(ciph_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(ciph_ctx);
 
     zap(iblock, BLOCK_SIZE);
     zap(oblock, BLOCK_SIZE);
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index 3ac3fd9..66ba95a 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -89,22 +89,27 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
 {
     int             ret, olen = BLOCK_SIZE;
     unsigned char   iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
-    EVP_CIPHER_CTX  ciph_ctx;
     struct iov_cursor cursor;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
-    ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
+    EVP_CIPHER_CTX* ciph_ctx;
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
+
+    ret = EVP_EncryptInit_ex(ciph_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(ciph_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(ciph_ctx,0);
+    ret = EVP_EncryptUpdate(ciph_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(ciph_ctx);
 
     zap(iblock, BLOCK_SIZE);
     zap(oblock, BLOCK_SIZE);
@@ -118,22 +123,27 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
 {
     int              ret = 0, olen = BLOCK_SIZE;
     unsigned char    iblock[BLOCK_SIZE], oblock[BLOCK_SIZE];
-    EVP_CIPHER_CTX   ciph_ctx;
     struct iov_cursor cursor;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
-    ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length),
+    EVP_CIPHER_CTX* ciph_ctx;
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
+
+    ret = EVP_DecryptInit_ex(ciph_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(ciph_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(ciph_ctx,0);
+    ret = EVP_DecryptUpdate(ciph_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(ciph_ctx);
 
     zap(iblock, BLOCK_SIZE);
     zap(oblock, BLOCK_SIZE);
diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
index 1db5ef0..2f3ff43 100644
--- a/src/lib/crypto/openssl/enc_provider/des.c
+++ b/src/lib/crypto/openssl/enc_provider/des.c
@@ -82,25 +82,29 @@ k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     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;
     krb5_boolean empty;
+    EVP_CIPHER_CTX *ciph_ctx;
 
     ret = validate(key, ivec, data, num_data, &empty);
     if (ret != 0 || empty)
         return ret;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
 
-    ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
+    ret = EVP_EncryptInit_ex(ciph_ctx, EVP_des_cbc(), NULL,
                              key->keyblock.contents, (ivec && ivec->data) ? (unsigned char*)ivec->data : NULL);
-    if (!ret)
+    if (!ret) {
+        EVP_CIPHER_CTX_free(ciph_ctx);
         return KRB5_CRYPTO_INTERNAL;
+    }
 
-    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+    EVP_CIPHER_CTX_set_padding(ciph_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,
+        ret = EVP_EncryptUpdate(ciph_ctx, oblock, &olen,
                                 (unsigned char *)iblock, DES_BLOCK_SIZE);
         if (!ret)
             break;
@@ -110,7 +114,7 @@ k5_des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     if (ivec != NULL)
         memcpy(ivec->data, oblock, DES_BLOCK_SIZE);
 
-    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+    EVP_CIPHER_CTX_free(ciph_ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
@@ -127,26 +131,30 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     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;
     krb5_boolean empty;
+    EVP_CIPHER_CTX *ciph_ctx;
 
     ret = validate(key, ivec, data, num_data, &empty);
     if (ret != 0 || empty)
         return ret;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
 
-    ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
+    ret = EVP_DecryptInit_ex(ciph_ctx, EVP_des_cbc(), NULL,
                              key->keyblock.contents,
                              (ivec) ? (unsigned char*)ivec->data : NULL);
-    if (!ret)
+    if (!ret) {
+        EVP_CIPHER_CTX_free(ciph_ctx);
         return KRB5_CRYPTO_INTERNAL;
+    }
 
-    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+    EVP_CIPHER_CTX_set_padding(ciph_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,
+        ret = EVP_DecryptUpdate(ciph_ctx, oblock, &olen,
                                 iblock, DES_BLOCK_SIZE);
         if (!ret)
             break;
@@ -156,7 +164,7 @@ k5_des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     if (ivec != NULL)
         memcpy(ivec->data, iblock, DES_BLOCK_SIZE);
 
-    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+    EVP_CIPHER_CTX_free(ciph_ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
index d531f10..23dd34a 100644
--- a/src/lib/crypto/openssl/enc_provider/des3.c
+++ b/src/lib/crypto/openssl/enc_provider/des3.c
@@ -81,26 +81,30 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     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;
     krb5_boolean empty;
+    EVP_CIPHER_CTX *ciph_ctx;
 
     ret = validate(key, ivec, data, num_data, &empty);
     if (ret != 0 || empty)
         return ret;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
 
-    ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
+    ret = EVP_EncryptInit_ex(ciph_ctx, EVP_des_ede3_cbc(), NULL,
                              key->keyblock.contents,
                              (ivec) ? (unsigned char*)ivec->data : NULL);
-    if (!ret)
+    if (!ret) {
+        EVP_CIPHER_CTX_free(ciph_ctx);
         return KRB5_CRYPTO_INTERNAL;
+    }
 
-    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+    EVP_CIPHER_CTX_set_padding(ciph_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,
+        ret = EVP_EncryptUpdate(ciph_ctx, oblock, &olen,
                                 (unsigned char *)iblock, DES3_BLOCK_SIZE);
         if (!ret)
             break;
@@ -110,7 +114,7 @@ k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     if (ivec != NULL)
         memcpy(ivec->data, oblock, DES3_BLOCK_SIZE);
 
-    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+    EVP_CIPHER_CTX_free(ciph_ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
@@ -127,26 +131,30 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     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;
     krb5_boolean empty;
+    EVP_CIPHER_CTX *ciph_ctx;
 
     ret = validate(key, ivec, data, num_data, &empty);
     if (ret != 0 || empty)
         return ret;
 
-    EVP_CIPHER_CTX_init(&ciph_ctx);
+    ciph_ctx = EVP_CIPHER_CTX_new();
+    if (!ciph_ctx)
+        return KRB5_CRYPTO_INTERNAL;
 
-    ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
+    ret = EVP_DecryptInit_ex(ciph_ctx, EVP_des_ede3_cbc(), NULL,
                              key->keyblock.contents,
                              (ivec) ? (unsigned char*)ivec->data : NULL);
-    if (!ret)
+    if (!ret) {
+        EVP_CIPHER_CTX_free(ciph_ctx);
         return KRB5_CRYPTO_INTERNAL;
+    }
 
-    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+    EVP_CIPHER_CTX_set_padding(ciph_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(ciph_ctx, oblock, &olen,
                                 (unsigned char *)iblock, DES3_BLOCK_SIZE);
         if (!ret)
             break;
@@ -156,7 +164,7 @@ k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
     if (ivec != NULL)
         memcpy(ivec->data, iblock, DES3_BLOCK_SIZE);
 
-    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+    EVP_CIPHER_CTX_free(ciph_ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index a8db754..fdbf1bd 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -44,7 +44,7 @@
  */
 struct arcfour_state {
     struct arcfour_state *loopback;
-    EVP_CIPHER_CTX ctx;
+    EVP_CIPHER_CTX *ctx;
 };
 
 #define RC4_KEY_SIZE 16
@@ -64,26 +64,33 @@ k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
     size_t i;
     int ret = 1, tmp_len = 0;
     krb5_crypto_iov *iov     = NULL;
-    EVP_CIPHER_CTX  ciph_ctx, *ctx;
     struct arcfour_state *arcstate;
     krb5_boolean do_init = TRUE;
+    EVP_CIPHER_CTX *ctx;
 
     arcstate = (state != NULL) ? (struct arcfour_state *) state->data : NULL;
     if (arcstate != NULL) {
-        ctx = &arcstate->ctx;
+        ctx = arcstate->ctx;
+        if (!ctx)
+            return KRB5_CRYPTO_INTERNAL;
         if (arcstate->loopback == arcstate)
             do_init = FALSE;
         else if (arcstate->loopback != NULL)
             return KRB5_CRYPTO_INTERNAL;
     } else {
-        ctx = &ciph_ctx;
+        ctx = EVP_CIPHER_CTX_new();
+        if (!ctx)
+            return KRB5_CRYPTO_INTERNAL;
     }
+
     if (do_init) {
-        EVP_CIPHER_CTX_init(ctx);
         ret = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, key->keyblock.contents,
                                  NULL);
-        if (!ret)
+        if (!ret) {
+            if (!arcstate)		/* free just created context.  */
+                EVP_CIPHER_CTX_free(ctx);
             return KRB5_CRYPTO_INTERNAL;
+        }
     }
 
     for (i = 0; i < num_data; i++) {
@@ -101,7 +108,7 @@ k5_arcfour_docrypt(krb5_key key,const krb5_data *state, krb5_crypto_iov *data,
     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);
+        EVP_CIPHER_CTX_free(ctx);
 
     if (!ret)
         return KRB5_CRYPTO_INTERNAL;
@@ -114,9 +121,8 @@ 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);
+    if (arcstate->ctx)
+        EVP_CIPHER_CTX_free(arcstate->ctx);
     free(arcstate);
 }
 
@@ -131,6 +137,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
     if (arcstate == NULL)
         return ENOMEM;
     arcstate->loopback = NULL;
+    arcstate->ctx = EVP_CIPHER_CTX_new();
+    if (!arcstate->ctx)
+        return ENOMEM;
     new_state->data = (char *) arcstate;
     new_state->length = sizeof(*arcstate);
     return 0;
diff --git a/src/lib/crypto/openssl/hash_provider/hash_md4.c b/src/lib/crypto/openssl/hash_provider/hash_md4.c
index 0fc1a34..931897e 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_md4.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_md4.c
@@ -32,21 +32,26 @@
 static krb5_error_code
 k5_md4_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
 {
-    EVP_MD_CTX ctx;
     unsigned int i;
 
-    if (output->length != MD4_DIGEST_LENGTH)
+    EVP_MD_CTX *ctx;
+    ctx = EVP_MD_CTX_new();
+    if (!ctx)
         return KRB5_CRYPTO_INTERNAL;
 
-    EVP_MD_CTX_init(&ctx);
-    EVP_DigestInit_ex(&ctx, EVP_md4(), NULL);
+    if (output->length != MD4_DIGEST_LENGTH) {
+        EVP_MD_CTX_free(ctx);
+        return KRB5_CRYPTO_INTERNAL;
+    }
+
+    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, (unsigned char *)d->data, d->length);
     }
-    EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
-    EVP_MD_CTX_cleanup(&ctx);
+    EVP_DigestFinal_ex(ctx, (unsigned char *)output->data, NULL);
+    EVP_MD_CTX_free(ctx);
     return 0;
 }
 
diff --git a/src/lib/crypto/openssl/hash_provider/hash_md5.c b/src/lib/crypto/openssl/hash_provider/hash_md5.c
index 5c1b3a9..80d9438 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_md5.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_md5.c
@@ -32,21 +32,26 @@
 static krb5_error_code
 k5_md5_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
 {
-    EVP_MD_CTX ctx;
     unsigned int i;
 
-    if (output->length != MD5_DIGEST_LENGTH)
+    EVP_MD_CTX *ctx;
+    ctx = EVP_MD_CTX_new();
+    if (!ctx)
         return KRB5_CRYPTO_INTERNAL;
 
-    EVP_MD_CTX_init(&ctx);
-    EVP_DigestInit_ex(&ctx, EVP_md5(), NULL);
+    if (output->length != MD5_DIGEST_LENGTH) {
+        EVP_MD_CTX_free(ctx);
+        return KRB5_CRYPTO_INTERNAL;
+    }
+
+    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, (unsigned char *)d->data, d->length);
     }
-    EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
-    EVP_MD_CTX_cleanup(&ctx);
+    EVP_DigestFinal_ex(ctx, (unsigned char *)output->data, NULL);
+    EVP_MD_CTX_free(ctx);
     return 0;
 }
 
diff --git a/src/lib/crypto/openssl/hash_provider/hash_sha1.c b/src/lib/crypto/openssl/hash_provider/hash_sha1.c
index cdfed55..894608f 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_sha1.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_sha1.c
@@ -33,21 +33,26 @@
 static krb5_error_code
 k5_sha1_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
 {
-    EVP_MD_CTX ctx;
     unsigned int i;
 
-    if (output->length != SHA_DIGEST_LENGTH)
+    EVP_MD_CTX *ctx;
+    ctx = EVP_MD_CTX_new();
+    if (!ctx)
         return KRB5_CRYPTO_INTERNAL;
 
-    EVP_MD_CTX_init(&ctx);
-    EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+    if (output->length != SHA_DIGEST_LENGTH) {
+        EVP_MD_CTX_free(ctx);
+        return KRB5_CRYPTO_INTERNAL;
+    }
+
+    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, (unsigned char *)d->data, d->length);
     }
-    EVP_DigestFinal_ex(&ctx, (unsigned char *)output->data, NULL);
-    EVP_MD_CTX_cleanup(&ctx);
+    EVP_DigestFinal_ex(ctx, (unsigned char *)output->data, NULL);
+    EVP_MD_CTX_free(ctx);
     return 0;
 }
 
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index 926790a..f4fd780 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -88,7 +88,12 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
 {
     unsigned int i = 0, md_len = 0;
     unsigned char md[EVP_MAX_MD_SIZE];
-    HMAC_CTX c;
+
+    HMAC_CTX *c;
+#if HAVE_HMAC_CTX
+    HMAC_CTX hmac_ctx;
+#endif
+
     size_t hashsize, blocksize;
 
     hashsize = hash->hashsize;
@@ -102,20 +107,28 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
     if (!map_digest(hash))
         return(KRB5_CRYPTO_INTERNAL); // unsupported alg
 
-    HMAC_CTX_init(&c);
-    HMAC_Init(&c, keyblock->contents, keyblock->length, map_digest(hash));
+#if HAVE_HMAC_CTX
+    c = &hmac_ctx;
+    HMAC_CTX_init(c);
+#else
+    c = HMAC_CTX_new();
+    if (!c)
+        return KRB5_CRYPTO_INTERNAL;
+#endif
+
+    HMAC_Init(c, 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(c, (unsigned char*) iov->data.data, iov->data.length);
     }
-    HMAC_Final(&c,(unsigned char *)md, &md_len);
+    HMAC_Final(c,(unsigned char *)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(c);
     return 0;
 
 
diff --git a/src/lib/crypto/openssl/sha256.c b/src/lib/crypto/openssl/sha256.c
index 395433f..da5d227 100644
--- a/src/lib/crypto/openssl/sha256.c
+++ b/src/lib/crypto/openssl/sha256.c
@@ -36,13 +36,16 @@
 krb5_error_code
 k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN])
 {
-    EVP_MD_CTX ctx;
+    EVP_MD_CTX *ctx;
     int ok;
 
-    EVP_MD_CTX_init(&ctx);
-    ok = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL);
-    ok = ok && EVP_DigestUpdate(&ctx, in->data, in->length);
-    ok = ok && EVP_DigestFinal_ex(&ctx, out, NULL);
-    EVP_MD_CTX_cleanup(&ctx);
+    ctx = EVP_MD_CTX_new();
+    if (!ctx)
+        return ENOMEM;
+
+    ok = EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
+    ok = ok && EVP_DigestUpdate(ctx, in->data, in->length);
+    ok = ok && EVP_DigestFinal_ex(ctx, out, NULL);
+    EVP_MD_CTX_free(ctx);
     return ok ? 0 : ENOMEM;
 }
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index d5e2769..c27cc17 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -1072,7 +1072,6 @@ cms_signeddata_create(krb5_context context,
     unsigned char *p;
     STACK_OF(X509) * cert_stack = NULL;
     ASN1_OCTET_STRING *digest_attr = NULL;
-    EVP_MD_CTX ctx, ctx2;
     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;
@@ -1186,13 +1185,21 @@ cms_signeddata_create(krb5_context context,
             abuf = data;
             alen = data_len;
         } else {
+            EVP_MD_CTX *ctx;
+            ctx = EVP_MD_CTX_new();
+            if (!ctx) {
+                retval = ENOMEM;
+                goto cleanup2;
+            }
+
             /* 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);
+            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();
@@ -1226,15 +1233,24 @@ cms_signeddata_create(krb5_context context,
          */
         if (id_cryptoctx->pkcs11_method == 1 &&
             id_cryptoctx->mech == CKM_RSA_PKCS) {
+
+            EVP_MD_CTX *ctx;
+            ctx = EVP_MD_CTX_new();
+            if (!ctx) {
+                retval = ENOMEM;
+                goto cleanup2;
+            }
+
             pkiDebug("mech = CKM_RSA_PKCS\n");
-            EVP_MD_CTX_init(&ctx2);
             /* 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)
@@ -1338,12 +1354,9 @@ cms_signeddata_create(krb5_context context,
 
 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);
@@ -2512,40 +2525,47 @@ pkinit_alg_agility_kdf(krb5_context context,
      *     -   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);
+        EVP_MD_CTX *ctx;
+        ctx = EVP_MD_CTX_new();
+        if (!ctx) {
+            retval = ENOMEM;
+            goto cleanup;
+        }
 
         /* -   Compute Hashi = H(counter || Z || OtherInfo). */
-        if (0 == EVP_DigestInit(&c, EVP_func())) {
+        if (0 == EVP_DigestInit(ctx, EVP_func())) {
             krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
                                    "Call to OpenSSL EVP_DigestInit() returned an error.");
+            EVP_MD_CTX_free(ctx);
             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 ((0 == EVP_DigestUpdate(ctx, &be_counter, 4)) ||
+            (0 == EVP_DigestUpdate(ctx, secret->data, secret->length)) ||
+            (0 == 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.");
+            EVP_MD_CTX_free(ctx);
             retval = KRB5_CRYPTO_INTERNAL;
             goto cleanup;
         }
 
         /* 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 (0 == EVP_DigestFinal(ctx, (unsigned char *)(random_data.data + offset), &s)) {
             krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
                                    "Call to OpenSSL EVP_DigestUpdate() returned an error.");
+            EVP_MD_CTX_free(ctx);
             retval = KRB5_CRYPTO_INTERNAL;
             goto cleanup;
         }
         offset += s;
         assert(s == hash_len);
 
-        EVP_MD_CTX_cleanup(&c);
+        EVP_MD_CTX_free(ctx);
     }
 
     retval = krb5_c_random_to_key(context, enctype, &random_data,
@@ -4072,22 +4092,26 @@ create_signature(unsigned char **sig, unsigned int *sig_len,
                  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)
+        return retval;
+
+    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;
 }
-- 
2.5.5



More information about the krbdev mailing list