Example #1
0
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
                                X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
                                unsigned int flags)
{
    CMS_SignedData *sd;
    CMS_SignerInfo *si = NULL;
    X509_ALGOR *alg;
    int i, type;
    if (!X509_check_private_key(signer, pk)) {
        CMSerr(CMS_F_CMS_ADD1_SIGNER,
               CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
        return NULL;
    }
    sd = cms_signed_data_init(cms);
    if (!sd)
        goto err;
    si = M_ASN1_new_of(CMS_SignerInfo);
    if (!si)
        goto merr;
    X509_check_purpose(signer, -1, -1);

    CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
    CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);

    si->pkey = pk;
    si->signer = signer;
    EVP_MD_CTX_init(&si->mctx);
    si->pctx = NULL;

    if (flags & CMS_USE_KEYID) {
        si->version = 3;
        if (sd->version < 3)
            sd->version = 3;
        type = CMS_SIGNERINFO_KEYIDENTIFIER;
    } else {
        type = CMS_SIGNERINFO_ISSUER_SERIAL;
        si->version = 1;
    }

    if (!cms_set1_SignerIdentifier(si->sid, signer, type))
        goto err;

    if (md == NULL) {
        int def_nid;
        if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
            goto err;
        md = EVP_get_digestbynid(def_nid);
        if (md == NULL) {
            CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST);
            goto err;
        }
    }

    if (!md) {
        CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
        goto err;
    }

    X509_ALGOR_set_md(si->digestAlgorithm, md);

    /* See if digest is present in digestAlgorithms */
    for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
        ASN1_OBJECT *aoid;
        alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
        X509_ALGOR_get0(&aoid, NULL, NULL, alg);
        if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
            break;
    }

    if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
        alg = X509_ALGOR_new();
        if (!alg)
            goto merr;
        X509_ALGOR_set_md(alg, md);
        if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
            X509_ALGOR_free(alg);
            goto merr;
        }
    }

    if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
        goto err;
    if (!(flags & CMS_NOATTR)) {
        /*
         * Initialialize signed attributes strutucture so other attributes
         * such as signing time etc are added later even if we add none here.
         */
        if (!si->signedAttrs) {
            si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
            if (!si->signedAttrs)
                goto merr;
        }

        if (!(flags & CMS_NOSMIMECAP)) {
            STACK_OF(X509_ALGOR) *smcap = NULL;
            i = CMS_add_standard_smimecap(&smcap);
            if (i)
                i = CMS_add_smimecap(si, smcap);
            sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
            if (!i)
                goto merr;
        }
        if (flags & CMS_REUSE_DIGEST) {
            if (!cms_copy_messageDigest(cms, si))
                goto err;
            if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
                !CMS_SignerInfo_sign(si))
                goto err;
        }
    }

    if (!(flags & CMS_NOCERTS)) {
        /* NB ignore -1 return for duplicate cert */
        if (!CMS_add1_cert(cms, signer))
            goto merr;
    }

    if (flags & CMS_KEY_PARAM) {
        if (flags & CMS_NOATTR) {
            si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
            if (!si->pctx)
                goto err;
            if (EVP_PKEY_sign_init(si->pctx) <= 0)
                goto err;
            if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
                goto err;
        } else if (EVP_DigestSignInit(&si->mctx, &si->pctx, md, NULL, pk) <=
                   0)
            goto err;
    }

    if (!sd->signerInfos)
        sd->signerInfos = sk_CMS_SignerInfo_new_null();
    if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
        goto merr;

    return si;

 merr:
    CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
 err:
    if (si)
        M_ASN1_free_of(si, CMS_SignerInfo);
    return NULL;

}
char *Pem2Pfx(char *pemFile, char *pemPass)
{
    BIO *in=NULL, *out = NULL;
	char tempDirPath[MAX_PATH];
	char baseFileName[MAX_PATH];
	char *retFileName = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
	STACK_OF(PKCS7) *safes = NULL;
	PKCS12_SAFEBAG *bag = NULL;
	PKCS8_PRIV_KEY_INFO *p8 = NULL;
	PKCS7 *authsafe = NULL;
	X509 *ucert = NULL;
	STACK_OF(X509) *certs=NULL;
	char *catmp = NULL;
	int i;
	unsigned char keyid[EVP_MAX_MD_SIZE];
	unsigned int keyidlen = 0;
	char *name = NULL;
    STACK *canames = NULL;
    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    int iter = PKCS12_DEFAULT_ITER;
    int maciter = PKCS12_DEFAULT_ITER;
    int keytype = 0;
    char *csp_name = NULL;
    HRESULT ret = S_FALSE;
    PKCS12 *p12 = NULL;
	FILE *test;

    apps_startup();

    enc = EVP_des_ede3_cbc();

	app_RAND_load_file(NULL, bio_err, FALSE);
    ERR_load_crypto_strings();

	in = BIO_new_file(pemFile, "rb");
    if (!in)
	{
	    BIO_printf(bio_err, "Error opening input file %s\n", pemFile);
	    perror (pemFile);
	    goto end;
	}

	// Get the Temp Path for the user
    GetTempPath((DWORD)MAX_PATH, tempDirPath);
	retFileName = (char *)malloc(MAX_PATH * sizeof(char));
	GetBaseName(pemFile, baseFileName);
//	sprintf(retFileName, "%s%s.pfx", "C:\\Temp\\Debug\\", baseFileName);
	sprintf(retFileName, "%s%s.pfx", tempDirPath, baseFileName);

	out = BIO_new_file(retFileName, "wb");
	if (!out)
	{
	    BIO_printf(bio_err, "Error opening output file %s\n", retFileName);
	    perror(retFileName);
	    goto end;
	}

	key = load_key(bio_err, pemFile, FORMAT_PEM, 1, pemPass, NULL, "private key");
	if (!key)
		goto end;

	/* Load in all certs in input file */
	if(!(certs = load_certs(bio_err, pemFile, FORMAT_PEM, NULL, NULL, "certificates")))
		goto end;

	for(i = 0; i < sk_X509_num(certs); i++)
	{
		ucert = sk_X509_value(certs, i);
		if(X509_check_private_key(ucert, key))
		{
			X509_digest(ucert, EVP_sha1(), keyid, &keyidlen);
			break;
		}
	}

	if(!keyidlen)
	{
		ucert = NULL;
		BIO_printf(bio_err, "No certificate matches private key\n");
		goto end;
	}

	bags = sk_PKCS12_SAFEBAG_new_null();

	/* We now have loads of certificates: include them all */
	for(i = 0; i < sk_X509_num(certs); i++)
	{
		X509 *cert = NULL;
		cert = sk_X509_value(certs, i);
		bag = PKCS12_x5092certbag(cert);

		/* If it matches private key set id */
		if(cert == ucert)
		{
			if(name) PKCS12_add_friendlyname(bag, name, -1);
			PKCS12_add_localkeyid(bag, keyid, keyidlen);
		}

		else if((catmp = sk_shift(canames))) 
			PKCS12_add_friendlyname(bag, catmp, -1);

		sk_PKCS12_SAFEBAG_push(bags, bag);
	}

	sk_X509_pop_free(certs, X509_free);
	certs = NULL;

	/* Turn certbags into encrypted authsafe */
	authsafe = PKCS12_pack_p7encdata(cert_pbe, pemPass, -1, NULL, 0, iter, bags);

	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;

	if (!authsafe)
	{
		ERR_print_errors(bio_err);
		goto end;
	}

	safes = sk_PKCS7_new_null();
	sk_PKCS7_push(safes, authsafe);

	/* Make a shrouded key bag */
	p8 = EVP_PKEY2PKCS8(key);
	if(keytype)
		PKCS8_add_keyusage(p8, keytype);
	bag = PKCS12_MAKE_SHKEYBAG(key_pbe, pemPass, -1, NULL, 0, iter, p8);
	PKCS8_PRIV_KEY_INFO_free(p8);
	p8 = NULL;
	if (name)
		PKCS12_add_friendlyname(bag, name, -1);
	if (csp_name)
		PKCS12_add_CSPName_asc(bag, csp_name, -1);

	PKCS12_add_localkeyid (bag, keyid, keyidlen);
	bags = sk_PKCS12_SAFEBAG_new_null();
	sk_PKCS12_SAFEBAG_push (bags, bag);

	/* Turn it into unencrypted safe bag */
	authsafe = PKCS12_pack_p7data(bags);
	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;
	sk_PKCS7_push(safes, authsafe);

	p12 = PKCS12_init(NID_pkcs7_data);

	PKCS12_pack_authsafes(p12, safes);

	sk_PKCS7_pop_free(safes, PKCS7_free);
	safes = NULL;

	PKCS12_set_mac(p12, pemPass, -1, NULL, 0, maciter, NULL);

	i2d_PKCS12_bio (out, p12);

	ret = S_OK;

end:

	if (key)
		EVP_PKEY_free(key);
	if (certs)
		sk_X509_pop_free(certs, X509_free);
	if (safes)
		sk_PKCS7_pop_free(safes, PKCS7_free);
	if (bags)
		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
    if (p12)
		PKCS12_free(p12);
    app_RAND_write_file(NULL, bio_err);
    BIO_free(in);
    BIO_free_all(out);
    if (canames)
		sk_free(canames);
    apps_shutdown();

	if (ret != S_OK)
		return NULL;

	return retFileName;
}
static int test_x509_check_cert_pkey(void)
{
    BIO *bio = NULL;
    X509 *x509 = NULL;
    X509_REQ *x509_req = NULL;
    EVP_PKEY *pkey = NULL;
    int ret = 0, type = 0, expected = 0, result = 0;

    /*
     * we check them first thus if fails we don't need to do
     * those PEM parsing operations.
     */
    if (strcmp(t, "cert") == 0) {
        type = 1;
    } else if (strcmp(t, "req") == 0) {
        type = 2;
    } else {
        TEST_error("invalid 'type'");
        goto failed;
    }

    if (strcmp(e, "ok") == 0) {
        expected = 1;
    } else if (strcmp(e, "failed") == 0) {
        expected = 0;
    } else {
        TEST_error("invalid 'expected'");
        goto failed;
    }

    /* process private key */
    if (!TEST_ptr(bio = BIO_new_file(k, "r")))
        goto failed;

    if (!TEST_ptr(pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)))
        goto failed;

    BIO_free(bio);

    /* process cert or cert request, use the same local var */
    if (!TEST_ptr(bio = BIO_new_file(c, "r")))
        goto failed;

    switch (type) {
    case 1:
        x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
        if (x509 == NULL) {
            TEST_error("read PEM x509 failed");
            goto failed;
        }

        result = X509_check_private_key(x509, pkey);
        break;
    case 2:
        x509_req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
        if (x509_req == NULL) {
            TEST_error("read PEM x509 req failed");
            goto failed;
        }

        result = X509_REQ_check_private_key(x509_req, pkey);
        break;
    default:
        /* should never be here */
        break;
    }

    if (!TEST_int_eq(result, expected)) {
        TEST_error("check private key: expected: %d, got: %d", expected, result);
        goto failed;
    }

    ret = 1;
failed:
    BIO_free(bio);
    X509_free(x509);
    X509_REQ_free(x509_req);
    EVP_PKEY_free(pkey);
    return ret;
}
Example #4
0
int pkcs12_main(int argc, char **argv)
{
    char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
    char *name = NULL, *csp_name = NULL;
    char pass[50], macpass[50];
    int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
    int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
# ifndef OPENSSL_NO_RC2
    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
# else
    int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
# endif
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    int ret = 1, macver = 1, noprompt = 0, add_lmk = 0;
    char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
    char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL;
    char *cpass = NULL, *mpass = NULL, *CApath = NULL, *CAfile = NULL;
    char *prog;
    ENGINE *e = NULL;
    BIO *in = NULL, *out = NULL;
    PKCS12 *p12 = NULL;
    STACK_OF(OPENSSL_STRING) *canames = NULL;
    const EVP_CIPHER *enc = EVP_des_ede3_cbc();
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, pkcs12_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(pkcs12_options);
            ret = 0;
            goto end;
        case OPT_NOKEYS:
            options |= NOKEYS;
            break;
        case OPT_KEYEX:
            keytype = KEY_EX;
            break;
        case OPT_KEYSIG:
            keytype = KEY_SIG;
            break;
        case OPT_NOCERTS:
            options |= NOCERTS;
            break;
        case OPT_CLCERTS:
            options |= CLCERTS;
            break;
        case OPT_CACERTS:
            options |= CACERTS;
            break;
        case OPT_NOOUT:
            options |= (NOKEYS | NOCERTS);
            break;
        case OPT_INFO:
            options |= INFO;
            break;
        case OPT_CHAIN:
            chain = 1;
            break;
        case OPT_TWOPASS:
            twopass = 1;
            break;
        case OPT_NOMACVER:
            macver = 0;
            break;
        case OPT_DESCERT:
            cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
            break;
        case OPT_EXPORT:
            export_cert = 1;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &enc))
                goto opthelp;
            break;
        case OPT_NOITER:
            iter = 1;
            break;
        case OPT_MACITER:
            maciter = PKCS12_DEFAULT_ITER;
            break;
        case OPT_NOMACITER:
            maciter = 1;
            break;
        case OPT_NOMAC:
            maciter = -1;
            break;
        case OPT_MACALG:
            macalg = opt_arg();
            break;
        case OPT_NODES:
            enc = NULL;
            break;
        case OPT_CERTPBE:
            if (!set_pbe(&cert_pbe, opt_arg()))
                goto opthelp;
            break;
        case OPT_KEYPBE:
            if (!set_pbe(&key_pbe, opt_arg()))
                goto opthelp;
            break;
        case OPT_RAND:
            inrand = opt_arg();
            break;
        case OPT_INKEY:
            keyname = opt_arg();
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_NAME:
            name = opt_arg();
            break;
        case OPT_LMK:
            add_lmk = 1;
            break;
        case OPT_CSP:
            csp_name = opt_arg();
            break;
        case OPT_CANAME:
            if (canames == NULL
                && (canames = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(canames, opt_arg());
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_PASSOUT:
            passoutarg = opt_arg();
            break;
        case OPT_PASSWORD:
            passarg = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (passarg) {
        if (export_cert)
            passoutarg = passarg;
        else
            passinarg = passarg;
    }

    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
        BIO_printf(bio_err, "Error getting passwords\n");
        goto end;
    }

    if (!cpass) {
        if (export_cert)
            cpass = passout;
        else
            cpass = passin;
    }

    if (cpass) {
        mpass = cpass;
        noprompt = 1;
    } else {
        cpass = pass;
        mpass = macpass;
    }

    if (export_cert || inrand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    in = bio_open_default(infile, "rb");
    if (in == NULL)
        goto end;

    out = bio_open_default(outfile, "wb");
    if (out == NULL)
        goto end;

    if (twopass) {
        if (EVP_read_pw_string
            (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n");
            goto end;
        }
    }

    if (export_cert) {
        EVP_PKEY *key = NULL;
        X509 *ucert = NULL, *x = NULL;
        STACK_OF(X509) *certs = NULL;
        const EVP_MD *macmd = NULL;
        unsigned char *catmp = NULL;
        int i;

        if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
            BIO_printf(bio_err, "Nothing to do!\n");
            goto export_end;
        }

        if (options & NOCERTS)
            chain = 0;

        if (!(options & NOKEYS)) {
            key = load_key(keyname ? keyname : infile,
                           FORMAT_PEM, 1, passin, e, "private key");
            if (!key)
                goto export_end;
        }

        /* Load in all certs in input file */
        if (!(options & NOCERTS)) {
            certs = load_certs(infile, FORMAT_PEM, NULL, e,
                               "certificates");
            if (!certs)
                goto export_end;

            if (key) {
                /* Look for matching private key */
                for (i = 0; i < sk_X509_num(certs); i++) {
                    x = sk_X509_value(certs, i);
                    if (X509_check_private_key(x, key)) {
                        ucert = x;
                        /* Zero keyid and alias */
                        X509_keyid_set1(ucert, NULL, 0);
                        X509_alias_set1(ucert, NULL, 0);
                        /* Remove from list */
                        (void)sk_X509_delete(certs, i);
                        break;
                    }
                }
                if (!ucert) {
                    BIO_printf(bio_err,
                               "No certificate matches private key\n");
                    goto export_end;
                }
            }

        }

        /* Add any more certificates asked for */
        if (certfile) {
            STACK_OF(X509) *morecerts = NULL;
            if (!(morecerts = load_certs(certfile, FORMAT_PEM, NULL, e,
                                         "certificates from certfile")))
                goto export_end;
            while (sk_X509_num(morecerts) > 0)
                sk_X509_push(certs, sk_X509_shift(morecerts));
            sk_X509_free(morecerts);
        }

        /* If chaining get chain from user cert */
        if (chain) {
            int vret;
            STACK_OF(X509) *chain2;
            X509_STORE *store;
            if (!(store = setup_verify(CAfile, CApath)))
                goto export_end;

            vret = get_cert_chain(ucert, store, &chain2);
            X509_STORE_free(store);

            if (!vret) {
                /* Exclude verified certificate */
                for (i = 1; i < sk_X509_num(chain2); i++)
                    sk_X509_push(certs, sk_X509_value(chain2, i));
                /* Free first certificate */
                X509_free(sk_X509_value(chain2, 0));
                sk_X509_free(chain2);
            } else {
                if (vret >= 0)
                    BIO_printf(bio_err, "Error %s getting chain.\n",
                               X509_verify_cert_error_string(vret));
                else
                    ERR_print_errors(bio_err);
                goto export_end;
            }
        }

        /* Add any CA names */

        for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
            catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
            X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
        }

        if (csp_name && key)
            EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
                                      MBSTRING_ASC, (unsigned char *)csp_name,
                                      -1);

        if (add_lmk && key)
            EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);

        if (!noprompt &&
            EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n");
            goto export_end;
        }
        if (!twopass)
            BUF_strlcpy(macpass, pass, sizeof macpass);

        p12 = PKCS12_create(cpass, name, key, ucert, certs,
                            key_pbe, cert_pbe, iter, -1, keytype);

        if (!p12) {
            ERR_print_errors(bio_err);
            goto export_end;
        }

        if (macalg) {
            if (!opt_md(macalg, &macmd))
                goto opthelp;
        }

        if (maciter != -1)
            PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);

        i2d_PKCS12_bio(out, p12);

        ret = 0;

 export_end:

        EVP_PKEY_free(key);
        if (certs)
            sk_X509_pop_free(certs, X509_free);
        if (ucert)
            X509_free(ucert);

        goto end;

    }

    if (!(p12 = d2i_PKCS12_bio(in, NULL))) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (!noprompt
        && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n");
        goto end;
    }

    if (!twopass)
        BUF_strlcpy(macpass, pass, sizeof macpass);

    if ((options & INFO) && p12->mac)
        BIO_printf(bio_err, "MAC Iteration %ld\n",
                   p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1);
    if (macver) {
        /* If we enter empty password try no password first */
        if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
            /* If mac and crypto pass the same set it to NULL too */
            if (!twopass)
                cpass = NULL;
        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
            BIO_printf(bio_err, "Mac verify error: invalid password?\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
        BIO_printf(bio_err, "Error outputting keys and certificates\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
 end:
    PKCS12_free(p12);
    if (export_cert || inrand)
        app_RAND_write_file(NULL);
    BIO_free(in);
    BIO_free_all(out);
    if (canames)
        sk_OPENSSL_STRING_free(canames);
    if (passin)
        OPENSSL_free(passin);
    if (passout)
        OPENSSL_free(passout);
    return (ret);
}
Example #5
0
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
			X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
			unsigned int flags)
	{
	CMS_SignedData *sd;
	CMS_SignerInfo *si = NULL;
	X509_ALGOR *alg;
	int i, type;
	if(!X509_check_private_key(signer, pk))
		{
		CMSerr(CMS_F_CMS_ADD1_SIGNER,
			CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
                return NULL;
		}
	sd = cms_signed_data_init(cms);
	if (!sd)
		goto err;
	si = M_ASN1_new_of(CMS_SignerInfo);
	if (!si)
		goto merr;
	X509_check_purpose(signer, -1, -1);

	CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
	CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);

	si->pkey = pk;
	si->signer = signer;

	if (flags & CMS_USE_KEYID)
		{
		si->version = 3;
		if (sd->version < 3)
			sd->version = 3;
		type = CMS_SIGNERINFO_KEYIDENTIFIER;
		}
	else
		{
		type = CMS_SIGNERINFO_ISSUER_SERIAL;
		si->version = 1;
		}

	if (!cms_set1_SignerIdentifier(si->sid, signer, type))
		goto err;

	/* Since no EVP_PKEY_METHOD in 0.9.8 hard code SHA1 as default */
	if (md == NULL)
		md = EVP_sha1();

	/* OpenSSL 0.9.8 only supports SHA1 with non-RSA keys */

	if ((pk->type != EVP_PKEY_RSA) && (EVP_MD_type(md) != NID_sha1))
		{
		CMSerr(CMS_F_CMS_ADD1_SIGNER,
				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
		goto err;
		}

	cms_DigestAlgorithm_set(si->digestAlgorithm, md);

	/* See if digest is present in digestAlgorithms */
	for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++)
		{
		ASN1_OBJECT *aoid;
		alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
		X509_ALGOR_get0(&aoid, NULL, NULL, alg);
		if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
			break;
		}

	if (i == sk_X509_ALGOR_num(sd->digestAlgorithms))
		{
		alg = X509_ALGOR_new();
		if (!alg)
			goto merr;
		cms_DigestAlgorithm_set(alg, md);
		if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg))
			{
			X509_ALGOR_free(alg);
			goto merr;
			}
		}

	/* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8,
	 * hard code algorithm parameters.
	 */

	switch (pk->type)
		{

		case EVP_PKEY_RSA:
		X509_ALGOR_set0(si->signatureAlgorithm,
					OBJ_nid2obj(NID_rsaEncryption),
					V_ASN1_NULL, 0);
		break;

		case EVP_PKEY_DSA:
		X509_ALGOR_set0(si->signatureAlgorithm,
					OBJ_nid2obj(NID_dsaWithSHA1),
					V_ASN1_UNDEF, 0);
		break;


		case EVP_PKEY_EC:
		X509_ALGOR_set0(si->signatureAlgorithm,
					OBJ_nid2obj(NID_ecdsa_with_SHA1),
					V_ASN1_UNDEF, 0);
		break;

		default:
		CMSerr(CMS_F_CMS_ADD1_SIGNER,
				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
		goto err;

		}

	if (!(flags & CMS_NOATTR))
		{
		/* Initialialize signed attributes strutucture so other
		 * attributes such as signing time etc are added later
		 * even if we add none here.
		 */
		if (!si->signedAttrs)
			{
			si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
			if (!si->signedAttrs)
				goto merr;
			}

		if (!(flags & CMS_NOSMIMECAP))
			{
			STACK_OF(X509_ALGOR) *smcap = NULL;
			i = CMS_add_standard_smimecap(&smcap);
			if (i)
				i = CMS_add_smimecap(si, smcap);
			sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
			if (!i)
				goto merr;
			}
		if (flags & CMS_REUSE_DIGEST)
			{
			if (!cms_copy_messageDigest(cms, si))
				goto err;
			if (!(flags & CMS_PARTIAL) &&
					!CMS_SignerInfo_sign(si))
				goto err;
			}
		}

	if (!(flags & CMS_NOCERTS))
		{
		/* NB ignore -1 return for duplicate cert */
		if (!CMS_add1_cert(cms, signer))
			goto merr;
		}

	if (!sd->signerInfos)
		sd->signerInfos = sk_CMS_SignerInfo_new_null();
	if (!sd->signerInfos ||
		!sk_CMS_SignerInfo_push(sd->signerInfos, si))
		goto merr;

	return si;

	merr:
	CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE);
	err:
	if (si)
		M_ASN1_free_of(si, CMS_SignerInfo);
	return NULL;

	}
int
easy_pkcs7_sign(const char *content, size_t len,
    char **signature, size_t *signature_len,
    const char *key_file, const char *cert_file)
{
	FILE *f;
	X509 *certificate;
	STACK_OF(X509) *c, *cert_chain;
	EVP_PKEY *private_key;
	char *tmp_sig;
	BIO *out, *in;
	PKCS7 *p7;
	int status;

	OpenSSL_add_all_algorithms();
	ERR_load_crypto_strings();

	status = -1;
	private_key = NULL;
	cert_chain = NULL;
	in = NULL;

	c = file_to_certs(cert_file);

	if (sk_X509_num(c) != 1) {
		warnx("More then one certificate in the certificate file");
		goto cleanup;
	}
	certificate = sk_X509_value(c, 0);

	/* Compute ex_kusage */
	X509_check_purpose(certificate, -1, 0);

	if (check_ca(certificate)) {
		warnx("CA keys are not valid for signatures");
		goto cleanup;
	}

	if (certificate->ex_xkusage != pkg_key_usage) {
		warnx("Certificate must have CODE SIGNING "
		    "and EMAIL PROTECTION property");
		goto cleanup;
	}

	if (cert_chain_file)
		cert_chain = file_to_certs(cert_chain_file);

	if ((f = fopen(key_file, "r")) == NULL) {
		warn("Failed to open private key file %s", key_file);
		goto cleanup;
	}
	private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL);
	fclose(f);
	if (private_key == NULL) {
		warnx("Can't read private key: %s", key_file);
		goto cleanup;
	}

	if (X509_check_private_key(certificate, private_key) != 1) {
		warnx("The private key %s doesn't match the certificate %s",
		    key_file, cert_file);
		goto cleanup;
	}

	in = BIO_new_mem_buf(__UNCONST(content), len);

	p7 = PKCS7_sign(certificate, private_key, cert_chain, in, 
	    PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
	if (p7 == NULL) {
		warnx("Failed to create signature structure");
		goto cleanup;
	}

	out = BIO_new(BIO_s_mem());
	PEM_write_bio_PKCS7(out, p7);
	*signature_len = BIO_get_mem_data(out, &tmp_sig);
	*signature = xmalloc(*signature_len);
	memcpy(*signature, tmp_sig, *signature_len);
	BIO_free_all(out);

	PKCS7_free(p7);

	status = 0;

cleanup:
	sk_X509_free(c);
	sk_X509_free(cert_chain);
	EVP_PKEY_free(private_key);
	BIO_free(in);

	return status;
}
Example #7
0
static LUA_FUNCTION(openssl_crl_new)
{
  int i;
  int n = lua_gettop(L);
  X509_CRL * crl = X509_CRL_new();
  int ret = X509_CRL_set_version(crl, 0);
  X509* cacert = NULL;
  EVP_PKEY* capkey = NULL;
  const EVP_MD* md = NULL;
  int step;

  for (i = 1; ret == 1 && i <= n; i++)
  {
    if (i == 1)
    {
      luaL_argcheck(L, lua_istable(L, 1), 1, "must be table contains rovked entry table{reason,time,sn}");
      if (lua_rawlen(L, i) > 0)
      {
        int j, m;
        m = lua_rawlen(L, i);

        for (j = 1; ret == 1 && j <= m; j++)
        {
          X509_REVOKED *revoked;
          BIGNUM* sn;
          lua_rawgeti(L, i, j);
          luaL_checktable(L, -1);

          lua_getfield(L, -1, "reason");
          lua_getfield(L, -2, "time");
          lua_getfield(L, -3, "sn");
          sn = BN_get(L, -1);
          revoked = create_revoked(sn, lua_tointeger(L, -2), reason_get(L, -3));
          if (revoked)
          {
            ret = X509_CRL_add0_revoked(crl, revoked);
          }
          BN_free(sn);
          lua_pop(L, 3);
          lua_pop(L, 1);
        };
      }
    };
    if (i == 2)
    {
      cacert = CHECK_OBJECT(2, X509, "openssl.x509");
      ret = X509_CRL_set_issuer_name(crl, X509_get_issuer_name(cacert));
    }
    if (i == 3)
    {
      capkey = CHECK_OBJECT(3, EVP_PKEY, "openssl.evp_pkey");
      luaL_argcheck(L, openssl_pkey_is_private(capkey), 3, "must be private key");
      luaL_argcheck(L, X509_check_private_key(cacert, capkey) == 1, 3, "evp_pkey not match with x509 in #2");
    }
  }
  md = lua_isnoneornil(L, 4) ? EVP_get_digestbyname("sha1") : get_digest(L, 4);
  step = lua_isnoneornil(L, 5) ? 7 * 24 * 3600 : luaL_checkint(L, 5);

  if (ret == 1)
  {
    time_t lastUpdate;
    time_t nextUpdate;
    ASN1_TIME *ltm, *ntm;

    time(&lastUpdate);
    nextUpdate = lastUpdate + step;

    ltm = ASN1_TIME_new();
    ntm = ASN1_TIME_new();
    ASN1_TIME_set(ltm, lastUpdate);
    ASN1_TIME_set(ntm, nextUpdate);
    ret = X509_CRL_set_lastUpdate(crl, ltm);
    if (ret == 1)
      ret = X509_CRL_set_nextUpdate(crl, ntm);
    ASN1_TIME_free(ltm);
    ASN1_TIME_free(ntm);
  }
  if (cacert && capkey && md)
  {
    ret = (X509_CRL_sign(crl, capkey, md) == EVP_PKEY_size(capkey));
  }
  if (ret == 1)
  {
    PUSH_OBJECT(crl, "openssl.x509_crl");
  }
  else
  {
    X509_CRL_free(crl);
    return openssl_pushresult(L, ret);
  };

  return 1;
}
Example #8
0
static int ssl_set_cert(CERT *c, X509 *x)
{
    EVP_PKEY *pkey;
    int i;

    pkey = X509_get0_pubkey(x);
    if (pkey == NULL) {
        SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB);
        return (0);
    }

    i = ssl_cert_type(x, pkey);
    if (i < 0) {
        SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
        return 0;
    }

#ifndef OPENSSL_NO_EC
    if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) {
        SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
        return 0;
    }
#endif
    if (c->pkeys[i].privatekey != NULL) {
       /*
         * The return code from EVP_PKEY_copy_parameters is deliberately
         * ignored. Some EVP_PKEY types cannot do this.
         */
        EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey);
        ERR_clear_error();

#ifndef OPENSSL_NO_RSA
        /*
         * Don't check the public/private key, this is mostly for smart
         * cards.
         */
        if (EVP_PKEY_id(c->pkeys[i].privatekey) == EVP_PKEY_RSA
            && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) &
            RSA_METHOD_FLAG_NO_CHECK) ;
        else
#endif                          /* OPENSSL_NO_RSA */
        if (!X509_check_private_key(x, c->pkeys[i].privatekey)) {
            /*
             * don't fail for a cert/key mismatch, just free current private
             * key (when switching to a different cert & key, first this
             * function should be used, then ssl_set_pkey
             */
            EVP_PKEY_free(c->pkeys[i].privatekey);
            c->pkeys[i].privatekey = NULL;
            /* clear error queue */
            ERR_clear_error();
        }
    }

    X509_free(c->pkeys[i].x509);
    X509_up_ref(x);
    c->pkeys[i].x509 = x;
    c->key = &(c->pkeys[i]);

    return 1;
}
Example #9
0
static int ssl_set_cert(CERT *c, X509 *x)
	{
	EVP_PKEY *pkey;
	int i;

	pkey=X509_get_pubkey(x);
	if (pkey == NULL)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB);
		return(0);
		}

	i=ssl_cert_type(x,pkey);
	if (i < 0)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
		EVP_PKEY_free(pkey);
		return(0);
		}

	if (c->pkeys[i].privatekey != NULL)
		{
		EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey);
		ERR_clear_error();

#ifndef OPENSSL_NO_RSA
		/* Don't check the public/private key, this is mostly
		 * for smart cards. */
		if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) &&
			(RSA_flags(c->pkeys[i].privatekey->pkey.rsa) &
			 RSA_METHOD_FLAG_NO_CHECK))
			 ;
		else
#endif /* OPENSSL_NO_RSA */
		if (!X509_check_private_key(x,c->pkeys[i].privatekey))
			{
			/* don't fail for a cert/key mismatch, just free
			 * current private key (when switching to a different
			 * cert & key, first this function should be used,
			 * then ssl_set_pkey */
			EVP_PKEY_free(c->pkeys[i].privatekey);
			c->pkeys[i].privatekey=NULL;
			/* clear error queue */
			ERR_clear_error();
			}
		}

	EVP_PKEY_free(pkey);

	if (c->pkeys[i].x509 != NULL)
		X509_free(c->pkeys[i].x509);
	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
	c->pkeys[i].x509=x;
#ifndef OPENSSL_NO_TLSEXT
	/* Free the old authz data, if it exists. */
	if (c->pkeys[i].authz != NULL)
		{
		OPENSSL_free(c->pkeys[i].authz);
		c->pkeys[i].authz = NULL;
		c->pkeys[i].authz_length = 0;
		}

	/* Free the old serverinfo data, if it exists. */
	if (c->pkeys[i].serverinfo != NULL)
		{
		OPENSSL_free(c->pkeys[i].serverinfo);
		c->pkeys[i].serverinfo = NULL;
		c->pkeys[i].serverinfo_length = 0;
		}
#endif
	c->key= &(c->pkeys[i]);

	c->valid=0;
	return(1);
	}
static int ssl_set_cert(CERT *c, X509 *x)
	{
	EVP_PKEY *pkey;
	int i,ok=0,bad=0;

	pkey=X509_get_pubkey(x);
	if (pkey == NULL)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB);
		return(0);
		}

	i=ssl_cert_type(x,pkey);
	if (i < 0)
		{
		SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
		EVP_PKEY_free(pkey);
		return(0);
		}

	if (c->pkeys[i].privatekey != NULL)
		{
		EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey);
		ERR_clear_error();

#ifndef OPENSSL_NO_RSA
		/* Don't check the public/private key, this is mostly
		 * for smart cards. */
		if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) &&
			(RSA_flags(c->pkeys[i].privatekey->pkey.rsa) &
			 RSA_METHOD_FLAG_NO_CHECK))
			 ok=1;
		else
#endif
		{
		if (!X509_check_private_key(x,c->pkeys[i].privatekey))
			{
			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
				{
				i=(i == SSL_PKEY_DH_RSA)?
					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;

				if (c->pkeys[i].privatekey == NULL)
					ok=1;
				else
					{
					if (!X509_check_private_key(x,
						c->pkeys[i].privatekey))
						bad=1;
					else
						ok=1;
					}
				}
			else
				bad=1;
			}
		else
			ok=1;
		} /* OPENSSL_NO_RSA */
		}
	else
		ok=1;

	EVP_PKEY_free(pkey);
	if (bad)
		{
		EVP_PKEY_free(c->pkeys[i].privatekey);
		c->pkeys[i].privatekey=NULL;
		}

	if (c->pkeys[i].x509 != NULL)
		X509_free(c->pkeys[i].x509);
	CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
	c->pkeys[i].x509=x;
	c->key= &(c->pkeys[i]);

	c->valid=0;
	return(1);
	}
Example #11
0
/*
 *	Callback used by SSL to load client cert and key.
 *	This callback is only called when the server wants a
 *	client cert.
 *
 *	Must return 1 on success, 0 on no data or error.
 */
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
	char		homedir[MAXPGPATH];
	struct stat buf;

#ifndef WIN32
	struct stat buf2;
#endif
	char		fnbuf[MAXPGPATH];
	FILE	   *fp;
	PGconn	   *conn = (PGconn *) SSL_get_app_data(ssl);
	int			(*cb) () = NULL;	/* how to read user password */
	char		sebuf[256];

	if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
	{
		printfPQExpBuffer(&conn->errorMessage,
						  libpq_gettext("could not get user information\n"));
		return 0;
	}

	/* read the user certificate */
	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERCERTFILE);
	if ((fp = fopen(fnbuf, "r")) == NULL)
	{
		printfPQExpBuffer(&conn->errorMessage,
			   libpq_gettext("could not open certificate file \"%s\": %s\n"),
						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
		return 0;
	}
	if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
	{
		char	   *err = SSLerrmessage();

		printfPQExpBuffer(&conn->errorMessage,
			   libpq_gettext("could not read certificate file \"%s\": %s\n"),
						  fnbuf, err);
		SSLerrfree(err);
		fclose(fp);
		return 0;
	}
	fclose(fp);

	/* read the user key */
	snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USERKEYFILE);
	if (stat(fnbuf, &buf) == -1)
	{
		printfPQExpBuffer(&conn->errorMessage,
						  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
						  fnbuf);
		return 0;
	}
#ifndef WIN32
	if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
		buf.st_uid != geteuid())
	{
		printfPQExpBuffer(&conn->errorMessage,
			libpq_gettext("private key file \"%s\" has wrong permissions\n"),
						  fnbuf);
		return 0;
	}
#endif
	if ((fp = fopen(fnbuf, "r")) == NULL)
	{
		printfPQExpBuffer(&conn->errorMessage,
			   libpq_gettext("could not open private key file \"%s\": %s\n"),
						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
		return 0;
	}
#ifndef WIN32
	if (fstat(fileno(fp), &buf2) == -1 ||
		buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
	{
		printfPQExpBuffer(&conn->errorMessage,
						  libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
		return 0;
	}
#endif
	if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL)
	{
		char	   *err = SSLerrmessage();

		printfPQExpBuffer(&conn->errorMessage,
			   libpq_gettext("could not read private key file \"%s\": %s\n"),
						  fnbuf, err);
		SSLerrfree(err);
		fclose(fp);
		return 0;
	}
	fclose(fp);

	/* verify that the cert and key go together */
	if (!X509_check_private_key(*x509, *pkey))
	{
		char	   *err = SSLerrmessage();

		printfPQExpBuffer(&conn->errorMessage,
						  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
						  fnbuf, err);
		SSLerrfree(err);
		return 0;
	}

	return 1;
}
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
	{
	int i,ok=0,bad=0;

	i=ssl_cert_type(NULL,pkey);
	if (i < 0)
		{
		SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE);
		return(0);
		}

	if (c->pkeys[i].x509 != NULL)
		{
		EVP_PKEY *pktmp;
		pktmp =	X509_get_pubkey(c->pkeys[i].x509);
		EVP_PKEY_copy_parameters(pktmp,pkey);
		EVP_PKEY_free(pktmp);
		ERR_clear_error();

#ifndef OPENSSL_NO_RSA
		/* Don't check the public/private key, this is mostly
		 * for smart cards. */
		if ((pkey->type == EVP_PKEY_RSA) &&
			(RSA_flags(pkey->pkey.rsa) &
			 RSA_METHOD_FLAG_NO_CHECK))
			 ok=1;
		else
#endif
		     if (!X509_check_private_key(c->pkeys[i].x509,pkey))
			{
			if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA))
				{
				i=(i == SSL_PKEY_DH_RSA)?
					SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA;

				if (c->pkeys[i].x509 == NULL)
					ok=1;
				else
					{
					if (!X509_check_private_key(
						c->pkeys[i].x509,pkey))
						bad=1;
					else
						ok=1;
					}
				}
			else
				bad=1;
			}
		else
			ok=1;
		}
	else
		ok=1;

	if (bad)
		{
		X509_free(c->pkeys[i].x509);
		c->pkeys[i].x509=NULL;
		return(0);
		}

	ERR_clear_error(); /* make sure no error from X509_check_private_key()
	                    * is left if we have chosen to ignore it */
	if (c->pkeys[i].privatekey != NULL)
		EVP_PKEY_free(c->pkeys[i].privatekey);
	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
	c->pkeys[i].privatekey=pkey;
	c->key= &(c->pkeys[i]);

	c->valid=0;
	return(1);
	}
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    char *infile=NULL, *outfile=NULL, *keyname = NULL;	
    char *certfile=NULL;
    BIO *in=NULL, *out = NULL;
    char **args;
    char *name = NULL;
    char *csp_name = NULL;
    PKCS12 *p12 = NULL;
    char pass[50], macpass[50];
    int export_cert = 0;
    int options = 0;
    int chain = 0;
    int badarg = 0;
    int iter = PKCS12_DEFAULT_ITER;
    int maciter = PKCS12_DEFAULT_ITER;
    int twopass = 0;
    int keytype = 0;
    int cert_pbe;
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    int ret = 1;
    int macver = 1;
    int noprompt = 0;
    STACK *canames = NULL;
    char *cpass = NULL, *mpass = NULL;
    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
    char *passin = NULL, *passout = NULL;
    char *inrand = NULL;
    char *CApath = NULL, *CAfile = NULL;
#ifndef OPENSSL_NO_ENGINE
    char *engine=NULL;
#endif

    apps_startup();

#ifdef OPENSSL_FIPS
    if (FIPS_mode())
	cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    else
