Print this page
8982 Support building with OpenSSL 1.1

@@ -29,10 +29,11 @@
  */
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  */
 
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>

@@ -367,10 +368,105 @@
     0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
     0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 };
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+/*
+ * Many things have changed in OpenSSL 1.1. The code in this file has been
+ * updated to use the v1.1 APIs but some are new and require emulation
+ * for older OpenSSL versions.
+ */
+
+/* EVP_MD_CTX construct and destructor names have changed */
+
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+
+/* ASN1_STRING_data is deprecated */
+#define ASN1_STRING_get0_data ASN1_STRING_data
+
+/* X509_STORE_CTX_trusted_stack is deprecated */
+#define X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_trusted_stack
+
+/* get_rfc2409_prime_1024() has been renamed. */
+#define BN_get_rfc2409_prime_1024 get_rfc2409_prime_1024
+
+#define OBJ_get0_data(o) ((o)->data)
+#define OBJ_length(o) ((o)->length)
+
+/* Some new DH functions that aren't in OpenSSL 1.0.x */
+#define DH_bits(dh) BN_num_bits((dh)->p);
+
+#define DH_set0_pqg(dh, p, q, g) __DH_set0_pqg(dh, p, q, g)
+static int
+__DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(dh->p);
+        dh->p = p;
+    }
+    if (q != NULL) {
+        BN_free(dh->q);
+        dh->q = q;
+    }
+    if (g != NULL) {
+        BN_free(dh->g);
+        dh->g = g;
+    }
+
+    if (q != NULL) {
+        dh->length = BN_num_bits(q);
+    }
+
+    return 1;
+}
+
+#define DH_get0_pqg(dh, p, q, g) __DH_get0_pqg(dh, p, q, g)
+static void
+__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_set0_key(dh, pub, priv) __DH_set0_key(dh, pub, priv)
+static int
+__DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    if (pub_key != NULL) {
+        BN_free(dh->pub_key);
+        dh->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(dh->priv_key);
+        dh->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+#define DH_get0_key(dh, pub, priv) __DH_get0_key(dh, pub, priv)
+static void
+__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;
+}
+
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
 /* Solaris Kerberos */
 static k5_mutex_t oids_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
 static int pkinit_oids_refs = 0;
 
 krb5_error_code

@@ -654,52 +750,74 @@
         return;
 
     /* Only call OBJ_cleanup once! */
     /* Solaris Kerberos: locking */
     k5_mutex_lock(&oids_mutex);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+    /*
+     * In OpenSSL versions prior to 1.1.0, OBJ_cleanup() cleaned up OpenSSL's
+     * internal object table. This function is deprecated in version 1.1.0.
+     * No explicit de-initialisation is now required.
+     */
     if (--pkinit_oids_refs == 0)
         OBJ_cleanup();
+#else
+    pkinit_oids_refs--;
+#endif
     k5_mutex_unlock(&oids_mutex);
 }
 
+/* Construct an OpenSSL DH object for an Oakley group. */
+static DH *
+make_dhprime(uint8_t *prime, size_t len)
+{
+    DH *dh = NULL;
+    BIGNUM *p = NULL, *q = NULL, *g = NULL;
+
+    if ((p = BN_bin2bn(prime, len, NULL)) == NULL)
+        goto cleanup;
+    if ((q = BN_new()) == NULL)
+        goto cleanup;
+    if (!BN_rshift1(q, p))
+        goto cleanup;
+    if ((g = BN_new()) == 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_dhprime(pkinit_1024_dhprime,
+        sizeof(pkinit_1024_dhprime));
     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_dhprime(pkinit_2048_dhprime,
+        sizeof(pkinit_2048_dhprime));
     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_dhprime(pkinit_4096_dhprime,
+        sizeof(pkinit_4096_dhprime));
     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;
 
 cleanup:
     if (retval)

@@ -856,11 +974,11 @@
     PKCS7_SIGNER_INFO *p7si = NULL;
     unsigned char *p;
     ASN1_TYPE *pkinit_data = NULL;
     STACK_OF(X509) * cert_stack = NULL;
     ASN1_OCTET_STRING *digest_attr = NULL;
-    EVP_MD_CTX ctx, ctx2;
+    EVP_MD_CTX *ctx = NULL, *ctx2 = NULL;
     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;
     unsigned int md_len, md_len2, alen, digestInfo_len;
     STACK_OF(X509_ATTRIBUTE) * sk;

@@ -900,40 +1018,42 @@
         pkiDebug("only including signer's certificate\n");
         sk_X509_push(cert_stack, X509_dup(cert));
     } 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];
         int i = 0, size = 0;
 
         if ((certstore = X509_STORE_new()) == NULL)
             goto cleanup;
