Commit message: PKINIT null pointer deref [CVE-2013-1415]

Don't dereference a null pointer when cleaning up.

The KDC plugin for PKINIT can dereference a null pointer when a
malformed packet causes processing to terminate early, leading to
a crash of the KDC process.  An attacker would need to have a valid
PKINIT certificate or have observed a successful PKINIT authentication,
or an unauthenticated attacker could execute the attack if anonymous
PKINIT is enabled.

CVSSv2 vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:P/RL:O/RC:C

This is a minimal commit for pullup; style fixes in a followup.
[kaduk@mit.edu: reformat and edit commit message]

(cherry picked from commit c773d3c775e9b2d88bcdff5f8a8ba88d7ec4e8ed)

ticket: 7570
version_fixed: 1.11.1
status: resolved
CVE: CVE-2013-1415
CWE: CWE-476
Vulnerability description: The pkinit_check_kdc_pkid function in plugins/preauth/pkinit/pkinit_crypto_openssl.c in the PKINIT implementation in the Key Distribution Center (KDC) in MIT Kerberos 5 (aka krb5) before 1.10.4 and 1.11.x before 1.11.1 does not properly handle errors during extraction of fields from an X.509 certificate, which allows remote attackers to cause a denial of service (NULL pointer dereference and daemon crash) via a malformed KRB5_PADATA_PK_AS_REQ AS-REQ request.

Project: krb5

cms_signeddata_create(krb5_context context,
                      pkinit_plg_crypto_context plg_cryptoctx,
                      pkinit_req_crypto_context req_cryptoctx,
                      pkinit_identity_crypto_context id_cryptoctx,
                      int cms_msg_type,
                      int include_certchain,
                      unsigned char *data,
                      unsigned int data_len,
                      unsigned char **signed_data,
                      unsigned int *signed_data_len)
{
    krb5_error_code retval = ENOMEM;
    PKCS7  *p7 = NULL, *inner_p7 = NULL;
    PKCS7_SIGNED *p7s = NULL;
    PKCS7_SIGNER_INFO *p7si = NULL;
    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;
    unsigned int md_len, md_len2, alen, digestInfo_len;
    STACK_OF(X509_ATTRIBUTE) * sk;
    unsigned char *sig = NULL;
    unsigned int sig_len = 0;
    X509_ALGOR *alg = NULL;
    ASN1_OCTET_STRING *digest = NULL;
    unsigned int alg_len = 0, digest_len = 0;
    unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
    X509 *cert = NULL;
    ASN1_OBJECT *oid = NULL;

    /* Start creating PKCS7 data. */
    if ((p7 = PKCS7_new()) == NULL)
        goto cleanup;
    p7->type = OBJ_nid2obj(NID_pkcs7_signed);

    if ((p7s = PKCS7_SIGNED_new()) == NULL)
        goto cleanup;
    p7->d.sign = p7s;
    if (!ASN1_INTEGER_set(p7s->version, 3))
        goto cleanup;

    /* pick the correct oid for the eContentInfo */
    oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
    if (oid == NULL)
        goto cleanup;

    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;

        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)) {
                int code = X509_STORE_CTX_get_error(&certctx);
                const char *msg = X509_verify_cert_error_string(code);
                pkiDebug("failed to create a certificate chain: %s\n", msg);
                if (!sk_X509_num(id_cryptoctx->trustedCAs))
                    pkiDebug("No trusted CAs found. Check your X509_anchors\n");
                retval = KRB5_PREAUTH_FAILED;
                krb5_set_error_message(context, retval,
                                       _("Cannot create cert chain: %s"), msg);
                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 */

        /* Set digest algs */
        p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);

        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;

        /* 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);
#ifdef DEBUG_SIG
            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
#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);
        }
#ifdef DEBUG_SIG
        print_buffer(sig, sig_len);
#endif
        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;
    } /* we have a certificate */

    /* start on adding data to the pkcs7 signed */
    retval = create_contentinfo(context, plg_cryptoctx, oid,
                                data, data_len, &inner_p7);
    if (p7s->contents != NULL)
        PKCS7_free(p7s->contents);
    p7s->contents = inner_p7;

    *signed_data_len = i2d_PKCS7(p7, NULL);
    if (!(*signed_data_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 der encode pkcs7\n");
        goto cleanup2;
    }
    retval = ENOMEM;
    if ((p = *signed_data = malloc(*signed_data_len)) == NULL)
        goto cleanup2;

    /* DER encode PKCS7 data */
    retval = i2d_PKCS7(p7, &p);
    if (!retval) {
        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 der encode pkcs7\n");
        goto cleanup2;
    }
    retval = 0;

#ifdef DEBUG_ASN1
    if (cms_msg_type == CMS_SIGN_CLIENT) {
        print_buffer_bin(*signed_data, *signed_data_len,
                         "/tmp/client_pkcs7_signeddata");
    } else {
        if (cms_msg_type == CMS_SIGN_SERVER) {
            print_buffer_bin(*signed_data, *signed_data_len,
                             "/tmp/kdc_pkcs7_signeddata");
        } else {
            print_buffer_bin(*signed_data, *signed_data_len,
                             "/tmp/draft9_pkcs7_signeddata");
        }
    }
#endif

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);
            if (digest != NULL)
                ASN1_OCTET_STRING_free(digest);
        }