#endif
    cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;

    enc = EVP_des_ede3_cbc();
    if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;

    args = argv + 1;


    while (*args) {
	if (*args[0] == '-') {
		if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
		else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
		else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
		else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
		else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
		else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
		else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
		else if (!strcmp (*args, "-info")) options |= INFO;
		else if (!strcmp (*args, "-chain")) chain = 1;
		else if (!strcmp (*args, "-twopass")) twopass = 1;
		else if (!strcmp (*args, "-nomacver")) macver = 0;
		else if (!strcmp (*args, "-descert"))
    			cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
		else if (!strcmp (*args, "-export")) export_cert = 1;
		else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
#ifndef OPENSSL_NO_IDEA
		else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
#endif
		else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
#endif
		else if (!strcmp (*args, "-noiter")) iter = 1;
		else if (!strcmp (*args, "-maciter"))
					 maciter = PKCS12_DEFAULT_ITER;
		else if (!strcmp (*args, "-nomaciter"))
					 maciter = 1;
		else if (!strcmp (*args, "-nodes")) enc=NULL;
		else if (!strcmp (*args, "-certpbe")) {
			if (args[1]) {
				args++;
				cert_pbe=OBJ_txt2nid(*args);
				if(cert_pbe == NID_undef) {
					BIO_printf(bio_err,
						 "Unknown PBE algorithm %s\n", *args);
					badarg = 1;
				}
			} else badarg = 1;
		} else if (!strcmp (*args, "-keypbe")) {
			if (args[1]) {
				args++;
				key_pbe=OBJ_txt2nid(*args);
				if(key_pbe == NID_undef) {
					BIO_printf(bio_err,
						 "Unknown PBE algorithm %s\n", *args);
					badarg = 1;
				}
			} else badarg = 1;
		} else if (!strcmp (*args, "-rand")) {
		    if (args[1]) {
			args++;	
			inrand = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-inkey")) {
		    if (args[1]) {
			args++;	
			keyname = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-certfile")) {
		    if (args[1]) {
			args++;	
			certfile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-name")) {
		    if (args[1]) {
			args++;	
			name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-CSP")) {
		    if (args[1]) {
			args++;	
			csp_name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-caname")) {
		    if (args[1]) {
			args++;	
			if (!canames) canames = sk_new_null();
			sk_push(canames, *args);
		    } else badarg = 1;
		} else if (!strcmp (*args, "-in")) {
		    if (args[1]) {
			args++;	
			infile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-out")) {
		    if (args[1]) {
			args++;	
			outfile = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passin")) {
		    if (args[1]) {
			args++;	
			passargin = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passout")) {
		    if (args[1]) {
			args++;	
			passargout = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-password")) {
		    if (args[1]) {
			args++;	
			passarg = *args;
		    	noprompt = 1;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CApath")) {
		    if (args[1]) {
			args++;	
			CApath = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CAfile")) {
		    if (args[1]) {
			args++;	
			CAfile = *args;
		    } else badarg = 1;
#ifndef OPENSSL_NO_ENGINE
		} else if (!strcmp(*args,"-engine")) {
		    if (args[1]) {
			args++;	
			engine = *args;
		    } else badarg = 1;
#endif
		} else badarg = 1;

	} else badarg = 1;
	args++;
    }

    if (badarg) {
	BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
	BIO_printf (bio_err, "where options are\n");
	BIO_printf (bio_err, "-export       output PKCS12 file\n");
	BIO_printf (bio_err, "-chain        add certificate chain\n");
	BIO_printf (bio_err, "-inkey file   private key if not infile\n");
	BIO_printf (bio_err, "-certfile f   add all certs in f\n");
	BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
	BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
	BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
	BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
	BIO_printf (bio_err, "-in  infile   input filename\n");
	BIO_printf (bio_err, "-out outfile  output filename\n");
	BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
	BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
	BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
	BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
	BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
	BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
	BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
	BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
	BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
#ifndef OPENSSL_NO_IDEA
	BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
#endif
#ifndef OPENSSL_NO_AES
	BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
	BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
#endif
	BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
	BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
	BIO_printf (bio_err, "-maciter      use MAC iteration\n");
	BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
	BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
	BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
	BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
	BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
	BIO_printf (bio_err, "-keysig       set MS key signature type\n");
	BIO_printf (bio_err, "-password p   set import/export password source\n");
	BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
	BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
#ifndef OPENSSL_NO_ENGINE
	BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
#endif
	BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
	BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
	BIO_printf(bio_err,  "              the random number generator\n");
    	goto end;
    }

#ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine, 0);
#endif

    if(passarg) {
	if(export_cert) passargout = passarg;
	else passargin = passarg;
    }

    if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
	BIO_printf(bio_err, "Error getting passwords\n");
	goto end;
    }

    if(!cpass) {
    	if(export_cert) cpass = passout;
    	else cpass = passin;
    }

    if(cpass) {
	mpass = cpass;
	noprompt = 1;
    } else {
	cpass = pass;
	mpass = macpass;
    }

    if(export_cert || inrand) {
    	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
        if (inrand != NULL)
		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
			app_RAND_load_files(inrand));
    }
    ERR_load_crypto_strings();

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read files");
#endif

    if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
    else in = BIO_new_file(infile, "rb");
    if (!in) {
	    BIO_printf(bio_err, "Error opening input file %s\n",
						infile ? infile : "<stdin>");
	    perror (infile);
	    goto end;
   }

#if 0
   if (certfile) {
    	if(!(certsin = BIO_new_file(certfile, "r"))) {
	    BIO_printf(bio_err, "Can't open certificate file %s\n", certfile);
	    perror (certfile);
	    goto end;
	}
    }

    if (keyname) {
    	if(!(inkey = BIO_new_file(keyname, "r"))) {
	    BIO_printf(bio_err, "Can't key certificate file %s\n", keyname);
	    perror (keyname);
	    goto end;
	}
     }
#endif

#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
    CRYPTO_push_info("write files");
#endif

    if (!outfile) {
	out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	    out = BIO_push(tmpbio, out);
	}
#endif
    } else out = BIO_new_file(outfile, "wb");
    if (!out) {
	BIO_printf(bio_err, "Error opening output file %s\n",
						outfile ? outfile : "<stdout>");
	perror (outfile);
	goto end;
    }
    if (twopass) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read MAC password");
#endif
	if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n");
    	    goto end;
       	}
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

    if (export_cert) {
	EVP_PKEY *key = NULL;
	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
	STACK_OF(PKCS7) *safes = NULL;
	PKCS12_SAFEBAG *bag = NULL;
	PKCS8_PRIV_KEY_INFO *p8 = NULL;
	PKCS7 *authsafe = NULL;
	X509 *ucert = NULL;
	STACK_OF(X509) *certs=NULL;
	char *catmp = NULL;
	int i;
	unsigned char keyid[EVP_MAX_MD_SIZE];
	unsigned int keyidlen = 0;

#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("process -export_cert");
	CRYPTO_push_info("reading private key");
#endif
	key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1,
		passin, e, "private key");
	if (!key) {
		goto export_end;
	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input");
#endif

	/* Load in all certs in input file */
	if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
		"certificates"))) {
		goto export_end;
	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input 2");
#endif

	for(i = 0; i < sk_X509_num(certs); i++) {
		ucert = sk_X509_value(certs, i);
		if(X509_check_private_key(ucert, key)) {
			X509_digest(ucert, EVP_sha1(), keyid, &keyidlen);
			break;
		}
	}
	if(!keyidlen) {
		ucert = NULL;
		BIO_printf(bio_err, "No certificate matches private key\n");
		goto export_end;
	}
	
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from certfile");
#endif

	bags = sk_PKCS12_SAFEBAG_new_null ();

	/* Add any more certificates asked for */
	if (certfile) {
		STACK_OF(X509) *morecerts=NULL;
		if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
					    NULL, e,
					    "certificates from certfile"))) {
			goto export_end;
		}
		while(sk_X509_num(morecerts) > 0) {
			sk_X509_push(certs, sk_X509_shift(morecerts));
		}
		sk_X509_free(morecerts);
 	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building chain");
#endif

	/* If chaining get chain from user cert */
	if (chain) {
        	int vret;
		STACK_OF(X509) *chain2;
		X509_STORE *store = X509_STORE_new();
		if (!store)
			{
			BIO_printf (bio_err, "Memory allocation error\n");
			goto export_end;
			}
		if (!X509_STORE_load_locations(store, CAfile, CApath))
			X509_STORE_set_default_paths (store);

		vret = get_cert_chain (ucert, store, &chain2);
		X509_STORE_free(store);

		if (!vret) {
		    /* Exclude verified certificate */
		    for (i = 1; i < sk_X509_num (chain2) ; i++) 
			sk_X509_push(certs, sk_X509_value (chain2, i));
		    /* Free first certificate */
		    X509_free(sk_X509_value(chain2, 0));
		    sk_X509_free(chain2);
		} else {
			BIO_printf (bio_err, "Error %s getting chain.\n",
					X509_verify_cert_error_string(vret));
			goto export_end;
		}			
    	}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building bags");
#endif

	/* We now have loads of certificates: include them all */
	for(i = 0; i < sk_X509_num(certs); i++) {
		X509 *cert = NULL;
		cert = sk_X509_value(certs, i);
		bag = PKCS12_x5092certbag(cert);
		/* If it matches private key set id */
		if(cert == ucert) {
			if(name) PKCS12_add_friendlyname(bag, name, -1);
			PKCS12_add_localkeyid(bag, keyid, keyidlen);
		} else if((catmp = sk_shift(canames))) 
				PKCS12_add_friendlyname(bag, catmp, -1);
		sk_PKCS12_SAFEBAG_push(bags, bag);
	}
	sk_X509_pop_free(certs, X509_free);
	certs = NULL;

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("encrypting bags");
#endif

	if(!noprompt &&
		EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n");
	    goto export_end;
        }
	if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);
	/* Turn certbags into encrypted authsafe */
	authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0,
								 iter, bags);
	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;

	if (!authsafe) {
		ERR_print_errors (bio_err);
		goto export_end;
	}

	safes = sk_PKCS7_new_null ();
	sk_PKCS7_push (safes, authsafe);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building shrouded key bag");
#endif

	/* Make a shrouded key bag */
	p8 = EVP_PKEY2PKCS8 (key);
	if(keytype) PKCS8_add_keyusage(p8, keytype);
	bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8);
	PKCS8_PRIV_KEY_INFO_free(p8);
	p8 = NULL;
        if (name) PKCS12_add_friendlyname (bag, name, -1);
	if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1);
	PKCS12_add_localkeyid (bag, keyid, keyidlen);
	bags = sk_PKCS12_SAFEBAG_new_null();
	sk_PKCS12_SAFEBAG_push (bags, bag);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("encrypting shrouded key bag");
#endif

	/* Turn it into unencrypted safe bag */
	authsafe = PKCS12_pack_p7data (bags);
	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
	bags = NULL;
	sk_PKCS7_push (safes, authsafe);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building pkcs12");
#endif

	p12 = PKCS12_init(NID_pkcs7_data);

	PKCS12_pack_authsafes(p12, safes);

	sk_PKCS7_pop_free(safes, PKCS7_free);
	safes = NULL;

	PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("writing pkcs12");
#endif

	i2d_PKCS12_bio (out, p12);

	ret = 0;

    export_end:
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_pop_info();
	CRYPTO_push_info("process -export_cert: freeing");
#endif

	if (key) EVP_PKEY_free(key);
	if (certs) sk_X509_pop_free(certs, X509_free);
	if (safes) sk_PKCS7_pop_free(safes, PKCS7_free);
	if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif
	goto end;
	
    }

    if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
	ERR_print_errors(bio_err);
	goto end;
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read import password");
#endif
    if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n");
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif

    if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);

    if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
    if(macver) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("verify MAC");
#endif
	/* If we enter empty password try no password first */
	if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
		/* If mac and crypto pass the same set it to NULL too */
		if(!twopass) cpass = NULL;
	} else if (!PKCS12_verify_mac(p12, mpass, -1)) {
	    BIO_printf (bio_err, "Mac verify error: invalid password?\n");
	    ERR_print_errors (bio_err);
	    goto end;
	}
	BIO_printf (bio_err, "MAC verified OK\n");
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("output keys and certificates");
#endif
    if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
	BIO_printf(bio_err, "Error outputting keys and certificates\n");
	ERR_print_errors (bio_err);
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    ret = 0;
 end:
    if (p12) PKCS12_free(p12);
    if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
#ifdef CRYPTO_MDEBUG
    CRYPTO_remove_all_info();