+        if ((certctx = X509_STORE_CTX_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);
+        X509_STORE_CTX_init(certctx, certstore, cert,
                             id_cryptoctx->intermediateCAs);
-        X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
+        X509_STORE_CTX_set0_trusted_stack(certctx, id_cryptoctx->trustedCAs);
         /* Solaris Kerberos */
-        if (X509_verify_cert(&certctx) <= 0) {
+        if (X509_verify_cert(certctx) <= 0) {
             pkiDebug("failed to create a certificate chain: %s\n", 
-            X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx)));
+            X509_verify_cert_error_string(X509_STORE_CTX_get_error(certctx)));
             if (!sk_X509_num(id_cryptoctx->trustedCAs)) 
                 pkiDebug("No trusted CAs found. Check your X509_anchors\n");
             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++) {
             X509 *x = sk_X509_value(certstack, i);
             X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
             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);
     }
     p7s->cert = cert_stack;
 

@@ -945,13 +1065,13 @@
     if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
                        X509_get_issuer_name(cert)))
         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 */
 
     /* Set digest algs */

@@ -981,15 +1101,20 @@
         abuf = data;
         alen = data_len;
     } 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 cleanup2;
+        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_MD_CTX_free(ctx);
+        ctx = NULL;
 
         /* create a message digest attr */
         digest_attr = ASN1_OCTET_STRING_new();
         ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
         PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,

