⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qca-ossl.cpp

📁 QCA的OPENSSL模块
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2004-2007  Justin Karneges <justin@affinix.com> * Copyright (C) 2004-2006  Brad Hards <bradh@frogmouth.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA * */#include <QtCrypto>#include <qcaprovider.h>#include <QDebug>#include <QtPlugin>#include <openssl/evp.h>#include <openssl/hmac.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <openssl/rand.h>#include <openssl/pem.h>#include <openssl/err.h>#include <openssl/x509v3.h>#include <openssl/pkcs12.h>#include <openssl/ssl.h>#ifndef OSSL_097// comment this out if you'd rather use openssl 0.9.6#define OSSL_097#endifusing namespace QCA;namespace opensslQCAPlugin {//----------------------------------------------------------------------------// Util//----------------------------------------------------------------------------static SecureArray bio2buf(BIO *b){	SecureArray buf;	while(1) {		SecureArray block(1024);		int ret = BIO_read(b, block.data(), block.size());		if(ret <= 0)			break;		block.resize(ret);		buf.append(block);		if(ret != 1024)			break;	}	BIO_free(b);	return buf;}static QByteArray bio2ba(BIO *b){	QByteArray buf;	while(1) {		QByteArray block(1024, 0);		int ret = BIO_read(b, block.data(), block.size());		if(ret <= 0)			break;		block.resize(ret);		buf.append(block);		if(ret != 1024)			break;	}	BIO_free(b);	return buf;}static BigInteger bn2bi(BIGNUM *n){	SecureArray buf(BN_num_bytes(n) + 1);	buf[0] = 0; // positive	BN_bn2bin(n, (unsigned char *)buf.data() + 1);	return BigInteger(buf);}static BIGNUM *bi2bn(const BigInteger &n){	SecureArray buf = n.toArray();	return BN_bin2bn((const unsigned char *)buf.data(), buf.size(), NULL);}static SecureArray dsasig_der_to_raw(const SecureArray &in){	DSA_SIG *sig = DSA_SIG_new();	const unsigned char *inp = (const unsigned char *)in.data();	d2i_DSA_SIG(&sig, &inp, in.size());	SecureArray part_r(20);	SecureArray part_s(20);	memset(part_r.data(), 0, 20);	memset(part_s.data(), 0, 20);	unsigned char *p = (unsigned char *)part_r.data();	BN_bn2bin(sig->r, p);	p = (unsigned char *)part_s.data();	BN_bn2bin(sig->s, p);	SecureArray result;	result.append(part_r);	result.append(part_s);	DSA_SIG_free(sig);	return result;}static SecureArray dsasig_raw_to_der(const SecureArray &in){	if(in.size() != 40)		return SecureArray();	DSA_SIG *sig = DSA_SIG_new();	SecureArray part_r(20);	SecureArray part_s(20);	memcpy(part_r.data(), in.data(), 20);	memcpy(part_s.data(), in.data() + 20, 20);	sig->r = BN_bin2bn((const unsigned char *)part_r.data(), part_r.size(), NULL);	sig->s = BN_bin2bn((const unsigned char *)part_s.data(), part_s.size(), NULL);	int len = i2d_DSA_SIG(sig, NULL);	SecureArray result(len);	unsigned char *p = (unsigned char *)result.data();	i2d_DSA_SIG(sig, &p);	DSA_SIG_free(sig);	return result;}static int passphrase_cb(char *buf, int size, int rwflag, void *u){	Q_UNUSED(buf);	Q_UNUSED(size);	Q_UNUSED(rwflag);	Q_UNUSED(u);	return 0;}/*static bool is_basic_constraint(const ConstraintType &t){	bool basic = false;	switch(t.known())	{		case DigitalSignature:		case NonRepudiation:		case KeyEncipherment:		case DataEncipherment:		case KeyAgreement:		case KeyCertificateSign:		case CRLSign:		case EncipherOnly:		case DecipherOnly:			basic = true;			break;		case ServerAuth:		case ClientAuth:		case CodeSigning:		case EmailProtection:		case IPSecEndSystem:		case IPSecTunnel:		case IPSecUser:		case TimeStamping:		case OCSPSigning:			break;	}	return basic;}static Constraints basic_only(const Constraints &list){	Constraints out;	for(int n = 0; n < list.count(); ++n)	{		if(is_basic_constraint(list[n]))			out += list[n];	}	return out;}static Constraints ext_only(const Constraints &list){	Constraints out;	for(int n = 0; n < list.count(); ++n)	{		if(!is_basic_constraint(list[n]))			out += list[n];	}	return out;}*/// logic from Botan/*static Constraints find_constraints(const PKeyContext &key, const Constraints &orig){	Constraints constraints;	if(key.key()->type() == PKey::RSA)		constraints += KeyEncipherment;	if(key.key()->type() == PKey::DH)		constraints += KeyAgreement;	if(key.key()->type() == PKey::RSA || key.key()->type() == PKey::DSA)	{		constraints += DigitalSignature;		constraints += NonRepudiation;	}	Constraints limits = basic_only(orig);	Constraints the_rest = ext_only(orig);	if(!limits.isEmpty())	{		Constraints reduced;		for(int n = 0; n < constraints.count(); ++n)		{			if(limits.contains(constraints[n]))				reduced += constraints[n];		}		constraints = reduced;	}	constraints += the_rest;	return constraints;}*/static void try_add_name_item(X509_NAME **name, int nid, const QString &val){	if(val.isEmpty())		return;	QByteArray buf = val.toLatin1();	if(!(*name))		*name = X509_NAME_new();	X509_NAME_add_entry_by_NID(*name, nid, MBSTRING_ASC, (unsigned char *)buf.data(), buf.size(), -1, 0);}static X509_NAME *new_cert_name(const CertificateInfo &info){	X509_NAME *name = 0;	// FIXME support multiple items of each type	try_add_name_item(&name, NID_commonName, info.value(CommonName));	try_add_name_item(&name, NID_countryName, info.value(Country));	try_add_name_item(&name, NID_localityName, info.value(Locality));	try_add_name_item(&name, NID_stateOrProvinceName, info.value(State));	try_add_name_item(&name, NID_organizationName, info.value(Organization));	try_add_name_item(&name, NID_organizationalUnitName, info.value(OrganizationalUnit));	return name;}static void try_get_name_item(X509_NAME *name, int nid, const CertificateInfoType &t, CertificateInfo *info){	int loc;	loc = -1;	while ((loc = X509_NAME_get_index_by_NID(name, nid, loc)) != -1) {		X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, loc);		ASN1_STRING *data = X509_NAME_ENTRY_get_data(ne);		QByteArray cs((const char *)data->data, data->length);		info->insert(t, QString::fromLatin1(cs));	}}static void try_get_name_item_by_oid(X509_NAME *name, const QString &oidText, const CertificateInfoType &t, CertificateInfo *info){        ASN1_OBJECT *oid = OBJ_txt2obj( oidText.toLatin1().data(), 1); // 1 = only accept dotted input	if(!oid)		return;	int loc;	loc = -1;	while ((loc = X509_NAME_get_index_by_OBJ(name, oid, loc)) != -1) {		X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, loc);		ASN1_STRING *data = X509_NAME_ENTRY_get_data(ne);		QByteArray cs((const char *)data->data, data->length);		info->insert(t, QString::fromLatin1(cs));		qDebug() << "oid: " << oidText << ",  result: " << cs;	}	ASN1_OBJECT_free(oid);}static CertificateInfo get_cert_name(X509_NAME *name){	CertificateInfo info;	try_get_name_item(name, NID_commonName, CommonName, &info);	try_get_name_item(name, NID_countryName, Country, &info);	try_get_name_item_by_oid(name, QString("1.3.6.1.4.1.311.60.2.1.3"), IncorporationCountry, &info);	try_get_name_item(name, NID_localityName, Locality, &info);	try_get_name_item_by_oid(name, QString("1.3.6.1.4.1.311.60.2.1.1"), IncorporationLocality, &info);	try_get_name_item(name, NID_stateOrProvinceName, State, &info);	try_get_name_item_by_oid(name, QString("1.3.6.1.4.1.311.60.2.1.2"), IncorporationState, &info);	try_get_name_item(name, NID_organizationName, Organization, &info);	try_get_name_item(name, NID_organizationalUnitName, OrganizationalUnit, &info);	// legacy email	{		CertificateInfo p9_info;		try_get_name_item(name, NID_pkcs9_emailAddress, EmailLegacy, &p9_info);		QList<QString> emails = info.values(Email);		QMapIterator<CertificateInfoType,QString> it(p9_info);		while(it.hasNext())		{			it.next();			if(!emails.contains(it.value()))				info.insert(Email, it.value());		}	}	return info;}static X509_EXTENSION *new_subject_key_id(X509 *cert){	X509V3_CTX ctx;	X509V3_set_ctx_nodb(&ctx);	X509V3_set_ctx(&ctx, NULL, cert, NULL, NULL, 0);	X509_EXTENSION *ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, "hash");	return ex;}static X509_EXTENSION *new_basic_constraints(bool ca, int pathlen){	BASIC_CONSTRAINTS *bs = BASIC_CONSTRAINTS_new();	bs->ca = (ca ? 1: 0);	bs->pathlen = ASN1_INTEGER_new();	ASN1_INTEGER_set(bs->pathlen, pathlen);	X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, 1, bs); // 1 = critical	BASIC_CONSTRAINTS_free(bs);	return ex;}static void get_basic_constraints(X509_EXTENSION *ex, bool *ca, int *pathlen){	BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ex);	*ca = (bs->ca ? true: false);	if(bs->pathlen)		*pathlen = ASN1_INTEGER_get(bs->pathlen);	else		*pathlen = 0;	BASIC_CONSTRAINTS_free(bs);}enum ConstraintBit{	Bit_DigitalSignature   = 0,	Bit_NonRepudiation     = 1,	Bit_KeyEncipherment    = 2,	Bit_DataEncipherment   = 3,	Bit_KeyAgreement       = 4,	Bit_KeyCertificateSign = 5,	Bit_CRLSign            = 6,	Bit_EncipherOnly       = 7,	Bit_DecipherOnly       = 8};static QByteArray ipaddress_string_to_bytes(const QString &){	return QByteArray(4, 0);}static GENERAL_NAME *new_general_name(const CertificateInfoType &t, const QString &val){	GENERAL_NAME *name = 0;	switch(t.known())	{		case Email:		{			QByteArray buf = val.toLatin1();			ASN1_IA5STRING *str = M_ASN1_IA5STRING_new();			ASN1_STRING_set((ASN1_STRING *)str, (unsigned char *)buf.data(), buf.size());			name = GENERAL_NAME_new();			name->type = GEN_EMAIL;			name->d.rfc822Name = str;			break;		}		case URI:		{			QByteArray buf = val.toLatin1();			ASN1_IA5STRING *str = M_ASN1_IA5STRING_new();			ASN1_STRING_set((ASN1_STRING *)str, (unsigned char *)buf.data(), buf.size());			name = GENERAL_NAME_new();			name->type = GEN_URI;			name->d.uniformResourceIdentifier = str;			break;		}		case DNS:		{			QByteArray buf = val.toLatin1();			ASN1_IA5STRING *str = M_ASN1_IA5STRING_new();			ASN1_STRING_set((ASN1_STRING *)str, (unsigned char *)buf.data(), buf.size());			name = GENERAL_NAME_new();			name->type = GEN_DNS;			name->d.dNSName = str;			break;		}		case IPAddress:		{			QByteArray buf = ipaddress_string_to_bytes(val);			ASN1_OCTET_STRING *str = ASN1_OCTET_STRING_new();			ASN1_STRING_set((ASN1_STRING *)str, (unsigned char *)buf.data(), buf.size());			name = GENERAL_NAME_new();			name->type = GEN_IPADD;			name->d.iPAddress = str;			break;		}		case XMPP:		{			QByteArray buf = val.toUtf8();			ASN1_UTF8STRING *str = ASN1_UTF8STRING_new();			ASN1_STRING_set((ASN1_STRING *)str, (unsigned char *)buf.data(), buf.size());			ASN1_TYPE *at = ASN1_TYPE_new();			at->type = V_ASN1_UTF8STRING;			at->value.utf8string = str;			OTHERNAME *other = OTHERNAME_new();			other->type_id = OBJ_txt2obj("1.3.6.1.5.5.7.8.5", 1); // 1 = only accept dotted input			other->value = at;			name = GENERAL_NAME_new();			name->type = GEN_OTHERNAME;			name->d.otherName = other;			break;		}		default:			break;	}	return name;}static void try_add_general_name(GENERAL_NAMES **gn, const CertificateInfoType &t, const QString &val){	if(val.isEmpty())		return;	GENERAL_NAME *name = new_general_name(t, val);	if(name)	{		if(!(*gn))			*gn = sk_GENERAL_NAME_new_null();		sk_GENERAL_NAME_push(*gn, name);	}}static X509_EXTENSION *new_cert_subject_alt_name(const CertificateInfo &info){	GENERAL_NAMES *gn = 0;	// FIXME support multiple items of each type	try_add_general_name(&gn, Email, info.value(Email));	try_add_general_name(&gn, URI, info.value(URI));	try_add_general_name(&gn, DNS, info.value(DNS));	try_add_general_name(&gn, IPAddress, info.value(IPAddress));	try_add_general_name(&gn, XMPP, info.value(XMPP));	if(!gn)		return 0;	X509_EXTENSION *ex = X509V3_EXT_i2d(NID_subject_alt_name, 0, gn);	sk_GENERAL_NAME_pop_free(gn, GENERAL_NAME_free);	return ex;}static GENERAL_NAME *find_next_general_name(GENERAL_NAMES *names, int type, int *pos){        int temp = *pos;        GENERAL_NAME *gn = 0;        *pos = -1;        for(int n = temp; n < sk_GENERAL_NAME_num(names); ++n)        {                GENERAL_NAME *i = sk_GENERAL_NAME_value(names, n);                if(i->type == type)                {                        gn = i;                        *pos = n;                        break;                }        }        return gn;}static void try_get_general_name(GENERAL_NAMES *names, const CertificateInfoType &t, CertificateInfo *info){        switch(t.known())        {                case Email:                {                        int pos = 0;                        while (pos != -1)                        {                                GENERAL_NAME *gn = find_next_general_name(names, GEN_EMAIL, &pos);                                if (pos != -1)                                {                                        QByteArray cs((const char *)ASN1_STRING_data(gn->d.rfc822Name), ASN1_STRING_length(gn->d.rfc822Name));                                        info->insert(t, QString::fromLatin1(cs));                                        ++pos;                                }                        }                        break;                }                case URI:                {                        int pos = 0;                        while (pos != -1)                        {                                GENERAL_NAME *gn = find_next_general_name(names, GEN_URI, &pos);                                if (pos != -1)                                {                                        QByteArray cs((const char *)ASN1_STRING_data(gn->d.uniformResourceIdentifier), ASN1_STRING_length(gn->d.uniformResourceIdentifier));                                        info->insert(t, QString::fromLatin1(cs));                                        ++pos;                                }                        }                        break;                }                case DNS:                {                        int pos = 0;                        while (pos != -1)                        {                                GENERAL_NAME *gn = find_next_general_name(names, GEN_DNS, &pos);                                if (pos != -1)                                {                                        QByteArray cs((const char *)ASN1_STRING_data(gn->d.dNSName), ASN1_STRING_length(gn->d.dNSName));                                        info->insert(t, QString::fromLatin1(cs));                                        ++pos;                                }                        }                        break;                }                case IPAddress:                {                        int pos = 0;                        while (pos != -1)                        {                                GENERAL_NAME *gn = find_next_general_name(names, GEN_IPADD, &pos);                                if (pos != -1)                                {                                        ASN1_OCTET_STRING *str = gn->d.iPAddress;                                        QByteArray buf((const char *)ASN1_STRING_data(str), ASN1_STRING_length(str));                                        QString out;                                        // IPv4 (TODO: handle IPv6)                                        if(buf.size() == 4)                                        {                                                out = "0.0.0.0";                                        }                                        else                                                break;                                        info->insert(t, out);                                        ++pos;                                }                        }                        break;                }                case XMPP:                {                        int pos = 0;                        while( pos != -1)                        {                                GENERAL_NAME *gn = find_next_general_name(names, GEN_OTHERNAME, &pos);                                if (pos != -1)                                {                                        OTHERNAME *other = gn->d.otherName;                                        if(!other)                                                break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -