pkinit: client: Use SignedData for anonymous
authorSam Hartman <hartmans@mit.edu>
Mon, 19 Sep 2011 00:34:36 +0000 (00:34 +0000)
committerSam Hartman <hartmans@mit.edu>
Mon, 19 Sep 2011 00:34:36 +0000 (00:34 +0000)
Per RFc 6112 use SignedData not ContentInfo for anonymous when the KDC
offers support for PKINIT_KX padata.

ticket: 6962

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25186 dc483132-0cff-0310-8789-dd5450dbe970

src/plugins/preauth/pkinit/pkinit.h
src/plugins/preauth/pkinit/pkinit_clnt.c
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c

index 6ba399de18f2f69927339889b237c3340eced926..8928e9d80c2d48bd16840e8ae26a86cc51059ca9 100644 (file)
@@ -219,12 +219,13 @@ typedef struct _pkinit_context *pkinit_context;
  * Client's per-request context
  */
 struct _pkinit_req_context {
-    int magic;
+  unsigned int magic;
     pkinit_req_crypto_context cryptoctx;
     pkinit_req_opts *opts;
     pkinit_identity_crypto_context idctx;
     pkinit_identity_opts *idopts;
     krb5_preauthtype pa_type;
+  int rfc6112_kdc;
 };
 typedef struct _pkinit_req_context *pkinit_req_context;
 
index cf95bd57b23991c88ea7f5cf8198c8f663bca1f5..85b01673785987f14268d1a5cb7f31b4f392d2e3 100644 (file)
  */
 int longhorn = 0;       /* Talking to a Longhorn server? */
 
+/**
+ * Return true if we should use ContentInfo rather than SignedData. This
+ * happens if we are talking to what might be an old (pre-6112) MIT KDC and
+ * we're using anonymous.
+ */
+static int
+use_content_info(krb5_context context, pkinit_req_context req,
+                 krb5_principal client)
+{
+    if (req->rfc6112_kdc)
+        return 0;
+    if (krb5_principal_compare_any_realm(context, client,
+                                         krb5_anonymous_principal()))
+                return 1;
+    return 0;
+    }
+
 static krb5_error_code
 pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
                      pkinit_req_context reqctx, krb5_timestamp ctsec,
@@ -347,9 +364,7 @@ pkinit_as_req_create(krb5_context context,
             retval = ENOMEM;
             goto cleanup;
         }