#endif
    BIO_free(in);
    BIO_free_all(out);
    if (canames) sk_free(canames);
    if(passin) OPENSSL_free(passin);
    if(passout) OPENSSL_free(passout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Example #14
0
CK_RV
gpkcs11_add_credentials(char *label,
			const char *cert_file,
			const char *private_key_file,
			char *id,
			int anchor)
{
    struct gpkcs11_st_object *o = NULL;
    CK_BBOOL bool_true = CK_TRUE;
    CK_BBOOL bool_false = CK_FALSE;
    CK_OBJECT_CLASS c;
    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
    CK_KEY_TYPE key_type;
    CK_MECHANISM_TYPE mech_type;
    CK_RV ret = CKR_GENERAL_ERROR;
    void *subject_data = NULL;
    size_t subject_length;
    X509 *cert, *proxy_cert = NULL;
    EVP_PKEY *public_key;
    FILE *f = NULL;
    size_t id_len = strlen(id);

    f = fopen(cert_file, "r");
    if (f == NULL) {
	gpkcs11_log("failed to open file %s\n", cert_file);
	return CKR_GENERAL_ERROR;
    }

    while (1) {
	cert = PEM_read_X509(f, NULL, NULL, NULL);
	if (cert == NULL) {
	    if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
		break;
	    ret = CKR_GENERAL_ERROR;
	    goto out;
	}
	if (proxy_cert == NULL)
	    proxy_cert = cert;
	ret = gpkcs11_add_certificate(label, cert, id, anchor);
	if (ret)
	    goto out;
    }

    public_key = X509_get_pubkey(proxy_cert);
    switch (EVP_PKEY_type(public_key->type)) {
    case EVP_PKEY_RSA:
	key_type = CKK_RSA;
	break;
    case EVP_PKEY_DSA:
	key_type = CKK_DSA;
	break;
    default:
	/* XXX */
	break;
    }

    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, 
			       X509_get_subject_name(proxy_cert), ret);
    if (ret)
	goto out;


    if (private_key_file) {
	CK_FLAGS flags;
	FILE *f;

	o = add_st_object();
	if (o == NULL) {
	    ret = CKR_DEVICE_MEMORY;
	    goto out;
	}
	o->type = STO_T_PRIVATE_KEY;
	o->u.private_key.file = strdup(private_key_file);
	o->u.private_key.key = NULL;

	o->u.private_key.cert = proxy_cert;

	c = CKO_PRIVATE_KEY;
	add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

	add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
	add_object_attribute(o, 0, CKA_ID, id, id_len);
	add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
	add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
	add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
	mech_type = CKM_RSA_X_509;
	add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

	add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
	add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
	flags = 0;
	add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));

	add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));

	add_pubkey_info(o, key_type, public_key);

	f = fopen(private_key_file, "r");
	if (f == NULL) {
	    gpkcs11_log("failed to open private key\n");
	    return CKR_GENERAL_ERROR;
	}

	o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL);
	fclose(f);
	if (o->u.private_key.key == NULL) {
	    gpkcs11_log("failed to read private key a startup\n");
	    /* don't bother with this failure for now, 
	       fix it at C_Login time */;
	} else {
	    /* XXX verify keytype */

	    if (key_type == CKK_RSA)
		RSA_set_method(o->u.private_key.key->pkey.rsa, 
			       RSA_PKCS1_SSLeay());

	    if (X509_check_private_key(proxy_cert, o->u.private_key.key) != 1) {
		EVP_PKEY_free(o->u.private_key.key);	    
		o->u.private_key.key = NULL;
		gpkcs11_log("private key doesn't verify\n");
	    } else {
		gpkcs11_log("private key usable\n");
		gpkcs11_soft_token.flags.login_done = 1;
	    }
	}
    }

    ret = CKR_OK;
 out:
    if (ret != CKR_OK) {
	gpkcs11_log("something went wrong when adding cert!\n");

	/* XXX wack o */;
    }

    if (f)
	fclose(f);

    return ret;
}
Example #15
0
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    char *infile=NULL, *outfile=NULL, *keyname = NULL;	
    char *certfile=NULL;
    BIO *in=NULL, *out = NULL;
    char **args;
    char *name = NULL;
    char *csp_name = NULL;
    int add_lmk = 0;
    PKCS12 *p12 = NULL;
    char pass[50], macpass[50];
    int export_cert = 0;
    int options = 0;
    int chain = 0;
    int badarg = 0;
    int iter = PKCS12_DEFAULT_ITER;
    int maciter = PKCS12_DEFAULT_ITER;
    int twopass = 0;
    int keytype = 0;
    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
    int ret = 1;
    int macver = 1;
    int noprompt = 0;
    STACK_OF(OPENSSL_STRING) *canames = NULL;
    char *cpass = NULL, *mpass = NULL;
    char *passargin = NULL, *passargout = NULL, *passarg = NULL;
    char *passin = NULL, *passout = NULL;
    char *inrand = NULL;
    char *macalg = NULL;
    char *CApath = NULL, *CAfile = NULL;
#ifndef OPENSSL_NO_ENGINE
    char *engine=NULL;
#endif

    apps_startup();

    enc = EVP_des_ede3_cbc();
    if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;

    args = argv + 1;


    while (*args) {
	if (*args[0] == '-') {
		if (!strcmp (*args, "-nokeys")) options |= NOKEYS;
		else if (!strcmp (*args, "-keyex")) keytype = KEY_EX;
		else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG;
		else if (!strcmp (*args, "-nocerts")) options |= NOCERTS;
		else if (!strcmp (*args, "-clcerts")) options |= CLCERTS;
		else if (!strcmp (*args, "-cacerts")) options |= CACERTS;
		else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS);
		else if (!strcmp (*args, "-info")) options |= INFO;
		else if (!strcmp (*args, "-chain")) chain = 1;
		else if (!strcmp (*args, "-twopass")) twopass = 1;
		else if (!strcmp (*args, "-nomacver")) macver = 0;
		else if (!strcmp (*args, "-descert"))
    			cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
		else if (!strcmp (*args, "-export")) export_cert = 1;
		else if (!strcmp (*args, "-des")) enc=EVP_des_cbc();
		else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
#ifndef OPENSSL_NO_IDEA
		else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc();
#endif
#ifndef OPENSSL_NO_SEED
		else if (!strcmp(*args, "-seed")) enc=EVP_seed_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc();
#endif
#ifndef OPENSSL_NO_CAMELLIA
		else if (!strcmp(*args,"-camellia128")) enc=EVP_camellia_128_cbc();
		else if (!strcmp(*args,"-camellia192")) enc=EVP_camellia_192_cbc();
		else if (!strcmp(*args,"-camellia256")) enc=EVP_camellia_256_cbc();
#endif
		else if (!strcmp (*args, "-noiter")) iter = 1;
		else if (!strcmp (*args, "-maciter"))
					 maciter = PKCS12_DEFAULT_ITER;
		else if (!strcmp (*args, "-nomaciter"))
					 maciter = 1;
		else if (!strcmp (*args, "-nomac"))
					 maciter = -1;
		else if (!strcmp (*args, "-macalg"))
		    if (args[1]) {
			args++;	
			macalg = *args;
		    } else badarg = 1;
		else if (!strcmp (*args, "-nodes")) enc=NULL;
		else if (!strcmp (*args, "-certpbe")) {
			if (!set_pbe(bio_err, &cert_pbe, *++args))
				badarg = 1;
		} else if (!strcmp (*args, "-keypbe")) {
			if (!set_pbe(bio_err, &key_pbe, *++args))
				badarg = 1;
		} else if (!strcmp (*args, "-rand")) {
		    if (args[1]) {
			args++;	
			inrand = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-inkey")) {
		    if (args[1]) {
			args++;	
			keyname = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-certfile")) {
		    if (args[1]) {
			args++;	
			certfile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-name")) {
		    if (args[1]) {
			args++;	
			name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-LMK"))
			add_lmk = 1;
		else if (!strcmp (*args, "-CSP")) {
		    if (args[1]) {
			args++;	
			csp_name = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-caname")) {
		    if (args[1]) {
			args++;	
			if (!canames) canames = sk_OPENSSL_STRING_new_null();
			sk_OPENSSL_STRING_push(canames, *args);
		    } else badarg = 1;
		} else if (!strcmp (*args, "-in")) {
		    if (args[1]) {
			args++;	
			infile = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-out")) {
		    if (args[1]) {
			args++;	
			outfile = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passin")) {
		    if (args[1]) {
			args++;	
			passargin = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-passout")) {
		    if (args[1]) {
			args++;	
			passargout = *args;
		    } else badarg = 1;
		} else if (!strcmp (*args, "-password")) {
		    if (args[1]) {
			args++;	
			passarg = *args;
		    	noprompt = 1;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CApath")) {
		    if (args[1]) {
			args++;	
			CApath = *args;
		    } else badarg = 1;
		} else if (!strcmp(*args,"-CAfile")) {
		    if (args[1]) {
			args++;	
			CAfile = *args;
		    } else badarg = 1;
#ifndef OPENSSL_NO_ENGINE
		} else if (!strcmp(*args,"-engine")) {
		    if (args[1]) {
			args++;	
			engine = *args;
		    } else badarg = 1;
#endif
		} else badarg = 1;

	} else badarg = 1;
	args++;
    }

    if (badarg) {
	BIO_printf (bio_err, "Usage: pkcs12 [options]\n");
	BIO_printf (bio_err, "where options are\n");
	BIO_printf (bio_err, "-export       output PKCS12 file\n");
	BIO_printf (bio_err, "-chain        add certificate chain\n");
	BIO_printf (bio_err, "-inkey file   private key if not infile\n");
	BIO_printf (bio_err, "-certfile f   add all certs in f\n");
	BIO_printf (bio_err, "-CApath arg   - PEM format directory of CA's\n");
	BIO_printf (bio_err, "-CAfile arg   - PEM format file of CA's\n");
	BIO_printf (bio_err, "-name \"name\"  use name as friendly name\n");
	BIO_printf (bio_err, "-caname \"nm\"  use nm as CA friendly name (can be used more than once).\n");
	BIO_printf (bio_err, "-in  infile   input filename\n");
	BIO_printf (bio_err, "-out outfile  output filename\n");
	BIO_printf (bio_err, "-noout        don't output anything, just verify.\n");
	BIO_printf (bio_err, "-nomacver     don't verify MAC.\n");
	BIO_printf (bio_err, "-nocerts      don't output certificates.\n");
	BIO_printf (bio_err, "-clcerts      only output client certificates.\n");
	BIO_printf (bio_err, "-cacerts      only output CA certificates.\n");
	BIO_printf (bio_err, "-nokeys       don't output private keys.\n");
	BIO_printf (bio_err, "-info         give info about PKCS#12 structure.\n");
	BIO_printf (bio_err, "-des          encrypt private keys with DES\n");
	BIO_printf (bio_err, "-des3         encrypt private keys with triple DES (default)\n");
#ifndef OPENSSL_NO_IDEA
	BIO_printf (bio_err, "-idea         encrypt private keys with idea\n");
#endif
#ifndef OPENSSL_NO_SEED
	BIO_printf (bio_err, "-seed         encrypt private keys with seed\n");
#endif
#ifndef OPENSSL_NO_AES
	BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
	BIO_printf (bio_err, "              encrypt PEM output with cbc aes\n");
#endif
#ifndef OPENSSL_NO_CAMELLIA
	BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
	BIO_printf (bio_err, "              encrypt PEM output with cbc camellia\n");
#endif
	BIO_printf (bio_err, "-nodes        don't encrypt private keys\n");
	BIO_printf (bio_err, "-noiter       don't use encryption iteration\n");
	BIO_printf (bio_err, "-nomaciter    don't use MAC iteration\n");
	BIO_printf (bio_err, "-maciter      use MAC iteration\n");
	BIO_printf (bio_err, "-nomac        don't generate MAC\n");
	BIO_printf (bio_err, "-twopass      separate MAC, encryption passwords\n");
	BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
	BIO_printf (bio_err, "-certpbe alg  specify certificate PBE algorithm (default RC2-40)\n");
	BIO_printf (bio_err, "-keypbe alg   specify private key PBE algorithm (default 3DES)\n");
	BIO_printf (bio_err, "-macalg alg   digest algorithm used in MAC (default SHA1)\n");
	BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
	BIO_printf (bio_err, "-keysig       set MS key signature type\n");
	BIO_printf (bio_err, "-password p   set import/export password source\n");
	BIO_printf (bio_err, "-passin p     input file pass phrase source\n");
	BIO_printf (bio_err, "-passout p    output file pass phrase source\n");
#ifndef OPENSSL_NO_ENGINE
	BIO_printf (bio_err, "-engine e     use engine e, possibly a hardware device.\n");
#endif
	BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
	BIO_printf(bio_err,  "              load the file (or the files in the directory) into\n");
	BIO_printf(bio_err,  "              the random number generator\n");
	BIO_printf(bio_err,  "-CSP name     Microsoft CSP name\n");
	BIO_printf(bio_err,  "-LMK          Add local machine keyset attribute to private key\n");
    	goto end;
    }

#ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine, 0);
#endif

    if(passarg) {
	if(export_cert) passargout = passarg;
	else passargin = passarg;
    }

    if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
	BIO_printf(bio_err, "Error getting passwords\n");
	goto end;
    }

    if(!cpass) {
    	if(export_cert) cpass = passout;
    	else cpass = passin;
    }

    if(cpass) {
	mpass = cpass;
	noprompt = 1;
    } else {
	cpass = pass;
	mpass = macpass;
    }

    if(export_cert || inrand) {
    	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
        if (inrand != NULL)
		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
			app_RAND_load_files(inrand));
    }
    ERR_load_crypto_strings();

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read files");
#endif

    if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE);
    else in = BIO_new_file(infile, "rb");
    if (!in) {
	    BIO_printf(bio_err, "Error opening input file %s\n",
						infile ? infile : "<stdin>");
	    perror (infile);
	    goto end;
   }

#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
    CRYPTO_push_info("write files");
#endif

    if (!outfile) {
	out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	    out = BIO_push(tmpbio, out);
	}
#endif
    } else out = BIO_new_file(outfile, "wb");
    if (!out) {
	BIO_printf(bio_err, "Error opening output file %s\n",
						outfile ? outfile : "<stdout>");
	perror (outfile);
	goto end;
    }
    if (twopass) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read MAC password");
#endif
	if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n");
    	    goto end;
       	}
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

    if (export_cert) {
	EVP_PKEY *key = NULL;
	X509 *ucert = NULL, *x = NULL;
	STACK_OF(X509) *certs=NULL;
	const EVP_MD *macmd = NULL;
	unsigned char *catmp = NULL;
	int i;

	if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS))
		{	
		BIO_printf(bio_err, "Nothing to do!\n");
		goto export_end;
		}

	if (options & NOCERTS)
		chain = 0;

#ifdef CRYPTO_MDEBUG
	CRYPTO_push_info("process -export_cert");
	CRYPTO_push_info("reading private key");
#endif
	if (!(options & NOKEYS))
		{
		key = load_key(bio_err, keyname ? keyname : infile,
				FORMAT_PEM, 1, passin, e, "private key");
		if (!key)
			goto export_end;
		}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input");
#endif

	/* Load in all certs in input file */
	if(!(options & NOCERTS))
		{
		certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e,
							"certificates");
		if (!certs)
			goto export_end;

		if (key)
			{
			/* Look for matching private key */
			for(i = 0; i < sk_X509_num(certs); i++)
				{
				x = sk_X509_value(certs, i);
				if(X509_check_private_key(x, key))
					{
					ucert = x;
					/* Zero keyid and alias */
					X509_keyid_set1(ucert, NULL, 0);
					X509_alias_set1(ucert, NULL, 0);
					/* Remove from list */
					(void)sk_X509_delete(certs, i);
					break;
					}
				}
			if (!ucert)
				{
				BIO_printf(bio_err, "No certificate matches private key\n");
				goto export_end;
				}
			}

		}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from input 2");
#endif

	/* Add any more certificates asked for */
	if(certfile)
		{
		STACK_OF(X509) *morecerts=NULL;
		if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM,
					    NULL, e,
					    "certificates from certfile")))
			goto export_end;
		while(sk_X509_num(morecerts) > 0)
			sk_X509_push(certs, sk_X509_shift(morecerts));
		sk_X509_free(morecerts);
 		}

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading certs from certfile");
#endif

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("building chain");
#endif

	/* If chaining get chain from user cert */
	if (chain) {
        	int vret;
		STACK_OF(X509) *chain2;
		X509_STORE *store = X509_STORE_new();
		if (!store)
			{
			BIO_printf (bio_err, "Memory allocation error\n");
			goto export_end;
			}
		if (!X509_STORE_load_locations(store, CAfile, CApath))
			X509_STORE_set_default_paths (store);

		vret = get_cert_chain (ucert, store, &chain2);
		X509_STORE_free(store);

		if (!vret) {
		    /* Exclude verified certificate */
		    for (i = 1; i < sk_X509_num (chain2) ; i++) 
			sk_X509_push(certs, sk_X509_value (chain2, i));
		    /* Free first certificate */
		    X509_free(sk_X509_value(chain2, 0));
		    sk_X509_free(chain2);
		} else {
			if (vret >= 0)
				BIO_printf (bio_err, "Error %s getting chain.\n",
					X509_verify_cert_error_string(vret));
			else
				ERR_print_errors(bio_err);
			goto export_end;
		}			
    	}

	/* Add any CA names */

	for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++)
		{
		catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
		X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
		}

	if (csp_name && key)
		EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
				MBSTRING_ASC, (unsigned char *)csp_name, -1);

	if (add_lmk && key)
		EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("reading password");