@@ -1017,18 +1142,23 @@
      *  digest OCTET STRING }
      */
     if (id_cryptoctx->pkcs11_method == 1 && 
             id_cryptoctx->mech == CKM_RSA_PKCS) {
         pkiDebug("mech = CKM_RSA_PKCS\n");
-        EVP_MD_CTX_init(&ctx2);
+        ctx2 = EVP_MD_CTX_new();
+        if (ctx2 == NULL)
+            goto cleanup2;
+        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(ctx2, 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(ctx2, EVP_sha1(), NULL);
+        EVP_DigestUpdate(ctx2, abuf, alen);
+        EVP_DigestFinal_ex(ctx2, md_data2, &md_len2);
+        EVP_MD_CTX_free(ctx2);
+        ctx2 = NULL;
 
         alg = X509_ALGOR_new();
         if (alg == NULL)
             goto cleanup2;
         alg->algorithm = OBJ_nid2obj(NID_sha1);

@@ -1158,15 +1288,17 @@
     }
 #endif
 
   cleanup2:
     if (cms_msg_type != CMS_SIGN_DRAFT9) 
-        EVP_MD_CTX_cleanup(&ctx);
+        if (ctx != NULL)
+                EVP_MD_CTX_free(ctx);
 #ifndef WITHOUT_PKCS11
     if (id_cryptoctx->pkcs11_method == 1 && 
             id_cryptoctx->mech == CKM_RSA_PKCS) {
-        EVP_MD_CTX_cleanup(&ctx2);
+        if (ctx2 != NULL)
+                EVP_MD_CTX_free(ctx2);
         if (digest_buf != NULL)
             free(digest_buf);
         if (digestInfo_buf != NULL)
             free(digestInfo_buf);
         if (alg_buf != NULL)

@@ -1208,11 +1340,11 @@
     const unsigned char *p = signed_data;
     STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
     PKCS7_SIGNER_INFO *si = NULL;
     X509 *x = NULL;
     X509_STORE *store = NULL;
-    X509_STORE_CTX cert_ctx;
+    X509_STORE_CTX *cert_ctx;
     STACK_OF(X509) *intermediateCAs = NULL;
     STACK_OF(X509_CRL) *revoked = NULL;
     STACK_OF(X509) *verified_chain = NULL;
     ASN1_OBJECT *oid = NULL;
     krb5_external_principal_identifier **krb5_verified_chain = NULL;

@@ -1252,13 +1384,13 @@
         goto cleanup;
 
     /* 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);
 
     /* get the signer's information from the PKCS7 message */
     if ((si_sk = PKCS7_get_signer_info(p7)) == NULL)
         goto cleanup;

@@ -1305,18 +1437,20 @@
     }
 
     /* 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))
+    if ((cert_ctx = X509_STORE_CTX_new()) == 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_set0_trusted_stack(cert_ctx, idctx->trustedCAs);
     else {
         pkiDebug("unable to find any trusted CAs\n");
         goto cleanup;
     }
 #ifdef DEBUG_CERTCHAIN

@@ -1347,15 +1481,16 @@
             pkiDebug("crls by CA #%d: %s\n", i , buf);
         }
     }
 #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);
 
-        reqctx->received_cert = X509_dup(cert_ctx.current_cert);
+        reqctx->received_cert = X509_dup(
+            X509_STORE_CTX_get_current_cert(cert_ctx));
         switch(j) {
             case X509_V_ERR_CERT_REVOKED:
                 retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
                 break;
             case X509_V_ERR_UNABLE_TO_GET_CRL:

@@ -1384,13 +1519,13 @@
         }
 #endif
     } 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());
     if (cms_msg_type == CMS_SIGN_DRAFT9)

@@ -1417,13 +1552,14 @@
         }
 
         if (valid_oid) 
             pkiDebug("PKCS7 Verification successful\n");
         else {
+            const ASN1_OBJECT *etype = p7->d.sign->contents->type;
             pkiDebug("wrong oid in eContentType\n");
-            print_buffer((unsigned char *)p7->d.sign->contents->type->data, 
-                (unsigned int)p7->d.sign->contents->type->length);
+            print_buffer((unsigned char *)OBJ_get0_data(etype),
+                OBJ_length(etype));
             retval = KRB5KDC_ERR_PREAUTH_FAILED;
             krb5_set_error_message(context, retval, "wrong oid\n");
             goto cleanup;
         }
     }

@@ -2161,43 +2297,44 @@
                  unsigned int *dh_pubkey_len)
 {
     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
     unsigned char *buf = NULL;
     int dh_err = 0;
-    ASN1_INTEGER *pub_key = NULL;
+    ASN1_INTEGER *asn_pub_key = NULL;
+    BIGNUM *p, *g, *q;
+    const BIGNUM *pub_key;
 
     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)
+        if ((g = BN_new()) == NULL || (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);
+                cryptoctx->dh = make_dhprime(pkinit_1024_dhprime,
+                    sizeof(pkinit_1024_dhprime));
                 break;
             case 2048:
                 pkiDebug("client uses 2048 DH keys\n");
-                cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime,
-                    sizeof(pkinit_2048_dhprime), NULL);
+                cryptoctx->dh = make_dhprime(pkinit_2048_dhprime,
+                    sizeof(pkinit_2048_dhprime));
                 break;
             case 4096:
                 pkiDebug("client uses 4096 DH keys\n");
-                cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime,
-                    sizeof(pkinit_4096_dhprime), NULL);
+                cryptoctx->dh = make_dhprime(pkinit_4096_dhprime,
+                    sizeof(pkinit_4096_dhprime));
                 break;
-            default:
+        }
+        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, &pub_key, NULL);
+
 /* Solaris Kerberos */
 #ifdef DEBUG
     DH_check(cryptoctx->dh, &dh_err);
     if (dh_err != 0) {
         pkiDebug("Warning: dh_check failed with %d\n", dh_err);

@@ -2211,46 +2348,47 @@
             pkiDebug("the g value is not a generator\n");
     }
 #endif
 #ifdef DEBUG_DH
     print_dh(cryptoctx->dh, "client's DH params\n");
-    print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
+    print_pubkey(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, pub_key, &dh_err);
     if (dh_err != 0) {
         pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
         goto cleanup;
     }
 
     /* pack DHparams */
     /* 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, (const BIGNUM **)&p, (const BIGNUM **)&q,
+        (const BIGNUM **)&g);
+    retval = pkinit_encode_dh_params(p, g, q, dh_params, dh_params_len);
     if (retval)
         goto cleanup;
 
     /* pack DH public key */
     /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
      * encoding shall be used as the contents (the value) of the
      * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
      * data element
      */
-    if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL)
+    if ((asn_pub_key = BN_to_ASN1_INTEGER(pub_key, NULL)) == NULL)
         goto cleanup;