-        /* For the new protocol, we support anonymous. */
-        if (krb5_principal_compare_any_realm(context, client,
-                                             krb5_anonymous_principal())) {
+        if (use_content_info(context, reqctx, client))
             retval = cms_contentinfo_create(context, plgctx->cryptoctx,
                                             reqctx->cryptoctx, reqctx->idctx,
                                             CMS_SIGN_CLIENT, (unsigned char *)
@@ -357,7 +372,7 @@ pkinit_as_req_create(krb5_context context,
                                             coded_auth_pack->length,
                                             &req->signedAuthPack.data,
                                             &req->signedAuthPack.length);
-        else {
+        else {
             retval = cms_signeddata_create(context, plgctx->cryptoctx,
                                            reqctx->cryptoctx, reqctx->idctx,
                                            CMS_SIGN_CLIENT, 1,
@@ -1012,7 +1027,10 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
         return EINVAL;
 
     switch ((int) in_padata->pa_type) {
-    case KRB5_PADATA_PK_AS_REQ:
+    case KRB5_PADATA_PKINIT_KX:
+        reqctx->rfc6112_kdc = 1;
+        return 0;
+            case KRB5_PADATA_PK_AS_REQ:
         pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
         processing_request = 1;
         break;
@@ -1176,14 +1194,23 @@ cleanup:
 static int
 pkinit_client_get_flags(krb5_context kcontext, krb5_preauthtype patype)
 {
+    if (patype == KRB5_PADATA_PKINIT_KX)
+        return PA_INFO|PA_PSEUDO;
     return PA_REAL;
 }
 
+/*
+ * We want to be notified about KRB5_PADATA_PKINIT_KX in addition to the actual
+ * pkinit patypes because RFC 6112 requires anonymous KDCs to send it. We use
+ * that to determine whether to use the broken MIT 1.9 behavior of sending
+ * ContentInfo rather than SignedData or the RFC 6112 behavior
+ */
 static krb5_preauthtype supported_client_pa_types[] = {
     KRB5_PADATA_PK_AS_REP,
     KRB5_PADATA_PK_AS_REQ,
     KRB5_PADATA_PK_AS_REP_OLD,
     KRB5_PADATA_PK_AS_REQ_OLD,
+    KRB5_PADATA_PKINIT_KX,
     0
 };
 
index 56fc3fe8f7fc67c78184a745877cfeff72d42e65..4247524ae54e18581922b0dc0ba24ea40033009f 100644 (file)
@@ -858,11 +858,6 @@ cms_signeddata_create(krb5_context context,
     X509 *cert = NULL;
     ASN1_OBJECT *oid = NULL;
 
-    if (id_cryptoctx->my_certs == NULL) {
-        krb5_set_error_message(context, EINVAL, _("cms_signdata_create called "
-                                                  "with no certificates"));
-        return EINVAL;
-    }
     /* Start creating PKCS7 data. */
     if ((p7 = PKCS7_new()) == NULL)
         goto cleanup;
@@ -874,206 +869,208 @@ cms_signeddata_create(krb5_context context,
     if (!ASN1_INTEGER_set(p7s->version, 3))
         goto cleanup;
 
-    /* create a cert chain that has at least the signer's certificate */
-    if ((cert_stack = sk_X509_new_null()) == NULL)
+    /* pick the correct oid for the eContentInfo */
+    oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
+    if (oid == NULL)
         goto cleanup;
 
-    cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
-    if (!include_certchain) {
-        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;
-        STACK_OF(X509) *certstack = NULL;
-        char buf[DN_BUF_LEN];
-        unsigned int i = 0, size = 0;
-
-        if ((certstore = X509_STORE_new()) == NULL)
-            goto cleanup;
-        pkiDebug("building certificate chain\n");
-        X509_STORE_set_verify_cb_func(certstore, openssl_callback);
-        X509_STORE_CTX_init(&certctx, certstore, cert,
-                            id_cryptoctx->intermediateCAs);
-        X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
-        if (!X509_verify_cert(&certctx)) {
-            pkiDebug("failed to create a certificate chain: %s\n",
-                     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");
+    if (id_cryptoctx->my_certs != NULL) {
+        /* create a cert chain that has at least the signer's certificate */
+        if ((cert_stack = sk_X509_new_null()) == NULL)
             goto cleanup;
-        }
-        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_free(certstore);
-        sk_X509_pop_free(certstack, X509_free);
-    }
-    p7s->cert = cert_stack;
-
-    /* fill-in PKCS7_SIGNER_INFO */
-    if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
-        goto cleanup;
-    if (!ASN1_INTEGER_set(p7si->version, 1))
-        goto cleanup;
-    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);
-    if (!(p7si->issuer_and_serial->serial =
-          M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
-        goto cleanup;
 
-    /* will not fill-out EVP_PKEY because it's on the smartcard */
+        cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+        if (!include_certchain) {
+            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;
+            STACK_OF(X509) *certstack = NULL;
+            char buf[DN_BUF_LEN];
+            unsigned int i = 0, size = 0;
+
+            if ((certstore = X509_STORE_new()) == NULL)
+                goto cleanup;
+            pkiDebug("building certificate chain\n");
+            X509_STORE_set_verify_cb_func(certstore, openssl_callback);
+            X509_STORE_CTX_init(&certctx, certstore, cert,
+                                id_cryptoctx->intermediateCAs);
+            X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
+            if (!X509_verify_cert(&certctx)) {
+                pkiDebug("failed to create a certificate chain: %s\n",
+                         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);
+            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_free(certstore);
+            sk_X509_pop_free(certstack, X509_free);
+        }
+        p7s->cert = cert_stack;
 
-    /* Set digest algs */
-    p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
+        /* fill-in PKCS7_SIGNER_INFO */
+        if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
+            goto cleanup;
+        if (!ASN1_INTEGER_set(p7si->version, 1))
+            goto cleanup;
+        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);
+        if (!(p7si->issuer_and_serial->serial =
+              M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+            goto cleanup;
 
-    if (p7si->digest_alg->parameter != NULL)
-        ASN1_TYPE_free(p7si->digest_alg->parameter);
-    if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
-        goto cleanup;
-    p7si->digest_alg->parameter->type = V_ASN1_NULL;
+        /* will not fill-out EVP_PKEY because it's on the smartcard */
 
-    /* Set sig algs */
-    if (p7si->digest_enc_alg->parameter != NULL)
-        ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
-    p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
-    if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
-        goto cleanup;
-    p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
+        /* Set digest algs */
+        p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
 
-    /* pick the correct oid for the eContentInfo */
-    oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
-    if (oid == NULL)
-        goto cleanup;
+        if (p7si->digest_alg->parameter != NULL)
+            ASN1_TYPE_free(p7si->digest_alg->parameter);
+        if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
+            goto cleanup;
+        p7si->digest_alg->parameter->type = V_ASN1_NULL;
 
-    if (cms_msg_type == CMS_SIGN_DRAFT9) {
-        /* don't include signed attributes for pa-type 15 request */
-        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);
-
-        /* 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,
-                                   V_ASN1_OCTET_STRING, (char *) digest_attr);
-
-        /* create a content-type attr */
-        PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
-                                   V_ASN1_OBJECT, oid);
-
-        /* create the signature over signed attributes. get DER encoded value */
-        /* This is the place where smartcard signature needs to be calculated */
-        sk = p7si->auth_attr;
-        alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
-                             ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
-        if (abuf == NULL)
-            goto cleanup2;
-    }
+        /* Set sig algs */
+        if (p7si->digest_enc_alg->parameter != NULL)
+            ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
+        p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
+        if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
+            goto cleanup;
+        p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
+
+        if (cms_msg_type == CMS_SIGN_DRAFT9){
+                /* don't include signed attributes for pa-type 15 request */
+                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);
+
+            /* 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,
+                                       V_ASN1_OCTET_STRING, (char *) digest_attr);
+
+            /* create a content-type attr */
+            PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
+                                       V_ASN1_OBJECT, oid);
+
+            /* create the signature over signed attributes. get DER encoded value */
+            /* This is the place where smartcard signature needs to be calculated */
+            sk = p7si->auth_attr;
+            alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
+                                 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
+            if (abuf == NULL)
+                goto cleanup2;
+        } /* signed attributes */
 
 #ifndef WITHOUT_PKCS11
-    /* Some tokens can only do RSAEncryption without sha1 hash */
-    /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
-     * function and the hash value into an ASN.1 value of type DigestInfo
-     * DigestInfo::=SEQUENCE {
-     *  digestAlgorithm  AlgorithmIdentifier,
-     *  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);
-        /* if this is not draft9 request, include digest signed attribute */
-        if (cms_msg_type != CMS_SIGN_DRAFT9)
-            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);
-
-        alg = X509_ALGOR_new();
-        if (alg == NULL)
-            goto cleanup2;
-        alg->algorithm = OBJ_nid2obj(NID_sha1);
-        alg->parameter = NULL;
-        alg_len = i2d_X509_ALGOR(alg, NULL);
-        alg_buf = malloc(alg_len);
-        if (alg_buf == NULL)
-            goto cleanup2;
-
-        digest = ASN1_OCTET_STRING_new();
-        if (digest == NULL)
-            goto cleanup2;
-        ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
-        digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
-        digest_buf = malloc(digest_len);
-        if (digest_buf == NULL)
-            goto cleanup2;
-
-        digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
-                                          V_ASN1_SEQUENCE);
-        y = digestInfo_buf = malloc(digestInfo_len);
-        if (digestInfo_buf == NULL)
-            goto cleanup2;
-        ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
-                        V_ASN1_UNIVERSAL);
-        i2d_X509_ALGOR(alg, &y);
-        i2d_ASN1_OCTET_STRING(digest, &y);
+        /* Some tokens can only do RSAEncryption without sha1 hash */
+        /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
+         * function and the hash value into an ASN.1 value of type DigestInfo
+         * DigestInfo::=SEQUENCE {
+         *  digestAlgorithm  AlgorithmIdentifier,
+         *  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);
+            /* if this is not draft9 request, include digest signed attribute */
+            if (cms_msg_type != CMS_SIGN_DRAFT9)
+                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);
+
+            alg = X509_ALGOR_new();
+            if (alg == NULL)
+                goto cleanup2;
+            alg->algorithm = OBJ_nid2obj(NID_sha1);
+            alg->parameter = NULL;
+            alg_len = i2d_X509_ALGOR(alg, NULL);
+            alg_buf = malloc(alg_len);
+            if (alg_buf == NULL)
+                goto cleanup2;
+
+            digest = ASN1_OCTET_STRING_new();
+            if (digest == NULL)
+                goto cleanup2;
+            ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
+            digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
+            digest_buf = malloc(digest_len);
+            if (digest_buf == NULL)
+                goto cleanup2;
+
+            digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
+                                              V_ASN1_SEQUENCE);
+            y = digestInfo_buf = malloc(digestInfo_len);
+            if (digestInfo_buf == NULL)
+                goto cleanup2;
+            ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
+                            V_ASN1_UNIVERSAL);
+            i2d_X509_ALGOR(alg, &y);
+            i2d_ASN1_OCTET_STRING(digest, &y);
 #ifdef DEBUG_SIG
-        pkiDebug("signing buffer\n");
-        print_buffer(digestInfo_buf, digestInfo_len);
-        print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
+            pkiDebug("signing buffer\n");
+            print_buffer(digestInfo_buf, digestInfo_len);
+            print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
 #endif
-        retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
-                                  digestInfo_len, &sig, &sig_len);
-    } else
+            retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
+                                      digestInfo_len, &sig, &sig_len);
+        } else
 #endif