#endif
        if (alg != NULL)
            X509_ALGOR_free(alg);
    }
cleanup:
    if (p7 != NULL)
        PKCS7_free(p7);
    free(sig);

    return retval;
}

Project: krb5

create_krb5_supportedCMSTypes(krb5_context context,
                              pkinit_plg_crypto_context plg_cryptoctx,
                              pkinit_req_crypto_context req_cryptoctx,
                              pkinit_identity_crypto_context id_cryptoctx,
                              krb5_algorithm_identifier ***oids)
{

    krb5_error_code retval = ENOMEM;
    krb5_algorithm_identifier **loids = NULL;
    krb5_data des3oid = {0, 8, "\x2A\x86\x48\x86\xF7\x0D\x03\x07" };

    *oids = NULL;
    loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
    if (loids == NULL)
        goto cleanup;
    loids[1] = NULL;
    loids[0] = malloc(sizeof(krb5_algorithm_identifier));
    if (loids[0] == NULL) {
        free(loids);
        goto cleanup;
    }
    retval = pkinit_copy_krb5_data(&loids[0]->algorithm, &des3oid);
    if (retval) {
        free(loids[0]);
        free(loids);
        goto cleanup;
    }
    loids[0]->parameters.length = 0;
    loids[0]->parameters.data = NULL;

    *oids = loids;
    retval = 0;
cleanup:

    return retval;
}

Project: krb5

pkinit_alg_values(krb5_context context,
                  const krb5_data *alg_id,
                  size_t *hash_bytes,
                  const EVP_MD *(**func)(void))
{
    *hash_bytes = 0;
    *func = NULL;
    if ((alg_id->length == krb5_pkinit_sha1_oid_len) &&
        (0 == memcmp(alg_id->data, &krb5_pkinit_sha1_oid,
                     krb5_pkinit_sha1_oid_len))) {
        *hash_bytes = 20;
        *func = &EVP_sha1;
        return 0;
    } else if ((alg_id->length == krb5_pkinit_sha256_oid_len) &&
               (0 == memcmp(alg_id->data, krb5_pkinit_sha256_oid,
                            krb5_pkinit_sha256_oid_len))) {
        *hash_bytes = 32;
        *func = &EVP_sha256;
        return 0;
    } else if ((alg_id->length == krb5_pkinit_sha512_oid_len) &&
               (0 == memcmp(alg_id->data, krb5_pkinit_sha512_oid,
                            krb5_pkinit_sha512_oid_len))) {
        *hash_bytes = 64;
        *func = &EVP_sha512;
        return 0;
    } else {
        krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS,
                               "Bad algorithm ID passed to PK-INIT KDF.");
        return KRB5_ERR_BAD_S2K_PARAMS;
    }
} /* pkinit_alg_values() */

Project: krb5

pkinit_create_sequence_of_principal_identifiers(
    krb5_context context,
    pkinit_plg_crypto_context plg_cryptoctx,
    pkinit_req_crypto_context req_cryptoctx,
    pkinit_identity_crypto_context id_cryptoctx,
    int type,
    krb5_pa_data ***e_data_out)
{
    krb5_error_code retval = KRB5KRB_ERR_GENERIC;
    krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
    krb5_data *td_certifiers = NULL;
    krb5_pa_data **pa_data = NULL;

    switch(type) {
    case TD_TRUSTED_CERTIFIERS:
        retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
                                               req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
        if (retval) {
            pkiDebug("create_krb5_trustedCertifiers failed\n");
            goto cleanup;
        }
        break;
    case TD_INVALID_CERTIFICATES:
        retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
                                                 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
        if (retval) {
            pkiDebug("create_krb5_invalidCertificates failed\n");
            goto cleanup;
        }
        break;
    default:
        retval = -1;
        goto cleanup;
    }

    retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers);
    if (retval) {
        pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
        goto cleanup;
    }