-    *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+    *dh_pubkey_len = i2d_ASN1_INTEGER(asn_pub_key, NULL);
     if ((buf = *dh_pubkey = (unsigned char *)
             malloc((size_t) *dh_pubkey_len)) == NULL) {
         retval  = ENOMEM;
         goto cleanup;
     }
-    i2d_ASN1_INTEGER(pub_key, &buf);
+    i2d_ASN1_INTEGER(asn_pub_key, &buf);
 
-    if (pub_key != NULL)
-        ASN1_INTEGER_free(pub_key);
+    if (asn_pub_key != NULL)
+        ASN1_INTEGER_free(asn_pub_key);
 
     retval = 0;
     return retval;
 
   cleanup:

@@ -2261,12 +2399,12 @@
         free(*dh_params);
     *dh_params = NULL;
     if (*dh_pubkey != NULL)
         free(*dh_pubkey);
     *dh_pubkey = NULL;
-    if (pub_key != NULL)
-        ASN1_INTEGER_free(pub_key);
+    if (asn_pub_key != NULL)
+        ASN1_INTEGER_free(asn_pub_key);
 
     return retval;
 }
 
 /* ARGSUSED */

@@ -2350,44 +2488,47 @@
 {
     DH *dh = NULL;
     unsigned char *tmp = NULL;
     int dh_prime_bits;
     krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+    const BIGNUM *p, *g, *q, *p2;
 
     tmp = dh_params->data;
     dh = DH_new();
     dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
     if (dh == NULL) {
         pkiDebug("failed to decode dhparams\n");
         goto cleanup;
     }
 
+    DH_get0_pqg(dh, &p, &q, &g);
+
     /* KDC SHOULD check to see if the key parameters satisfy its policy */
-    dh_prime_bits = BN_num_bits(dh->p);
+    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);
         goto cleanup;
     }
 
     /* check dhparams is group 2 */