-    {
-        pkiDebug("mech = %s\n",
-                 id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
-        retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
-                                  &sig, &sig_len);
-    }
+        {
+            pkiDebug("mech = %s\n",
+                     id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
+            retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
+                                      &sig, &sig_len);
+        }
 #ifdef DEBUG_SIG
-    print_buffer(sig, sig_len);
+        print_buffer(sig, sig_len);
 #endif
-    if (cms_msg_type != CMS_SIGN_DRAFT9)
-        free(abuf);
-    if (retval)
-        goto cleanup2;
+        if (cms_msg_type != CMS_SIGN_DRAFT9 )
+            free(abuf);
+        if (retval)
+            goto cleanup2;
 
-    /* Add signature */
-    if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
-                         (int)sig_len)) {
-        unsigned long err = ERR_peek_error();
-        retval = KRB5KDC_ERR_PREAUTH_FAILED;
-        krb5_set_error_message(context, retval, "%s\n",
-                               ERR_error_string(err, NULL));
-        pkiDebug("failed to add a signed digest attribute\n");
-        goto cleanup2;
-    }
-    /* adder signer_info to pkcs7 signed */
-    if (!PKCS7_add_signer(p7, p7si))
-        goto cleanup2;
+        /* Add signature */
+        if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
+                             (int)sig_len)) {
+            unsigned long err = ERR_peek_error();
+            retval = KRB5KDC_ERR_PREAUTH_FAILED;
+            krb5_set_error_message(context, retval, "%s\n",
+                                   ERR_error_string(err, NULL));
+            pkiDebug("failed to add a signed digest attribute\n");
+            goto cleanup2;
+        }
+        /* adder signer_info to pkcs7 signed */
+        if (!PKCS7_add_signer(p7, p7si))
+            goto cleanup2;
+    } /* we have a certificate */
 
     /* start on adding data to the pkcs7 signed */
     retval = create_contentinfo(context, plg_cryptoctx, oid,
@@ -1123,21 +1120,23 @@ cms_signeddata_create(krb5_context context,
 #endif
 
 cleanup2:
-    if (cms_msg_type != CMS_SIGN_DRAFT9)
-        EVP_MD_CTX_cleanup(&ctx);
+    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);
-        if (digest != NULL)
-            ASN1_OCTET_STRING_free(digest);
-    }
+        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);
+            if (digest != NULL)
+                ASN1_OCTET_STRING_free(digest);
+        }
 #endif
-    if (alg != NULL)
-        X509_ALGOR_free(alg);
+        if (alg != NULL)
+            X509_ALGOR_free(alg);
+    }
 cleanup:
     if (p7 != NULL)
         PKCS7_free(p7);