#ifdef DEBUG_ASN1
    print_buffer_bin((unsigned char *)td_certifiers->data,
                     td_certifiers->length, "/tmp/kdc_td_certifiers");
#endif
    pa_data = malloc(2 * sizeof(krb5_pa_data *));
    if (pa_data == NULL) {
        retval = ENOMEM;
        goto cleanup;
    }
    pa_data[1] = NULL;
    pa_data[0] = malloc(sizeof(krb5_pa_data));
    if (pa_data[0] == NULL) {
        free(pa_data);
        retval = ENOMEM;
        goto cleanup;
    }
    pa_data[0]->pa_type = type;
    pa_data[0]->length = td_certifiers->length;
    pa_data[0]->contents = (krb5_octet *)td_certifiers->data;
    *e_data_out = pa_data;
    retval = 0;

cleanup:
    if (krb5_trusted_certifiers != NULL)
        free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
    free(td_certifiers);
    return retval;
}

Project: krb5

pkinit_get_certs_pkcs12(krb5_context context,
                        pkinit_plg_crypto_context plg_cryptoctx,
                        pkinit_req_crypto_context req_cryptoctx,
                        pkinit_identity_opts *idopts,
                        pkinit_identity_crypto_context id_cryptoctx,
                        krb5_principal princ)
{
    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
    X509 *x = NULL;
    PKCS12 *p12 = NULL;
    int ret;
    FILE *fp;
    EVP_PKEY *y = NULL;

    if (idopts->cert_filename == NULL) {
        pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
        goto cleanup;
    }

    if (idopts->key_filename == NULL) {
        pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
        goto cleanup;
    }

    fp = fopen(idopts->cert_filename, "rb");
    if (fp == NULL) {
        pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
                 idopts->cert_filename, errno);
        goto cleanup;
    }
    set_cloexec_file(fp);

    p12 = d2i_PKCS12_fp(fp, NULL);
    fclose(fp);
    if (p12 == NULL) {
        pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
                 idopts->cert_filename);
        goto cleanup;
    }
    /*
     * Try parsing with no pass phrase first.  If that fails,
     * prompt for the pass phrase and try again.
     */
    ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
    if (ret == 0) {
        krb5_data rdat;
        krb5_prompt kprompt;
        krb5_prompt_type prompt_type;
        int r = 0;
        char prompt_string[128];
        char prompt_reply[128];
        char *prompt_prefix = _("Pass phrase for");

        pkiDebug("Initial PKCS12_parse with no password failed\n");

        memset(prompt_reply, '\0', sizeof(prompt_reply));
        rdat.data = prompt_reply;
        rdat.length = sizeof(prompt_reply);

        r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
                     prompt_prefix, idopts->cert_filename);
        if (r >= (int) sizeof(prompt_string)) {
            pkiDebug("Prompt string, '%s %s', is too long!\n",
                     prompt_prefix, idopts->cert_filename);
            goto cleanup;
        }
        kprompt.prompt = prompt_string;
        kprompt.hidden = 1;
        kprompt.reply = &rdat;
        prompt_type = KRB5_PROMPT_TYPE_PREAUTH;

        /* PROMPTER_INVOCATION */
        k5int_set_prompt_types(context, &prompt_type);
        r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
                                      NULL, NULL, 1, &kprompt);
        k5int_set_prompt_types(context, 0);

        ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
        if (ret == 0) {
            pkiDebug("Seconde PKCS12_parse with password failed\n");
            goto cleanup;
        }
    }
    id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
    if (id_cryptoctx->creds[0] == NULL)
        goto cleanup;
    id_cryptoctx->creds[0]->name =
        reassemble_pkcs12_name(idopts->cert_filename);
    id_cryptoctx->creds[0]->cert = x;
#ifndef WITHOUT_PKCS11
    id_cryptoctx->creds[0]->cert_id = NULL;
    id_cryptoctx->creds[0]->cert_id_len = 0;
#endif
    id_cryptoctx->creds[0]->key = y;
    id_cryptoctx->creds[1] = NULL;

    retval = 0;

cleanup:
    if (p12)
        PKCS12_free(p12);
    if (retval) {
        if (x != NULL)
            X509_free(x);
        if (y != NULL)
            EVP_PKEY_free(y);
    }
    return retval;
}

Project: krb5