-    if (pkinit_check_dh_params(cryptoctx->dh_1024->p,
-                               dh->p, dh->g, dh->q) == 0) {
+    DH_get0_pqg(cryptoctx->dh_1024, &p2, NULL, NULL);
+    if (pkinit_check_dh_params(p2, p, g, q) == 0) {
         retval = 0;
         goto cleanup;
     }
 
     /* check dhparams is group 14 */
-    if (pkinit_check_dh_params(cryptoctx->dh_2048->p,
-                               dh->p, dh->g, dh->q) == 0) {
+    DH_get0_pqg(cryptoctx->dh_2048, &p2, NULL, NULL);
+    if (pkinit_check_dh_params(p2, p, g, q) == 0) {
         retval = 0;
         goto cleanup;
     }
 
     /* check dhparams is group 16 */
-    if (pkinit_check_dh_params(cryptoctx->dh_4096->p,
-                               dh->p, dh->g, dh->q) == 0) {
+    DH_get0_pqg(cryptoctx->dh_4096, &p2, NULL, NULL);
+    if (pkinit_check_dh_params(p2, p, g, q) == 0) {
         retval = 0;
         goto cleanup;
     }
 
   cleanup:

@@ -2414,46 +2555,51 @@
                   unsigned int *server_key_len)
 {
     /* Solaris Kerberos */
     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
     DH *dh = NULL, *dh_server = NULL;
-    unsigned char *p = NULL;
-    ASN1_INTEGER *pub_key = NULL;
+    const BIGNUM *p, *g, *q, *s_pub_key;
+    BIGNUM *pub_key;
+    unsigned char *s = NULL;
+    ASN1_INTEGER *asn_pub_key = NULL;
 
     /* get client's received DH parameters that we saved in server_check_dh */
     dh = cryptoctx->dh;
 
     dh_server = DH_new();
     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);
+    DH_get0_pqg(dh, &p, &g, &q);
+    DH_set0_pqg(dh_server, BN_dup(p), BN_dup(g), BN_dup(q));
 
     /* decode client's public key */
-    p = data;
-    pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
+    s = data;
+    asn_pub_key = d2i_ASN1_INTEGER(NULL,
+        (const unsigned char **)&s, (int)data_len);
+    if (asn_pub_key == NULL)
+        goto cleanup;
+    pub_key = ASN1_INTEGER_to_BN(asn_pub_key, NULL);
     if (pub_key == NULL)
         goto cleanup;
-    dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL);
-    if (dh->pub_key == NULL)
-        goto cleanup;
-    ASN1_INTEGER_free(pub_key);
+    DH_set0_key(dh, pub_key, NULL);
+    ASN1_INTEGER_free(asn_pub_key);
 
     if (!DH_generate_key(dh_server))
         goto cleanup;
 
     /* generate DH session key */
     *server_key_len = DH_size(dh_server);
-    if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len)) == NULL)
+    if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len))
+        == NULL)
         goto cleanup;
-    DH_compute_key(*server_key, dh->pub_key, dh_server);
+    DH_compute_key(*server_key, pub_key, dh_server);
+    DH_get0_key(dh_server, &s_pub_key, NULL);
 
 #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(pub_key, "client's pub_key=");
+    print_pubkey(s_pub_key, "server's pub_key=");
     pkiDebug("server secret key=");
     print_buffer(*server_key, *server_key_len);
 #endif
 
     /* KDC reply */

@@ -2461,18 +2607,19 @@
     /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
      * encoding shall be used as the contents (the value) of the
      * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
      * data element
      */
-    if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL)
+    if ((asn_pub_key = BN_to_ASN1_INTEGER(s_pub_key, NULL)) == NULL)
         goto cleanup;
-    *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
-    if ((p = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len)) == NULL)
+    *dh_pubkey_len = i2d_ASN1_INTEGER(asn_pub_key, NULL);
+    if ((s = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len))
+        == NULL)
         goto cleanup;
-    i2d_ASN1_INTEGER(pub_key, &p);
-    if (pub_key != NULL)
-        ASN1_INTEGER_free(pub_key);
+    i2d_ASN1_INTEGER(asn_pub_key, &s);
+    if (asn_pub_key != NULL)
+        ASN1_INTEGER_free(asn_pub_key);
 
     retval = 0;
 
     if (dh_server != NULL)
         DH_free(dh_server);

@@ -2502,22 +2649,28 @@
 
     ret = k5_mutex_lock(&init_mutex);
     if (ret == 0) {
         if (!did_init) {
             /* initialize openssl routines */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+            /*
+             * As of version 1.1.0, OpenSSL will automatically allocate
+             * resources as-needed.
+             */
             CRYPTO_malloc_init();
             ERR_load_crypto_strings();
             OpenSSL_add_all_algorithms();
+#endif
             did_init++;
         }
         k5_mutex_unlock(&init_mutex);
     }
     return (ret);
 }
 
 static krb5_error_code
-pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q,
+pkinit_encode_dh_params(const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
                         unsigned char **buf, unsigned int *buf_len)
 {
     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
     int bufsize = 0, r = 0;
     unsigned char *tmp = NULL;

@@ -2558,10 +2711,12 @@
         ASN1_INTEGER_free(aq);
 
     return retval;
 }
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
 static DH *
 pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
 {
     ASN1_INTEGER ai, *aip = NULL;
     long length = (long) len;

@@ -2617,10 +2772,67 @@
     M_ASN1_D2I_end_sequence();
     M_ASN1_D2I_Finish(a, DH_free, 0);
 
 }
 
+#else
+
+/*
+ * This is taken from the internal dh_asn1.c file in OpenSSL 1.1, modified to
+ * make q an optional field.
+ */
+
+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 *
+pkinit_decode_dh_params(DH **a, unsigned char **pp, unsigned int len)
+{
+        int_dhx942_dh *params;
+        DH *dh = *a;
+
+        if (dh == NULL)
+                return NULL;
+
+        params = (int_dhx942_dh *)ASN1_item_d2i(NULL,
+            (const unsigned char **)pp, len, ASN1_ITEM_rptr(DHxparams));
+        if (params == NULL) {
+                DH_free(dh);
+                return NULL;
+        }
+
+        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;
+}
+
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
 static krb5_error_code
 pkinit_create_sequence_of_principal_identifiers(
     krb5_context context,
     pkinit_plg_crypto_context plg_cryptoctx,
     pkinit_req_crypto_context req_cryptoctx,

@@ -2761,34 +2973,32 @@
     unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
     unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
     krb5_typed_data **typed_data = NULL;
     krb5_data *data = NULL, *encoded_algId = NULL;
     krb5_algorithm_identifier **algId = NULL;
+    const BIGNUM *p, *q, *g;
 
     /* Solaris Kerberos */
     if (opts->dh_min_bits > 4096) {
         retval = EINVAL;
         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;
 
     if (opts->dh_min_bits <= 1024) {
         algId = malloc(4 * sizeof(krb5_algorithm_identifier *));

@@ -2978,11 +3188,12 @@
 
     return retval;
 }
 
 static int
-pkinit_check_dh_params(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1)
+pkinit_check_dh_params(const BIGNUM *p1, const BIGNUM *p2, const BIGNUM *g1,
+    const BIGNUM *q1)
 {
     BIGNUM *g2 = NULL, *q2 = NULL;
     /* Solaris Kerberos */
     int retval = EINVAL;
 

@@ -3022,40 +3233,42 @@
     pkiDebug("dh parameters\n");
 
     while (algId[i] != NULL) {
         DH *dh = NULL;
         unsigned char *tmp = NULL;
+        const BIGNUM *p, *g, *q, *p2;
         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 = 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_prime_bits = DH_bits(dh);
         pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
                  *new_dh_size, dh_prime_bits);
+        DH_get0_pqg(dh, &p, &q, &g);
         switch(dh_prime_bits) {
             case 1024:
-                if (pkinit_check_dh_params(cryptoctx->dh_1024->p, dh->p,
-                        dh->g, dh->q) == 0) {
+                DH_get0_pqg(cryptoctx->dh_1024, &p2, NULL, NULL);
+                if (pkinit_check_dh_params(p2, p, g, q) == 0) {
                     *new_dh_size = 1024;
                     ok = 1;
                 }
                 break;
             case 2048:
-                if (pkinit_check_dh_params(cryptoctx->dh_2048->p, dh->p,
-                        dh->g, dh->q) == 0) {
+                DH_get0_pqg(cryptoctx->dh_2048, &p2, NULL, NULL);
+                if (pkinit_check_dh_params(p2, p, g, q) == 0) {
                     *new_dh_size = 2048;
                     ok = 1;
                 }
                 break;
             case 4096:
-                if (pkinit_check_dh_params(cryptoctx->dh_4096->p, dh->p,
-                        dh->g, dh->q) == 0) {
+                DH_get0_pqg(cryptoctx->dh_4096, &p2, NULL, NULL);
+                if (pkinit_check_dh_params(p2, p, g, q) == 0) {
                     *new_dh_size = 4096;
                     ok = 1;
                 }
                 break;
             default:

@@ -3111,18 +3324,12 @@
 }
 
 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;
-        }
-    }
+    if (!ok)
+        return (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL);
     return ok;
 }
 
 static ASN1_OBJECT *
 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)

@@ -3307,38 +3514,35 @@
 prepare_enc_data(unsigned char *indata,
                  int indata_len,
                  unsigned char **outdata,
                  int *outdata_len)
 {
-    /* Solaris Kerberos */
-    ASN1_const_CTX c;
-    long length = indata_len;
-    int Ttag, Tclass;
-    long Tlen;
+    int tag, class;
+    long tlen, slen;
+    const uint8_t *p = indata, *oldp;
 
-    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);
+    /* Top-bit set means that the conversion failed. */
+    if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
+        return EINVAL;
+    if (tag != V_ASN1_SEQUENCE)
+        return EINVAL;
 
-    asn1_GetSequence(&c,&length);
+    oldp = p;
+    if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
+        return EINVAL;
+    p += tlen;
+    slen -= (p - oldp);
 
-    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
-    c.p += Tlen;
-    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+    if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
+        return EINVAL;
 
-    asn1_const_Finish(&c);
-
-    *outdata = (unsigned char *)malloc((size_t)Tlen);
-    /* Solaris Kerberos */
-    if (outdata == NULL)
+    *outdata = malloc(tlen);
+    if (*outdata == NULL)
         return ENOMEM;
+    memcpy(*outdata, p, tlen);
+    *outdata_len = tlen;
     
-    (void) memcpy(*outdata, c.p, (size_t)Tlen);
-    *outdata_len = Tlen;
-
     return 0;
 }
 
 #ifndef WITHOUT_PKCS11
 static void *

@@ -4366,10 +4570,11 @@
 {
     CK_OBJECT_CLASS cls;
     CK_ATTRIBUTE attrs[4];
     CK_ULONG count;
     CK_KEY_TYPE keytype;
+    RSA *rsa;
     unsigned int nattrs = 0;
     int r;
 #ifdef PKINIT_USE_KEY_USAGE
     CK_BBOOL true_false;
 #endif

@@ -4426,10 +4631,11 @@
      */
     if (r == CKR_OK && count != 1) {
 
         EVP_PKEY *priv;
         X509 *cert;
+        const BIGNUM *rsan;
         unsigned int n_len;
         unsigned char *n_bytes;
 
         cert = sk_X509_value(id_cryptoctx->my_certs, 0);
         priv = X509_get_pubkey(cert);

@@ -4457,17 +4663,25 @@
         attrs[nattrs].type = CKA_KEY_TYPE;
         attrs[nattrs].pValue = &keytype;
         attrs[nattrs].ulValueLen = sizeof keytype;
         nattrs++;
 
-        n_len = BN_num_bytes(priv->pkey.rsa->n);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+        rsa = priv->pkey.rsa;
+        rsan = rsa->n;
+        n_len = BN_num_bytes(rsan);
+#else
+        rsa = EVP_PKEY_get0_RSA(priv);
+        RSA_get0_key(rsa, &rsan, NULL, NULL);
+        n_len = RSA_size(rsa);
+#endif
         n_bytes = (unsigned char *) malloc((size_t) n_len);
         if (n_bytes == NULL) {
                 return (ENOMEM);
         }
 
-        if (BN_bn2bin(priv->pkey.rsa->n, n_bytes) == 0) {
+        if (BN_bn2bin(rsan, n_bytes) == 0) {
                 free (n_bytes);
                 pkiDebug("zero-byte key modulus\n");
                 return KRB5KDC_ERR_PREAUTH_FAILED;
         }
 

@@ -4772,15 +4986,11 @@
     buf_len = EVP_PKEY_size(pkey);
     buf = (unsigned char *)malloc((size_t) buf_len + 10);
     if (buf == NULL)
         return ENOMEM;
 
-#if OPENSSL_VERSION_NUMBER < 0x10000000L
-    len = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey);
-#else
     len = EVP_PKEY_decrypt_old(buf, data, (int)data_len, pkey);
-#endif
     if (len <= 0) {
         pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
         /* Solaris Kerberos */
         free(buf);
         return KRB5KRB_ERR_GENERIC;

@@ -4794,27 +5004,30 @@
 static krb5_error_code
 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 *md_ctx;
 
     if (pkey == NULL)
         /* Solaris Kerberos */
         return EINVAL;
 
-    EVP_VerifyInit(&md_ctx, EVP_sha1());
-    EVP_SignUpdate(&md_ctx, data, data_len);
+    if ((md_ctx = EVP_MD_CTX_new()) == NULL)
+        return EINVAL;
+
+    EVP_VerifyInit(md_ctx, EVP_sha1());
+    EVP_SignUpdate(md_ctx, data, data_len);
     *sig_len = EVP_PKEY_size(pkey);
     if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL)
         goto cleanup;
-    EVP_SignFinal(&md_ctx, *sig, sig_len, pkey);
+    EVP_SignFinal(md_ctx, *sig, sig_len, pkey);
 
     retval = 0;
 
   cleanup:
-    EVP_MD_CTX_cleanup(&md_ctx);
+    EVP_MD_CTX_free(md_ctx);
 
     return retval;
 }
 
 /*

@@ -6096,12 +6309,12 @@
 #ifdef LONGHORN_BETA_COMPAT
 if (longhorn == 0) { /* XXX Longhorn doesn't like this */
 #endif
         is = PKCS7_ISSUER_AND_SERIAL_new();
         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));
         len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
         if ((p = krb5_cas[i]->issuerAndSerialNumber.data =
              (unsigned char *)malloc((size_t) len)) == NULL)
             goto cleanup;
         i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);

