krb5 commit: Add libk5crypto support for OpenSSL 1.1.0

Greg Hudson ghudson at mit.edu
Thu Sep 22 22:17:42 EDT 2016


https://github.com/krb5/krb5/commit/32172bbf02b5bb8c8b2ffb7da553581ff56f3b75
commit 32172bbf02b5bb8c8b2ffb7da553581ff56f3b75
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Jun 17 12:00:21 2016 -0400

    Add libk5crypto support for OpenSSL 1.1.0
    
    OpenSSL 1.1.0 makes the EVP_MD_CTX, EVP_CIPH_CTX, and EVP_HMAC_CTX
    types opaque.  Change the libk5crypto OpenSSL code to work with
    OpenSSL 1.1 while retaining compatibility with previous versions.
    
    ticket: 8398 (new)

 src/lib/crypto/openssl/crypto_mod.h              |    8 ++++
 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        |   38 ++++++++++-------
 src/lib/crypto/openssl/enc_provider/des3.c       |   37 ++++++++++-------
 src/lib/crypto/openssl/enc_provider/rc4.c        |   50 +++++++++++-----------
 src/lib/crypto/openssl/hash_provider/hash_md4.c  |   15 ++++---
 src/lib/crypto/openssl/hash_provider/hash_md5.c  |   15 ++++---
 src/lib/crypto/openssl/hash_provider/hash_sha1.c |   15 ++++---
 src/lib/crypto/openssl/hmac.c                    |   42 ++++++++++++++++---
 src/lib/crypto/openssl/sha256.c                  |   14 ++++---
 11 files changed, 196 insertions(+), 114 deletions(-)

diff --git a/src/lib/crypto/openssl/crypto_mod.h b/src/lib/crypto/openssl/crypto_mod.h
index 56fb168..6f6badb 100644
--- a/src/lib/crypto/openssl/crypto_mod.h
+++ b/src/lib/crypto/openssl/crypto_mod.h
@@ -33,9 +33,17 @@
 #ifndef CRYPTO_MOD_H
 #define CRYPTO_MOD_H
 
+#include <openssl/crypto.h>
 #include <openssl/aes.h>
 #include <openssl/sha.h>
 
+/* 1.1 standardizes constructor and destructor names, renaming
+ * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#endif
+
 #define aes_ctx AES_KEY
 #define krb5int_aes_enc_key(k, len, ctx) AES_set_encrypt_key(k, 8*(len), ctx)
 #define krb5int_aes_enc_blk(in, out, ctx) AES_encrypt(in, out, ctx)
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
index 8afa1a7..6b4622f 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  *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 *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   *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 --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index 3ac3fd9..2da6913 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;
+    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 *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   *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 --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
index 1db5ef0..a662db5 100644
--- a/src/lib/crypto/openssl/enc_provider/des.c
+++ b/src/lib/crypto/openssl/enc_provider/des.c
@@ -82,26 +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;
+    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_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(ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
@@ -127,27 +130,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;
+    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_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(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..1c439c2 100644
--- a/src/lib/crypto/openssl/enc_provider/des3.c
+++ b/src/lib/crypto/openssl/enc_provider/des3.c
@@ -81,27 +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;
+    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_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(ctx);
 
     zap(iblock, sizeof(iblock));
     zap(oblock, sizeof(oblock));
@@ -127,26 +130,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;
+    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_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(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..7f3c086 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -36,15 +36,14 @@
 #include <openssl/evp.h>
 
 /*
- * The loopback field is NULL if ctx is uninitialized (no encrypt or decrypt
- * operation has taken place), or a pointer to the structure address if ctx is
- * initialized.  If the application copies the state (not a valid operation,
- * but one which happens to works with some other enc providers), we can detect
- * it via the loopback field and return a sane error code.
+ * The loopback field is a pointer to the structure.  If the application copies
+ * the state (not a valid operation, but one which happens to works with some
+ * other enc providers), we can detect it via the loopback field and return a
+ * sane error code.
  */
 struct arcfour_state {
     struct arcfour_state *loopback;
-    EVP_CIPHER_CTX ctx;
+    EVP_CIPHER_CTX *ctx;
 };
 
 #define RC4_KEY_SIZE 16
@@ -64,26 +63,30 @@ k5_arcfour_docrypt(krb5_key key,const 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;
+    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 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);
+    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_keyblock *key,
     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 --git a/src/lib/crypto/openssl/hash_provider/hash_md4.c b/src/lib/crypto/openssl/hash_provider/hash_md4.c
index 0fc1a34..37cf72f 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_md4.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_md4.c
@@ -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 --git a/src/lib/crypto/openssl/hash_provider/hash_md5.c b/src/lib/crypto/openssl/hash_provider/hash_md5.c
index 5c1b3a9..29e7c4b 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_md5.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_md5.c
@@ -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 --git a/src/lib/crypto/openssl/hash_provider/hash_sha1.c b/src/lib/crypto/openssl/hash_provider/hash_sha1.c
index cdfed55..99d1d2f 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_sha1.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_sha1.c
@@ -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 --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index 926790a..b9cbd9b 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -55,6 +55,33 @@
 #include <openssl/hmac.h>
 #include <openssl/evp.h>
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+/* OpenSSL 1.1 makes HMAC_CTX opaque, while 1.0 does not have pointer
+ * constructors or destructors. */
+
+#define HMAC_CTX_new compat_hmac_ctx_new
+static HMAC_CTX *
+compat_hmac_ctx_new()
+{
+    HMAC_CTX *ctx;
+
+    ctx = calloc(1, sizeof(*ctx));
+    if (ctx != NULL)
+        HMAC_CTX_init(ctx);
+    return ctx;
+}
+
+#define HMAC_CTX_free compat_hmac_ctx_free
+static void
+compat_hmac_ctx_free(HMAC_CTX *ctx)
+{
+    HMAC_CTX_cleanup(ctx);
+    free(ctx);
+}
+
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
 /*
  * the HMAC transform looks like:
  *
@@ -88,7 +115,7 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
 {
     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_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));
+    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 --git a/src/lib/crypto/openssl/sha256.c b/src/lib/crypto/openssl/sha256.c
index 395433f..fa095d4 100644
--- a/src/lib/crypto/openssl/sha256.c
+++ b/src/lib/crypto/openssl/sha256.c
@@ -36,13 +36,15 @@
 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 == NULL)
+        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;
 }


More information about the cvs-krb5 mailing list