pkinit_open_session(krb5_context context,
                    pkinit_identity_crypto_context cctx)
{
    CK_ULONG i, r;
    unsigned char *cp;
    CK_ULONG count = 0;
    CK_SLOT_ID_PTR slotlist;
    CK_TOKEN_INFO tinfo;

    if (cctx->p11_module != NULL)
        return 0; /* session already open */

    /* Load module */
    cctx->p11_module =
        pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
    if (cctx->p11_module == NULL)
        return KRB5KDC_ERR_PREAUTH_FAILED;

    /* Init */
    if ((r = cctx->p11->C_Initialize(NULL)) != CKR_OK) {
        pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r));
        return KRB5KDC_ERR_PREAUTH_FAILED;
    }

    /* Get the list of available slots */
    if (cctx->slotid != PK_NOSLOT) {
        /* A slot was specified, so that's the only one in the list */
        count = 1;
        slotlist = malloc(sizeof(CK_SLOT_ID));
        slotlist[0] = cctx->slotid;
    } else {
        if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
            return KRB5KDC_ERR_PREAUTH_FAILED;
        if (count == 0)
            return KRB5KDC_ERR_PREAUTH_FAILED;
        slotlist = malloc(count * sizeof (CK_SLOT_ID));
        if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK)
            return KRB5KDC_ERR_PREAUTH_FAILED;
    }

    /* Look for the given token label, or if none given take the first one */
    for (i = 0; i < count; i++) {
        /* Open session */
        if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
                                          NULL, NULL, &cctx->session)) != CKR_OK) {
            pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r));
            return KRB5KDC_ERR_PREAUTH_FAILED;
        }

        /* Get token info */
        if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) {
            pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r));
            return KRB5KDC_ERR_PREAUTH_FAILED;
        }
        for (cp = tinfo.label + sizeof (tinfo.label) - 1;
             *cp == '\0' || *cp == ' '; cp--)
            *cp = '\0';
        pkiDebug("open_session: slotid %d token \"%s\"\n",
                 (int) slotlist[i], tinfo.label);
        if (cctx->token_label == NULL ||
            !strcmp((char *) cctx->token_label, (char *) tinfo.label))
            break;
        cctx->p11->C_CloseSession(cctx->session);
    }
    if (i >= count) {
        free(slotlist);
        pkiDebug("open_session: no matching token found\n");
        return KRB5KDC_ERR_PREAUTH_FAILED;
    }
    cctx->slotid = slotlist[i];
    free(slotlist);
    pkiDebug("open_session: slotid %d (%lu of %d)\n", (int) cctx->slotid,
             i + 1, (int) count);

    /* Login if needed */
    if (tinfo.flags & CKF_LOGIN_REQUIRED)
        r = pkinit_login(context, cctx, &tinfo);

    return r;
}

Project: krb5

pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
{
    int nid;

    switch (pkcs7_type) {
    case CMS_SIGN_CLIENT:
        return cryptoctx->id_pkinit_authData;
    case CMS_SIGN_DRAFT9:
        /*
         * Delay creating this OID until we know we need it.
         * It shadows an existing OpenSSL oid.  If it
         * is created too early, it breaks things like
         * the use of pkcs12 (which uses pkcs7 structures).
         * We need this shadow version because our code
         * depends on the "other" type to be unknown to the
         * OpenSSL code.
         */
        if (cryptoctx->id_pkinit_authData9 == NULL) {
            pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
                     __FUNCTION__);
            nid = OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
                             "PKCS7 data");
            if (nid == NID_undef)
                return NULL;
            cryptoctx->id_pkinit_authData9 = OBJ_nid2obj(nid);
        }
        return cryptoctx->id_pkinit_authData9;
    case CMS_SIGN_SERVER:
        return cryptoctx->id_pkinit_DHKeyData;
    case CMS_ENVEL_SERVER:
        return cryptoctx->id_pkinit_rkeyData;
    default:
        return NULL;
    }

}

Project: krb5

prepare_enc_data(unsigned char *indata,
                 int indata_len,
                 unsigned char **outdata,
                 int *outdata_len)
{
    int retval = -1;
    ASN1_const_CTX c;
    long length = indata_len;
    int Ttag, Tclass;
    long Tlen;

    c.pp = (const unsigned char **)&indata;
    c.q = *(const unsigned char **)&indata;
    c.error = ERR_R_NESTED_ASN1_ERROR;
    c.p= *(const unsigned char **)&indata;
    c.max = (length == 0)?0:(c.p+length);

    asn1_GetSequence(&c,&length);

    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
    c.p += Tlen;
    ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);

    asn1_const_Finish(&c);

    *outdata = malloc((size_t)Tlen);
    if (*outdata == NULL) {
        retval = ENOMEM;
        goto cleanup;
    }
    memcpy(*outdata, c.p, (size_t)Tlen);
    *outdata_len = Tlen;

    retval = 0;
cleanup:

    return retval;
}