#endif

	if(!noprompt &&
		EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n");
	    	goto export_end;
        	}
	if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("creating PKCS#12 structure");
#endif

	p12 = PKCS12_create(cpass, name, key, ucert, certs,
				key_pbe, cert_pbe, iter, -1, keytype);

	if (!p12)
		{
	    	ERR_print_errors (bio_err);
		goto export_end;
		}

	if (macalg)
		{
		macmd = EVP_get_digestbyname(macalg);
		if (!macmd)
			{
			BIO_printf(bio_err, "Unknown digest algorithm %s\n", 
						macalg);
			}
		}

	if (maciter != -1)
		PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_push_info("writing pkcs12");
#endif

	i2d_PKCS12_bio(out, p12);

	ret = 0;

    export_end:
#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
	CRYPTO_pop_info();
	CRYPTO_push_info("process -export_cert: freeing");
#endif

	if (key) EVP_PKEY_free(key);
	if (certs) sk_X509_pop_free(certs, X509_free);
	if (ucert) X509_free(ucert);

#ifdef CRYPTO_MDEBUG
	CRYPTO_pop_info();
#endif
	goto end;
	
    }

    if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
	ERR_print_errors(bio_err);
	goto end;
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("read import password");
#endif
    if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n");
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif

    if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass);

    if ((options & INFO) && p12->mac) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
    if(macver) {
#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("verify MAC");
#endif
	/* If we enter empty password try no password first */
	if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
		/* If mac and crypto pass the same set it to NULL too */
		if(!twopass) cpass = NULL;
	} else if (!PKCS12_verify_mac(p12, mpass, -1)) {
	    BIO_printf (bio_err, "Mac verify error: invalid password?\n");
	    ERR_print_errors (bio_err);
	    goto end;
	}
	BIO_printf (bio_err, "MAC verified OK\n");
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    }

#ifdef CRYPTO_MDEBUG
    CRYPTO_push_info("output keys and certificates");
#endif
    if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) {
	BIO_printf(bio_err, "Error outputting keys and certificates\n");
	ERR_print_errors (bio_err);
	goto end;
    }
#ifdef CRYPTO_MDEBUG
    CRYPTO_pop_info();
#endif
    ret = 0;
 end:
    if (p12) PKCS12_free(p12);
    if(export_cert || inrand) app_RAND_write_file(NULL, bio_err);
#ifdef CRYPTO_MDEBUG
    CRYPTO_remove_all_info();