@@ -6301,12 +6514,12 @@
                 krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial;
                 krb5_cas[i]->u.issuerAndSerial.data = NULL;
                 krb5_cas[i]->u.issuerAndSerial.length = 0;
                 is = PKCS7_ISSUER_AND_SERIAL_new();
                 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));
                 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
                 if ((p = krb5_cas[i]->u.issuerAndSerial.data =
                     (unsigned char *)malloc((size_t) len)) == NULL)
                     goto cleanup;
                 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);

@@ -6351,12 +6564,12 @@
     if (req_cryptoctx->received_cert == NULL)
         return 0;
 
     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 = (unsigned char *)malloc((size_t) len)) == NULL)
         goto cleanup;
     i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
     *out_len = len;

@@ -6537,13 +6750,13 @@
     if (cert) {
         for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
             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,
+                tmp_ret = ASN1_INTEGER_cmp(X509_get_serialNumber(cert),
                                              ri->issuer_and_serial->serial);
                 if (!tmp_ret)
                     break;
             }
             ri=NULL;

@@ -6560,12 +6773,12 @@
 
     if (cert == NULL) {
         for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
             ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
             jj = pkinit_decode_data(context, id_cryptoctx,
-                M_ASN1_STRING_data(ri->enc_key),
-                (unsigned int) M_ASN1_STRING_length(ri->enc_key),
+                (unsigned char *)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);
                 goto cleanup;
             }

@@ -6578,18 +6791,18 @@
             ERR_clear_error();
             ri = NULL;
         }
 
         if (ri == NULL) {
-            PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
+            PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
             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),
+            (unsigned char *)ASN1_STRING_get0_data(ri->enc_key),
+            ASN1_STRING_length(ri->enc_key),
             &tmp, &tmp_len);
         /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
         if (jj || tmp_len == 0) {
             PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
             goto cleanup;

@@ -6609,11 +6822,11 @@
          * and effective key length. The key length is
          * 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);
+                     PKCS7_R_DECRYPT_ERROR);
             goto cleanup;
         }
     }
     if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
         goto cleanup;