#endif
    BIO_free(in);
    BIO_free_all(out);
    if (canames) sk_OPENSSL_STRING_free(canames);
    if(passin) OPENSSL_free(passin);
    if(passout) OPENSSL_free(passout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Example #16
0
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
	     X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
	     int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
	{
	int ret=0;
	ASN1_INTEGER *bs=NULL;
	X509_STORE_CTX xsc;
	EVP_PKEY *upkey;

	upkey = X509_get_pubkey(xca);
	EVP_PKEY_copy_parameters(upkey,pkey);
	EVP_PKEY_free(upkey);

	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
		{
		BIO_printf(bio_err,"Error initialising X509 store\n");
		goto end;
		}
	if (sno) bs = sno;
	else if (!(bs = load_serial(CAfile, serialfile, create)))
		goto end;

	if (!X509_STORE_add_cert(ctx,x)) goto end;

	/* NOTE: this certificate can/should be self signed, unless it was
	 * a certificate request in which case it is not. */
	X509_STORE_CTX_set_cert(&xsc,x);
	if (!reqfile && !X509_verify_cert(&xsc))
		goto end;

	if (!X509_check_private_key(xca,pkey))
		{
		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
		goto end;
		}

	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
	if (!X509_set_serialNumber(x,bs)) goto end;

	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
		goto end;

	/* hardwired expired */
	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
		goto end;

	if (clrext)
		{
		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
		}

	if (conf)
		{
		X509V3_CTX ctx2;
		X509_set_version(x,2); /* version 3 certificate */
                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
                X509V3_set_nconf(&ctx2, conf);
                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
		}

	if (!X509_sign(x,pkey,digest)) goto end;
	ret=1;
end:
	X509_STORE_CTX_cleanup(&xsc);
	if (!ret)
		ERR_print_errors(bio_err);
	if (!sno) ASN1_INTEGER_free(bs);
	return ret;
	}
Example #17
0
/*
 * Main entry point.
 */
int
main(int argc, char *argv[])
{
	const char *argv0;
	int ch;
	opts_t *opts;
	char *natengine;
	int pidfd = -1;
	int rv = EXIT_FAILURE;

	argv0 = argv[0];
	opts = opts_new();
	natengine = strdup(nat_getdefaultname());

	while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z
	                    "k:c:C:K:t:OPs:e:Eu:j:p:l:L:S:dDVh")) != -1) {
		switch (ch) {
			case 'c':
				if (opts->cacrt)
					X509_free(opts->cacrt);
				opts->cacrt = ssl_x509_load(optarg);
				if (!opts->cacrt) {
					fprintf(stderr, "%s: error loading CA "
					                "cert from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				ssl_x509_refcount_inc(opts->cacrt);
				sk_X509_insert(opts->chain, opts->cacrt, 0);
				if (!opts->cakey) {
					opts->cakey = ssl_key_load(optarg);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'k':
				if (opts->cakey)
					EVP_PKEY_free(opts->cakey);
				opts->cakey = ssl_key_load(optarg);
				if (!opts->cakey) {
					fprintf(stderr, "%s: error loading CA "
					                "key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				if (!opts->cacrt) {
					opts->cacrt = ssl_x509_load(optarg);
					if (opts->cacrt) {
						ssl_x509_refcount_inc(
						               opts->cacrt);
						sk_X509_insert(opts->chain,
						               opts->cacrt, 0);
					}
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'C':
				if (ssl_x509chain_load(NULL, &opts->chain,
				                       optarg) == -1) {
					fprintf(stderr, "%s: error loading "
					                "chain from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
			case 'K':
				if (opts->key)
					EVP_PKEY_free(opts->key);
				opts->key = ssl_key_load(optarg);
				if (!opts->key) {
					fprintf(stderr, "%s: error loading lea"
					                "f key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 't':
				if (!sys_isdir(optarg)) {
					fprintf(stderr, "%s: '%s' is not a "
					                "directory\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				if (opts->tgcrtdir)
					free(opts->tgcrtdir);
				opts->tgcrtdir = strdup(optarg);
				break;
			case 'O':
				opts->deny_ocsp = 1;
				break;
			case 'P':
				opts->passthrough = 1;
				break;
#ifndef OPENSSL_NO_DH
			case 'g':
				if (opts->dh)
					DH_free(opts->dh);
				opts->dh = ssl_dh_load(optarg);
				if (!opts->dh) {
					fprintf(stderr, "%s: error loading DH "
					                "params from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH
			case 'G':
			{
				EC_KEY *ec;
				if (opts->ecdhcurve)
					free(opts->ecdhcurve);
				if (!(ec = ssl_ec_by_name(optarg))) {
					fprintf(stderr, "%s: unknown curve "
					                "'%s'\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				EC_KEY_free(ec);
				opts->ecdhcurve = strdup(optarg);
				break;
			}
#endif /* !OPENSSL_NO_ECDH */
#ifdef SSL_OP_NO_COMPRESSION
			case 'Z':
				opts->sslcomp = 0;
				break;
#endif /* SSL_OP_NO_COMPRESSION */
			case 's':
				if (opts->ciphers)
					free(opts->ciphers);
				opts->ciphers = strdup(optarg);
				break;
			case 'e':
				free(natengine);
				natengine = strdup(optarg);
				break;
			case 'E':
				nat_list_engines();
				exit(EXIT_SUCCESS);
				break;
			case 'u':
				if (opts->dropuser)
					free(opts->dropuser);
				opts->dropuser = strdup(optarg);
				break;
			case 'p':
				if (opts->pidfile)
					free(opts->pidfile);
				opts->pidfile = strdup(optarg);
				break;
			case 'j':
				if (opts->jaildir)
					free(opts->jaildir);
				opts->jaildir = strdup(optarg);
				break;
			case 'l':
				if (opts->connectlog)
					free(opts->connectlog);
				opts->connectlog = strdup(optarg);
				break;
			case 'L':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 0;
				break;
			case 'S':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 1;
				break;
			case 'd':
				opts->detach = 1;
				break;
			case 'D':
				log_dbg_mode(LOG_DBG_MODE_ERRLOG);
				opts->debug = 1;
				break;
			case 'V':
				main_version();
				exit(EXIT_SUCCESS);
			case 'h':
				main_usage();
				exit(EXIT_SUCCESS);
			case '?':
				exit(EXIT_FAILURE);
			default:
				main_usage();
				exit(EXIT_FAILURE);
		}
	}
	argc -= optind;
	argv += optind;
	opts->spec = proxyspec_parse(&argc, &argv, natengine);

	/* usage checks */
	if (opts->detach && OPTS_DEBUG(opts)) {
		fprintf(stderr, "%s: -d and -D are mutually exclusive.\n",
		                argv0);
		exit(EXIT_FAILURE);
	}
	if (!opts->spec) {
		fprintf(stderr, "%s: no proxyspec specified.\n", argv0);
		exit(EXIT_FAILURE);
	}
	for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
		if (spec->connect_addrlen || spec->sni_port)
			continue;
		if (!spec->natengine) {
			fprintf(stderr, "%s: no supported NAT engines "
			                "on this platform.\n"
			                "Only static addr and SNI proxyspecs "
			                "supported.\n", argv0);
			exit(EXIT_FAILURE);
		}
		if (spec->listen_addr.ss_family == AF_INET6 &&
		    !nat_ipv6ready(spec->natengine)) {
			fprintf(stderr, "%s: IPv6 not supported by '%s'\n",
			                argv0, spec->natengine);
			exit(EXIT_FAILURE);
		}
		spec->natlookup = nat_getlookupcb(spec->natengine);
		spec->natsocket = nat_getsocketcb(spec->natengine);
	}
	if (opts_has_ssl_spec(opts)) {
		if ((opts->cacrt || !opts->tgcrtdir) && !opts->cakey) {
			fprintf(stderr, "%s: no CA key specified (-k).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && !opts->cacrt) {
			fprintf(stderr, "%s: no CA cert specified (-c).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && opts->cacrt &&
		    (X509_check_private_key(opts->cacrt, opts->cakey) != 1)) {
			fprintf(stderr, "%s: CA cert does not match key.\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
	}

	/* prevent multiple instances running */
	if (opts->pidfile) {
		pidfd = sys_pidf_open(opts->pidfile);
		if (pidfd == -1) {
			fprintf(stderr, "%s: cannot open PID file '%s' "
			                "- process already running?\n",
			                argv0, opts->pidfile);
			exit(EXIT_FAILURE);
		}
	}

	/* dynamic defaults */
	if (!opts->ciphers) {
		opts->ciphers = strdup("ALL:-aNULL");
		if (!opts->ciphers) {
			fprintf(stderr, "%s: out of memory.\n", argv0);
			exit(EXIT_FAILURE);
		}
	}
	if (!opts->jaildir && (geteuid() == 0) && !opts->contentlogdir) {
		opts->jaildir = strdup("/var/empty");
	}
	if (!opts->dropuser && !geteuid() && !getuid() &&
	    !opts->contentlogdir) {
		opts->dropuser = strdup("nobody");
	}
	if (opts_has_ssl_spec(opts) && !opts->key) {
		opts->key = ssl_key_genrsa(1024);
		if (!opts->key) {
			fprintf(stderr, "%s: error generating RSA key:\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Generated RSA key for leaf certs.\n");
		}
	}

	/* debugging */
	if (OPTS_DEBUG(opts)) {
		main_version();
		log_dbg_printf("proxyspecs:\n");
		for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
			char *lbuf, *cbuf = NULL;
			lbuf = sys_sockaddr_str((struct sockaddr *)
			                        &spec->listen_addr,
			                        spec->listen_addrlen);
			if (spec->connect_addrlen) {
				cbuf = sys_sockaddr_str((struct sockaddr *)
				                        &spec->connect_addr,
				                        spec->connect_addrlen);
			}
			if (spec->sni_port) {
				asprintf(&cbuf, "sni %i", spec->sni_port);
			}
			log_dbg_printf("- %s %s %s %s\n", lbuf,
			               (spec->ssl ? "ssl" : "tcp"),
			               (spec->http ? "http" : "plain"),
			               (spec->natengine ? spec->natengine
			                                : cbuf));
			if (lbuf)
				free(lbuf);
			if (cbuf)
				free(cbuf);
		}
		if (opts->cacrt) {
			char *subj = ssl_x509_subject(opts->cacrt);
			log_dbg_printf("Loaded CA: '%s'\n", subj);
			free(subj);
#ifdef DEBUG_CERTIFICATE
			log_dbg_print_free(ssl_x509_to_str(opts->cacrt));
			log_dbg_print_free(ssl_x509_to_pem(opts->cacrt));
#endif /* DEBUG_CERTIFICATE */
		} else {
			log_dbg_printf("No CA loaded.\n");
		}
	}

	/*
	 * Initialize as much as possible before daemon() in order to be
	 * able to provide direct feedback to the user when failing.
	 */
	if (cachemgr_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit cachemgr.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (log_preinit(opts) == -1) {
		fprintf(stderr, "%s: failed to preinit logging.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (nat_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit NAT lookup.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Bind listeners before dropping privileges */
	proxy_ctx_t *proxy = proxy_new(opts);
	if (!proxy) {
		fprintf(stderr, "%s: failed to initialize proxy.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Drop privs, chroot, detach from TTY */
	if (sys_privdrop(opts->dropuser, opts->jaildir) == -1) {
		fprintf(stderr, "%s: failed to drop privileges: %s\n",
		                argv0, strerror(errno));
		exit(EXIT_FAILURE);
	}
	if (opts->detach) {
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Detaching from TTY, see syslog for "
			               "errors after this point\n");
		}
		if (daemon(1, 0) == -1) {
			fprintf(stderr, "%s: failed to detach from TTY: %s\n",
			                argv0, strerror(errno));
			exit(EXIT_FAILURE);
		}
		log_err_mode(LOG_ERR_MODE_SYSLOG);
		ssl_reinit();
	}

	/* Post-privdrop/chroot/detach initialization, thread spawning */
	if (log_init(opts) == -1) {
		fprintf(stderr, "%s: failed to init log facility.\n", argv0);
		goto out_log_failed;
	}
	if (opts->pidfile && (sys_pidf_write(pidfd) == -1)) {
		log_err_printf("Failed to write PID to PID file '%s': %s\n",
		               opts->pidfile, strerror(errno));
		goto out_pidwrite_failed;
	}
	if (cachemgr_init() == -1) {
		log_err_printf("Failed to init cache manager.\n");
		goto out_cachemgr_failed;
	}
	if (nat_init() == -1) {
		log_err_printf("Failed to init NAT state table lookup.\n");
		goto out_nat_failed;
	}

	if (opts->tgcrtdir) {
		sys_dir_eachfile(opts->tgcrtdir, main_loadtgcrt, opts);
	}

	rv = EXIT_SUCCESS;

	proxy_run(proxy);
	proxy_free(proxy);
	nat_fini();
out_nat_failed:
	cachemgr_fini();
out_cachemgr_failed:
	if (opts->pidfile) {
		sys_pidf_close(pidfd, opts->pidfile);
	}
out_pidwrite_failed:
	log_fini();
out_log_failed:
	opts_free(opts);
	ssl_fini();
	return rv;
}
Example #18
0
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
{
    int i;
    /*
     * Special case for DH: check two DH certificate types for a match. This
     * means for DH certificates we must set the certificate first.
     */
    if (pkey->type == EVP_PKEY_DH) {
        X509 *x;
        i = -1;
        x = c->pkeys[SSL_PKEY_DH_RSA].x509;
        if (x && X509_check_private_key(x, pkey))
            i = SSL_PKEY_DH_RSA;
        x = c->pkeys[SSL_PKEY_DH_DSA].x509;
        if (i == -1 && x && X509_check_private_key(x, pkey))
            i = SSL_PKEY_DH_DSA;
        ERR_clear_error();
    } else
        i = ssl_cert_type(NULL, pkey);
    if (i < 0) {
        SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
        return (0);
    }

    if (c->pkeys[i].x509 != NULL) {
        EVP_PKEY *pktmp;
        pktmp = X509_get_pubkey(c->pkeys[i].x509);
        if (pktmp == NULL) {
            SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE);
            EVP_PKEY_free(pktmp);
            return 0;
        }
        /*
         * The return code from EVP_PKEY_copy_parameters is deliberately
         * ignored. Some EVP_PKEY types cannot do this.
         */
        EVP_PKEY_copy_parameters(pktmp, pkey);
        EVP_PKEY_free(pktmp);
        ERR_clear_error();

#ifndef OPENSSL_NO_RSA
        /*
         * Don't check the public/private key, this is mostly for smart
         * cards.
         */
        if ((pkey->type == EVP_PKEY_RSA) &&
            (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ;
        else
#endif
        if (!X509_check_private_key(c->pkeys[i].x509, pkey)) {
            X509_free(c->pkeys[i].x509);
            c->pkeys[i].x509 = NULL;
            return 0;
        }
    }

    if (c->pkeys[i].privatekey != NULL)
        EVP_PKEY_free(c->pkeys[i].privatekey);
    CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
    c->pkeys[i].privatekey = pkey;
    c->key = &(c->pkeys[i]);

    c->valid = 0;
    return (1);
}